1 /*
2 * SafeArray test program
3 *
4 * Copyright 2002 Marcus Meissner
5 *
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.
10 *
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.
15 *
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
19 *
20 */
21
22 #include <stdarg.h>
23 #include <stdio.h>
24 #include <math.h>
25 #include <float.h>
26
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"
38
39 #include "wtypes.h"
40 #include "oleauto.h"
41
42 #ifndef FADF_CREATEVECTOR
43 const USHORT FADF_CREATEVECTOR = 0x2000;
44 #endif
45
46 static HMODULE hOleaut32;
47
48 static HRESULT (WINAPI *pSafeArrayAllocDescriptorEx)(VARTYPE,UINT,SAFEARRAY**);
49 static HRESULT (WINAPI *pSafeArrayCopyData)(SAFEARRAY*,SAFEARRAY*);
50 static HRESULT (WINAPI *pSafeArrayGetVartype)(SAFEARRAY*,VARTYPE*);
51 static HRESULT (WINAPI *pSafeArrayGetRecordInfo)(SAFEARRAY*,IRecordInfo**);
52 static SAFEARRAY* (WINAPI *pSafeArrayCreateEx)(VARTYPE,UINT,SAFEARRAYBOUND*,LPVOID);
53 static SAFEARRAY* (WINAPI *pSafeArrayCreateVector)(VARTYPE,LONG,ULONG);
54
55 #define GETPTR(func) p##func = (void*)GetProcAddress(hOleaut32, #func)
56
57 /* Has I8/UI8 data type? */
58 static BOOL has_i8;
59 /* Has INT_PTR/UINT_PTR type? */
60 static BOOL has_int_ptr;
61
62 static const USHORT ignored_copy_features[] =
63 {
64 FADF_AUTO,
65 FADF_STATIC,
66 FADF_EMBEDDED,
67 FADF_FIXEDSIZE
68 };
69
70 #define START_REF_COUNT 1
71 #define RECORD_SIZE 64
72 #define RECORD_SIZE_FAIL 17
73 /************************************************************************
74 * Dummy IRecordInfo Implementation
75 */
76 typedef struct IRecordInfoImpl
77 {
78 IRecordInfo IRecordInfo_iface;
79 LONG ref;
80 unsigned int sizeCalled;
81 unsigned int clearCalled;
82 unsigned int recordcopy;
83 } IRecordInfoImpl;
84
impl_from_IRecordInfo(IRecordInfo * iface)85 static inline IRecordInfoImpl *impl_from_IRecordInfo(IRecordInfo *iface)
86 {
87 return CONTAINING_RECORD(iface, IRecordInfoImpl, IRecordInfo_iface);
88 }
89
RecordInfo_QueryInterface(IRecordInfo * iface,REFIID riid,void ** obj)90 static HRESULT WINAPI RecordInfo_QueryInterface(IRecordInfo *iface, REFIID riid, void **obj)
91 {
92 *obj = NULL;
93
94 if (IsEqualIID(riid, &IID_IUnknown) ||
95 IsEqualIID(riid, &IID_IRecordInfo))
96 {
97 *obj = iface;
98 IRecordInfo_AddRef(iface);
99 return S_OK;
100 }
101
102 return E_NOINTERFACE;
103 }
104
RecordInfo_AddRef(IRecordInfo * iface)105 static ULONG WINAPI RecordInfo_AddRef(IRecordInfo *iface)
106 {
107 IRecordInfoImpl* This = impl_from_IRecordInfo(iface);
108 return InterlockedIncrement(&This->ref);
109 }
110
RecordInfo_Release(IRecordInfo * iface)111 static ULONG WINAPI RecordInfo_Release(IRecordInfo *iface)
112 {
113 IRecordInfoImpl* This = impl_from_IRecordInfo(iface);
114 ULONG ref = InterlockedDecrement(&This->ref);
115
116 if (!ref)
117 HeapFree(GetProcessHeap(), 0, This);
118
119 return ref;
120 }
121
RecordInfo_RecordInit(IRecordInfo * iface,PVOID pvNew)122 static HRESULT WINAPI RecordInfo_RecordInit(IRecordInfo *iface, PVOID pvNew)
123 {
124 ok(0, "unexpected call\n");
125 return E_NOTIMPL;
126 }
127
128 static BOOL fail_GetSize; /* Whether to fail the GetSize call */
129
RecordInfo_RecordClear(IRecordInfo * iface,PVOID pvExisting)130 static HRESULT WINAPI RecordInfo_RecordClear(IRecordInfo *iface, PVOID pvExisting)
131 {
132 IRecordInfoImpl* This = impl_from_IRecordInfo(iface);
133 This->clearCalled++;
134 return S_OK;
135 }
136
RecordInfo_RecordCopy(IRecordInfo * iface,PVOID pvExisting,PVOID pvNew)137 static HRESULT WINAPI RecordInfo_RecordCopy(IRecordInfo *iface, PVOID pvExisting, PVOID pvNew)
138 {
139 IRecordInfoImpl* This = impl_from_IRecordInfo(iface);
140 This->recordcopy++;
141 return S_OK;
142 }
143
RecordInfo_GetGuid(IRecordInfo * iface,GUID * pguid)144 static HRESULT WINAPI RecordInfo_GetGuid(IRecordInfo *iface, GUID *pguid)
145 {
146 ok(0, "unexpected call\n");
147 return E_NOTIMPL;
148 }
149
RecordInfo_GetName(IRecordInfo * iface,BSTR * pbstrName)150 static HRESULT WINAPI RecordInfo_GetName(IRecordInfo *iface, BSTR *pbstrName)
151 {
152 ok(0, "unexpected call\n");
153 return E_NOTIMPL;
154 }
155
RecordInfo_GetSize(IRecordInfo * iface,ULONG * size)156 static HRESULT WINAPI RecordInfo_GetSize(IRecordInfo *iface, ULONG* size)
157 {
158 IRecordInfoImpl* This = impl_from_IRecordInfo(iface);
159 This->sizeCalled++;
160 if (fail_GetSize)
161 {
162 *size = RECORD_SIZE_FAIL;
163 return E_UNEXPECTED;
164 }
165 *size = RECORD_SIZE;
166 return S_OK;
167 }
168
RecordInfo_GetTypeInfo(IRecordInfo * iface,ITypeInfo ** ppTypeInfo)169 static HRESULT WINAPI RecordInfo_GetTypeInfo(IRecordInfo *iface, ITypeInfo **ppTypeInfo)
170 {
171 ok(0, "unexpected call\n");
172 return E_NOTIMPL;
173 }
174
RecordInfo_GetField(IRecordInfo * iface,PVOID pvData,LPCOLESTR szFieldName,VARIANT * pvarField)175 static HRESULT WINAPI RecordInfo_GetField(IRecordInfo *iface, PVOID pvData,
176 LPCOLESTR szFieldName, VARIANT *pvarField)
177 {
178 ok(0, "unexpected call\n");
179 return E_NOTIMPL;
180 }
181
RecordInfo_GetFieldNoCopy(IRecordInfo * iface,PVOID pvData,LPCOLESTR szFieldName,VARIANT * pvarField,PVOID * ppvDataCArray)182 static HRESULT WINAPI RecordInfo_GetFieldNoCopy(IRecordInfo *iface, PVOID pvData,
183 LPCOLESTR szFieldName, VARIANT *pvarField, PVOID *ppvDataCArray)
184 {
185 ok(0, "unexpected call\n");
186 return E_NOTIMPL;
187 }
188
RecordInfo_PutField(IRecordInfo * iface,ULONG wFlags,PVOID pvData,LPCOLESTR szFieldName,VARIANT * pvarField)189 static HRESULT WINAPI RecordInfo_PutField(IRecordInfo *iface, ULONG wFlags, PVOID pvData,
190 LPCOLESTR szFieldName, VARIANT *pvarField)
191 {
192 ok(0, "unexpected call\n");
193 return E_NOTIMPL;
194 }
195
RecordInfo_PutFieldNoCopy(IRecordInfo * iface,ULONG wFlags,PVOID pvData,LPCOLESTR szFieldName,VARIANT * pvarField)196 static HRESULT WINAPI RecordInfo_PutFieldNoCopy(IRecordInfo *iface, ULONG wFlags,
197 PVOID pvData, LPCOLESTR szFieldName, VARIANT *pvarField)
198 {
199 ok(0, "unexpected call\n");
200 return E_NOTIMPL;
201 }
202
RecordInfo_GetFieldNames(IRecordInfo * iface,ULONG * pcNames,BSTR * rgBstrNames)203 static HRESULT WINAPI RecordInfo_GetFieldNames(IRecordInfo *iface, ULONG *pcNames,
204 BSTR *rgBstrNames)
205 {
206 ok(0, "unexpected call\n");
207 return E_NOTIMPL;
208 }
209
RecordInfo_IsMatchingType(IRecordInfo * iface,IRecordInfo * info2)210 static BOOL WINAPI RecordInfo_IsMatchingType(IRecordInfo *iface, IRecordInfo *info2)
211 {
212 ok(0, "unexpected call\n");
213 return FALSE;
214 }
215
RecordInfo_RecordCreate(IRecordInfo * iface)216 static PVOID WINAPI RecordInfo_RecordCreate(IRecordInfo *iface)
217 {
218 ok(0, "unexpected call\n");
219 return NULL;
220 }
221
RecordInfo_RecordCreateCopy(IRecordInfo * iface,PVOID pvSource,PVOID * ppvDest)222 static HRESULT WINAPI RecordInfo_RecordCreateCopy(IRecordInfo *iface, PVOID pvSource,
223 PVOID *ppvDest)
224 {
225 ok(0, "unexpected call\n");
226 return E_NOTIMPL;
227 }
228
RecordInfo_RecordDestroy(IRecordInfo * iface,PVOID pvRecord)229 static HRESULT WINAPI RecordInfo_RecordDestroy(IRecordInfo *iface, PVOID pvRecord)
230 {
231 ok(0, "unexpected call\n");
232 return E_NOTIMPL;
233 }
234
235 static const IRecordInfoVtbl RecordInfoVtbl =
236 {
237 RecordInfo_QueryInterface,
238 RecordInfo_AddRef,
239 RecordInfo_Release,
240 RecordInfo_RecordInit,
241 RecordInfo_RecordClear,
242 RecordInfo_RecordCopy,
243 RecordInfo_GetGuid,
244 RecordInfo_GetName,
245 RecordInfo_GetSize,
246 RecordInfo_GetTypeInfo,
247 RecordInfo_GetField,
248 RecordInfo_GetFieldNoCopy,
249 RecordInfo_PutField,
250 RecordInfo_PutFieldNoCopy,
251 RecordInfo_GetFieldNames,
252 RecordInfo_IsMatchingType,
253 RecordInfo_RecordCreate,
254 RecordInfo_RecordCreateCopy,
255 RecordInfo_RecordDestroy
256 };
257
IRecordInfoImpl_Construct(void)258 static IRecordInfoImpl *IRecordInfoImpl_Construct(void)
259 {
260 IRecordInfoImpl *rec;
261
262 rec = HeapAlloc(GetProcessHeap(), 0, sizeof(IRecordInfoImpl));
263 rec->IRecordInfo_iface.lpVtbl = &RecordInfoVtbl;
264 rec->ref = START_REF_COUNT;
265 rec->clearCalled = 0;
266 rec->sizeCalled = 0;
267 return rec;
268 }
269
SAFEARRAY_GetVTSize(VARTYPE vt)270 static DWORD SAFEARRAY_GetVTSize(VARTYPE vt)
271 {
272 switch (vt)
273 {
274 case VT_I1:
275 case VT_UI1: return sizeof(BYTE);
276 case VT_BOOL:
277 case VT_I2:
278 case VT_UI2: return sizeof(SHORT);
279 case VT_I4:
280 case VT_UI4:
281 case VT_R4:
282 case VT_ERROR: return sizeof(LONG);
283 case VT_R8: return sizeof(LONG64);
284 case VT_I8:
285 case VT_UI8:
286 if (has_i8)
287 return sizeof(LONG64);
288 break;
289 case VT_INT:
290 case VT_UINT: return sizeof(INT);
291 case VT_INT_PTR:
292 case VT_UINT_PTR:
293 if (has_int_ptr)
294 return sizeof(UINT_PTR);
295 break;
296 case VT_CY: return sizeof(CY);
297 case VT_DATE: return sizeof(DATE);
298 case VT_BSTR: return sizeof(BSTR);
299 case VT_DISPATCH: return sizeof(LPDISPATCH);
300 case VT_VARIANT: return sizeof(VARIANT);
301 case VT_UNKNOWN: return sizeof(LPUNKNOWN);
302 case VT_DECIMAL: return sizeof(DECIMAL);
303 }
304 return 0;
305 }
306
check_for_VT_INT_PTR(void)307 static void check_for_VT_INT_PTR(void)
308 {
309 /* Set a global flag if VT_INT_PTR is supported */
310
311 SAFEARRAY* a;
312 SAFEARRAYBOUND bound;
313 bound.cElements = 0;
314 bound.lLbound = 0;
315 a = SafeArrayCreate(VT_INT_PTR, 1, &bound);
316 if (a) {
317 HRESULT hres;
318 trace("VT_INT_PTR is supported\n");
319 has_int_ptr = TRUE;
320 hres = SafeArrayDestroy(a);
321 ok(hres == S_OK, "got 0x%08x\n", hres);
322 }
323 else {
324 trace("VT_INT_PTR is not supported\n");
325 has_int_ptr = FALSE;
326 }
327 }
328
329 #define VARTYPE_NOT_SUPPORTED 0
330 static struct {
331 VARTYPE vt; /* VT */
332 UINT elemsize; /* elementsize by VT */
333 UINT expflags; /* fFeatures from SafeArrayAllocDescriptorEx */
334 UINT addflags; /* additional fFeatures from SafeArrayCreate */
335 } vttypes[] = {
336 {VT_EMPTY, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
337 {VT_NULL, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
338 {VT_I2, 2, FADF_HAVEVARTYPE,0},
339 {VT_I4, 4, FADF_HAVEVARTYPE,0},
340 {VT_R4, 4, FADF_HAVEVARTYPE,0},
341 {VT_R8, 8, FADF_HAVEVARTYPE,0},
342 {VT_CY, 8, FADF_HAVEVARTYPE,0},
343 {VT_DATE, 8, FADF_HAVEVARTYPE,0},
344 {VT_BSTR, sizeof(BSTR), FADF_HAVEVARTYPE,FADF_BSTR},
345 {VT_DISPATCH, sizeof(LPDISPATCH), FADF_HAVEIID, FADF_DISPATCH},
346 {VT_ERROR, 4, FADF_HAVEVARTYPE,0},
347 {VT_BOOL, 2, FADF_HAVEVARTYPE,0},
348 {VT_VARIANT, sizeof(VARIANT), FADF_HAVEVARTYPE,FADF_VARIANT},
349 {VT_UNKNOWN, sizeof(LPUNKNOWN), FADF_HAVEIID, FADF_UNKNOWN},
350 {VT_DECIMAL, sizeof(DECIMAL), FADF_HAVEVARTYPE,0},
351 {15, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0}, /* no VT_xxx */
352 {VT_I1, 1, FADF_HAVEVARTYPE,0},
353 {VT_UI1, 1, FADF_HAVEVARTYPE,0},
354 {VT_UI2, 2, FADF_HAVEVARTYPE,0},
355 {VT_UI4, 4, FADF_HAVEVARTYPE,0},
356 {VT_I8, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
357 {VT_UI8, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
358 {VT_INT, sizeof(INT), FADF_HAVEVARTYPE,0},
359 {VT_UINT, sizeof(UINT), FADF_HAVEVARTYPE,0},
360 {VT_VOID, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
361 {VT_HRESULT, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
362 {VT_PTR, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
363 {VT_SAFEARRAY,VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
364 {VT_CARRAY, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
365 {VT_USERDEFINED,VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
366 {VT_LPSTR, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
367 {VT_LPWSTR, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
368 {VT_FILETIME, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
369 {VT_RECORD, VARTYPE_NOT_SUPPORTED,FADF_RECORD,0},
370 {VT_BLOB, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
371 {VT_STREAM, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
372 {VT_STORAGE, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
373 {VT_STREAMED_OBJECT,VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
374 {VT_STORED_OBJECT,VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
375 {VT_BLOB_OBJECT,VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
376 {VT_CF, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
377 {VT_CLSID, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
378 };
379
test_safearray(void)380 static void test_safearray(void)
381 {
382 SAFEARRAY *a, b, *c;
383 unsigned int i, diff;
384 LONG indices[2];
385 HRESULT hres;
386 SAFEARRAYBOUND bound, bounds[2];
387 VARIANT v,d;
388 LPVOID data;
389 IID iid;
390 VARTYPE vt;
391 LONG l;
392 unsigned char *ptr1, *ptr2;
393
394 hres = SafeArrayDestroy( NULL);
395 ok( hres == S_OK, "SafeArrayDestroy( NULL) returned 0x%x\n", hres);
396
397 bound.cElements = 1;
398 bound.lLbound = 0;
399 a = SafeArrayCreate(-1, 1, &bound);
400 ok(NULL == a,"SAC(-1,1,[1,0]) not failed?\n");
401
402 bound.cElements = 0;
403 bound.lLbound = 42;
404 a = SafeArrayCreate(VT_I4, 1, &bound);
405 ok(NULL != a,"SAC(VT_I4,1,[0,0]) failed.\n");
406
407 hres = SafeArrayGetLBound(a, 1, &l);
408 ok(hres == S_OK, "SAGLB of 0 size dimensioned array failed with %x\n",hres);
409 ok(l == 42, "SAGLB of 0 size dimensioned array failed to return 42, but returned %d\n",l);
410 hres = SafeArrayGetUBound(a, 1, &l);
411 ok(hres == S_OK, "SAGUB of 0 size dimensioned array failed with %x\n",hres);
412 ok(l == 41, "SAGUB of 0 size dimensioned array failed to return 41, but returned %d\n",l);
413
414 hres = SafeArrayAccessData(a, &data);
415 ok(hres == S_OK, "SafeArrayAccessData of 0 size dimensioned array failed with %x\n", hres);
416 SafeArrayUnaccessData(a);
417
418 bound.cElements = 2;
419 hres = SafeArrayRedim(a, &bound);
420 ok(hres == S_OK,"SAR of a 0 elements dimension failed with hres %x\n", hres);
421 bound.cElements = 0;
422 hres = SafeArrayRedim(a, &bound);
423 ok(hres == S_OK || hres == E_OUTOFMEMORY,
424 "SAR to a 0 elements dimension failed with hres %x\n", hres);
425 hres = SafeArrayDestroy(a);
426 ok(hres == S_OK,"SAD of 0 dim array failed with hres %x\n", hres);
427
428 SafeArrayAllocDescriptor(2, &a);
429 a->rgsabound[0].cElements = 2;
430 a->rgsabound[0].lLbound = 1;
431 a->rgsabound[1].cElements = 4;
432 a->rgsabound[1].lLbound = 1;
433 a->cbElements = 2;
434 hres = SafeArrayAllocData(a);
435 ok(hres == S_OK, "SafeArrayAllocData failed with hres %x\n", hres);
436
437 indices[0] = 4;
438 indices[1] = 2;
439 hres = SafeArrayPtrOfIndex(a, indices, (void **)&ptr1);
440 ok(hres == S_OK, "SAPOI failed with hres %x\n", hres);
441 SafeArrayAccessData(a, (void **)&ptr2);
442 ok(ptr1 - ptr2 == 14, "SAPOI got wrong ptr\n");
443 *(WORD *)ptr1 = 0x55aa;
444 SafeArrayUnaccessData(a);
445
446 bound.cElements = 10;
447 bound.lLbound = 1;
448 SafeArrayRedim(a, &bound);
449 ptr1 = NULL;
450 SafeArrayPtrOfIndex(a, indices, (void **)&ptr1);
451 ok(*(WORD *)ptr1 == 0x55aa, "Data not preserved when resizing array\n");
452
453 bound.cElements = 10;
454 bound.lLbound = 0;
455 SafeArrayRedim(a, &bound);
456 SafeArrayPtrOfIndex(a, indices, (void **)&ptr1);
457 ok(*(WORD *)ptr1 == 0 ||
458 broken(*(WORD *)ptr1 != 0), /* Win 2003 */
459 "Expanded area not zero-initialized\n");
460
461 indices[1] = 1;
462 SafeArrayPtrOfIndex(a, indices, (void **)&ptr1);
463 ok(*(WORD *)ptr1 == 0x55aa ||
464 broken(*(WORD *)ptr1 != 0x55aa), /* Win 2003 */
465 "Data not preserved when resizing array\n");
466
467 hres = SafeArrayDestroy(a);
468 ok(hres == S_OK,"SAD failed with hres %x\n", hres);
469
470 bounds[0].cElements = 0; bounds[0].lLbound = 1;
471 bounds[1].cElements = 2; bounds[1].lLbound = 23;
472 a = SafeArrayCreate(VT_I4,2,bounds);
473 ok(a != NULL,"SAC(VT_INT32,2,...) with 0 element dim failed.\n");
474
475 hres = SafeArrayDestroy(a);
476 ok(hres == S_OK,"SAD failed with hres %x\n", hres);
477 bounds[0].cElements = 1; bounds[0].lLbound = 1;
478 bounds[1].cElements = 0; bounds[1].lLbound = 23;
479 a = SafeArrayCreate(VT_I4,2,bounds);
480 ok(a != NULL,"SAC(VT_INT32,2,...) with 0 element dim failed.\n");
481
482 hres = SafeArrayDestroy(a);
483 ok(hres == S_OK,"SAD failed with hres %x\n", hres);
484
485 bounds[0].cElements = 42; bounds[0].lLbound = 1;
486 bounds[1].cElements = 2; bounds[1].lLbound = 23;
487 a = SafeArrayCreate(VT_I4,2,bounds);
488 ok(a != NULL,"SAC(VT_INT32,2,...) failed.\n");
489
490 hres = SafeArrayGetLBound (a, 0, &l);
491 ok (hres == DISP_E_BADINDEX, "SAGLB 0 failed with %x\n", hres);
492 hres = SafeArrayGetLBound (a, 1, &l);
493 ok (hres == S_OK, "SAGLB 1 failed with %x\n", hres);
494 ok (l == 1, "SAGLB 1 returned %d instead of 1\n", l);
495 hres = SafeArrayGetLBound (a, 2, &l);
496 ok (hres == S_OK, "SAGLB 2 failed with %x\n", hres);
497 ok (l == 23, "SAGLB 2 returned %d instead of 23\n", l);
498 hres = SafeArrayGetLBound (a, 3, &l);
499 ok (hres == DISP_E_BADINDEX, "SAGLB 3 failed with %x\n", hres);
500
501 hres = SafeArrayGetUBound (a, 0, &l);
502 ok (hres == DISP_E_BADINDEX, "SAGUB 0 failed with %x\n", hres);
503 hres = SafeArrayGetUBound (a, 1, &l);
504 ok (hres == S_OK, "SAGUB 1 failed with %x\n", hres);
505 ok (l == 42, "SAGUB 1 returned %d instead of 42\n", l);
506 hres = SafeArrayGetUBound (a, 2, &l);
507 ok (hres == S_OK, "SAGUB 2 failed with %x\n", hres);
508 ok (l == 24, "SAGUB 2 returned %d instead of 24\n", l);
509 hres = SafeArrayGetUBound (a, 3, &l);
510 ok (hres == DISP_E_BADINDEX, "SAGUB 3 failed with %x\n", hres);
511
512 i = SafeArrayGetDim(a);
513 ok(i == 2, "getdims of 2 din array returned %d\n",i);
514
515 indices[0] = 0;
516 indices[1] = 23;
517 hres = SafeArrayGetElement(a, indices, &i);
518 ok(DISP_E_BADINDEX == hres,"SAGE failed [0,23], hres 0x%x\n",hres);
519
520 indices[0] = 1;
521 indices[1] = 22;
522 hres = SafeArrayGetElement(a, indices, &i);
523 ok(DISP_E_BADINDEX == hres,"SAGE failed [1,22], hres 0x%x\n",hres);
524
525 indices[0] = 1;
526 indices[1] = 23;
527 hres = SafeArrayGetElement(a, indices, &i);
528 ok(S_OK == hres,"SAGE failed [1,23], hres 0x%x\n",hres);
529
530 indices[0] = 1;
531 indices[1] = 25;
532 hres = SafeArrayGetElement(a, indices, &i);
533 ok(DISP_E_BADINDEX == hres,"SAGE failed [1,24], hres 0x%x\n",hres);
534
535 indices[0] = 3;
536 indices[1] = 23;
537 hres = SafeArrayGetElement(a, indices, &i);
538 ok(S_OK == hres,"SAGE failed [42,23], hres 0x%x\n",hres);
539
540 hres = SafeArrayAccessData(a, (void**)&ptr1);
541 ok(S_OK == hres, "SAAD failed with 0x%x\n", hres);
542
543 indices[0] = 3;
544 indices[1] = 23;
545 hres = SafeArrayPtrOfIndex(a, indices, (void**)&ptr2);
546 ok(S_OK == hres,"SAPOI failed [1,23], hres 0x%x\n",hres);
547 diff = ptr2 - ptr1;
548 ok(diff == 8,"ptr difference is not 8, but %d (%p vs %p)\n", diff, ptr2, ptr1);
549
550 indices[0] = 3;
551 indices[1] = 24;
552 hres = SafeArrayPtrOfIndex(a, indices, (void**)&ptr2);
553 ok(S_OK == hres,"SAPOI failed [5,24], hres 0x%x\n",hres);
554 diff = ptr2 - ptr1;
555 ok(diff == 176,"ptr difference is not 176, but %d (%p vs %p)\n", diff, ptr2, ptr1);
556
557 indices[0] = 20;
558 indices[1] = 23;
559 hres = SafeArrayPtrOfIndex(a, indices, (void**)&ptr2);
560 ok(S_OK == hres,"SAPOI failed [20,23], hres 0x%x\n",hres);
561 diff = ptr2 - ptr1;
562 ok(diff == 76,"ptr difference is not 76, but %d (%p vs %p)\n", diff, ptr2, ptr1);
563
564 hres = SafeArrayUnaccessData(a);
565 ok(S_OK == hres, "SAUAD failed with 0x%x\n", hres);
566
567 hres = SafeArrayDestroy(a);
568 ok(hres == S_OK,"SAD failed with hres %x\n", hres);
569
570 for (i = 0; i < ARRAY_SIZE(vttypes); i++) {
571 if ((i == VT_I8 || i == VT_UI8) && has_i8)
572 {
573 vttypes[i].elemsize = sizeof(LONG64);
574 }
575
576 a = SafeArrayCreate(vttypes[i].vt, 1, &bound);
577
578 ok((!a && !vttypes[i].elemsize) ||
579 (a && vttypes[i].elemsize == a->cbElements),
580 "SAC(%d,1,[1,0]), %p result %d, expected %d\n",
581 vttypes[i].vt,a,(a?a->cbElements:0),vttypes[i].elemsize);
582
583 if (a)
584 {
585 ok(a->fFeatures == (vttypes[i].expflags | vttypes[i].addflags),
586 "SAC of %d returned feature flags %x, expected %x\n",
587 vttypes[i].vt, a->fFeatures,
588 vttypes[i].expflags|vttypes[i].addflags);
589 ok(SafeArrayGetElemsize(a) == vttypes[i].elemsize,
590 "SAGE for vt %d returned elemsize %d instead of expected %d\n",
591 vttypes[i].vt, SafeArrayGetElemsize(a),vttypes[i].elemsize);
592 }
593
594 if (!a) continue;
595
596 if (pSafeArrayGetVartype)
597 {
598 hres = pSafeArrayGetVartype(a, &vt);
599 ok(hres == S_OK, "SAGVT of arra y with vt %d failed with %x\n", vttypes[i].vt, hres);
600 /* Windows prior to Vista returns VT_UNKNOWN instead of VT_DISPATCH */
601 ok(broken(vt == VT_UNKNOWN) || vt == vttypes[i].vt, "SAGVT of array with vt %d returned %d\n", vttypes[i].vt, vt);
602 }
603
604 hres = SafeArrayCopy(a, &c);
605 ok(hres == S_OK, "failed to copy safearray of vt %d with hres %x\n", vttypes[i].vt, hres);
606
607 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
608 );
609 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);
610 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);
611
612 if (pSafeArrayGetVartype) {
613 hres = pSafeArrayGetVartype(c, &vt);
614 ok(hres == S_OK, "SAGVT of array with vt %d failed with %x\n", vttypes[i].vt, hres);
615 /* Windows prior to Vista returns VT_UNKNOWN instead of VT_DISPATCH */
616 ok(broken(vt == VT_UNKNOWN) || vt == vttypes[i].vt, "SAGVT of array with vt %d returned %d\n", vttypes[i].vt, vt);
617 }
618
619 if (pSafeArrayCopyData) {
620 hres = pSafeArrayCopyData(a, c);
621 ok(hres == S_OK, "failed to copy safearray data of vt %d with hres %x\n", vttypes[i].vt, hres);
622
623 hres = SafeArrayDestroyData(c);
624 ok(hres == S_OK,"SADD of copy of array with vt %d failed with hres %x\n", vttypes[i].vt, hres);
625 }
626
627 hres = SafeArrayDestroy(c);
628 ok(hres == S_OK,"SAD failed with hres %x\n", hres);
629
630 hres = SafeArrayDestroy(a);
631 ok(hres == S_OK,"SAD of array with vt %d failed with hres %x\n", vttypes[i].vt, hres);
632 }
633
634 /* Test conversion of type|VT_ARRAY <-> VT_BSTR */
635 bound.lLbound = 0;
636 bound.cElements = 10;
637 a = SafeArrayCreate(VT_UI1, 1, &bound);
638 ok(a != NULL, "SAC failed.\n");
639 ok(S_OK == SafeArrayAccessData(a, &data),"SACD failed\n");
640 memcpy(data,"Hello World\n",10);
641 ok(S_OK == SafeArrayUnaccessData(a),"SAUD failed\n");
642 V_VT(&v) = VT_ARRAY|VT_UI1;
643 V_ARRAY(&v) = a;
644 hres = VariantChangeTypeEx(&v, &v, 0, 0, VT_BSTR);
645 ok(hres==S_OK, "CTE VT_ARRAY|VT_UI1 -> VT_BSTR failed with %x\n",hres);
646 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));
647 ok(V_BSTR(&v)[0] == 0x6548,"First letter are not 'He', but %x\n", V_BSTR(&v)[0]);
648 VariantClear(&v);
649
650 VariantInit(&d);
651 V_VT(&v) = VT_BSTR;
652 V_BSTR(&v) = SysAllocStringLen(NULL, 0);
653 hres = VariantChangeTypeEx(&d, &v, 0, 0, VT_UI1|VT_ARRAY);
654 ok(hres==S_OK, "CTE VT_BSTR -> VT_UI1|VT_ARRAY failed with %x\n",hres);
655 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));
656 VariantClear(&v);
657 VariantClear(&d);
658
659 /* check locking functions */
660 a = SafeArrayCreate(VT_I4, 1, &bound);
661 ok(a!=NULL,"SAC should not fail\n");
662
663 hres = SafeArrayAccessData(a, &data);
664 ok(hres == S_OK,"SAAD failed with hres %x\n",hres);
665
666 hres = SafeArrayDestroy(a);
667 ok(hres == DISP_E_ARRAYISLOCKED,"locked safe array destroy not failed with DISP_E_ARRAYISLOCKED, but with hres %x\n", hres);
668
669 hres = SafeArrayDestroyData(a);
670 ok(hres == DISP_E_ARRAYISLOCKED,"locked safe array destroy data not failed with DISP_E_ARRAYISLOCKED, but with hres %x\n", hres);
671
672 hres = SafeArrayDestroyDescriptor(a);
673 ok(hres == DISP_E_ARRAYISLOCKED,"locked safe array destroy descriptor not failed with DISP_E_ARRAYISLOCKED, but with hres %x\n", hres);
674
675 hres = SafeArrayUnaccessData(a);
676 ok(hres == S_OK,"SAUD failed after lock/destroy test\n");
677
678 hres = SafeArrayDestroy(a);
679 ok(hres == S_OK,"SAD failed after lock/destroy test\n");
680
681 /* Test if we need to destroy data before descriptor */
682 a = SafeArrayCreate(VT_I4, 1, &bound);
683 ok(a!=NULL,"SAC should not fail\n");
684 hres = SafeArrayDestroyDescriptor(a);
685 ok(hres == S_OK,"SADD with data in array failed with hres %x\n",hres);
686
687 /* IID functions */
688 /* init a small stack safearray */
689 memset(&b, 0, sizeof(b));
690 b.cDims = 1;
691 memset(&iid, 0x42, sizeof(IID));
692 hres = SafeArraySetIID(&b, &iid);
693 ok(hres == E_INVALIDARG, "Unexpected ret value %#x.\n", hres);
694
695 hres = SafeArrayAllocDescriptor(1, &a);
696 ok(hres == S_OK, "Failed to allocate array descriptor, hr %#x.\n", hres);
697 ok((a->fFeatures & FADF_HAVEIID) == 0, "Unexpected features mask %#x.\n", a->fFeatures);
698 hres = SafeArraySetIID(a, &iid);
699 ok(hres == E_INVALIDARG, "Unexpected ret value %#x.\n", hres);
700
701 hres = SafeArrayDestroyDescriptor(a);
702 ok(hres == S_OK,"SADD failed with hres %x\n",hres);
703
704 if (!pSafeArrayAllocDescriptorEx)
705 return;
706
707 for (i = 0; i < ARRAY_SIZE(vttypes); i++) {
708 a = NULL;
709 hres = pSafeArrayAllocDescriptorEx(vttypes[i].vt,1,&a);
710 ok(hres == S_OK, "SafeArrayAllocDescriptorEx gave hres 0x%x\n", hres);
711 ok(a->fFeatures == vttypes[i].expflags,"SAADE(%d) resulted with flags %x, expected %x\n", vttypes[i].vt, a->fFeatures, vttypes[i].expflags);
712 if (a->fFeatures & FADF_HAVEIID) {
713 hres = SafeArrayGetIID(a, &iid);
714 ok(hres == S_OK,"SAGIID failed for vt %d with hres %x\n", vttypes[i].vt,hres);
715 switch (vttypes[i].vt) {
716 case VT_UNKNOWN:
717 ok(IsEqualGUID(((GUID*)a)-1,&IID_IUnknown),"guid for VT_UNKNOWN is not IID_IUnknown\n");
718 ok(IsEqualGUID(&iid, &IID_IUnknown),"SAGIID returned wrong GUID for IUnknown\n");
719 break;
720 case VT_DISPATCH:
721 ok(IsEqualGUID(((GUID*)a)-1,&IID_IDispatch),"guid for VT_UNKNOWN is not IID_IDispatch\n");
722 ok(IsEqualGUID(&iid, &IID_IDispatch),"SAGIID returned wrong GUID for IDispatch\n");
723 break;
724 default:
725 ok(FALSE,"unknown vt %d with FADF_HAVEIID\n",vttypes[i].vt);
726 break;
727 }
728 } else {
729 hres = SafeArrayGetIID(a, &iid);
730 ok(hres == E_INVALIDARG,"SAGIID did not fail for vt %d with hres %x\n", vttypes[i].vt,hres);
731 }
732 if (a->fFeatures & FADF_RECORD) {
733 ok(vttypes[i].vt == VT_RECORD,"FADF_RECORD for non record %d\n",vttypes[i].vt);
734 }
735 if (a->fFeatures & FADF_HAVEVARTYPE) {
736 ok(vttypes[i].vt == ((DWORD*)a)[-1], "FADF_HAVEVARTYPE set, but vt %d mismatch stored %d\n",vttypes[i].vt,((DWORD*)a)[-1]);
737 }
738
739 hres = pSafeArrayGetVartype(a, &vt);
740 ok(hres == S_OK, "SAGVT of array with vt %d failed with %x\n", vttypes[i].vt, hres);
741
742 if (vttypes[i].vt == VT_DISPATCH) {
743 /* Special case. Checked against Windows. */
744 ok(vt == VT_UNKNOWN, "SAGVT of array with VT_DISPATCH returned not VT_UNKNOWN, but %d\n", vt);
745 } else {
746 ok(vt == vttypes[i].vt, "SAGVT of array with vt %d returned %d\n", vttypes[i].vt, vt);
747 }
748
749 if (a->fFeatures & FADF_HAVEIID) {
750 hres = SafeArraySetIID(a, &IID_IStorage); /* random IID */
751 ok(hres == S_OK,"SASIID failed with FADF_HAVEIID set for vt %d with %x\n", vttypes[i].vt, hres);
752 hres = SafeArrayGetIID(a, &iid);
753 ok(hres == S_OK,"SAGIID failed with FADF_HAVEIID set for vt %d with %x\n", vttypes[i].vt, hres);
754 ok(IsEqualGUID(&iid, &IID_IStorage),"returned iid is not IID_IStorage\n");
755 } else {
756 hres = SafeArraySetIID(a, &IID_IStorage); /* random IID */
757 ok(hres == E_INVALIDARG,"SASIID did not failed with !FADF_HAVEIID set for vt %d with %x\n", vttypes[i].vt, hres);
758 }
759 hres = SafeArrayDestroyDescriptor(a);
760 ok(hres == S_OK,"SADD failed with hres %x\n",hres);
761 }
762 }
763
test_SafeArrayAllocDestroyDescriptor(void)764 static void test_SafeArrayAllocDestroyDescriptor(void)
765 {
766 SAFEARRAY *sa;
767 HRESULT hres;
768 UINT i;
769
770 /* Failure cases */
771 hres = SafeArrayAllocDescriptor(0, &sa);
772 ok(hres == E_INVALIDARG, "0 dimensions gave hres 0x%x\n", hres);
773
774 hres = SafeArrayAllocDescriptor(65536, &sa);
775 ok(hres == E_INVALIDARG, "65536 dimensions gave hres 0x%x\n", hres);
776
777 if (0)
778 {
779 /* Crashes on 95: XP & Wine return E_POINTER */
780 hres=SafeArrayAllocDescriptor(1, NULL);
781 ok(hres == E_POINTER,"NULL parm gave hres 0x%x\n", hres);
782 }
783
784 /* Test up to the dimension boundary case */
785 for (i = 5; i <= 65535; i += 30)
786 {
787 hres = SafeArrayAllocDescriptor(i, &sa);
788 ok(hres == S_OK, "%d dimensions failed; hres 0x%x\n", i, hres);
789
790 if (hres == S_OK)
791 {
792 ok(SafeArrayGetDim(sa) == i, "Dimension is %d; should be %d\n",
793 SafeArrayGetDim(sa), i);
794
795 hres = SafeArrayDestroyDescriptor(sa);
796 ok(hres == S_OK, "destroy failed; hres 0x%x\n", hres);
797 }
798 }
799
800 if (!pSafeArrayAllocDescriptorEx)
801 return;
802
803 hres = pSafeArrayAllocDescriptorEx(VT_UI1, 0, &sa);
804 ok(hres == E_INVALIDARG, "0 dimensions gave hres 0x%x\n", hres);
805
806 hres = pSafeArrayAllocDescriptorEx(VT_UI1, 65536, &sa);
807 ok(hres == E_INVALIDARG, "65536 dimensions gave hres 0x%x\n", hres);
808
809 hres = pSafeArrayAllocDescriptorEx(VT_UI1, 1, NULL);
810 ok(hres == E_POINTER,"NULL parm gave hres 0x%x\n", hres);
811
812 hres = pSafeArrayAllocDescriptorEx(-1, 1, &sa);
813 ok(hres == S_OK, "VT = -1 gave hres 0x%x\n", hres);
814
815 sa->rgsabound[0].cElements = 0;
816 sa->rgsabound[0].lLbound = 1;
817
818 hres = SafeArrayAllocData(sa);
819 ok(hres == S_OK, "SafeArrayAllocData gave hres 0x%x\n", hres);
820
821 hres = SafeArrayDestroy(sa);
822 ok(hres == S_OK,"SafeArrayDestroy failed with hres %x\n",hres);
823 }
824
test_SafeArrayCreateLockDestroy(void)825 static void test_SafeArrayCreateLockDestroy(void)
826 {
827 SAFEARRAYBOUND sab[4];
828 SAFEARRAY *sa;
829 HRESULT hres;
830 VARTYPE vt;
831 UINT dimension;
832
833 for (dimension = 0; dimension < ARRAY_SIZE(sab); dimension++)
834 {
835 sab[dimension].lLbound = 0;
836 sab[dimension].cElements = 8;
837 }
838
839 /* Failure cases */
840 /* This test crashes very early versions with no error checking...
841 sa = SafeArrayCreate(VT_UI1, 1, NULL);
842 ok(sa == NULL, "NULL bounds didn't fail\n");
843 */
844 sa = SafeArrayCreate(VT_UI1, 65536, sab);
845 ok(!sa, "Max bounds didn't fail\n");
846
847 memset(sab, 0, sizeof(sab));
848
849 /* Don't test 0 sized dimensions, as Windows has a bug which allows this */
850
851 for (dimension = 0; dimension < ARRAY_SIZE(sab); dimension++)
852 sab[dimension].cElements = 8;
853
854 /* Test all VARTYPES in 1-4 dimensions */
855 for (dimension = 1; dimension < 4; dimension++)
856 {
857 for (vt = VT_EMPTY; vt < VT_CLSID; vt++)
858 {
859 DWORD dwLen = SAFEARRAY_GetVTSize(vt);
860
861 sa = SafeArrayCreate(vt, dimension, sab);
862
863 if (dwLen)
864 ok(sa != NULL, "VARTYPE %d (@%d dimensions) failed\n", vt, dimension);
865 else
866 ok(sa == NULL || vt == VT_R8,
867 "VARTYPE %d (@%d dimensions) succeeded!\n", vt, dimension);
868
869 if (sa)
870 {
871 ok(SafeArrayGetDim(sa) == dimension,
872 "VARTYPE %d (@%d dimensions) cDims is %d, expected %d\n",
873 vt, dimension, SafeArrayGetDim(sa), dimension);
874 ok(SafeArrayGetElemsize(sa) == dwLen || vt == VT_R8,
875 "VARTYPE %d (@%d dimensions) cbElements is %d, expected %d\n",
876 vt, dimension, SafeArrayGetElemsize(sa), dwLen);
877
878 if (vt != VT_UNKNOWN && vt != VT_DISPATCH)
879 {
880 ok((sa->fFeatures & FADF_HAVEIID) == 0,
881 "Non interface type should not have FADF_HAVEIID\n");
882 hres = SafeArraySetIID(sa, &IID_IUnknown);
883 ok(hres == E_INVALIDARG, "Unexpected ret value %#x.\n", hres);
884 if (vt != VT_RECORD)
885 {
886 VARTYPE aVt;
887
888 ok(sa->fFeatures & FADF_HAVEVARTYPE,
889 "Non interface type should have FADF_HAVEVARTYPE\n");
890 if (pSafeArrayGetVartype)
891 {
892 hres = pSafeArrayGetVartype(sa, &aVt);
893 ok(hres == S_OK && aVt == vt,
894 "Non interface type %d: bad type %d, hres %x\n", vt, aVt, hres);
895 }
896 }
897 }
898 else
899 {
900 ok(sa->fFeatures & FADF_HAVEIID, "Interface type should have FADF_HAVEIID\n");
901 hres = SafeArraySetIID(sa, &IID_IUnknown);
902 ok(hres == S_OK, "Failed to set array IID, hres %#x.\n", hres);
903 ok((sa->fFeatures & FADF_HAVEVARTYPE) == 0,
904 "Interface type %d should not have FADF_HAVEVARTYPE\n", vt);
905 }
906
907 hres = SafeArrayLock(sa);
908 ok(hres == S_OK, "Lock VARTYPE %d (@%d dimensions) failed; hres 0x%x\n",
909 vt, dimension, hres);
910
911 if (hres == S_OK)
912 {
913 hres = SafeArrayDestroy(sa);
914 ok(hres == DISP_E_ARRAYISLOCKED,"Destroy() got hres %x\n", hres);
915
916 hres = SafeArrayDestroyData(sa);
917 ok(hres == DISP_E_ARRAYISLOCKED,"DestroyData() got hres %x\n", hres);
918
919 hres = SafeArrayDestroyDescriptor(sa);
920 ok(hres == DISP_E_ARRAYISLOCKED,"DestroyDescriptor() got hres %x\n", hres);
921
922 hres = SafeArrayUnlock(sa);
923 ok(hres == S_OK, "Unlock VARTYPE %d (@%d dims) hres 0x%x\n",
924 vt, dimension, hres);
925
926 hres = SafeArrayDestroy(sa);
927 ok(hres == S_OK, "destroy VARTYPE %d (@%d dims) hres 0x%x\n",
928 vt, dimension, hres);
929 }
930 }
931 }
932 }
933 }
934
test_VectorCreateLockDestroy(void)935 static void test_VectorCreateLockDestroy(void)
936 {
937 SAFEARRAY *sa;
938 HRESULT hres;
939 VARTYPE vt;
940 int element;
941
942 if (!pSafeArrayCreateVector)
943 {
944 win_skip("SafeArrayCreateVector not supported\n");
945 return;
946 }
947 sa = pSafeArrayCreateVector(VT_UI1, 0, 0);
948 ok(sa != NULL, "SACV with 0 elements failed.\n");
949
950 hres = SafeArrayDestroy(sa);
951 ok(hres == S_OK, "SafeArrayDestroy failed with hres %x\n",hres);
952
953 /* Test all VARTYPES in different lengths */
954 for (element = 1; element <= 101; element += 10)
955 {
956 for (vt = VT_EMPTY; vt < VT_CLSID; vt++)
957 {
958 DWORD dwLen = SAFEARRAY_GetVTSize(vt);
959
960 sa = pSafeArrayCreateVector(vt, 0, element);
961
962 if (dwLen)
963 ok(sa != NULL, "VARTYPE %d (@%d elements) failed\n", vt, element);
964 else
965 ok(sa == NULL, "VARTYPE %d (@%d elements) succeeded!\n", vt, element);
966
967 if (sa)
968 {
969 ok(SafeArrayGetDim(sa) == 1, "VARTYPE %d (@%d elements) cDims %d, not 1\n",
970 vt, element, SafeArrayGetDim(sa));
971 ok(SafeArrayGetElemsize(sa) == dwLen,
972 "VARTYPE %d (@%d elements) cbElements is %d, expected %d\n",
973 vt, element, SafeArrayGetElemsize(sa), dwLen);
974
975 hres = SafeArrayLock(sa);
976 ok(hres == S_OK, "Lock VARTYPE %d (@%d elements) failed; hres 0x%x\n",
977 vt, element, hres);
978
979 if (hres == S_OK)
980 {
981 hres = SafeArrayUnlock(sa);
982 ok(hres == S_OK, "Unlock VARTYPE %d (@%d elements) failed; hres 0x%x\n",
983 vt, element, hres);
984
985 hres = SafeArrayDestroy(sa);
986 ok(hres == S_OK, "destroy VARTYPE %d (@%d elements) failed; hres 0x%x\n",
987 vt, element, hres);
988 }
989 }
990 }
991 }
992 }
993
test_LockUnlock(void)994 static void test_LockUnlock(void)
995 {
996 SAFEARRAYBOUND sab[4];
997 SAFEARRAY *sa;
998 HRESULT hres;
999 BOOL bVector = FALSE;
1000 int dimension;
1001
1002 /* Failure cases */
1003 hres = SafeArrayLock(NULL);
1004 ok(hres == E_INVALIDARG, "Lock NULL array hres 0x%x\n", hres);
1005 hres = SafeArrayUnlock(NULL);
1006 ok(hres == E_INVALIDARG, "Lock NULL array hres 0x%x\n", hres);
1007
1008 for (dimension = 0; dimension < ARRAY_SIZE(sab); dimension++)
1009 {
1010 sab[dimension].lLbound = 0;
1011 sab[dimension].cElements = 8;
1012 }
1013
1014 sa = SafeArrayCreate(VT_UI1, ARRAY_SIZE(sab), sab);
1015
1016 /* Test maximum locks */
1017 test_LockUnlock_Vector:
1018 if (sa)
1019 {
1020 int count = 0;
1021
1022 hres = SafeArrayUnlock(sa);
1023 ok (hres == E_UNEXPECTED, "Bad %sUnlock gave hres 0x%x\n",
1024 bVector ? "vector " : "\n", hres);
1025
1026 while ((hres = SafeArrayLock(sa)) == S_OK)
1027 count++;
1028 ok (count == 65535 && hres == E_UNEXPECTED, "Lock %sfailed at %d; hres 0x%x\n",
1029 bVector ? "vector " : "\n", count, hres);
1030
1031 if (count == 65535 && hres == E_UNEXPECTED)
1032 {
1033 while ((hres = SafeArrayUnlock(sa)) == S_OK)
1034 count--;
1035 ok (count == 0 && hres == E_UNEXPECTED, "Unlock %sfailed at %d; hres 0x%x\n",
1036 bVector ? "vector " : "\n", count, hres);
1037 }
1038
1039 hres = SafeArrayDestroy(sa);
1040 ok(hres == S_OK, "got 0x%08x\n", hres);
1041 }
1042
1043 if (bVector == FALSE && pSafeArrayCreateVector)
1044 {
1045 /* Test again with a vector */
1046 sa = pSafeArrayCreateVector(VT_UI1, 0, 100);
1047 bVector = TRUE;
1048 goto test_LockUnlock_Vector;
1049 }
1050 }
1051
test_SafeArrayGetPutElement(void)1052 static void test_SafeArrayGetPutElement(void)
1053 {
1054 SAFEARRAYBOUND sab[4];
1055 LONG indices[ARRAY_SIZE(sab)], index;
1056 SAFEARRAY *sa;
1057 HRESULT hres;
1058 int value = 0, gotvalue, dimension;
1059 IRecordInfoImpl *irec;
1060 unsigned int x,y,z,a;
1061
1062 for (dimension = 0; dimension < ARRAY_SIZE(sab); dimension++)
1063 {
1064 sab[dimension].lLbound = dimension * 2 + 1;
1065 sab[dimension].cElements = dimension * 3 + 1;
1066 }
1067
1068 sa = SafeArrayCreate(VT_INT, ARRAY_SIZE(sab), sab);
1069 if (!sa)
1070 return; /* Some early versions can't handle > 3 dims */
1071
1072 ok(sa->cbElements == sizeof(value), "int size mismatch\n");
1073
1074 /* Failure cases */
1075 for (x = 0; x < ARRAY_SIZE(sab); x++)
1076 {
1077 indices[0] = sab[0].lLbound;
1078 indices[1] = sab[1].lLbound;
1079 indices[2] = sab[2].lLbound;
1080 indices[3] = sab[3].lLbound;
1081
1082 indices[x] = indices[x] - 1;
1083 hres = SafeArrayPutElement(sa, indices, &value);
1084 ok(hres == DISP_E_BADINDEX, "Put allowed too small index in dimension %d\n", x);
1085 hres = SafeArrayGetElement(sa, indices, &value);
1086 ok(hres == DISP_E_BADINDEX, "Get allowed too small index in dimension %d\n", x);
1087
1088 indices[x] = sab[x].lLbound + sab[x].cElements;
1089 hres = SafeArrayPutElement(sa, indices, &value);
1090 ok(hres == DISP_E_BADINDEX, "Put allowed too big index in dimension %d\n", x);
1091 hres = SafeArrayGetElement(sa, indices, &value);
1092 ok(hres == DISP_E_BADINDEX, "Get allowed too big index in dimension %d\n", x);
1093 }
1094
1095 indices[0] = sab[0].lLbound;
1096 indices[1] = sab[1].lLbound;
1097 indices[2] = sab[2].lLbound;
1098 indices[3] = sab[3].lLbound;
1099
1100 hres = SafeArrayPutElement(NULL, indices, &value);
1101 ok(hres == E_INVALIDARG, "Put NULL array hres 0x%x\n", hres);
1102 hres = SafeArrayGetElement(NULL, indices, &value);
1103 ok(hres == E_INVALIDARG, "Get NULL array hres 0x%x\n", hres);
1104
1105 hres = SafeArrayPutElement(sa, NULL, &value);
1106 ok(hres == E_INVALIDARG, "Put NULL indices hres 0x%x\n", hres);
1107 hres = SafeArrayGetElement(sa, NULL, &value);
1108 ok(hres == E_INVALIDARG, "Get NULL indices hres 0x%x\n", hres);
1109
1110 if (0)
1111 {
1112 /* This is retarded. Windows checks every case of invalid parameters
1113 * except the following, which crashes. We ERR this in Wine.
1114 */
1115 hres = SafeArrayPutElement(sa, indices, NULL);
1116 ok(hres == E_INVALIDARG, "Put NULL value hres 0x%x\n", hres);
1117 }
1118
1119 hres = SafeArrayGetElement(sa, indices, NULL);
1120 ok(hres == E_INVALIDARG, "Get NULL value hres 0x%x\n", hres);
1121
1122 value = 0;
1123
1124 /* Make sure we can read and get back the correct values in 4 dimensions,
1125 * Each with a different size and lower bound.
1126 */
1127 for (x = 0; x < sab[0].cElements; x++)
1128 {
1129 indices[0] = sab[0].lLbound + x;
1130 for (y = 0; y < sab[1].cElements; y++)
1131 {
1132 indices[1] = sab[1].lLbound + y;
1133 for (z = 0; z < sab[2].cElements; z++)
1134 {
1135 indices[2] = sab[2].lLbound + z;
1136 for (a = 0; a < sab[3].cElements; a++)
1137 {
1138 indices[3] = sab[3].lLbound + a;
1139 hres = SafeArrayPutElement(sa, indices, &value);
1140 ok(hres == S_OK, "Failed to put element at (%d,%d,%d,%d) hres 0x%x\n",
1141 x, y, z, a, hres);
1142 value++;
1143 }
1144 }
1145 }
1146 }
1147
1148 value = 0;
1149
1150 for (x = 0; x < sab[0].cElements; x++)
1151 {
1152 indices[0] = sab[0].lLbound + x;
1153 for (y = 0; y < sab[1].cElements; y++)
1154 {
1155 indices[1] = sab[1].lLbound + y;
1156 for (z = 0; z < sab[2].cElements; z++)
1157 {
1158 indices[2] = sab[2].lLbound + z;
1159 for (a = 0; a < sab[3].cElements; a++)
1160 {
1161 indices[3] = sab[3].lLbound + a;
1162 gotvalue = value / 3;
1163 hres = SafeArrayGetElement(sa, indices, &gotvalue);
1164 ok(hres == S_OK, "Failed to get element at (%d,%d,%d,%d) hres 0x%x\n",
1165 x, y, z, a, hres);
1166 if (hres == S_OK)
1167 ok(value == gotvalue, "Got value %d instead of %d at (%d,%d,%d,%d)\n",
1168 gotvalue, value, x, y, z, a);
1169 value++;
1170 }
1171 }
1172 }
1173 }
1174 hres = SafeArrayDestroy(sa);
1175 ok(hres == S_OK, "got 0x%08x\n", hres);
1176
1177 /* VT_RECORD array */
1178 irec = IRecordInfoImpl_Construct();
1179 irec->ref = 1;
1180
1181 sab[0].lLbound = 0;
1182 sab[0].cElements = 8;
1183
1184 sa = pSafeArrayCreateEx(VT_RECORD, 1, sab, &irec->IRecordInfo_iface);
1185 ok(sa != NULL, "failed to create array\n");
1186 ok(irec->ref == 2, "got %d\n", irec->ref);
1187
1188 index = 0;
1189 irec->recordcopy = 0;
1190 hres = SafeArrayPutElement(sa, &index, (void*)0xdeadbeef);
1191 ok(hres == S_OK, "got 0x%08x\n", hres);
1192 ok(irec->recordcopy == 1, "got %d\n", irec->recordcopy);
1193
1194 index = 0;
1195 irec->recordcopy = 0;
1196 hres = SafeArrayGetElement(sa, &index, (void*)0xdeadbeef);
1197 ok(hres == S_OK, "got 0x%08x\n", hres);
1198 ok(irec->recordcopy == 1, "got %d\n", irec->recordcopy);
1199
1200 hres = SafeArrayDestroy(sa);
1201 ok(hres == S_OK, "got 0x%08x\n", hres);
1202 ok(irec->ref == 1, "got %d\n", irec->ref);
1203 IRecordInfo_Release(&irec->IRecordInfo_iface);
1204 }
1205
test_SafeArrayGetPutElement_BSTR(void)1206 static void test_SafeArrayGetPutElement_BSTR(void)
1207 {
1208 SAFEARRAYBOUND sab;
1209 LONG indices[1];
1210 SAFEARRAY *sa;
1211 HRESULT hres;
1212 BSTR value = 0, gotvalue;
1213 const OLECHAR szTest[5] = { 'T','e','s','t','\0' };
1214
1215 sab.lLbound = 1;
1216 sab.cElements = 1;
1217
1218 sa = SafeArrayCreate(VT_BSTR, 1, &sab);
1219 ok(sa != NULL, "BSTR test couldn't create array\n");
1220 if (!sa)
1221 return;
1222
1223 ok(sa->cbElements == sizeof(BSTR), "BSTR size mismatch\n");
1224
1225 indices[0] = sab.lLbound;
1226 value = SysAllocString(szTest);
1227 ok (value != NULL, "Expected non-NULL\n");
1228 hres = SafeArrayPutElement(sa, indices, value);
1229 ok(hres == S_OK, "Failed to put bstr element hres 0x%x\n", hres);
1230 gotvalue = NULL;
1231 hres = SafeArrayGetElement(sa, indices, &gotvalue);
1232 ok(hres == S_OK, "Failed to get bstr element at hres 0x%x\n", hres);
1233 if (hres == S_OK)
1234 ok(SysStringLen(value) == SysStringLen(gotvalue), "Got len %d instead of %d\n", SysStringLen(gotvalue), SysStringLen(value));
1235 hres = SafeArrayDestroy(sa);
1236 ok(hres == S_OK, "got 0x%08x\n", hres);
1237 SysFreeString(value);
1238 SysFreeString(gotvalue);
1239 }
1240
1241 struct xtunk_impl {
1242 IUnknown IUnknown_iface;
1243 LONG ref;
1244 };
1245 static const IUnknownVtbl xtunk_vtbl;
1246
1247 static struct xtunk_impl xtunk = {{&xtunk_vtbl}, 0};
1248
tunk_QueryInterface(IUnknown * punk,REFIID riid,void ** x)1249 static HRESULT WINAPI tunk_QueryInterface(IUnknown *punk, REFIID riid, void **x)
1250 {
1251 return E_FAIL;
1252 }
1253
tunk_AddRef(IUnknown * punk)1254 static ULONG WINAPI tunk_AddRef(IUnknown *punk)
1255 {
1256 return ++xtunk.ref;
1257 }
1258
tunk_Release(IUnknown * punk)1259 static ULONG WINAPI tunk_Release(IUnknown *punk)
1260 {
1261 return --xtunk.ref;
1262 }
1263
1264 static const IUnknownVtbl xtunk_vtbl = {
1265 tunk_QueryInterface,
1266 tunk_AddRef,
1267 tunk_Release
1268 };
1269
test_SafeArrayGetPutElement_IUnknown(void)1270 static void test_SafeArrayGetPutElement_IUnknown(void)
1271 {
1272 SAFEARRAYBOUND sab;
1273 LONG indices[1];
1274 SAFEARRAY *sa;
1275 HRESULT hres;
1276 IUnknown *gotvalue;
1277
1278 sab.lLbound = 1;
1279 sab.cElements = 1;
1280 sa = SafeArrayCreate(VT_UNKNOWN, 1, &sab);
1281 ok(sa != NULL, "UNKNOWN test couldn't create array\n");
1282 if (!sa)
1283 return;
1284
1285 ok(sa->cbElements == sizeof(LPUNKNOWN), "LPUNKNOWN size mismatch\n");
1286
1287 indices[0] = sab.lLbound;
1288 xtunk.ref = 1;
1289 hres = SafeArrayPutElement(sa, indices, &xtunk.IUnknown_iface);
1290 ok(hres == S_OK, "Failed to put bstr element hres 0x%x\n", hres);
1291 ok(xtunk.ref == 2,"Failed to increment refcount of iface.\n");
1292 gotvalue = NULL;
1293 hres = SafeArrayGetElement(sa, indices, &gotvalue);
1294 ok(xtunk.ref == 3,"Failed to increment refcount of iface.\n");
1295 ok(hres == S_OK, "Failed to get bstr element at hres 0x%x\n", hres);
1296 if (hres == S_OK)
1297 ok(gotvalue == &xtunk.IUnknown_iface, "Got %p instead of %p\n", gotvalue, &xtunk.IUnknown_iface);
1298 hres = SafeArrayDestroy(sa);
1299 ok(hres == S_OK, "got 0x%08x\n", hres);
1300 ok(xtunk.ref == 2,"Failed to decrement refcount of iface.\n");
1301 }
1302
test_SafeArrayRedim_IUnknown(void)1303 static void test_SafeArrayRedim_IUnknown(void)
1304 {
1305 SAFEARRAYBOUND sab;
1306 LONG indices[1];
1307 SAFEARRAY *sa;
1308 HRESULT hres;
1309
1310 sab.lLbound = 1;
1311 sab.cElements = 2;
1312 sa = SafeArrayCreate(VT_UNKNOWN, 1, &sab);
1313 ok(sa != NULL, "UNKNOWN test couldn't create array\n");
1314 if (!sa)
1315 return;
1316
1317 ok(sa->cbElements == sizeof(LPUNKNOWN), "LPUNKNOWN size mismatch\n");
1318
1319 indices[0] = 2;
1320 xtunk.ref = 1;
1321 hres = SafeArrayPutElement(sa, indices, &xtunk.IUnknown_iface);
1322 ok(hres == S_OK, "Failed to put IUnknown element hres 0x%x\n", hres);
1323 ok(xtunk.ref == 2,"Failed to increment refcount of iface.\n");
1324 sab.cElements = 1;
1325 hres = SafeArrayRedim(sa, &sab);
1326 ok(hres == S_OK, "Failed to shrink array hres 0x%x\n", hres);
1327 ok(xtunk.ref == 1, "Failed to decrement refcount\n");
1328 hres = SafeArrayDestroy(sa);
1329 ok(hres == S_OK, "got 0x%08x\n", hres);
1330 }
1331
test_SafeArrayGetPutElement_VARIANT(void)1332 static void test_SafeArrayGetPutElement_VARIANT(void)
1333 {
1334 SAFEARRAYBOUND sab;
1335 LONG indices[1];
1336 SAFEARRAY *sa;
1337 HRESULT hres;
1338 VARIANT value, gotvalue;
1339
1340 sab.lLbound = 1;
1341 sab.cElements = 1;
1342 sa = SafeArrayCreate(VT_VARIANT, 1, &sab);
1343 ok(sa != NULL, "VARIANT test couldn't create array\n");
1344 if (!sa)
1345 return;
1346
1347 ok(sa->cbElements == sizeof(VARIANT), "VARIANT size mismatch\n");
1348
1349 indices[0] = sab.lLbound;
1350 V_VT(&value) = VT_I4;
1351 V_I4(&value) = 0x42424242;
1352 hres = SafeArrayPutElement(sa, indices, &value);
1353 ok(hres == S_OK, "Failed to put Variant I4 element hres 0x%x\n", hres);
1354
1355 V_VT(&gotvalue) = 0xdead;
1356 hres = SafeArrayGetElement(sa, indices, &gotvalue);
1357 ok(hres == S_OK, "Failed to get variant element at hres 0x%x\n", hres);
1358
1359 V_VT(&gotvalue) = VT_EMPTY;
1360 hres = SafeArrayGetElement(sa, indices, &gotvalue);
1361 ok(hres == S_OK, "Failed to get variant element at hres 0x%x\n", hres);
1362 if (hres == S_OK) {
1363 ok(V_VT(&value) == V_VT(&gotvalue), "Got type 0x%x instead of 0x%x\n", V_VT(&value), V_VT(&gotvalue));
1364 if (V_VT(&value) == V_VT(&gotvalue))
1365 ok(V_I4(&value) == V_I4(&gotvalue), "Got %d instead of %d\n", V_I4(&value), V_VT(&gotvalue));
1366 }
1367 hres = SafeArrayDestroy(sa);
1368 ok(hres == S_OK, "got 0x%08x\n", hres);
1369 }
1370
test_SafeArrayCopyData(void)1371 static void test_SafeArrayCopyData(void)
1372 {
1373 SAFEARRAYBOUND sab[4];
1374 SAFEARRAY *sa;
1375 SAFEARRAY *sacopy;
1376 HRESULT hres;
1377 int dimension, size = 1, i;
1378
1379 if (!pSafeArrayCopyData)
1380 {
1381 win_skip("SafeArrayCopyData not supported\n");
1382 return;
1383 }
1384
1385 for (dimension = 0; dimension < ARRAY_SIZE(sab); dimension++)
1386 {
1387 sab[dimension].lLbound = dimension * 2 + 2;
1388 sab[dimension].cElements = dimension * 3 + 1;
1389 size *= sab[dimension].cElements;
1390 }
1391
1392 sa = SafeArrayCreate(VT_INT, ARRAY_SIZE(sab), sab);
1393 ok(sa != NULL, "Copy test couldn't create array\n");
1394 sacopy = SafeArrayCreate(VT_INT, ARRAY_SIZE(sab), sab);
1395 ok(sacopy != NULL, "Copy test couldn't create copy array\n");
1396
1397 if (!sa || !sacopy)
1398 return;
1399
1400 ok(sa->cbElements == sizeof(int), "int size mismatch\n");
1401
1402 /* Fill the source array with some data; it doesn't matter what */
1403 for (dimension = 0; dimension < size; dimension++)
1404 {
1405 int* data = sa->pvData;
1406 data[dimension] = dimension;
1407 }
1408
1409 hres = pSafeArrayCopyData(sa, sacopy);
1410 ok(hres == S_OK, "copy data failed hres 0x%x\n", hres);
1411 if (hres == S_OK)
1412 {
1413 ok(!memcmp(sa->pvData, sacopy->pvData, size * sizeof(int)), "compared different\n");
1414 }
1415
1416 /* Failure cases */
1417 hres = pSafeArrayCopyData(NULL, sacopy);
1418 ok(hres == E_INVALIDARG, "Null copy source hres 0x%x\n", hres);
1419 hres = pSafeArrayCopyData(sa, NULL);
1420 ok(hres == E_INVALIDARG, "Null copy hres 0x%x\n", hres);
1421
1422 sacopy->rgsabound[0].cElements += 1;
1423 hres = pSafeArrayCopyData(sa, sacopy);
1424 ok(hres == E_INVALIDARG, "Bigger copy first dimension hres 0x%x\n", hres);
1425
1426 sacopy->rgsabound[0].cElements -= 2;
1427 hres = pSafeArrayCopyData(sa, sacopy);
1428 ok(hres == E_INVALIDARG, "Smaller copy first dimension hres 0x%x\n", hres);
1429 sacopy->rgsabound[0].cElements += 1;
1430
1431 sacopy->rgsabound[3].cElements += 1;
1432 hres = pSafeArrayCopyData(sa, sacopy);
1433 ok(hres == E_INVALIDARG, "Bigger copy last dimension hres 0x%x\n", hres);
1434
1435 sacopy->rgsabound[3].cElements -= 2;
1436 hres = pSafeArrayCopyData(sa, sacopy);
1437 ok(hres == E_INVALIDARG, "Smaller copy last dimension hres 0x%x\n", hres);
1438 sacopy->rgsabound[3].cElements += 1;
1439
1440 hres = SafeArrayDestroy(sacopy);
1441 ok(hres == S_OK, "got 0x%08x\n", hres);
1442 sacopy = NULL;
1443 hres = pSafeArrayCopyData(sa, sacopy);
1444 ok(hres == E_INVALIDARG, "->Null copy hres 0x%x\n", hres);
1445
1446 hres = SafeArrayCopy(sa, &sacopy);
1447 ok(hres == S_OK, "copy failed hres 0x%x\n", hres);
1448 ok(SafeArrayGetElemsize(sa) == SafeArrayGetElemsize(sacopy),"elemsize wrong\n");
1449 ok(SafeArrayGetDim(sa) == SafeArrayGetDim(sacopy),"dimensions wrong\n");
1450 ok(!memcmp(sa->pvData, sacopy->pvData, size * sizeof(int)), "compared different\n");
1451 hres = SafeArrayDestroy(sacopy);
1452 ok(hres == S_OK, "got 0x%08x\n", hres);
1453
1454 sacopy = SafeArrayCreate(VT_INT, ARRAY_SIZE(sab), sab);
1455 ok(sacopy != NULL, "Copy test couldn't create copy array\n");
1456 ok(sacopy->fFeatures == FADF_HAVEVARTYPE, "0x%04x\n", sacopy->fFeatures);
1457
1458 for (i = 0; i < ARRAY_SIZE(ignored_copy_features); i++)
1459 {
1460 USHORT feature = ignored_copy_features[i];
1461 USHORT orig = sacopy->fFeatures;
1462
1463 sa->fFeatures |= feature;
1464 hres = SafeArrayCopyData(sa, sacopy);
1465 ok(hres == S_OK, "got 0x%08x\n", hres);
1466 ok(sacopy->fFeatures == orig && orig == FADF_HAVEVARTYPE, "got features 0x%04x\n", sacopy->fFeatures);
1467 sa->fFeatures &= ~feature;
1468 }
1469
1470 hres = SafeArrayDestroy(sacopy);
1471 ok(hres == S_OK, "got 0x%08x\n", hres);
1472 hres = SafeArrayDestroy(sa);
1473 ok(hres == S_OK, "got 0x%08x\n", hres);
1474
1475 /* copy data from a vector */
1476 sa = SafeArrayCreateVector(VT_UI1, 0, 2);
1477
1478 sacopy = SafeArrayCreateVector(VT_UI1, 0, 2);
1479 ok(sa->fFeatures == (FADF_HAVEVARTYPE|FADF_CREATEVECTOR) ||
1480 broken(sa->fFeatures == FADF_CREATEVECTOR /* W2k */),
1481 "got 0x%08x\n", sa->fFeatures);
1482 ok(sacopy->fFeatures == (FADF_HAVEVARTYPE|FADF_CREATEVECTOR) ||
1483 broken(sacopy->fFeatures == FADF_CREATEVECTOR /* W2k */),
1484 "got 0x%08x\n", sacopy->fFeatures);
1485 hres = SafeArrayCopyData(sa, sacopy);
1486 ok(hres == S_OK, "got 0x%08x\n", hres);
1487 ok(sacopy->fFeatures == (FADF_HAVEVARTYPE|FADF_CREATEVECTOR) ||
1488 broken(sacopy->fFeatures == FADF_CREATEVECTOR /* W2k */),
1489 "got 0x%04x\n", sacopy->fFeatures);
1490 SafeArrayDestroy(sacopy);
1491
1492 sacopy = SafeArrayCreate(VT_UI1, ARRAY_SIZE(sab), sab);
1493 ok(sacopy != NULL, "Copy test couldn't create copy array\n");
1494 ok(sacopy->fFeatures == FADF_HAVEVARTYPE, "0x%04x\n", sacopy->fFeatures);
1495 hres = SafeArrayCopyData(sa, sacopy);
1496 ok(hres == E_INVALIDARG, "got 0x%08x\n", hres);
1497 SafeArrayDestroy(sacopy);
1498
1499 SafeArrayDestroy(sa);
1500 }
1501
test_SafeArrayCreateEx(void)1502 static void test_SafeArrayCreateEx(void)
1503 {
1504 IRecordInfoImpl* iRec;
1505 SAFEARRAYBOUND sab[4];
1506 SAFEARRAY *sa;
1507 HRESULT hres;
1508 UINT dimension;
1509
1510 if (!pSafeArrayCreateEx)
1511 {
1512 win_skip("SafeArrayCreateEx not supported\n");
1513 return;
1514 }
1515
1516 for (dimension = 0; dimension < ARRAY_SIZE(sab); dimension++)
1517 {
1518 sab[dimension].lLbound = 0;
1519 sab[dimension].cElements = 8;
1520 }
1521
1522 /* Failure cases */
1523 sa = pSafeArrayCreateEx(VT_UI1, 1, NULL, NULL);
1524 ok(sa == NULL, "CreateEx NULL bounds didn't fail\n");
1525
1526 /* test IID storage & defaulting */
1527 sa = pSafeArrayCreateEx(VT_DISPATCH, 1, sab, (PVOID)&IID_ITypeInfo);
1528 ok(sa != NULL, "CreateEx (ITypeInfo) failed\n");
1529
1530 if (sa)
1531 {
1532 GUID guid;
1533
1534 hres = SafeArrayGetIID(sa, &guid);
1535 ok(hres == S_OK, "Failed to get array IID, hres %#x.\n", hres);
1536 ok(IsEqualGUID(&guid, &IID_ITypeInfo), "CreateEx (ITypeInfo) bad IID\n");
1537 hres = SafeArraySetIID(sa, &IID_IUnknown);
1538 ok(hres == S_OK, "Failed to set IID, hres = %8x\n", hres);
1539 hres = SafeArrayGetIID(sa, &guid);
1540 ok(hres == S_OK && IsEqualGUID(&guid, &IID_IUnknown), "Set bad IID\n");
1541 hres = SafeArrayDestroy(sa);
1542 ok(hres == S_OK, "got 0x%08x\n", hres);
1543 }
1544
1545 sa = pSafeArrayCreateEx(VT_DISPATCH, 1, sab, NULL);
1546 ok(sa != NULL, "CreateEx (NULL) failed\n");
1547
1548 if (sa)
1549 {
1550 GUID guid;
1551
1552 hres = SafeArrayGetIID(sa, &guid);
1553 ok(hres == S_OK, "Failed to get array IID, hres %#x.\n", hres);
1554 ok(IsEqualGUID(&guid, &IID_IDispatch), "CreateEx (NULL) bad IID\n");
1555 hres = SafeArrayDestroy(sa);
1556 ok(hres == S_OK, "got 0x%08x\n", hres);
1557 }
1558
1559 sa = pSafeArrayCreateEx(VT_UNKNOWN, 1, sab, NULL);
1560 ok(sa != NULL, "CreateEx (NULL-Unk) failed\n");
1561
1562 if (sa)
1563 {
1564 GUID guid;
1565
1566 hres = SafeArrayGetIID(sa, &guid);
1567 ok(hres == S_OK, "Failed to get array IID, hres %#x.\n", hres);
1568 ok(IsEqualGUID(&guid, &IID_IUnknown), "CreateEx (NULL-Unk) bad IID\n");
1569 hres = SafeArrayDestroy(sa);
1570 ok(hres == S_OK, "got 0x%08x\n", hres);
1571 }
1572
1573 /* VT_RECORD failure case */
1574 sa = pSafeArrayCreateEx(VT_RECORD, 1, sab, NULL);
1575 ok(sa == NULL, "CreateEx (NULL-Rec) succeeded\n");
1576
1577 iRec = IRecordInfoImpl_Construct();
1578
1579 /* Win32 doesn't care if GetSize fails */
1580 fail_GetSize = TRUE;
1581 sa = pSafeArrayCreateEx(VT_RECORD, 1, sab, &iRec->IRecordInfo_iface);
1582 ok(sa != NULL, "CreateEx (Fail Size) failed\n");
1583 ok(iRec->ref == START_REF_COUNT + 1, "Wrong iRec refcount %d\n", iRec->ref);
1584 ok(iRec->sizeCalled == 1, "GetSize called %d times\n", iRec->sizeCalled);
1585 ok(iRec->clearCalled == 0, "Clear called %d times\n", iRec->clearCalled);
1586 if (sa)
1587 {
1588 ok(sa->cbElements == RECORD_SIZE_FAIL, "Altered size to %d\n", sa->cbElements);
1589 hres = SafeArrayDestroy(sa);
1590 ok(hres == S_OK, "got 0x%08x\n", hres);
1591 ok(iRec->clearCalled == sab[0].cElements, "Destroy->Clear called %d times\n", iRec->clearCalled);
1592 ok(iRec->ref == START_REF_COUNT, "got %d, expected %d\n", iRec->ref, START_REF_COUNT);
1593 }
1594
1595 /* Test VT_RECORD array */
1596 fail_GetSize = FALSE;
1597 iRec->ref = START_REF_COUNT;
1598 iRec->sizeCalled = 0;
1599 iRec->clearCalled = 0;
1600 sa = pSafeArrayCreateEx(VT_RECORD, 1, sab, &iRec->IRecordInfo_iface);
1601 ok(sa != NULL, "CreateEx (Rec) failed\n");
1602 ok(iRec->ref == START_REF_COUNT + 1, "Wrong iRec refcount %d\n", iRec->ref);
1603 ok(iRec->sizeCalled == 1, "GetSize called %d times\n", iRec->sizeCalled);
1604 ok(iRec->clearCalled == 0, "Clear called %d times\n", iRec->clearCalled);
1605 if (sa && pSafeArrayGetRecordInfo)
1606 {
1607 IRecordInfo* saRec = NULL;
1608 SAFEARRAY *sacopy;
1609
1610 hres = pSafeArrayGetRecordInfo(sa, &saRec);
1611 ok(hres == S_OK,"GRI failed\n");
1612 ok(saRec == &iRec->IRecordInfo_iface, "Different saRec\n");
1613 ok(iRec->ref == START_REF_COUNT + 2, "Didn't AddRef %d\n", iRec->ref);
1614 IRecordInfo_Release(saRec);
1615
1616 ok(sa->cbElements == RECORD_SIZE,"Elemsize is %d\n", sa->cbElements);
1617
1618 /* try to copy record based arrays */
1619 sacopy = pSafeArrayCreateEx(VT_RECORD, 1, sab, &iRec->IRecordInfo_iface);
1620 iRec->recordcopy = 0;
1621 iRec->clearCalled = 0;
1622 /* array copy code doesn't explicitly clear a record */
1623 hres = SafeArrayCopyData(sa, sacopy);
1624 ok(hres == S_OK, "got 0x%08x\n", hres);
1625 ok(iRec->recordcopy == sab[0].cElements, "got %d\n", iRec->recordcopy);
1626 ok(iRec->clearCalled == 0, "got %d\n", iRec->clearCalled);
1627
1628 hres = SafeArrayDestroy(sacopy);
1629 ok(hres == S_OK, "got 0x%08x\n", hres);
1630
1631 iRec->clearCalled = 0;
1632 iRec->sizeCalled = 0;
1633 hres = SafeArrayDestroy(sa);
1634 ok(hres == S_OK, "got 0x%08x\n", hres);
1635 ok(iRec->sizeCalled == 0, "Destroy->GetSize called %d times\n", iRec->sizeCalled);
1636 ok(iRec->clearCalled == sab[0].cElements, "Destroy->Clear called %d times\n", iRec->clearCalled);
1637 ok(iRec->ref == START_REF_COUNT, "Wrong iRec refcount %d\n", iRec->ref);
1638 }
1639 else
1640 {
1641 hres = SafeArrayDestroy(sa);
1642 ok(hres == S_OK, "got 0x%08x\n", hres);
1643 }
1644
1645 IRecordInfo_Release(&iRec->IRecordInfo_iface);
1646 }
1647
test_SafeArrayClear(void)1648 static void test_SafeArrayClear(void)
1649 {
1650 SAFEARRAYBOUND sab;
1651 SAFEARRAY *sa;
1652 VARIANTARG v;
1653 HRESULT hres;
1654
1655 sab.lLbound = 0;
1656 sab.cElements = 10;
1657 sa = SafeArrayCreate(VT_UI1, 1, &sab);
1658 ok(sa != NULL, "Create() failed.\n");
1659 if (!sa)
1660 return;
1661
1662 /* Test clearing non-NULL variants containing arrays */
1663 V_VT(&v) = VT_ARRAY|VT_UI1;
1664 V_ARRAY(&v) = sa;
1665 hres = VariantClear(&v);
1666 ok(hres == S_OK && V_VT(&v) == VT_EMPTY, "VariantClear: hres 0x%x, Type %d\n", hres, V_VT(&v));
1667 ok(V_ARRAY(&v) == sa, "VariantClear: Overwrote value\n");
1668
1669 sa = SafeArrayCreate(VT_UI1, 1, &sab);
1670 ok(sa != NULL, "Create() failed.\n");
1671 if (!sa)
1672 return;
1673
1674 V_VT(&v) = VT_SAFEARRAY;
1675 V_ARRAY(&v) = sa;
1676 hres = VariantClear(&v);
1677 ok(hres == DISP_E_BADVARTYPE, "VariantClear: hres 0x%x\n", hres);
1678
1679 V_VT(&v) = VT_SAFEARRAY|VT_BYREF;
1680 V_ARRAYREF(&v) = &sa;
1681 hres = VariantClear(&v);
1682 ok(hres == DISP_E_BADVARTYPE, "VariantClear: hres 0x%x\n", hres);
1683
1684 hres = SafeArrayDestroy(sa);
1685 ok(hres == S_OK, "got 0x%08x\n", hres);
1686 }
1687
test_SafeArrayCopy(void)1688 static void test_SafeArrayCopy(void)
1689 {
1690 SAFEARRAYBOUND sab;
1691 SAFEARRAY *sa, *sa2;
1692 VARIANTARG vSrc, vDst;
1693 HRESULT hres;
1694 int i;
1695
1696 sab.lLbound = 0;
1697 sab.cElements = 10;
1698 sa = SafeArrayCreate(VT_UI1, 1, &sab);
1699 ok(sa != NULL, "Create() failed.\n");
1700 if (!sa)
1701 return;
1702
1703 /* Test copying non-NULL variants containing arrays */
1704 V_VT(&vSrc) = (VT_ARRAY|VT_BYREF|VT_UI1);
1705 V_ARRAYREF(&vSrc) = &sa;
1706 V_VT(&vDst) = VT_EMPTY;
1707
1708 hres = VariantCopy(&vDst, &vSrc);
1709 ok(hres == S_OK && V_VT(&vDst) == (VT_ARRAY|VT_BYREF|VT_UI1),
1710 "VariantCopy: hres 0x%x, Type %d\n", hres, V_VT(&vDst));
1711 ok(V_ARRAYREF(&vDst) == &sa, "VariantClear: Performed deep copy\n");
1712
1713 V_VT(&vSrc) = (VT_ARRAY|VT_UI1);
1714 V_ARRAY(&vSrc) = sa;
1715 V_VT(&vDst) = VT_EMPTY;
1716
1717 hres = VariantCopy(&vDst, &vSrc);
1718 ok(hres == S_OK && V_VT(&vDst) == (VT_ARRAY|VT_UI1),
1719 "VariantCopy: hres 0x%x, Type %d\n", hres, V_VT(&vDst));
1720 ok(V_ARRAY(&vDst) != sa, "VariantClear: Performed shallow copy\n");
1721
1722 hres = SafeArrayDestroy(V_ARRAY(&vSrc));
1723 ok(hres == S_OK, "got 0x%08x\n", hres);
1724 hres = SafeArrayDestroy(V_ARRAY(&vDst));
1725 ok(hres == S_OK, "got 0x%08x\n", hres);
1726
1727 hres = SafeArrayAllocDescriptor(1, &sa);
1728 ok(hres == S_OK, "SafeArrayAllocDescriptor failed with error 0x%08x\n", hres);
1729
1730 sa->cbElements = 16;
1731 hres = SafeArrayCopy(sa, &sa2);
1732 ok(hres == S_OK, "SafeArrayCopy failed with error 0x%08x\n", hres);
1733 ok(sa != sa2, "SafeArrayCopy performed shallow copy\n");
1734
1735 hres = SafeArrayDestroy(sa2);
1736 ok(hres == S_OK, "got 0x%08x\n", hres);
1737 hres = SafeArrayDestroy(sa);
1738 ok(hres == S_OK, "got 0x%08x\n", hres);
1739
1740 sa2 = (void*)0xdeadbeef;
1741 hres = SafeArrayCopy(NULL, &sa2);
1742 ok(hres == S_OK, "SafeArrayCopy failed with error 0x%08x\n", hres);
1743 ok(!sa2, "SafeArrayCopy didn't return NULL for output array\n");
1744
1745 hres = SafeArrayAllocDescriptor(1, &sa);
1746 ok(hres == S_OK, "SafeArrayAllocDescriptor failed with error 0x%08x\n", hres);
1747
1748 sa2 = (void*)0xdeadbeef;
1749 hres = SafeArrayCopy(sa, &sa2);
1750 ok(hres == E_INVALIDARG,
1751 "SafeArrayCopy with empty array should have failed with error E_INVALIDARG instead of 0x%08x\n",
1752 hres);
1753 ok(!sa2, "SafeArrayCopy didn't return NULL for output array\n");
1754
1755 hres = SafeArrayDestroy(sa2);
1756 ok(hres == S_OK, "got 0x%08x\n", hres);
1757 hres = SafeArrayDestroy(sa);
1758 ok(hres == S_OK, "got 0x%08x\n", hres);
1759
1760 /* test feature copy */
1761 hres = SafeArrayAllocDescriptor(1, &sa);
1762 ok(hres == S_OK, "SafeArrayAllocDescriptor failed with error 0x%08x\n", hres);
1763 ok(sa->fFeatures == 0, "got src features 0x%04x\n", sa->fFeatures);
1764 sa->cbElements = 16;
1765
1766 for (i = 0; i < ARRAY_SIZE(ignored_copy_features); i++)
1767 {
1768 USHORT feature = ignored_copy_features[i];
1769
1770 sa->fFeatures |= feature;
1771 hres = SafeArrayCopy(sa, &sa2);
1772 ok(hres == S_OK, "got 0x%08x\n", hres);
1773 ok(sa2->fFeatures == 0, "got features 0x%04x\n", sa2->fFeatures);
1774 hres = SafeArrayDestroy(sa2);
1775 ok(hres == S_OK, "got 0x%08x\n", hres);
1776 sa->fFeatures &= ~feature;
1777 }
1778
1779 SafeArrayDestroy(sa);
1780
1781 /* copy from a vector */
1782 sa = SafeArrayCreateVector(VT_UI1, 0, 2);
1783 ok(sa->fFeatures == (FADF_HAVEVARTYPE|FADF_CREATEVECTOR) ||
1784 broken(sa->fFeatures == FADF_CREATEVECTOR /* W2k */),
1785 "got 0x%08x\n", sa->fFeatures);
1786 hres = SafeArrayCopy(sa, &sa2);
1787 ok(hres == S_OK, "got 0x%08x\n", hres);
1788 ok(sa2->fFeatures == FADF_HAVEVARTYPE ||
1789 broken(!sa2->fFeatures /* W2k */), "got 0x%04x\n",
1790 sa2->fFeatures);
1791
1792 SafeArrayDestroy(sa2);
1793 SafeArrayDestroy(sa);
1794 }
1795
1796 #define MKARRAY(low,num,typ) sab.lLbound = low; sab.cElements = num; \
1797 sa = SafeArrayCreate(typ, 1, &sab); ok(sa != NULL, "Create() failed.\n"); \
1798 if (!sa) return; \
1799 V_VT(&v) = VT_ARRAY|typ; V_ARRAY(&v) = sa; VariantInit(&v2)
1800
1801 #define MKARRAYCONT(low,num,typ) sab.lLbound = low; sab.cElements = num; \
1802 sa = SafeArrayCreate(typ, 1, &sab); if (!sa) continue; \
1803 V_VT(&v) = VT_ARRAY|typ; V_ARRAY(&v) = sa; VariantInit(&v2)
1804
test_SafeArrayChangeTypeEx(void)1805 static void test_SafeArrayChangeTypeEx(void)
1806 {
1807 static const char *szHello = "Hello World";
1808 SAFEARRAYBOUND sab;
1809 SAFEARRAY *sa;
1810 VARIANTARG v,v2;
1811 VARTYPE vt;
1812 HRESULT hres;
1813
1814 /* VT_ARRAY|VT_UI1 -> VT_BSTR */
1815 MKARRAY(0,strlen(szHello)+1,VT_UI1);
1816 memcpy(sa->pvData, szHello, strlen(szHello)+1);
1817
1818 hres = VariantChangeTypeEx(&v2, &v, 0, 0, VT_BSTR);
1819 ok(hres == S_OK, "CTE VT_ARRAY|VT_UI1 -> VT_BSTR failed with %x\n", hres);
1820 if (hres == S_OK)
1821 {
1822 ok(V_VT(&v2) == VT_BSTR, "CTE VT_ARRAY|VT_UI1 -> VT_BSTR did not return VT_BSTR, but %d.\n",V_VT(&v2));
1823 ok(strcmp((char*)V_BSTR(&v2),szHello) == 0,"Expected string '%s', got '%s'\n", szHello,
1824 (char*)V_BSTR(&v2));
1825 VariantClear(&v2);
1826 }
1827
1828 /* VT_VECTOR|VT_UI1 -> VT_BSTR */
1829 hres = SafeArrayDestroy(sa);
1830 ok(hres == S_OK, "got 0x%08x\n", hres);
1831 if (pSafeArrayCreateVector)
1832 {
1833 sa = pSafeArrayCreateVector(VT_UI1, 0, strlen(szHello)+1);
1834 ok(sa != NULL, "CreateVector() failed.\n");
1835 if (!sa)
1836 return;
1837
1838 memcpy(sa->pvData, szHello, strlen(szHello)+1);
1839 V_VT(&v) = VT_VECTOR|VT_UI1;
1840 V_ARRAY(&v) = sa;
1841 VariantInit(&v2);
1842
1843 hres = VariantChangeTypeEx(&v2, &v, 0, 0, VT_BSTR);
1844 ok(hres == DISP_E_BADVARTYPE, "CTE VT_VECTOR|VT_UI1 returned %x\n", hres);
1845
1846 /* (vector)VT_ARRAY|VT_UI1 -> VT_BSTR (In place) */
1847 V_VT(&v) = VT_ARRAY|VT_UI1;
1848 hres = VariantChangeTypeEx(&v, &v, 0, 0, VT_BSTR);
1849 ok(hres == S_OK, "CTE VT_ARRAY|VT_UI1 -> VT_BSTR failed with %x\n", hres);
1850 if (hres == S_OK)
1851 {
1852 ok(V_VT(&v) == VT_BSTR, "CTE VT_ARRAY|VT_UI1 -> VT_BSTR did not return VT_BSTR, but %d.\n",V_VT(&v));
1853 ok(strcmp((char*)V_BSTR(&v),szHello) == 0,"Expected string '%s', got '%s'\n", szHello,
1854 (char*)V_BSTR(&v));
1855 VariantClear(&v);
1856 }
1857 }
1858
1859 /* To/from BSTR only works with arrays of VT_UI1 */
1860 for (vt = VT_EMPTY; vt <= VT_CLSID; vt++)
1861 {
1862 if (vt == VT_UI1)
1863 continue;
1864
1865 sab.lLbound = 0;
1866 sab.cElements = 1;
1867 sa = SafeArrayCreate(vt, 1, &sab);
1868 if (!sa) continue;
1869
1870 V_VT(&v) = VT_ARRAY|vt;
1871 V_ARRAY(&v) = sa;
1872 VariantInit(&v2);
1873
1874 hres = VariantChangeTypeEx(&v2, &v, 0, 0, VT_BSTR);
1875 if (vt == VT_INT_PTR || vt == VT_UINT_PTR)
1876 {
1877 ok(hres == DISP_E_BADVARTYPE, "expected DISP_E_BADVARTYPE, got 0x%08x\n", hres);
1878 SafeArrayDestroy(sa);
1879 }
1880 else
1881 {
1882 ok(hres == DISP_E_TYPEMISMATCH, "got 0x%08x for vt=%d, instead of DISP_E_TYPEMISMATCH\n", hres, vt);
1883 hres = VariantClear(&v);
1884 ok(hres == S_OK, "expected S_OK, got 0x%08x\n", hres);
1885 }
1886 VariantClear(&v2);
1887 }
1888
1889 /* Can't change an array of one type into array of another type , even
1890 * if the other type is the same size
1891 */
1892 if (pSafeArrayCreateVector)
1893 {
1894 sa = pSafeArrayCreateVector(VT_UI1, 0, 1);
1895 ok(sa != NULL, "CreateVector() failed.\n");
1896 if (!sa)
1897 return;
1898
1899 V_VT(&v) = VT_ARRAY|VT_UI1;
1900 V_ARRAY(&v) = sa;
1901 hres = VariantChangeTypeEx(&v2, &v, 0, 0, VT_ARRAY|VT_I1);
1902 ok(hres == DISP_E_TYPEMISMATCH, "CTE VT_ARRAY|VT_UI1->VT_ARRAY|VT_I1 returned %x\n", hres);
1903
1904 /* But can change to the same array type */
1905 hres = SafeArrayDestroy(sa);
1906 ok(hres == S_OK, "got 0x%08x\n", hres);
1907 sa = pSafeArrayCreateVector(VT_UI1, 0, 1);
1908 ok(sa != NULL, "CreateVector() failed.\n");
1909 if (!sa)
1910 return;
1911 V_VT(&v) = VT_ARRAY|VT_UI1;
1912 V_ARRAY(&v) = sa;
1913 hres = VariantChangeTypeEx(&v2, &v, 0, 0, VT_ARRAY|VT_UI1);
1914 ok(hres == S_OK, "CTE VT_ARRAY|VT_UI1->VT_ARRAY|VT_UI1 returned %x\n", hres);
1915 hres = SafeArrayDestroy(sa);
1916 ok(hres == S_OK, "got 0x%08x\n", hres);
1917 VariantClear(&v2);
1918 }
1919
1920 /* NULL/EMPTY */
1921 MKARRAY(0,1,VT_UI1);
1922 hres = VariantChangeTypeEx(&v2, &v, 0, 0, VT_NULL);
1923 ok(hres == DISP_E_TYPEMISMATCH, "CTE VT_ARRAY|VT_UI1 returned %x\n", hres);
1924 VariantClear(&v);
1925 MKARRAY(0,1,VT_UI1);
1926 hres = VariantChangeTypeEx(&v2, &v, 0, 0, VT_EMPTY);
1927 ok(hres == DISP_E_TYPEMISMATCH, "CTE VT_ARRAY|VT_UI1 returned %x\n", hres);
1928 VariantClear(&v);
1929 }
1930
test_SafeArrayDestroyData(void)1931 static void test_SafeArrayDestroyData (void)
1932 {
1933 SAFEARRAYBOUND sab[2];
1934 SAFEARRAY *sa;
1935 HRESULT hres;
1936 int value = 0xdeadbeef;
1937 LONG index[1];
1938 void *temp_pvData;
1939 USHORT features;
1940
1941 sab[0].lLbound = 0;
1942 sab[0].cElements = 10;
1943 sa = SafeArrayCreate(VT_INT, 1, sab);
1944 ok(sa != NULL, "Create() failed.\n");
1945 ok(sa->fFeatures == FADF_HAVEVARTYPE, "got 0x%x\n", sa->fFeatures);
1946
1947 index[0] = 1;
1948 SafeArrayPutElement (sa, index, &value);
1949
1950 /* SafeArrayDestroyData shouldn't free pvData if FADF_STATIC is set. */
1951 features = (sa->fFeatures |= FADF_STATIC);
1952 temp_pvData = sa->pvData;
1953 hres = SafeArrayDestroyData(sa);
1954 ok(hres == S_OK, "SADData FADF_STATIC failed, error code %x.\n",hres);
1955 ok(features == sa->fFeatures, "got 0x%x\n", sa->fFeatures);
1956 ok(sa->pvData == temp_pvData, "SADData FADF_STATIC: pvData=%p, expected %p (fFeatures = %d).\n",
1957 sa->pvData, temp_pvData, sa->fFeatures);
1958 SafeArrayGetElement (sa, index, &value);
1959 ok(value == 0, "Data not cleared after SADData\n");
1960
1961 /* Clear FADF_STATIC, now really destroy the data. */
1962 features = (sa->fFeatures ^= FADF_STATIC);
1963 hres = SafeArrayDestroyData(sa);
1964 ok(hres == S_OK, "SADData !FADF_STATIC failed, error code %x.\n",hres);
1965 ok(features == sa->fFeatures, "got 0x%x\n", sa->fFeatures);
1966 ok(sa->pvData == NULL, "SADData !FADF_STATIC: pvData=%p, expected NULL.\n", sa->pvData);
1967
1968 hres = SafeArrayDestroy(sa);
1969 ok(hres == S_OK, "SAD failed, error code %x.\n", hres);
1970
1971 /* two dimensions */
1972 sab[0].lLbound = 0;
1973 sab[0].cElements = 10;
1974 sab[1].lLbound = 0;
1975 sab[1].cElements = 10;
1976
1977 sa = SafeArrayCreate(VT_INT, 2, sab);
1978 ok(sa != NULL, "Create() failed.\n");
1979 ok(sa->fFeatures == FADF_HAVEVARTYPE, "got 0x%x\n", sa->fFeatures);
1980
1981 features = sa->fFeatures;
1982 hres = SafeArrayDestroyData(sa);
1983 ok(hres == S_OK, "got 0x%08x\n",hres);
1984 ok(features == sa->fFeatures, "got 0x%x\n", sa->fFeatures);
1985
1986 SafeArrayDestroy(sa);
1987
1988 /* try to destroy data from descriptor */
1989 hres = SafeArrayAllocDescriptor(1, &sa);
1990 ok(hres == S_OK, "got 0x%08x\n", hres);
1991 ok(sa->fFeatures == 0, "got 0x%x\n", sa->fFeatures);
1992
1993 hres = SafeArrayDestroyData(sa);
1994 ok(hres == S_OK, "got 0x%08x\n", hres);
1995 ok(sa->fFeatures == 0, "got 0x%x\n", sa->fFeatures);
1996
1997 hres = SafeArrayDestroyDescriptor(sa);
1998 ok(hres == S_OK, "got 0x%08x\n", hres);
1999
2000 hres = SafeArrayAllocDescriptor(2, &sa);
2001 ok(hres == S_OK, "got 0x%08x\n", hres);
2002 ok(sa->fFeatures == 0, "got 0x%x\n", sa->fFeatures);
2003
2004 hres = SafeArrayDestroyData(sa);
2005 ok(hres == S_OK, "got 0x%08x\n", hres);
2006 ok(sa->fFeatures == 0, "got 0x%x\n", sa->fFeatures);
2007
2008 hres = SafeArrayDestroyDescriptor(sa);
2009 ok(hres == S_OK, "got 0x%08x\n", hres);
2010
2011 /* vector case */
2012 sa = SafeArrayCreateVector(VT_I4, 0, 10);
2013 ok(sa != NULL, "got %p\n", sa);
2014 ok(sa->fFeatures == (FADF_CREATEVECTOR|FADF_HAVEVARTYPE), "got 0x%x\n", sa->fFeatures);
2015
2016 ok(sa->pvData != NULL, "got %p\n", sa->pvData);
2017 hres = SafeArrayDestroyData(sa);
2018 ok(hres == S_OK, "got 0x%08x\n", hres);
2019 todo_wine
2020 ok(sa->fFeatures == FADF_HAVEVARTYPE, "got 0x%x\n", sa->fFeatures);
2021 todo_wine
2022 ok(sa->pvData == NULL || broken(sa->pvData != NULL), "got %p\n", sa->pvData);
2023 /* There was a bug on windows, especially visible on 64bit systems,
2024 probably double-free or similar issue. */
2025 sa->pvData = NULL;
2026 SafeArrayDestroy(sa);
2027 }
2028
test_safearray_layout(void)2029 static void test_safearray_layout(void)
2030 {
2031 IRecordInfoImpl *irec;
2032 IRecordInfo *record;
2033 GUID guid, *guidptr;
2034 SAFEARRAYBOUND sab;
2035 SAFEARRAY *sa;
2036 DWORD *dwptr;
2037 HRESULT hr;
2038
2039 sab.lLbound = 0;
2040 sab.cElements = 10;
2041
2042 /* GUID field */
2043 sa = SafeArrayCreate(VT_UNKNOWN, 1, &sab);
2044 ok(sa != NULL, "got %p\n", sa);
2045
2046 guidptr = (GUID*)sa - 1;
2047 ok(IsEqualIID(guidptr, &IID_IUnknown), "got %s\n", wine_dbgstr_guid(guidptr));
2048
2049 hr = SafeArraySetIID(sa, &IID_IDispatch);
2050 ok(hr == S_OK, "got 0x%08x\n", hr);
2051 ok(IsEqualIID(guidptr, &IID_IDispatch), "got %s\n", wine_dbgstr_guid(guidptr));
2052
2053 memcpy(guidptr, &IID_IUnknown, sizeof(GUID));
2054 hr = SafeArrayGetIID(sa, &guid);
2055 ok(hr == S_OK, "got 0x%08x\n", hr);
2056 ok(IsEqualIID(&guid, &IID_IUnknown), "got %s\n", wine_dbgstr_guid(&guid));
2057
2058 hr = SafeArrayDestroy(sa);
2059 ok(hr == S_OK, "got 0x%08x\n", hr);
2060
2061 /* VARTYPE field */
2062 sa = SafeArrayCreate(VT_UI1, 1, &sab);
2063 ok(sa != NULL, "got %p\n", sa);
2064
2065 dwptr = (DWORD*)sa - 1;
2066 ok(*dwptr == VT_UI1, "got %d\n", *dwptr);
2067
2068 hr = SafeArrayDestroy(sa);
2069 ok(hr == S_OK, "got 0x%08x\n", hr);
2070
2071 /* IRecordInfo pointer */
2072 irec = IRecordInfoImpl_Construct();
2073 irec->ref = 1;
2074
2075 sa = pSafeArrayCreateEx(VT_RECORD, 1, &sab, &irec->IRecordInfo_iface);
2076 ok(sa != NULL, "failed to create array\n");
2077
2078 record = *((IRecordInfo**)sa - 1);
2079 ok(record == &irec->IRecordInfo_iface, "got %p\n", record);
2080
2081 hr = SafeArrayDestroy(sa);
2082 ok(hr == S_OK, "got 0x%08x\n", hr);
2083 IRecordInfo_Release(&irec->IRecordInfo_iface);
2084 }
2085
START_TEST(safearray)2086 START_TEST(safearray)
2087 {
2088 hOleaut32 = GetModuleHandleA("oleaut32.dll");
2089
2090 has_i8 = GetProcAddress(hOleaut32, "VarI8FromI1") != NULL;
2091
2092 GETPTR(SafeArrayAllocDescriptorEx);
2093 GETPTR(SafeArrayCopyData);
2094 GETPTR(SafeArrayGetVartype);
2095 GETPTR(SafeArrayCreateEx);
2096 GETPTR(SafeArrayCreateVector);
2097 GETPTR(SafeArrayGetRecordInfo);
2098
2099 check_for_VT_INT_PTR();
2100 test_safearray();
2101 test_SafeArrayAllocDestroyDescriptor();
2102 test_SafeArrayCreateLockDestroy();
2103 test_VectorCreateLockDestroy();
2104 test_LockUnlock();
2105 test_SafeArrayChangeTypeEx();
2106 test_SafeArrayCopy();
2107 test_SafeArrayClear();
2108 test_SafeArrayCreateEx();
2109 test_SafeArrayCopyData();
2110 test_SafeArrayDestroyData();
2111 test_SafeArrayGetPutElement();
2112 test_SafeArrayGetPutElement_BSTR();
2113 test_SafeArrayGetPutElement_IUnknown();
2114 test_SafeArrayRedim_IUnknown();
2115 test_SafeArrayGetPutElement_VARIANT();
2116 test_safearray_layout();
2117 }
2118