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