TESTING -- override pthreads to fix gstreamer v5
[wine/multimedia.git] / dlls / oleaut32 / tests / safearray.c
blobf57b886d0f456007b42a5e215d6e01c5dc59344e
1 /*
2 * SafeArray test program
4 * Copyright 2002 Marcus Meissner
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include <stdarg.h>
23 #include <stdio.h>
24 #include <math.h>
25 #include <float.h>
27 #define COBJMACROS
28 #define CONST_VTABLE
29 #include "wine/test.h"
30 #include "windef.h"
31 #include "winbase.h"
32 #include "winuser.h"
33 #include "wingdi.h"
34 #include "winnls.h"
35 #include "winsock2.h"
36 #include "winerror.h"
37 #include "winnt.h"
39 #include "wtypes.h"
40 #include "oleauto.h"
42 #ifndef FADF_CREATEVECTOR
43 const USHORT FADF_CREATEVECTOR = 0x2000;
44 #endif
46 static HMODULE hOleaut32;
48 static HRESULT (WINAPI *pSafeArrayAllocDescriptorEx)(VARTYPE,UINT,SAFEARRAY**);
49 static HRESULT (WINAPI *pSafeArrayCopyData)(SAFEARRAY*,SAFEARRAY*);
50 static HRESULT (WINAPI *pSafeArrayGetIID)(SAFEARRAY*,GUID*);
51 static HRESULT (WINAPI *pSafeArraySetIID)(SAFEARRAY*,REFGUID);
52 static HRESULT (WINAPI *pSafeArrayGetVartype)(SAFEARRAY*,VARTYPE*);
53 static HRESULT (WINAPI *pSafeArrayGetRecordInfo)(SAFEARRAY*,IRecordInfo**);
54 static SAFEARRAY* (WINAPI *pSafeArrayCreateEx)(VARTYPE,UINT,SAFEARRAYBOUND*,LPVOID);
55 static SAFEARRAY* (WINAPI *pSafeArrayCreateVector)(VARTYPE,LONG,ULONG);
57 #define GETPTR(func) p##func = (void*)GetProcAddress(hOleaut32, #func)
59 /* Has I8/UI8 data type? */
60 static BOOL has_i8;
61 /* Has INT_PTR/UINT_PTR type? */
62 static BOOL has_int_ptr;
64 static const USHORT ignored_copy_features[] =
66 FADF_AUTO,
67 FADF_STATIC,
68 FADF_EMBEDDED,
69 FADF_FIXEDSIZE
72 #define START_REF_COUNT 1
73 #define RECORD_SIZE 64
74 #define RECORD_SIZE_FAIL 17
75 /************************************************************************
76 * Dummy IRecordInfo Implementation
78 typedef struct IRecordInfoImpl
80 IRecordInfo IRecordInfo_iface;
81 LONG ref;
82 unsigned int sizeCalled;
83 unsigned int clearCalled;
84 unsigned int recordcopy;
85 } IRecordInfoImpl;
87 static inline IRecordInfoImpl *impl_from_IRecordInfo(IRecordInfo *iface)
89 return CONTAINING_RECORD(iface, IRecordInfoImpl, IRecordInfo_iface);
92 static HRESULT WINAPI RecordInfo_QueryInterface(IRecordInfo *iface, REFIID riid, void **obj)
94 *obj = NULL;
96 if (IsEqualIID(riid, &IID_IUnknown) ||
97 IsEqualIID(riid, &IID_IRecordInfo))
99 *obj = iface;
100 IRecordInfo_AddRef(iface);
101 return S_OK;
104 return E_NOINTERFACE;
107 static ULONG WINAPI RecordInfo_AddRef(IRecordInfo *iface)
109 IRecordInfoImpl* This = impl_from_IRecordInfo(iface);
110 return InterlockedIncrement(&This->ref);
113 static ULONG WINAPI RecordInfo_Release(IRecordInfo *iface)
115 IRecordInfoImpl* This = impl_from_IRecordInfo(iface);
116 ULONG ref = InterlockedDecrement(&This->ref);
118 if (!ref)
119 HeapFree(GetProcessHeap(), 0, This);
121 return ref;
124 static HRESULT WINAPI RecordInfo_RecordInit(IRecordInfo *iface, PVOID pvNew)
126 ok(0, "unexpected call\n");
127 return E_NOTIMPL;
130 static BOOL fail_GetSize; /* Whether to fail the GetSize call */
132 static HRESULT WINAPI RecordInfo_RecordClear(IRecordInfo *iface, PVOID pvExisting)
134 IRecordInfoImpl* This = impl_from_IRecordInfo(iface);
135 This->clearCalled++;
136 return S_OK;
139 static HRESULT WINAPI RecordInfo_RecordCopy(IRecordInfo *iface, PVOID pvExisting, PVOID pvNew)
141 IRecordInfoImpl* This = impl_from_IRecordInfo(iface);
142 This->recordcopy++;
143 return S_OK;
146 static HRESULT WINAPI RecordInfo_GetGuid(IRecordInfo *iface, GUID *pguid)
148 ok(0, "unexpected call\n");
149 return E_NOTIMPL;
152 static HRESULT WINAPI RecordInfo_GetName(IRecordInfo *iface, BSTR *pbstrName)
154 ok(0, "unexpected call\n");
155 return E_NOTIMPL;
158 static HRESULT WINAPI RecordInfo_GetSize(IRecordInfo *iface, ULONG* size)
160 IRecordInfoImpl* This = impl_from_IRecordInfo(iface);
161 This->sizeCalled++;
162 if (fail_GetSize)
164 *size = RECORD_SIZE_FAIL;
165 return E_UNEXPECTED;
167 *size = RECORD_SIZE;
168 return S_OK;
171 static HRESULT WINAPI RecordInfo_GetTypeInfo(IRecordInfo *iface, ITypeInfo **ppTypeInfo)
173 ok(0, "unexpected call\n");
174 return E_NOTIMPL;
177 static HRESULT WINAPI RecordInfo_GetField(IRecordInfo *iface, PVOID pvData,
178 LPCOLESTR szFieldName, VARIANT *pvarField)
180 ok(0, "unexpected call\n");
181 return E_NOTIMPL;
184 static HRESULT WINAPI RecordInfo_GetFieldNoCopy(IRecordInfo *iface, PVOID pvData,
185 LPCOLESTR szFieldName, VARIANT *pvarField, PVOID *ppvDataCArray)
187 ok(0, "unexpected call\n");
188 return E_NOTIMPL;
191 static HRESULT WINAPI RecordInfo_PutField(IRecordInfo *iface, ULONG wFlags, PVOID pvData,
192 LPCOLESTR szFieldName, VARIANT *pvarField)
194 ok(0, "unexpected call\n");
195 return E_NOTIMPL;
198 static HRESULT WINAPI RecordInfo_PutFieldNoCopy(IRecordInfo *iface, ULONG wFlags,
199 PVOID pvData, LPCOLESTR szFieldName, VARIANT *pvarField)
201 ok(0, "unexpected call\n");
202 return E_NOTIMPL;
205 static HRESULT WINAPI RecordInfo_GetFieldNames(IRecordInfo *iface, ULONG *pcNames,
206 BSTR *rgBstrNames)
208 ok(0, "unexpected call\n");
209 return E_NOTIMPL;
212 static BOOL WINAPI RecordInfo_IsMatchingType(IRecordInfo *iface, IRecordInfo *info2)
214 ok(0, "unexpected call\n");
215 return FALSE;
218 static PVOID WINAPI RecordInfo_RecordCreate(IRecordInfo *iface)
220 ok(0, "unexpected call\n");
221 return NULL;
224 static HRESULT WINAPI RecordInfo_RecordCreateCopy(IRecordInfo *iface, PVOID pvSource,
225 PVOID *ppvDest)
227 ok(0, "unexpected call\n");
228 return E_NOTIMPL;
231 static HRESULT WINAPI RecordInfo_RecordDestroy(IRecordInfo *iface, PVOID pvRecord)
233 ok(0, "unexpected call\n");
234 return E_NOTIMPL;
237 static const IRecordInfoVtbl RecordInfoVtbl =
239 RecordInfo_QueryInterface,
240 RecordInfo_AddRef,
241 RecordInfo_Release,
242 RecordInfo_RecordInit,
243 RecordInfo_RecordClear,
244 RecordInfo_RecordCopy,
245 RecordInfo_GetGuid,
246 RecordInfo_GetName,
247 RecordInfo_GetSize,
248 RecordInfo_GetTypeInfo,
249 RecordInfo_GetField,
250 RecordInfo_GetFieldNoCopy,
251 RecordInfo_PutField,
252 RecordInfo_PutFieldNoCopy,
253 RecordInfo_GetFieldNames,
254 RecordInfo_IsMatchingType,
255 RecordInfo_RecordCreate,
256 RecordInfo_RecordCreateCopy,
257 RecordInfo_RecordDestroy
260 static IRecordInfoImpl *IRecordInfoImpl_Construct(void)
262 IRecordInfoImpl *rec;
264 rec = HeapAlloc(GetProcessHeap(), 0, sizeof(IRecordInfoImpl));
265 rec->IRecordInfo_iface.lpVtbl = &RecordInfoVtbl;
266 rec->ref = START_REF_COUNT;
267 rec->clearCalled = 0;
268 rec->sizeCalled = 0;
269 return rec;
272 static DWORD SAFEARRAY_GetVTSize(VARTYPE vt)
274 switch (vt)
276 case VT_I1:
277 case VT_UI1: return sizeof(BYTE);
278 case VT_BOOL:
279 case VT_I2:
280 case VT_UI2: return sizeof(SHORT);
281 case VT_I4:
282 case VT_UI4:
283 case VT_R4:
284 case VT_ERROR: return sizeof(LONG);
285 case VT_R8: return sizeof(LONG64);
286 case VT_I8:
287 case VT_UI8:
288 if (has_i8)
289 return sizeof(LONG64);
290 break;
291 case VT_INT:
292 case VT_UINT: return sizeof(INT);
293 case VT_INT_PTR:
294 case VT_UINT_PTR:
295 if (has_int_ptr)
296 return sizeof(UINT_PTR);
297 break;
298 case VT_CY: return sizeof(CY);
299 case VT_DATE: return sizeof(DATE);
300 case VT_BSTR: return sizeof(BSTR);
301 case VT_DISPATCH: return sizeof(LPDISPATCH);
302 case VT_VARIANT: return sizeof(VARIANT);
303 case VT_UNKNOWN: return sizeof(LPUNKNOWN);
304 case VT_DECIMAL: return sizeof(DECIMAL);
306 return 0;
309 static void check_for_VT_INT_PTR(void)
311 /* Set a global flag if VT_INT_PTR is supported */
313 SAFEARRAY* a;
314 SAFEARRAYBOUND bound;
315 bound.cElements = 0;
316 bound.lLbound = 0;
317 a = SafeArrayCreate(VT_INT_PTR, 1, &bound);
318 if (a) {
319 HRESULT hres;
320 trace("VT_INT_PTR is supported\n");
321 has_int_ptr = TRUE;
322 hres = SafeArrayDestroy(a);
323 ok(hres == S_OK, "got 0x%08x\n", hres);
325 else {
326 trace("VT_INT_PTR is not supported\n");
327 has_int_ptr = FALSE;
331 #define VARTYPE_NOT_SUPPORTED 0
332 static struct {
333 VARTYPE vt; /* VT */
334 UINT elemsize; /* elementsize by VT */
335 UINT expflags; /* fFeatures from SafeArrayAllocDescriptorEx */
336 UINT addflags; /* additional fFeatures from SafeArrayCreate */
337 } vttypes[] = {
338 {VT_EMPTY, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
339 {VT_NULL, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
340 {VT_I2, 2, FADF_HAVEVARTYPE,0},
341 {VT_I4, 4, FADF_HAVEVARTYPE,0},
342 {VT_R4, 4, FADF_HAVEVARTYPE,0},
343 {VT_R8, 8, FADF_HAVEVARTYPE,0},
344 {VT_CY, 8, FADF_HAVEVARTYPE,0},
345 {VT_DATE, 8, FADF_HAVEVARTYPE,0},
346 {VT_BSTR, sizeof(BSTR), FADF_HAVEVARTYPE,FADF_BSTR},
347 {VT_DISPATCH, sizeof(LPDISPATCH), FADF_HAVEIID, FADF_DISPATCH},
348 {VT_ERROR, 4, FADF_HAVEVARTYPE,0},
349 {VT_BOOL, 2, FADF_HAVEVARTYPE,0},
350 {VT_VARIANT, sizeof(VARIANT), FADF_HAVEVARTYPE,FADF_VARIANT},
351 {VT_UNKNOWN, sizeof(LPUNKNOWN), FADF_HAVEIID, FADF_UNKNOWN},
352 {VT_DECIMAL, sizeof(DECIMAL), FADF_HAVEVARTYPE,0},
353 {15, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0}, /* no VT_xxx */
354 {VT_I1, 1, FADF_HAVEVARTYPE,0},
355 {VT_UI1, 1, FADF_HAVEVARTYPE,0},
356 {VT_UI2, 2, FADF_HAVEVARTYPE,0},
357 {VT_UI4, 4, FADF_HAVEVARTYPE,0},
358 {VT_I8, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
359 {VT_UI8, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
360 {VT_INT, sizeof(INT), FADF_HAVEVARTYPE,0},
361 {VT_UINT, sizeof(UINT), FADF_HAVEVARTYPE,0},
362 {VT_VOID, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
363 {VT_HRESULT, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
364 {VT_PTR, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
365 {VT_SAFEARRAY,VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
366 {VT_CARRAY, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
367 {VT_USERDEFINED,VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
368 {VT_LPSTR, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
369 {VT_LPWSTR, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
370 {VT_FILETIME, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
371 {VT_RECORD, VARTYPE_NOT_SUPPORTED,FADF_RECORD,0},
372 {VT_BLOB, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
373 {VT_STREAM, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
374 {VT_STORAGE, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
375 {VT_STREAMED_OBJECT,VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
376 {VT_STORED_OBJECT,VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
377 {VT_BLOB_OBJECT,VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
378 {VT_CF, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
379 {VT_CLSID, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
382 static void test_safearray(void)
384 SAFEARRAY *a, b, *c;
385 unsigned int i, diff;
386 LONG indices[2];
387 HRESULT hres;
388 SAFEARRAYBOUND bound, bounds[2];
389 VARIANT v,d;
390 LPVOID data;
391 IID iid;
392 VARTYPE vt;
393 LONG l;
394 unsigned char *ptr1, *ptr2;
396 hres = SafeArrayDestroy( NULL);
397 ok( hres == S_OK, "SafeArrayDestroy( NULL) returned 0x%x\n", hres);
399 bound.cElements = 1;
400 bound.lLbound = 0;
401 a = SafeArrayCreate(-1, 1, &bound);
402 ok(NULL == a,"SAC(-1,1,[1,0]) not failed?\n");
404 bound.cElements = 0;
405 bound.lLbound = 42;
406 a = SafeArrayCreate(VT_I4, 1, &bound);
407 ok(NULL != a,"SAC(VT_I4,1,[0,0]) failed.\n");
409 hres = SafeArrayGetLBound(a, 1, &l);
410 ok(hres == S_OK, "SAGLB of 0 size dimensioned array failed with %x\n",hres);
411 ok(l == 42, "SAGLB of 0 size dimensioned array failed to return 42, but returned %d\n",l);
412 hres = SafeArrayGetUBound(a, 1, &l);
413 ok(hres == S_OK, "SAGUB of 0 size dimensioned array failed with %x\n",hres);
414 ok(l == 41, "SAGUB of 0 size dimensioned array failed to return 41, but returned %d\n",l);
416 hres = SafeArrayAccessData(a, &data);
417 ok(hres == S_OK, "SafeArrayAccessData of 0 size dimensioned array failed with %x\n", hres);
418 SafeArrayUnaccessData(a);
420 bound.cElements = 2;
421 hres = SafeArrayRedim(a, &bound);
422 ok(hres == S_OK,"SAR of a 0 elements dimension failed with hres %x\n", hres);
423 bound.cElements = 0;
424 hres = SafeArrayRedim(a, &bound);
425 ok(hres == S_OK || hres == E_OUTOFMEMORY,
426 "SAR to a 0 elements dimension failed with hres %x\n", hres);
427 hres = SafeArrayDestroy(a);
428 ok(hres == S_OK,"SAD of 0 dim array failed with hres %x\n", hres);
430 SafeArrayAllocDescriptor(2, &a);
431 a->rgsabound[0].cElements = 2;
432 a->rgsabound[0].lLbound = 1;
433 a->rgsabound[1].cElements = 4;
434 a->rgsabound[1].lLbound = 1;
435 a->cbElements = 2;
436 hres = SafeArrayAllocData(a);
437 ok(hres == S_OK, "SafeArrayAllocData failed with hres %x\n", hres);
439 indices[0] = 4;
440 indices[1] = 2;
441 hres = SafeArrayPtrOfIndex(a, indices, (void **)&ptr1);
442 ok(hres == S_OK, "SAPOI failed with hres %x\n", hres);
443 SafeArrayAccessData(a, (void **)&ptr2);
444 ok(ptr1 - ptr2 == 14, "SAPOI got wrong ptr\n");
445 *(WORD *)ptr1 = 0x55aa;
446 SafeArrayUnaccessData(a);
448 bound.cElements = 10;
449 bound.lLbound = 1;
450 SafeArrayRedim(a, &bound);
451 ptr1 = NULL;
452 SafeArrayPtrOfIndex(a, indices, (void **)&ptr1);
453 ok(*(WORD *)ptr1 == 0x55aa, "Data not preserved when resizing array\n");
455 bound.cElements = 10;
456 bound.lLbound = 0;
457 SafeArrayRedim(a, &bound);
458 SafeArrayPtrOfIndex(a, indices, (void **)&ptr1);
459 ok(*(WORD *)ptr1 == 0 ||
460 broken(*(WORD *)ptr1 != 0), /* Win 2003 */
461 "Expanded area not zero-initialized\n");
463 indices[1] = 1;
464 SafeArrayPtrOfIndex(a, indices, (void **)&ptr1);
465 ok(*(WORD *)ptr1 == 0x55aa ||
466 broken(*(WORD *)ptr1 != 0x55aa), /* Win 2003 */
467 "Data not preserved when resizing array\n");
469 hres = SafeArrayDestroy(a);
470 ok(hres == S_OK,"SAD failed with hres %x\n", hres);
472 bounds[0].cElements = 0; bounds[0].lLbound = 1;
473 bounds[1].cElements = 2; bounds[1].lLbound = 23;
474 a = SafeArrayCreate(VT_I4,2,bounds);
475 ok(a != NULL,"SAC(VT_INT32,2,...) with 0 element dim failed.\n");
477 hres = SafeArrayDestroy(a);
478 ok(hres == S_OK,"SAD failed with hres %x\n", hres);
479 bounds[0].cElements = 1; bounds[0].lLbound = 1;
480 bounds[1].cElements = 0; bounds[1].lLbound = 23;
481 a = SafeArrayCreate(VT_I4,2,bounds);
482 ok(a != NULL,"SAC(VT_INT32,2,...) with 0 element dim failed.\n");
484 hres = SafeArrayDestroy(a);
485 ok(hres == S_OK,"SAD failed with hres %x\n", hres);
487 bounds[0].cElements = 42; bounds[0].lLbound = 1;
488 bounds[1].cElements = 2; bounds[1].lLbound = 23;
489 a = SafeArrayCreate(VT_I4,2,bounds);
490 ok(a != NULL,"SAC(VT_INT32,2,...) failed.\n");
492 hres = SafeArrayGetLBound (a, 0, &l);
493 ok (hres == DISP_E_BADINDEX, "SAGLB 0 failed with %x\n", hres);
494 hres = SafeArrayGetLBound (a, 1, &l);
495 ok (hres == S_OK, "SAGLB 1 failed with %x\n", hres);
496 ok (l == 1, "SAGLB 1 returned %d instead of 1\n", l);
497 hres = SafeArrayGetLBound (a, 2, &l);
498 ok (hres == S_OK, "SAGLB 2 failed with %x\n", hres);
499 ok (l == 23, "SAGLB 2 returned %d instead of 23\n", l);
500 hres = SafeArrayGetLBound (a, 3, &l);
501 ok (hres == DISP_E_BADINDEX, "SAGLB 3 failed with %x\n", hres);
503 hres = SafeArrayGetUBound (a, 0, &l);
504 ok (hres == DISP_E_BADINDEX, "SAGUB 0 failed with %x\n", hres);
505 hres = SafeArrayGetUBound (a, 1, &l);
506 ok (hres == S_OK, "SAGUB 1 failed with %x\n", hres);
507 ok (l == 42, "SAGUB 1 returned %d instead of 42\n", l);
508 hres = SafeArrayGetUBound (a, 2, &l);
509 ok (hres == S_OK, "SAGUB 2 failed with %x\n", hres);
510 ok (l == 24, "SAGUB 2 returned %d instead of 24\n", l);
511 hres = SafeArrayGetUBound (a, 3, &l);
512 ok (hres == DISP_E_BADINDEX, "SAGUB 3 failed with %x\n", hres);
514 i = SafeArrayGetDim(a);
515 ok(i == 2, "getdims of 2 din array returned %d\n",i);
517 indices[0] = 0;
518 indices[1] = 23;
519 hres = SafeArrayGetElement(a, indices, &i);
520 ok(DISP_E_BADINDEX == hres,"SAGE failed [0,23], hres 0x%x\n",hres);
522 indices[0] = 1;
523 indices[1] = 22;
524 hres = SafeArrayGetElement(a, indices, &i);
525 ok(DISP_E_BADINDEX == hres,"SAGE failed [1,22], hres 0x%x\n",hres);
527 indices[0] = 1;
528 indices[1] = 23;
529 hres = SafeArrayGetElement(a, indices, &i);
530 ok(S_OK == hres,"SAGE failed [1,23], hres 0x%x\n",hres);
532 indices[0] = 1;
533 indices[1] = 25;
534 hres = SafeArrayGetElement(a, indices, &i);
535 ok(DISP_E_BADINDEX == hres,"SAGE failed [1,24], hres 0x%x\n",hres);
537 indices[0] = 3;
538 indices[1] = 23;
539 hres = SafeArrayGetElement(a, indices, &i);
540 ok(S_OK == hres,"SAGE failed [42,23], hres 0x%x\n",hres);
542 hres = SafeArrayAccessData(a, (void**)&ptr1);
543 ok(S_OK == hres, "SAAD failed with 0x%x\n", hres);
545 indices[0] = 3;
546 indices[1] = 23;
547 hres = SafeArrayPtrOfIndex(a, indices, (void**)&ptr2);
548 ok(S_OK == hres,"SAPOI failed [1,23], hres 0x%x\n",hres);
549 diff = ptr2 - ptr1;
550 ok(diff == 8,"ptr difference is not 8, but %d (%p vs %p)\n", diff, ptr2, ptr1);
552 indices[0] = 3;
553 indices[1] = 24;
554 hres = SafeArrayPtrOfIndex(a, indices, (void**)&ptr2);
555 ok(S_OK == hres,"SAPOI failed [5,24], hres 0x%x\n",hres);
556 diff = ptr2 - ptr1;
557 ok(diff == 176,"ptr difference is not 176, but %d (%p vs %p)\n", diff, ptr2, ptr1);
559 indices[0] = 20;
560 indices[1] = 23;
561 hres = SafeArrayPtrOfIndex(a, indices, (void**)&ptr2);
562 ok(S_OK == hres,"SAPOI failed [20,23], hres 0x%x\n",hres);
563 diff = ptr2 - ptr1;
564 ok(diff == 76,"ptr difference is not 76, but %d (%p vs %p)\n", diff, ptr2, ptr1);
566 hres = SafeArrayUnaccessData(a);
567 ok(S_OK == hres, "SAUAD failed with 0x%x\n", hres);
569 hres = SafeArrayDestroy(a);
570 ok(hres == S_OK,"SAD failed with hres %x\n", hres);
572 for (i=0;i<sizeof(vttypes)/sizeof(vttypes[0]);i++) {
573 if ((i == VT_I8 || i == VT_UI8) && has_i8)
575 vttypes[i].elemsize = sizeof(LONG64);
578 a = SafeArrayCreate(vttypes[i].vt, 1, &bound);
580 ok((!a && !vttypes[i].elemsize) ||
581 (a && vttypes[i].elemsize == a->cbElements),
582 "SAC(%d,1,[1,0]), %p result %d, expected %d\n",
583 vttypes[i].vt,a,(a?a->cbElements:0),vttypes[i].elemsize);
585 if (a)
587 ok(a->fFeatures == (vttypes[i].expflags | vttypes[i].addflags),
588 "SAC of %d returned feature flags %x, expected %x\n",
589 vttypes[i].vt, a->fFeatures,
590 vttypes[i].expflags|vttypes[i].addflags);
591 ok(SafeArrayGetElemsize(a) == vttypes[i].elemsize,
592 "SAGE for vt %d returned elemsize %d instead of expected %d\n",
593 vttypes[i].vt, SafeArrayGetElemsize(a),vttypes[i].elemsize);
596 if (!a) continue;
598 if (pSafeArrayGetVartype)
600 hres = pSafeArrayGetVartype(a, &vt);
601 ok(hres == S_OK, "SAGVT of arra y with vt %d failed with %x\n", vttypes[i].vt, hres);
602 /* Windows prior to Vista returns VT_UNKNOWN instead of VT_DISPATCH */
603 ok(broken(vt == VT_UNKNOWN) || vt == vttypes[i].vt, "SAGVT of array with vt %d returned %d\n", vttypes[i].vt, vt);
606 hres = SafeArrayCopy(a, &c);
607 ok(hres == S_OK, "failed to copy safearray of vt %d with hres %x\n", vttypes[i].vt, hres);
609 ok(vttypes[i].elemsize == c->cbElements,"copy of SAC(%d,1,[1,0]), result %d, expected %d\n",vttypes[i].vt,(c?c->cbElements:0),vttypes[i].elemsize
611 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);
612 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);
614 if (pSafeArrayGetVartype) {
615 hres = pSafeArrayGetVartype(c, &vt);
616 ok(hres == S_OK, "SAGVT of array with vt %d failed with %x\n", vttypes[i].vt, hres);
617 /* Windows prior to Vista returns VT_UNKNOWN instead of VT_DISPATCH */
618 ok(broken(vt == VT_UNKNOWN) || vt == vttypes[i].vt, "SAGVT of array with vt %d returned %d\n", vttypes[i].vt, vt);
621 if (pSafeArrayCopyData) {
622 hres = pSafeArrayCopyData(a, c);
623 ok(hres == S_OK, "failed to copy safearray data of vt %d with hres %x\n", vttypes[i].vt, hres);
625 hres = SafeArrayDestroyData(c);
626 ok(hres == S_OK,"SADD of copy of array with vt %d failed with hres %x\n", vttypes[i].vt, hres);
629 hres = SafeArrayDestroy(c);
630 ok(hres == S_OK,"SAD failed with hres %x\n", hres);
632 hres = SafeArrayDestroy(a);
633 ok(hres == S_OK,"SAD of array with vt %d failed with hres %x\n", vttypes[i].vt, hres);
636 /* Test conversion of type|VT_ARRAY <-> VT_BSTR */
637 bound.lLbound = 0;
638 bound.cElements = 10;
639 a = SafeArrayCreate(VT_UI1, 1, &bound);
640 ok(a != NULL, "SAC failed.\n");
641 ok(S_OK == SafeArrayAccessData(a, &data),"SACD failed\n");
642 memcpy(data,"Hello World\n",10);
643 ok(S_OK == SafeArrayUnaccessData(a),"SAUD failed\n");
644 V_VT(&v) = VT_ARRAY|VT_UI1;
645 V_ARRAY(&v) = a;
646 hres = VariantChangeTypeEx(&v, &v, 0, 0, VT_BSTR);
647 ok(hres==S_OK, "CTE VT_ARRAY|VT_UI1 -> VT_BSTR failed with %x\n",hres);
648 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));
649 ok(V_BSTR(&v)[0] == 0x6548,"First letter are not 'He', but %x\n", V_BSTR(&v)[0]);
650 VariantClear(&v);
652 VariantInit(&d);
653 V_VT(&v) = VT_BSTR;
654 V_BSTR(&v) = SysAllocStringLen(NULL, 0);
655 hres = VariantChangeTypeEx(&d, &v, 0, 0, VT_UI1|VT_ARRAY);
656 ok(hres==S_OK, "CTE VT_BSTR -> VT_UI1|VT_ARRAY failed with %x\n",hres);
657 ok(V_VT(&d) == (VT_UI1|VT_ARRAY),"CTE BSTR -> VT_UI1|VT_ARRAY did not return VT_UI1|VT_ARRAY, but %d.v\n",V_VT(&v));
658 VariantClear(&v);
659 VariantClear(&d);
661 /* check locking functions */
662 a = SafeArrayCreate(VT_I4, 1, &bound);
663 ok(a!=NULL,"SAC should not fail\n");
665 hres = SafeArrayAccessData(a, &data);
666 ok(hres == S_OK,"SAAD failed with hres %x\n",hres);
668 hres = SafeArrayDestroy(a);
669 ok(hres == DISP_E_ARRAYISLOCKED,"locked safe array destroy not failed with DISP_E_ARRAYISLOCKED, but with hres %x\n", hres);
671 hres = SafeArrayDestroyData(a);
672 ok(hres == DISP_E_ARRAYISLOCKED,"locked safe array destroy data not failed with DISP_E_ARRAYISLOCKED, but with hres %x\n", hres);
674 hres = SafeArrayDestroyDescriptor(a);
675 ok(hres == DISP_E_ARRAYISLOCKED,"locked safe array destroy descriptor not failed with DISP_E_ARRAYISLOCKED, but with hres %x\n", hres);
677 hres = SafeArrayUnaccessData(a);
678 ok(hres == S_OK,"SAUD failed after lock/destroy test\n");
680 hres = SafeArrayDestroy(a);
681 ok(hres == S_OK,"SAD failed after lock/destroy test\n");
683 /* Test if we need to destroy data before descriptor */
684 a = SafeArrayCreate(VT_I4, 1, &bound);
685 ok(a!=NULL,"SAC should not fail\n");
686 hres = SafeArrayDestroyDescriptor(a);
687 ok(hres == S_OK,"SADD with data in array failed with hres %x\n",hres);
689 /* IID functions */
690 /* init a small stack safearray */
691 if (pSafeArraySetIID) {
692 memset(&b, 0, sizeof(b));
693 b.cDims = 1;
694 memset(&iid, 0x42, sizeof(IID));
695 hres = pSafeArraySetIID(&b,&iid);
696 ok(hres == E_INVALIDARG,"SafeArraySetIID of non IID capable safearray did not return E_INVALIDARG, but %x\n",hres);
698 hres = SafeArrayAllocDescriptor(1,&a);
699 ok(hres == S_OK,"SafeArrayAllocDescriptor should return S_OK, but got %x\n",hres);
700 ok((a->fFeatures & FADF_HAVEIID) == 0,"newly allocated descriptor with SAAD should not have FADF_HAVEIID\n");
701 hres = pSafeArraySetIID(a,&iid);
702 ok(hres == E_INVALIDARG,"SafeArraySetIID of newly allocated descriptor with SAAD should return E_INVALIDARG, but got %x\n",hres);
704 hres = SafeArrayDestroyDescriptor(a);
705 ok(hres == S_OK,"SADD failed with hres %x\n",hres);
708 if (!pSafeArrayAllocDescriptorEx)
709 return;
711 for (i=0;i<sizeof(vttypes)/sizeof(vttypes[0]);i++) {
712 a = NULL;
713 hres = pSafeArrayAllocDescriptorEx(vttypes[i].vt,1,&a);
714 ok(hres == S_OK, "SafeArrayAllocDescriptorEx gave hres 0x%x\n", hres);
715 ok(a->fFeatures == vttypes[i].expflags,"SAADE(%d) resulted with flags %x, expected %x\n", vttypes[i].vt, a->fFeatures, vttypes[i].expflags);
716 if (a->fFeatures & FADF_HAVEIID) {
717 hres = pSafeArrayGetIID(a, &iid);
718 ok(hres == S_OK,"SAGIID failed for vt %d with hres %x\n", vttypes[i].vt,hres);
719 switch (vttypes[i].vt) {
720 case VT_UNKNOWN:
721 ok(IsEqualGUID(((GUID*)a)-1,&IID_IUnknown),"guid for VT_UNKNOWN is not IID_IUnknown\n");
722 ok(IsEqualGUID(&iid, &IID_IUnknown),"SAGIID returned wrong GUID for IUnknown\n");
723 break;
724 case VT_DISPATCH:
725 ok(IsEqualGUID(((GUID*)a)-1,&IID_IDispatch),"guid for VT_UNKNOWN is not IID_IDispatch\n");
726 ok(IsEqualGUID(&iid, &IID_IDispatch),"SAGIID returned wrong GUID for IDispatch\n");
727 break;
728 default:
729 ok(FALSE,"unknown vt %d with FADF_HAVEIID\n",vttypes[i].vt);
730 break;
732 } else {
733 hres = pSafeArrayGetIID(a, &iid);
734 ok(hres == E_INVALIDARG,"SAGIID did not fail for vt %d with hres %x\n", vttypes[i].vt,hres);
736 if (a->fFeatures & FADF_RECORD) {
737 ok(vttypes[i].vt == VT_RECORD,"FADF_RECORD for non record %d\n",vttypes[i].vt);
739 if (a->fFeatures & FADF_HAVEVARTYPE) {
740 ok(vttypes[i].vt == ((DWORD*)a)[-1], "FADF_HAVEVARTYPE set, but vt %d mismatch stored %d\n",vttypes[i].vt,((DWORD*)a)[-1]);
743 hres = pSafeArrayGetVartype(a, &vt);
744 ok(hres == S_OK, "SAGVT of array with vt %d failed with %x\n", vttypes[i].vt, hres);
746 if (vttypes[i].vt == VT_DISPATCH) {
747 /* Special case. Checked against Windows. */
748 ok(vt == VT_UNKNOWN, "SAGVT of array with VT_DISPATCH returned not VT_UNKNOWN, but %d\n", vt);
749 } else {
750 ok(vt == vttypes[i].vt, "SAGVT of array with vt %d returned %d\n", vttypes[i].vt, vt);
753 if (a->fFeatures & FADF_HAVEIID) {
754 hres = pSafeArraySetIID(a, &IID_IStorage); /* random IID */
755 ok(hres == S_OK,"SASIID failed with FADF_HAVEIID set for vt %d with %x\n", vttypes[i].vt, hres);
756 hres = pSafeArrayGetIID(a, &iid);
757 ok(hres == S_OK,"SAGIID failed with FADF_HAVEIID set for vt %d with %x\n", vttypes[i].vt, hres);
758 ok(IsEqualGUID(&iid, &IID_IStorage),"returned iid is not IID_IStorage\n");
759 } else {
760 hres = pSafeArraySetIID(a, &IID_IStorage); /* random IID */
761 ok(hres == E_INVALIDARG,"SASIID did not failed with !FADF_HAVEIID set for vt %d with %x\n", vttypes[i].vt, hres);
763 hres = SafeArrayDestroyDescriptor(a);
764 ok(hres == S_OK,"SADD failed with hres %x\n",hres);
768 static void test_SafeArrayAllocDestroyDescriptor(void)
770 SAFEARRAY *sa;
771 HRESULT hres;
772 int i;
774 /* Failure cases */
775 hres = SafeArrayAllocDescriptor(0, &sa);
776 ok(hres == E_INVALIDARG, "0 dimensions gave hres 0x%x\n", hres);
778 hres = SafeArrayAllocDescriptor(65536, &sa);
779 ok(hres == E_INVALIDARG, "65536 dimensions gave hres 0x%x\n", hres);
781 if (0)
783 /* Crashes on 95: XP & Wine return E_POINTER */
784 hres=SafeArrayAllocDescriptor(1, NULL);
785 ok(hres == E_POINTER,"NULL parm gave hres 0x%x\n", hres);
788 /* Test up to the dimension boundary case */
789 for (i = 5; i <= 65535; i += 30)
791 hres = SafeArrayAllocDescriptor(i, &sa);
792 ok(hres == S_OK, "%d dimensions failed; hres 0x%x\n", i, hres);
794 if (hres == S_OK)
796 ok(SafeArrayGetDim(sa) == (UINT)i, "Dimension is %d; should be %d\n",
797 SafeArrayGetDim(sa), i);
799 hres = SafeArrayDestroyDescriptor(sa);
800 ok(hres == S_OK, "destroy failed; hres 0x%x\n", hres);
804 if (!pSafeArrayAllocDescriptorEx)
805 return;
807 hres = pSafeArrayAllocDescriptorEx(VT_UI1, 0, &sa);
808 ok(hres == E_INVALIDARG, "0 dimensions gave hres 0x%x\n", hres);
810 hres = pSafeArrayAllocDescriptorEx(VT_UI1, 65536, &sa);
811 ok(hres == E_INVALIDARG, "65536 dimensions gave hres 0x%x\n", hres);
813 hres = pSafeArrayAllocDescriptorEx(VT_UI1, 1, NULL);
814 ok(hres == E_POINTER,"NULL parm gave hres 0x%x\n", hres);
816 hres = pSafeArrayAllocDescriptorEx(-1, 1, &sa);
817 ok(hres == S_OK, "VT = -1 gave hres 0x%x\n", hres);
819 sa->rgsabound[0].cElements = 0;
820 sa->rgsabound[0].lLbound = 1;
822 hres = SafeArrayAllocData(sa);
823 ok(hres == S_OK, "SafeArrayAllocData gave hres 0x%x\n", hres);
825 hres = SafeArrayDestroy(sa);
826 ok(hres == S_OK,"SafeArrayDestroy failed with hres %x\n",hres);
829 static void test_SafeArrayCreateLockDestroy(void)
831 SAFEARRAYBOUND sab[4];
832 SAFEARRAY *sa;
833 HRESULT hres;
834 VARTYPE vt;
835 int dimension;
837 #define NUM_DIMENSIONS (int)(sizeof(sab) / sizeof(sab[0]))
839 for (dimension = 0; dimension < NUM_DIMENSIONS; dimension++)
841 sab[dimension].lLbound = 0;
842 sab[dimension].cElements = 8;
845 /* Failure cases */
846 /* This test crashes very early versions with no error checking...
847 sa = SafeArrayCreate(VT_UI1, 1, NULL);
848 ok(sa == NULL, "NULL bounds didn't fail\n");
850 sa = SafeArrayCreate(VT_UI1, 65536, sab);
851 ok(!sa, "Max bounds didn't fail\n");
853 memset(sab, 0, sizeof(sab));
855 /* Don't test 0 sized dimensions, as Windows has a bug which allows this */
857 for (dimension = 0; dimension < NUM_DIMENSIONS; dimension++)
858 sab[dimension].cElements = 8;
860 /* Test all VARTYPES in 1-4 dimensions */
861 for (dimension = 1; dimension < 4; dimension++)
863 for (vt = VT_EMPTY; vt < VT_CLSID; vt++)
865 DWORD dwLen = SAFEARRAY_GetVTSize(vt);
867 sa = SafeArrayCreate(vt, dimension, sab);
869 if (dwLen)
870 ok(sa != NULL, "VARTYPE %d (@%d dimensions) failed\n", vt, dimension);
871 else
872 ok(sa == NULL || vt == VT_R8,
873 "VARTYPE %d (@%d dimensions) succeeded!\n", vt, dimension);
875 if (sa)
877 ok(SafeArrayGetDim(sa) == (UINT)dimension,
878 "VARTYPE %d (@%d dimensions) cDims is %d, expected %d\n",
879 vt, dimension, SafeArrayGetDim(sa), dimension);
880 ok(SafeArrayGetElemsize(sa) == dwLen || vt == VT_R8,
881 "VARTYPE %d (@%d dimensions) cbElements is %d, expected %d\n",
882 vt, dimension, SafeArrayGetElemsize(sa), dwLen);
884 if (vt != VT_UNKNOWN && vt != VT_DISPATCH)
886 ok((sa->fFeatures & FADF_HAVEIID) == 0,
887 "Non interface type should not have FADF_HAVEIID\n");
888 if (pSafeArraySetIID)
890 hres = pSafeArraySetIID(sa, &IID_IUnknown);
891 ok(hres == E_INVALIDARG,
892 "Non interface type allowed SetIID(), hres %x\n", hres);
894 if (vt != VT_RECORD)
896 VARTYPE aVt;
898 ok(sa->fFeatures & FADF_HAVEVARTYPE,
899 "Non interface type should have FADF_HAVEVARTYPE\n");
900 if (pSafeArrayGetVartype)
902 hres = pSafeArrayGetVartype(sa, &aVt);
903 ok(hres == S_OK && aVt == vt,
904 "Non interface type %d: bad type %d, hres %x\n", vt, aVt, hres);
908 else
910 ok(sa->fFeatures & FADF_HAVEIID, "Interface type should have FADF_HAVEIID\n");
911 if (pSafeArraySetIID)
913 hres = pSafeArraySetIID(sa, &IID_IUnknown);
914 ok(hres == S_OK,
915 "Non interface type disallowed SetIID(), hres %x\n", hres);
917 ok((sa->fFeatures & FADF_HAVEVARTYPE) == 0,
918 "Interface type %d should not have FADF_HAVEVARTYPE\n", vt);
921 hres = SafeArrayLock(sa);
922 ok(hres == S_OK, "Lock VARTYPE %d (@%d dimensions) failed; hres 0x%x\n",
923 vt, dimension, hres);
925 if (hres == S_OK)
927 hres = SafeArrayDestroy(sa);
928 ok(hres == DISP_E_ARRAYISLOCKED,"Destroy() got hres %x\n", hres);
930 hres = SafeArrayDestroyData(sa);
931 ok(hres == DISP_E_ARRAYISLOCKED,"DestroyData() got hres %x\n", hres);
933 hres = SafeArrayDestroyDescriptor(sa);
934 ok(hres == DISP_E_ARRAYISLOCKED,"DestroyDescriptor() got hres %x\n", hres);
936 hres = SafeArrayUnlock(sa);
937 ok(hres == S_OK, "Unlock VARTYPE %d (@%d dims) hres 0x%x\n",
938 vt, dimension, hres);
940 hres = SafeArrayDestroy(sa);
941 ok(hres == S_OK, "destroy VARTYPE %d (@%d dims) hres 0x%x\n",
942 vt, dimension, hres);
949 static void test_VectorCreateLockDestroy(void)
951 SAFEARRAY *sa;
952 HRESULT hres;
953 VARTYPE vt;
954 int element;
956 if (!pSafeArrayCreateVector)
958 win_skip("SafeArrayCreateVector not supported\n");
959 return;
961 sa = pSafeArrayCreateVector(VT_UI1, 0, 0);
962 ok(sa != NULL, "SACV with 0 elements failed.\n");
964 hres = SafeArrayDestroy(sa);
965 ok(hres == S_OK, "SafeArrayDestroy failed with hres %x\n",hres);
967 /* Test all VARTYPES in different lengths */
968 for (element = 1; element <= 101; element += 10)
970 for (vt = VT_EMPTY; vt < VT_CLSID; vt++)
972 DWORD dwLen = SAFEARRAY_GetVTSize(vt);
974 sa = pSafeArrayCreateVector(vt, 0, element);
976 if (dwLen)
977 ok(sa != NULL, "VARTYPE %d (@%d elements) failed\n", vt, element);
978 else
979 ok(sa == NULL, "VARTYPE %d (@%d elements) succeeded!\n", vt, element);
981 if (sa)
983 ok(SafeArrayGetDim(sa) == 1, "VARTYPE %d (@%d elements) cDims %d, not 1\n",
984 vt, element, SafeArrayGetDim(sa));
985 ok(SafeArrayGetElemsize(sa) == dwLen,
986 "VARTYPE %d (@%d elements) cbElements is %d, expected %d\n",
987 vt, element, SafeArrayGetElemsize(sa), dwLen);
989 hres = SafeArrayLock(sa);
990 ok(hres == S_OK, "Lock VARTYPE %d (@%d elements) failed; hres 0x%x\n",
991 vt, element, hres);
993 if (hres == S_OK)
995 hres = SafeArrayUnlock(sa);
996 ok(hres == S_OK, "Unlock VARTYPE %d (@%d elements) failed; hres 0x%x\n",
997 vt, element, hres);
999 hres = SafeArrayDestroy(sa);
1000 ok(hres == S_OK, "destroy VARTYPE %d (@%d elements) failed; hres 0x%x\n",
1001 vt, element, hres);
1008 static void test_LockUnlock(void)
1010 SAFEARRAYBOUND sab[4];
1011 SAFEARRAY *sa;
1012 HRESULT hres;
1013 BOOL bVector = FALSE;
1014 int dimension;
1016 /* Failure cases */
1017 hres = SafeArrayLock(NULL);
1018 ok(hres == E_INVALIDARG, "Lock NULL array hres 0x%x\n", hres);
1019 hres = SafeArrayUnlock(NULL);
1020 ok(hres == E_INVALIDARG, "Lock NULL array hres 0x%x\n", hres);
1022 for (dimension = 0; dimension < NUM_DIMENSIONS; dimension++)
1024 sab[dimension].lLbound = 0;
1025 sab[dimension].cElements = 8;
1028 sa = SafeArrayCreate(VT_UI1, NUM_DIMENSIONS, sab);
1030 /* Test maximum locks */
1031 test_LockUnlock_Vector:
1032 if (sa)
1034 int count = 0;
1036 hres = SafeArrayUnlock(sa);
1037 ok (hres == E_UNEXPECTED, "Bad %sUnlock gave hres 0x%x\n",
1038 bVector ? "vector " : "\n", hres);
1040 while ((hres = SafeArrayLock(sa)) == S_OK)
1041 count++;
1042 ok (count == 65535 && hres == E_UNEXPECTED, "Lock %sfailed at %d; hres 0x%x\n",
1043 bVector ? "vector " : "\n", count, hres);
1045 if (count == 65535 && hres == E_UNEXPECTED)
1047 while ((hres = SafeArrayUnlock(sa)) == S_OK)
1048 count--;
1049 ok (count == 0 && hres == E_UNEXPECTED, "Unlock %sfailed at %d; hres 0x%x\n",
1050 bVector ? "vector " : "\n", count, hres);
1053 hres = SafeArrayDestroy(sa);
1054 ok(hres == S_OK, "got 0x%08x\n", hres);
1057 if (bVector == FALSE && pSafeArrayCreateVector)
1059 /* Test again with a vector */
1060 sa = pSafeArrayCreateVector(VT_UI1, 0, 100);
1061 bVector = TRUE;
1062 goto test_LockUnlock_Vector;
1066 static void test_SafeArrayGetPutElement(void)
1068 SAFEARRAYBOUND sab[4];
1069 LONG indices[NUM_DIMENSIONS], index;
1070 SAFEARRAY *sa;
1071 HRESULT hres;
1072 int value = 0, gotvalue, dimension;
1073 IRecordInfoImpl *irec;
1074 unsigned int x,y,z,a;
1076 for (dimension = 0; dimension < NUM_DIMENSIONS; dimension++)
1078 sab[dimension].lLbound = dimension * 2 + 1;
1079 sab[dimension].cElements = dimension * 3 + 1;
1082 sa = SafeArrayCreate(VT_INT, NUM_DIMENSIONS, sab);
1083 if (!sa)
1084 return; /* Some early versions can't handle > 3 dims */
1086 ok(sa->cbElements == sizeof(value), "int size mismatch\n");
1088 /* Failure cases */
1089 for (x = 0; x < NUM_DIMENSIONS; x++)
1091 indices[0] = sab[0].lLbound;
1092 indices[1] = sab[1].lLbound;
1093 indices[2] = sab[2].lLbound;
1094 indices[3] = sab[3].lLbound;
1096 indices[x] = indices[x] - 1;
1097 hres = SafeArrayPutElement(sa, indices, &value);
1098 ok(hres == DISP_E_BADINDEX, "Put allowed too small index in dimension %d\n", x);
1099 hres = SafeArrayGetElement(sa, indices, &value);
1100 ok(hres == DISP_E_BADINDEX, "Get allowed too small index in dimension %d\n", x);
1102 indices[x] = sab[x].lLbound + sab[x].cElements;
1103 hres = SafeArrayPutElement(sa, indices, &value);
1104 ok(hres == DISP_E_BADINDEX, "Put allowed too big index in dimension %d\n", x);
1105 hres = SafeArrayGetElement(sa, indices, &value);
1106 ok(hres == DISP_E_BADINDEX, "Get allowed too big index in dimension %d\n", x);
1109 indices[0] = sab[0].lLbound;
1110 indices[1] = sab[1].lLbound;
1111 indices[2] = sab[2].lLbound;
1112 indices[3] = sab[3].lLbound;
1114 hres = SafeArrayPutElement(NULL, indices, &value);
1115 ok(hres == E_INVALIDARG, "Put NULL array hres 0x%x\n", hres);
1116 hres = SafeArrayGetElement(NULL, indices, &value);
1117 ok(hres == E_INVALIDARG, "Get NULL array hres 0x%x\n", hres);
1119 hres = SafeArrayPutElement(sa, NULL, &value);
1120 ok(hres == E_INVALIDARG, "Put NULL indices hres 0x%x\n", hres);
1121 hres = SafeArrayGetElement(sa, NULL, &value);
1122 ok(hres == E_INVALIDARG, "Get NULL indices hres 0x%x\n", hres);
1124 if (0)
1126 /* This is retarded. Windows checks every case of invalid parameters
1127 * except the following, which crashes. We ERR this in Wine.
1129 hres = SafeArrayPutElement(sa, indices, NULL);
1130 ok(hres == E_INVALIDARG, "Put NULL value hres 0x%x\n", hres);
1133 hres = SafeArrayGetElement(sa, indices, NULL);
1134 ok(hres == E_INVALIDARG, "Get NULL value hres 0x%x\n", hres);
1136 value = 0;
1138 /* Make sure we can read and get back the correct values in 4 dimensions,
1139 * Each with a different size and lower bound.
1141 for (x = 0; x < sab[0].cElements; x++)
1143 indices[0] = sab[0].lLbound + x;
1144 for (y = 0; y < sab[1].cElements; y++)
1146 indices[1] = sab[1].lLbound + y;
1147 for (z = 0; z < sab[2].cElements; z++)
1149 indices[2] = sab[2].lLbound + z;
1150 for (a = 0; a < sab[3].cElements; a++)
1152 indices[3] = sab[3].lLbound + a;
1153 hres = SafeArrayPutElement(sa, indices, &value);
1154 ok(hres == S_OK, "Failed to put element at (%d,%d,%d,%d) hres 0x%x\n",
1155 x, y, z, a, hres);
1156 value++;
1162 value = 0;
1164 for (x = 0; x < sab[0].cElements; x++)
1166 indices[0] = sab[0].lLbound + x;
1167 for (y = 0; y < sab[1].cElements; y++)
1169 indices[1] = sab[1].lLbound + y;
1170 for (z = 0; z < sab[2].cElements; z++)
1172 indices[2] = sab[2].lLbound + z;
1173 for (a = 0; a < sab[3].cElements; a++)
1175 indices[3] = sab[3].lLbound + a;
1176 gotvalue = value / 3;
1177 hres = SafeArrayGetElement(sa, indices, &gotvalue);
1178 ok(hres == S_OK, "Failed to get element at (%d,%d,%d,%d) hres 0x%x\n",
1179 x, y, z, a, hres);
1180 if (hres == S_OK)
1181 ok(value == gotvalue, "Got value %d instead of %d at (%d,%d,%d,%d)\n",
1182 gotvalue, value, x, y, z, a);
1183 value++;
1188 hres = SafeArrayDestroy(sa);
1189 ok(hres == S_OK, "got 0x%08x\n", hres);
1191 /* VT_RECORD array */
1192 irec = IRecordInfoImpl_Construct();
1193 irec->ref = 1;
1195 sab[0].lLbound = 0;
1196 sab[0].cElements = 8;
1198 sa = pSafeArrayCreateEx(VT_RECORD, 1, sab, &irec->IRecordInfo_iface);
1199 ok(sa != NULL, "failed to create array\n");
1200 ok(irec->ref == 2, "got %d\n", irec->ref);
1202 index = 0;
1203 irec->recordcopy = 0;
1204 hres = SafeArrayPutElement(sa, &index, (void*)0xdeadbeef);
1205 ok(hres == S_OK, "got 0x%08x\n", hres);
1206 ok(irec->recordcopy == 1, "got %d\n", irec->recordcopy);
1208 index = 0;
1209 irec->recordcopy = 0;
1210 hres = SafeArrayGetElement(sa, &index, (void*)0xdeadbeef);
1211 ok(hres == S_OK, "got 0x%08x\n", hres);
1212 ok(irec->recordcopy == 1, "got %d\n", irec->recordcopy);
1214 hres = SafeArrayDestroy(sa);
1215 ok(hres == S_OK, "got 0x%08x\n", hres);
1216 ok(irec->ref == 1, "got %d\n", irec->ref);
1217 IRecordInfo_Release(&irec->IRecordInfo_iface);
1220 static void test_SafeArrayGetPutElement_BSTR(void)
1222 SAFEARRAYBOUND sab;
1223 LONG indices[1];
1224 SAFEARRAY *sa;
1225 HRESULT hres;
1226 BSTR value = 0, gotvalue;
1227 const OLECHAR szTest[5] = { 'T','e','s','t','\0' };
1229 sab.lLbound = 1;
1230 sab.cElements = 1;
1232 sa = SafeArrayCreate(VT_BSTR, 1, &sab);
1233 ok(sa != NULL, "BSTR test couldn't create array\n");
1234 if (!sa)
1235 return;
1237 ok(sa->cbElements == sizeof(BSTR), "BSTR size mismatch\n");
1239 indices[0] = sab.lLbound;
1240 value = SysAllocString(szTest);
1241 ok (value != NULL, "Expected non-NULL\n");
1242 hres = SafeArrayPutElement(sa, indices, value);
1243 ok(hres == S_OK, "Failed to put bstr element hres 0x%x\n", hres);
1244 gotvalue = NULL;
1245 hres = SafeArrayGetElement(sa, indices, &gotvalue);
1246 ok(hres == S_OK, "Failed to get bstr element at hres 0x%x\n", hres);
1247 if (hres == S_OK)
1248 ok(SysStringLen(value) == SysStringLen(gotvalue), "Got len %d instead of %d\n", SysStringLen(gotvalue), SysStringLen(value));
1249 hres = SafeArrayDestroy(sa);
1250 ok(hres == S_OK, "got 0x%08x\n", hres);
1251 SysFreeString(value);
1252 SysFreeString(gotvalue);
1255 struct xtunk_impl {
1256 IUnknown IUnknown_iface;
1257 LONG ref;
1259 static const IUnknownVtbl xtunk_vtbl;
1261 static struct xtunk_impl xtunk = {{&xtunk_vtbl}, 0};
1263 static HRESULT WINAPI tunk_QueryInterface(IUnknown *punk, REFIID riid, void **x)
1265 return E_FAIL;
1268 static ULONG WINAPI tunk_AddRef(IUnknown *punk)
1270 return ++xtunk.ref;
1273 static ULONG WINAPI tunk_Release(IUnknown *punk)
1275 return --xtunk.ref;
1278 static const IUnknownVtbl xtunk_vtbl = {
1279 tunk_QueryInterface,
1280 tunk_AddRef,
1281 tunk_Release
1284 static void test_SafeArrayGetPutElement_IUnknown(void)
1286 SAFEARRAYBOUND sab;
1287 LONG indices[1];
1288 SAFEARRAY *sa;
1289 HRESULT hres;
1290 IUnknown *gotvalue;
1292 sab.lLbound = 1;
1293 sab.cElements = 1;
1294 sa = SafeArrayCreate(VT_UNKNOWN, 1, &sab);
1295 ok(sa != NULL, "UNKNOWN test couldn't create array\n");
1296 if (!sa)
1297 return;
1299 ok(sa->cbElements == sizeof(LPUNKNOWN), "LPUNKNOWN size mismatch\n");
1301 indices[0] = sab.lLbound;
1302 xtunk.ref = 1;
1303 hres = SafeArrayPutElement(sa, indices, &xtunk.IUnknown_iface);
1304 ok(hres == S_OK, "Failed to put bstr element hres 0x%x\n", hres);
1305 ok(xtunk.ref == 2,"Failed to increment refcount of iface.\n");
1306 gotvalue = NULL;
1307 hres = SafeArrayGetElement(sa, indices, &gotvalue);
1308 ok(xtunk.ref == 3,"Failed to increment refcount of iface.\n");
1309 ok(hres == S_OK, "Failed to get bstr element at hres 0x%x\n", hres);
1310 if (hres == S_OK)
1311 ok(gotvalue == &xtunk.IUnknown_iface, "Got %p instead of %p\n", gotvalue, &xtunk.IUnknown_iface);
1312 hres = SafeArrayDestroy(sa);
1313 ok(hres == S_OK, "got 0x%08x\n", hres);
1314 ok(xtunk.ref == 2,"Failed to decrement refcount of iface.\n");
1317 static void test_SafeArrayRedim_IUnknown(void)
1319 SAFEARRAYBOUND sab;
1320 LONG indices[1];
1321 SAFEARRAY *sa;
1322 HRESULT hres;
1324 sab.lLbound = 1;
1325 sab.cElements = 2;
1326 sa = SafeArrayCreate(VT_UNKNOWN, 1, &sab);
1327 ok(sa != NULL, "UNKNOWN test couldn't create array\n");
1328 if (!sa)
1329 return;
1331 ok(sa->cbElements == sizeof(LPUNKNOWN), "LPUNKNOWN size mismatch\n");
1333 indices[0] = 2;
1334 xtunk.ref = 1;
1335 hres = SafeArrayPutElement(sa, indices, &xtunk.IUnknown_iface);
1336 ok(hres == S_OK, "Failed to put IUnknown element hres 0x%x\n", hres);
1337 ok(xtunk.ref == 2,"Failed to increment refcount of iface.\n");
1338 sab.cElements = 1;
1339 hres = SafeArrayRedim(sa, &sab);
1340 ok(hres == S_OK, "Failed to shrink array hres 0x%x\n", hres);
1341 ok(xtunk.ref == 1, "Failed to decrement refcount\n");
1342 hres = SafeArrayDestroy(sa);
1343 ok(hres == S_OK, "got 0x%08x\n", hres);
1346 static void test_SafeArrayGetPutElement_VARIANT(void)
1348 SAFEARRAYBOUND sab;
1349 LONG indices[1];
1350 SAFEARRAY *sa;
1351 HRESULT hres;
1352 VARIANT value, gotvalue;
1354 sab.lLbound = 1;
1355 sab.cElements = 1;
1356 sa = SafeArrayCreate(VT_VARIANT, 1, &sab);
1357 ok(sa != NULL, "VARIANT test couldn't create array\n");
1358 if (!sa)
1359 return;
1361 ok(sa->cbElements == sizeof(VARIANT), "VARIANT size mismatch\n");
1363 indices[0] = sab.lLbound;
1364 V_VT(&value) = VT_I4;
1365 V_I4(&value) = 0x42424242;
1366 hres = SafeArrayPutElement(sa, indices, &value);
1367 ok(hres == S_OK, "Failed to put Variant I4 element hres 0x%x\n", hres);
1369 V_VT(&gotvalue) = 0xdead;
1370 hres = SafeArrayGetElement(sa, indices, &gotvalue);
1371 ok(hres == S_OK, "Failed to get variant element at hres 0x%x\n", hres);
1373 V_VT(&gotvalue) = VT_EMPTY;
1374 hres = SafeArrayGetElement(sa, indices, &gotvalue);
1375 ok(hres == S_OK, "Failed to get variant element at hres 0x%x\n", hres);
1376 if (hres == S_OK) {
1377 ok(V_VT(&value) == V_VT(&gotvalue), "Got type 0x%x instead of 0x%x\n", V_VT(&value), V_VT(&gotvalue));
1378 if (V_VT(&value) == V_VT(&gotvalue))
1379 ok(V_I4(&value) == V_I4(&gotvalue), "Got %d instead of %d\n", V_I4(&value), V_VT(&gotvalue));
1381 hres = SafeArrayDestroy(sa);
1382 ok(hres == S_OK, "got 0x%08x\n", hres);
1385 static void test_SafeArrayCopyData(void)
1387 SAFEARRAYBOUND sab[4];
1388 SAFEARRAY *sa;
1389 SAFEARRAY *sacopy;
1390 HRESULT hres;
1391 int dimension, size = 1, i;
1393 if (!pSafeArrayCopyData)
1395 win_skip("SafeArrayCopyData not supported\n");
1396 return;
1399 for (dimension = 0; dimension < NUM_DIMENSIONS; dimension++)
1401 sab[dimension].lLbound = dimension * 2 + 2;
1402 sab[dimension].cElements = dimension * 3 + 1;
1403 size *= sab[dimension].cElements;
1406 sa = SafeArrayCreate(VT_INT, NUM_DIMENSIONS, sab);
1407 ok(sa != NULL, "Copy test couldn't create array\n");
1408 sacopy = SafeArrayCreate(VT_INT, NUM_DIMENSIONS, sab);
1409 ok(sacopy != NULL, "Copy test couldn't create copy array\n");
1411 if (!sa || !sacopy)
1412 return;
1414 ok(sa->cbElements == sizeof(int), "int size mismatch\n");
1416 /* Fill the source array with some data; it doesn't matter what */
1417 for (dimension = 0; dimension < size; dimension++)
1419 int* data = sa->pvData;
1420 data[dimension] = dimension;
1423 hres = pSafeArrayCopyData(sa, sacopy);
1424 ok(hres == S_OK, "copy data failed hres 0x%x\n", hres);
1425 if (hres == S_OK)
1427 ok(!memcmp(sa->pvData, sacopy->pvData, size * sizeof(int)), "compared different\n");
1430 /* Failure cases */
1431 hres = pSafeArrayCopyData(NULL, sacopy);
1432 ok(hres == E_INVALIDARG, "Null copy source hres 0x%x\n", hres);
1433 hres = pSafeArrayCopyData(sa, NULL);
1434 ok(hres == E_INVALIDARG, "Null copy hres 0x%x\n", hres);
1436 sacopy->rgsabound[0].cElements += 1;
1437 hres = pSafeArrayCopyData(sa, sacopy);
1438 ok(hres == E_INVALIDARG, "Bigger copy first dimension hres 0x%x\n", hres);
1440 sacopy->rgsabound[0].cElements -= 2;
1441 hres = pSafeArrayCopyData(sa, sacopy);
1442 ok(hres == E_INVALIDARG, "Smaller copy first dimension hres 0x%x\n", hres);
1443 sacopy->rgsabound[0].cElements += 1;
1445 sacopy->rgsabound[3].cElements += 1;
1446 hres = pSafeArrayCopyData(sa, sacopy);
1447 ok(hres == E_INVALIDARG, "Bigger copy last dimension hres 0x%x\n", hres);
1449 sacopy->rgsabound[3].cElements -= 2;
1450 hres = pSafeArrayCopyData(sa, sacopy);
1451 ok(hres == E_INVALIDARG, "Smaller copy last dimension hres 0x%x\n", hres);
1452 sacopy->rgsabound[3].cElements += 1;
1454 hres = SafeArrayDestroy(sacopy);
1455 ok(hres == S_OK, "got 0x%08x\n", hres);
1456 sacopy = NULL;
1457 hres = pSafeArrayCopyData(sa, sacopy);
1458 ok(hres == E_INVALIDARG, "->Null copy hres 0x%x\n", hres);
1460 hres = SafeArrayCopy(sa, &sacopy);
1461 ok(hres == S_OK, "copy failed hres 0x%x\n", hres);
1462 ok(SafeArrayGetElemsize(sa) == SafeArrayGetElemsize(sacopy),"elemsize wrong\n");
1463 ok(SafeArrayGetDim(sa) == SafeArrayGetDim(sacopy),"dimensions wrong\n");
1464 ok(!memcmp(sa->pvData, sacopy->pvData, size * sizeof(int)), "compared different\n");
1465 hres = SafeArrayDestroy(sacopy);
1466 ok(hres == S_OK, "got 0x%08x\n", hres);
1468 sacopy = SafeArrayCreate(VT_INT, NUM_DIMENSIONS, sab);
1469 ok(sacopy != NULL, "Copy test couldn't create copy array\n");
1470 ok(sacopy->fFeatures == FADF_HAVEVARTYPE, "0x%04x\n", sacopy->fFeatures);
1472 for (i = 0; i < sizeof(ignored_copy_features)/sizeof(USHORT); i++)
1474 USHORT feature = ignored_copy_features[i];
1475 USHORT orig = sacopy->fFeatures;
1477 sa->fFeatures |= feature;
1478 hres = SafeArrayCopyData(sa, sacopy);
1479 ok(hres == S_OK, "got 0x%08x\n", hres);
1480 ok(sacopy->fFeatures == orig && orig == FADF_HAVEVARTYPE, "got features 0x%04x\n", sacopy->fFeatures);
1481 sa->fFeatures &= ~feature;
1484 hres = SafeArrayDestroy(sacopy);
1485 ok(hres == S_OK, "got 0x%08x\n", hres);
1486 hres = SafeArrayDestroy(sa);
1487 ok(hres == S_OK, "got 0x%08x\n", hres);
1489 /* copy data from a vector */
1490 sa = SafeArrayCreateVector(VT_UI1, 0, 2);
1492 sacopy = SafeArrayCreateVector(VT_UI1, 0, 2);
1493 ok(sa->fFeatures == (FADF_HAVEVARTYPE|FADF_CREATEVECTOR) ||
1494 broken(sa->fFeatures == FADF_CREATEVECTOR /* W2k */),
1495 "got 0x%08x\n", sa->fFeatures);
1496 ok(sacopy->fFeatures == (FADF_HAVEVARTYPE|FADF_CREATEVECTOR) ||
1497 broken(sacopy->fFeatures == FADF_CREATEVECTOR /* W2k */),
1498 "got 0x%08x\n", sacopy->fFeatures);
1499 hres = SafeArrayCopyData(sa, sacopy);
1500 ok(hres == S_OK, "got 0x%08x\n", hres);
1501 ok(sacopy->fFeatures == (FADF_HAVEVARTYPE|FADF_CREATEVECTOR) ||
1502 broken(sacopy->fFeatures == FADF_CREATEVECTOR /* W2k */),
1503 "got 0x%04x\n", sacopy->fFeatures);
1504 SafeArrayDestroy(sacopy);
1506 sacopy = SafeArrayCreate(VT_UI1, NUM_DIMENSIONS, sab);
1507 ok(sacopy != NULL, "Copy test couldn't create copy array\n");
1508 ok(sacopy->fFeatures == FADF_HAVEVARTYPE, "0x%04x\n", sacopy->fFeatures);
1509 hres = SafeArrayCopyData(sa, sacopy);
1510 ok(hres == E_INVALIDARG, "got 0x%08x\n", hres);
1511 SafeArrayDestroy(sacopy);
1513 SafeArrayDestroy(sa);
1516 static void test_SafeArrayCreateEx(void)
1518 IRecordInfoImpl* iRec;
1519 SAFEARRAYBOUND sab[4];
1520 SAFEARRAY *sa;
1521 HRESULT hres;
1522 int dimension;
1524 if (!pSafeArrayCreateEx)
1526 win_skip("SafeArrayCreateEx not supported\n");
1527 return;
1530 for (dimension = 0; dimension < NUM_DIMENSIONS; dimension++)
1532 sab[dimension].lLbound = 0;
1533 sab[dimension].cElements = 8;
1536 /* Failure cases */
1537 sa = pSafeArrayCreateEx(VT_UI1, 1, NULL, NULL);
1538 ok(sa == NULL, "CreateEx NULL bounds didn't fail\n");
1540 /* test IID storage & defaulting */
1541 sa = pSafeArrayCreateEx(VT_DISPATCH, 1, sab, (PVOID)&IID_ITypeInfo);
1542 ok(sa != NULL, "CreateEx (ITypeInfo) failed\n");
1544 if (sa)
1546 GUID guid;
1547 if (pSafeArrayGetIID)
1549 hres = pSafeArrayGetIID(sa, &guid);
1550 ok(hres == S_OK, "CreateEx (ITypeInfo) no IID hres 0x%x\n", hres);
1551 if (hres == S_OK)
1553 ok(IsEqualGUID(&guid, &IID_ITypeInfo), "CreateEx (ITypeInfo) bad IID\n");
1556 if (pSafeArraySetIID)
1558 hres = pSafeArraySetIID(sa, &IID_IUnknown);
1559 ok(hres == S_OK, "Failed to set IID, hres = %8x\n", hres);
1560 if (hres == S_OK && pSafeArrayGetIID)
1562 hres = pSafeArrayGetIID(sa, &guid);
1563 ok(hres == S_OK && IsEqualGUID(&guid, &IID_IUnknown), "Set bad IID\n");
1566 hres = SafeArrayDestroy(sa);
1567 ok(hres == S_OK, "got 0x%08x\n", hres);
1570 sa = pSafeArrayCreateEx(VT_DISPATCH, 1, sab, NULL);
1571 ok(sa != NULL, "CreateEx (NULL) failed\n");
1573 if (sa)
1575 GUID guid;
1576 if (pSafeArrayGetIID)
1578 hres = pSafeArrayGetIID(sa, &guid);
1579 ok(hres == S_OK, "CreateEx (NULL) no IID hres 0x%x\n", hres);
1580 if (hres == S_OK)
1582 ok(IsEqualGUID(&guid, &IID_IDispatch), "CreateEx (NULL) bad IID\n");
1585 hres = SafeArrayDestroy(sa);
1586 ok(hres == S_OK, "got 0x%08x\n", hres);
1589 sa = pSafeArrayCreateEx(VT_UNKNOWN, 1, sab, NULL);
1590 ok(sa != NULL, "CreateEx (NULL-Unk) failed\n");
1592 if (sa)
1594 GUID guid;
1595 if (pSafeArrayGetIID)
1597 hres = pSafeArrayGetIID(sa, &guid);
1598 ok(hres == S_OK, "CreateEx (NULL-Unk) no IID hres 0x%x\n", hres);
1599 if (hres == S_OK)
1601 ok(IsEqualGUID(&guid, &IID_IUnknown), "CreateEx (NULL-Unk) bad IID\n");
1604 hres = SafeArrayDestroy(sa);
1605 ok(hres == S_OK, "got 0x%08x\n", hres);
1608 /* VT_RECORD failure case */
1609 sa = pSafeArrayCreateEx(VT_RECORD, 1, sab, NULL);
1610 ok(sa == NULL, "CreateEx (NULL-Rec) succeeded\n");
1612 iRec = IRecordInfoImpl_Construct();
1614 /* Win32 doesn't care if GetSize fails */
1615 fail_GetSize = TRUE;
1616 sa = pSafeArrayCreateEx(VT_RECORD, 1, sab, &iRec->IRecordInfo_iface);
1617 ok(sa != NULL, "CreateEx (Fail Size) failed\n");
1618 ok(iRec->ref == START_REF_COUNT + 1, "Wrong iRec refcount %d\n", iRec->ref);
1619 ok(iRec->sizeCalled == 1, "GetSize called %d times\n", iRec->sizeCalled);
1620 ok(iRec->clearCalled == 0, "Clear called %d times\n", iRec->clearCalled);
1621 if (sa)
1623 ok(sa->cbElements == RECORD_SIZE_FAIL, "Altered size to %d\n", sa->cbElements);
1624 hres = SafeArrayDestroy(sa);
1625 ok(hres == S_OK, "got 0x%08x\n", hres);
1626 ok(iRec->clearCalled == sab[0].cElements, "Destroy->Clear called %d times\n", iRec->clearCalled);
1627 ok(iRec->ref == START_REF_COUNT, "got %d, expected %d\n", iRec->ref, START_REF_COUNT);
1630 /* Test VT_RECORD array */
1631 fail_GetSize = FALSE;
1632 iRec->ref = START_REF_COUNT;
1633 iRec->sizeCalled = 0;
1634 iRec->clearCalled = 0;
1635 sa = pSafeArrayCreateEx(VT_RECORD, 1, sab, &iRec->IRecordInfo_iface);
1636 ok(sa != NULL, "CreateEx (Rec) failed\n");
1637 ok(iRec->ref == START_REF_COUNT + 1, "Wrong iRec refcount %d\n", iRec->ref);
1638 ok(iRec->sizeCalled == 1, "GetSize called %d times\n", iRec->sizeCalled);
1639 ok(iRec->clearCalled == 0, "Clear called %d times\n", iRec->clearCalled);
1640 if (sa && pSafeArrayGetRecordInfo)
1642 IRecordInfo* saRec = NULL;
1643 SAFEARRAY *sacopy;
1645 hres = pSafeArrayGetRecordInfo(sa, &saRec);
1646 ok(hres == S_OK,"GRI failed\n");
1647 ok(saRec == &iRec->IRecordInfo_iface, "Different saRec\n");
1648 ok(iRec->ref == START_REF_COUNT + 2, "Didn't AddRef %d\n", iRec->ref);
1649 IRecordInfo_Release(saRec);
1651 ok(sa->cbElements == RECORD_SIZE,"Elemsize is %d\n", sa->cbElements);
1653 /* try to copy record based arrays */
1654 sacopy = pSafeArrayCreateEx(VT_RECORD, 1, sab, &iRec->IRecordInfo_iface);
1655 iRec->recordcopy = 0;
1656 iRec->clearCalled = 0;
1657 /* array copy code doesn't explicitly clear a record */
1658 hres = SafeArrayCopyData(sa, sacopy);
1659 ok(hres == S_OK, "got 0x%08x\n", hres);
1660 ok(iRec->recordcopy == sab[0].cElements, "got %d\n", iRec->recordcopy);
1661 ok(iRec->clearCalled == 0, "got %d\n", iRec->clearCalled);
1663 hres = SafeArrayDestroy(sacopy);
1664 ok(hres == S_OK, "got 0x%08x\n", hres);
1666 iRec->clearCalled = 0;
1667 iRec->sizeCalled = 0;
1668 hres = SafeArrayDestroy(sa);
1669 ok(hres == S_OK, "got 0x%08x\n", hres);
1670 ok(iRec->sizeCalled == 0, "Destroy->GetSize called %d times\n", iRec->sizeCalled);
1671 ok(iRec->clearCalled == sab[0].cElements, "Destroy->Clear called %d times\n", iRec->clearCalled);
1672 ok(iRec->ref == START_REF_COUNT, "Wrong iRec refcount %d\n", iRec->ref);
1674 else
1676 hres = SafeArrayDestroy(sa);
1677 ok(hres == S_OK, "got 0x%08x\n", hres);
1680 IRecordInfo_Release(&iRec->IRecordInfo_iface);
1683 static void test_SafeArrayClear(void)
1685 SAFEARRAYBOUND sab;
1686 SAFEARRAY *sa;
1687 VARIANTARG v;
1688 HRESULT hres;
1690 sab.lLbound = 0;
1691 sab.cElements = 10;
1692 sa = SafeArrayCreate(VT_UI1, 1, &sab);
1693 ok(sa != NULL, "Create() failed.\n");
1694 if (!sa)
1695 return;
1697 /* Test clearing non-NULL variants containing arrays */
1698 V_VT(&v) = VT_ARRAY|VT_UI1;
1699 V_ARRAY(&v) = sa;
1700 hres = VariantClear(&v);
1701 ok(hres == S_OK && V_VT(&v) == VT_EMPTY, "VariantClear: hres 0x%x, Type %d\n", hres, V_VT(&v));
1702 ok(V_ARRAY(&v) == sa, "VariantClear: Overwrote value\n");
1704 sa = SafeArrayCreate(VT_UI1, 1, &sab);
1705 ok(sa != NULL, "Create() failed.\n");
1706 if (!sa)
1707 return;
1709 V_VT(&v) = VT_SAFEARRAY;
1710 V_ARRAY(&v) = sa;
1711 hres = VariantClear(&v);
1712 ok(hres == DISP_E_BADVARTYPE, "VariantClear: hres 0x%x\n", hres);
1714 V_VT(&v) = VT_SAFEARRAY|VT_BYREF;
1715 V_ARRAYREF(&v) = &sa;
1716 hres = VariantClear(&v);
1717 ok(hres == DISP_E_BADVARTYPE, "VariantClear: hres 0x%x\n", hres);
1719 hres = SafeArrayDestroy(sa);
1720 ok(hres == S_OK, "got 0x%08x\n", hres);
1723 static void test_SafeArrayCopy(void)
1725 SAFEARRAYBOUND sab;
1726 SAFEARRAY *sa, *sa2;
1727 VARIANTARG vSrc, vDst;
1728 HRESULT hres;
1729 int i;
1731 sab.lLbound = 0;
1732 sab.cElements = 10;
1733 sa = SafeArrayCreate(VT_UI1, 1, &sab);
1734 ok(sa != NULL, "Create() failed.\n");
1735 if (!sa)
1736 return;
1738 /* Test copying non-NULL variants containing arrays */
1739 V_VT(&vSrc) = (VT_ARRAY|VT_BYREF|VT_UI1);
1740 V_ARRAYREF(&vSrc) = &sa;
1741 V_VT(&vDst) = VT_EMPTY;
1743 hres = VariantCopy(&vDst, &vSrc);
1744 ok(hres == S_OK && V_VT(&vDst) == (VT_ARRAY|VT_BYREF|VT_UI1),
1745 "VariantCopy: hres 0x%x, Type %d\n", hres, V_VT(&vDst));
1746 ok(V_ARRAYREF(&vDst) == &sa, "VariantClear: Performed deep copy\n");
1748 V_VT(&vSrc) = (VT_ARRAY|VT_UI1);
1749 V_ARRAY(&vSrc) = sa;
1750 V_VT(&vDst) = VT_EMPTY;
1752 hres = VariantCopy(&vDst, &vSrc);
1753 ok(hres == S_OK && V_VT(&vDst) == (VT_ARRAY|VT_UI1),
1754 "VariantCopy: hres 0x%x, Type %d\n", hres, V_VT(&vDst));
1755 ok(V_ARRAY(&vDst) != sa, "VariantClear: Performed shallow copy\n");
1757 hres = SafeArrayDestroy(V_ARRAY(&vSrc));
1758 ok(hres == S_OK, "got 0x%08x\n", hres);
1759 hres = SafeArrayDestroy(V_ARRAY(&vDst));
1760 ok(hres == S_OK, "got 0x%08x\n", hres);
1762 hres = SafeArrayAllocDescriptor(1, &sa);
1763 ok(hres == S_OK, "SafeArrayAllocDescriptor failed with error 0x%08x\n", hres);
1765 sa->cbElements = 16;
1766 hres = SafeArrayCopy(sa, &sa2);
1767 ok(hres == S_OK, "SafeArrayCopy failed with error 0x%08x\n", hres);
1768 ok(sa != sa2, "SafeArrayCopy performed shallow copy\n");
1770 hres = SafeArrayDestroy(sa2);
1771 ok(hres == S_OK, "got 0x%08x\n", hres);
1772 hres = SafeArrayDestroy(sa);
1773 ok(hres == S_OK, "got 0x%08x\n", hres);
1775 sa2 = (void*)0xdeadbeef;
1776 hres = SafeArrayCopy(NULL, &sa2);
1777 ok(hres == S_OK, "SafeArrayCopy failed with error 0x%08x\n", hres);
1778 ok(!sa2, "SafeArrayCopy didn't return NULL for output array\n");
1780 hres = SafeArrayAllocDescriptor(1, &sa);
1781 ok(hres == S_OK, "SafeArrayAllocDescriptor failed with error 0x%08x\n", hres);
1783 sa2 = (void*)0xdeadbeef;
1784 hres = SafeArrayCopy(sa, &sa2);
1785 ok(hres == E_INVALIDARG,
1786 "SafeArrayCopy with empty array should have failed with error E_INVALIDARG instead of 0x%08x\n",
1787 hres);
1788 ok(!sa2, "SafeArrayCopy didn't return NULL for output array\n");
1790 hres = SafeArrayDestroy(sa2);
1791 ok(hres == S_OK, "got 0x%08x\n", hres);
1792 hres = SafeArrayDestroy(sa);
1793 ok(hres == S_OK, "got 0x%08x\n", hres);
1795 /* test feature copy */
1796 hres = SafeArrayAllocDescriptor(1, &sa);
1797 ok(hres == S_OK, "SafeArrayAllocDescriptor failed with error 0x%08x\n", hres);
1798 ok(sa->fFeatures == 0, "got src features 0x%04x\n", sa->fFeatures);
1799 sa->cbElements = 16;
1801 for (i = 0; i < sizeof(ignored_copy_features)/sizeof(USHORT); i++)
1803 USHORT feature = ignored_copy_features[i];
1805 sa->fFeatures |= feature;
1806 hres = SafeArrayCopy(sa, &sa2);
1807 ok(hres == S_OK, "got 0x%08x\n", hres);
1808 ok(sa2->fFeatures == 0, "got features 0x%04x\n", sa2->fFeatures);
1809 hres = SafeArrayDestroy(sa2);
1810 ok(hres == S_OK, "got 0x%08x\n", hres);
1811 sa->fFeatures &= ~feature;
1814 SafeArrayDestroy(sa);
1816 /* copy from a vector */
1817 sa = SafeArrayCreateVector(VT_UI1, 0, 2);
1818 ok(sa->fFeatures == (FADF_HAVEVARTYPE|FADF_CREATEVECTOR) ||
1819 broken(sa->fFeatures == FADF_CREATEVECTOR /* W2k */),
1820 "got 0x%08x\n", sa->fFeatures);
1821 hres = SafeArrayCopy(sa, &sa2);
1822 ok(hres == S_OK, "got 0x%08x\n", hres);
1823 ok(sa2->fFeatures == FADF_HAVEVARTYPE ||
1824 broken(!sa2->fFeatures /* W2k */), "got 0x%04x\n",
1825 sa2->fFeatures);
1827 SafeArrayDestroy(sa2);
1828 SafeArrayDestroy(sa);
1831 #define MKARRAY(low,num,typ) sab.lLbound = low; sab.cElements = num; \
1832 sa = SafeArrayCreate(typ, 1, &sab); ok(sa != NULL, "Create() failed.\n"); \
1833 if (!sa) return; \
1834 V_VT(&v) = VT_ARRAY|typ; V_ARRAY(&v) = sa; VariantInit(&v2)
1836 #define MKARRAYCONT(low,num,typ) sab.lLbound = low; sab.cElements = num; \
1837 sa = SafeArrayCreate(typ, 1, &sab); if (!sa) continue; \
1838 V_VT(&v) = VT_ARRAY|typ; V_ARRAY(&v) = sa; VariantInit(&v2)
1840 static void test_SafeArrayChangeTypeEx(void)
1842 static const char *szHello = "Hello World";
1843 SAFEARRAYBOUND sab;
1844 SAFEARRAY *sa;
1845 VARIANTARG v,v2;
1846 VARTYPE vt;
1847 HRESULT hres;
1849 /* VT_ARRAY|VT_UI1 -> VT_BSTR */
1850 MKARRAY(0,strlen(szHello)+1,VT_UI1);
1851 memcpy(sa->pvData, szHello, strlen(szHello)+1);
1853 hres = VariantChangeTypeEx(&v2, &v, 0, 0, VT_BSTR);
1854 ok(hres == S_OK, "CTE VT_ARRAY|VT_UI1 -> VT_BSTR failed with %x\n", hres);
1855 if (hres == S_OK)
1857 ok(V_VT(&v2) == VT_BSTR, "CTE VT_ARRAY|VT_UI1 -> VT_BSTR did not return VT_BSTR, but %d.\n",V_VT(&v2));
1858 ok(strcmp((char*)V_BSTR(&v2),szHello) == 0,"Expected string '%s', got '%s'\n", szHello,
1859 (char*)V_BSTR(&v2));
1860 VariantClear(&v2);
1863 /* VT_VECTOR|VT_UI1 -> VT_BSTR */
1864 hres = SafeArrayDestroy(sa);
1865 ok(hres == S_OK, "got 0x%08x\n", hres);
1866 if (pSafeArrayCreateVector)
1868 sa = pSafeArrayCreateVector(VT_UI1, 0, strlen(szHello)+1);
1869 ok(sa != NULL, "CreateVector() failed.\n");
1870 if (!sa)
1871 return;
1873 memcpy(sa->pvData, szHello, strlen(szHello)+1);
1874 V_VT(&v) = VT_VECTOR|VT_UI1;
1875 V_ARRAY(&v) = sa;
1876 VariantInit(&v2);
1878 hres = VariantChangeTypeEx(&v2, &v, 0, 0, VT_BSTR);
1879 ok(hres == DISP_E_BADVARTYPE, "CTE VT_VECTOR|VT_UI1 returned %x\n", hres);
1881 /* (vector)VT_ARRAY|VT_UI1 -> VT_BSTR (In place) */
1882 V_VT(&v) = VT_ARRAY|VT_UI1;
1883 hres = VariantChangeTypeEx(&v, &v, 0, 0, VT_BSTR);
1884 ok(hres == S_OK, "CTE VT_ARRAY|VT_UI1 -> VT_BSTR failed with %x\n", hres);
1885 if (hres == S_OK)
1887 ok(V_VT(&v) == VT_BSTR, "CTE VT_ARRAY|VT_UI1 -> VT_BSTR did not return VT_BSTR, but %d.\n",V_VT(&v));
1888 ok(strcmp((char*)V_BSTR(&v),szHello) == 0,"Expected string '%s', got '%s'\n", szHello,
1889 (char*)V_BSTR(&v));
1890 VariantClear(&v);
1894 /* To/from BSTR only works with arrays of VT_UI1 */
1895 for (vt = VT_EMPTY; vt <= VT_CLSID; vt++)
1897 if (vt == VT_UI1)
1898 continue;
1900 sab.lLbound = 0;
1901 sab.cElements = 1;
1902 sa = SafeArrayCreate(vt, 1, &sab);
1903 if (!sa) continue;
1905 V_VT(&v) = VT_ARRAY|vt;
1906 V_ARRAY(&v) = sa;
1907 VariantInit(&v2);
1909 hres = VariantChangeTypeEx(&v2, &v, 0, 0, VT_BSTR);
1910 if (vt == VT_INT_PTR || vt == VT_UINT_PTR)
1912 ok(hres == DISP_E_BADVARTYPE, "expected DISP_E_BADVARTYPE, got 0x%08x\n", hres);
1913 SafeArrayDestroy(sa);
1915 else
1917 ok(hres == DISP_E_TYPEMISMATCH, "got 0x%08x for vt=%d, instead of DISP_E_TYPEMISMATCH\n", hres, vt);
1918 hres = VariantClear(&v);
1919 ok(hres == S_OK, "expected S_OK, got 0x%08x\n", hres);
1921 VariantClear(&v2);
1924 /* Can't change an array of one type into array of another type , even
1925 * if the other type is the same size
1927 if (pSafeArrayCreateVector)
1929 sa = pSafeArrayCreateVector(VT_UI1, 0, 1);
1930 ok(sa != NULL, "CreateVector() failed.\n");
1931 if (!sa)
1932 return;
1934 V_VT(&v) = VT_ARRAY|VT_UI1;
1935 V_ARRAY(&v) = sa;
1936 hres = VariantChangeTypeEx(&v2, &v, 0, 0, VT_ARRAY|VT_I1);
1937 ok(hres == DISP_E_TYPEMISMATCH, "CTE VT_ARRAY|VT_UI1->VT_ARRAY|VT_I1 returned %x\n", hres);
1939 /* But can change to the same array type */
1940 hres = SafeArrayDestroy(sa);
1941 ok(hres == S_OK, "got 0x%08x\n", hres);
1942 sa = pSafeArrayCreateVector(VT_UI1, 0, 1);
1943 ok(sa != NULL, "CreateVector() failed.\n");
1944 if (!sa)
1945 return;
1946 V_VT(&v) = VT_ARRAY|VT_UI1;
1947 V_ARRAY(&v) = sa;
1948 hres = VariantChangeTypeEx(&v2, &v, 0, 0, VT_ARRAY|VT_UI1);
1949 ok(hres == S_OK, "CTE VT_ARRAY|VT_UI1->VT_ARRAY|VT_UI1 returned %x\n", hres);
1950 hres = SafeArrayDestroy(sa);
1951 ok(hres == S_OK, "got 0x%08x\n", hres);
1952 VariantClear(&v2);
1955 /* NULL/EMPTY */
1956 MKARRAY(0,1,VT_UI1);
1957 hres = VariantChangeTypeEx(&v2, &v, 0, 0, VT_NULL);
1958 ok(hres == DISP_E_TYPEMISMATCH, "CTE VT_ARRAY|VT_UI1 returned %x\n", hres);
1959 VariantClear(&v);
1960 MKARRAY(0,1,VT_UI1);
1961 hres = VariantChangeTypeEx(&v2, &v, 0, 0, VT_EMPTY);
1962 ok(hres == DISP_E_TYPEMISMATCH, "CTE VT_ARRAY|VT_UI1 returned %x\n", hres);
1963 VariantClear(&v);
1966 static void test_SafeArrayDestroyData (void)
1968 SAFEARRAYBOUND sab[2];
1969 SAFEARRAY *sa;
1970 HRESULT hres;
1971 int value = 0xdeadbeef;
1972 LONG index[1];
1973 void *temp_pvData;
1974 USHORT features;
1976 sab[0].lLbound = 0;
1977 sab[0].cElements = 10;
1978 sa = SafeArrayCreate(VT_INT, 1, sab);
1979 ok(sa != NULL, "Create() failed.\n");
1980 ok(sa->fFeatures == FADF_HAVEVARTYPE, "got 0x%x\n", sa->fFeatures);
1982 index[0] = 1;
1983 SafeArrayPutElement (sa, index, &value);
1985 /* SafeArrayDestroyData shouldn't free pvData if FADF_STATIC is set. */
1986 features = (sa->fFeatures |= FADF_STATIC);
1987 temp_pvData = sa->pvData;
1988 hres = SafeArrayDestroyData(sa);
1989 ok(hres == S_OK, "SADData FADF_STATIC failed, error code %x.\n",hres);
1990 ok(features == sa->fFeatures, "got 0x%x\n", sa->fFeatures);
1991 ok(sa->pvData == temp_pvData, "SADData FADF_STATIC: pvData=%p, expected %p (fFeatures = %d).\n",
1992 sa->pvData, temp_pvData, sa->fFeatures);
1993 SafeArrayGetElement (sa, index, &value);
1994 ok(value == 0, "Data not cleared after SADData\n");
1996 /* Clear FADF_STATIC, now really destroy the data. */
1997 features = (sa->fFeatures ^= FADF_STATIC);
1998 hres = SafeArrayDestroyData(sa);
1999 ok(hres == S_OK, "SADData !FADF_STATIC failed, error code %x.\n",hres);
2000 ok(features == sa->fFeatures, "got 0x%x\n", sa->fFeatures);
2001 ok(sa->pvData == NULL, "SADData !FADF_STATIC: pvData=%p, expected NULL.\n", sa->pvData);
2003 hres = SafeArrayDestroy(sa);
2004 ok(hres == S_OK, "SAD failed, error code %x.\n", hres);
2006 /* two dimensions */
2007 sab[0].lLbound = 0;
2008 sab[0].cElements = 10;
2009 sab[1].lLbound = 0;
2010 sab[1].cElements = 10;
2012 sa = SafeArrayCreate(VT_INT, 2, sab);
2013 ok(sa != NULL, "Create() failed.\n");
2014 ok(sa->fFeatures == FADF_HAVEVARTYPE, "got 0x%x\n", sa->fFeatures);
2016 features = sa->fFeatures;
2017 hres = SafeArrayDestroyData(sa);
2018 ok(hres == S_OK, "got 0x%08x\n",hres);
2019 ok(features == sa->fFeatures, "got 0x%x\n", sa->fFeatures);
2021 SafeArrayDestroy(sa);
2023 /* try to destroy data from descriptor */
2024 hres = SafeArrayAllocDescriptor(1, &sa);
2025 ok(hres == S_OK, "got 0x%08x\n", hres);
2026 ok(sa->fFeatures == 0, "got 0x%x\n", sa->fFeatures);
2028 hres = SafeArrayDestroyData(sa);
2029 ok(hres == S_OK, "got 0x%08x\n", hres);
2030 ok(sa->fFeatures == 0, "got 0x%x\n", sa->fFeatures);
2032 hres = SafeArrayDestroyDescriptor(sa);
2033 ok(hres == S_OK, "got 0x%08x\n", hres);
2035 hres = SafeArrayAllocDescriptor(2, &sa);
2036 ok(hres == S_OK, "got 0x%08x\n", hres);
2037 ok(sa->fFeatures == 0, "got 0x%x\n", sa->fFeatures);
2039 hres = SafeArrayDestroyData(sa);
2040 ok(hres == S_OK, "got 0x%08x\n", hres);
2041 ok(sa->fFeatures == 0, "got 0x%x\n", sa->fFeatures);
2043 hres = SafeArrayDestroyDescriptor(sa);
2044 ok(hres == S_OK, "got 0x%08x\n", hres);
2046 /* vector case */
2047 sa = SafeArrayCreateVector(VT_I4, 0, 10);
2048 ok(sa != NULL, "got %p\n", sa);
2049 ok(sa->fFeatures == (FADF_CREATEVECTOR|FADF_HAVEVARTYPE), "got 0x%x\n", sa->fFeatures);
2051 ok(sa->pvData != NULL, "got %p\n", sa->pvData);
2052 hres = SafeArrayDestroyData(sa);
2053 ok(hres == S_OK, "got 0x%08x\n", hres);
2054 todo_wine
2055 ok(sa->fFeatures == FADF_HAVEVARTYPE, "got 0x%x\n", sa->fFeatures);
2056 ok(sa->pvData != NULL, "got %p\n", sa->pvData);
2057 /* There seems to be a bug on windows, especially visible on 64bit systems,
2058 probably double-free of similar issue. */
2059 sa->pvData = NULL;
2060 SafeArrayDestroy(sa);
2063 static void test_safearray_layout(void)
2065 IRecordInfoImpl *irec;
2066 IRecordInfo *record;
2067 GUID guid, *guidptr;
2068 SAFEARRAYBOUND sab;
2069 SAFEARRAY *sa;
2070 DWORD *dwptr;
2071 HRESULT hr;
2073 sab.lLbound = 0;
2074 sab.cElements = 10;
2076 /* GUID field */
2077 sa = SafeArrayCreate(VT_UNKNOWN, 1, &sab);
2078 ok(sa != NULL, "got %p\n", sa);
2080 guidptr = (GUID*)sa - 1;
2081 ok(IsEqualIID(guidptr, &IID_IUnknown), "got %s\n", wine_dbgstr_guid(guidptr));
2083 hr = SafeArraySetIID(sa, &IID_IDispatch);
2084 ok(hr == S_OK, "got 0x%08x\n", hr);
2085 ok(IsEqualIID(guidptr, &IID_IDispatch), "got %s\n", wine_dbgstr_guid(guidptr));
2087 memcpy(guidptr, &IID_IUnknown, sizeof(GUID));
2088 hr = SafeArrayGetIID(sa, &guid);
2089 ok(hr == S_OK, "got 0x%08x\n", hr);
2090 ok(IsEqualIID(&guid, &IID_IUnknown), "got %s\n", wine_dbgstr_guid(&guid));
2092 hr = SafeArrayDestroy(sa);
2093 ok(hr == S_OK, "got 0x%08x\n", hr);
2095 /* VARTYPE field */
2096 sa = SafeArrayCreate(VT_UI1, 1, &sab);
2097 ok(sa != NULL, "got %p\n", sa);
2099 dwptr = (DWORD*)sa - 1;
2100 ok(*dwptr == VT_UI1, "got %d\n", *dwptr);
2102 hr = SafeArrayDestroy(sa);
2103 ok(hr == S_OK, "got 0x%08x\n", hr);
2105 /* IRecordInfo pointer */
2106 irec = IRecordInfoImpl_Construct();
2107 irec->ref = 1;
2109 sa = pSafeArrayCreateEx(VT_RECORD, 1, &sab, &irec->IRecordInfo_iface);
2110 ok(sa != NULL, "failed to create array\n");
2112 record = *((IRecordInfo**)sa - 1);
2113 ok(record == &irec->IRecordInfo_iface, "got %p\n", record);
2115 hr = SafeArrayDestroy(sa);
2116 ok(hr == S_OK, "got 0x%08x\n", hr);
2117 IRecordInfo_Release(&irec->IRecordInfo_iface);
2120 START_TEST(safearray)
2122 hOleaut32 = GetModuleHandleA("oleaut32.dll");
2124 has_i8 = GetProcAddress(hOleaut32, "VarI8FromI1") != NULL;
2126 GETPTR(SafeArrayAllocDescriptorEx);
2127 GETPTR(SafeArrayCopyData);
2128 GETPTR(SafeArrayGetIID);
2129 GETPTR(SafeArraySetIID);
2130 GETPTR(SafeArrayGetVartype);
2131 GETPTR(SafeArrayCreateEx);
2132 GETPTR(SafeArrayCreateVector);
2133 GETPTR(SafeArrayGetRecordInfo);
2135 check_for_VT_INT_PTR();
2136 test_safearray();
2137 test_SafeArrayAllocDestroyDescriptor();
2138 test_SafeArrayCreateLockDestroy();
2139 test_VectorCreateLockDestroy();
2140 test_LockUnlock();
2141 test_SafeArrayChangeTypeEx();
2142 test_SafeArrayCopy();
2143 test_SafeArrayClear();
2144 test_SafeArrayCreateEx();
2145 test_SafeArrayCopyData();
2146 test_SafeArrayDestroyData();
2147 test_SafeArrayGetPutElement();
2148 test_SafeArrayGetPutElement_BSTR();
2149 test_SafeArrayGetPutElement_IUnknown();
2150 test_SafeArrayRedim_IUnknown();
2151 test_SafeArrayGetPutElement_VARIANT();
2152 test_safearray_layout();