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