ReactOS  0.4.14-dev-317-g96040ec
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 
48 static HRESULT (WINAPI *pSafeArrayAllocDescriptorEx)(VARTYPE,UINT,SAFEARRAY**);
49 static HRESULT (WINAPI *pSafeArrayCopyData)(SAFEARRAY*,SAFEARRAY*);
50 static HRESULT (WINAPI *pSafeArrayGetVartype)(SAFEARRAY*,VARTYPE*);
51 static HRESULT (WINAPI *pSafeArrayGetRecordInfo)(SAFEARRAY*,IRecordInfo**);
54 
55 #define GETPTR(func) p##func = (void*)GetProcAddress(hOleaut32, #func)
56 
57 /* Has I8/UI8 data type? */
58 static BOOL has_i8;
59 /* Has INT_PTR/UINT_PTR type? */
61 
62 static const USHORT ignored_copy_features[] =
63  {
64  FADF_AUTO,
65  FADF_STATIC,
66  FADF_EMBEDDED,
67  FADF_FIXEDSIZE
68  };
69 
70 #define START_REF_COUNT 1
71 #define RECORD_SIZE 64
72 #define RECORD_SIZE_FAIL 17
73 /************************************************************************
74  * Dummy IRecordInfo Implementation
75  */
76 typedef struct IRecordInfoImpl
77 {
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 
94  if (IsEqualIID(riid, &IID_IUnknown) ||
95  IsEqualIID(riid, &IID_IRecordInfo))
96  {
97  *obj = iface;
98  IRecordInfo_AddRef(iface);
99  return S_OK;
100  }
101 
102  return E_NOINTERFACE;
103 }
104 
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 
128 static BOOL fail_GetSize; /* Whether to fail the GetSize call */
129 
131 {
133  This->clearCalled++;
134  return S_OK;
135 }
136 
137 static HRESULT WINAPI RecordInfo_RecordCopy(IRecordInfo *iface, PVOID pvExisting, PVOID pvNew)
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 
235 static 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 
307 static void check_for_VT_INT_PTR(void)
308 {
309  /* Set a global flag if VT_INT_PTR is supported */
310 
311  SAFEARRAY* a;
312  SAFEARRAYBOUND bound;
313  bound.cElements = 0;
314  bound.lLbound = 0;
315  a = SafeArrayCreate(VT_INT_PTR, 1, &bound);
316  if (a) {
317  HRESULT hres;
318  trace("VT_INT_PTR is supported\n");
319  has_int_ptr = TRUE;
321  ok(hres == S_OK, "got 0x%08x\n", hres);
322  }
323  else {
324  trace("VT_INT_PTR is not supported\n");
325  has_int_ptr = FALSE;
326  }
327 }
328 
329 #define VARTYPE_NOT_SUPPORTED 0
330 static struct {
331  VARTYPE vt; /* VT */
332  UINT elemsize; /* elementsize by VT */
333  UINT expflags; /* fFeatures from SafeArrayAllocDescriptorEx */
334  UINT addflags; /* additional fFeatures from SafeArrayCreate */
335 } vttypes[] = {
336 {VT_EMPTY, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
337 {VT_NULL, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
338 {VT_I2, 2, FADF_HAVEVARTYPE,0},
339 {VT_I4, 4, FADF_HAVEVARTYPE,0},
340 {VT_R4, 4, FADF_HAVEVARTYPE,0},
341 {VT_R8, 8, FADF_HAVEVARTYPE,0},
342 {VT_CY, 8, FADF_HAVEVARTYPE,0},
343 {VT_DATE, 8, FADF_HAVEVARTYPE,0},
344 {VT_BSTR, sizeof(BSTR), FADF_HAVEVARTYPE,FADF_BSTR},
345 {VT_DISPATCH, sizeof(LPDISPATCH), FADF_HAVEIID, FADF_DISPATCH},
346 {VT_ERROR, 4, FADF_HAVEVARTYPE,0},
347 {VT_BOOL, 2, FADF_HAVEVARTYPE,0},
348 {VT_VARIANT, sizeof(VARIANT), FADF_HAVEVARTYPE,FADF_VARIANT},
349 {VT_UNKNOWN, sizeof(LPUNKNOWN), FADF_HAVEIID, FADF_UNKNOWN},
350 {VT_DECIMAL, sizeof(DECIMAL), FADF_HAVEVARTYPE,0},
351 {15, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0}, /* no VT_xxx */
352 {VT_I1, 1, FADF_HAVEVARTYPE,0},
353 {VT_UI1, 1, FADF_HAVEVARTYPE,0},
354 {VT_UI2, 2, FADF_HAVEVARTYPE,0},
355 {VT_UI4, 4, FADF_HAVEVARTYPE,0},
356 {VT_I8, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
357 {VT_UI8, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
358 {VT_INT, sizeof(INT), FADF_HAVEVARTYPE,0},
359 {VT_UINT, sizeof(UINT), FADF_HAVEVARTYPE,0},
360 {VT_VOID, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
361 {VT_HRESULT, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
362 {VT_PTR, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
363 {VT_SAFEARRAY,VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
364 {VT_CARRAY, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
365 {VT_USERDEFINED,VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
366 {VT_LPSTR, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
367 {VT_LPWSTR, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
368 {VT_FILETIME, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
369 {VT_RECORD, VARTYPE_NOT_SUPPORTED,FADF_RECORD,0},
370 {VT_BLOB, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
371 {VT_STREAM, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
372 {VT_STORAGE, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
373 {VT_STREAMED_OBJECT,VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
374 {VT_STORED_OBJECT,VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
375 {VT_BLOB_OBJECT,VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
376 {VT_CF, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
377 {VT_CLSID, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
378 };
379 
380 static void test_safearray(void)
381 {
382  SAFEARRAY *a, b, *c;
383  unsigned int i, diff;
384  LONG indices[2];
385  HRESULT hres;
386  SAFEARRAYBOUND bound, bounds[2];
387  VARIANT v,d;
388  LPVOID data;
389  IID iid;
390  VARTYPE vt;
391  LONG l;
392  unsigned char *ptr1, *ptr2;
393 
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 
512  i = SafeArrayGetDim(a);
513  ok(i == 2, "getdims of 2 din array returned %d\n",i);
514 
515  indices[0] = 0;
516  indices[1] = 23;
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;
652  V_BSTR(&v) = SysAllocStringLen(NULL, 0);
653  hres = VariantChangeTypeEx(&d, &v, 0, 0, VT_UI1|VT_ARRAY);
654  ok(hres==S_OK, "CTE VT_BSTR -> VT_UI1|VT_ARRAY failed with %x\n",hres);
655  ok(V_VT(&d) == (VT_UI1|VT_ARRAY),"CTE BSTR -> VT_UI1|VT_ARRAY did not return VT_UI1|VT_ARRAY, but %d.v\n",V_VT(&v));
656  VariantClear(&v);
657  VariantClear(&d);
658 
659  /* check locking functions */
660  a = SafeArrayCreate(VT_I4, 1, &bound);
661  ok(a!=NULL,"SAC should not fail\n");
662 
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;
767  HRESULT hres;
768  UINT i;
769 
770  /* Failure cases */
772  ok(hres == E_INVALIDARG, "0 dimensions gave hres 0x%x\n", hres);
773 
774  hres = SafeArrayAllocDescriptor(65536, &sa);
775  ok(hres == E_INVALIDARG, "65536 dimensions gave hres 0x%x\n", hres);
776 
777  if (0)
778  {
779  /* Crashes on 95: XP & Wine return E_POINTER */
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",
793  SafeArrayGetDim(sa), i);
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;
829  HRESULT hres;
830  VARTYPE vt;
831  UINT dimension;
832 
833  for (dimension = 0; dimension < ARRAY_SIZE(sab); dimension++)
834  {
835  sab[dimension].lLbound = 0;
836  sab[dimension].cElements = 8;
837  }
838 
839  /* Failure cases */
840 /* This test crashes very early versions with no error checking...
841  sa = SafeArrayCreate(VT_UI1, 1, NULL);
842  ok(sa == NULL, "NULL bounds didn't fail\n");
843 */
844  sa = SafeArrayCreate(VT_UI1, 65536, sab);
845  ok(!sa, "Max bounds didn't fail\n");
846 
847  memset(sab, 0, sizeof(sab));
848 
849  /* Don't test 0 sized dimensions, as Windows has a bug which allows this */
850 
851  for (dimension = 0; dimension < ARRAY_SIZE(sab); dimension++)
852  sab[dimension].cElements = 8;
853 
854  /* Test all VARTYPES in 1-4 dimensions */
855  for (dimension = 1; dimension < 4; dimension++)
856  {
857  for (vt = VT_EMPTY; vt < VT_CLSID; vt++)
858  {
859  DWORD dwLen = SAFEARRAY_GetVTSize(vt);
860 
861  sa = SafeArrayCreate(vt, dimension, sab);
862 
863  if (dwLen)
864  ok(sa != NULL, "VARTYPE %d (@%d dimensions) failed\n", vt, dimension);
865  else
866  ok(sa == NULL || vt == VT_R8,
867  "VARTYPE %d (@%d dimensions) succeeded!\n", vt, dimension);
868 
869  if (sa)
870  {
871  ok(SafeArrayGetDim(sa) == dimension,
872  "VARTYPE %d (@%d dimensions) cDims is %d, expected %d\n",
873  vt, dimension, SafeArrayGetDim(sa), dimension);
874  ok(SafeArrayGetElemsize(sa) == dwLen || vt == VT_R8,
875  "VARTYPE %d (@%d dimensions) cbElements is %d, expected %d\n",
876  vt, dimension, SafeArrayGetElemsize(sa), dwLen);
877 
878  if (vt != VT_UNKNOWN && vt != VT_DISPATCH)
879  {
880  ok((sa->fFeatures & FADF_HAVEIID) == 0,
881  "Non interface type should not have FADF_HAVEIID\n");
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 
907  hres = SafeArrayLock(sa);
908  ok(hres == S_OK, "Lock VARTYPE %d (@%d dimensions) failed; hres 0x%x\n",
909  vt, dimension, hres);
910 
911  if (hres == S_OK)
912  {
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;
938  HRESULT hres;
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  {
958  DWORD dwLen = SAFEARRAY_GetVTSize(vt);
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",
973  vt, element, SafeArrayGetElemsize(sa), dwLen);
974 
975  hres = SafeArrayLock(sa);
976  ok(hres == S_OK, "Lock VARTYPE %d (@%d elements) failed; hres 0x%x\n",
977  vt, element, hres);
978 
979  if (hres == S_OK)
980  {
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 
994 static void test_LockUnlock(void)
995 {
996  SAFEARRAYBOUND sab[4];
997  SAFEARRAY *sa;
998  HRESULT hres;
999  BOOL bVector = FALSE;
1000  int dimension;
1001 
1002  /* Failure cases */
1003  hres = SafeArrayLock(NULL);
1004  ok(hres == E_INVALIDARG, "Lock NULL array hres 0x%x\n", hres);
1006  ok(hres == E_INVALIDARG, "Lock NULL array hres 0x%x\n", hres);
1007 
1008  for (dimension = 0; dimension < ARRAY_SIZE(sab); dimension++)
1009  {
1010  sab[dimension].lLbound = 0;
1011  sab[dimension].cElements = 8;
1012  }
1013 
1014  sa = SafeArrayCreate(VT_UI1, ARRAY_SIZE(sab), sab);
1015 
1016  /* Test maximum locks */
1017 test_LockUnlock_Vector:
1018  if (sa)
1019  {
1020  int count = 0;
1021 
1022  hres = SafeArrayUnlock(sa);
1023  ok (hres == E_UNEXPECTED, "Bad %sUnlock gave hres 0x%x\n",
1024  bVector ? "vector " : "\n", hres);
1025 
1026  while ((hres = SafeArrayLock(sa)) == S_OK)
1027  count++;
1028  ok (count == 65535 && hres == E_UNEXPECTED, "Lock %sfailed at %d; hres 0x%x\n",
1029  bVector ? "vector " : "\n", count, hres);
1030 
1031  if (count == 65535 && hres == E_UNEXPECTED)
1032  {
1033  while ((hres = SafeArrayUnlock(sa)) == S_OK)
1034  count--;
1035  ok (count == 0 && hres == E_UNEXPECTED, "Unlock %sfailed at %d; hres 0x%x\n",
1036  bVector ? "vector " : "\n", count, hres);
1037  }
1038 
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];
1055  LONG indices[ARRAY_SIZE(sab)], index;
1056  SAFEARRAY *sa;
1057  HRESULT hres;
1058  int value = 0, gotvalue, dimension;
1059  IRecordInfoImpl *irec;
1060  unsigned int x,y,z,a;
1061 
1062  for (dimension = 0; dimension < ARRAY_SIZE(sab); dimension++)
1063  {
1064  sab[dimension].lLbound = dimension * 2 + 1;
1065  sab[dimension].cElements = dimension * 3 + 1;
1066  }
1067 
1068  sa = SafeArrayCreate(VT_INT, ARRAY_SIZE(sab), sab);
1069  if (!sa)
1070  return; /* Some early versions can't handle > 3 dims */
1071 
1072  ok(sa->cbElements == sizeof(value), "int size mismatch\n");
1073 
1074  /* Failure cases */
1075  for (x = 0; x < ARRAY_SIZE(sab); x++)
1076  {
1077  indices[0] = sab[0].lLbound;
1078  indices[1] = sab[1].lLbound;
1079  indices[2] = sab[2].lLbound;
1080  indices[3] = sab[3].lLbound;
1081 
1082  indices[x] = indices[x] - 1;
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 */
1178  irec = IRecordInfoImpl_Construct();
1179  irec->ref = 1;
1180 
1181  sab[0].lLbound = 0;
1182  sab[0].cElements = 8;
1183 
1184  sa = pSafeArrayCreateEx(VT_RECORD, 1, sab, &irec->IRecordInfo_iface);
1185  ok(sa != NULL, "failed to create array\n");
1186  ok(irec->ref == 2, "got %d\n", irec->ref);
1187 
1188  index = 0;
1189  irec->recordcopy = 0;
1190  hres = SafeArrayPutElement(sa, &index, (void*)0xdeadbeef);
1191  ok(hres == S_OK, "got 0x%08x\n", hres);
1192  ok(irec->recordcopy == 1, "got %d\n", irec->recordcopy);
1193 
1194  index = 0;
1195  irec->recordcopy = 0;
1196  hres = SafeArrayGetElement(sa, &index, (void*)0xdeadbeef);
1197  ok(hres == S_OK, "got 0x%08x\n", hres);
1198  ok(irec->recordcopy == 1, "got %d\n", irec->recordcopy);
1199 
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 
1241 struct xtunk_impl {
1244 };
1245 static const IUnknownVtbl xtunk_vtbl;
1246 
1247 static 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 
1264 static const IUnknownVtbl xtunk_vtbl = {
1266  tunk_AddRef,
1267  tunk_Release
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 
1371 static void test_SafeArrayCopyData(void)
1372 {
1373  SAFEARRAYBOUND sab[4];
1374  SAFEARRAY *sa;
1375  SAFEARRAY *sacopy;
1376  HRESULT hres;
1377  int dimension, size = 1, i;
1378 
1379  if (!pSafeArrayCopyData)
1380  {
1381  win_skip("SafeArrayCopyData not supported\n");
1382  return;
1383  }
1384 
1385  for (dimension = 0; dimension < ARRAY_SIZE(sab); dimension++)
1386  {
1387  sab[dimension].lLbound = dimension * 2 + 2;
1388  sab[dimension].cElements = dimension * 3 + 1;
1389  size *= sab[dimension].cElements;
1390  }
1391 
1392  sa = SafeArrayCreate(VT_INT, ARRAY_SIZE(sab), sab);
1393  ok(sa != NULL, "Copy test couldn't create array\n");
1394  sacopy = SafeArrayCreate(VT_INT, ARRAY_SIZE(sab), sab);
1395  ok(sacopy != NULL, "Copy test couldn't create copy array\n");
1396 
1397  if (!sa || !sacopy)
1398  return;
1399 
1400  ok(sa->cbElements == sizeof(int), "int size mismatch\n");
1401 
1402  /* Fill the source array with some data; it doesn't matter what */
1403  for (dimension = 0; dimension < size; dimension++)
1404  {
1405  int* data = sa->pvData;
1406  data[dimension] = dimension;
1407  }
1408 
1409  hres = pSafeArrayCopyData(sa, sacopy);
1410  ok(hres == S_OK, "copy data failed hres 0x%x\n", hres);
1411  if (hres == S_OK)
1412  {
1413  ok(!memcmp(sa->pvData, sacopy->pvData, size * sizeof(int)), "compared different\n");
1414  }
1415 
1416  /* Failure cases */
1417  hres = pSafeArrayCopyData(NULL, sacopy);
1418  ok(hres == E_INVALIDARG, "Null copy source hres 0x%x\n", hres);
1419  hres = pSafeArrayCopyData(sa, NULL);
1420  ok(hres == E_INVALIDARG, "Null copy hres 0x%x\n", hres);
1421 
1422  sacopy->rgsabound[0].cElements += 1;
1423  hres = pSafeArrayCopyData(sa, sacopy);
1424  ok(hres == E_INVALIDARG, "Bigger copy first dimension hres 0x%x\n", hres);
1425 
1426  sacopy->rgsabound[0].cElements -= 2;
1427  hres = pSafeArrayCopyData(sa, sacopy);
1428  ok(hres == E_INVALIDARG, "Smaller copy first dimension hres 0x%x\n", hres);
1429  sacopy->rgsabound[0].cElements += 1;
1430 
1431  sacopy->rgsabound[3].cElements += 1;
1432  hres = pSafeArrayCopyData(sa, sacopy);
1433  ok(hres == E_INVALIDARG, "Bigger copy last dimension hres 0x%x\n", hres);
1434 
1435  sacopy->rgsabound[3].cElements -= 2;
1436  hres = pSafeArrayCopyData(sa, sacopy);
1437  ok(hres == E_INVALIDARG, "Smaller copy last dimension hres 0x%x\n", hres);
1438  sacopy->rgsabound[3].cElements += 1;
1439 
1440  hres = SafeArrayDestroy(sacopy);
1441  ok(hres == S_OK, "got 0x%08x\n", hres);
1442  sacopy = NULL;
1443  hres = pSafeArrayCopyData(sa, sacopy);
1444  ok(hres == E_INVALIDARG, "->Null copy hres 0x%x\n", hres);
1445 
1446  hres = SafeArrayCopy(sa, &sacopy);
1447  ok(hres == S_OK, "copy failed hres 0x%x\n", hres);
1448  ok(SafeArrayGetElemsize(sa) == SafeArrayGetElemsize(sacopy),"elemsize wrong\n");
1449  ok(SafeArrayGetDim(sa) == SafeArrayGetDim(sacopy),"dimensions wrong\n");
1450  ok(!memcmp(sa->pvData, sacopy->pvData, size * sizeof(int)), "compared different\n");
1451  hres = SafeArrayDestroy(sacopy);
1452  ok(hres == S_OK, "got 0x%08x\n", hres);
1453 
1454  sacopy = SafeArrayCreate(VT_INT, ARRAY_SIZE(sab), sab);
1455  ok(sacopy != NULL, "Copy test couldn't create copy array\n");
1456  ok(sacopy->fFeatures == FADF_HAVEVARTYPE, "0x%04x\n", sacopy->fFeatures);
1457 
1458  for (i = 0; i < ARRAY_SIZE(ignored_copy_features); i++)
1459  {
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 */
1476  sa = SafeArrayCreateVector(VT_UI1, 0, 2);
1477 
1478  sacopy = SafeArrayCreateVector(VT_UI1, 0, 2);
1479  ok(sa->fFeatures == (FADF_HAVEVARTYPE|FADF_CREATEVECTOR) ||
1480  broken(sa->fFeatures == FADF_CREATEVECTOR /* W2k */),
1481  "got 0x%08x\n", sa->fFeatures);
1482  ok(sacopy->fFeatures == (FADF_HAVEVARTYPE|FADF_CREATEVECTOR) ||
1483  broken(sacopy->fFeatures == FADF_CREATEVECTOR /* W2k */),
1484  "got 0x%08x\n", sacopy->fFeatures);
1485  hres = SafeArrayCopyData(sa, sacopy);
1486  ok(hres == S_OK, "got 0x%08x\n", hres);
1487  ok(sacopy->fFeatures == (FADF_HAVEVARTYPE|FADF_CREATEVECTOR) ||
1488  broken(sacopy->fFeatures == FADF_CREATEVECTOR /* W2k */),
1489  "got 0x%04x\n", sacopy->fFeatures);
1490  SafeArrayDestroy(sacopy);
1491 
1492  sacopy = SafeArrayCreate(VT_UI1, ARRAY_SIZE(sab), sab);
1493  ok(sacopy != NULL, "Copy test couldn't create copy array\n");
1494  ok(sacopy->fFeatures == FADF_HAVEVARTYPE, "0x%04x\n", sacopy->fFeatures);
1495  hres = SafeArrayCopyData(sa, sacopy);
1496  ok(hres == E_INVALIDARG, "got 0x%08x\n", hres);
1497  SafeArrayDestroy(sacopy);
1498 
1500 }
1501 
1502 static void test_SafeArrayCreateEx(void)
1503 {
1504  IRecordInfoImpl* iRec;
1505  SAFEARRAYBOUND sab[4];
1506  SAFEARRAY *sa;
1507  HRESULT hres;
1508  UINT dimension;
1509 
1510  if (!pSafeArrayCreateEx)
1511  {
1512  win_skip("SafeArrayCreateEx not supported\n");
1513  return;
1514  }
1515 
1516  for (dimension = 0; dimension < ARRAY_SIZE(sab); dimension++)
1517  {
1518  sab[dimension].lLbound = 0;
1519  sab[dimension].cElements = 8;
1520  }
1521 
1522  /* Failure cases */
1524  ok(sa == NULL, "CreateEx NULL bounds didn't fail\n");
1525 
1526  /* test IID storage & defaulting */
1527  sa = pSafeArrayCreateEx(VT_DISPATCH, 1, sab, (PVOID)&IID_ITypeInfo);
1528  ok(sa != NULL, "CreateEx (ITypeInfo) failed\n");
1529 
1530  if (sa)
1531  {
1532  GUID guid;
1533 
1534  hres = SafeArrayGetIID(sa, &guid);
1535  ok(hres == S_OK, "Failed to get array IID, hres %#x.\n", hres);
1536  ok(IsEqualGUID(&guid, &IID_ITypeInfo), "CreateEx (ITypeInfo) bad IID\n");
1538  ok(hres == S_OK, "Failed to set IID, hres = %8x\n", hres);
1539  hres = SafeArrayGetIID(sa, &guid);
1540  ok(hres == S_OK && IsEqualGUID(&guid, &IID_IUnknown), "Set bad IID\n");
1542  ok(hres == S_OK, "got 0x%08x\n", hres);
1543  }
1544 
1545  sa = pSafeArrayCreateEx(VT_DISPATCH, 1, sab, NULL);
1546  ok(sa != NULL, "CreateEx (NULL) failed\n");
1547 
1548  if (sa)
1549  {
1550  GUID guid;
1551 
1552  hres = SafeArrayGetIID(sa, &guid);
1553  ok(hres == S_OK, "Failed to get array IID, hres %#x.\n", hres);
1554  ok(IsEqualGUID(&guid, &IID_IDispatch), "CreateEx (NULL) bad IID\n");
1556  ok(hres == S_OK, "got 0x%08x\n", hres);
1557  }
1558 
1559  sa = pSafeArrayCreateEx(VT_UNKNOWN, 1, sab, NULL);
1560  ok(sa != NULL, "CreateEx (NULL-Unk) failed\n");
1561 
1562  if (sa)
1563  {
1564  GUID guid;
1565 
1566  hres = SafeArrayGetIID(sa, &guid);
1567  ok(hres == S_OK, "Failed to get array IID, hres %#x.\n", hres);
1568  ok(IsEqualGUID(&guid, &IID_IUnknown), "CreateEx (NULL-Unk) bad IID\n");
1570  ok(hres == S_OK, "got 0x%08x\n", hres);
1571  }
1572 
1573  /* VT_RECORD failure case */
1574  sa = pSafeArrayCreateEx(VT_RECORD, 1, sab, NULL);
1575  ok(sa == NULL, "CreateEx (NULL-Rec) succeeded\n");
1576 
1577  iRec = IRecordInfoImpl_Construct();
1578 
1579  /* Win32 doesn't care if GetSize fails */
1580  fail_GetSize = TRUE;
1581  sa = pSafeArrayCreateEx(VT_RECORD, 1, sab, &iRec->IRecordInfo_iface);
1582  ok(sa != NULL, "CreateEx (Fail Size) failed\n");
1583  ok(iRec->ref == START_REF_COUNT + 1, "Wrong iRec refcount %d\n", iRec->ref);
1584  ok(iRec->sizeCalled == 1, "GetSize called %d times\n", iRec->sizeCalled);
1585  ok(iRec->clearCalled == 0, "Clear called %d times\n", iRec->clearCalled);
1586  if (sa)
1587  {
1588  ok(sa->cbElements == RECORD_SIZE_FAIL, "Altered size to %d\n", sa->cbElements);
1590  ok(hres == S_OK, "got 0x%08x\n", hres);
1591  ok(iRec->clearCalled == sab[0].cElements, "Destroy->Clear called %d times\n", iRec->clearCalled);
1592  ok(iRec->ref == START_REF_COUNT, "got %d, expected %d\n", iRec->ref, START_REF_COUNT);
1593  }
1594 
1595  /* Test VT_RECORD array */
1596  fail_GetSize = FALSE;
1597  iRec->ref = START_REF_COUNT;
1598  iRec->sizeCalled = 0;
1599  iRec->clearCalled = 0;
1600  sa = pSafeArrayCreateEx(VT_RECORD, 1, sab, &iRec->IRecordInfo_iface);
1601  ok(sa != NULL, "CreateEx (Rec) failed\n");
1602  ok(iRec->ref == START_REF_COUNT + 1, "Wrong iRec refcount %d\n", iRec->ref);
1603  ok(iRec->sizeCalled == 1, "GetSize called %d times\n", iRec->sizeCalled);
1604  ok(iRec->clearCalled == 0, "Clear called %d times\n", iRec->clearCalled);
1605  if (sa && pSafeArrayGetRecordInfo)
1606  {
1607  IRecordInfo* saRec = NULL;
1608  SAFEARRAY *sacopy;
1609 
1610  hres = pSafeArrayGetRecordInfo(sa, &saRec);
1611  ok(hres == S_OK,"GRI failed\n");
1612  ok(saRec == &iRec->IRecordInfo_iface, "Different saRec\n");
1613  ok(iRec->ref == START_REF_COUNT + 2, "Didn't AddRef %d\n", iRec->ref);
1614  IRecordInfo_Release(saRec);
1615 
1616  ok(sa->cbElements == RECORD_SIZE,"Elemsize is %d\n", sa->cbElements);
1617 
1618  /* try to copy record based arrays */
1619  sacopy = pSafeArrayCreateEx(VT_RECORD, 1, sab, &iRec->IRecordInfo_iface);
1620  iRec->recordcopy = 0;
1621  iRec->clearCalled = 0;
1622  /* array copy code doesn't explicitly clear a record */
1623  hres = SafeArrayCopyData(sa, sacopy);
1624  ok(hres == S_OK, "got 0x%08x\n", hres);
1625  ok(iRec->recordcopy == sab[0].cElements, "got %d\n", iRec->recordcopy);
1626  ok(iRec->clearCalled == 0, "got %d\n", iRec->clearCalled);
1627 
1628  hres = SafeArrayDestroy(sacopy);
1629  ok(hres == S_OK, "got 0x%08x\n", hres);
1630 
1631  iRec->clearCalled = 0;
1632  iRec->sizeCalled = 0;
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 
1648 static void test_SafeArrayClear(void)
1649 {
1650  SAFEARRAYBOUND sab;
1651  SAFEARRAY *sa;
1652  VARIANTARG v;
1653  HRESULT hres;
1654 
1655  sab.lLbound = 0;
1656  sab.cElements = 10;
1657  sa = SafeArrayCreate(VT_UI1, 1, &sab);
1658  ok(sa != NULL, "Create() failed.\n");
1659  if (!sa)
1660  return;
1661 
1662  /* Test clearing non-NULL variants containing arrays */
1663  V_VT(&v) = VT_ARRAY|VT_UI1;
1664  V_ARRAY(&v) = sa;
1665  hres = VariantClear(&v);
1666  ok(hres == S_OK && V_VT(&v) == VT_EMPTY, "VariantClear: hres 0x%x, Type %d\n", hres, V_VT(&v));
1667  ok(V_ARRAY(&v) == sa, "VariantClear: Overwrote value\n");
1668 
1669  sa = SafeArrayCreate(VT_UI1, 1, &sab);
1670  ok(sa != NULL, "Create() failed.\n");
1671  if (!sa)
1672  return;
1673 
1674  V_VT(&v) = VT_SAFEARRAY;
1675  V_ARRAY(&v) = sa;
1676  hres = VariantClear(&v);
1677  ok(hres == DISP_E_BADVARTYPE, "VariantClear: hres 0x%x\n", hres);
1678 
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 
1688 static void test_SafeArrayCopy(void)
1689 {
1690  SAFEARRAYBOUND sab;
1691  SAFEARRAY *sa, *sa2;
1692  VARIANTARG vSrc, vDst;
1693  HRESULT hres;
1694  int i;
1695 
1696  sab.lLbound = 0;
1697  sab.cElements = 10;
1698  sa = SafeArrayCreate(VT_UI1, 1, &sab);
1699  ok(sa != NULL, "Create() failed.\n");
1700  if (!sa)
1701  return;
1702 
1703  /* Test copying non-NULL variants containing arrays */
1704  V_VT(&vSrc) = (VT_ARRAY|VT_BYREF|VT_UI1);
1705  V_ARRAYREF(&vSrc) = &sa;
1706  V_VT(&vDst) = VT_EMPTY;
1707 
1708  hres = VariantCopy(&vDst, &vSrc);
1709  ok(hres == S_OK && V_VT(&vDst) == (VT_ARRAY|VT_BYREF|VT_UI1),
1710  "VariantCopy: hres 0x%x, Type %d\n", hres, V_VT(&vDst));
1711  ok(V_ARRAYREF(&vDst) == &sa, "VariantClear: Performed deep copy\n");
1712 
1713  V_VT(&vSrc) = (VT_ARRAY|VT_UI1);
1714  V_ARRAY(&vSrc) = sa;
1715  V_VT(&vDst) = VT_EMPTY;
1716 
1717  hres = VariantCopy(&vDst, &vSrc);
1718  ok(hres == S_OK && V_VT(&vDst) == (VT_ARRAY|VT_UI1),
1719  "VariantCopy: hres 0x%x, Type %d\n", hres, V_VT(&vDst));
1720  ok(V_ARRAY(&vDst) != sa, "VariantClear: Performed shallow copy\n");
1721 
1722  hres = SafeArrayDestroy(V_ARRAY(&vSrc));
1723  ok(hres == S_OK, "got 0x%08x\n", hres);
1724  hres = SafeArrayDestroy(V_ARRAY(&vDst));
1725  ok(hres == S_OK, "got 0x%08x\n", hres);
1726 
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 */
1782  sa = SafeArrayCreateVector(VT_UI1, 0, 2);
1783  ok(sa->fFeatures == (FADF_HAVEVARTYPE|FADF_CREATEVECTOR) ||
1784  broken(sa->fFeatures == FADF_CREATEVECTOR /* W2k */),
1785  "got 0x%08x\n", sa->fFeatures);
1786  hres = SafeArrayCopy(sa, &sa2);
1787  ok(hres == S_OK, "got 0x%08x\n", hres);
1788  ok(sa2->fFeatures == FADF_HAVEVARTYPE ||
1789  broken(!sa2->fFeatures /* W2k */), "got 0x%04x\n",
1790  sa2->fFeatures);
1791 
1792  SafeArrayDestroy(sa2);
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  {
1894  sa = pSafeArrayCreateVector(VT_UI1, 0, 1);
1895  ok(sa != NULL, "CreateVector() failed.\n");
1896  if (!sa)
1897  return;
1898 
1899  V_VT(&v) = VT_ARRAY|VT_UI1;
1900  V_ARRAY(&v) = sa;
1901  hres = VariantChangeTypeEx(&v2, &v, 0, 0, VT_ARRAY|VT_I1);
1902  ok(hres == DISP_E_TYPEMISMATCH, "CTE VT_ARRAY|VT_UI1->VT_ARRAY|VT_I1 returned %x\n", hres);
1903 
1904  /* But can change to the same array type */
1906  ok(hres == S_OK, "got 0x%08x\n", hres);
1907  sa = pSafeArrayCreateVector(VT_UI1, 0, 1);
1908  ok(sa != NULL, "CreateVector() failed.\n");
1909  if (!sa)
1910  return;
1911  V_VT(&v) = VT_ARRAY|VT_UI1;
1912  V_ARRAY(&v) = sa;
1913  hres = VariantChangeTypeEx(&v2, &v, 0, 0, VT_ARRAY|VT_UI1);
1914  ok(hres == S_OK, "CTE VT_ARRAY|VT_UI1->VT_ARRAY|VT_UI1 returned %x\n", hres);
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 
1931 static void test_SafeArrayDestroyData (void)
1932 {
1933  SAFEARRAYBOUND sab[2];
1934  SAFEARRAY *sa;
1935  HRESULT hres;
1936  int value = 0xdeadbeef;
1937  LONG index[1];
1938  void *temp_pvData;
1939  USHORT features;
1940 
1941  sab[0].lLbound = 0;
1942  sab[0].cElements = 10;
1943  sa = SafeArrayCreate(VT_INT, 1, sab);
1944  ok(sa != NULL, "Create() failed.\n");
1945  ok(sa->fFeatures == FADF_HAVEVARTYPE, "got 0x%x\n", sa->fFeatures);
1946 
1947  index[0] = 1;
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);
2019 todo_wine
2020  ok(sa->fFeatures == FADF_HAVEVARTYPE, "got 0x%x\n", sa->fFeatures);
2021 todo_wine
2022  ok(sa->pvData == NULL || broken(sa->pvData != NULL), "got %p\n", sa->pvData);
2023  /* There was a bug on windows, especially visible on 64bit systems,
2024  probably double-free or similar issue. */
2025  sa->pvData = NULL;
2027 }
2028 
2029 static 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));
2054  hr = SafeArrayGetIID(sa, &guid);
2055  ok(hr == S_OK, "got 0x%08x\n", hr);
2056  ok(IsEqualIID(&guid, &IID_IUnknown), "got %s\n", wine_dbgstr_guid(&guid));
2057 
2058  hr = SafeArrayDestroy(sa);
2059  ok(hr == S_OK, "got 0x%08x\n", hr);
2060 
2061  /* VARTYPE field */
2062  sa = SafeArrayCreate(VT_UI1, 1, &sab);
2063  ok(sa != NULL, "got %p\n", sa);
2064 
2065  dwptr = (DWORD*)sa - 1;
2066  ok(*dwptr == VT_UI1, "got %d\n", *dwptr);
2067 
2068  hr = SafeArrayDestroy(sa);
2069  ok(hr == S_OK, "got 0x%08x\n", hr);
2070 
2071  /* IRecordInfo pointer */
2072  irec = IRecordInfoImpl_Construct();
2073  irec->ref = 1;
2074 
2075  sa = pSafeArrayCreateEx(VT_RECORD, 1, &sab, &irec->IRecordInfo_iface);
2076  ok(sa != NULL, "failed to create array\n");
2077 
2078  record = *((IRecordInfo**)sa - 1);
2079  ok(record == &irec->IRecordInfo_iface, "got %p\n", record);
2080 
2081  hr = SafeArrayDestroy(sa);
2082  ok(hr == S_OK, "got 0x%08x\n", hr);
2083  IRecordInfo_Release(&irec->IRecordInfo_iface);
2084 }
2085 
2086 START_TEST(safearray)
2087 {
2088  hOleaut32 = GetModuleHandleA("oleaut32.dll");
2089 
2090  has_i8 = GetProcAddress(hOleaut32, "VarI8FromI1") != NULL;
2091 
2098 
2100  test_safearray();
2104  test_LockUnlock();
2117 }
UINT expflags
Definition: safearray.c:333
unsigned int clearCalled
Definition: safearray.c:81
unsigned __int3264 UINT_PTR
Definition: activex.cpp:275
WCHAR OLECHAR
Definition: compat.h:1933
INTERNETFEATURELIST feature
Definition: misc.c:1689
static void test_VectorCreateLockDestroy(void)
Definition: safearray.c:935
UINT WINAPI SafeArrayGetDim(SAFEARRAY *psa)
Definition: safearray.c:1096
GLuint GLuint GLsizei GLenum const GLvoid * indices
Definition: gl.h:1545
#define RECORD_SIZE_FAIL
Definition: safearray.c:72
struct tagVARIANT VARIANT
Definition: compat.h:2018
IUnknown IUnknown_iface
Definition: safearray.c:1242
HRESULT WINAPI SafeArrayGetRecordInfo(SAFEARRAY *psa, IRecordInfo **pRinfo)
Definition: safearray.c:1611
#define REFIID
Definition: guiddef.h:118
#define TRUE
Definition: types.h:120
#define E_NOINTERFACE
Definition: winerror.h:2364
Definition: compat.h:1939
#define RECORD_SIZE
Definition: safearray.c:71
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
Definition: compat.h:1955
HRESULT hr
Definition: shlfolder.c:183
BSTR WINAPI SysAllocStringLen(const OLECHAR *str, unsigned int len)
Definition: oleaut.c:342
Definition: compat.h:1951
static HRESULT WINAPI RecordInfo_RecordCopy(IRecordInfo *iface, PVOID pvExisting, PVOID pvNew)
Definition: safearray.c:137
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
HRESULT WINAPI SafeArrayCopyData(SAFEARRAY *psaSource, SAFEARRAY *psaTarget)
Definition: safearray.c:1314
static void test_safearray_layout(void)
Definition: safearray.c:2029
REFIID riid
Definition: precomp.h:44
unsigned int recordcopy
Definition: safearray.c:82
GLuint GLuint GLsizei count
Definition: gl.h:1545
#define V_ARRAY(A)
Definition: oleauto.h:222
SAFEARRAYBOUND rgsabound[1]
Definition: compat.h:2001
START_TEST(safearray)
Definition: safearray.c:2086
static HRESULT WINAPI RecordInfo_PutFieldNoCopy(IRecordInfo *iface, ULONG wFlags, PVOID pvData, LPCOLESTR szFieldName, VARIANT *pvarField)
Definition: safearray.c:196
USHORT fFeatures
Definition: compat.h:1997
#define INT
Definition: polytest.cpp:20
static BOOL WINAPI RecordInfo_IsMatchingType(IRecordInfo *iface, IRecordInfo *info2)
Definition: safearray.c:210
static HRESULT WINAPI RecordInfo_GetField(IRecordInfo *iface, PVOID pvData, LPCOLESTR szFieldName, VARIANT *pvarField)
Definition: safearray.c:175
double DATE
Definition: compat.h:1894
#define VARTYPE_NOT_SUPPORTED
Definition: safearray.c:329
const char * wine_dbgstr_guid(const GUID *guid)
static SAFEARRAY *WINAPI * pSafeArrayCreateVector(VARTYPE, LONG, ULONG)
static void test_SafeArrayGetPutElement_BSTR(void)
Definition: safearray.c:1206
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
static struct @1645 vttypes[]
static HRESULT WINAPI RecordInfo_RecordInit(IRecordInfo *iface, PVOID pvNew)
Definition: safearray.c:122
HRESULT WINAPI SafeArrayGetElement(SAFEARRAY *psa, LONG *rgIndices, void *pvData)
Definition: safearray.c:949
OLECHAR * BSTR
Definition: compat.h:1934
void WINAPI VariantInit(VARIANTARG *pVarg)
Definition: variant.c:571
#define E_FAIL
Definition: ddrawi.h:102
static HRESULT(WINAPI *pSafeArrayAllocDescriptorEx)(VARTYPE
static UINT
Definition: safearray.c:48
Definition: send.c:47
#define DISP_E_ARRAYISLOCKED
Definition: winerror.h:2522
static void test_SafeArrayCopy(void)
Definition: safearray.c:1688
#define V_I4(A)
Definition: oleauto.h:247
static const USHORT ignored_copy_features[]
Definition: safearray.c:62
static const IUnknownVtbl xtunk_vtbl
Definition: safearray.c:1245
static BOOL fail_GetSize
Definition: safearray.c:128
const USHORT FADF_CREATEVECTOR
Definition: safearray.c:43
static HRESULT WINAPI RecordInfo_GetFieldNoCopy(IRecordInfo *iface, PVOID pvData, LPCOLESTR szFieldName, VARIANT *pvarField, PVOID *ppvDataCArray)
Definition: safearray.c:182
static HRESULT WINAPI RecordInfo_RecordClear(IRecordInfo *iface, PVOID pvExisting)
Definition: safearray.c:130
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
const GUID * guid
static ULONG WINAPI RecordInfo_AddRef(IRecordInfo *iface)
Definition: safearray.c:105
HRESULT WINAPI SafeArraySetIID(SAFEARRAY *psa, REFGUID guid)
Definition: safearray.c:1643
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
static ULONG WINAPI RecordInfo_Release(IRecordInfo *iface)
Definition: safearray.c:111
HRESULT WINAPI SafeArrayAccessData(SAFEARRAY *psa, void **ppvData)
Definition: safearray.c:1139
unsigned int BOOL
Definition: ntddk_ex.h:94
long LONG
Definition: pedump.c:60
static HRESULT WINAPI tunk_QueryInterface(IUnknown *punk, REFIID riid, void **x)
Definition: safearray.c:1249
#define a
Definition: ke_i.h:78
short SHORT
Definition: pedump.c:59
static LPUNKNOWN
Definition: ndr_ole.c:49
GLenum GLint ref
Definition: glext.h:6028
static void test_SafeArrayAllocDestroyDescriptor(void)
Definition: safearray.c:764
#define V_ARRAYREF(A)
Definition: oleauto.h:223
#define E_INVALIDARG
Definition: ddrawi.h:101
GLdouble GLdouble z
Definition: glext.h:5874
static HRESULT WINAPI RecordInfo_PutField(IRecordInfo *iface, ULONG wFlags, PVOID pvData, LPCOLESTR szFieldName, VARIANT *pvarField)
Definition: safearray.c:189
HRESULT WINAPI SafeArrayPtrOfIndex(SAFEARRAY *psa, LONG *rgIndices, void **ppvData)
Definition: safearray.c:1196
_In_ ULONG _In_opt_ PVOID pvData
Definition: winddi.h:3748
smooth NULL
Definition: ftsmooth.c:416
static BOOL has_int_ptr
Definition: safearray.c:60
BSTR WINAPI SysAllocString(LPCOLESTR str)
Definition: oleaut.c:241
static IRecordInfoImpl * IRecordInfoImpl_Construct(void)
Definition: safearray.c:258
static void test_SafeArrayCopyData(void)
Definition: safearray.c:1371
GLuint index
Definition: glext.h:6031
static void test_SafeArrayGetPutElement(void)
Definition: safearray.c:1052
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
#define b
Definition: ke_i.h:79
HRESULT WINAPI SafeArrayLock(SAFEARRAY *psa)
Definition: safearray.c:797
r l[0]
Definition: byte_order.h:167
union tagCY CY
HRESULT WINAPI SafeArrayUnlock(SAFEARRAY *psa)
Definition: safearray.c:833
UINT addflags
Definition: safearray.c:334
static void test_SafeArrayChangeTypeEx(void)
Definition: safearray.c:1805
int64_t LONG64
Definition: typedefs.h:66
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
#define DISP_E_TYPEMISMATCH
Definition: winerror.h:2514
GLsizeiptr size
Definition: glext.h:5919
static HRESULT WINAPI RecordInfo_GetSize(IRecordInfo *iface, ULONG *size)
Definition: safearray.c:156
HRESULT hres
Definition: protocol.c:465
#define GetProcessHeap()
Definition: compat.h:395
#define trace
Definition: atltest.h:70
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
#define d
Definition: ke_i.h:81
static HRESULT WINAPI RecordInfo_GetName(IRecordInfo *iface, BSTR *pbstrName)
Definition: safearray.c:150
SAFEARRAY *WINAPI SafeArrayCreateEx(VARTYPE vt, UINT cDims, SAFEARRAYBOUND *rgsabound, LPVOID pvExtra)
Definition: safearray.c:630
LONG HRESULT
Definition: typedefs.h:77
HRESULT WINAPI SafeArrayCopy(SAFEARRAY *psa, SAFEARRAY **ppsaOut)
Definition: safearray.c:1381
const GUID IID_IUnknown
static BOOL has_i8
Definition: safearray.c:58
PVOID pvData
Definition: compat.h:2000
#define WINAPI
Definition: msvc.h:8
const GLubyte * c
Definition: glext.h:8905
unsigned short WORD
Definition: ntddk_ex.h:93
HRESULT WINAPI SafeArrayGetLBound(SAFEARRAY *psa, UINT nDim, LONG *plLbound)
Definition: safearray.c:1068
unsigned long DWORD
Definition: ntddk_ex.h:95
static IRecordInfoImpl * impl_from_IRecordInfo(IRecordInfo *iface)
Definition: safearray.c:85
HRESULT WINAPI SafeArrayAllocData(SAFEARRAY *psa)
Definition: safearray.c:559
static HMODULE hOleaut32
Definition: safearray.c:46
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
#define START_REF_COUNT
Definition: safearray.c:70
static HRESULT WINAPI RecordInfo_GetGuid(IRecordInfo *iface, GUID *pguid)
Definition: safearray.c:144
HRESULT WINAPI SafeArrayDestroy(SAFEARRAY *psa)
Definition: safearray.c:1349
SAFEARRAY *WINAPI SafeArrayCreateVector(VARTYPE vt, LONG lLbound, ULONG cElements)
Definition: safearray.c:679
#define GETPTR(func)
Definition: safearray.c:55
const GUID IID_IDispatch
#define DISP_E_BADVARTYPE
Definition: winerror.h:2517
HRESULT WINAPI DECLSPEC_HOTPATCH VariantClear(VARIANTARG *pVarg)
Definition: variant.c:651
Definition: compat.h:1940
#define index(s, c)
Definition: various.h:29
#define todo_wine
Definition: test.h:154
#define InterlockedDecrement
Definition: armddk.h:52
#define V_VT(A)
Definition: oleauto.h:211
static DWORD SAFEARRAY_GetVTSize(VARTYPE vt)
Definition: safearray.c:270
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
HMODULE WINAPI DECLSPEC_HOTPATCH GetModuleHandleA(LPCSTR lpModuleName)
Definition: loader.c:821
unsigned char BYTE
Definition: mem.h:68
static void test_LockUnlock(void)
Definition: safearray.c:994
UINT WINAPI SysStringLen(BSTR str)
Definition: oleaut.c:199
HRESULT WINAPI SafeArrayRedim(SAFEARRAY *psa, SAFEARRAYBOUND *psabound)
Definition: safearray.c:1458
Definition: compat.h:1942
GLsizei const GLfloat * value
Definition: glext.h:6069
#define V_BSTR(A)
Definition: oleauto.h:226
HRESULT WINAPI SafeArrayDestroyData(SAFEARRAY *psa)
Definition: safearray.c:1258
#define broken(x)
Definition: _sntprintf.h:21
static void test_SafeArrayDestroyData(void)
Definition: safearray.c:1931
struct tagDEC DECIMAL
Definition: compat.h:1977
_In_ DWORD _Out_ _In_ WORD wFlags
Definition: wincon.h:519
GLfloat GLfloat GLfloat v2
Definition: glext.h:6063
HRESULT WINAPI SafeArrayDestroyDescriptor(SAFEARRAY *psa)
Definition: safearray.c:757
unsigned int sizeCalled
Definition: safearray.c:80
static HRESULT WINAPI RecordInfo_RecordDestroy(IRecordInfo *iface, PVOID pvRecord)
Definition: safearray.c:229
SAFEARRAY *WINAPI SafeArrayCreate(VARTYPE vt, UINT cDims, SAFEARRAYBOUND *rgsabound)
Definition: safearray.c:602
HRESULT WINAPI SafeArrayGetIID(SAFEARRAY *psa, GUID *pGuid)
Definition: safearray.c:1672
#define S_OK
Definition: intsafe.h:59
HRESULT WINAPI SafeArrayGetUBound(SAFEARRAY *psa, UINT nDim, LONG *plUbound)
Definition: safearray.c:1035
static struct xtunk_impl xtunk
Definition: safearray.c:1247
#define InterlockedIncrement
Definition: armddk.h:53
UINT elemsize
Definition: safearray.c:332
const GLdouble * v
Definition: gl.h:2040
unsigned short USHORT
Definition: pedump.c:61
static void test_SafeArrayCreateEx(void)
Definition: safearray.c:1502
#define ARRAY_SIZE(a)
Definition: main.h:24
#define ok(value,...)
Definition: atltest.h:57
#define E_NOTIMPL
Definition: ddrawi.h:99
struct IRecordInfoImpl IRecordInfoImpl
unsigned short VARTYPE
Definition: compat.h:1895
UINT WINAPI SafeArrayGetElemsize(SAFEARRAY *psa)
Definition: safearray.c:1116
void WINAPI DECLSPEC_HOTPATCH SysFreeString(BSTR str)
Definition: oleaut.c:274
HRESULT WINAPI SafeArrayAllocDescriptorEx(VARTYPE vt, UINT cDims, SAFEARRAY **ppsaOut)
Definition: safearray.c:523
static void test_SafeArrayRedim_IUnknown(void)
Definition: safearray.c:1303
unsigned int UINT
Definition: ndis.h:50
BOOL WINAPI IsEqualGUID(REFGUID rguid1, REFGUID rguid2)
Definition: compobj.c:4112
HRESULT WINAPI SafeArrayGetVartype(SAFEARRAY *psa, VARTYPE *pvt)
Definition: safearray.c:1536
GLint GLint GLint GLint GLint GLint y
Definition: gl.h:1548
#define E_UNEXPECTED
Definition: winerror.h:2456
#define MKARRAY(low, num, typ)
Definition: safearray.c:1796
static void test_safearray(void)
Definition: safearray.c:380
static HRESULT WINAPI RecordInfo_QueryInterface(IRecordInfo *iface, REFIID riid, void **obj)
Definition: safearray.c:90
HRESULT WINAPI SafeArrayPutElement(SAFEARRAY *psa, LONG *rgIndices, void *pvData)
Definition: safearray.c:866
#define c
Definition: ke_i.h:80
static HRESULT WINAPI RecordInfo_GetTypeInfo(IRecordInfo *iface, ITypeInfo **ppTypeInfo)
Definition: safearray.c:169
unsigned int ULONG
Definition: retypes.h:1
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
VARTYPE vt
Definition: safearray.c:331
#define GetProcAddress(x, y)
Definition: compat.h:410
static void test_SafeArrayGetPutElement_IUnknown(void)
Definition: safearray.c:1270
#define DISP_E_BADINDEX
Definition: winerror.h:2520
GLboolean GLboolean GLboolean GLboolean a
Definition: glext.h:6204
static HRESULT WINAPI RecordInfo_RecordCreateCopy(IRecordInfo *iface, PVOID pvSource, PVOID *ppvDest)
Definition: safearray.c:222
HRESULT WINAPI SafeArrayAllocDescriptor(UINT cDims, SAFEARRAY **ppsaOut)
Definition: safearray.c:478
HRESULT WINAPI VariantCopy(VARIANTARG *pvargDest, VARIANTARG *pvargSrc)
Definition: variant.c:751
#define E_POINTER
Definition: winerror.h:2365
static void check_for_VT_INT_PTR(void)
Definition: safearray.c:307
static void test_SafeArrayGetPutElement_VARIANT(void)
Definition: safearray.c:1332
#define memset(x, y, z)
Definition: compat.h:39
static SAFEARRAY **static SAFEARRAY *static VARTYPE *static IRecordInfo **static SAFEARRAY *WINAPI * pSafeArrayCreateEx(VARTYPE, UINT, SAFEARRAYBOUND *, LPVOID)
#define win_skip
Definition: test.h:141
static void test_SafeArrayClear(void)
Definition: safearray.c:1648
static ULONG WINAPI tunk_AddRef(IUnknown *punk)
Definition: safearray.c:1254
#define HeapFree(x, y, z)
Definition: compat.h:394
static struct sockaddr_in sa
Definition: adnsresfilter.c:69
#define IsEqualIID(riid1, riid2)
Definition: guiddef.h:95
Definition: compat.h:1941
HRESULT WINAPI SafeArrayUnaccessData(SAFEARRAY *psa)
Definition: safearray.c:1170
Definition: compat.h:1938
static PVOID WINAPI RecordInfo_RecordCreate(IRecordInfo *iface)
Definition: safearray.c:216
static void test_SafeArrayCreateLockDestroy(void)
Definition: safearray.c:825
IRecordInfo IRecordInfo_iface
Definition: recinfo.c:44
static ULONG WINAPI tunk_Release(IUnknown *punk)
Definition: safearray.c:1259
HRESULT WINAPI VariantChangeTypeEx(VARIANTARG *pvargDest, VARIANTARG *pvargSrc, LCID lcid, USHORT wFlags, VARTYPE vt)
Definition: variant.c:991
static HRESULT WINAPI RecordInfo_GetFieldNames(IRecordInfo *iface, ULONG *pcNames, BSTR *rgBstrNames)
Definition: safearray.c:203
static const IRecordInfoVtbl RecordInfoVtbl
Definition: safearray.c:235