winetest: Generate the list of test resources in make_makefiles.
[wine/wine-gecko.git] / dlls / oleaut32 / tests / safearray.c
blob4cd2ad600d65e898a4e0d93199f254a574a2d4a3
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>
26 #include <time.h>
28 #define COBJMACROS
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 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 const IRecordInfoVtbl *lpvtbl;
81 LONG ref;
82 DWORD sizeCalled;
83 DWORD clearCalled;
84 } IRecordInfoImpl;
86 static const IRecordInfoVtbl IRecordInfoImpl_VTable;
88 static IRecordInfoImpl *IRecordInfoImpl_Construct(void)
90 IRecordInfoImpl *rec;
92 rec = HeapAlloc(GetProcessHeap(), 0, sizeof(IRecordInfoImpl));
93 rec->lpvtbl = &IRecordInfoImpl_VTable;
94 rec->ref = START_REF_COUNT;
95 rec->clearCalled = 0;
96 rec->sizeCalled = 0;
97 return rec;
100 static ULONG CALLBACK IRecordInfoImpl_AddRef(IRecordInfo *iface)
102 IRecordInfoImpl* This=(IRecordInfoImpl*)iface;
103 return InterlockedIncrement(&This->ref);
106 static ULONG CALLBACK IRecordInfoImpl_Release(IRecordInfo *iface)
108 IRecordInfoImpl* This=(IRecordInfoImpl*)iface;
109 return InterlockedDecrement(&This->ref);
112 static BOOL fail_GetSize; /* Whether to fail the GetSize call */
114 static HRESULT CALLBACK IRecordInfoImpl_RecordClear(IRecordInfo *iface, PVOID pvExisting)
116 IRecordInfoImpl* This=(IRecordInfoImpl*)iface;
117 This->clearCalled++;
118 return S_OK;
121 static HRESULT CALLBACK IRecordInfoImpl_GetSize(IRecordInfo *iface, ULONG* size)
123 IRecordInfoImpl* This=(IRecordInfoImpl*)iface;
124 This->sizeCalled++;
125 *size = 17;
126 if (fail_GetSize)
127 return E_UNEXPECTED;
128 *size = RECORD_SIZE;
129 return S_OK;
132 static HRESULT CALLBACK IRecordInfoImpl_Dummy(IRecordInfo *iface)
134 trace("Called an unexpected IRecordInfo method - please report!\n");
135 /* Quit because we'll just crash anyway */
136 fflush(NULL);
137 exit(255);
140 static const IRecordInfoVtbl IRecordInfoImpl_VTable =
142 (PVOID)IRecordInfoImpl_Dummy,
143 IRecordInfoImpl_AddRef,
144 IRecordInfoImpl_Release,
145 (PVOID)IRecordInfoImpl_Dummy,
146 IRecordInfoImpl_RecordClear,
147 (PVOID)IRecordInfoImpl_Dummy,
148 (PVOID)IRecordInfoImpl_Dummy,
149 (PVOID)IRecordInfoImpl_Dummy,
150 (PVOID)IRecordInfoImpl_GetSize,
151 (PVOID)IRecordInfoImpl_Dummy,
152 (PVOID)IRecordInfoImpl_Dummy,
153 (PVOID)IRecordInfoImpl_Dummy,
154 (PVOID)IRecordInfoImpl_Dummy,
155 (PVOID)IRecordInfoImpl_Dummy,
156 (PVOID)IRecordInfoImpl_Dummy,
157 (PVOID)IRecordInfoImpl_Dummy,
158 (PVOID)IRecordInfoImpl_Dummy,
159 (PVOID)IRecordInfoImpl_Dummy,
160 (PVOID)IRecordInfoImpl_Dummy
163 static DWORD SAFEARRAY_GetVTSize(VARTYPE vt)
165 switch (vt)
167 case VT_I1:
168 case VT_UI1: return sizeof(BYTE);
169 case VT_BOOL:
170 case VT_I2:
171 case VT_UI2: return sizeof(SHORT);
172 case VT_I4:
173 case VT_UI4:
174 case VT_R4:
175 case VT_ERROR: return sizeof(LONG);
176 case VT_R8:
177 if (HAVE_OLEAUT32_R8)
178 return sizeof(LONG64);
179 case VT_I8:
180 case VT_UI8:
181 if (HAVE_OLEAUT32_I8)
182 return sizeof(LONG64);
183 break;
184 case VT_INT:
185 case VT_UINT: return sizeof(INT);
186 case VT_INT_PTR:
187 case VT_UINT_PTR:
188 if (HAVE_OLEAUT32_INT_PTR)
189 return sizeof(UINT_PTR);
190 break;
191 case VT_CY: return sizeof(CY);
192 case VT_DATE: return sizeof(DATE);
193 case VT_BSTR: return sizeof(BSTR);
194 case VT_DISPATCH: return sizeof(LPDISPATCH);
195 case VT_VARIANT: return sizeof(VARIANT);
196 case VT_UNKNOWN: return sizeof(LPUNKNOWN);
197 case VT_DECIMAL:
198 if (HAVE_OLEAUT32_DECIMAL)
199 return sizeof(DECIMAL);
200 break;
202 return 0;
205 static void check_for_VT_INT_PTR(void)
207 /* Set a global flag if VT_INT_PTR is supported */
209 SAFEARRAY* a;
210 SAFEARRAYBOUND bound;
211 bound.cElements = 0;
212 bound.lLbound = 0;
213 a = SafeArrayCreate(VT_INT_PTR, 1, &bound);
214 if (a) {
215 trace("VT_INT_PTR is supported\n");
216 HAVE_OLEAUT32_INT_PTR = TRUE;
217 SafeArrayDestroy(a);
219 else {
220 trace("VT_INT_PTR is not supported\n");
221 HAVE_OLEAUT32_INT_PTR = FALSE;
225 #define VARTYPE_NOT_SUPPORTED 0
226 static struct {
227 VARTYPE vt; /* VT */
228 UINT elemsize; /* elementsize by VT */
229 UINT expflags; /* fFeatures from SafeArrayAllocDescriptorEx */
230 UINT addflags; /* additional fFeatures from SafeArrayCreate */
231 } vttypes[] = {
232 {VT_EMPTY, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
233 {VT_NULL, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
234 {VT_I2, 2, FADF_HAVEVARTYPE,0},
235 {VT_I4, 4, FADF_HAVEVARTYPE,0},
236 {VT_R4, 4, FADF_HAVEVARTYPE,0},
237 {VT_R8, 8, FADF_HAVEVARTYPE,0},
238 {VT_CY, 8, FADF_HAVEVARTYPE,0},
239 {VT_DATE, 8, FADF_HAVEVARTYPE,0},
240 {VT_BSTR, sizeof(BSTR), FADF_HAVEVARTYPE,FADF_BSTR},
241 {VT_DISPATCH, sizeof(LPDISPATCH), FADF_HAVEIID, FADF_DISPATCH},
242 {VT_ERROR, 4, FADF_HAVEVARTYPE,0},
243 {VT_BOOL, 2, FADF_HAVEVARTYPE,0},
244 {VT_VARIANT, sizeof(VARIANT), FADF_HAVEVARTYPE,FADF_VARIANT},
245 {VT_UNKNOWN, sizeof(LPUNKNOWN), FADF_HAVEIID, FADF_UNKNOWN},
246 {VT_DECIMAL, sizeof(DECIMAL), FADF_HAVEVARTYPE,0},
247 {15, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0}, /* no VT_xxx */
248 {VT_I1, 1, FADF_HAVEVARTYPE,0},
249 {VT_UI1, 1, FADF_HAVEVARTYPE,0},
250 {VT_UI2, 2, FADF_HAVEVARTYPE,0},
251 {VT_UI4, 4, FADF_HAVEVARTYPE,0},
252 {VT_I8, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
253 {VT_UI8, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
254 {VT_INT, sizeof(INT), FADF_HAVEVARTYPE,0},
255 {VT_UINT, sizeof(UINT), FADF_HAVEVARTYPE,0},
256 {VT_VOID, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
257 {VT_HRESULT, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
258 {VT_PTR, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
259 {VT_SAFEARRAY,VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
260 {VT_CARRAY, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
261 {VT_USERDEFINED,VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
262 {VT_LPSTR, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
263 {VT_LPWSTR, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
264 {VT_FILETIME, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
265 {VT_RECORD, VARTYPE_NOT_SUPPORTED,FADF_RECORD,0},
266 {VT_BLOB, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
267 {VT_STREAM, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
268 {VT_STORAGE, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
269 {VT_STREAMED_OBJECT,VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
270 {VT_STORED_OBJECT,VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
271 {VT_BLOB_OBJECT,VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
272 {VT_CF, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
273 {VT_CLSID, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
276 static void test_safearray(void)
278 SAFEARRAY *a, b, *c;
279 unsigned int i;
280 LONG indices[2];
281 HRESULT hres;
282 SAFEARRAYBOUND bound, bounds[2];
283 VARIANT v;
284 LPVOID data;
285 IID iid;
286 VARTYPE vt;
287 LONG l;
288 unsigned char *ptr1, *ptr2;
290 hres = SafeArrayDestroy( NULL);
291 ok( hres == S_OK, "SafeArrayDestroy( NULL) returned 0x%lx\n", hres);
293 bound.cElements = 1;
294 bound.lLbound = 0;
295 a = SafeArrayCreate(-1, 1, &bound);
296 ok(NULL == a,"SAC(-1,1,[1,0]) not failed?\n");
298 bound.cElements = 0;
299 bound.lLbound = 42;
300 a = SafeArrayCreate(VT_I4, 1, &bound);
301 ok(NULL != a,"SAC(VT_I4,1,[0,0]) failed.\n");
303 hres = SafeArrayGetLBound(a, 1, &l);
304 ok(hres == S_OK, "SAGLB of 0 size dimensioned array failed with %lx\n",hres);
305 ok(l == 42, "SAGLB of 0 size dimensioned array failed to return 42, but returned %ld\n",l);
306 hres = SafeArrayGetUBound(a, 1, &l);
307 ok(hres == S_OK, "SAGUB of 0 size dimensioned array failed with %lx\n",hres);
308 ok(l == 41, "SAGUB of 0 size dimensioned array failed to return 41, but returned %ld\n",l);
310 hres = SafeArrayAccessData(a, &data);
311 ok(hres == S_OK, "SafeArrayAccessData of 0 size dimensioned array failed with %lx\n", hres);
312 SafeArrayUnaccessData(a);
314 bound.cElements = 2;
315 hres = SafeArrayRedim(a, &bound);
316 ok(hres == S_OK,"SAR of a 0 elements dimension failed with hres %lx\n", hres);
317 bound.cElements = 0;
318 hres = SafeArrayRedim(a, &bound);
319 ok(hres == S_OK || hres == E_OUTOFMEMORY,
320 "SAR to a 0 elements dimension failed with hres %lx\n", hres);
321 hres = SafeArrayDestroy(a);
322 ok(hres == S_OK,"SAD of 0 dim array faild with hres %lx\n", hres);
324 SafeArrayAllocDescriptor(2, &a);
325 a->rgsabound[0].cElements = 2;
326 a->rgsabound[0].lLbound = 1;
327 a->rgsabound[1].cElements = 4;
328 a->rgsabound[1].lLbound = 1;
329 a->cbElements = 2;
330 SafeArrayAllocData(a);
332 indices[0] = 4;
333 indices[1] = 2;
334 hres = SafeArrayPtrOfIndex(a, indices, (void **)&ptr1);
335 ok(hres == S_OK, "SAPOI failed with hres %lx\n", hres);
336 SafeArrayAccessData(a, (void **)&ptr2);
337 ok(ptr1 - ptr2 == 14, "SAPOI got wrong ptr\n");
338 *(WORD *)ptr1 = 0x55aa;
339 SafeArrayUnaccessData(a);
341 bound.cElements = 10;
342 bound.lLbound = 1;
343 SafeArrayRedim(a, &bound);
344 ptr1 = NULL;
345 SafeArrayPtrOfIndex(a, indices, (void **)&ptr1);
346 ok(*(WORD *)ptr1 == 0x55aa, "Data not preserved when resizing array\n");
348 bound.cElements = 10;
349 bound.lLbound = 0;
350 SafeArrayRedim(a, &bound);
351 SafeArrayPtrOfIndex(a, indices, (void **)&ptr1);
352 ok(*(WORD *)ptr1 == 0, "Expanded area not zero-initialized\n");
354 indices[1] = 1;
355 SafeArrayPtrOfIndex(a, indices, (void **)&ptr1);
356 ok(*(WORD *)ptr1 == 0x55aa, "Data not preserved when resizing array\n");
358 bounds[0].cElements = 0; bounds[0].lLbound = 1;
359 bounds[1].cElements = 2; bounds[1].lLbound = 23;
360 a = SafeArrayCreate(VT_I4,2,bounds);
361 ok(a != NULL,"SAC(VT_INT32,2,...) with 0 element dim failed.\n");
362 bounds[0].cElements = 1; bounds[0].lLbound = 1;
363 bounds[1].cElements = 0; bounds[1].lLbound = 23;
364 a = SafeArrayCreate(VT_I4,2,bounds);
365 ok(a != NULL,"SAC(VT_INT32,2,...) with 0 element dim failed.\n");
367 bounds[0].cElements = 42; bounds[0].lLbound = 1;
368 bounds[1].cElements = 2; bounds[1].lLbound = 23;
369 a = SafeArrayCreate(VT_I4,2,bounds);
370 ok(a != NULL,"SAC(VT_INT32,2,...) failed.\n");
372 hres = SafeArrayGetLBound (a, 0, &l);
373 ok (hres == DISP_E_BADINDEX, "SAGLB 0 failed with %lx\n", hres);
374 hres = SafeArrayGetLBound (a, 1, &l);
375 ok (hres == S_OK, "SAGLB 1 failed with %lx\n", hres);
376 ok (l == 1, "SAGLB 1 returned %ld instead of 1\n", l);
377 hres = SafeArrayGetLBound (a, 2, &l);
378 ok (hres == S_OK, "SAGLB 2 failed with %lx\n", hres);
379 ok (l == 23, "SAGLB 2 returned %ld instead of 23\n", l);
380 hres = SafeArrayGetLBound (a, 3, &l);
381 ok (hres == DISP_E_BADINDEX, "SAGLB 3 failed with %lx\n", hres);
383 hres = SafeArrayGetUBound (a, 0, &l);
384 ok (hres == DISP_E_BADINDEX, "SAGUB 0 failed with %lx\n", hres);
385 hres = SafeArrayGetUBound (a, 1, &l);
386 ok (hres == S_OK, "SAGUB 1 failed with %lx\n", hres);
387 ok (l == 42, "SAGUB 1 returned %ld instead of 42\n", l);
388 hres = SafeArrayGetUBound (a, 2, &l);
389 ok (hres == S_OK, "SAGUB 2 failed with %lx\n", hres);
390 ok (l == 24, "SAGUB 2 returned %ld instead of 24\n", l);
391 hres = SafeArrayGetUBound (a, 3, &l);
392 ok (hres == DISP_E_BADINDEX, "SAGUB 3 failed with %lx\n", hres);
394 i = SafeArrayGetDim(a);
395 ok(i == 2, "getdims of 2 din array returned %d\n",i);
397 indices[0] = 0;
398 indices[1] = 23;
399 hres = SafeArrayGetElement(a, indices, &i);
400 ok(DISP_E_BADINDEX == hres,"SAGE failed [0,23], hres 0x%lx\n",hres);
402 indices[0] = 1;
403 indices[1] = 22;
404 hres = SafeArrayGetElement(a, indices, &i);
405 ok(DISP_E_BADINDEX == hres,"SAGE failed [1,22], hres 0x%lx\n",hres);
407 indices[0] = 1;
408 indices[1] = 23;
409 hres = SafeArrayGetElement(a, indices, &i);
410 ok(S_OK == hres,"SAGE failed [1,23], hres 0x%lx\n",hres);
412 indices[0] = 1;
413 indices[1] = 25;
414 hres = SafeArrayGetElement(a, indices, &i);
415 ok(DISP_E_BADINDEX == hres,"SAGE failed [1,24], hres 0x%lx\n",hres);
417 indices[0] = 3;
418 indices[1] = 23;
419 hres = SafeArrayGetElement(a, indices, &i);
420 ok(S_OK == hres,"SAGE failed [42,23], hres 0x%lx\n",hres);
422 hres = SafeArrayAccessData(a, (void**)&ptr1);
423 ok(S_OK == hres, "SAAD failed with 0x%lx\n", hres);
425 indices[0] = 3;
426 indices[1] = 23;
427 hres = SafeArrayPtrOfIndex(a, indices, (void**)&ptr2);
428 ok(S_OK == hres,"SAPOI failed [1,23], hres 0x%lx\n",hres);
429 ok(ptr2 - ptr1 == 8,"ptr difference is not 8, but %d (%p vs %p)\n", ptr2-ptr1, ptr2, ptr1);
431 indices[0] = 3;
432 indices[1] = 24;
433 hres = SafeArrayPtrOfIndex(a, indices, (void**)&ptr2);
434 ok(S_OK == hres,"SAPOI failed [5,24], hres 0x%lx\n",hres);
435 ok(ptr2 - ptr1 == 176,"ptr difference is not 176, but %d (%p vs %p)\n", ptr2-ptr1, ptr2, ptr1);
437 indices[0] = 20;
438 indices[1] = 23;
439 hres = SafeArrayPtrOfIndex(a, indices, (void**)&ptr2);
440 ok(S_OK == hres,"SAPOI failed [20,23], hres 0x%lx\n",hres);
441 ok(ptr2 - ptr1 == 76,"ptr difference is not 76, but %d (%p vs %p)\n", ptr2-ptr1, ptr2, ptr1);
443 hres = SafeArrayUnaccessData(a);
444 ok(S_OK == hres, "SAUAD failed with 0x%lx\n", hres);
446 for (i=0;i<sizeof(vttypes)/sizeof(vttypes[0]);i++) {
447 if ((i == VT_I8 || i == VT_UI8) && HAVE_OLEAUT32_I8)
449 vttypes[i].elemsize = sizeof(LONG64);
452 a = SafeArrayCreate(vttypes[i].vt, 1, &bound);
454 ok((!a && !vttypes[i].elemsize) ||
455 (a && vttypes[i].elemsize == a->cbElements) ||
456 (IS_ANCIENT && (vttypes[i].vt == VT_DECIMAL || vttypes[i].vt == VT_I1 ||
457 vttypes[i].vt == VT_UI2 || vttypes[i].vt == VT_UI4 || vttypes[i].vt == VT_INT ||
458 vttypes[i].vt == VT_UINT)),
459 "SAC(%d,1,[1,0]), %p result %ld, expected %d\n",
460 vttypes[i].vt,a,(a?a->cbElements:0),vttypes[i].elemsize);
462 if (a)
464 if (!HAVE_OLEAUT32_RECORD)
465 vttypes[i].expflags = 0;
466 ok(a->fFeatures == (vttypes[i].expflags | vttypes[i].addflags),
467 "SAC of %d returned feature flags %x, expected %x\n",
468 vttypes[i].vt, a->fFeatures,
469 vttypes[i].expflags|vttypes[i].addflags);
470 ok(SafeArrayGetElemsize(a) == vttypes[i].elemsize,
471 "SAGE for vt %d returned elemsize %d instead of expected %d\n",
472 vttypes[i].vt, SafeArrayGetElemsize(a),vttypes[i].elemsize);
475 if (!a) continue;
477 if (pSafeArrayGetVartype)
479 hres = pSafeArrayGetVartype(a, &vt);
480 ok(hres == S_OK, "SAGVT of arra y with vt %d failed with %lx\n", vttypes[i].vt, hres);
481 if (vttypes[i].vt == VT_DISPATCH) {
482 /* Special case. Checked against Windows. */
483 ok(vt == VT_UNKNOWN, "SAGVT of a rray with VT_DISPATCH returned not VT_UNKNOWN, but %d\n", vt);
484 } else {
485 ok(vt == vttypes[i].vt, "SAGVT of array with vt %d returned %d\n", vttypes[i].vt, vt);
489 hres = SafeArrayCopy(a, &c);
490 ok(hres == S_OK, "failed to copy safearray of vt %d with hres %lx\n", vttypes[i].vt, hres);
492 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
494 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);
495 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);
497 if (pSafeArrayGetVartype) {
498 hres = pSafeArrayGetVartype(c, &vt);
499 ok(hres == S_OK, "SAGVT of array with vt %d failed with %lx\n", vttypes[i].vt, hres);
500 if (vttypes[i].vt == VT_DISPATCH) {
501 /* Special case. Checked against Windows. */
502 ok(vt == VT_UNKNOWN, "SAGVT of array with VT_DISPATCH returned not VT_UNKNOWN, but %d\n", vt);
503 } else {
504 ok(vt == vttypes[i].vt, "SAGVT of array with vt %d returned %d\n", vttypes[i].vt, vt);
508 if (pSafeArrayCopyData) {
509 hres = pSafeArrayCopyData(a, c);
510 ok(hres == S_OK, "failed to copy safearray data of vt %d with hres %lx\n", vttypes[i].vt, hres);
512 hres = SafeArrayDestroyData(c);
513 ok(hres == S_OK,"SADD of copy of array with vt %d failed with hres %lx\n", vttypes[i].vt, hres);
516 hres = SafeArrayDestroy(a);
517 ok(hres == S_OK,"SAD of array with vt %d failed with hres %lx\n", vttypes[i].vt, hres);
520 /* Test conversion of type|VT_ARRAY <-> VT_BSTR */
521 bound.lLbound = 0;
522 bound.cElements = 10;
523 a = SafeArrayCreate(VT_UI1, 1, &bound);
524 ok(a != NULL, "SAC failed.\n");
525 ok(S_OK == SafeArrayAccessData(a, &data),"SACD failed\n");
526 memcpy(data,"Hello World\n",10);
527 ok(S_OK == SafeArrayUnaccessData(a),"SAUD failed\n");
528 V_VT(&v) = VT_ARRAY|VT_UI1;
529 V_ARRAY(&v) = a;
530 hres = VariantChangeTypeEx(&v, &v, 0, 0, VT_BSTR);
531 ok(hres==S_OK, "CTE VT_ARRAY|VT_UI1 -> VT_BSTR failed with %lx\n",hres);
532 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));
533 ok(V_BSTR(&v)[0] == 0x6548,"First letter are not 'He', but %x\n", V_BSTR(&v)[0]);
535 /* check locking functions */
536 a = SafeArrayCreate(VT_I4, 1, &bound);
537 ok(a!=NULL,"SAC should not fail\n");
539 hres = SafeArrayAccessData(a, &data);
540 ok(hres == S_OK,"SAAD failed with hres %lx\n",hres);
542 hres = SafeArrayDestroy(a);
543 ok(hres == DISP_E_ARRAYISLOCKED,"locked safe array destroy not failed with DISP_E_ARRAYISLOCKED, but with hres %lx\n", hres);
545 hres = SafeArrayDestroyData(a);
546 ok(hres == DISP_E_ARRAYISLOCKED,"locked safe array destroy data not failed with DISP_E_ARRAYISLOCKED, but with hres %lx\n", hres);
548 hres = SafeArrayDestroyDescriptor(a);
549 ok(hres == DISP_E_ARRAYISLOCKED,"locked safe array destroy descriptor not failed with DISP_E_ARRAYISLOCKED, but with hres %lx\n", hres);
551 hres = SafeArrayUnaccessData(a);
552 ok(hres == S_OK,"SAUD failed after lock/destroy test\n");
554 hres = SafeArrayDestroy(a);
555 ok(hres == S_OK,"SAD failed after lock/destroy test\n");
557 /* Test if we need to destroy data before descriptor */
558 a = SafeArrayCreate(VT_I4, 1, &bound);
559 ok(a!=NULL,"SAC should not fail\n");
560 hres = SafeArrayDestroyDescriptor(a);
561 ok(hres == S_OK,"SADD with data in array failed with hres %lx\n",hres);
564 /* IID functions */
565 /* init a small stack safearray */
566 if (pSafeArraySetIID) {
567 memset(&b, 0, sizeof(b));
568 b.cDims = 1;
569 memset(&iid, 0x42, sizeof(IID));
570 hres = pSafeArraySetIID(&b,&iid);
571 ok(hres == E_INVALIDARG,"SafeArraySetIID of non IID capable safearray did not return E_INVALIDARG, but %lx\n",hres);
573 hres = SafeArrayAllocDescriptor(1,&a);
574 ok((a->fFeatures & FADF_HAVEIID) == 0,"newly allocated descriptor with SAAD should not have FADF_HAVEIID\n");
575 hres = pSafeArraySetIID(a,&iid);
576 ok(hres == E_INVALIDARG,"SafeArraySetIID of newly allocated descriptor with SAAD should return E_INVALIDARG, but %lx\n",hres);
579 if (!pSafeArrayAllocDescriptorEx)
580 return;
582 for (i=0;i<sizeof(vttypes)/sizeof(vttypes[0]);i++) {
583 a = NULL;
584 hres = pSafeArrayAllocDescriptorEx(vttypes[i].vt,1,&a);
585 ok(a->fFeatures == vttypes[i].expflags,"SAADE(%d) resulted with flags %x, expected %x\n", vttypes[i].vt, a->fFeatures, vttypes[i].expflags);
586 if (a->fFeatures & FADF_HAVEIID) {
587 hres = pSafeArrayGetIID(a, &iid);
588 ok(hres == S_OK,"SAGIID failed for vt %d with hres %lx\n", vttypes[i].vt,hres);
589 switch (vttypes[i].vt) {
590 case VT_UNKNOWN:
591 ok(IsEqualGUID(((GUID*)a)-1,&IID_IUnknown),"guid for VT_UNKNOWN is not IID_IUnknown\n");
592 ok(IsEqualGUID(&iid, &IID_IUnknown),"SAGIID returned wrong GUID for IUnknown\n");
593 break;
594 case VT_DISPATCH:
595 ok(IsEqualGUID(((GUID*)a)-1,&IID_IDispatch),"guid for VT_UNKNOWN is not IID_IDispatch\n");
596 ok(IsEqualGUID(&iid, &IID_IDispatch),"SAGIID returned wrong GUID for IDispatch\n");
597 break;
598 default:
599 ok(FALSE,"unknown vt %d with FADF_HAVEIID\n",vttypes[i].vt);
600 break;
602 } else {
603 hres = pSafeArrayGetIID(a, &iid);
604 ok(hres == E_INVALIDARG,"SAGIID did not fail for vt %d with hres %lx\n", vttypes[i].vt,hres);
606 if (a->fFeatures & FADF_RECORD) {
607 ok(vttypes[i].vt == VT_RECORD,"FADF_RECORD for non record %d\n",vttypes[i].vt);
609 if (a->fFeatures & FADF_HAVEVARTYPE) {
610 ok(vttypes[i].vt == ((DWORD*)a)[-1], "FADF_HAVEVARTYPE set, but vt %d mismatch stored %ld\n",vttypes[i].vt,((DWORD*)a)[-1]);
613 hres = pSafeArrayGetVartype(a, &vt);
614 ok(hres == S_OK, "SAGVT of array with vt %d failed with %lx\n", vttypes[i].vt, hres);
616 if (vttypes[i].vt == VT_DISPATCH) {
617 /* Special case. Checked against Windows. */
618 ok(vt == VT_UNKNOWN, "SAGVT of array with VT_DISPATCH returned not VT_UNKNOWN, but %d\n", vt);
619 } else {
620 ok(vt == vttypes[i].vt, "SAGVT of array with vt %d returned %d\n", vttypes[i].vt, vt);
623 if (a->fFeatures & FADF_HAVEIID) {
624 hres = pSafeArraySetIID(a, &IID_IStorage); /* random IID */
625 ok(hres == S_OK,"SASIID failed with FADF_HAVEIID set for vt %d with %lx\n", vttypes[i].vt, hres);
626 hres = pSafeArrayGetIID(a, &iid);
627 ok(hres == S_OK,"SAGIID failed with FADF_HAVEIID set for vt %d with %lx\n", vttypes[i].vt, hres);
628 ok(IsEqualGUID(&iid, &IID_IStorage),"returned iid is not IID_IStorage\n");
629 } else {
630 hres = pSafeArraySetIID(a, &IID_IStorage); /* random IID */
631 ok(hres == E_INVALIDARG,"SASIID did not failed with !FADF_HAVEIID set for vt %d with %lx\n", vttypes[i].vt, hres);
633 hres = SafeArrayDestroyDescriptor(a);
634 ok(hres == S_OK,"SADD failed with hres %lx\n",hres);
638 static void test_SafeArrayAllocDestroyDescriptor(void)
640 SAFEARRAY *sa;
641 HRESULT hres;
642 int i;
644 /* Failure cases */
645 hres = SafeArrayAllocDescriptor(0, &sa);
646 ok(hres == E_INVALIDARG, "0 dimensions gave hres 0x%lx\n", hres);
648 hres = SafeArrayAllocDescriptor(65536, &sa);
649 ok(IS_ANCIENT || hres == E_INVALIDARG,
650 "65536 dimensions gave hres 0x%lx\n", hres);
652 #if 0
653 /* Crashes on 95: XP & Wine return E_POINTER */
654 hres=SafeArrayAllocDescriptor(1, NULL);
655 ok(hres == E_POINTER,"NULL parm gave hres 0x%lx\n", hres);
656 #endif
658 /* Test up to the dimension boundary case */
659 for (i = 5; i <= 65535; i += 30)
661 hres = SafeArrayAllocDescriptor(i, &sa);
662 ok(hres == S_OK, "%d dimensions failed; hres 0x%lx\n", i, hres);
664 if (hres == S_OK)
666 ok(SafeArrayGetDim(sa) == (UINT)i, "Dimension is %d; should be %d\n",
667 SafeArrayGetDim(sa), i);
669 hres = SafeArrayDestroyDescriptor(sa);
670 ok(hres == S_OK, "destroy failed; hres 0x%lx\n", hres);
674 if (!pSafeArrayAllocDescriptorEx)
675 return;
677 hres = pSafeArrayAllocDescriptorEx(VT_UI1, 0, &sa);
678 ok(hres == E_INVALIDARG, "0 dimensions gave hres 0x%lx\n", hres);
680 hres = pSafeArrayAllocDescriptorEx(VT_UI1, 65536, &sa);
681 ok(hres == E_INVALIDARG, "65536 dimensions gave hres 0x%lx\n", hres);
683 hres = pSafeArrayAllocDescriptorEx(VT_UI1, 1, NULL);
684 ok(hres == E_POINTER,"NULL parm gave hres 0x%lx\n", hres);
686 hres = pSafeArrayAllocDescriptorEx(-1, 1, &sa);
687 ok(hres == S_OK, "VT = -1 gave hres 0x%lx\n", hres);
689 sa->rgsabound[0].cElements = 0;
690 sa->rgsabound[0].lLbound = 1;
692 hres = SafeArrayAllocData(sa);
693 todo_wine
695 ok(hres == S_OK, "SafeArrayAllocData gave hres 0x%lx\n", hres);
699 static void test_SafeArrayCreateLockDestroy(void)
701 SAFEARRAYBOUND sab[4];
702 SAFEARRAY *sa;
703 HRESULT hres;
704 VARTYPE vt;
705 int dimension;
707 #define NUM_DIMENSIONS (int)(sizeof(sab) / sizeof(sab[0]))
709 for (dimension = 0; dimension < NUM_DIMENSIONS; dimension++)
711 sab[dimension].lLbound = 0;
712 sab[dimension].cElements = 8;
715 /* Failure cases */
716 /* This test crashes very early versions with no error checking...
717 sa = SafeArrayCreate(VT_UI1, 1, NULL);
718 ok(sa == NULL, "NULL bounds didn't fail\n");
720 sa = SafeArrayCreate(VT_UI1, 65536, sab);
721 ok(IS_ANCIENT || !sa, "Max bounds didn't fail\n");
723 memset(sab, 0, sizeof(sab));
725 /* Don't test 0 sized dimensions, as Windows has a bug which allows this */
727 for (dimension = 0; dimension < NUM_DIMENSIONS; dimension++)
728 sab[dimension].cElements = 8;
730 /* Test all VARTYPES in 1-4 dimensions */
731 for (dimension = 1; dimension < 4; dimension++)
733 for (vt = VT_EMPTY; vt < VT_CLSID; vt++)
735 DWORD dwLen = SAFEARRAY_GetVTSize(vt);
737 sa = SafeArrayCreate(vt, dimension, sab);
739 if (dwLen)
740 ok(sa || (IS_ANCIENT && (vt == VT_DECIMAL || vt == VT_I1 || vt == VT_UI2 ||
741 vt == VT_UI4 || vt == VT_INT || vt == VT_UINT)),
742 "VARTYPE %d (@%d dimensions) failed\n", vt, dimension);
743 else
744 ok(sa == NULL || vt == VT_R8,
745 "VARTYPE %d (@%d dimensions) succeeded!\n", vt, dimension);
747 if (sa)
749 ok(SafeArrayGetDim(sa) == (UINT)dimension,
750 "VARTYPE %d (@%d dimensions) cDims is %d, expected %d\n",
751 vt, dimension, SafeArrayGetDim(sa), dimension);
752 ok(SafeArrayGetElemsize(sa) == dwLen || vt == VT_R8,
753 "VARTYPE %d (@%d dimensions) cbElements is %d, expected %ld\n",
754 vt, dimension, SafeArrayGetElemsize(sa), dwLen);
756 if (vt != VT_UNKNOWN && vt != VT_DISPATCH)
758 ok((sa->fFeatures & FADF_HAVEIID) == 0,
759 "Non interface type should not have FADF_HAVEIID\n");
760 if (pSafeArraySetIID)
762 hres = pSafeArraySetIID(sa, &IID_IUnknown);
763 ok(hres == E_INVALIDARG,
764 "Non interface type allowed SetIID(), hres %lx\n", hres);
766 if (vt != VT_RECORD)
768 VARTYPE aVt;
770 ok(IS_ANCIENT || sa->fFeatures & FADF_HAVEVARTYPE,
771 "Non interface type should have FADF_HAVEVARTYPE\n");
772 if (pSafeArrayGetVartype)
774 hres = pSafeArrayGetVartype(sa, &aVt);
775 ok(hres == S_OK && aVt == vt,
776 "Non interface type %d: bad type %d, hres %lx\n", vt, aVt, hres);
780 else
782 ok(IS_ANCIENT || sa->fFeatures & FADF_HAVEIID,
783 "Interface type should have FADF_HAVEIID\n");
784 if (pSafeArraySetIID)
786 hres = pSafeArraySetIID(sa, &IID_IUnknown);
787 ok(hres == S_OK,
788 "Non interface type disallowed SetIID(), hres %lx\n", hres);
790 ok((sa->fFeatures & FADF_HAVEVARTYPE) == 0,
791 "Interface type %d should not have FADF_HAVEVARTYPE\n", vt);
794 hres = SafeArrayLock(sa);
795 ok(hres == S_OK, "Lock VARTYPE %d (@%d dimensions) failed; hres 0x%lx\n",
796 vt, dimension, hres);
798 if (hres == S_OK)
800 hres = SafeArrayDestroy(sa);
801 ok(hres == DISP_E_ARRAYISLOCKED,"Destroy() got hres %lx\n", hres);
803 hres = SafeArrayDestroyData(sa);
804 ok(hres == DISP_E_ARRAYISLOCKED,"DestroyData() got hres %lx\n", hres);
806 hres = SafeArrayDestroyDescriptor(sa);
807 ok(hres == DISP_E_ARRAYISLOCKED,"DestroyDescriptor() got hres %lx\n", hres);
809 hres = SafeArrayUnlock(sa);
810 ok(hres == S_OK, "Unlock VARTYPE %d (@%d dims) hres 0x%lx\n",
811 vt, dimension, hres);
813 hres = SafeArrayDestroyDescriptor(sa);
814 ok(hres == S_OK, "destroy VARTYPE %d (@%d dims) hres 0x%lx\n",
815 vt, dimension, hres);
822 static void test_VectorCreateLockDestroy(void)
824 SAFEARRAY *sa;
825 HRESULT hres;
826 VARTYPE vt;
827 int element;
829 if (!pSafeArrayCreateVector)
830 return;
831 sa = pSafeArrayCreateVector(VT_UI1, 0, 0);
832 ok(sa != NULL, "SACV with 0 elements failed.\n");
834 /* Test all VARTYPES in different lengths */
835 for (element = 1; element <= 101; element += 10)
837 for (vt = VT_EMPTY; vt < VT_CLSID; vt++)
839 DWORD dwLen = SAFEARRAY_GetVTSize(vt);
841 sa = pSafeArrayCreateVector(vt, 0, element);
843 if (dwLen)
844 ok(sa != NULL, "VARTYPE %d (@%d elements) failed\n", vt, element);
845 else
846 ok(sa == NULL, "VARTYPE %d (@%d elements) succeeded!\n", vt, element);
848 if (sa)
850 ok(SafeArrayGetDim(sa) == 1, "VARTYPE %d (@%d elements) cDims %d, not 1\n",
851 vt, element, SafeArrayGetDim(sa));
852 ok(SafeArrayGetElemsize(sa) == dwLen,
853 "VARTYPE %d (@%d elements) cbElements is %d, expected %ld\n",
854 vt, element, SafeArrayGetElemsize(sa), dwLen);
856 hres = SafeArrayLock(sa);
857 ok(hres == S_OK, "Lock VARTYPE %d (@%d elements) failed; hres 0x%lx\n",
858 vt, element, hres);
860 if (hres == S_OK)
862 hres = SafeArrayUnlock(sa);
863 ok(hres == S_OK, "Unlock VARTYPE %d (@%d elements) failed; hres 0x%lx\n",
864 vt, element, hres);
866 hres = SafeArrayDestroyDescriptor(sa);
867 ok(hres == S_OK, "destroy VARTYPE %d (@%d elements) failed; hres 0x%lx\n",
868 vt, element, hres);
875 static void test_LockUnlock(void)
877 SAFEARRAYBOUND sab[4];
878 SAFEARRAY *sa;
879 HRESULT hres;
880 BOOL bVector = FALSE;
881 int dimension;
883 /* Failure cases */
884 hres = SafeArrayLock(NULL);
885 ok(hres == E_INVALIDARG, "Lock NULL array hres 0x%lx\n", hres);
886 hres = SafeArrayUnlock(NULL);
887 ok(hres == E_INVALIDARG, "Lock NULL array hres 0x%lx\n", hres);
889 for (dimension = 0; dimension < NUM_DIMENSIONS; dimension++)
891 sab[dimension].lLbound = 0;
892 sab[dimension].cElements = 8;
895 sa = SafeArrayCreate(VT_UI1, NUM_DIMENSIONS, sab);
897 /* Test maximum locks */
898 test_LockUnlock_Vector:
899 if (sa)
901 int count = 0;
903 hres = SafeArrayUnlock(sa);
904 ok (hres == E_UNEXPECTED, "Bad %sUnlock gave hres 0x%lx\n",
905 bVector ? "vector " : "\n", hres);
907 while ((hres = SafeArrayLock(sa)) == S_OK)
908 count++;
909 ok (count == 65535 && hres == E_UNEXPECTED, "Lock %sfailed at %d; hres 0x%lx\n",
910 bVector ? "vector " : "\n", count, hres);
912 if (count == 65535 && hres == E_UNEXPECTED)
914 while ((hres = SafeArrayUnlock(sa)) == S_OK)
915 count--;
916 ok (count == 0 && hres == E_UNEXPECTED, "Unlock %sfailed at %d; hres 0x%lx\n",
917 bVector ? "vector " : "\n", count, hres);
920 SafeArrayDestroy(sa);
923 if (bVector == FALSE && pSafeArrayCreateVector)
925 /* Test again with a vector */
926 sa = pSafeArrayCreateVector(VT_UI1, 0, 100);
927 bVector = TRUE;
928 goto test_LockUnlock_Vector;
932 static void test_SafeArrayGetPutElement(void)
934 SAFEARRAYBOUND sab[4];
935 LONG indices[NUM_DIMENSIONS];
936 SAFEARRAY *sa;
937 HRESULT hres;
938 int value = 0, gotvalue, dimension;
939 unsigned int x,y,z,a;
941 for (dimension = 0; dimension < NUM_DIMENSIONS; dimension++)
943 sab[dimension].lLbound = dimension * 2 + 1;
944 sab[dimension].cElements = dimension * 3 + 1;
947 sa = SafeArrayCreate(VT_INT, NUM_DIMENSIONS, sab);
948 if (!sa)
949 return; /* Some early versions can't handle > 3 dims */
951 ok(sa->cbElements == sizeof(value), "int size mismatch\n");
952 if (sa->cbElements != sizeof(value))
953 return;
955 /* Failure cases */
956 for (x = 0; x < NUM_DIMENSIONS; x++)
958 indices[0] = sab[0].lLbound;
959 indices[1] = sab[1].lLbound;
960 indices[2] = sab[2].lLbound;
961 indices[3] = sab[3].lLbound;
963 indices[x] = indices[x] - 1;
964 hres = SafeArrayPutElement(sa, indices, &value);
965 ok(hres == DISP_E_BADINDEX, "Put allowed too small index in dimension %d\n", x);
966 hres = SafeArrayGetElement(sa, indices, &value);
967 ok(hres == DISP_E_BADINDEX, "Get allowed too small index in dimension %d\n", x);
969 indices[x] = sab[x].lLbound + sab[x].cElements;
970 hres = SafeArrayPutElement(sa, indices, &value);
971 ok(hres == DISP_E_BADINDEX, "Put allowed too big index in dimension %d\n", x);
972 hres = SafeArrayGetElement(sa, indices, &value);
973 ok(hres == DISP_E_BADINDEX, "Get allowed too big index in dimension %d\n", x);
976 indices[0] = sab[0].lLbound;
977 indices[1] = sab[1].lLbound;
978 indices[2] = sab[2].lLbound;
979 indices[3] = sab[3].lLbound;
981 hres = SafeArrayPutElement(NULL, indices, &value);
982 ok(hres == E_INVALIDARG, "Put NULL array hres 0x%lx\n", hres);
983 hres = SafeArrayGetElement(NULL, indices, &value);
984 ok(hres == E_INVALIDARG, "Get NULL array hres 0x%lx\n", hres);
986 hres = SafeArrayPutElement(sa, NULL, &value);
987 ok(hres == E_INVALIDARG, "Put NULL indices hres 0x%lx\n", hres);
988 hres = SafeArrayGetElement(sa, NULL, &value);
989 ok(hres == E_INVALIDARG, "Get NULL indices hres 0x%lx\n", hres);
991 #if 0
992 /* This is retarded. Windows checks every case of invalid parameters
993 * except the following, which crashes. We ERR this in Wine.
995 hres = SafeArrayPutElement(sa, indices, NULL);
996 ok(hres == E_INVALIDARG, "Put NULL value hres 0x%lx\n", hres);
997 #endif
999 hres = SafeArrayGetElement(sa, indices, NULL);
1000 ok(hres == E_INVALIDARG, "Get NULL value hres 0x%lx\n", hres);
1002 value = 0;
1004 /* Make sure we can read and get back the correct values in 4 dimensions,
1005 * Each with a different size and lower bound.
1007 for (x = 0; x < sab[0].cElements; x++)
1009 indices[0] = sab[0].lLbound + x;
1010 for (y = 0; y < sab[1].cElements; y++)
1012 indices[1] = sab[1].lLbound + y;
1013 for (z = 0; z < sab[2].cElements; z++)
1015 indices[2] = sab[2].lLbound + z;
1016 for (a = 0; a < sab[3].cElements; a++)
1018 indices[3] = sab[3].lLbound + a;
1019 hres = SafeArrayPutElement(sa, indices, &value);
1020 ok(hres == S_OK, "Failed to put element at (%d,%d,%d,%d) hres 0x%lx\n",
1021 x, y, z, a, hres);
1022 value++;
1028 value = 0;
1030 for (x = 0; x < sab[0].cElements; x++)
1032 indices[0] = sab[0].lLbound + x;
1033 for (y = 0; y < sab[1].cElements; y++)
1035 indices[1] = sab[1].lLbound + y;
1036 for (z = 0; z < sab[2].cElements; z++)
1038 indices[2] = sab[2].lLbound + z;
1039 for (a = 0; a < sab[3].cElements; a++)
1041 indices[3] = sab[3].lLbound + a;
1042 gotvalue = value / 3;
1043 hres = SafeArrayGetElement(sa, indices, &gotvalue);
1044 ok(hres == S_OK, "Failed to get element at (%d,%d,%d,%d) hres 0x%lx\n",
1045 x, y, z, a, hres);
1046 if (hres == S_OK)
1047 ok(value == gotvalue, "Got value %d instead of %d at (%d,%d,%d,%d)\n",
1048 gotvalue, value, x, y, z, a);
1049 value++;
1054 SafeArrayDestroy(sa);
1057 static void test_SafeArrayGetPutElement_BSTR(void)
1059 SAFEARRAYBOUND sab;
1060 LONG indices[1];
1061 SAFEARRAY *sa;
1062 HRESULT hres;
1063 BSTR value = 0, gotvalue;
1064 const OLECHAR szTest[5] = { 'T','e','s','t','\0' };
1066 sab.lLbound = 1;
1067 sab.cElements = 1;
1069 sa = SafeArrayCreate(VT_BSTR, 1, &sab);
1070 ok(sa != NULL, "BSTR test couldn't create array\n");
1071 if (!sa)
1072 return;
1074 ok(sa->cbElements == sizeof(BSTR), "BSTR size mismatch\n");
1075 if (sa->cbElements != sizeof(BSTR))
1076 return;
1078 indices[0] = sab.lLbound;
1079 value = SysAllocString(szTest);
1080 ok (value != NULL, "Expected non-NULL\n");
1081 hres = SafeArrayPutElement(sa, indices, value);
1082 ok(hres == S_OK, "Failed to put bstr element hres 0x%lx\n", hres);
1083 gotvalue = NULL;
1084 hres = SafeArrayGetElement(sa, indices, &gotvalue);
1085 ok(hres == S_OK, "Failed to get bstr element at hres 0x%lx\n", hres);
1086 if (hres == S_OK)
1087 ok(SysStringLen(value) == SysStringLen(gotvalue), "Got len %d instead of %d\n", SysStringLen(gotvalue), SysStringLen(value));
1088 SafeArrayDestroy(sa);
1091 static int tunk_xref = 0;
1092 static HRESULT WINAPI tunk_QueryInterface(LPUNKNOWN punk,REFIID riid, LPVOID *x) {
1093 return E_FAIL;
1095 static ULONG WINAPI tunk_AddRef(LPUNKNOWN punk) {
1096 return ++tunk_xref;
1099 static ULONG WINAPI tunk_Release(LPUNKNOWN punk) {
1100 return --tunk_xref;
1103 static const IUnknownVtbl xtunk_vtbl = {
1104 tunk_QueryInterface,
1105 tunk_AddRef,
1106 tunk_Release
1109 static struct xtunk_iface {
1110 const IUnknownVtbl *lpvtbl;
1111 } xtunk_iface;
1114 static void test_SafeArrayGetPutElement_IUnknown(void)
1116 SAFEARRAYBOUND sab;
1117 LONG indices[1];
1118 SAFEARRAY *sa;
1119 HRESULT hres;
1120 LPUNKNOWN value = 0, gotvalue;
1122 sab.lLbound = 1;
1123 sab.cElements = 1;
1124 sa = SafeArrayCreate(VT_UNKNOWN, 1, &sab);
1125 ok(sa != NULL, "UNKNOWN test couldn't create array\n");
1126 if (!sa)
1127 return;
1129 ok(sa->cbElements == sizeof(LPUNKNOWN), "LPUNKNOWN size mismatch\n");
1130 if (sa->cbElements != sizeof(LPUNKNOWN))
1131 return;
1133 indices[0] = sab.lLbound;
1134 xtunk_iface.lpvtbl = &xtunk_vtbl;
1135 value = (LPUNKNOWN)&xtunk_iface;
1136 tunk_xref = 1;
1137 ok (value != NULL, "Expected non-NULL\n");
1138 hres = SafeArrayPutElement(sa, indices, value);
1139 ok(hres == S_OK, "Failed to put bstr element hres 0x%lx\n", hres);
1140 ok(tunk_xref == 2,"Failed to increment refcount of iface.\n");
1141 gotvalue = NULL;
1142 hres = SafeArrayGetElement(sa, indices, &gotvalue);
1143 ok(tunk_xref == 3,"Failed to increment refcount of iface.\n");
1144 ok(hres == S_OK, "Failed to get bstr element at hres 0x%lx\n", hres);
1145 if (hres == S_OK)
1146 ok(value == gotvalue, "Got %p instead of %p\n", gotvalue, value);
1147 SafeArrayDestroy(sa);
1148 ok(tunk_xref == 2,"Failed to decrement refcount of iface.\n");
1151 static void test_SafeArrayRedim_IUnknown(void)
1153 SAFEARRAYBOUND sab;
1154 LONG indices[1];
1155 SAFEARRAY *sa;
1156 HRESULT hres;
1157 LPUNKNOWN value;
1159 sab.lLbound = 1;
1160 sab.cElements = 2;
1161 sa = SafeArrayCreate(VT_UNKNOWN, 1, &sab);
1162 ok(sa != NULL, "UNKNOWN test couldn't create array\n");
1163 if (!sa)
1164 return;
1166 ok(sa->cbElements == sizeof(LPUNKNOWN), "LPUNKNOWN size mismatch\n");
1167 if (sa->cbElements != sizeof(LPUNKNOWN))
1168 return;
1170 indices[0] = 2;
1171 xtunk_iface.lpvtbl = &xtunk_vtbl;
1172 value = (LPUNKNOWN)&xtunk_iface;
1173 tunk_xref = 1;
1174 hres = SafeArrayPutElement(sa, indices, value);
1175 ok(hres == S_OK, "Failed to put IUnknown element hres 0x%lx\n", hres);
1176 ok(tunk_xref == 2,"Failed to increment refcount of iface.\n");
1177 sab.cElements = 1;
1178 hres = SafeArrayRedim(sa, &sab);
1179 ok(hres == S_OK, "Failed to shrink array hres 0x%lx\n", hres);
1180 ok(tunk_xref == 1, "Failed to decrement refcount\n");
1181 SafeArrayDestroy(sa);
1184 static void test_SafeArrayGetPutElement_VARIANT(void)
1186 SAFEARRAYBOUND sab;
1187 LONG indices[1];
1188 SAFEARRAY *sa;
1189 HRESULT hres;
1190 VARIANT value, gotvalue;
1192 sab.lLbound = 1;
1193 sab.cElements = 1;
1194 sa = SafeArrayCreate(VT_VARIANT, 1, &sab);
1195 ok(sa != NULL, "VARIANT test couldn't create array\n");
1196 if (!sa)
1197 return;
1199 ok(sa->cbElements == sizeof(VARIANT), "VARIANT size mismatch\n");
1200 if (sa->cbElements != sizeof(VARIANT))
1201 return;
1203 indices[0] = sab.lLbound;
1204 V_VT(&value) = VT_I4;
1205 V_I4(&value) = 0x42424242;
1206 hres = SafeArrayPutElement(sa, indices, &value);
1207 ok(hres == S_OK, "Failed to put Variant I4 element hres 0x%lx\n", hres);
1209 V_VT(&gotvalue) = 0xdead;
1210 hres = SafeArrayGetElement(sa, indices, &gotvalue);
1211 ok(hres == S_OK, "Failed to get variant element at hres 0x%lx\n", hres);
1213 V_VT(&gotvalue) = VT_EMPTY;
1214 hres = SafeArrayGetElement(sa, indices, &gotvalue);
1215 ok(hres == S_OK, "Failed to get variant element at hres 0x%lx\n", hres);
1216 if (hres == S_OK) {
1217 ok(V_VT(&value) == V_VT(&gotvalue), "Got type 0x%x instead of 0x%x\n", V_VT(&value), V_VT(&gotvalue));
1218 if (V_VT(&value) == V_VT(&gotvalue))
1219 ok(V_I4(&value) == V_I4(&gotvalue), "Got %ld instead of %d\n", V_I4(&value), V_VT(&gotvalue));
1221 SafeArrayDestroy(sa);
1225 static void test_SafeArrayCopyData(void)
1227 SAFEARRAYBOUND sab[4];
1228 SAFEARRAY *sa;
1229 SAFEARRAY *sacopy;
1230 HRESULT hres;
1231 int dimension,size=1;
1233 if (!pSafeArrayCopyData)
1234 return;
1236 for (dimension = 0; dimension < NUM_DIMENSIONS; dimension++)
1238 sab[dimension].lLbound = dimension * 2 + 2;
1239 sab[dimension].cElements = dimension * 3 + 1;
1240 size *= sab[dimension].cElements;
1243 sa = SafeArrayCreate(VT_INT, NUM_DIMENSIONS, sab);
1244 ok(sa != NULL, "Copy test couldn't create array\n");
1245 sacopy = SafeArrayCreate(VT_INT, NUM_DIMENSIONS, sab);
1246 ok(sacopy != NULL, "Copy test couldn't create copy array\n");
1248 if (!sa || !sacopy)
1249 return;
1251 ok(sa->cbElements == sizeof(int), "int size mismatch\n");
1252 if (sa->cbElements != sizeof(int))
1253 return;
1255 /* Fill the source array with some data; it doesn't matter what */
1256 for (dimension = 0; dimension < size; dimension++)
1258 int* data = (int*)sa->pvData;
1259 data[dimension] = dimension;
1262 hres = pSafeArrayCopyData(sa, sacopy);
1263 ok(hres == S_OK, "copy data failed hres 0x%lx\n", hres);
1264 if (hres == S_OK)
1266 ok(!memcmp(sa->pvData, sacopy->pvData, size * sizeof(int)), "compared different\n");
1269 /* Failure cases */
1270 hres = pSafeArrayCopyData(NULL, sacopy);
1271 ok(hres == E_INVALIDARG, "Null copy source hres 0x%lx\n", hres);
1272 hres = pSafeArrayCopyData(sa, NULL);
1273 ok(hres == E_INVALIDARG, "Null copy hres 0x%lx\n", hres);
1275 sacopy->rgsabound[0].cElements += 1;
1276 hres = pSafeArrayCopyData(sa, sacopy);
1277 ok(hres == E_INVALIDARG, "Bigger copy first dimension hres 0x%lx\n", hres);
1279 sacopy->rgsabound[0].cElements -= 2;
1280 hres = pSafeArrayCopyData(sa, sacopy);
1281 ok(hres == E_INVALIDARG, "Smaller copy first dimension hres 0x%lx\n", hres);
1282 sacopy->rgsabound[0].cElements += 1;
1284 sacopy->rgsabound[3].cElements += 1;
1285 hres = pSafeArrayCopyData(sa, sacopy);
1286 ok(hres == E_INVALIDARG, "Bigger copy last dimension hres 0x%lx\n", hres);
1288 sacopy->rgsabound[3].cElements -= 2;
1289 hres = pSafeArrayCopyData(sa, sacopy);
1290 ok(hres == E_INVALIDARG, "Smaller copy last dimension hres 0x%lx\n", hres);
1291 sacopy->rgsabound[3].cElements += 1;
1293 SafeArrayDestroy(sacopy);
1294 sacopy = NULL;
1295 hres = pSafeArrayCopyData(sa, sacopy);
1296 ok(hres == E_INVALIDARG, "->Null copy hres 0x%lx\n", hres);
1298 hres = SafeArrayCopy(sa, &sacopy);
1299 ok(hres == S_OK, "copy failed hres 0x%lx\n", hres);
1300 if (hres == S_OK)
1302 ok(SafeArrayGetElemsize(sa) == SafeArrayGetElemsize(sacopy),"elemsize wrong\n");
1303 ok(SafeArrayGetDim(sa) == SafeArrayGetDim(sacopy),"dimensions wrong\n");
1304 ok(!memcmp(sa->pvData, sacopy->pvData, size * sizeof(int)), "compared different\n");
1307 SafeArrayDestroy(sa);
1310 static void test_SafeArrayCreateEx(void)
1312 IRecordInfoImpl* iRec;
1313 SAFEARRAYBOUND sab[4];
1314 SAFEARRAY *sa;
1315 HRESULT hres;
1316 int dimension;
1318 if (!pSafeArrayCreateEx)
1319 return;
1321 for (dimension = 0; dimension < NUM_DIMENSIONS; dimension++)
1323 sab[dimension].lLbound = 0;
1324 sab[dimension].cElements = 8;
1327 /* Failure cases */
1328 sa = pSafeArrayCreateEx(VT_UI1, 1, NULL, NULL);
1329 ok(sa == NULL, "CreateEx NULL bounds didn't fail\n");
1331 /* test IID storage & defaulting */
1332 sa = pSafeArrayCreateEx(VT_DISPATCH, 1, sab, (PVOID)&IID_ITypeInfo);
1333 ok(sa != NULL, "CreateEx (ITypeInfo) failed\n");
1335 if (sa)
1337 GUID guid;
1338 if (pSafeArrayGetIID)
1340 hres = pSafeArrayGetIID(sa, &guid);
1341 ok(hres == S_OK, "CreateEx (ITypeInfo) no IID hres 0x%lx\n", hres);
1342 if (hres == S_OK)
1344 ok(IsEqualGUID(&guid, &IID_ITypeInfo), "CreateEx (ITypeInfo) bad IID\n");
1347 if (pSafeArraySetIID)
1349 hres = pSafeArraySetIID(sa, &IID_IUnknown);
1350 ok(hres == S_OK, "Failed to set IID, hres = %8lx\n", hres);
1351 if (hres == S_OK && pSafeArrayGetIID)
1353 hres = pSafeArrayGetIID(sa, &guid);
1354 ok(hres == S_OK && IsEqualGUID(&guid, &IID_IUnknown), "Set bad IID\n");
1357 SafeArrayDestroy(sa);
1360 sa = pSafeArrayCreateEx(VT_DISPATCH, 1, sab, NULL);
1361 ok(sa != NULL, "CreateEx (NULL) failed\n");
1363 if (sa)
1365 GUID guid;
1366 if (pSafeArrayGetIID)
1368 hres = pSafeArrayGetIID(sa, &guid);
1369 ok(hres == S_OK, "CreateEx (NULL) no IID hres 0x%lx\n", hres);
1370 if (hres == S_OK)
1372 ok(IsEqualGUID(&guid, &IID_IDispatch), "CreateEx (NULL) bad IID\n");
1375 SafeArrayDestroy(sa);
1378 sa = pSafeArrayCreateEx(VT_UNKNOWN, 1, sab, NULL);
1379 ok(sa != NULL, "CreateEx (NULL-Unk) failed\n");
1381 if (sa)
1383 GUID guid;
1384 if (pSafeArrayGetIID)
1386 hres = pSafeArrayGetIID(sa, &guid);
1387 ok(hres == S_OK, "CreateEx (NULL-Unk) no IID hres 0x%lx\n", hres);
1388 if (hres == S_OK)
1390 ok(IsEqualGUID(&guid, &IID_IUnknown), "CreateEx (NULL-Unk) bad IID\n");
1393 SafeArrayDestroy(sa);
1396 /* VT_RECORD failure case */
1397 sa = pSafeArrayCreateEx(VT_RECORD, 1, sab, NULL);
1398 ok(sa == NULL, "CreateEx (NULL-Rec) succeded\n");
1400 iRec = IRecordInfoImpl_Construct();
1402 /* Win32 doesn't care if GetSize fails */
1403 fail_GetSize = TRUE;
1404 sa = pSafeArrayCreateEx(VT_RECORD, 1, sab, (LPVOID)iRec);
1405 ok(sa != NULL, "CreateEx (Fail Size) failed\n");
1406 ok(iRec->ref == START_REF_COUNT + 1, "Wrong iRec refcount %ld\n", iRec->ref);
1407 ok(iRec->sizeCalled == 1, "GetSize called %ld times\n", iRec->sizeCalled);
1408 ok(iRec->clearCalled == 0, "Clear called %ld times\n", iRec->clearCalled);
1409 if (sa)
1411 ok(sa->cbElements == RECORD_SIZE_FAIL, "Altered size to %ld\n", sa->cbElements);
1412 SafeArrayDestroy(sa);
1413 ok(iRec->clearCalled == sab[0].cElements, "Destroy->Clear called %ld times\n", iRec->clearCalled);
1416 /* Test VT_RECORD array */
1417 fail_GetSize = FALSE;
1418 iRec->ref = START_REF_COUNT;
1419 iRec->sizeCalled = 0;
1420 iRec->clearCalled = 0;
1421 sa = pSafeArrayCreateEx(VT_RECORD, 1, sab, (LPVOID)iRec);
1422 ok(sa != NULL, "CreateEx (Rec) failed\n");
1423 ok(iRec->ref == START_REF_COUNT + 1, "Wrong iRec refcount %ld\n", iRec->ref);
1424 ok(iRec->sizeCalled == 1, "GetSize called %ld times\n", iRec->sizeCalled);
1425 ok(iRec->clearCalled == 0, "Clear called %ld times\n", iRec->clearCalled);
1426 if (sa && pSafeArrayGetRecordInfo)
1428 IRecordInfo* saRec = NULL;
1429 hres = pSafeArrayGetRecordInfo(sa, &saRec);
1431 ok(hres == S_OK,"GRI failed\n");
1432 ok(saRec == (IRecordInfo*)iRec,"Different saRec\n");
1433 ok(iRec->ref == START_REF_COUNT + 2, "Didn't AddRef %ld\n", iRec->ref);
1434 if (iRec->ref == START_REF_COUNT + 2)
1435 IRecordInfo_Release(saRec);
1437 ok(sa->cbElements == RECORD_SIZE,"Elemsize is %ld\n", sa->cbElements);
1439 SafeArrayDestroy(sa);
1440 ok(iRec->sizeCalled == 1, "Destroy->GetSize called %ld times\n", iRec->sizeCalled);
1441 ok(iRec->clearCalled == sab[0].cElements, "Destroy->Clear called %ld times\n", iRec->clearCalled);
1442 ok(iRec->ref == START_REF_COUNT, "Wrong iRec refcount %ld\n", iRec->ref);
1446 static void test_SafeArrayClear(void)
1448 SAFEARRAYBOUND sab;
1449 SAFEARRAY *sa;
1450 VARIANTARG v;
1451 HRESULT hres;
1453 sab.lLbound = 0;
1454 sab.cElements = 10;
1455 sa = SafeArrayCreate(VT_UI1, 1, &sab);
1456 ok(sa != NULL, "Create() failed.\n");
1457 if (!sa)
1458 return;
1460 /* Test clearing non-NULL variants containing arrays */
1461 V_VT(&v) = VT_ARRAY|VT_UI1;
1462 V_ARRAY(&v) = sa;
1463 hres = VariantClear(&v);
1464 ok(hres == S_OK && V_VT(&v) == VT_EMPTY, "VariantClear: hres 0x%lx, Type %d\n", hres, V_VT(&v));
1465 ok(V_ARRAY(&v) == sa, "VariantClear: Overwrote value\n");
1467 sa = SafeArrayCreate(VT_UI1, 1, &sab);
1468 ok(sa != NULL, "Create() failed.\n");
1469 if (!sa)
1470 return;
1472 V_VT(&v) = VT_SAFEARRAY;
1473 V_ARRAY(&v) = sa;
1474 hres = VariantClear(&v);
1475 ok(hres == DISP_E_BADVARTYPE, "VariantClear: hres 0x%lx\n", hres);
1477 V_VT(&v) = VT_SAFEARRAY|VT_BYREF;
1478 V_ARRAYREF(&v) = &sa;
1479 hres = VariantClear(&v);
1480 ok(hres == DISP_E_BADVARTYPE, "VariantClear: hres 0x%lx\n", hres);
1482 SafeArrayDestroy(sa);
1485 static void test_SafeArrayCopy(void)
1487 SAFEARRAYBOUND sab;
1488 SAFEARRAY *sa, *sa2;
1489 VARIANTARG vSrc, vDst;
1490 HRESULT hres;
1492 sab.lLbound = 0;
1493 sab.cElements = 10;
1494 sa = SafeArrayCreate(VT_UI1, 1, &sab);
1495 ok(sa != NULL, "Create() failed.\n");
1496 if (!sa)
1497 return;
1499 /* Test copying non-NULL variants containing arrays */
1500 V_VT(&vSrc) = (VT_ARRAY|VT_BYREF|VT_UI1);
1501 V_ARRAYREF(&vSrc) = &sa;
1502 V_VT(&vDst) = VT_EMPTY;
1504 hres = VariantCopy(&vDst, &vSrc);
1505 ok(hres == S_OK && V_VT(&vDst) == (VT_ARRAY|VT_BYREF|VT_UI1),
1506 "VariantCopy: hres 0x%lx, Type %d\n", hres, V_VT(&vDst));
1507 ok(V_ARRAYREF(&vDst) == &sa, "VariantClear: Performed deep copy\n");
1509 V_VT(&vSrc) = (VT_ARRAY|VT_UI1);
1510 V_ARRAY(&vSrc) = sa;
1511 V_VT(&vDst) = VT_EMPTY;
1513 hres = VariantCopy(&vDst, &vSrc);
1514 ok(hres == S_OK && V_VT(&vDst) == (VT_ARRAY|VT_UI1),
1515 "VariantCopy: hres 0x%lx, Type %d\n", hres, V_VT(&vDst));
1516 ok(V_ARRAY(&vDst) != sa, "VariantClear: Performed shallow copy\n");
1518 SafeArrayDestroy(V_ARRAY(&vSrc));
1519 SafeArrayDestroy(V_ARRAY(&vDst));
1521 hres = SafeArrayAllocDescriptor(1, &sa);
1522 ok(hres == S_OK, "SafeArrayAllocDescriptor failed with error 0x%08lx\n", hres);
1524 hres = SafeArrayCopy(sa, &sa2);
1525 ok(hres == E_INVALIDARG,
1526 "SafeArrayCopy with empty array should have failed with error E_INVALIDARG instead of 0x%08lx\n",
1527 hres);
1528 sa->cbElements = 16;
1529 hres = SafeArrayCopy(sa, &sa2);
1530 ok(hres == S_OK, "SafeArrayCopy failed with error 0x%08lx\n", hres);
1532 SafeArrayDestroy(sa);
1535 #define MKARRAY(low,num,typ) sab.lLbound = low; sab.cElements = num; \
1536 sa = SafeArrayCreate(typ, 1, &sab); ok(sa != NULL, "Create() failed.\n"); \
1537 if (!sa) return; \
1538 V_VT(&v) = VT_ARRAY|typ; V_ARRAY(&v) = sa; VariantInit(&v2)
1540 #define MKARRAYCONT(low,num,typ) sab.lLbound = low; sab.cElements = num; \
1541 sa = SafeArrayCreate(typ, 1, &sab); if (!sa) continue; \
1542 V_VT(&v) = VT_ARRAY|typ; V_ARRAY(&v) = sa; VariantInit(&v2)
1544 static void test_SafeArrayChangeTypeEx(void)
1546 static const char *szHello = "Hello World";
1547 SAFEARRAYBOUND sab;
1548 SAFEARRAY *sa;
1549 VARIANTARG v,v2;
1550 VARTYPE vt;
1551 HRESULT hres;
1553 /* VT_ARRAY|VT_UI1 -> VT_BSTR */
1554 MKARRAY(0,strlen(szHello)+1,VT_UI1);
1555 memcpy(sa->pvData, szHello, strlen(szHello)+1);
1557 hres = VariantChangeTypeEx(&v2, &v, 0, 0, VT_BSTR);
1558 ok(hres == S_OK, "CTE VT_ARRAY|VT_UI1 -> VT_BSTR failed with %lx\n", hres);
1559 if (hres == S_OK)
1561 ok(V_VT(&v2) == VT_BSTR, "CTE VT_ARRAY|VT_UI1 -> VT_BSTR did not return VT_BSTR, but %d.\n",V_VT(&v2));
1562 ok(strcmp((char*)V_BSTR(&v2),szHello) == 0,"Expected string '%s', got '%s'\n", szHello,
1563 (char*)V_BSTR(&v2));
1564 VariantClear(&v2);
1567 /* VT_VECTOR|VT_UI1 -> VT_BSTR */
1568 SafeArrayDestroy(sa);
1569 if (pSafeArrayCreateVector)
1571 sa = pSafeArrayCreateVector(VT_UI1, 0, strlen(szHello)+1);
1572 ok(sa != NULL, "CreateVector() failed.\n");
1573 if (!sa)
1574 return;
1576 memcpy(sa->pvData, szHello, strlen(szHello)+1);
1577 V_VT(&v) = VT_VECTOR|VT_UI1;
1578 V_ARRAY(&v) = sa;
1579 VariantInit(&v2);
1581 hres = VariantChangeTypeEx(&v2, &v, 0, 0, VT_BSTR);
1582 ok(hres == DISP_E_BADVARTYPE, "CTE VT_VECTOR|VT_UI1 returned %lx\n", hres);
1584 /* (vector)VT_ARRAY|VT_UI1 -> VT_BSTR (In place) */
1585 V_VT(&v) = VT_ARRAY|VT_UI1;
1586 hres = VariantChangeTypeEx(&v, &v, 0, 0, VT_BSTR);
1587 ok(hres == S_OK, "CTE VT_ARRAY|VT_UI1 -> VT_BSTR failed with %lx\n", hres);
1588 if (hres == S_OK)
1590 ok(V_VT(&v) == VT_BSTR, "CTE VT_ARRAY|VT_UI1 -> VT_BSTR did not return VT_BSTR, but %d.\n",V_VT(&v));
1591 ok(strcmp((char*)V_BSTR(&v),szHello) == 0,"Expected string '%s', got '%s'\n", szHello,
1592 (char*)V_BSTR(&v));
1593 VariantClear(&v);
1597 /* To/from BSTR only works with arrays of VT_UI1 */
1598 for (vt = 0; vt <= VT_CLSID; vt++)
1600 if (vt == VT_UI1)
1601 continue;
1603 MKARRAYCONT(0,1,vt);
1604 hres = VariantChangeTypeEx(&v2, &v, 0, 0, VT_BSTR);
1605 ok(hres != S_OK, "CTE VT_ARRAY|VT %d->BSTR succeeded\n", vt);
1606 VariantClear(&v2);
1609 /* Can't change an array of one type into array of another type , even
1610 * if the other type is the same size
1612 if (pSafeArrayCreateVector)
1614 sa = pSafeArrayCreateVector(VT_UI1, 0, 1);
1615 ok(sa != NULL, "CreateVector() failed.\n");
1616 if (!sa)
1617 return;
1619 V_VT(&v) = VT_ARRAY|VT_UI1;
1620 V_ARRAY(&v) = sa;
1621 hres = VariantChangeTypeEx(&v2, &v, 0, 0, VT_ARRAY|VT_I1);
1622 ok(hres == DISP_E_TYPEMISMATCH, "CTE VT_ARRAY|VT_UI1->VT_ARRAY|VT_I1 returned %lx\n", hres);
1624 /* But can change to the same array type */
1625 SafeArrayDestroy(sa);
1626 sa = pSafeArrayCreateVector(VT_UI1, 0, 1);
1627 ok(sa != NULL, "CreateVector() failed.\n");
1628 if (!sa)
1629 return;
1630 V_VT(&v) = VT_ARRAY|VT_UI1;
1631 V_ARRAY(&v) = sa;
1632 hres = VariantChangeTypeEx(&v2, &v, 0, 0, VT_ARRAY|VT_UI1);
1633 ok(hres == S_OK, "CTE VT_ARRAY|VT_UI1->VT_ARRAY|VT_UI1 returned %lx\n", hres);
1636 /* NULL/EMPTY */
1637 MKARRAY(0,1,VT_UI1);
1638 hres = VariantChangeTypeEx(&v2, &v, 0, 0, VT_NULL);
1639 ok(hres == DISP_E_TYPEMISMATCH, "CTE VT_ARRAY|VT_UI1 returned %lx\n", hres);
1640 MKARRAY(0,1,VT_UI1);
1641 hres = VariantChangeTypeEx(&v2, &v, 0, 0, VT_EMPTY);
1642 ok(hres == DISP_E_TYPEMISMATCH, "CTE VT_ARRAY|VT_UI1 returned %lx\n", hres);
1646 static void test_SafeArrayDestroyData (void)
1648 SAFEARRAYBOUND sab;
1649 SAFEARRAY *sa;
1650 HRESULT hres;
1651 int value = 0xdeadbeef;
1652 LONG index[1];
1653 void HUGEP *temp_pvData;
1655 sab.lLbound = 0;
1656 sab.cElements = 10;
1657 sa = SafeArrayCreate(VT_INT, 1, &sab);
1658 ok(sa != NULL, "Create() failed.\n");
1659 if (!sa)
1660 return;
1661 index[0] = 1;
1662 SafeArrayPutElement (sa, index, &value);
1664 /* SafeArrayDestroyData shouldn't free pvData if FADF_STATIC is set. */
1665 sa->fFeatures |= FADF_STATIC;
1666 temp_pvData = sa->pvData;
1667 hres = SafeArrayDestroyData(sa);
1668 ok(hres == S_OK, "SADData FADF_STATIC failed, error code %lx.\n",hres);
1669 ok(sa->pvData == temp_pvData, "SADData FADF_STATIC: pvData=%p, expected %p (fFeatures = %d).\n",
1670 sa->pvData, temp_pvData, sa->fFeatures);
1671 SafeArrayGetElement (sa, index, &value);
1672 ok(value == 0, "Data not cleared after SADData\n");
1674 /* Clear FADF_STATIC, now really destroy the data. */
1675 sa->fFeatures ^= FADF_STATIC;
1676 hres = SafeArrayDestroyData(sa);
1677 ok(hres == S_OK, "SADData !FADF_STATIC failed, error code %lx.\n",hres);
1678 ok(sa->pvData == NULL, "SADData !FADF_STATIC: pvData=%p, expected NULL.\n", sa->pvData);
1680 hres = SafeArrayDestroy(sa);
1681 ok(hres == S_OK, "SAD failed, error code %lx.\n", hres);
1684 START_TEST(safearray)
1686 hOleaut32 = LoadLibraryA("oleaut32.dll");
1688 GETPTR(SafeArrayAllocDescriptorEx);
1689 GETPTR(SafeArrayCopyData);
1690 GETPTR(SafeArrayGetIID);
1691 GETPTR(SafeArraySetIID);
1692 GETPTR(SafeArrayGetVartype);
1693 GETPTR(SafeArrayCreateEx);
1694 GETPTR(SafeArrayCreateVector);
1696 check_for_VT_INT_PTR();
1697 test_safearray();
1698 test_SafeArrayAllocDestroyDescriptor();
1699 test_SafeArrayCreateLockDestroy();
1700 test_VectorCreateLockDestroy();
1701 test_LockUnlock();
1702 test_SafeArrayChangeTypeEx();
1703 test_SafeArrayCopy();
1704 test_SafeArrayClear();
1705 test_SafeArrayCreateEx();
1706 test_SafeArrayCopyData();
1707 test_SafeArrayDestroyData();
1708 test_SafeArrayGetPutElement();
1709 test_SafeArrayGetPutElement_BSTR();
1710 test_SafeArrayGetPutElement_IUnknown();
1711 test_SafeArrayRedim_IUnknown();
1712 test_SafeArrayGetPutElement_VARIANT();