ReactOS 0.4.15-dev-7906-g1b85a5f
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
42static 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 */
123
124static 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
138static 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
182static 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
306struct unk_impl
307{
309 LONG ref;
310};
311
312static 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
343static const IUnknownVtbl unk_vtbl =
344{
348};
349
350static 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
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
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
430typedef struct _PMemoryAllocator {
433
435{
436 return CoTaskMemAlloc(cbSize);
437}
438
439static void WINAPI PMemoryAllocator_Free(PMemoryAllocator *_this, void *pv)
440{
441 CoTaskMemFree(pv);
442}
443
444#ifdef __i386__
445
446#include "pshpack1.h"
447typedef 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
459static 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
469{
472
474 fill_thunk(&wrapperCodeMem[1], PMemoryAllocator_Free);
475
476 vtable->Allocate = &wrapperCodeMem[0];
477 vtable->Free = &wrapperCodeMem[1];
478}
479
480#else
481
483{
486}
487
488#endif
489
490static const char serialized_empty[] = {
491 0,0, /* VT_EMPTY */
492 0,0, /* padding */
493};
494
495static const char serialized_null[] = {
496 1,0, /* VT_NULL */
497 0,0, /* padding */
498};
499
500static const char serialized_i4[] = {
501 3,0, /* VT_I4 */
502 0,0, /* padding */
503 0xef,0xcd,0xab,0xfe
504};
505
506static 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
515static 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
523static 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
582static void test_varianttoproperty(void)
583{
584 HANDLE hole32;
585 PROPVARIANT propvar;
586 SERIALIZEDPROPERTYVALUE *propvalue, *own_propvalue;
587 SERIALIZEDPROPERTYVALUE* (__stdcall *pStgConvertVariantToProperty)(
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
676START_TEST(propvariant)
677{
679 test_copy();
682}
unsigned char BOOLEAN
#define expect(EXPECTED, GOT)
Definition: SystemMenu.c:483
#define broken(x)
Definition: _sntprintf.h:21
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
static struct sockaddr_in sa
Definition: adnsresfilter.c:69
#define InterlockedIncrement
Definition: armddk.h:53
#define InterlockedDecrement
Definition: armddk.h:52
#define trace
Definition: atltest.h:70
#define ok(value,...)
Definition: atltest.h:57
#define START_TEST(x)
Definition: atltest.h:75
#define ARRAY_SIZE(A)
Definition: main.h:33
#define U(x)
Definition: wordpad.c:45
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
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
unsigned int idx
Definition: utils.c:41
#define GetProcessHeap()
Definition: compat.h:736
#define GetProcAddress(x, y)
Definition: compat.h:753
#define HeapAlloc
Definition: compat.h:733
OLECHAR * BSTR
Definition: compat.h:2293
unsigned short VARTYPE
Definition: compat.h:2254
#define HeapFree(x, y, z)
Definition: compat.h:735
@ VT_BLOB
Definition: compat.h:2330
@ VT_BLOB_OBJECT
Definition: compat.h:2335
@ VT_BSTR
Definition: compat.h:2303
@ VT_LPSTR
Definition: compat.h:2324
@ VT_NULL
Definition: compat.h:2296
@ VT_UNKNOWN
Definition: compat.h:2308
@ VT_TYPEMASK
Definition: compat.h:2346
@ VT_BYREF
Definition: compat.h:2342
@ VT_CLSID
Definition: compat.h:2337
@ VT_ARRAY
Definition: compat.h:2341
@ VT_LPWSTR
Definition: compat.h:2325
@ VT_I4
Definition: compat.h:2298
@ VT_EMPTY
Definition: compat.h:2295
@ VT_RECORD
Definition: compat.h:2326
@ VT_VECTOR
Definition: compat.h:2340
HMODULE WINAPI DECLSPEC_HOTPATCH GetModuleHandleA(LPCSTR lpModuleName)
Definition: loader.c:812
static REFPROPVARIANT propvarSrc
Definition: suminfo.c:85
static REFPROPVARIANT PROPVAR_CHANGE_FLAGS VARTYPE vt
Definition: suminfo.c:86
HRESULT WINAPI PropVariantClear(PROPVARIANT *pvar)
Definition: ole2.c:2968
HRESULT WINAPI PropVariantCopy(PROPVARIANT *pvarDest, const PROPVARIANT *pvarSrc)
Definition: ole2.c:3086
SAFEARRAY *WINAPI SafeArrayCreate(VARTYPE vt, UINT cDims, SAFEARRAYBOUND *rgsabound)
Definition: safearray.c:600
HRESULT WINAPI SafeArrayPutElement(SAFEARRAY *psa, LONG *rgIndices, void *pvData)
Definition: safearray.c:864
void uninit(_In_ device_extension *Vcb)
Definition: btrfs.c:2001
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
GLenum func
Definition: glext.h:6028
GLbitfield flags
Definition: glext.h:7161
GLenum GLsizei len
Definition: glext.h:6722
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
VOID WINAPI CoTaskMemFree(LPVOID ptr)
Definition: ifs.c:442
LPVOID WINAPI CoTaskMemAlloc(SIZE_T size)
Definition: ifs.c:426
REFIID riid
Definition: atlbase.h:39
REFIID LPVOID * ppv
Definition: atlbase.h:39
#define S_OK
Definition: intsafe.h:52
int WINAPI lstrcmpW(LPCWSTR lpString1, LPCWSTR lpString2)
Definition: lstring.c:170
#define todo_wine_if(is_todo)
Definition: custom.c:76
#define todo_wine
Definition: custom.c:79
static void * vtable[]
Definition: typelib.c:1231
static void * wrapperCodeMem
Definition: txtsrv.c:467
static const CLSID IPropertyStorage UINT *static const PROPSPEC PROPVARIANT *static UINT const PROPSPEC PROPVARIANT PROPID
Definition: shellole.c:78
#define MEM_COMMIT
Definition: nt_native.h:1313
#define PAGE_EXECUTE_READWRITE
Definition: nt_native.h:1308
BSTR WINAPI SysAllocString(LPCOLESTR str)
Definition: oleaut.c:238
void WINAPI DECLSPEC_HOTPATCH SysFreeString(BSTR str)
Definition: oleaut.c:271
#define BOOLEAN
Definition: pedump.c:73
long LONG
Definition: pedump.c:60
unsigned short USHORT
Definition: pedump.c:61
SERIALIZEDPROPERTYVALUE
Definition: propidl.idl:439
static void test_validtypes(void)
Definition: propvariant.c:182
static void setup_vtable(struct _PMemoryAllocator_vtable *vtable)
Definition: propvariant.c:482
static const char serialized_bstr_mb[]
Definition: propvariant.c:515
static const char serialized_empty[]
Definition: propvariant.c:490
#define PROP_V0
Definition: propvariant.c:35
static ULONG WINAPI unk_Release(IUnknown *iface)
Definition: propvariant.c:335
static const char serialized_null[]
Definition: propvariant.c:495
static struct unk_impl * impl_from_IUnknown(IUnknown *iface)
Definition: propvariant.c:312
static HRESULT WINAPI unk_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
Definition: propvariant.c:317
static void WINAPI PMemoryAllocator_Free(PMemoryAllocator *_this, void *pv)
Definition: propvariant.c:439
static void test_copy(void)
Definition: propvariant.c:350
static void test_varianttoproperty(void)
Definition: propvariant.c:582
static void *WINAPI PMemoryAllocator_Allocate(PMemoryAllocator *_this, ULONG cbSize)
Definition: propvariant.c:434
static ULONG WINAPI unk_AddRef(IUnknown *iface)
Definition: propvariant.c:327
#define PROP_INV
Definition: propvariant.c:33
static void test_propertytovariant(void)
Definition: propvariant.c:523
static const char serialized_bstr_wc[]
Definition: propvariant.c:506
#define PROP_V1A
Definition: propvariant.c:39
static const char serialized_i4[]
Definition: propvariant.c:500
static const IUnknownVtbl unk_vtbl
Definition: propvariant.c:343
struct _PMemoryAllocator PMemoryAllocator
static const struct valid_mapping valid_types[]
static const char * wine_vtypes[VT_CLSID+1]
Definition: propvariant.c:124
#define PROP_TODO
Definition: propvariant.c:40
#define PROP_V1
Definition: propvariant.c:37
#define REFIID
Definition: guiddef.h:118
#define CP_UTF8
Definition: nls.h:20
int winetest_debug
#define win_skip
Definition: test.h:160
#define memset(x, y, z)
Definition: compat.h:39
HRESULT hr
Definition: shlfolder.c:183
struct _PMemoryAllocator_vtable * vt
Definition: propvariant.c:431
Definition: parser.c:49
Definition: cproxy.c:248
Definition: api.c:544
IUnknown IUnknown_iface
Definition: api.c:545
LONG ref
Definition: api.c:546
BYTE with_vector
Definition: propvariant.c:46
void test_string()
Definition: test_string.cpp:38
#define __stdcall
Definition: typedefs.h:25
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
int ret
static GLenum _GLUfuncptr fn
Definition: wgl_font.c:159
LPVOID NTAPI VirtualAlloc(IN LPVOID lpAddress, IN SIZE_T dwSize, IN DWORD flAllocationType, IN DWORD flProtect)
Definition: virtmem.c:65
#define WINAPI
Definition: msvc.h:6
#define DISP_E_BADVARTYPE
Definition: winerror.h:2517
#define STG_E_INVALIDPARAMETER
Definition: winerror.h:2580
__wchar_t WCHAR
Definition: xmlstorage.h:180
unsigned char BYTE
Definition: xxhash.c:193