ReactOS  0.4.14-dev-593-g1793dcc
propvariant.c
Go to the documentation of this file.
1 /*
2  * PropVariant Tests
3  *
4  * Copyright 2004 Robert Shearman
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 #define COBJMACROS
22 #ifdef __REACTOS__
23 #define CONST_VTABLE
24 #endif
25 
26 #include "windows.h"
27 #include "wtypes.h"
28 #include "ddeml.h"
29 
30 #include "wine/test.h"
31 
32 /* invalid in all versions */
33 #define PROP_INV 0x7f
34 /* valid in v0 and above (NT4+) */
35 #define PROP_V0 0
36 /* valid in v1 and above (Win2k+) */
37 #define PROP_V1 1
38 /* valid in v1a and above (WinXP+) */
39 #define PROP_V1A 2
40 #define PROP_TODO 0x80
41 
42 static const struct valid_mapping
43 {
48 } valid_types[] =
49 {
50  { PROP_V0 , PROP_INV, PROP_INV, PROP_INV }, /* VT_EMPTY */
51  { PROP_V0 , PROP_INV, PROP_INV, PROP_INV }, /* VT_NULL */
52  { PROP_V0 , PROP_V1 , PROP_V0 , PROP_V1 | PROP_TODO }, /* VT_I2 */
53  { PROP_V0 , PROP_V1 , PROP_V0 , PROP_V1 | PROP_TODO }, /* VT_I4 */
54  { PROP_V0 , PROP_V1 , PROP_V0 , PROP_V1 | PROP_TODO }, /* VT_R4 */
55  { PROP_V0 , PROP_V1 , PROP_V0 , PROP_V1 | PROP_TODO }, /* VT_R8 */
56  { PROP_V0 , PROP_V1 , PROP_V0 , PROP_V1 | PROP_TODO }, /* VT_CY */
57  { PROP_V0 , PROP_V1 , PROP_V0 , PROP_V1 | PROP_TODO }, /* VT_DATE */
58  { PROP_V0 , PROP_V1 , PROP_V0 , PROP_V1 | PROP_TODO }, /* VT_BSTR */
59  { PROP_V1 , PROP_V1 , PROP_INV, PROP_V1 | PROP_TODO }, /* VT_DISPATCH */
60  { PROP_V0 , PROP_V1 , PROP_V0 , PROP_V1 | PROP_TODO }, /* VT_ERROR */
61  { PROP_V0 , PROP_V1 , PROP_V0 , PROP_V1 | PROP_TODO }, /* VT_BOOL */
62  { PROP_V1 | PROP_TODO , PROP_V1 , PROP_V0 , PROP_V1 | PROP_TODO }, /* VT_VARIANT */
63  { PROP_V1 , PROP_V1, PROP_INV, PROP_V1 | PROP_TODO }, /* VT_UNKNOWN */
64  { PROP_V1 , PROP_V1 , PROP_INV, PROP_V1 | PROP_TODO }, /* VT_DECIMAL */
65  { PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* 15 */
66  { PROP_V1 , PROP_V1 , PROP_V1 , PROP_V1 | PROP_TODO }, /* VT_I1 */
67  { PROP_V0 , PROP_V1 , PROP_V0 , PROP_V1 | PROP_TODO }, /* VT_UI1 */
68  { PROP_V0 , PROP_V1 , PROP_V0 , PROP_V1 | PROP_TODO }, /* VT_UI2 */
69  { PROP_V0 , PROP_V1 , PROP_V0 , PROP_V1 | PROP_TODO }, /* VT_UI4 */
70  { PROP_V0 , PROP_V1A | PROP_TODO, PROP_V0 , PROP_V1A | PROP_TODO }, /* VT_I8 */
71  { PROP_V0 , PROP_V1A | PROP_TODO, PROP_V0 , PROP_V1A | PROP_TODO }, /* VT_UI8 */
72  { PROP_V1 , PROP_V1 , PROP_INV, PROP_V1 | PROP_TODO }, /* VT_INT */
73  { PROP_V1 , PROP_V1 , PROP_INV, PROP_V1 | PROP_TODO }, /* VT_UINT */
74  { PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* VT_VOID */
75  { PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* VT_HRESULT */
76  { PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* VT_PTR */
77  { PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* VT_SAFEARRAY */
78  { PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* VT_CARRAY */
79  { PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* VT_USERDEFINED */
80  { PROP_V0 , PROP_INV, PROP_V0 , PROP_INV }, /* VT_LPSTR */
81  { PROP_V0 , PROP_INV, PROP_V0 , PROP_INV }, /* VT_LPWSTR */
82  { PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* 32 */
83  { PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* 33 */
84  { PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* 34 */
85  { PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* 35 */
86  { PROP_V1 | PROP_TODO , PROP_V1 | PROP_TODO , PROP_INV, PROP_V1 | PROP_TODO }, /* VT_RECORD */
87  { PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* VT_INT_PTR */
88  { PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* VT_UINT_PTR */
89  { PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* 39 */
90  { PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* 40 */
91  { PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* 41 */
92  { PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* 42 */
93  { PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* 43 */
94  { PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* 44 */
95  { PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* 45 */
96  { PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* 46 */
97  { PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* 47 */
98  { PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* 48 */
99  { PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* 49 */
100  { PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* 50 */
101  { PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* 51 */
102  { PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* 52 */
103  { PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* 53 */
104  { PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* 54 */
105  { PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* 55 */
106  { PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* 56 */
107  { PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* 57 */
108  { PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* 58 */
109  { PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* 59 */
110  { PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* 60 */
111  { PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* 61 */
112  { PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* 62 */
113  { PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* 63 */
114  { PROP_V0 , PROP_INV, PROP_V0 , PROP_INV }, /* VT_FILETIME */
115  { PROP_V0 , PROP_INV, PROP_INV, PROP_INV }, /* VT_BLOB */
116  { PROP_V0 , PROP_INV, PROP_INV, PROP_INV }, /* VT_STREAM */
117  { PROP_V0 , PROP_INV, PROP_INV, PROP_INV }, /* VT_STORAGE */
118  { PROP_V0 , PROP_INV, PROP_INV, PROP_INV }, /* VT_STREAMED_OBJECT */
119  { PROP_V0 , PROP_INV, PROP_INV, PROP_INV }, /* VT_STORED_OBJECT */
120  { PROP_V0 , PROP_INV, PROP_INV, PROP_INV }, /* VT_BLOB_OBJECT */
121  { PROP_V0 , PROP_INV, PROP_V0 , PROP_INV } /* VT_CF */
122 };
123 
124 static const char* wine_vtypes[VT_CLSID+1] =
125 {
126  "VT_EMPTY","VT_NULL","VT_I2","VT_I4","VT_R4","VT_R8","VT_CY","VT_DATE",
127  "VT_BSTR","VT_DISPATCH","VT_ERROR","VT_BOOL","VT_VARIANT","VT_UNKNOWN",
128  "VT_DECIMAL","15","VT_I1","VT_UI1","VT_UI2","VT_UI4","VT_I8","VT_UI8",
129  "VT_INT","VT_UINT","VT_VOID","VT_HRESULT","VT_PTR","VT_SAFEARRAY",
130  "VT_CARRAY","VT_USERDEFINED","VT_LPSTR","VT_LPWSTR","32","33","34","35",
131  "VT_RECORD","VT_INT_PTR","VT_UINT_PTR","39","40","41","42","43","44","45",
132  "46","47","48","49","50","51","52","53","54","55","56","57","58","59","60",
133  "61","62","63","VT_FILETIME","VT_BLOB","VT_STREAM","VT_STORAGE",
134  "VT_STREAMED_OBJECT","VT_STORED_OBJECT","VT_BLOB_OBJECT","VT_CF","VT_CLSID"
135 };
136 
137 
138 static void expect(HRESULT hr, VARTYPE vt, BOOL copy, int line)
139 {
140  int idx = vt & VT_TYPEMASK;
141  BYTE flags;
142  const char *modifier;
143 
144  if(vt & VT_BYREF)
145  {
146  flags = valid_types[idx].byref;
147  modifier = "byref";
148  }
149  else if(vt & VT_ARRAY)
150  {
151  flags = valid_types[idx].with_array;
152  modifier = "array";
153  }
154  else if(vt & VT_VECTOR)
155  {
156  flags = valid_types[idx].with_vector;
157  modifier = "vector";
158  }
159  else
160  {
161  flags = valid_types[idx].simple;
162  modifier = "simple";
163  }
164 
165  if(flags == PROP_INV)
166  {
167  if (copy && (vt & VT_VECTOR))
168  ok(hr == DISP_E_BADVARTYPE || hr == STG_E_INVALIDPARAMETER, "%s (%s): got %08x (line %d)\n", wine_vtypes[idx], modifier, hr, line);
169  else
170  ok(hr == (copy ? DISP_E_BADVARTYPE : STG_E_INVALIDPARAMETER), "%s (%s): got %08x (line %d)\n", wine_vtypes[idx], modifier, hr, line);
171  }
172  else if(flags == PROP_V0)
173  ok(hr == S_OK, "%s (%s): got %08x\n", wine_vtypes[idx], modifier, hr);
175  {
176  if(hr != S_OK)
177  win_skip("%s (%s): unsupported\n", wine_vtypes[idx], modifier);
178  else ok(hr == S_OK, "%s (%s): got %08x\n", wine_vtypes[idx], modifier, hr);
179  }
180 }
181 
182 static void test_validtypes(void)
183 {
184  PROPVARIANT propvar, copy, uninit;
185  HRESULT hr;
186  unsigned int i, ret;
187 
188  memset(&uninit, 0x77, sizeof(uninit));
189 
190  memset(&propvar, 0x55, sizeof(propvar));
191  hr = PropVariantClear(&propvar);
192  ok(hr == STG_E_INVALIDPARAMETER, "expected STG_E_INVALIDPARAMETER, got %08x\n", hr);
193  ok(propvar.vt == 0, "expected 0, got %d\n", propvar.vt);
194  ok(U(propvar).uhVal.QuadPart == 0, "expected 0, got %#x/%#x\n",
195  U(propvar).uhVal.u.LowPart, U(propvar).uhVal.u.HighPart);
196 
197  for (i = 0; i < ARRAY_SIZE(valid_types); i++)
198  {
199  VARTYPE vt;
200 
201  memset(&propvar, 0x55, sizeof(propvar));
202  if (i == VT_RECORD)
203  memset(&propvar, 0, sizeof(propvar));
204  else if (i == VT_BLOB || i == VT_BLOB_OBJECT)
205  {
206  U(propvar).blob.cbSize = 0;
207  U(propvar).blob.pBlobData = NULL;
208  }
209  else
210  U(propvar).pszVal = NULL;
211  vt = propvar.vt = i;
212  memset(&copy, 0x77, sizeof(copy));
213  hr = PropVariantCopy(&copy, &propvar);
214  expect(hr, vt, TRUE, __LINE__);
215  if (hr == S_OK)
216  {
217  ok(copy.vt == propvar.vt, "expected %d, got %d\n", propvar.vt, copy.vt);
218  ok(U(copy).uhVal.QuadPart == U(propvar).uhVal.QuadPart, "%u: expected %#x/%#x, got %#x/%#x\n",
219  i, U(propvar).uhVal.u.LowPart, U(propvar).uhVal.u.HighPart,
220  U(copy).uhVal.u.LowPart, U(copy).uhVal.u.HighPart);
221  }
222  else
223  {
224  ret = memcmp(&copy, &uninit, sizeof(copy));
225  ok(!ret || broken(ret) /* win2000 */, "%d: copy should stay unchanged\n", i);
226  }
227  hr = PropVariantClear(&propvar);
228  expect(hr, vt, FALSE, __LINE__);
229  ok(propvar.vt == 0, "expected 0, got %d\n", propvar.vt);
230  ok(U(propvar).uhVal.QuadPart == 0, "%u: expected 0, got %#x/%#x\n",
231  i, U(propvar).uhVal.u.LowPart, U(propvar).uhVal.u.HighPart);
232 
233  memset(&propvar, 0x55, sizeof(propvar));
234  U(propvar).pszVal = NULL;
235  vt = propvar.vt = i | VT_ARRAY;
236  memset(&copy, 0x77, sizeof(copy));
237  hr = PropVariantCopy(&copy, &propvar);
238  expect(hr, vt, TRUE, __LINE__);
239  if (hr == S_OK)
240  {
241  ok(copy.vt == propvar.vt, "expected %d, got %d\n", propvar.vt, copy.vt);
242  ok(U(copy).uhVal.QuadPart == 0, "%u: expected 0, got %#x/%#x\n",
243  i, U(copy).uhVal.u.LowPart, U(copy).uhVal.u.HighPart);
244  }
245  else
246  {
247  ret = memcmp(&copy, &uninit, sizeof(copy));
248  ok(!ret || broken(ret) /* win2000 */, "%d: copy should stay unchanged\n", i);
249  }
250  hr = PropVariantClear(&propvar);
251  expect(hr, vt, FALSE, __LINE__);
252  ok(propvar.vt == 0, "expected 0, got %d\n", propvar.vt);
253  ok(U(propvar).uhVal.QuadPart == 0, "%u: expected 0, got %#x/%#x\n",
254  i, U(propvar).uhVal.u.LowPart, U(propvar).uhVal.u.HighPart);
255 
256  memset(&propvar, 0x55, sizeof(propvar));
257  U(propvar).caub.cElems = 0;
258  U(propvar).caub.pElems = NULL;
259  vt = propvar.vt = i | VT_VECTOR;
260  memset(&copy, 0x77, sizeof(copy));
261  hr = PropVariantCopy(&copy, &propvar);
262  expect(hr, vt, TRUE, __LINE__);
263  if (hr == S_OK)
264  {
265  ok(copy.vt == propvar.vt, "expected %d, got %d\n", propvar.vt, copy.vt);
266  ok(!U(copy).caub.cElems, "%u: expected 0, got %d\n", i, U(copy).caub.cElems);
267  ok(!U(copy).caub.pElems, "%u: expected NULL, got %p\n", i, U(copy).caub.pElems);
268  }
269  else
270  {
271  ret = memcmp(&copy, &uninit, sizeof(copy));
272  ok(!ret || broken(ret) /* win2000 */, "%d: copy should stay unchanged\n", i);
273  }
274  hr = PropVariantClear(&propvar);
275  expect(hr, vt, FALSE, __LINE__);
276  ok(propvar.vt == 0, "expected 0, got %d\n", propvar.vt);
277  ok(U(propvar).uhVal.QuadPart == 0, "%u: expected 0, got %#x/%#x\n",
278  i, U(propvar).uhVal.u.LowPart, U(propvar).uhVal.u.HighPart);
279 
280  memset(&propvar, 0x55, sizeof(propvar));
281  U(propvar).pszVal = NULL;
282  vt = propvar.vt = i | VT_BYREF;
283  memset(&copy, 0x77, sizeof(copy));
284  hr = PropVariantCopy(&copy, &propvar);
285  expect(hr, vt, TRUE, __LINE__);
286  if (hr == S_OK)
287  {
288  ok(copy.vt == propvar.vt, "expected %d, got %d\n", propvar.vt, copy.vt);
289  ok(U(copy).uhVal.QuadPart == U(propvar).uhVal.QuadPart, "%u: expected %#x/%#x, got %#x/%#x\n",
290  i, U(propvar).uhVal.u.LowPart, U(propvar).uhVal.u.HighPart,
291  U(copy).uhVal.u.LowPart, U(copy).uhVal.u.HighPart);
292  }
293  else
294  {
295  ret = memcmp(&copy, &uninit, sizeof(copy));
296  ok(!ret || broken(ret) /* win2000 */, "%d: copy should stay unchanged\n", i);
297  }
298  hr = PropVariantClear(&propvar);
299  expect(hr, vt, FALSE, __LINE__);
300  ok(propvar.vt == 0, "expected 0, got %d\n", propvar.vt);
301  ok(U(propvar).uhVal.QuadPart == 0, "%u: expected 0, got %#x/%#x\n",
302  i, U(propvar).uhVal.u.LowPart, U(propvar).uhVal.u.HighPart);
303  }
304 }
305 
306 struct unk_impl
307 {
309  LONG ref;
310 };
311 
312 static inline struct unk_impl *impl_from_IUnknown(IUnknown *iface)
313 {
314  return CONTAINING_RECORD(iface, struct unk_impl, IUnknown_iface);
315 }
316 
318 {
319  struct unk_impl *This = impl_from_IUnknown(iface);
320  if(winetest_debug > 1)
321  trace("Call to unk_QueryInterface()\n");
322  *ppv = &This->IUnknown_iface;
323  IUnknown_AddRef(iface);
324  return S_OK;
325 }
326 
328 {
329  struct unk_impl *This = impl_from_IUnknown(iface);
330  if(winetest_debug > 1)
331  trace("Call to unk_AddRef()\n");
332  return InterlockedIncrement(&This->ref);
333 }
334 
336 {
337  struct unk_impl *This = impl_from_IUnknown(iface);
338  if(winetest_debug > 1)
339  trace("Call to unk_Release()\n");
340  return InterlockedDecrement(&This->ref);
341 }
342 
343 static const IUnknownVtbl unk_vtbl =
344 {
346  unk_AddRef,
348 };
349 
350 static void test_copy(void)
351 {
352  static char szTestString[] = "Test String";
353  static WCHAR wszTestString[] = {'T','e','s','t',' ','S','t','r','i','n','g',0};
354  struct unk_impl unk_obj = {{&unk_vtbl}, 1};
355  PROPVARIANT propvarSrc;
356  PROPVARIANT propvarDst;
357  SAFEARRAY *sa;
358  SAFEARRAYBOUND sabound;
359  LONG saindex;
360  HRESULT hr;
361 
362  propvarSrc.vt = VT_BSTR;
363  U(propvarSrc).bstrVal = SysAllocString(wszTestString);
364 
365  hr = PropVariantCopy(&propvarDst, &propvarSrc);
366  ok(hr == S_OK, "PropVariantCopy(...VT_BSTR...) failed\n");
367  ok(!lstrcmpW(U(propvarSrc).bstrVal, U(propvarDst).bstrVal), "BSTR not copied properly\n");
369  ok(hr == S_OK, "PropVariantClear(...VT_BSTR...) failed\n");
370  hr = PropVariantClear(&propvarDst);
371  ok(hr == S_OK, "PropVariantClear(...VT_BSTR...) failed\n");
372 
373  propvarSrc.vt = VT_LPWSTR;
374  U(propvarSrc).pwszVal = wszTestString;
375  hr = PropVariantCopy(&propvarDst, &propvarSrc);
376  ok(hr == S_OK, "PropVariantCopy(...VT_LPWSTR...) failed\n");
377  ok(!lstrcmpW(U(propvarSrc).pwszVal, U(propvarDst).pwszVal), "Wide string not copied properly\n");
378  hr = PropVariantClear(&propvarDst);
379  ok(hr == S_OK, "PropVariantClear(...VT_LPWSTR...) failed\n");
380  memset(&propvarSrc, 0, sizeof(propvarSrc));
381 
382  propvarSrc.vt = VT_LPSTR;
383  U(propvarSrc).pszVal = szTestString;
384  hr = PropVariantCopy(&propvarDst, &propvarSrc);
385  ok(hr == S_OK, "PropVariantCopy(...VT_LPSTR...) failed\n");
386  ok(!strcmp(U(propvarSrc).pszVal, U(propvarDst).pszVal), "String not copied properly\n");
387  hr = PropVariantClear(&propvarDst);
388  ok(hr == S_OK, "PropVariantClear(...VT_LPSTR...) failed\n");
389  memset(&propvarSrc, 0, sizeof(propvarSrc));
390 
391  propvarSrc.vt = VT_UNKNOWN;
392  U(propvarSrc).punkVal = &unk_obj.IUnknown_iface;
393  hr = PropVariantCopy(&propvarDst, &propvarSrc);
394  ok(hr == S_OK, "PropVariantCopy(...VT_UNKNOWN...) failed: 0x%08x.\n", hr);
395  ok(U(propvarDst).punkVal == &unk_obj.IUnknown_iface, "Got wrong IUnknown pointer\n");
396  ok(unk_obj.ref == 2, "got wrong refcount: %d.\n", unk_obj.ref);
397  hr = PropVariantClear(&propvarDst);
398  ok(hr == S_OK, "PropVariantClear(...VT_UNKNOWN...) failed: 0x%08x.\n", hr);
399  ok(unk_obj.ref == 1, "got wrong refcount: %d.\n", unk_obj.ref);
400  memset(&propvarSrc, 0, sizeof(propvarSrc));
401 
402  sabound.lLbound = 0;
403  sabound.cElements = 2;
404  sa = SafeArrayCreate(VT_UNKNOWN, 1, &sabound);
405  saindex = 0;
406  SafeArrayPutElement(sa, &saindex, &unk_obj.IUnknown_iface);
407  saindex = 1;
408  SafeArrayPutElement(sa, &saindex, &unk_obj.IUnknown_iface);
409  ok(unk_obj.ref == 3, "got wrong refcount: %d.\n", unk_obj.ref);
410 
412  U(propvarSrc).parray = sa;
413  hr = PropVariantCopy(&propvarDst, &propvarSrc);
414  ok(hr == S_OK, "PropVariantCopy(...VT_ARRAY|VT_UNKNOWN...) failed: 0x%08x.\n", hr);
415  ok(unk_obj.ref == 5, "got wrong refcount: %d.\n", unk_obj.ref);
416  hr = PropVariantClear(&propvarDst);
417  ok(hr == S_OK, "PropVariantClear(...VT_ARRAY|VT_UNKNOWN...) failed: 0x%08x.\n", hr);
418  ok(unk_obj.ref == 3, "got wrong refcount: %d.\n", unk_obj.ref);
420  ok(hr == S_OK, "PropVariantClear(...VT_ARRAY|VT_UNKNOWN...) failed: 0x%08x.\n", hr);
421  ok(unk_obj.ref == 1, "got wrong refcount: %d.\n", unk_obj.ref);
422  memset(&propvarSrc, 0, sizeof(propvarSrc));
423 }
424 
426  void *Allocate; /* virtual void* Allocate(ULONG cbSize); */
427  void *Free; /* virtual void Free(void *pv); */
428 };
429 
430 typedef struct _PMemoryAllocator {
433 
435 {
436  return CoTaskMemAlloc(cbSize);
437 }
438 
439 static void WINAPI PMemoryAllocator_Free(PMemoryAllocator *_this, void *pv)
440 {
441  CoTaskMemFree(pv);
442 }
443 
444 #ifdef __i386__
445 
446 #include "pshpack1.h"
447 typedef struct
448 {
449  BYTE pop_eax; /* popl %eax */
450  BYTE push_ecx; /* pushl %ecx */
451  BYTE push_eax; /* pushl %eax */
452  BYTE jmp_func; /* jmp $func */
453  DWORD func;
455 #include "poppack.h"
456 
458 
459 static void fill_thunk(THISCALL_TO_STDCALL_THUNK *thunk, void *fn)
460 {
461  thunk->pop_eax = 0x58;
462  thunk->push_ecx = 0x51;
463  thunk->push_eax = 0x50;
464  thunk->jmp_func = 0xe9;
465  thunk->func = (char*)fn - (char*)(&thunk->func + 1);
466 }
467 
468 static void setup_vtable(struct _PMemoryAllocator_vtable *vtable)
469 {
472 
473  fill_thunk(&wrapperCodeMem[0], PMemoryAllocator_Allocate);
474  fill_thunk(&wrapperCodeMem[1], PMemoryAllocator_Free);
475 
476  vtable->Allocate = &wrapperCodeMem[0];
477  vtable->Free = &wrapperCodeMem[1];
478 }
479 
480 #else
481 
483 {
484  vtable->Allocate = PMemoryAllocator_Allocate;
486 }
487 
488 #endif
489 
490 static const char serialized_empty[] = {
491  0,0, /* VT_EMPTY */
492  0,0, /* padding */
493 };
494 
495 static const char serialized_null[] = {
496  1,0, /* VT_NULL */
497  0,0, /* padding */
498 };
499 
500 static const char serialized_i4[] = {
501  3,0, /* VT_I4 */
502  0,0, /* padding */
503  0xef,0xcd,0xab,0xfe
504 };
505 
506 static const char serialized_bstr_wc[] = {
507  8,0, /* VT_BSTR */
508  0,0, /* padding */
509  10,0,0,0, /* size */
510  't',0,'e',0,
511  's',0,'t',0,
512  0,0,0,0
513 };
514 
515 static const char serialized_bstr_mb[] = {
516  8,0, /* VT_BSTR */
517  0,0, /* padding */
518  5,0,0,0, /* size */
519  't','e','s','t',
520  0,0,0,0
521 };
522 
523 static void test_propertytovariant(void)
524 {
525  HANDLE hole32;
526  BOOLEAN (__stdcall *pStgConvertPropertyToVariant)(const SERIALIZEDPROPERTYVALUE*,USHORT,PROPVARIANT*,PMemoryAllocator*);
527  PROPVARIANT propvar;
530  BOOLEAN ret;
531  static const WCHAR test_string[] = {'t','e','s','t',0};
532 
533  hole32 = GetModuleHandleA("ole32");
534 
535  pStgConvertPropertyToVariant = (void*)GetProcAddress(hole32, "StgConvertPropertyToVariant");
536 
537  if (!pStgConvertPropertyToVariant)
538  {
539  win_skip("StgConvertPropertyToVariant not available\n");
540  return;
541  }
542 
544  allocator.vt = &vtable;
545 
546  ret = pStgConvertPropertyToVariant((SERIALIZEDPROPERTYVALUE*)serialized_empty,
547  CP_WINUNICODE, &propvar, &allocator);
548 
549  ok(ret == 0, "StgConvertPropertyToVariant returned %i\n", ret);
550  ok(propvar.vt == VT_EMPTY, "unexpected vt %x\n", propvar.vt);
551 
552  ret = pStgConvertPropertyToVariant((SERIALIZEDPROPERTYVALUE*)serialized_null,
553  CP_WINUNICODE, &propvar, &allocator);
554 
555  ok(ret == 0, "StgConvertPropertyToVariant returned %i\n", ret);
556  ok(propvar.vt == VT_NULL, "unexpected vt %x\n", propvar.vt);
557 
558  ret = pStgConvertPropertyToVariant((SERIALIZEDPROPERTYVALUE*)serialized_i4,
559  CP_WINUNICODE, &propvar, &allocator);
560 
561  ok(ret == 0, "StgConvertPropertyToVariant returned %i\n", ret);
562  ok(propvar.vt == VT_I4, "unexpected vt %x\n", propvar.vt);
563  ok(U(propvar).lVal == 0xfeabcdef, "unexpected lVal %x\n", U(propvar).lVal);
564 
565  ret = pStgConvertPropertyToVariant((SERIALIZEDPROPERTYVALUE*)serialized_bstr_wc,
566  CP_WINUNICODE, &propvar, &allocator);
567 
568  ok(ret == 0, "StgConvertPropertyToVariant returned %i\n", ret);
569  ok(propvar.vt == VT_BSTR, "unexpected vt %x\n", propvar.vt);
570  ok(!lstrcmpW(U(propvar).bstrVal, test_string), "unexpected string value\n");
571  PropVariantClear(&propvar);
572 
573  ret = pStgConvertPropertyToVariant((SERIALIZEDPROPERTYVALUE*)serialized_bstr_mb,
574  CP_UTF8, &propvar, &allocator);
575 
576  ok(ret == 0, "StgConvertPropertyToVariant returned %i\n", ret);
577  ok(propvar.vt == VT_BSTR, "unexpected vt %x\n", propvar.vt);
578  ok(!lstrcmpW(U(propvar).bstrVal, test_string), "unexpected string value\n");
579  PropVariantClear(&propvar);
580 }
581 
582 static void test_varianttoproperty(void)
583 {
584  HANDLE hole32;
585  PROPVARIANT propvar;
586  SERIALIZEDPROPERTYVALUE *propvalue, *own_propvalue;
587  SERIALIZEDPROPERTYVALUE* (__stdcall *pStgConvertVariantToProperty)(
588  const PROPVARIANT*,USHORT,SERIALIZEDPROPERTYVALUE*,ULONG*,PROPID,BOOLEAN,ULONG*);
589  ULONG len;
590  static const WCHAR test_string[] = {'t','e','s','t',0};
591  BSTR test_string_bstr;
592 
593  hole32 = GetModuleHandleA("ole32");
594 
595  pStgConvertVariantToProperty = (void*)GetProcAddress(hole32, "StgConvertVariantToProperty");
596 
597  if (!pStgConvertVariantToProperty)
598  {
599  win_skip("StgConvertVariantToProperty not available\n");
600  return;
601  }
602 
603  own_propvalue = HeapAlloc(GetProcessHeap(), 0, sizeof(SERIALIZEDPROPERTYVALUE) + 20);
604 
605  PropVariantInit(&propvar);
606 
607  propvar.vt = VT_I4;
608  U(propvar).lVal = 0xfeabcdef;
609 
610  len = 0xdeadbeef;
611  propvalue = pStgConvertVariantToProperty(&propvar, CP_WINUNICODE, NULL, &len,
612  0, FALSE, 0);
613 
614  ok(propvalue == NULL, "got nonnull propvalue\n");
615  todo_wine ok(len == 8, "unexpected length %d\n", len);
616 
617  if (len == 0xdeadbeef)
618  {
619  HeapFree(GetProcessHeap(), 0, own_propvalue);
620  return;
621  }
622 
623  len = 20;
624  propvalue = pStgConvertVariantToProperty(&propvar, CP_WINUNICODE, own_propvalue, &len,
625  0, FALSE, 0);
626 
627  ok(propvalue == own_propvalue, "unexpected propvalue %p\n", propvalue);
628  ok(len == 8, "unexpected length %d\n", len);
629  ok(!memcmp(propvalue, serialized_i4, 8), "got wrong data\n");
630 
631  propvar.vt = VT_EMPTY;
632  len = 20;
633  own_propvalue->dwType = 0xdeadbeef;
634  propvalue = pStgConvertVariantToProperty(&propvar, CP_WINUNICODE, own_propvalue, &len,
635  0, FALSE, 0);
636 
637  ok(propvalue == own_propvalue, "unexpected propvalue %p\n", propvalue);
638  ok(len == 4 || broken(len == 0) /* before Vista */, "unexpected length %d\n", len);
639  if (len) ok(!memcmp(propvalue, serialized_empty, 4), "got wrong data\n");
640  else ok(propvalue->dwType == 0xdeadbeef, "unexpected type %d\n", propvalue->dwType);
641 
642  propvar.vt = VT_NULL;
643  len = 20;
644  propvalue = pStgConvertVariantToProperty(&propvar, CP_WINUNICODE, own_propvalue, &len,
645  0, FALSE, 0);
646 
647  ok(propvalue == own_propvalue, "unexpected propvalue %p\n", propvalue);
648  ok(len == 4, "unexpected length %d\n", len);
649  ok(!memcmp(propvalue, serialized_null, 4), "got wrong data\n");
650 
651  test_string_bstr = SysAllocString(test_string);
652 
653  propvar.vt = VT_BSTR;
654  U(propvar).bstrVal = test_string_bstr;
655  len = 20;
656  propvalue = pStgConvertVariantToProperty(&propvar, CP_WINUNICODE, own_propvalue, &len,
657  0, FALSE, 0);
658 
659  ok(propvalue == own_propvalue, "unexpected propvalue %p\n", propvalue);
660  ok(len == 20, "unexpected length %d\n", len);
661  ok(!memcmp(propvalue, serialized_bstr_wc, 20), "got wrong data\n");
662 
663  len = 20;
664  propvalue = pStgConvertVariantToProperty(&propvar, CP_UTF8, own_propvalue, &len,
665  0, FALSE, 0);
666 
667  ok(propvalue == own_propvalue, "unexpected propvalue %p\n", propvalue);
668  ok(len == 16, "unexpected length %d\n", len);
669  ok(!memcmp(propvalue, serialized_bstr_mb, 16), "got wrong data\n");
670 
671  SysFreeString(test_string_bstr);
672 
673  HeapFree(GetProcessHeap(), 0, own_propvalue);
674 }
675 
676 START_TEST(propvariant)
677 {
678  test_validtypes();
679  test_copy();
682 }
GLenum func
Definition: glext.h:6028
static ULONG WINAPI unk_AddRef(IUnknown *iface)
Definition: propvariant.c:327
#define REFIID
Definition: guiddef.h:118
#define TRUE
Definition: types.h:120
static void test_varianttoproperty(void)
Definition: propvariant.c:582
Definition: compat.h:1947
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
VOID WINAPI CoTaskMemFree(LPVOID ptr)
Definition: ifs.c:420
static void * vtable[]
Definition: typelib.c:1231
SERIALIZEDPROPERTYVALUE
Definition: propidl.idl:439
HRESULT hr
Definition: shlfolder.c:183
Definition: cproxy.c:247
IUnknown IUnknown_iface
Definition: api.c:545
static GLenum _GLUfuncptr fn
Definition: wgl_font.c:159
REFIID riid
Definition: precomp.h:44
HRESULT WINAPI PropVariantClear(PROPVARIANT *pvar)
Definition: ole2.c:2968
int WINAPI lstrcmpW(LPCWSTR lpString1, LPCWSTR lpString2)
Definition: lstring.c:170
#define U(x)
Definition: wordpad.c:44
static void expect(HRESULT hr, VARTYPE vt, BOOL copy, int line)
Definition: propvariant.c:138
REFIID LPVOID * ppv
Definition: atlbase.h:39
LONG ref
Definition: api.c:546
#define PROP_TODO
Definition: propvariant.c:40
OLECHAR * BSTR
Definition: compat.h:1942
void uninit(_In_ device_extension *Vcb)
Definition: btrfs.c:1918
static const CLSID IPropertyStorage UINT *static const PROPSPEC PROPVARIANT *static UINT const PROPSPEC PROPVARIANT PROPID
Definition: shellole.c:77
static void test_propertytovariant(void)
Definition: propvariant.c:523
#define MEM_COMMIT
Definition: nt_native.h:1313
static REFPROPVARIANT propvarSrc
Definition: suminfo.c:85
int winetest_debug
static const char serialized_bstr_mb[]
Definition: propvariant.c:515
struct _PMemoryAllocator_vtable * vt
Definition: propvariant.c:431
static const char serialized_empty[]
Definition: propvariant.c:490
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
LPVOID NTAPI VirtualAlloc(IN LPVOID lpAddress, IN SIZE_T dwSize, IN DWORD flAllocationType, IN DWORD flProtect)
Definition: virtmem.c:74
#define CP_UTF8
Definition: nls.h:20
#define PROP_V0
Definition: propvariant.c:35
unsigned int BOOL
Definition: ntddk_ex.h:94
long LONG
Definition: pedump.c:60
static const char serialized_null[]
Definition: propvariant.c:495
unsigned int idx
Definition: utils.c:41
unsigned char BOOLEAN
static void setup_vtable(struct _PMemoryAllocator_vtable *vtable)
Definition: propvariant.c:482
START_TEST(propvariant)
Definition: propvariant.c:676
static ULONG WINAPI unk_Release(IUnknown *iface)
Definition: propvariant.c:335
smooth NULL
Definition: ftsmooth.c:416
BSTR WINAPI SysAllocString(LPCOLESTR str)
Definition: oleaut.c:238
Definition: parser.c:48
#define PROP_V1
Definition: propvariant.c:37
static void test_copy(void)
Definition: propvariant.c:350
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
HRESULT WINAPI PropVariantCopy(PROPVARIANT *pvarDest, const PROPVARIANT *pvarSrc)
Definition: ole2.c:3086
#define todo_wine_if(is_todo)
Definition: test.h:164
static void * wrapperCodeMem
Definition: txtsrv.c:510
BYTE with_vector
Definition: propvariant.c:46
#define GetProcessHeap()
Definition: compat.h:403
#define trace
Definition: atltest.h:70
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
__wchar_t WCHAR
Definition: xmlstorage.h:180
LONG HRESULT
Definition: typedefs.h:77
#define WINAPI
Definition: msvc.h:6
unsigned long DWORD
Definition: ntddk_ex.h:95
#define PROP_INV
Definition: propvariant.c:33
#define __stdcall
Definition: typedefs.h:25
static struct unk_impl * impl_from_IUnknown(IUnknown *iface)
Definition: propvariant.c:312
static REFPROPVARIANT PROPVAR_CHANGE_FLAGS VARTYPE vt
Definition: suminfo.c:85
#define STG_E_INVALIDPARAMETER
Definition: winerror.h:2580
GLbitfield flags
Definition: glext.h:7161
Definition: api.c:544
#define DISP_E_BADVARTYPE
Definition: winerror.h:2517
int ret
#define todo_wine
Definition: test.h:163
#define InterlockedDecrement
Definition: armddk.h:52
GLenum GLsizei len
Definition: glext.h:6722
HMODULE WINAPI DECLSPEC_HOTPATCH GetModuleHandleA(LPCSTR lpModuleName)
Definition: loader.c:821
unsigned char BYTE
Definition: mem.h:68
static const char serialized_bstr_wc[]
Definition: propvariant.c:506
static HRESULT WINAPI unk_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
Definition: propvariant.c:317
#define broken(x)
Definition: _sntprintf.h:21
static const IUnknownVtbl unk_vtbl
Definition: propvariant.c:343
static const char serialized_i4[]
Definition: propvariant.c:500
#define PROP_V1A
Definition: propvariant.c:39
SAFEARRAY *WINAPI SafeArrayCreate(VARTYPE vt, UINT cDims, SAFEARRAYBOUND *rgsabound)
Definition: safearray.c:600
static void test_validtypes(void)
Definition: propvariant.c:182
#define S_OK
Definition: intsafe.h:59
#define InterlockedIncrement
Definition: armddk.h:53
unsigned short USHORT
Definition: pedump.c:61
#define ARRAY_SIZE(a)
Definition: main.h:24
#define ok(value,...)
Definition: atltest.h:57
unsigned short VARTYPE
Definition: compat.h:1903
INT copy(TCHAR source[MAX_PATH], TCHAR dest[MAX_PATH], INT append, DWORD lpdwFlags, BOOL bTouch)
Definition: copy.c:51
#define CP_WINUNICODE
Definition: ddeml.h:33
void WINAPI DECLSPEC_HOTPATCH SysFreeString(BSTR str)
Definition: oleaut.c:271
void test_string()
Definition: test_string.cpp:38
#define BOOLEAN
Definition: pedump.c:73
HRESULT WINAPI SafeArrayPutElement(SAFEARRAY *psa, LONG *rgIndices, void *pvData)
Definition: safearray.c:864
static void WINAPI PMemoryAllocator_Free(PMemoryAllocator *_this, void *pv)
Definition: propvariant.c:439
unsigned int ULONG
Definition: retypes.h:1
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
#define GetProcAddress(x, y)
Definition: compat.h:418
#define PAGE_EXECUTE_READWRITE
Definition: nt_native.h:1308
static const char * wine_vtypes[VT_CLSID+1]
Definition: propvariant.c:124
struct _PMemoryAllocator PMemoryAllocator
#define memset(x, y, z)
Definition: compat.h:39
static const struct valid_mapping valid_types[]
#define win_skip
Definition: test.h:150
LPVOID WINAPI CoTaskMemAlloc(SIZE_T size)
Definition: ifs.c:404
static void *WINAPI PMemoryAllocator_Allocate(PMemoryAllocator *_this, ULONG cbSize)
Definition: propvariant.c:434
#define HeapFree(x, y, z)
Definition: compat.h:402
static struct sockaddr_in sa
Definition: adnsresfilter.c:69