ReactOS 0.4.16-dev-321-g63bb46a
safearray.c
Go to the documentation of this file.
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
47
48static HRESULT (WINAPI *pSafeArrayAllocDescriptorEx)(VARTYPE,UINT,SAFEARRAY**);
49static HRESULT (WINAPI *pSafeArrayCopyData)(SAFEARRAY*,SAFEARRAY*);
50static HRESULT (WINAPI *pSafeArrayGetVartype)(SAFEARRAY*,VARTYPE*);
51static HRESULT (WINAPI *pSafeArrayGetRecordInfo)(SAFEARRAY*,IRecordInfo**);
54
55#define GETPTR(func) p##func = (void*)GetProcAddress(hOleaut32, #func)
56
57/* Has I8/UI8 data type? */
58static BOOL has_i8;
59/* Has INT_PTR/UINT_PTR type? */
61
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 */
76typedef struct IRecordInfoImpl
77{
79 LONG ref;
80 unsigned int sizeCalled;
81 unsigned int clearCalled;
82 unsigned int recordcopy;
84
86{
87 return CONTAINING_RECORD(iface, IRecordInfoImpl, IRecordInfo_iface);
88}
89
91{
92 *obj = NULL;
93
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
106{
108 return InterlockedIncrement(&This->ref);
109}
110
112{
115
116 if (!ref)
118
119 return ref;
120}
121
123{
124 ok(0, "unexpected call\n");
125 return E_NOTIMPL;
126}
127
128static BOOL fail_GetSize; /* Whether to fail the GetSize call */
129
131{
133 This->clearCalled++;
134 return S_OK;
135}
136
138{
140 This->recordcopy++;
141 return S_OK;
142}
143
145{
146 ok(0, "unexpected call\n");
147 return E_NOTIMPL;
148}
149
151{
152 ok(0, "unexpected call\n");
153 return E_NOTIMPL;
154}
155
157{
159 This->sizeCalled++;
160 if (fail_GetSize)
161 {
163 return E_UNEXPECTED;
164 }
165 *size = RECORD_SIZE;
166 return S_OK;
167}
168
170{
171 ok(0, "unexpected call\n");
172 return E_NOTIMPL;
173}
174
176 LPCOLESTR szFieldName, VARIANT *pvarField)
177{
178 ok(0, "unexpected call\n");
179 return E_NOTIMPL;
180}
181
183 LPCOLESTR szFieldName, VARIANT *pvarField, PVOID *ppvDataCArray)
184{
185 ok(0, "unexpected call\n");
186 return E_NOTIMPL;
187}
188
190 LPCOLESTR szFieldName, VARIANT *pvarField)
191{
192 ok(0, "unexpected call\n");
193 return E_NOTIMPL;
194}
195
197 PVOID pvData, LPCOLESTR szFieldName, VARIANT *pvarField)
198{
199 ok(0, "unexpected call\n");
200 return E_NOTIMPL;
201}
202
204 BSTR *rgBstrNames)
205{
206 ok(0, "unexpected call\n");
207 return E_NOTIMPL;
208}
209
211{
212 ok(0, "unexpected call\n");
213 return FALSE;
214}
215
217{
218 ok(0, "unexpected call\n");
219 return NULL;
220}
221
223 PVOID *ppvDest)
224{
225 ok(0, "unexpected call\n");
226 return E_NOTIMPL;
227}
228
230{
231 ok(0, "unexpected call\n");
232 return E_NOTIMPL;
233}
234
235static const IRecordInfoVtbl RecordInfoVtbl =
236{
256};
257
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
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
307static 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) {
318 trace("VT_INT_PTR is supported\n");
321 ok(hres == S_OK, "got 0x%08x\n", hres);
322 }
323 else {
324 trace("VT_INT_PTR is not supported\n");
326 }
327}
328
329#define VARTYPE_NOT_SUPPORTED 0
330static 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},
379
380static void test_safearray(void)
381{
382 SAFEARRAY *a, b, *c;
383 unsigned int i, diff;
384 LONG indices[2];
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
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
415 ok(hres == S_OK, "SafeArrayAccessData of 0 size dimensioned array failed with %x\n", hres);
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);
426 ok(hres == S_OK,"SAD of 0 dim array failed with hres %x\n", hres);
427
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;
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;
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
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
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
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
513 ok(i == 2, "getdims of 2 din array returned %d\n",i);
514
515 indices[0] = 0;
516 indices[1] = 23;
518 ok(DISP_E_BADINDEX == hres,"SAGE failed [0,23], hres 0x%x\n",hres);
519
520 indices[0] = 1;
521 indices[1] = 22;
523 ok(DISP_E_BADINDEX == hres,"SAGE failed [1,22], hres 0x%x\n",hres);
524
525 indices[0] = 1;
526 indices[1] = 23;
528 ok(S_OK == hres,"SAGE failed [1,23], hres 0x%x\n",hres);
529
530 indices[0] = 1;
531 indices[1] = 25;
533 ok(DISP_E_BADINDEX == hres,"SAGE failed [1,24], hres 0x%x\n",hres);
534
535 indices[0] = 3;
536 indices[1] = 23;
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
565 ok(S_OK == hres, "SAUAD failed with 0x%x\n", hres);
566
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);
590 "SAGE for vt %d returned elemsize %d instead of expected %d\n",
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
624 ok(hres == S_OK,"SADD of copy of array with vt %d failed with hres %x\n", vttypes[i].vt, hres);
625 }
626
628 ok(hres == S_OK,"SAD failed with hres %x\n", hres);
629
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;
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
664 ok(hres == S_OK,"SAAD failed with hres %x\n",hres);
665
667 ok(hres == DISP_E_ARRAYISLOCKED,"locked safe array destroy not failed with DISP_E_ARRAYISLOCKED, but with hres %x\n", hres);
668
670 ok(hres == DISP_E_ARRAYISLOCKED,"locked safe array destroy data not failed with DISP_E_ARRAYISLOCKED, but with hres %x\n", hres);
671
673 ok(hres == DISP_E_ARRAYISLOCKED,"locked safe array destroy descriptor not failed with DISP_E_ARRAYISLOCKED, but with hres %x\n", hres);
674
676 ok(hres == S_OK,"SAUD failed after lock/destroy test\n");
677
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");
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
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
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 }
760 ok(hres == S_OK,"SADD failed with hres %x\n",hres);
761 }
762}
763
765{
766 SAFEARRAY *sa;
768 UINT i;
769
770 /* Failure cases */
772 ok(hres == E_INVALIDARG, "0 dimensions gave hres 0x%x\n", hres);
773
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 */
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 {
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",
794
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
819 ok(hres == S_OK, "SafeArrayAllocData gave hres 0x%x\n", hres);
820
822 ok(hres == S_OK,"SafeArrayDestroy failed with hres %x\n",hres);
823}
824
826{
827 SAFEARRAYBOUND sab[4];
828 SAFEARRAY *sa;
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 {
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");
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");
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
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 {
914 ok(hres == DISP_E_ARRAYISLOCKED,"Destroy() got hres %x\n", hres);
915
917 ok(hres == DISP_E_ARRAYISLOCKED,"DestroyData() got hres %x\n", hres);
918
920 ok(hres == DISP_E_ARRAYISLOCKED,"DestroyDescriptor() got hres %x\n", hres);
921
923 ok(hres == S_OK, "Unlock VARTYPE %d (@%d dims) hres 0x%x\n",
924 vt, dimension, hres);
925
927 ok(hres == S_OK, "destroy VARTYPE %d (@%d dims) hres 0x%x\n",
928 vt, dimension, hres);
929 }
930 }
931 }
932 }
933}
934
936{
937 SAFEARRAY *sa;
939 VARTYPE vt;
940 int element;
941
943 {
944 win_skip("SafeArrayCreateVector not supported\n");
945 return;
946 }
948 ok(sa != NULL, "SACV with 0 elements failed.\n");
949
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 {
959
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",
971 ok(SafeArrayGetElemsize(sa) == dwLen,
972 "VARTYPE %d (@%d elements) cbElements is %d, expected %d\n",
974
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 {
982 ok(hres == S_OK, "Unlock VARTYPE %d (@%d elements) failed; hres 0x%x\n",
983 vt, element, hres);
984
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
994static void test_LockUnlock(void)
995{
996 SAFEARRAYBOUND sab[4];
997 SAFEARRAY *sa;
999 BOOL bVector = FALSE;
1000 int dimension;
1001
1002 /* Failure cases */
1004 ok(hres == E_INVALIDARG, "Lock NULL array hres 0x%x\n", hres);
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 */
1017test_LockUnlock_Vector:
1018 if (sa)
1019 {
1020 int count = 0;
1021
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
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
1053{
1054 SAFEARRAYBOUND sab[4];
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;
1084 ok(hres == DISP_E_BADINDEX, "Put allowed too small index in dimension %d\n", x);
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;
1090 ok(hres == DISP_E_BADINDEX, "Put allowed too big index in dimension %d\n", x);
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
1101 ok(hres == E_INVALIDARG, "Put NULL array hres 0x%x\n", hres);
1103 ok(hres == E_INVALIDARG, "Get NULL array hres 0x%x\n", hres);
1104
1106 ok(hres == E_INVALIDARG, "Put NULL indices hres 0x%x\n", hres);
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 */
1116 ok(hres == E_INVALIDARG, "Put NULL value hres 0x%x\n", hres);
1117 }
1118
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;
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 }
1175 ok(hres == S_OK, "got 0x%08x\n", hres);
1176
1177 /* VT_RECORD array */
1179 irec->ref = 1;
1180
1181 sab[0].lLbound = 0;
1182 sab[0].cElements = 8;
1183
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
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
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");
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));
1236 ok(hres == S_OK, "got 0x%08x\n", hres);
1238 SysFreeString(gotvalue);
1239}
1240
1244};
1245static const IUnknownVtbl xtunk_vtbl;
1246
1247static struct xtunk_impl xtunk = {{&xtunk_vtbl}, 0};
1248
1250{
1251 return E_FAIL;
1252}
1253
1255{
1256 return ++xtunk.ref;
1257}
1258
1260{
1261 return --xtunk.ref;
1262}
1263
1264static const IUnknownVtbl xtunk_vtbl = {
1268};
1269
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);
1299 ok(hres == S_OK, "got 0x%08x\n", hres);
1300 ok(xtunk.ref == 2,"Failed to decrement refcount of iface.\n");
1301}
1302
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");
1329 ok(hres == S_OK, "got 0x%08x\n", hres);
1330}
1331
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;
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 }
1368 ok(hres == S_OK, "got 0x%08x\n", hres);
1369}
1370
1371static 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 {
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);
1473 ok(hres == S_OK, "got 0x%08x\n", hres);
1474
1475 /* copy data from a vector */
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
1500}
1501
1502static 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 */
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
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");
1538 ok(hres == S_OK, "Failed to set IID, hres = %8x\n", hres);
1540 ok(hres == S_OK && IsEqualGUID(&guid, &IID_IUnknown), "Set bad IID\n");
1542 ok(hres == S_OK, "got 0x%08x\n", hres);
1543 }
1544
1546 ok(sa != NULL, "CreateEx (NULL) failed\n");
1547
1548 if (sa)
1549 {
1550 GUID guid;
1551
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");
1556 ok(hres == S_OK, "got 0x%08x\n", hres);
1557 }
1558
1560 ok(sa != NULL, "CreateEx (NULL-Unk) failed\n");
1561
1562 if (sa)
1563 {
1564 GUID guid;
1565
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");
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
1578
1579 /* Win32 doesn't care if GetSize fails */
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);
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 */
1597 iRec->ref = START_REF_COUNT;
1598 iRec->sizeCalled = 0;
1599 iRec->clearCalled = 0;
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;
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 {
1642 ok(hres == S_OK, "got 0x%08x\n", hres);
1643 }
1644
1645 IRecordInfo_Release(&iRec->IRecordInfo_iface);
1646}
1647
1648static 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
1680 V_ARRAYREF(&v) = &sa;
1681 hres = VariantClear(&v);
1682 ok(hres == DISP_E_BADVARTYPE, "VariantClear: hres 0x%x\n", hres);
1683
1685 ok(hres == S_OK, "got 0x%08x\n", hres);
1686}
1687
1688static 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
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);
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
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);
1758 ok(hres == S_OK, "got 0x%08x\n", hres);
1759
1760 /* test feature copy */
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 {
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
1780
1781 /* copy from a vector */
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);
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
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 */
1830 ok(hres == S_OK, "got 0x%08x\n", hres);
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);
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 */
1893 {
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;
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 */
1906 ok(hres == S_OK, "got 0x%08x\n", hres);
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;
1914 ok(hres == S_OK, "CTE VT_ARRAY|VT_UI1->VT_ARRAY|VT_UI1 returned %x\n", hres);
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
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;
1949
1950/* SafeArrayDestroyData shouldn't free pvData if FADF_STATIC is set. */
1951 features = (sa->fFeatures |= FADF_STATIC);
1952 temp_pvData = sa->pvData;
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);
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);
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
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;
1983 ok(hres == S_OK, "got 0x%08x\n",hres);
1984 ok(features == sa->fFeatures, "got 0x%x\n", sa->fFeatures);
1985
1987
1988 /* try to destroy data from descriptor */
1990 ok(hres == S_OK, "got 0x%08x\n", hres);
1991 ok(sa->fFeatures == 0, "got 0x%x\n", sa->fFeatures);
1992
1994 ok(hres == S_OK, "got 0x%08x\n", hres);
1995 ok(sa->fFeatures == 0, "got 0x%x\n", sa->fFeatures);
1996
1998 ok(hres == S_OK, "got 0x%08x\n", hres);
1999
2001 ok(hres == S_OK, "got 0x%08x\n", hres);
2002 ok(sa->fFeatures == 0, "got 0x%x\n", sa->fFeatures);
2003
2005 ok(hres == S_OK, "got 0x%08x\n", hres);
2006 ok(sa->fFeatures == 0, "got 0x%x\n", sa->fFeatures);
2007
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);
2018 ok(hres == S_OK, "got 0x%08x\n", hres);
2020 ok(sa->fFeatures == FADF_HAVEVARTYPE, "got 0x%x\n", sa->fFeatures);
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;
2027}
2028
2029static void test_safearray_layout(void)
2030{
2031 IRecordInfoImpl *irec;
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
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));
2055 ok(hr == S_OK, "got 0x%08x\n", hr);
2056 ok(IsEqualIID(&guid, &IID_IUnknown), "got %s\n", wine_dbgstr_guid(&guid));
2057
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
2069 ok(hr == S_OK, "got 0x%08x\n", hr);
2070
2071 /* IRecordInfo pointer */
2073 irec->ref = 1;
2074
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
2082 ok(hr == S_OK, "got 0x%08x\n", hr);
2083 IRecordInfo_Release(&irec->IRecordInfo_iface);
2084}
2085
2086START_TEST(safearray)
2087{
2088 hOleaut32 = GetModuleHandleA("oleaut32.dll");
2089
2090 has_i8 = GetProcAddress(hOleaut32, "VarI8FromI1") != NULL;
2091
2098
2117}
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
static struct sockaddr_in sa
Definition: adnsresfilter.c:69
#define InterlockedIncrement
Definition: armddk.h:53
#define InterlockedDecrement
Definition: armddk.h:52
#define trace
Definition: atltest.h:70
#define ok(value,...)
Definition: atltest.h:57
#define broken(x)
Definition: atltest.h:178
#define START_TEST(x)
Definition: atltest.h:75
#define index(s, c)
Definition: various.h:29
#define ARRAY_SIZE(A)
Definition: main.h:20
const GUID IID_IUnknown
r l[0]
Definition: byte_order.h:168
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
#define E_INVALIDARG
Definition: ddrawi.h:101
#define E_NOTIMPL
Definition: ddrawi.h:99
#define E_FAIL
Definition: ddrawi.h:102
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
double DATE
Definition: compat.h:2253
union tagCY CY
#define GetProcessHeap()
Definition: compat.h:736
struct tagDEC DECIMAL
struct tagVARIANT VARIANT
Definition: compat.h:2377
#define GetProcAddress(x, y)
Definition: compat.h:753
#define HeapAlloc
Definition: compat.h:733
WCHAR OLECHAR
Definition: compat.h:2292
OLECHAR * BSTR
Definition: compat.h:2293
unsigned short VARTYPE
Definition: compat.h:2254
#define HeapFree(x, y, z)
Definition: compat.h:735
@ VT_BLOB
Definition: compat.h:2330
@ VT_UI8
Definition: compat.h:2315
@ VT_BLOB_OBJECT
Definition: compat.h:2335
@ VT_BSTR
Definition: compat.h:2303
@ VT_VOID
Definition: compat.h:2318
@ VT_INT
Definition: compat.h:2316
@ VT_LPSTR
Definition: compat.h:2324
@ VT_R4
Definition: compat.h:2299
@ VT_UINT_PTR
Definition: compat.h:2328
@ VT_NULL
Definition: compat.h:2296
@ VT_UNKNOWN
Definition: compat.h:2308
@ VT_BYREF
Definition: compat.h:2342
@ VT_PTR
Definition: compat.h:2320
@ VT_UI2
Definition: compat.h:2312
@ VT_DECIMAL
Definition: compat.h:2309
@ VT_ERROR
Definition: compat.h:2305
@ VT_CLSID
Definition: compat.h:2337
@ VT_STREAM
Definition: compat.h:2331
@ VT_ARRAY
Definition: compat.h:2341
@ VT_STORED_OBJECT
Definition: compat.h:2334
@ VT_SAFEARRAY
Definition: compat.h:2321
@ VT_LPWSTR
Definition: compat.h:2325
@ VT_R8
Definition: compat.h:2300
@ VT_CY
Definition: compat.h:2301
@ VT_VARIANT
Definition: compat.h:2307
@ VT_I8
Definition: compat.h:2314
@ VT_I1
Definition: compat.h:2310
@ VT_I4
Definition: compat.h:2298
@ VT_CF
Definition: compat.h:2336
@ VT_STORAGE
Definition: compat.h:2332
@ VT_USERDEFINED
Definition: compat.h:2323
@ VT_HRESULT
Definition: compat.h:2319
@ VT_FILETIME
Definition: compat.h:2329
@ VT_INT_PTR
Definition: compat.h:2327
@ VT_DATE
Definition: compat.h:2302
@ VT_BOOL
Definition: compat.h:2306
@ VT_STREAMED_OBJECT
Definition: compat.h:2333
@ VT_I2
Definition: compat.h:2297
@ VT_UI4
Definition: compat.h:2313
@ VT_UINT
Definition: compat.h:2317
@ VT_EMPTY
Definition: compat.h:2295
@ VT_CARRAY
Definition: compat.h:2322
@ VT_RECORD
Definition: compat.h:2326
@ VT_VECTOR
Definition: compat.h:2340
@ VT_DISPATCH
Definition: compat.h:2304
@ VT_UI1
Definition: compat.h:2311
HMODULE WINAPI DECLSPEC_HOTPATCH GetModuleHandleA(LPCSTR lpModuleName)
Definition: loader.c:812
static REFPROPVARIANT PROPVAR_CHANGE_FLAGS VARTYPE vt
Definition: suminfo.c:91
HRESULT WINAPI SafeArrayGetUBound(SAFEARRAY *psa, UINT nDim, LONG *plUbound)
Definition: safearray.c:1033
HRESULT WINAPI SafeArrayDestroyDescriptor(SAFEARRAY *psa)
Definition: safearray.c:755
HRESULT WINAPI SafeArrayGetElement(SAFEARRAY *psa, LONG *rgIndices, void *pvData)
Definition: safearray.c:947
HRESULT WINAPI SafeArrayAccessData(SAFEARRAY *psa, void **ppvData)
Definition: safearray.c:1137
HRESULT WINAPI SafeArrayUnlock(SAFEARRAY *psa)
Definition: safearray.c:831
HRESULT WINAPI SafeArrayAllocDescriptorEx(VARTYPE vt, UINT cDims, SAFEARRAY **ppsaOut)
Definition: safearray.c:521
HRESULT WINAPI SafeArrayUnaccessData(SAFEARRAY *psa)
Definition: safearray.c:1168
HRESULT WINAPI SafeArrayCopy(SAFEARRAY *psa, SAFEARRAY **ppsaOut)
Definition: safearray.c:1379
UINT WINAPI SafeArrayGetDim(SAFEARRAY *psa)
Definition: safearray.c:1094
SAFEARRAY *WINAPI SafeArrayCreateVector(VARTYPE vt, LONG lLbound, ULONG cElements)
Definition: safearray.c:677
HRESULT WINAPI SafeArrayGetIID(SAFEARRAY *psa, GUID *pGuid)
Definition: safearray.c:1670
HRESULT WINAPI SafeArrayGetLBound(SAFEARRAY *psa, UINT nDim, LONG *plLbound)
Definition: safearray.c:1066
HRESULT WINAPI SafeArrayDestroyData(SAFEARRAY *psa)
Definition: safearray.c:1256
UINT WINAPI SafeArrayGetElemsize(SAFEARRAY *psa)
Definition: safearray.c:1114
HRESULT WINAPI SafeArrayAllocDescriptor(UINT cDims, SAFEARRAY **ppsaOut)
Definition: safearray.c:476
HRESULT WINAPI SafeArrayGetRecordInfo(SAFEARRAY *psa, IRecordInfo **pRinfo)
Definition: safearray.c:1609
static DWORD SAFEARRAY_GetVTSize(VARTYPE vt)
Definition: safearray.c:111
HRESULT WINAPI SafeArrayPtrOfIndex(SAFEARRAY *psa, LONG *rgIndices, void **ppvData)
Definition: safearray.c:1194
SAFEARRAY *WINAPI SafeArrayCreateEx(VARTYPE vt, UINT cDims, SAFEARRAYBOUND *rgsabound, LPVOID pvExtra)
Definition: safearray.c:628
HRESULT WINAPI SafeArrayLock(SAFEARRAY *psa)
Definition: safearray.c:795
HRESULT WINAPI SafeArrayDestroy(SAFEARRAY *psa)
Definition: safearray.c:1347
static const USHORT ignored_copy_features
Definition: safearray.c:88
HRESULT WINAPI SafeArrayRedim(SAFEARRAY *psa, SAFEARRAYBOUND *psabound)
Definition: safearray.c:1456
SAFEARRAY *WINAPI SafeArrayCreate(VARTYPE vt, UINT cDims, SAFEARRAYBOUND *rgsabound)
Definition: safearray.c:600
HRESULT WINAPI SafeArrayCopyData(SAFEARRAY *psaSource, SAFEARRAY *psaTarget)
Definition: safearray.c:1312
HRESULT WINAPI SafeArrayAllocData(SAFEARRAY *psa)
Definition: safearray.c:557
HRESULT WINAPI SafeArraySetIID(SAFEARRAY *psa, REFGUID guid)
Definition: safearray.c:1641
HRESULT WINAPI SafeArrayGetVartype(SAFEARRAY *psa, VARTYPE *pvt)
Definition: safearray.c:1534
HRESULT WINAPI SafeArrayPutElement(SAFEARRAY *psa, LONG *rgIndices, void *pvData)
Definition: safearray.c:864
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
unsigned short WORD
Definition: ntddk_ex.h:93
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
const GLdouble * v
Definition: gl.h:2040
GLint GLint GLint GLint GLint GLint y
Definition: gl.h:1548
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLuint GLuint GLsizei GLenum const GLvoid * indices
Definition: gl.h:1545
GLsizeiptr size
Definition: glext.h:5919
const GLubyte * c
Definition: glext.h:8905
GLuint index
Definition: glext.h:6031
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
GLboolean GLboolean GLboolean GLboolean a
Definition: glext.h:6204
GLfloat GLfloat GLfloat v2
Definition: glext.h:6063
GLdouble GLdouble z
Definition: glext.h:5874
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
REFIID riid
Definition: atlbase.h:39
#define S_OK
Definition: intsafe.h:52
#define d
Definition: ke_i.h:81
#define a
Definition: ke_i.h:78
#define c
Definition: ke_i.h:80
#define b
Definition: ke_i.h:79
const GUID * guid
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
HRESULT hres
Definition: protocol.c:465
#define todo_wine
Definition: custom.c:89
static void test_SafeArrayGetPutElement_VARIANT(void)
Definition: safearray.c:1332
#define RECORD_SIZE_FAIL
Definition: safearray.c:72
static void test_SafeArrayDestroyData(void)
Definition: safearray.c:1931
static ULONG WINAPI tunk_Release(IUnknown *punk)
Definition: safearray.c:1259
static void test_LockUnlock(void)
Definition: safearray.c:994
static HRESULT WINAPI RecordInfo_RecordCreateCopy(IRecordInfo *iface, PVOID pvSource, PVOID *ppvDest)
Definition: safearray.c:222
static void test_SafeArrayClear(void)
Definition: safearray.c:1648
UINT addflags
Definition: safearray.c:334
const USHORT FADF_CREATEVECTOR
Definition: safearray.c:43
static ULONG WINAPI RecordInfo_Release(IRecordInfo *iface)
Definition: safearray.c:111
struct IRecordInfoImpl IRecordInfoImpl
static HMODULE hOleaut32
Definition: safearray.c:46
static BOOL has_i8
Definition: safearray.c:58
static void test_SafeArrayCreateEx(void)
Definition: safearray.c:1502
static IRecordInfoImpl * impl_from_IRecordInfo(IRecordInfo *iface)
Definition: safearray.c:85
static HRESULT WINAPI RecordInfo_RecordDestroy(IRecordInfo *iface, PVOID pvRecord)
Definition: safearray.c:229
static HRESULT WINAPI RecordInfo_GetFieldNames(IRecordInfo *iface, ULONG *pcNames, BSTR *rgBstrNames)
Definition: safearray.c:203
#define GETPTR(func)
Definition: safearray.c:55
static struct xtunk_impl xtunk
Definition: safearray.c:1247
static void test_safearray_layout(void)
Definition: safearray.c:2029
static HRESULT WINAPI RecordInfo_GetTypeInfo(IRecordInfo *iface, ITypeInfo **ppTypeInfo)
Definition: safearray.c:169
static void test_SafeArrayCreateLockDestroy(void)
Definition: safearray.c:825
static void test_SafeArrayRedim_IUnknown(void)
Definition: safearray.c:1303
static void test_SafeArrayGetPutElement_BSTR(void)
Definition: safearray.c:1206
#define VARTYPE_NOT_SUPPORTED
Definition: safearray.c:329
static ULONG WINAPI RecordInfo_AddRef(IRecordInfo *iface)
Definition: safearray.c:105
UINT expflags
Definition: safearray.c:333
static void test_SafeArrayGetPutElement_IUnknown(void)
Definition: safearray.c:1270
#define START_REF_COUNT
Definition: safearray.c:70
static const IRecordInfoVtbl RecordInfoVtbl
Definition: safearray.c:235
static SAFEARRAY **static SAFEARRAY *static VARTYPE *static IRecordInfo **static SAFEARRAY *WINAPI * pSafeArrayCreateEx(VARTYPE, UINT, SAFEARRAYBOUND *, LPVOID)
static HRESULT WINAPI RecordInfo_RecordClear(IRecordInfo *iface, PVOID pvExisting)
Definition: safearray.c:130
static BOOL WINAPI RecordInfo_IsMatchingType(IRecordInfo *iface, IRecordInfo *info2)
Definition: safearray.c:210
static const IUnknownVtbl xtunk_vtbl
Definition: safearray.c:1245
static void test_SafeArrayCopyData(void)
Definition: safearray.c:1371
static HRESULT WINAPI RecordInfo_GetSize(IRecordInfo *iface, ULONG *size)
Definition: safearray.c:156
static BOOL fail_GetSize
Definition: safearray.c:128
static HRESULT WINAPI RecordInfo_GetGuid(IRecordInfo *iface, GUID *pguid)
Definition: safearray.c:144
static PVOID WINAPI RecordInfo_RecordCreate(IRecordInfo *iface)
Definition: safearray.c:216
static HRESULT WINAPI RecordInfo_GetField(IRecordInfo *iface, PVOID pvData, LPCOLESTR szFieldName, VARIANT *pvarField)
Definition: safearray.c:175
static HRESULT WINAPI tunk_QueryInterface(IUnknown *punk, REFIID riid, void **x)
Definition: safearray.c:1249
static HRESULT WINAPI RecordInfo_GetFieldNoCopy(IRecordInfo *iface, PVOID pvData, LPCOLESTR szFieldName, VARIANT *pvarField, PVOID *ppvDataCArray)
Definition: safearray.c:182
static void test_SafeArrayChangeTypeEx(void)
Definition: safearray.c:1805
static BOOL has_int_ptr
Definition: safearray.c:60
static HRESULT WINAPI RecordInfo_GetName(IRecordInfo *iface, BSTR *pbstrName)
Definition: safearray.c:150
#define MKARRAY(low, num, typ)
Definition: safearray.c:1796
static ULONG WINAPI tunk_AddRef(IUnknown *punk)
Definition: safearray.c:1254
static void test_SafeArrayAllocDestroyDescriptor(void)
Definition: safearray.c:764
static HRESULT WINAPI RecordInfo_QueryInterface(IRecordInfo *iface, REFIID riid, void **obj)
Definition: safearray.c:90
static void test_VectorCreateLockDestroy(void)
Definition: safearray.c:935
static HRESULT WINAPI RecordInfo_RecordInit(IRecordInfo *iface, PVOID pvNew)
Definition: safearray.c:122
static void test_safearray(void)
Definition: safearray.c:380
UINT elemsize
Definition: safearray.c:332
static HRESULT WINAPI RecordInfo_PutField(IRecordInfo *iface, ULONG wFlags, PVOID pvData, LPCOLESTR szFieldName, VARIANT *pvarField)
Definition: safearray.c:189
static HRESULT WINAPI RecordInfo_RecordCopy(IRecordInfo *iface, PVOID pvExisting, PVOID pvNew)
Definition: safearray.c:137
static IRecordInfoImpl * IRecordInfoImpl_Construct(void)
Definition: safearray.c:258
static struct @1699 vttypes[]
static void test_SafeArrayGetPutElement(void)
Definition: safearray.c:1052
static HRESULT WINAPI RecordInfo_PutFieldNoCopy(IRecordInfo *iface, ULONG wFlags, PVOID pvData, LPCOLESTR szFieldName, VARIANT *pvarField)
Definition: safearray.c:196
static void check_for_VT_INT_PTR(void)
Definition: safearray.c:307
#define RECORD_SIZE
Definition: safearray.c:71
static SAFEARRAY *WINAPI * pSafeArrayCreateVector(VARTYPE, LONG, ULONG)
static void test_SafeArrayCopy(void)
Definition: safearray.c:1688
static UINT
Definition: safearray.c:48
INTERNETFEATURELIST feature
Definition: misc.c:1719
unsigned __int3264 UINT_PTR
Definition: mstsclib_h.h:274
unsigned int UINT
Definition: ndis.h:50
static LPUNKNOWN
Definition: ndr_ole.c:49
BSTR WINAPI SysAllocString(LPCOLESTR str)
Definition: oleaut.c:238
UINT WINAPI SysStringLen(BSTR str)
Definition: oleaut.c:196
void WINAPI DECLSPEC_HOTPATCH SysFreeString(BSTR str)
Definition: oleaut.c:271
BSTR WINAPI SysAllocStringLen(const OLECHAR *str, unsigned int len)
Definition: oleaut.c:339
#define V_ARRAY(A)
Definition: oleauto.h:222
#define V_ARRAYREF(A)
Definition: oleauto.h:223
#define V_VT(A)
Definition: oleauto.h:211
#define V_BSTR(A)
Definition: oleauto.h:226
#define V_I4(A)
Definition: oleauto.h:247
const GUID IID_IDispatch
short SHORT
Definition: pedump.c:59
long LONG
Definition: pedump.c:60
unsigned short USHORT
Definition: pedump.c:61
#define INT
Definition: polytest.cpp:20
#define IsEqualGUID(rguid1, rguid2)
Definition: guiddef.h:147
#define IsEqualIID(riid1, riid2)
Definition: guiddef.h:95
#define REFIID
Definition: guiddef.h:118
static __inline const char * wine_dbgstr_guid(const GUID *id)
Definition: debug.h:197
#define win_skip
Definition: test.h:163
#define memset(x, y, z)
Definition: compat.h:39
HRESULT hr
Definition: shlfolder.c:183
IRecordInfo IRecordInfo_iface
Definition: recinfo.c:43
unsigned int sizeCalled
Definition: safearray.c:80
unsigned int recordcopy
Definition: safearray.c:82
unsigned int clearCalled
Definition: safearray.c:81
Definition: send.c:48
USHORT fFeatures
Definition: compat.h:2356
SAFEARRAYBOUND rgsabound[1]
Definition: compat.h:2360
PVOID pvData
Definition: compat.h:2359
IUnknown IUnknown_iface
Definition: safearray.c:1242
int64_t LONG64
Definition: typedefs.h:68
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
Definition: pdh_main.c:94
HRESULT WINAPI VariantChangeTypeEx(VARIANTARG *pvargDest, VARIANTARG *pvargSrc, LCID lcid, USHORT wFlags, VARTYPE vt)
Definition: variant.c:988
HRESULT WINAPI DECLSPEC_HOTPATCH VariantClear(VARIANTARG *pVarg)
Definition: variant.c:648
void WINAPI VariantInit(VARIANTARG *pVarg)
Definition: variant.c:568
HRESULT WINAPI VariantCopy(VARIANTARG *pvargDest, VARIANTARG *pvargSrc)
Definition: variant.c:748
_In_ DWORD _Out_ _In_ WORD wFlags
Definition: wincon.h:531
_In_ ULONG _In_opt_ PVOID pvData
Definition: winddi.h:3749
#define HRESULT
Definition: msvc.h:7
#define WINAPI
Definition: msvc.h:6
#define DISP_E_ARRAYISLOCKED
Definition: winerror.h:2522
#define E_NOINTERFACE
Definition: winerror.h:2364
#define DISP_E_BADVARTYPE
Definition: winerror.h:2517
#define E_UNEXPECTED
Definition: winerror.h:2456
#define DISP_E_BADINDEX
Definition: winerror.h:2520
#define E_POINTER
Definition: winerror.h:2365
#define DISP_E_TYPEMISMATCH
Definition: winerror.h:2514
unsigned char BYTE
Definition: xxhash.c:193