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