Test that SafeArrayDestroyData keeps the pointer if FADF_STATIC is
[wine/multimedia.git] / dlls / oleaut32 / tests / safearray.c
blob08094f2f34ff3b5555fa88190480c1afe3bfde3b
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 #define COBJMACROS
30 #include "wine/test.h"
31 #include "windef.h"
32 #include "winbase.h"
33 #include "winuser.h"
34 #include "wingdi.h"
35 #include "winnls.h"
36 #include "winsock.h"
37 #include "winerror.h"
38 #include "winnt.h"
40 #include "wtypes.h"
41 #include "oleauto.h"
43 static HMODULE hOleaut32;
45 static HRESULT (WINAPI *pSafeArrayAllocDescriptorEx)(VARTYPE,UINT,SAFEARRAY**);
46 static HRESULT (WINAPI *pSafeArrayCopyData)(SAFEARRAY*,SAFEARRAY*);
47 static HRESULT (WINAPI *pSafeArrayGetIID)(SAFEARRAY*,GUID*);
48 static HRESULT (WINAPI *pSafeArraySetIID)(SAFEARRAY*,REFGUID);
49 static HRESULT (WINAPI *pSafeArrayGetVartype)(SAFEARRAY*,VARTYPE*);
50 static HRESULT (WINAPI *pSafeArrayGetRecordInfo)(SAFEARRAY*,IRecordInfo**);
51 static SAFEARRAY* (WINAPI *pSafeArrayCreateEx)(VARTYPE,UINT,SAFEARRAYBOUND*,LPVOID);
52 static SAFEARRAY* (WINAPI *pSafeArrayCreateVector)(VARTYPE,LONG,ULONG);
54 #define GETPTR(func) p##func = (void*)GetProcAddress(hOleaut32, #func)
56 /* Is a given function exported from oleaut32? */
57 #define HAVE_FUNC(func) ((void*)GetProcAddress(hOleaut32, #func) != NULL)
59 /* Have IRecordInfo data type? */
60 #define HAVE_OLEAUT32_RECORD HAVE_FUNC(SafeArraySetRecordInfo)
61 /* Have I8/UI8 data type? */
62 #define HAVE_OLEAUT32_I8 HAVE_FUNC(VarI8FromI1)
63 /* Have the decimal type? */
64 #define HAVE_OLEAUT32_DECIMAL HAVE_FUNC(VarDecAdd)
65 /* very old version? */
66 #define IS_ANCIENT (!HAVE_FUNC(VarI1FromI2))
68 #define START_REF_COUNT 1
69 #define RECORD_SIZE 64
70 #define RECORD_SIZE_FAIL 17
71 /************************************************************************
72 * Dummy IRecordInfo Implementation
74 typedef struct IRecordInfoImpl
76 IRecordInfoVtbl *lpvtbl;
77 DWORD ref;
78 DWORD sizeCalled;
79 DWORD clearCalled;
80 } IRecordInfoImpl;
82 static IRecordInfoVtbl IRecordInfoImpl_VTable;
84 static IRecordInfoImpl *IRecordInfoImpl_Construct()
86 IRecordInfoImpl *rec;
88 rec = HeapAlloc(GetProcessHeap(), 0, sizeof(IRecordInfoImpl));
89 rec->lpvtbl = &IRecordInfoImpl_VTable;
90 rec->ref = START_REF_COUNT;
91 rec->clearCalled = 0;
92 rec->sizeCalled = 0;
93 return rec;
96 static ULONG CALLBACK IRecordInfoImpl_AddRef(IRecordInfo *iface)
98 IRecordInfoImpl* This=(IRecordInfoImpl*)iface;
99 return ++This->ref;
102 static ULONG CALLBACK IRecordInfoImpl_Release(IRecordInfo *iface)
104 IRecordInfoImpl* This=(IRecordInfoImpl*)iface;
105 return --This->ref;
108 static BOOL fail_GetSize; /* Whether to fail the GetSize call */
110 static HRESULT CALLBACK IRecordInfoImpl_RecordClear(IRecordInfo *iface, PVOID pvExisting)
112 IRecordInfoImpl* This=(IRecordInfoImpl*)iface;
113 This->clearCalled++;
114 return S_OK;
117 static HRESULT CALLBACK IRecordInfoImpl_GetSize(IRecordInfo *iface, ULONG* size)
119 IRecordInfoImpl* This=(IRecordInfoImpl*)iface;
120 This->sizeCalled++;
121 *size = 17;
122 if (fail_GetSize)
123 return E_UNEXPECTED;
124 *size = RECORD_SIZE;
125 return S_OK;
128 static HRESULT CALLBACK IRecordInfoImpl_Dummy(IRecordInfo *iface)
130 trace("Called an unexpected IRecordInfo method - please report!\n");
131 /* Quit because we'll just crash anyway */
132 fflush(NULL);
133 exit(255);
136 static IRecordInfoVtbl IRecordInfoImpl_VTable =
138 (PVOID)IRecordInfoImpl_Dummy,
139 IRecordInfoImpl_AddRef,
140 IRecordInfoImpl_Release,
141 (PVOID)IRecordInfoImpl_Dummy,
142 IRecordInfoImpl_RecordClear,
143 (PVOID)IRecordInfoImpl_Dummy,
144 (PVOID)IRecordInfoImpl_Dummy,
145 (PVOID)IRecordInfoImpl_Dummy,
146 (PVOID)IRecordInfoImpl_GetSize,
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,
156 (PVOID)IRecordInfoImpl_Dummy
159 static DWORD SAFEARRAY_GetVTSize(VARTYPE vt)
161 switch (vt)
163 case VT_I1:
164 case VT_UI1: return sizeof(BYTE);
165 case VT_BOOL:
166 case VT_I2:
167 case VT_UI2: return sizeof(SHORT);
168 case VT_I4:
169 case VT_UI4:
170 case VT_R4:
171 case VT_ERROR: return sizeof(LONG);
172 case VT_R8:
173 case VT_I8:
174 case VT_UI8:
175 if (HAVE_OLEAUT32_I8)
176 return sizeof(LONG64);
177 break;
178 case VT_INT:
179 case VT_UINT: return sizeof(INT);
180 case VT_INT_PTR:
181 case VT_UINT_PTR: return sizeof(UINT_PTR);
182 case VT_CY: return sizeof(CY);
183 case VT_DATE: return sizeof(DATE);
184 case VT_BSTR: return sizeof(BSTR);
185 case VT_DISPATCH: return sizeof(LPDISPATCH);
186 case VT_VARIANT: return sizeof(VARIANT);
187 case VT_UNKNOWN: return sizeof(LPUNKNOWN);
188 case VT_DECIMAL:
189 if (HAVE_OLEAUT32_DECIMAL)
190 return sizeof(DECIMAL);
191 break;
193 return 0;
196 #define VARTYPE_NOT_SUPPORTED 0
197 static struct {
198 VARTYPE vt; /* VT */
199 UINT elemsize; /* elementsize by VT */
200 UINT expflags; /* fFeatures from SafeArrayAllocDescriptorEx */
201 UINT addflags; /* additional fFeatures from SafeArrayCreate */
202 } vttypes[] = {
203 {VT_EMPTY, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
204 {VT_NULL, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
205 {VT_I2, 2, FADF_HAVEVARTYPE,0},
206 {VT_I4, 4, FADF_HAVEVARTYPE,0},
207 {VT_R4, 4, FADF_HAVEVARTYPE,0},
208 {VT_R8, 8, FADF_HAVEVARTYPE,0},
209 {VT_CY, 8, FADF_HAVEVARTYPE,0},
210 {VT_DATE, 8, FADF_HAVEVARTYPE,0},
211 {VT_BSTR, sizeof(BSTR), FADF_HAVEVARTYPE,FADF_BSTR},
212 {VT_DISPATCH, sizeof(LPDISPATCH), FADF_HAVEIID, FADF_DISPATCH},
213 {VT_ERROR, 4, FADF_HAVEVARTYPE,0},
214 {VT_BOOL, 2, FADF_HAVEVARTYPE,0},
215 {VT_VARIANT, sizeof(VARIANT), FADF_HAVEVARTYPE,FADF_VARIANT},
216 {VT_UNKNOWN, sizeof(LPUNKNOWN), FADF_HAVEIID, FADF_UNKNOWN},
217 {VT_DECIMAL, sizeof(DECIMAL), FADF_HAVEVARTYPE,0},
218 {15, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0}, /* no VT_xxx */
219 {VT_I1, 1, FADF_HAVEVARTYPE,0},
220 {VT_UI1, 1, FADF_HAVEVARTYPE,0},
221 {VT_UI2, 2, FADF_HAVEVARTYPE,0},
222 {VT_UI4, 4, FADF_HAVEVARTYPE,0},
223 {VT_I8, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
224 {VT_UI8, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
225 {VT_INT, sizeof(INT), FADF_HAVEVARTYPE,0},
226 {VT_UINT, sizeof(UINT), FADF_HAVEVARTYPE,0},
227 {VT_VOID, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
228 {VT_HRESULT, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
229 {VT_PTR, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
230 {VT_SAFEARRAY,VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
231 {VT_CARRAY, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
232 {VT_USERDEFINED,VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
233 {VT_LPSTR, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
234 {VT_LPWSTR, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
235 {VT_FILETIME, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
236 {VT_RECORD, VARTYPE_NOT_SUPPORTED,FADF_RECORD,0},
237 {VT_BLOB, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
238 {VT_STREAM, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
239 {VT_STORAGE, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
240 {VT_STREAMED_OBJECT,VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
241 {VT_STORED_OBJECT,VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
242 {VT_BLOB_OBJECT,VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
243 {VT_CF, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
244 {VT_CLSID, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
247 static void test_safearray(void)
249 SAFEARRAY *a, b, *c;
250 unsigned int i;
251 long indices[2];
252 HRESULT hres;
253 SAFEARRAYBOUND bound, bounds[2];
254 VARIANT v;
255 LPVOID data;
256 IID iid;
257 VARTYPE vt;
258 LONG l;
259 unsigned char *ptr1, *ptr2;
261 bound.cElements = 1;
262 bound.lLbound = 0;
263 a = SafeArrayCreate(-1, 1, &bound);
264 ok(NULL == a,"SAC(-1,1,[1,0]) not failed?\n");
266 bound.cElements = 0;
267 bound.lLbound = 42;
268 a = SafeArrayCreate(VT_I4, 1, &bound);
269 ok(NULL != a,"SAC(VT_I4,1,[0,0]) failed.\n");
271 hres = SafeArrayGetLBound(a, 1, &l);
272 ok(hres == S_OK, "SAGLB of 0 size dimensioned array failed with %lx\n",hres);
273 ok(l == 42, "SAGLB of 0 size dimensioned array failed to return 42, but returned %ld\n",l);
274 hres = SafeArrayGetUBound(a, 1, &l);
275 ok(hres == S_OK, "SAGUB of 0 size dimensioned array failed with %lx\n",hres);
276 ok(l == 41, "SAGUB of 0 size dimensioned array failed to return 41, but returned %ld\n",l);
278 hres = SafeArrayAccessData(a, &data);
279 ok(hres == S_OK, "SafeArrayAccessData of 0 size dimensioned array failed with %lx\n", hres);
280 SafeArrayUnaccessData(a);
282 bound.cElements = 2;
283 hres = SafeArrayRedim(a, &bound);
284 ok(hres == S_OK,"SAR of a 0 elements dimension failed with hres %lx\n", hres);
285 bound.cElements = 0;
286 hres = SafeArrayRedim(a, &bound);
287 ok(hres == S_OK || hres == E_OUTOFMEMORY,
288 "SAR to a 0 elements dimension failed with hres %lx\n", hres);
289 hres = SafeArrayDestroy(a);
290 ok(hres == S_OK,"SAD of 0 dim array faild with hres %lx\n", hres);
292 bounds[0].cElements = 0; bounds[0].lLbound = 1;
293 bounds[1].cElements = 2; bounds[1].lLbound = 23;
294 a = SafeArrayCreate(VT_I4,2,bounds);
295 ok(a != NULL,"SAC(VT_INT32,2,...) with 0 element dim failed.\n");
296 bounds[0].cElements = 1; bounds[0].lLbound = 1;
297 bounds[1].cElements = 0; bounds[1].lLbound = 23;
298 a = SafeArrayCreate(VT_I4,2,bounds);
299 ok(a != NULL,"SAC(VT_INT32,2,...) with 0 element dim failed.\n");
301 bounds[0].cElements = 42; bounds[0].lLbound = 1;
302 bounds[1].cElements = 2; bounds[1].lLbound = 23;
303 a = SafeArrayCreate(VT_I4,2,bounds);
304 ok(a != NULL,"SAC(VT_INT32,2,...) failed.\n");
306 hres = SafeArrayGetLBound (a, 0, &l);
307 ok (hres == DISP_E_BADINDEX, "SAGLB 0 failed with %lx\n", hres);
308 hres = SafeArrayGetLBound (a, 1, &l);
309 ok (hres == S_OK, "SAGLB 1 failed with %lx\n", hres);
310 ok (l == 1, "SAGLB 1 returned %ld instead of 1\n", l);
311 hres = SafeArrayGetLBound (a, 2, &l);
312 ok (hres == S_OK, "SAGLB 2 failed with %lx\n", hres);
313 ok (l == 23, "SAGLB 2 returned %ld instead of 23\n", l);
314 hres = SafeArrayGetLBound (a, 3, &l);
315 ok (hres == DISP_E_BADINDEX, "SAGLB 3 failed with %lx\n", hres);
317 hres = SafeArrayGetUBound (a, 0, &l);
318 ok (hres == DISP_E_BADINDEX, "SAGUB 0 failed with %lx\n", hres);
319 hres = SafeArrayGetUBound (a, 1, &l);
320 ok (hres == S_OK, "SAGUB 1 failed with %lx\n", hres);
321 ok (l == 42, "SAGUB 1 returned %ld instead of 42\n", l);
322 hres = SafeArrayGetUBound (a, 2, &l);
323 ok (hres == S_OK, "SAGUB 2 failed with %lx\n", hres);
324 ok (l == 24, "SAGUB 2 returned %ld instead of 24\n", l);
325 hres = SafeArrayGetUBound (a, 3, &l);
326 ok (hres == DISP_E_BADINDEX, "SAGUB 3 failed with %lx\n", hres);
328 i = SafeArrayGetDim(a);
329 ok(i == 2, "getdims of 2 din array returned %d\n",i);
331 indices[0] = 0;
332 indices[1] = 23;
333 hres = SafeArrayGetElement(a, indices, &i);
334 ok(DISP_E_BADINDEX == hres,"SAGE failed [0,23], hres 0x%lx\n",hres);
336 indices[0] = 1;
337 indices[1] = 22;
338 hres = SafeArrayGetElement(a, indices, &i);
339 ok(DISP_E_BADINDEX == hres,"SAGE failed [1,22], hres 0x%lx\n",hres);
341 indices[0] = 1;
342 indices[1] = 23;
343 hres = SafeArrayGetElement(a, indices, &i);
344 ok(S_OK == hres,"SAGE failed [1,23], hres 0x%lx\n",hres);
346 indices[0] = 1;
347 indices[1] = 25;
348 hres = SafeArrayGetElement(a, indices, &i);
349 ok(DISP_E_BADINDEX == hres,"SAGE failed [1,24], hres 0x%lx\n",hres);
351 indices[0] = 3;
352 indices[1] = 23;
353 hres = SafeArrayGetElement(a, indices, &i);
354 ok(S_OK == hres,"SAGE failed [42,23], hres 0x%lx\n",hres);
356 hres = SafeArrayAccessData(a, (void**)&ptr1);
357 ok(S_OK == hres, "SAAD failed with 0x%lx\n", hres);
359 indices[0] = 3;
360 indices[1] = 23;
361 hres = SafeArrayPtrOfIndex(a, indices, (void**)&ptr2);
362 ok(S_OK == hres,"SAPOI failed [1,23], hres 0x%lx\n",hres);
363 ok(ptr2 - ptr1 == 8,"ptr difference is not 8, but %d (%p vs %p)\n", ptr2-ptr1, ptr2, ptr1);
365 indices[0] = 3;
366 indices[1] = 24;
367 hres = SafeArrayPtrOfIndex(a, indices, (void**)&ptr2);
368 ok(S_OK == hres,"SAPOI failed [5,24], hres 0x%lx\n",hres);
369 ok(ptr2 - ptr1 == 176,"ptr difference is not 176, but %d (%p vs %p)\n", ptr2-ptr1, ptr2, ptr1);
371 indices[0] = 20;
372 indices[1] = 23;
373 hres = SafeArrayPtrOfIndex(a, indices, (void**)&ptr2);
374 ok(S_OK == hres,"SAPOI failed [20,23], hres 0x%lx\n",hres);
375 ok(ptr2 - ptr1 == 76,"ptr difference is not 76, but %d (%p vs %p)\n", ptr2-ptr1, ptr2, ptr1);
377 hres = SafeArrayUnaccessData(a);
378 ok(S_OK == hres, "SAUAD failed with 0x%lx\n", hres);
380 for (i=0;i<sizeof(vttypes)/sizeof(vttypes[0]);i++) {
381 if ((i == VT_I8 || i == VT_UI8) && HAVE_OLEAUT32_I8)
383 vttypes[i].elemsize = sizeof(LONG64);
386 a = SafeArrayCreate(vttypes[i].vt, 1, &bound);
388 ok((!a && !vttypes[i].elemsize) ||
389 (a && vttypes[i].elemsize == a->cbElements) ||
390 (IS_ANCIENT && (vttypes[i].vt == VT_DECIMAL || vttypes[i].vt == VT_I1 ||
391 vttypes[i].vt == VT_UI2 || vttypes[i].vt == VT_UI4 || vttypes[i].vt == VT_INT ||
392 vttypes[i].vt == VT_UINT)),
393 "SAC(%d,1,[1,0]), %p result %ld, expected %d\n",
394 vttypes[i].vt,a,(a?a->cbElements:0),vttypes[i].elemsize);
396 if (a)
398 if (!HAVE_OLEAUT32_RECORD)
399 vttypes[i].expflags = 0;
400 ok(a->fFeatures == (vttypes[i].expflags | vttypes[i].addflags),
401 "SAC of %d returned feature flags %x, expected %x\n",
402 vttypes[i].vt, a->fFeatures,
403 vttypes[i].expflags|vttypes[i].addflags);
404 ok(SafeArrayGetElemsize(a) == vttypes[i].elemsize,
405 "SAGE for vt %d returned elemsize %d instead of expected %d\n",
406 vttypes[i].vt, SafeArrayGetElemsize(a),vttypes[i].elemsize);
409 if (!a) continue;
411 if (pSafeArrayGetVartype)
413 hres = pSafeArrayGetVartype(a, &vt);
414 ok(hres == S_OK, "SAGVT of arra y with vt %d failed with %lx\n", vttypes[i].vt, hres);
415 if (vttypes[i].vt == VT_DISPATCH) {
416 /* Special case. Checked against Windows. */
417 ok(vt == VT_UNKNOWN, "SAGVT of a rray with VT_DISPATCH returned not VT_UNKNOWN, but %d\n", vt);
418 } else {
419 ok(vt == vttypes[i].vt, "SAGVT of array with vt %d returned %d\n", vttypes[i].vt, vt);
423 hres = SafeArrayCopy(a, &c);
424 ok(hres == S_OK, "failed to copy safearray of vt %d with hres %lx\n", vttypes[i].vt, hres);
426 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
428 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);
429 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);
431 if (pSafeArrayGetVartype) {
432 hres = pSafeArrayGetVartype(c, &vt);
433 ok(hres == S_OK, "SAGVT of array with vt %d failed with %lx\n", vttypes[i].vt, hres);
434 if (vttypes[i].vt == VT_DISPATCH) {
435 /* Special case. Checked against Windows. */
436 ok(vt == VT_UNKNOWN, "SAGVT of array with VT_DISPATCH returned not VT_UNKNOWN, but %d\n", vt);
437 } else {
438 ok(vt == vttypes[i].vt, "SAGVT of array with vt %d returned %d\n", vttypes[i].vt, vt);
442 if (pSafeArrayCopyData) {
443 hres = pSafeArrayCopyData(a, c);
444 ok(hres == S_OK, "failed to copy safearray data of vt %d with hres %lx\n", vttypes[i].vt, hres);
446 hres = SafeArrayDestroyData(c);
447 ok(hres == S_OK,"SADD of copy of array with vt %d failed with hres %lx\n", vttypes[i].vt, hres);
450 hres = SafeArrayDestroy(a);
451 ok(hres == S_OK,"SAD of array with vt %d failed with hres %lx\n", vttypes[i].vt, hres);
454 /* Test conversion of type|VT_ARRAY <-> VT_BSTR */
455 bound.lLbound = 0;
456 bound.cElements = 10;
457 a = SafeArrayCreate(VT_UI1, 1, &bound);
458 ok(a != NULL, "SAC failed.\n");
459 ok(S_OK == SafeArrayAccessData(a, &data),"SACD failed\n");
460 memcpy(data,"Hello World\n",10);
461 ok(S_OK == SafeArrayUnaccessData(a),"SAUD failed\n");
462 V_VT(&v) = VT_ARRAY|VT_UI1;
463 V_ARRAY(&v) = a;
464 hres = VariantChangeTypeEx(&v, &v, 0, 0, VT_BSTR);
465 ok(hres==S_OK, "CTE VT_ARRAY|VT_UI1 -> VT_BSTR failed with %lx\n",hres);
466 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));
467 ok(V_BSTR(&v)[0] == 0x6548,"First letter are not 'He', but %x\n", V_BSTR(&v)[0]);
469 /* check locking functions */
470 a = SafeArrayCreate(VT_I4, 1, &bound);
471 ok(a!=NULL,"SAC should not fail\n");
473 hres = SafeArrayAccessData(a, &data);
474 ok(hres == S_OK,"SAAD failed with hres %lx\n",hres);
476 hres = SafeArrayDestroy(a);
477 ok(hres == DISP_E_ARRAYISLOCKED,"locked safe array destroy not failed with DISP_E_ARRAYISLOCKED, but with hres %lx\n", hres);
479 hres = SafeArrayDestroyData(a);
480 ok(hres == DISP_E_ARRAYISLOCKED,"locked safe array destroy data not failed with DISP_E_ARRAYISLOCKED, but with hres %lx\n", hres);
482 hres = SafeArrayDestroyDescriptor(a);
483 ok(hres == DISP_E_ARRAYISLOCKED,"locked safe array destroy descriptor not failed with DISP_E_ARRAYISLOCKED, but with hres %lx\n", hres);
485 hres = SafeArrayUnaccessData(a);
486 ok(hres == S_OK,"SAUD failed after lock/destroy test\n");
488 hres = SafeArrayDestroy(a);
489 ok(hres == S_OK,"SAD failed after lock/destroy test\n");
491 /* Test if we need to destroy data before descriptor */
492 a = SafeArrayCreate(VT_I4, 1, &bound);
493 ok(a!=NULL,"SAC should not fail\n");
494 hres = SafeArrayDestroyDescriptor(a);
495 ok(hres == S_OK,"SADD with data in array failed with hres %lx\n",hres);
498 /* IID functions */
499 /* init a small stack safearray */
500 if (pSafeArraySetIID) {
501 memset(&b, 0, sizeof(b));
502 b.cDims = 1;
503 memset(&iid, 0x42, sizeof(IID));
504 hres = pSafeArraySetIID(&b,&iid);
505 ok(hres == E_INVALIDARG,"SafeArraySetIID of non IID capable safearray did not return E_INVALIDARG, but %lx\n",hres);
507 hres = SafeArrayAllocDescriptor(1,&a);
508 ok((a->fFeatures & FADF_HAVEIID) == 0,"newly allocated descriptor with SAAD should not have FADF_HAVEIID\n");
509 hres = pSafeArraySetIID(a,&iid);
510 ok(hres == E_INVALIDARG,"SafeArraySetIID of newly allocated descriptor with SAAD should return E_INVALIDARG, but %lx\n",hres);
513 if (!pSafeArrayAllocDescriptorEx)
514 return;
516 for (i=0;i<sizeof(vttypes)/sizeof(vttypes[0]);i++) {
517 a = NULL;
518 hres = pSafeArrayAllocDescriptorEx(vttypes[i].vt,1,&a);
519 ok(a->fFeatures == vttypes[i].expflags,"SAADE(%d) resulted with flags %x, expected %x\n", vttypes[i].vt, a->fFeatures, vttypes[i].expflags);
520 if (a->fFeatures & FADF_HAVEIID) {
521 hres = pSafeArrayGetIID(a, &iid);
522 ok(hres == S_OK,"SAGIID failed for vt %d with hres %lx\n", vttypes[i].vt,hres);
523 switch (vttypes[i].vt) {
524 case VT_UNKNOWN:
525 ok(IsEqualGUID(((GUID*)a)-1,&IID_IUnknown),"guid for VT_UNKNOWN is not IID_IUnknown\n");
526 ok(IsEqualGUID(&iid, &IID_IUnknown),"SAGIID returned wrong GUID for IUnknown\n");
527 break;
528 case VT_DISPATCH:
529 ok(IsEqualGUID(((GUID*)a)-1,&IID_IDispatch),"guid for VT_UNKNOWN is not IID_IDispatch\n");
530 ok(IsEqualGUID(&iid, &IID_IDispatch),"SAGIID returned wrong GUID for IDispatch\n");
531 break;
532 default:
533 ok(FALSE,"unknown vt %d with FADF_HAVEIID\n",vttypes[i].vt);
534 break;
536 } else {
537 hres = pSafeArrayGetIID(a, &iid);
538 ok(hres == E_INVALIDARG,"SAGIID did not fail for vt %d with hres %lx\n", vttypes[i].vt,hres);
540 if (a->fFeatures & FADF_RECORD) {
541 ok(vttypes[i].vt == VT_RECORD,"FADF_RECORD for non record %d\n",vttypes[i].vt);
543 if (a->fFeatures & FADF_HAVEVARTYPE) {
544 ok(vttypes[i].vt == ((DWORD*)a)[-1], "FADF_HAVEVARTYPE set, but vt %d mismatch stored %ld\n",vttypes[i].vt,((DWORD*)a)[-1]);
547 hres = pSafeArrayGetVartype(a, &vt);
548 ok(hres == S_OK, "SAGVT of array with vt %d failed with %lx\n", vttypes[i].vt, hres);
550 if (vttypes[i].vt == VT_DISPATCH) {
551 /* Special case. Checked against Windows. */
552 ok(vt == VT_UNKNOWN, "SAGVT of array with VT_DISPATCH returned not VT_UNKNOWN, but %d\n", vt);
553 } else {
554 ok(vt == vttypes[i].vt, "SAGVT of array with vt %d returned %d\n", vttypes[i].vt, vt);
557 if (a->fFeatures & FADF_HAVEIID) {
558 hres = pSafeArraySetIID(a, &IID_IStorage); /* random IID */
559 ok(hres == S_OK,"SASIID failed with FADF_HAVEIID set for vt %d with %lx\n", vttypes[i].vt, hres);
560 hres = pSafeArrayGetIID(a, &iid);
561 ok(hres == S_OK,"SAGIID failed with FADF_HAVEIID set for vt %d with %lx\n", vttypes[i].vt, hres);
562 ok(IsEqualGUID(&iid, &IID_IStorage),"returned iid is not IID_IStorage\n");
563 } else {
564 hres = pSafeArraySetIID(a, &IID_IStorage); /* random IID */
565 ok(hres == E_INVALIDARG,"SASIID did not failed with !FADF_HAVEIID set for vt %d with %lx\n", vttypes[i].vt, hres);
567 hres = SafeArrayDestroyDescriptor(a);
568 ok(hres == S_OK,"SADD failed with hres %lx\n",hres);
572 static void test_SafeArrayAllocDestroyDescriptor(void)
574 SAFEARRAY *sa;
575 HRESULT hres;
576 int i;
578 /* Failure cases */
579 hres = SafeArrayAllocDescriptor(0, &sa);
580 ok(hres == E_INVALIDARG, "0 dimensions gave hres 0x%lx\n", hres);
582 hres = SafeArrayAllocDescriptor(65536, &sa);
583 ok(IS_ANCIENT || hres == E_INVALIDARG,
584 "65536 dimensions gave hres 0x%lx\n", hres);
586 #if 0
587 /* Crashes on 95: XP & Wine return E_POINTER */
588 hres=SafeArrayAllocDescriptor(1, NULL);
589 ok(hres == E_POINTER,"NULL parm gave hres 0x%lx\n", hres);
590 #endif
592 /* Test up to the dimension boundary case */
593 for (i = 5; i <= 65535; i += 30)
595 hres = SafeArrayAllocDescriptor(i, &sa);
596 ok(hres == S_OK, "%d dimensions failed; hres 0x%lx\n", i, hres);
598 if (hres == S_OK)
600 ok(SafeArrayGetDim(sa) == (UINT)i, "Dimension is %d; should be %d\n",
601 SafeArrayGetDim(sa), i);
603 hres = SafeArrayDestroyDescriptor(sa);
604 ok(hres == S_OK, "destroy failed; hres 0x%lx\n", hres);
608 if (!pSafeArrayAllocDescriptorEx)
609 return;
611 hres = pSafeArrayAllocDescriptorEx(VT_UI1, 0, &sa);
612 ok(hres == E_INVALIDARG, "0 dimensions gave hres 0x%lx\n", hres);
614 hres = pSafeArrayAllocDescriptorEx(VT_UI1, 65536, &sa);
615 ok(hres == E_INVALIDARG, "65536 dimensions gave hres 0x%lx\n", hres);
617 hres = pSafeArrayAllocDescriptorEx(VT_UI1, 1, NULL);
618 ok(hres == E_POINTER,"NULL parm gave hres 0x%lx\n", hres);
620 hres = pSafeArrayAllocDescriptorEx(-1, 1, &sa);
621 ok(hres == S_OK, "VT = -1 gave hres 0x%lx\n", hres);
623 sa->rgsabound[0].cElements = 0;
624 sa->rgsabound[0].lLbound = 1;
626 hres = SafeArrayAllocData(sa);
627 todo_wine
629 ok(hres == S_OK, "SafeArrayAllocData gave hres 0x%lx\n", hres);
633 static void test_SafeArrayCreateLockDestroy(void)
635 SAFEARRAYBOUND sab[4];
636 SAFEARRAY *sa;
637 HRESULT hres;
638 VARTYPE vt;
639 int dimension;
641 #define NUM_DIMENSIONS (int)(sizeof(sab) / sizeof(sab[0]))
643 for (dimension = 0; dimension < NUM_DIMENSIONS; dimension++)
645 sab[dimension].lLbound = 0;
646 sab[dimension].cElements = 8;
649 /* Failure cases */
650 /* This test crashes very early versions with no error checking...
651 sa = SafeArrayCreate(VT_UI1, 1, NULL);
652 ok(sa == NULL, "NULL bounds didn't fail\n");
654 sa = SafeArrayCreate(VT_UI1, 65536, sab);
655 ok(IS_ANCIENT || !sa, "Max bounds didn't fail\n");
657 memset(sab, 0, sizeof(sab));
659 /* Don't test 0 sized dimensions, as Windows has a bug which allows this */
661 for (dimension = 0; dimension < NUM_DIMENSIONS; dimension++)
662 sab[dimension].cElements = 8;
664 /* Test all VARTYPES in 1-4 dimensions */
665 for (dimension = 1; dimension < 4; dimension++)
667 for (vt = VT_EMPTY; vt < VT_CLSID; vt++)
669 DWORD dwLen = SAFEARRAY_GetVTSize(vt);
671 sa = SafeArrayCreate(vt, dimension, sab);
673 if (dwLen)
674 ok(sa || (IS_ANCIENT && (vt == VT_DECIMAL || vt == VT_I1 || vt == VT_UI2 ||
675 vt == VT_UI4 || vt == VT_INT || vt == VT_UINT || vt == VT_UINT_PTR ||
676 vt == VT_INT_PTR)),
677 "VARTYPE %d (@%d dimensions) failed\n", vt, dimension);
678 else
679 ok(sa == NULL || vt == VT_R8,
680 "VARTYPE %d (@%d dimensions) succeeded!\n", vt, dimension);
682 if (sa)
684 ok(SafeArrayGetDim(sa) == (UINT)dimension,
685 "VARTYPE %d (@%d dimensions) cDims is %d, expected %d\n",
686 vt, dimension, SafeArrayGetDim(sa), dimension);
687 ok(SafeArrayGetElemsize(sa) == dwLen || vt == VT_R8,
688 "VARTYPE %d (@%d dimensions) cbElements is %d, expected %ld\n",
689 vt, dimension, SafeArrayGetElemsize(sa), dwLen);
691 if (vt != VT_UNKNOWN && vt != VT_DISPATCH)
693 ok((sa->fFeatures & FADF_HAVEIID) == 0,
694 "Non interface type should not have FADF_HAVEIID\n");
695 if (pSafeArraySetIID)
697 hres = pSafeArraySetIID(sa, &IID_IUnknown);
698 ok(hres == E_INVALIDARG,
699 "Non interface type allowed SetIID(), hres %lx\n", hres);
701 if (vt != VT_RECORD)
703 VARTYPE aVt;
705 ok(IS_ANCIENT || sa->fFeatures & FADF_HAVEVARTYPE,
706 "Non interface type should have FADF_HAVEVARTYPE\n");
707 if (pSafeArrayGetVartype)
709 hres = pSafeArrayGetVartype(sa, &aVt);
710 ok(hres == S_OK && aVt == vt,
711 "Non interface type %d: bad type %d, hres %lx\n", vt, aVt, hres);
715 else
717 ok(IS_ANCIENT || sa->fFeatures & FADF_HAVEIID,
718 "Interface type should have FADF_HAVEIID\n");
719 if (pSafeArraySetIID)
721 hres = pSafeArraySetIID(sa, &IID_IUnknown);
722 ok(hres == S_OK,
723 "Non interface type disallowed SetIID(), hres %lx\n", hres);
725 ok((sa->fFeatures & FADF_HAVEVARTYPE) == 0,
726 "Interface type %d should not have FADF_HAVEVARTYPE\n", vt);
729 hres = SafeArrayLock(sa);
730 ok(hres == S_OK, "Lock VARTYPE %d (@%d dimensions) failed; hres 0x%lx\n",
731 vt, dimension, hres);
733 if (hres == S_OK)
735 hres = SafeArrayDestroy(sa);
736 ok(hres == DISP_E_ARRAYISLOCKED,"Destroy() got hres %lx\n", hres);
738 hres = SafeArrayDestroyData(sa);
739 ok(hres == DISP_E_ARRAYISLOCKED,"DestroyData() got hres %lx\n", hres);
741 hres = SafeArrayDestroyDescriptor(sa);
742 ok(hres == DISP_E_ARRAYISLOCKED,"DestroyDescriptor() got hres %lx\n", hres);
744 hres = SafeArrayUnlock(sa);
745 ok(hres == S_OK, "Unlock VARTYPE %d (@%d dims) hres 0x%lx\n",
746 vt, dimension, hres);
748 hres = SafeArrayDestroyDescriptor(sa);
749 ok(hres == S_OK, "destroy VARTYPE %d (@%d dims) hres 0x%lx\n",
750 vt, dimension, hres);
757 static void test_VectorCreateLockDestroy(void)
759 SAFEARRAY *sa;
760 HRESULT hres;
761 VARTYPE vt;
762 int element;
764 if (!pSafeArrayCreateVector)
765 return;
766 sa = pSafeArrayCreateVector(VT_UI1, 0, 0);
767 ok(sa != NULL, "SACV with 0 elements failed.\n");
769 /* Test all VARTYPES in different lengths */
770 for (element = 1; element <= 101; element += 10)
772 for (vt = VT_EMPTY; vt < VT_CLSID; vt++)
774 DWORD dwLen = SAFEARRAY_GetVTSize(vt);
776 sa = pSafeArrayCreateVector(vt, 0, element);
778 if (dwLen)
780 /* win2000 has a bug where U/INT_PTR aren't accepted */
781 ok(sa != NULL || vt == VT_INT_PTR || vt == VT_UINT_PTR,
782 "VARTYPE %d (@%d elements) failed\n", vt, element);
784 else
785 ok(sa == NULL, "VARTYPE %d (@%d elements) succeeded!\n", vt, element);
787 if (sa)
789 ok(SafeArrayGetDim(sa) == 1, "VARTYPE %d (@%d elements) cDims %d, not 1\n",
790 vt, element, SafeArrayGetDim(sa));
791 ok(SafeArrayGetElemsize(sa) == dwLen,
792 "VARTYPE %d (@%d elements) cbElements is %d, expected %ld\n",
793 vt, element, SafeArrayGetElemsize(sa), dwLen);
795 hres = SafeArrayLock(sa);
796 ok(hres == S_OK, "Lock VARTYPE %d (@%d elements) failed; hres 0x%lx\n",
797 vt, element, hres);
799 if (hres == S_OK)
801 hres = SafeArrayUnlock(sa);
802 ok(hres == S_OK, "Unlock VARTYPE %d (@%d elements) failed; hres 0x%lx\n",
803 vt, element, hres);
805 hres = SafeArrayDestroyDescriptor(sa);
806 ok(hres == S_OK, "destroy VARTYPE %d (@%d elements) failed; hres 0x%lx\n",
807 vt, element, hres);
814 static void test_LockUnlock(void)
816 SAFEARRAYBOUND sab[4];
817 SAFEARRAY *sa;
818 HRESULT hres;
819 BOOL bVector = FALSE;
820 int dimension;
822 /* Failure cases */
823 hres = SafeArrayLock(NULL);
824 ok(hres == E_INVALIDARG, "Lock NULL array hres 0x%lx\n", hres);
825 hres = SafeArrayUnlock(NULL);
826 ok(hres == E_INVALIDARG, "Lock NULL array hres 0x%lx\n", hres);
828 for (dimension = 0; dimension < NUM_DIMENSIONS; dimension++)
830 sab[dimension].lLbound = 0;
831 sab[dimension].cElements = 8;
834 sa = SafeArrayCreate(VT_UI1, NUM_DIMENSIONS, sab);
836 /* Test maximum locks */
837 test_LockUnlock_Vector:
838 if (sa)
840 int count = 0;
842 hres = SafeArrayUnlock(sa);
843 ok (hres == E_UNEXPECTED, "Bad %sUnlock gave hres 0x%lx\n",
844 bVector ? "vector " : "\n", hres);
846 while ((hres = SafeArrayLock(sa)) == S_OK)
847 count++;
848 ok (count == 65535 && hres == E_UNEXPECTED, "Lock %sfailed at %d; hres 0x%lx\n",
849 bVector ? "vector " : "\n", count, hres);
851 if (count == 65535 && hres == E_UNEXPECTED)
853 while ((hres = SafeArrayUnlock(sa)) == S_OK)
854 count--;
855 ok (count == 0 && hres == E_UNEXPECTED, "Unlock %sfailed at %d; hres 0x%lx\n",
856 bVector ? "vector " : "\n", count, hres);
859 SafeArrayDestroy(sa);
862 if (bVector == FALSE && pSafeArrayCreateVector)
864 /* Test again with a vector */
865 sa = pSafeArrayCreateVector(VT_UI1, 0, 100);
866 bVector = TRUE;
867 goto test_LockUnlock_Vector;
871 static void test_SafeArrayGetPutElement(void)
873 SAFEARRAYBOUND sab[4];
874 LONG indices[NUM_DIMENSIONS];
875 SAFEARRAY *sa;
876 HRESULT hres;
877 int value = 0, gotvalue, dimension;
878 unsigned int x,y,z,a;
880 for (dimension = 0; dimension < NUM_DIMENSIONS; dimension++)
882 sab[dimension].lLbound = dimension * 2 + 1;
883 sab[dimension].cElements = dimension * 3 + 1;
886 sa = SafeArrayCreate(VT_INT, NUM_DIMENSIONS, sab);
887 if (!sa)
888 return; /* Some early versions can't handle > 3 dims */
890 ok(sa->cbElements == sizeof(value), "int size mismatch\n");
891 if (sa->cbElements != sizeof(value))
892 return;
894 /* Failure cases */
895 for (x = 0; x < NUM_DIMENSIONS; 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 indices[x] = indices[x] - 1;
903 hres = SafeArrayPutElement(sa, indices, &value);
904 ok(hres == DISP_E_BADINDEX, "Put allowed too small index in dimension %d\n", x);
905 hres = SafeArrayGetElement(sa, indices, &value);
906 ok(hres == DISP_E_BADINDEX, "Get allowed too small index in dimension %d\n", x);
908 indices[x] = sab[x].lLbound + sab[x].cElements;
909 hres = SafeArrayPutElement(sa, indices, &value);
910 ok(hres == DISP_E_BADINDEX, "Put allowed too big index in dimension %d\n", x);
911 hres = SafeArrayGetElement(sa, indices, &value);
912 ok(hres == DISP_E_BADINDEX, "Get allowed too big index in dimension %d\n", x);
915 indices[0] = sab[0].lLbound;
916 indices[1] = sab[1].lLbound;
917 indices[2] = sab[2].lLbound;
918 indices[3] = sab[3].lLbound;
920 hres = SafeArrayPutElement(NULL, indices, &value);
921 ok(hres == E_INVALIDARG, "Put NULL array hres 0x%lx\n", hres);
922 hres = SafeArrayGetElement(NULL, indices, &value);
923 ok(hres == E_INVALIDARG, "Get NULL array hres 0x%lx\n", hres);
925 hres = SafeArrayPutElement(sa, NULL, &value);
926 ok(hres == E_INVALIDARG, "Put NULL indices hres 0x%lx\n", hres);
927 hres = SafeArrayGetElement(sa, NULL, &value);
928 ok(hres == E_INVALIDARG, "Get NULL indices hres 0x%lx\n", hres);
930 #if 0
931 /* This is retarded. Windows checks every case of invalid parameters
932 * except the following, which crashes. We ERR this in Wine.
934 hres = SafeArrayPutElement(sa, indices, NULL);
935 ok(hres == E_INVALIDARG, "Put NULL value hres 0x%lx\n", hres);
936 #endif
938 hres = SafeArrayGetElement(sa, indices, NULL);
939 ok(hres == E_INVALIDARG, "Get NULL value hres 0x%lx\n", hres);
941 value = 0;
943 /* Make sure we can read and get back the correct values in 4 dimensions,
944 * Each with a different size and lower bound.
946 for (x = 0; x < sab[0].cElements; x++)
948 indices[0] = sab[0].lLbound + x;
949 for (y = 0; y < sab[1].cElements; y++)
951 indices[1] = sab[1].lLbound + y;
952 for (z = 0; z < sab[2].cElements; z++)
954 indices[2] = sab[2].lLbound + z;
955 for (a = 0; a < sab[3].cElements; a++)
957 indices[3] = sab[3].lLbound + a;
958 hres = SafeArrayPutElement(sa, indices, &value);
959 ok(hres == S_OK, "Failed to put element at (%d,%d,%d,%d) hres 0x%lx\n",
960 x, y, z, a, hres);
961 value++;
967 value = 0;
969 for (x = 0; x < sab[0].cElements; x++)
971 indices[0] = sab[0].lLbound + x;
972 for (y = 0; y < sab[1].cElements; y++)
974 indices[1] = sab[1].lLbound + y;
975 for (z = 0; z < sab[2].cElements; z++)
977 indices[2] = sab[2].lLbound + z;
978 for (a = 0; a < sab[3].cElements; a++)
980 indices[3] = sab[3].lLbound + a;
981 gotvalue = value / 3;
982 hres = SafeArrayGetElement(sa, indices, &gotvalue);
983 ok(hres == S_OK, "Failed to get element at (%d,%d,%d,%d) hres 0x%lx\n",
984 x, y, z, a, hres);
985 if (hres == S_OK)
986 ok(value == gotvalue, "Got value %d instead of %d at (%d,%d,%d,%d)\n",
987 gotvalue, value, x, y, z, a);
988 value++;
993 SafeArrayDestroy(sa);
996 static void test_SafeArrayGetPutElement_BSTR(void)
998 SAFEARRAYBOUND sab;
999 LONG indices[1];
1000 SAFEARRAY *sa;
1001 HRESULT hres;
1002 BSTR value = 0, gotvalue;
1003 const OLECHAR szTest[5] = { 'T','e','s','t','\0' };
1005 sab.lLbound = 1;
1006 sab.cElements = 1;
1008 sa = SafeArrayCreate(VT_BSTR, 1, &sab);
1009 ok(sa != NULL, "BSTR test couldn't create array\n");
1010 if (!sa)
1011 return;
1013 ok(sa->cbElements == sizeof(BSTR), "BSTR size mismatch\n");
1014 if (sa->cbElements != sizeof(BSTR))
1015 return;
1017 indices[0] = sab.lLbound;
1018 value = SysAllocString(szTest);
1019 ok (value != NULL, "Expected non-NULL\n");
1020 hres = SafeArrayPutElement(sa, indices, value);
1021 ok(hres == S_OK, "Failed to put bstr element hres 0x%lx\n", hres);
1022 gotvalue = NULL;
1023 hres = SafeArrayGetElement(sa, indices, &gotvalue);
1024 ok(hres == S_OK, "Failed to get bstr element at hres 0x%lx\n", hres);
1025 if (hres == S_OK)
1026 ok(SysStringLen(value) == SysStringLen(gotvalue), "Got len %d instead of %d\n", SysStringLen(gotvalue), SysStringLen(value));
1027 SafeArrayDestroy(sa);
1030 static int tunk_xref = 0;
1031 static HRESULT WINAPI tunk_QueryInterface(LPUNKNOWN punk,REFIID riid, LPVOID *x) {
1032 return E_FAIL;
1034 static ULONG WINAPI tunk_AddRef(LPUNKNOWN punk) {
1035 return ++tunk_xref;
1038 static ULONG WINAPI tunk_Release(LPUNKNOWN punk) {
1039 return --tunk_xref;
1042 static IUnknownVtbl xtunk_vtbl = {
1043 tunk_QueryInterface,
1044 tunk_AddRef,
1045 tunk_Release
1048 static struct xtunk_iface {
1049 IUnknownVtbl *lpvtbl;
1050 } xtunk_iface;
1053 static void test_SafeArrayGetPutElement_IUnknown(void)
1055 SAFEARRAYBOUND sab;
1056 LONG indices[1];
1057 SAFEARRAY *sa;
1058 HRESULT hres;
1059 LPUNKNOWN value = 0, gotvalue;
1061 sab.lLbound = 1;
1062 sab.cElements = 1;
1063 sa = SafeArrayCreate(VT_UNKNOWN, 1, &sab);
1064 ok(sa != NULL, "UNKNOWN test couldn't create array\n");
1065 if (!sa)
1066 return;
1068 ok(sa->cbElements == sizeof(LPUNKNOWN), "LPUNKNOWN size mismatch\n");
1069 if (sa->cbElements != sizeof(LPUNKNOWN))
1070 return;
1072 indices[0] = sab.lLbound;
1073 xtunk_iface.lpvtbl = &xtunk_vtbl;
1074 value = (LPUNKNOWN)&xtunk_iface;
1075 tunk_xref = 1;
1076 ok (value != NULL, "Expected non-NULL\n");
1077 hres = SafeArrayPutElement(sa, indices, value);
1078 ok(hres == S_OK, "Failed to put bstr element hres 0x%lx\n", hres);
1079 ok(tunk_xref == 2,"Failed to increment refcount of iface.\n");
1080 gotvalue = NULL;
1081 hres = SafeArrayGetElement(sa, indices, &gotvalue);
1082 ok(tunk_xref == 3,"Failed to increment refcount of iface.\n");
1083 ok(hres == S_OK, "Failed to get bstr element at hres 0x%lx\n", hres);
1084 if (hres == S_OK)
1085 ok(value == gotvalue, "Got %p instead of %p\n", gotvalue, value);
1086 SafeArrayDestroy(sa);
1087 ok(tunk_xref == 2,"Failed to decrement refcount of iface.\n");
1090 static void test_SafeArrayGetPutElement_VARIANT(void)
1092 SAFEARRAYBOUND sab;
1093 LONG indices[1];
1094 SAFEARRAY *sa;
1095 HRESULT hres;
1096 VARIANT value, gotvalue;
1098 sab.lLbound = 1;
1099 sab.cElements = 1;
1100 sa = SafeArrayCreate(VT_VARIANT, 1, &sab);
1101 ok(sa != NULL, "VARIANT test couldn't create array\n");
1102 if (!sa)
1103 return;
1105 ok(sa->cbElements == sizeof(VARIANT), "VARIANT size mismatch\n");
1106 if (sa->cbElements != sizeof(VARIANT))
1107 return;
1109 indices[0] = sab.lLbound;
1110 V_VT(&value) = VT_I4;
1111 V_I4(&value) = 0x42424242;
1112 hres = SafeArrayPutElement(sa, indices, &value);
1113 ok(hres == S_OK, "Failed to put Variant I4 element hres 0x%lx\n", hres);
1115 V_VT(&gotvalue) = 0xdead;
1116 hres = SafeArrayGetElement(sa, indices, &gotvalue);
1117 ok(hres == S_OK, "Failed to get variant element at hres 0x%lx\n", hres);
1119 V_VT(&gotvalue) = VT_EMPTY;
1120 hres = SafeArrayGetElement(sa, indices, &gotvalue);
1121 ok(hres == S_OK, "Failed to get variant element at hres 0x%lx\n", hres);
1122 if (hres == S_OK) {
1123 ok(V_VT(&value) == V_VT(&gotvalue), "Got type 0x%x instead of 0x%x\n", V_VT(&value), V_VT(&gotvalue));
1124 if (V_VT(&value) == V_VT(&gotvalue))
1125 ok(V_I4(&value) == V_I4(&gotvalue), "Got %ld instead of %d\n", V_I4(&value), V_VT(&gotvalue));
1127 SafeArrayDestroy(sa);
1131 static void test_SafeArrayCopyData(void)
1133 SAFEARRAYBOUND sab[4];
1134 SAFEARRAY *sa;
1135 SAFEARRAY *sacopy;
1136 HRESULT hres;
1137 int dimension,size=1;
1139 if (!pSafeArrayCopyData)
1140 return;
1142 for (dimension = 0; dimension < NUM_DIMENSIONS; dimension++)
1144 sab[dimension].lLbound = dimension * 2 + 2;
1145 sab[dimension].cElements = dimension * 3 + 1;
1146 size *= sab[dimension].cElements;
1149 sa = SafeArrayCreate(VT_INT, NUM_DIMENSIONS, sab);
1150 ok(sa != NULL, "Copy test couldn't create array\n");
1151 sacopy = SafeArrayCreate(VT_INT, NUM_DIMENSIONS, sab);
1152 ok(sacopy != NULL, "Copy test couldn't create copy array\n");
1154 if (!sa || !sacopy)
1155 return;
1157 ok(sa->cbElements == sizeof(int), "int size mismatch\n");
1158 if (sa->cbElements != sizeof(int))
1159 return;
1161 /* Fill the source array with some data; it doesn't matter what */
1162 for (dimension = 0; dimension < size; dimension++)
1164 int* data = (int*)sa->pvData;
1165 data[dimension] = dimension;
1168 hres = pSafeArrayCopyData(sa, sacopy);
1169 ok(hres == S_OK, "copy data failed hres 0x%lx\n", hres);
1170 if (hres == S_OK)
1172 ok(!memcmp(sa->pvData, sacopy->pvData, size * sizeof(int)), "compared different\n");
1175 /* Failure cases */
1176 hres = pSafeArrayCopyData(NULL, sacopy);
1177 ok(hres == E_INVALIDARG, "Null copy source hres 0x%lx\n", hres);
1178 hres = pSafeArrayCopyData(sa, NULL);
1179 ok(hres == E_INVALIDARG, "Null copy hres 0x%lx\n", hres);
1181 sacopy->rgsabound[0].cElements += 1;
1182 hres = pSafeArrayCopyData(sa, sacopy);
1183 ok(hres == E_INVALIDARG, "Bigger copy first dimension hres 0x%lx\n", hres);
1185 sacopy->rgsabound[0].cElements -= 2;
1186 hres = pSafeArrayCopyData(sa, sacopy);
1187 ok(hres == E_INVALIDARG, "Smaller copy first dimension hres 0x%lx\n", hres);
1188 sacopy->rgsabound[0].cElements += 1;
1190 sacopy->rgsabound[3].cElements += 1;
1191 hres = pSafeArrayCopyData(sa, sacopy);
1192 ok(hres == E_INVALIDARG, "Bigger copy last dimension hres 0x%lx\n", hres);
1194 sacopy->rgsabound[3].cElements -= 2;
1195 hres = pSafeArrayCopyData(sa, sacopy);
1196 ok(hres == E_INVALIDARG, "Smaller copy last dimension hres 0x%lx\n", hres);
1197 sacopy->rgsabound[3].cElements += 1;
1199 SafeArrayDestroy(sacopy);
1200 sacopy = NULL;
1201 hres = pSafeArrayCopyData(sa, sacopy);
1202 ok(hres == E_INVALIDARG, "->Null copy hres 0x%lx\n", hres);
1204 hres = SafeArrayCopy(sa, &sacopy);
1205 ok(hres == S_OK, "copy failed hres 0x%lx\n", hres);
1206 if (hres == S_OK)
1208 ok(SafeArrayGetElemsize(sa) == SafeArrayGetElemsize(sacopy),"elemsize wrong\n");
1209 ok(SafeArrayGetDim(sa) == SafeArrayGetDim(sacopy),"dimensions wrong\n");
1210 ok(!memcmp(sa->pvData, sacopy->pvData, size * sizeof(int)), "compared different\n");
1213 SafeArrayDestroy(sa);
1216 static void test_SafeArrayCreateEx(void)
1218 IRecordInfoImpl* iRec;
1219 SAFEARRAYBOUND sab[4];
1220 SAFEARRAY *sa;
1221 HRESULT hres;
1222 int dimension;
1224 if (!pSafeArrayCreateEx)
1225 return;
1227 for (dimension = 0; dimension < NUM_DIMENSIONS; dimension++)
1229 sab[dimension].lLbound = 0;
1230 sab[dimension].cElements = 8;
1233 /* Failure cases */
1234 sa = pSafeArrayCreateEx(VT_UI1, 1, NULL, NULL);
1235 ok(sa == NULL, "CreateEx NULL bounds didn't fail\n");
1237 /* test IID storage & defaulting */
1238 sa = pSafeArrayCreateEx(VT_DISPATCH, 1, sab, (PVOID)&IID_ITypeInfo);
1239 ok(sa != NULL, "CreateEx (ITypeInfo) failed\n");
1241 if (sa)
1243 GUID guid;
1244 if (pSafeArrayGetIID)
1246 hres = pSafeArrayGetIID(sa, &guid);
1247 ok(hres == S_OK, "CreateEx (ITypeInfo) no IID hres 0x%lx\n", hres);
1248 if (hres == S_OK)
1250 ok(IsEqualGUID(&guid, &IID_ITypeInfo), "CreateEx (ITypeInfo) bad IID\n");
1253 if (pSafeArraySetIID)
1255 hres = pSafeArraySetIID(sa, &IID_IUnknown);
1256 ok(hres == S_OK, "Failed to set IID, hres = %8lx\n", hres);
1257 if (hres == S_OK && pSafeArrayGetIID)
1259 hres = pSafeArrayGetIID(sa, &guid);
1260 ok(hres == S_OK && IsEqualGUID(&guid, &IID_IUnknown), "Set bad IID\n");
1263 SafeArrayDestroy(sa);
1266 sa = pSafeArrayCreateEx(VT_DISPATCH, 1, sab, NULL);
1267 ok(sa != NULL, "CreateEx (NULL) failed\n");
1269 if (sa)
1271 GUID guid;
1272 if (pSafeArrayGetIID)
1274 hres = pSafeArrayGetIID(sa, &guid);
1275 ok(hres == S_OK, "CreateEx (NULL) no IID hres 0x%lx\n", hres);
1276 if (hres == S_OK)
1278 ok(IsEqualGUID(&guid, &IID_IDispatch), "CreateEx (NULL) bad IID\n");
1281 SafeArrayDestroy(sa);
1284 sa = pSafeArrayCreateEx(VT_UNKNOWN, 1, sab, NULL);
1285 ok(sa != NULL, "CreateEx (NULL-Unk) failed\n");
1287 if (sa)
1289 GUID guid;
1290 if (pSafeArrayGetIID)
1292 hres = pSafeArrayGetIID(sa, &guid);
1293 ok(hres == S_OK, "CreateEx (NULL-Unk) no IID hres 0x%lx\n", hres);
1294 if (hres == S_OK)
1296 ok(IsEqualGUID(&guid, &IID_IUnknown), "CreateEx (NULL-Unk) bad IID\n");
1299 SafeArrayDestroy(sa);
1302 /* VT_RECORD failure case */
1303 sa = pSafeArrayCreateEx(VT_RECORD, 1, sab, NULL);
1304 ok(sa == NULL, "CreateEx (NULL-Rec) succeded\n");
1306 iRec = IRecordInfoImpl_Construct();
1308 /* Win32 doesn't care if GetSize fails */
1309 fail_GetSize = TRUE;
1310 sa = pSafeArrayCreateEx(VT_RECORD, 1, sab, (LPVOID)iRec);
1311 ok(sa != NULL, "CreateEx (Fail Size) failed\n");
1312 ok(iRec->ref == START_REF_COUNT + 1, "Wrong iRec refcount %ld\n", iRec->ref);
1313 ok(iRec->sizeCalled == 1, "GetSize called %ld times\n", iRec->sizeCalled);
1314 ok(iRec->clearCalled == 0, "Clear called %ld times\n", iRec->clearCalled);
1315 if (sa)
1317 ok(sa->cbElements == RECORD_SIZE_FAIL, "Altered size to %ld\n", sa->cbElements);
1318 SafeArrayDestroy(sa);
1319 ok(iRec->clearCalled == sab[0].cElements, "Destroy->Clear called %ld times\n", iRec->clearCalled);
1322 /* Test VT_RECORD array */
1323 fail_GetSize = FALSE;
1324 iRec->ref = START_REF_COUNT;
1325 iRec->sizeCalled = 0;
1326 iRec->clearCalled = 0;
1327 sa = pSafeArrayCreateEx(VT_RECORD, 1, sab, (LPVOID)iRec);
1328 ok(sa != NULL, "CreateEx (Rec) failed\n");
1329 ok(iRec->ref == START_REF_COUNT + 1, "Wrong iRec refcount %ld\n", iRec->ref);
1330 ok(iRec->sizeCalled == 1, "GetSize called %ld times\n", iRec->sizeCalled);
1331 ok(iRec->clearCalled == 0, "Clear called %ld times\n", iRec->clearCalled);
1332 if (sa && pSafeArrayGetRecordInfo)
1334 IRecordInfo* saRec = NULL;
1335 hres = pSafeArrayGetRecordInfo(sa, &saRec);
1337 ok(hres == S_OK,"GRI failed\n");
1338 ok(saRec == (IRecordInfo*)iRec,"Different saRec\n");
1339 ok(iRec->ref == START_REF_COUNT + 2, "Didn't AddRef %ld\n", iRec->ref);
1340 if (iRec->ref == START_REF_COUNT + 2)
1341 IRecordInfo_Release(saRec);
1343 ok(sa->cbElements == RECORD_SIZE,"Elemsize is %ld\n", sa->cbElements);
1345 SafeArrayDestroy(sa);
1346 ok(iRec->sizeCalled == 1, "Destroy->GetSize called %ld times\n", iRec->sizeCalled);
1347 ok(iRec->clearCalled == sab[0].cElements, "Destroy->Clear called %ld times\n", iRec->clearCalled);
1348 ok(iRec->ref == START_REF_COUNT, "Wrong iRec refcount %ld\n", iRec->ref);
1352 static void test_SafeArrayClear(void)
1354 SAFEARRAYBOUND sab;
1355 SAFEARRAY *sa;
1356 VARIANTARG v;
1357 HRESULT hres;
1359 sab.lLbound = 0;
1360 sab.cElements = 10;
1361 sa = SafeArrayCreate(VT_UI1, 1, &sab);
1362 ok(sa != NULL, "Create() failed.\n");
1363 if (!sa)
1364 return;
1366 /* Test clearing non-NULL variants containing arrays */
1367 V_VT(&v) = VT_ARRAY|VT_UI1;
1368 V_ARRAY(&v) = sa;
1369 hres = VariantClear(&v);
1370 ok(hres == S_OK && V_VT(&v) == VT_EMPTY, "VariantClear: hres 0x%lx, Type %d\n", hres, V_VT(&v));
1371 ok(V_ARRAY(&v) == sa, "VariantClear: Overwrote value\n");
1373 sa = SafeArrayCreate(VT_UI1, 1, &sab);
1374 ok(sa != NULL, "Create() failed.\n");
1375 if (!sa)
1376 return;
1378 V_VT(&v) = VT_SAFEARRAY;
1379 V_ARRAY(&v) = sa;
1380 hres = VariantClear(&v);
1381 ok(hres == DISP_E_BADVARTYPE, "VariantClear: hres 0x%lx\n", hres);
1383 V_VT(&v) = VT_SAFEARRAY|VT_BYREF;
1384 V_ARRAYREF(&v) = &sa;
1385 hres = VariantClear(&v);
1386 ok(hres == DISP_E_BADVARTYPE, "VariantClear: hres 0x%lx\n", hres);
1388 SafeArrayDestroy(sa);
1391 static void test_SafeArrayCopy(void)
1393 SAFEARRAYBOUND sab;
1394 SAFEARRAY *sa;
1395 VARIANTARG vSrc, vDst;
1396 HRESULT hres;
1398 sab.lLbound = 0;
1399 sab.cElements = 10;
1400 sa = SafeArrayCreate(VT_UI1, 1, &sab);
1401 ok(sa != NULL, "Create() failed.\n");
1402 if (!sa)
1403 return;
1405 /* Test copying non-NULL variants containing arrays */
1406 V_VT(&vSrc) = (VT_ARRAY|VT_BYREF|VT_UI1);
1407 V_ARRAYREF(&vSrc) = &sa;
1408 V_VT(&vDst) = VT_EMPTY;
1410 hres = VariantCopy(&vDst, &vSrc);
1411 ok(hres == S_OK && V_VT(&vDst) == (VT_ARRAY|VT_BYREF|VT_UI1),
1412 "VariantCopy: hres 0x%lx, Type %d\n", hres, V_VT(&vDst));
1413 ok(V_ARRAYREF(&vDst) == &sa, "VariantClear: Performed deep copy\n");
1415 V_VT(&vSrc) = (VT_ARRAY|VT_UI1);
1416 V_ARRAY(&vSrc) = sa;
1417 V_VT(&vDst) = VT_EMPTY;
1419 hres = VariantCopy(&vDst, &vSrc);
1420 ok(hres == S_OK && V_VT(&vDst) == (VT_ARRAY|VT_UI1),
1421 "VariantCopy: hres 0x%lx, Type %d\n", hres, V_VT(&vDst));
1422 ok(V_ARRAY(&vDst) != sa, "VariantClear: Performed shallow copy\n");
1424 SafeArrayDestroy(V_ARRAY(&vSrc));
1425 SafeArrayDestroy(V_ARRAY(&vDst));
1428 #define MKARRAY(low,num,typ) sab.lLbound = low; sab.cElements = num; \
1429 sa = SafeArrayCreate(typ, 1, &sab); ok(sa != NULL, "Create() failed.\n"); \
1430 if (!sa) return; \
1431 V_VT(&v) = VT_ARRAY|typ; V_ARRAY(&v) = sa; VariantInit(&v2)
1433 #define MKARRAYCONT(low,num,typ) sab.lLbound = low; sab.cElements = num; \
1434 sa = SafeArrayCreate(typ, 1, &sab); if (!sa) continue; \
1435 V_VT(&v) = VT_ARRAY|typ; V_ARRAY(&v) = sa; VariantInit(&v2)
1437 static void test_SafeArrayChangeTypeEx(void)
1439 static const char *szHello = "Hello World";
1440 SAFEARRAYBOUND sab;
1441 SAFEARRAY *sa;
1442 VARIANTARG v,v2;
1443 VARTYPE vt;
1444 HRESULT hres;
1446 /* VT_ARRAY|VT_UI1 -> VT_BSTR */
1447 MKARRAY(0,strlen(szHello)+1,VT_UI1);
1448 memcpy(sa->pvData, szHello, strlen(szHello)+1);
1450 hres = VariantChangeTypeEx(&v2, &v, 0, 0, VT_BSTR);
1451 ok(hres == S_OK, "CTE VT_ARRAY|VT_UI1 -> VT_BSTR failed with %lx\n", hres);
1452 if (hres == S_OK)
1454 ok(V_VT(&v2) == VT_BSTR, "CTE VT_ARRAY|VT_UI1 -> VT_BSTR did not return VT_BSTR, but %d.\n",V_VT(&v2));
1455 ok(strcmp((char*)V_BSTR(&v2),szHello) == 0,"Expected string '%s', got '%s'\n", szHello,
1456 (char*)V_BSTR(&v2));
1457 VariantClear(&v2);
1460 /* VT_VECTOR|VT_UI1 -> VT_BSTR */
1461 SafeArrayDestroy(sa);
1462 if (pSafeArrayCreateVector)
1464 sa = pSafeArrayCreateVector(VT_UI1, 0, strlen(szHello)+1);
1465 ok(sa != NULL, "CreateVector() failed.\n");
1466 if (!sa)
1467 return;
1469 memcpy(sa->pvData, szHello, strlen(szHello)+1);
1470 V_VT(&v) = VT_VECTOR|VT_UI1;
1471 V_ARRAY(&v) = sa;
1472 VariantInit(&v2);
1474 hres = VariantChangeTypeEx(&v2, &v, 0, 0, VT_BSTR);
1475 ok(hres == DISP_E_BADVARTYPE, "CTE VT_VECTOR|VT_UI1 returned %lx\n", hres);
1477 /* (vector)VT_ARRAY|VT_UI1 -> VT_BSTR (In place) */
1478 V_VT(&v) = VT_ARRAY|VT_UI1;
1479 hres = VariantChangeTypeEx(&v, &v, 0, 0, VT_BSTR);
1480 ok(hres == S_OK, "CTE VT_ARRAY|VT_UI1 -> VT_BSTR failed with %lx\n", hres);
1481 if (hres == S_OK)
1483 ok(V_VT(&v) == VT_BSTR, "CTE VT_ARRAY|VT_UI1 -> VT_BSTR did not return VT_BSTR, but %d.\n",V_VT(&v));
1484 ok(strcmp((char*)V_BSTR(&v),szHello) == 0,"Expected string '%s', got '%s'\n", szHello,
1485 (char*)V_BSTR(&v));
1486 VariantClear(&v);
1490 /* To/from BSTR only works with arrays of VT_UI1 */
1491 for (vt = 0; vt <= VT_CLSID; vt++)
1493 if (vt == VT_UI1)
1494 continue;
1496 MKARRAYCONT(0,1,vt);
1497 hres = VariantChangeTypeEx(&v2, &v, 0, 0, VT_BSTR);
1498 ok(hres != S_OK, "CTE VT_ARRAY|VT %d->BSTR succeeded\n", vt);
1499 VariantClear(&v2);
1502 /* Can't change an array of one type into array of another type , even
1503 * if the other type is the same size
1505 if (pSafeArrayCreateVector)
1507 sa = pSafeArrayCreateVector(VT_UI1, 0, 1);
1508 ok(sa != NULL, "CreateVector() failed.\n");
1509 if (!sa)
1510 return;
1512 V_VT(&v) = VT_ARRAY|VT_UI1;
1513 V_ARRAY(&v) = sa;
1514 hres = VariantChangeTypeEx(&v2, &v, 0, 0, VT_ARRAY|VT_I1);
1515 ok(hres == DISP_E_TYPEMISMATCH, "CTE VT_ARRAY|VT_UI1->VT_ARRAY|VT_I1 returned %lx\n", hres);
1517 /* But can change to the same array type */
1518 SafeArrayDestroy(sa);
1519 sa = pSafeArrayCreateVector(VT_UI1, 0, 1);
1520 ok(sa != NULL, "CreateVector() failed.\n");
1521 if (!sa)
1522 return;
1523 V_VT(&v) = VT_ARRAY|VT_UI1;
1524 V_ARRAY(&v) = sa;
1525 hres = VariantChangeTypeEx(&v2, &v, 0, 0, VT_ARRAY|VT_UI1);
1526 ok(hres == S_OK, "CTE VT_ARRAY|VT_UI1->VT_ARRAY|VT_UI1 returned %lx\n", hres);
1529 /* NULL/EMPTY */
1530 MKARRAY(0,1,VT_UI1);
1531 hres = VariantChangeTypeEx(&v2, &v, 0, 0, VT_NULL);
1532 ok(hres == DISP_E_TYPEMISMATCH, "CTE VT_ARRAY|VT_UI1 returned %lx\n", hres);
1533 MKARRAY(0,1,VT_UI1);
1534 hres = VariantChangeTypeEx(&v2, &v, 0, 0, VT_EMPTY);
1535 ok(hres == DISP_E_TYPEMISMATCH, "CTE VT_ARRAY|VT_UI1 returned %lx\n", hres);
1539 static void test_SafeArrayDestroyData (void)
1541 SAFEARRAYBOUND sab;
1542 SAFEARRAY *sa;
1543 HRESULT hres;
1544 int value = 0;
1545 long index[1];
1546 void HUGEP *temp_pvData;
1548 sab.lLbound = 0;
1549 sab.cElements = 10;
1550 sa = SafeArrayCreate(VT_INT, 1, &sab);
1551 ok(sa != NULL, "Create() failed.\n");
1552 if (!sa)
1553 return;
1554 index[0] = 1;
1555 SafeArrayPutElement (sa, index, &value);
1557 /* SafeArrayDestroyData shouldn't do anything if FADF_STATIC is set. */
1558 sa->fFeatures |= FADF_STATIC;
1559 temp_pvData = sa->pvData;
1560 hres = SafeArrayDestroyData(sa);
1561 ok(hres == S_OK, "SADData FADF_STATIC failed, error code %lx.\n",hres);
1562 ok(sa->pvData == temp_pvData, "SADData FADF_STATIC: pvData=%p, expected %p (fFeatures = %d).\n",
1563 sa->pvData, temp_pvData, sa->fFeatures);
1565 /* Clear FADF_STATIC, now really destroy the data. */
1566 sa->fFeatures ^= FADF_STATIC;
1567 hres = SafeArrayDestroyData(sa);
1568 ok(hres == S_OK, "SADData !FADF_STATIC failed, error code %lx.\n",hres);
1569 ok(sa->pvData == NULL, "SADData !FADF_STATIC: pvData=%p, expected NULL.\n", sa->pvData);
1571 hres = SafeArrayDestroy(sa);
1572 ok(hres == S_OK, "SAD failed, error code %lx.\n", hres);
1575 START_TEST(safearray)
1577 hOleaut32 = LoadLibraryA("oleaut32.dll");
1579 GETPTR(SafeArrayAllocDescriptorEx);
1580 GETPTR(SafeArrayCopyData);
1581 GETPTR(SafeArrayGetIID);
1582 GETPTR(SafeArraySetIID);
1583 GETPTR(SafeArrayGetVartype);
1584 GETPTR(SafeArrayCreateEx);
1585 GETPTR(SafeArrayCreateVector);
1587 test_safearray();
1588 test_SafeArrayAllocDestroyDescriptor();
1589 test_SafeArrayCreateLockDestroy();
1590 test_VectorCreateLockDestroy();
1591 test_LockUnlock();
1592 test_SafeArrayChangeTypeEx();
1593 test_SafeArrayCopy();
1594 test_SafeArrayClear();
1595 test_SafeArrayCreateEx();
1596 test_SafeArrayCopyData();
1597 test_SafeArrayDestroyData();
1598 test_SafeArrayGetPutElement();
1599 test_SafeArrayGetPutElement_BSTR();
1600 test_SafeArrayGetPutElement_IUnknown();
1601 test_SafeArrayGetPutElement_VARIANT();