1 /*
2  * Unit tests for Windows property system
3  *
4  * Copyright 2006 Paul Vriens
5  * Copyright 2010 Andrew Nguyen
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21 
22 #define COBJMACROS
23 
24 #include <stdarg.h>
25 #include <stdio.h>
26 
27 #define NONAMELESSUNION
28 
29 #include "windef.h"
30 #include "winbase.h"
31 #include "objbase.h"
32 #include "initguid.h"
33 #include "propsys.h"
34 #include "propvarutil.h"
35 #include "wine/test.h"
36 
37 DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0);
38 DEFINE_GUID(dummy_guid, 0xdeadbeef, 0xdead, 0xbeef, 0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0xba, 0xbe);
39 DEFINE_GUID(expect_guid, 0x12345678, 0x1234, 0x1234, 0x12, 0x34, 0x12, 0x34, 0x56, 0x78, 0x90, 0x12);
40 
41 #define GUID_MEMBERS(g) {(g).Data1, (g).Data2, (g).Data3, {(g).Data4[0], (g).Data4[1], (g).Data4[2], (g).Data4[3], (g).Data4[4], (g).Data4[5], (g).Data4[6], (g).Data4[7]}}
42 
43 static const char topic[] = "wine topic";
44 static const WCHAR topicW[] = {'w','i','n','e',' ','t','o','p','i','c',0};
45 static const WCHAR emptyW[] = {0};
46 
47 static int strcmp_wa(LPCWSTR strw, const char *stra)
48 {
49     CHAR buf[512];
50     WideCharToMultiByte(CP_ACP, 0, strw, -1, buf, sizeof(buf), NULL, NULL);
51     return lstrcmpA(stra, buf);
52 }
53 
54 static void test_PSStringFromPropertyKey(void)
55 {
56     static const WCHAR fillerW[] = {'X','X','X','X','X','X','X','X','X','X','X','X','X','X','X','X','X','X','X','X',
57                                     'X','X','X','X','X','X','X','X','X','X','X','X','X','X','X','X','X','X','X','X',
58                                     'X','X','X','X','X','X','X','X','X','X'};
59     static const WCHAR zero_fillerW[] = {'\0','X','X','X','X','X','X','X','X','X','X','X','X','X','X','X','X','X',
60                                          'X','X','X','X','X','X','X','X','X','X','X','X','X','X','X','X','X','X',
61                                          'X','X','X','X','X','X','X','X','X','X','X','X','X','X'};
62     static const WCHAR zero_truncatedW[] = {'\0','0','0','0','0','0','0','0','0','-','0','0','0','0','-','0','0',
63                                             '0','0','-','0','0','0','0','-','0','0','0','0','0','0','0','0','0',
64                                             '0','0','0','}',' ','\0','9','X','X','X','X','X','X','X','X','X'};
65     static const WCHAR zero_truncated2W[] = {'\0','0','0','0','0','0','0','0','0','-','0','0','0','0','-','0','0',
66                                              '0','0','-','0','0','0','0','-','0','0','0','0','0','0','0','0','0',
67                                              '0','0','0','}',' ','\0','9','2','7','6','9','4','9','2','X','X'};
68     static const WCHAR zero_truncated3W[] = {'\0','0','0','0','0','0','0','0','0','-','0','0','0','0','-','0','0',
69                                             '0','0','-','0','0','0','0','-','0','0','0','0','0','0','0','0','0',
70                                             '0','0','0','}',' ','\0','9','2','7','6','9','4','9','2','4','X'};
71     static const WCHAR zero_truncated4W[] = {'\0','0','0','0','0','0','0','0','0','-','0','0','0','0','-','0','0',
72                                              '0','0','-','0','0','0','0','-','0','0','0','0','0','0','0','0','0',
73                                              '0','0','0','}',' ','\0','7','X','X','X','X','X','X','X','X','X'};
74     static const WCHAR truncatedW[] = {'{','0','0','0','0','0','0','0','0','-','0','0','0','0','-','0','0','0',
75                                         '0','-','0','0','0','0','-','0','0','0','0','0','0','0','0','0','0','0',
76                                         '0','}',' ','\0','9','X','X','X','X','X','X','X','X','X'};
77     static const WCHAR truncated2W[] = {'{','0','0','0','0','0','0','0','0','-','0','0','0','0','-','0','0','0',
78                                         '0','-','0','0','0','0','-','0','0','0','0','0','0','0','0','0','0','0',
79                                         '0','}',' ','\0','9','2','7','6','9','4','9','2','X','X'};
80     static const WCHAR truncated3W[] = {'{','0','0','0','0','0','0','0','0','-','0','0','0','0','-','0','0','0',
81                                        '0','-','0','0','0','0','-','0','0','0','0','0','0','0','0','0','0','0',
82                                        '0','}',' ','\0','9','2','7','6','9','4','9','2','4','X'};
83     static const WCHAR truncated4W[] = {'{','0','0','0','0','0','0','0','0','-','0','0','0','0','-','0','0','0',
84                                         '0','-','0','0','0','0','-','0','0','0','0','0','0','0','0','0','0','0',
85                                         '0','}',' ','\0','7','X','X','X','X','X','X','X','X','X'};
86     static const WCHAR expectedW[] = {'{','0','0','0','0','0','0','0','0','-','0','0','0','0','-','0','0','0',
87                                       '0','-','0','0','0','0','-','0','0','0','0','0','0','0','0','0','0','0',
88                                       '0','}',' ','4','2','9','4','9','6','7','2','9','5',0};
89     static const WCHAR expected2W[] = {'{','0','0','0','0','0','0','0','0','-','0','0','0','0','-','0','0','0',
90                                        '0','-','0','0','0','0','-','0','0','0','0','0','0','0','0','0','0','0',
91                                        '0','}',' ','1','3','5','7','9','\0','X','X','X','X','X'};
92     static const WCHAR expected3W[] = {'{','0','0','0','0','0','0','0','0','-','0','0','0','0','-','0','0','0',
93                                        '0','-','0','0','0','0','-','0','0','0','0','0','0','0','0','0','0','0',
94                                        '0','}',' ','0','\0','X','X','X','X','X','X','X','X','X'};
95     PROPERTYKEY prop = {GUID_MEMBERS(GUID_NULL), ~0U};
96     PROPERTYKEY prop2 = {GUID_MEMBERS(GUID_NULL), 13579};
97     PROPERTYKEY prop3 = {GUID_MEMBERS(GUID_NULL), 0};
98     WCHAR out[PKEYSTR_MAX];
99     HRESULT ret;
100 
101     const struct
102     {
103         REFPROPERTYKEY pkey;
104         LPWSTR psz;
105         UINT cch;
106         HRESULT hr_expect;
107         const WCHAR *buf_expect;
108         BOOL hr_broken;
109         HRESULT hr2;
110         BOOL buf_broken;
111         const WCHAR *buf2;
112     } testcases[] =
113     {
114         {NULL, NULL, 0, E_POINTER},
115         {&prop, NULL, 0, E_POINTER},
116         {&prop, NULL, PKEYSTR_MAX, E_POINTER},
117         {NULL, out, 0, E_NOT_SUFFICIENT_BUFFER, fillerW},
118         {NULL, out, PKEYSTR_MAX, E_NOT_SUFFICIENT_BUFFER, zero_fillerW, FALSE, 0, TRUE, fillerW},
119         {&prop, out, 0, E_NOT_SUFFICIENT_BUFFER, fillerW},
120         {&prop, out, GUIDSTRING_MAX, E_NOT_SUFFICIENT_BUFFER, fillerW},
121         {&prop, out, GUIDSTRING_MAX + 1, E_NOT_SUFFICIENT_BUFFER, fillerW},
122         {&prop, out, GUIDSTRING_MAX + 2, E_NOT_SUFFICIENT_BUFFER, zero_truncatedW, TRUE, S_OK, TRUE, truncatedW},
123         {&prop, out, PKEYSTR_MAX - 2, E_NOT_SUFFICIENT_BUFFER, zero_truncated2W, TRUE, S_OK, TRUE, truncated2W},
124         {&prop, out, PKEYSTR_MAX - 1, E_NOT_SUFFICIENT_BUFFER, zero_truncated3W, TRUE, S_OK, TRUE, truncated3W},
125         {&prop, out, PKEYSTR_MAX, S_OK, expectedW},
126         {&prop2, out, GUIDSTRING_MAX + 2, E_NOT_SUFFICIENT_BUFFER, zero_truncated4W, TRUE, S_OK, TRUE, truncated4W},
127         {&prop2, out, GUIDSTRING_MAX + 6, S_OK, expected2W},
128         {&prop2, out, PKEYSTR_MAX, S_OK, expected2W},
129         {&prop3, out, GUIDSTRING_MAX + 1, E_NOT_SUFFICIENT_BUFFER, fillerW},
130         {&prop3, out, GUIDSTRING_MAX + 2, S_OK, expected3W},
131         {&prop3, out, PKEYSTR_MAX, S_OK, expected3W},
132     };
133 
134     int i;
135 
136     for (i = 0; i < ARRAY_SIZE(testcases); i++)
137     {
138         if (testcases[i].psz)
139             memcpy(testcases[i].psz, fillerW, PKEYSTR_MAX * sizeof(WCHAR));
140 
141         ret = PSStringFromPropertyKey(testcases[i].pkey,
142                                       testcases[i].psz,
143                                       testcases[i].cch);
144         ok(ret == testcases[i].hr_expect ||
145            broken(testcases[i].hr_broken && ret == testcases[i].hr2), /* Vista/Win2k8 */
146            "[%d] Expected PSStringFromPropertyKey to return 0x%08x, got 0x%08x\n",
147            i, testcases[i].hr_expect, ret);
148 
149         if (testcases[i].psz)
150             ok(!memcmp(testcases[i].psz, testcases[i].buf_expect, PKEYSTR_MAX * sizeof(WCHAR)) ||
151                 broken(testcases[i].buf_broken &&
152                        !memcmp(testcases[i].psz, testcases[i].buf2, PKEYSTR_MAX * sizeof(WCHAR))), /* Vista/Win2k8 */
153                "[%d] Unexpected output contents\n", i);
154     }
155 }
156 
157 static void test_PSPropertyKeyFromString(void)
158 {
159     static const WCHAR fmtid_clsidW[] = {'S','t','d','F','o','n','t',' ','1',0};
160     static const WCHAR fmtid_truncatedW[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
161                                              '1','2','3','4','-',0};
162     static const WCHAR fmtid_nobracketsW[] = {'1','2','3','4','5','6','7','8','-','1','2','3','4','-',
163                                               '1','2','3','4','-','1','2','3','4','-',
164                                               '1','2','3','4','5','6','7','8','9','0','1','2',0};
165     static const WCHAR fmtid_badbracketW[] = {'X','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
166                                               '1','2','3','4','-','1','2','3','4','-',
167                                               '1','2','3','4','5','6','7','8','9','0','1','2','}',0};
168     static const WCHAR fmtid_badcharW[] = {'{','X','2','3','4','5','6','7','8','-','1','2','3','4','-',
169                                            '1','2','3','4','-','1','2','3','4','-',
170                                            '1','2','3','4','5','6','7','8','9','0','1','2','}',0};
171     static const WCHAR fmtid_badchar2W[] = {'{','1','2','3','4','5','6','7','X','-','1','2','3','4','-',
172                                             '1','2','3','4','-','1','2','3','4','-',
173                                             '1','2','3','4','5','6','7','8','9','0','1','2','}',0};
174     static const WCHAR fmtid_baddashW[] = {'{','1','2','3','4','5','6','7','8','X','1','2','3','4','-',
175                                            '1','2','3','4','-','1','2','3','4','-',
176                                            '1','2','3','4','5','6','7','8','9','0','1','2','}',0};
177     static const WCHAR fmtid_badchar3W[] = {'{','1','2','3','4','5','6','7','8','-','X','2','3','4','-',
178                                             '1','2','3','4','-','1','2','3','4','-',
179                                             '1','2','3','4','5','6','7','8','9','0','1','2','}',0};
180     static const WCHAR fmtid_badchar4W[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','X','-',
181                                             '1','2','3','4','-','1','2','3','4','-',
182                                             '1','2','3','4','5','6','7','8','9','0','1','2','}',0};
183     static const WCHAR fmtid_baddash2W[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','X',
184                                             '1','2','3','4','-','1','2','3','4','-',
185                                             '1','2','3','4','5','6','7','8','9','0','1','2','}',0};
186     static const WCHAR fmtid_badchar5W[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
187                                             'X','2','3','4','-','1','2','3','4','-',
188                                             '1','2','3','4','5','6','7','8','9','0','1','2','}',0};
189     static const WCHAR fmtid_badchar6W[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
190                                             '1','2','3','X','-','1','2','3','4','-',
191                                             '1','2','3','4','5','6','7','8','9','0','1','2','}',0};
192     static const WCHAR fmtid_baddash3W[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
193                                             '1','2','3','4','X','1','2','3','4','-',
194                                             '1','2','3','4','5','6','7','8','9','0','1','2','}',0};
195     static const WCHAR fmtid_badchar7W[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
196                                             '1','2','3','4','-','X','2','3','4','-',
197                                             '1','2','3','4','5','6','7','8','9','0','1','2','}',0};
198     static const WCHAR fmtid_badchar8W[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
199                                             '1','2','3','4','-','1','2','3','X','-',
200                                             '1','2','3','4','5','6','7','8','9','0','1','2','}',0};
201     static const WCHAR fmtid_baddash4W[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
202                                             '1','2','3','4','-','1','2','3','4','X',
203                                             '1','2','3','4','5','6','7','8','9','0','1','2','}',0};
204     static const WCHAR fmtid_badchar9W[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
205                                             '1','2','3','4','-','1','2','3','4','-',
206                                             'X','2','3','4','5','6','7','8','9','0','1','2','}',0};
207     static const WCHAR fmtid_badchar9_adjW[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
208                                                 '1','2','3','4','-','1','2','3','4','-',
209                                                 '1','X','3','4','5','6','7','8','9','0','1','2','}',0};
210     static const WCHAR fmtid_badchar10W[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
211                                              '1','2','3','4','-','1','2','3','4','-',
212                                              '1','2','X','4','5','6','7','8','9','0','1','2','}',0};
213     static const WCHAR fmtid_badchar11W[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
214                                              '1','2','3','4','-','1','2','3','4','-',
215                                              '1','2','3','4','X','6','7','8','9','0','1','2','}',0};
216     static const WCHAR fmtid_badchar12W[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
217                                              '1','2','3','4','-','1','2','3','4','-',
218                                              '1','2','3','4','5','6','X','8','9','0','1','2','}',0};
219     static const WCHAR fmtid_badchar13W[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
220                                              '1','2','3','4','-','1','2','3','4','-',
221                                              '1','2','3','4','5','6','7','8','X','0','1','2','}',0};
222     static const WCHAR fmtid_badchar14W[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
223                                              '1','2','3','4','-','1','2','3','4','-',
224                                              '1','2','3','4','5','6','7','8','9','0','X','2','}',0};
225     static const WCHAR fmtid_badbracket2W[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
226                                                '1','2','3','4','-','1','2','3','4','-',
227                                                '1','2','3','4','5','6','7','8','9','0','1','2','X',0};
228     static const WCHAR fmtid_spaceW[] = {' ','{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
229                                          '1','2','3','4','-','1','2','3','4','-',
230                                          '1','2','3','4','5','6','7','8','9','0','1','2','}',0};
231     static const WCHAR fmtid_spaceendW[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
232                                             '1','2','3','4','-','1','2','3','4','-',
233                                             '1','2','3','4','5','6','7','8','9','0','1','2','}',' ',0};
234     static const WCHAR fmtid_spacesendW[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
235                                              '1','2','3','4','-','1','2','3','4','-',
236                                              '1','2','3','4','5','6','7','8','9','0','1','2','}',' ',' ',' ',0};
237     static const WCHAR fmtid_nopidW[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
238                                          '1','2','3','4','-','1','2','3','4','-',
239                                          '1','2','3','4','5','6','7','8','9','0','1','2','}',0};
240     static const WCHAR fmtid_badpidW[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
241                                           '1','2','3','4','-','1','2','3','4','-',
242                                           '1','2','3','4','5','6','7','8','9','0','1','2','}',' ','D','E','A','D',0};
243     static const WCHAR fmtid_adjpidW[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
244                                           '1','2','3','4','-','1','2','3','4','-',
245                                           '1','2','3','4','5','6','7','8','9','0','1','2','}','1','3','5','7','9',0};
246     static const WCHAR fmtid_spacespidW[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
247                                              '1','2','3','4','-','1','2','3','4','-',
248                                              '1','2','3','4','5','6','7','8','9','0','1','2','}',' ',' ',' ','1','3','5','7','9',0};
249     static const WCHAR fmtid_negpidW[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
250                                           '1','2','3','4','-','1','2','3','4','-',
251                                           '1','2','3','4','5','6','7','8','9','0','1','2','}',' ','-','1','3','5','7','9',0};
252     static const WCHAR fmtid_negnegpidW[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
253                                              '1','2','3','4','-','1','2','3','4','-',
254                                              '1','2','3','4','5','6','7','8','9','0','1','2','}',' ','-','-','1','3','5','7','9',0};
255     static const WCHAR fmtid_negnegnegpidW[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
256                                                 '1','2','3','4','-','1','2','3','4','-',
257                                                 '1','2','3','4','5','6','7','8','9','0','1','2','}',' ','-','-','-','1','3','5','7','9',0};
258     static const WCHAR fmtid_negspacepidW[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
259                                                '1','2','3','4','-','1','2','3','4','-',
260                                                '1','2','3','4','5','6','7','8','9','0','1','2','}',' ','-',' ','1','3','5','7','9',0};
261     static const WCHAR fmtid_negspacenegpidW[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
262                                                '1','2','3','4','-','1','2','3','4','-',
263                                                '1','2','3','4','5','6','7','8','9','0','1','2','}',' ','-',' ','-','1','3','5','7','9',0};
264     static const WCHAR fmtid_negspacespidW[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
265                                                '1','2','3','4','-','1','2','3','4','-',
266                                                '1','2','3','4','5','6','7','8','9','0','1','2','}',' ','-',' ','-',' ','-','1','3','5','7','9',0};
267     static const WCHAR fmtid_pospidW[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
268                                           '1','2','3','4','-','1','2','3','4','-',
269                                           '1','2','3','4','5','6','7','8','9','0','1','2','}',' ','+','1','3','5','7','9',0};
270     static const WCHAR fmtid_posnegpidW[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
271                                              '1','2','3','4','-','1','2','3','4','-',
272                                              '1','2','3','4','5','6','7','8','9','0','1','2','}',' ','+','-','+','-','1','3','5','7','9',0};
273     static const WCHAR fmtid_symbolpidW[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
274                                              '1','2','3','4','-','1','2','3','4','-',
275                                              '1','2','3','4','5','6','7','8','9','0','1','2','}',' ','+','/','$','-','1','3','5','7','9',0};
276     static const WCHAR fmtid_letterpidW[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
277                                              '1','2','3','4','-','1','2','3','4','-',
278                                              '1','2','3','4','5','6','7','8','9','0','1','2','}',' ','A','B','C','D','1','3','5','7','9',0};
279     static const WCHAR fmtid_spacepadpidW[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
280                                                '1','2','3','4','-','1','2','3','4','-',
281                                                '1','2','3','4','5','6','7','8','9','0','1','2','}',' ','1','3','5','7','9',' ',' ',' ',0};
282     static const WCHAR fmtid_spacemixpidW[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
283                                                '1','2','3','4','-','1','2','3','4','-',
284                                                '1','2','3','4','5','6','7','8','9','0','1','2','}',' ','1',' ','3',' ','5','7','9',' ',' ',' ',0};
285     static const WCHAR fmtid_tabpidW[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
286                                           '1','2','3','4','-','1','2','3','4','-',
287                                           '1','2','3','4','5','6','7','8','9','0','1','2','}','\t','1','3','5','7','9',0};
288     static const WCHAR fmtid_hexpidW[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
289                                           '1','2','3','4','-','1','2','3','4','-',
290                                           '1','2','3','4','5','6','7','8','9','0','1','2','}',' ','0','x','D','E','A','D',0};
291     static const WCHAR fmtid_mixedpidW[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
292                                             '1','2','3','4','-','1','2','3','4','-',
293                                             '1','2','3','4','5','6','7','8','9','0','1','2','}',' ','A','9','B','5','C','3','D','1',0};
294     static const WCHAR fmtid_overflowpidW[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
295                                                '1','2','3','4','-','1','2','3','4','-',
296                                                '1','2','3','4','5','6','7','8','9','0','1','2','}',' ','1','2','3','4','5','6','7','8','9','0','1',0};
297     static const WCHAR fmtid_commapidW[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
298                                              '1','2','3','4','-','1','2','3','4','-',
299                                              '1','2','3','4','5','6','7','8','9','0','1','2','}',',','1','3','5','7','9',0};
300     static const WCHAR fmtid_commaspidW[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
301                                              '1','2','3','4','-','1','2','3','4','-',
302                                              '1','2','3','4','5','6','7','8','9','0','1','2','}',',',',',',','1','3','5','7','9',0};
303     static const WCHAR fmtid_commaspacepidW[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
304                                                  '1','2','3','4','-','1','2','3','4','-',
305                                                  '1','2','3','4','5','6','7','8','9','0','1','2','}',',',' ','1','3','5','7','9',0};
306     static const WCHAR fmtid_spacecommapidW[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
307                                                  '1','2','3','4','-','1','2','3','4','-',
308                                                  '1','2','3','4','5','6','7','8','9','0','1','2','}',' ',',','1','3','5','7','9',0};
309     static const WCHAR fmtid_spccommaspcpidW[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
310                                                   '1','2','3','4','-','1','2','3','4','-',
311                                                   '1','2','3','4','5','6','7','8','9','0','1','2','}',' ',',',' ','1','3','5','7','9',0};
312     static const WCHAR fmtid_spacescommaspidW[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
313                                                    '1','2','3','4','-','1','2','3','4','-',
314                                                    '1','2','3','4','5','6','7','8','9','0','1','2','}',' ',',',' ',',','1','3','5','7','9',0};
315     static const WCHAR fmtid_commanegpidW[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
316                                                '1','2','3','4','-','1','2','3','4','-',
317                                                '1','2','3','4','5','6','7','8','9','0','1','2','}',',','-','1','3','5','7','9',0};
318     static const WCHAR fmtid_spccommanegpidW[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
319                                                '1','2','3','4','-','1','2','3','4','-',
320                                                '1','2','3','4','5','6','7','8','9','0','1','2','}',' ',',','-','1','3','5','7','9',0};
321     static const WCHAR fmtid_commaspcnegpidW[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
322                                                '1','2','3','4','-','1','2','3','4','-',
323                                                '1','2','3','4','5','6','7','8','9','0','1','2','}',',',' ','-','1','3','5','7','9',0};
324     static const WCHAR fmtid_spccommaspcnegpidW[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
325                                                '1','2','3','4','-','1','2','3','4','-',
326                                                '1','2','3','4','5','6','7','8','9','0','1','2','}',' ',',',' ','-','1','3','5','7','9',0};
327     static const WCHAR fmtid_commanegspcpidW[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
328                                                '1','2','3','4','-','1','2','3','4','-',
329                                                '1','2','3','4','5','6','7','8','9','0','1','2','}',',','-',' ','1','3','5','7','9',0};
330     static const WCHAR fmtid_negcommapidW[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
331                                                '1','2','3','4','-','1','2','3','4','-',
332                                                '1','2','3','4','5','6','7','8','9','0','1','2','}','-',',','1','3','5','7','9',0};
333     static const WCHAR fmtid_normalpidW[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
334                                              '1','2','3','4','-','1','2','3','4','-',
335                                              '1','2','3','4','5','6','7','8','9','0','1','2','}',' ','1','3','5','7','9',0};
336     PROPERTYKEY out_init = {GUID_MEMBERS(dummy_guid), 0xdeadbeef};
337     PROPERTYKEY out;
338     HRESULT ret;
339 
340     const struct
341     {
342         LPCWSTR pwzString;
343         PROPERTYKEY *pkey;
344         HRESULT hr_expect;
345         PROPERTYKEY pkey_expect;
346     } testcases[] =
347     {
348         {NULL, NULL, E_POINTER},
349         {NULL, &out, E_POINTER, {GUID_MEMBERS(out_init.fmtid), out_init.pid}},
350         {emptyW, NULL, E_POINTER},
351         {emptyW, &out, E_INVALIDARG, {GUID_MEMBERS(GUID_NULL), 0}},
352         {fmtid_clsidW, &out, E_INVALIDARG, {GUID_MEMBERS(GUID_NULL), 0}},
353         {fmtid_truncatedW, &out, E_INVALIDARG, { {0x12345678,0x1234,0x1234,{0,0,0,0,0,0,0,0}}, 0}},
354         {fmtid_nobracketsW, &out, E_INVALIDARG, {GUID_MEMBERS(GUID_NULL), 0}},
355         {fmtid_badbracketW, &out, E_INVALIDARG, {GUID_MEMBERS(GUID_NULL), 0}},
356         {fmtid_badcharW, &out, E_INVALIDARG, {GUID_MEMBERS(GUID_NULL), 0}},
357         {fmtid_badchar2W, &out, E_INVALIDARG, {GUID_MEMBERS(GUID_NULL), 0}},
358         {fmtid_baddashW, &out, E_INVALIDARG, { {0x12345678,0,0,{0,0,0,0,0,0,0,0}}, 0}},
359         {fmtid_badchar3W, &out, E_INVALIDARG, { {0x12345678,0,0,{0,0,0,0,0,0,0,0}}, 0}},
360         {fmtid_badchar4W, &out, E_INVALIDARG, { {0x12345678,0,0,{0,0,0,0,0,0,0,0}}, 0}},
361         {fmtid_baddash2W, &out, E_INVALIDARG, { {0x12345678,0,0,{0,0,0,0,0,0,0,0}}, 0}},
362         {fmtid_badchar5W, &out, E_INVALIDARG, { {0x12345678,0x1234,0,{0,0,0,0,0,0,0,0}}, 0}},
363         {fmtid_badchar6W, &out, E_INVALIDARG, { {0x12345678,0x1234,0,{0,0,0,0,0,0,0,0}}, 0}},
364         {fmtid_baddash3W, &out, E_INVALIDARG, { {0x12345678,0x1234,0,{0,0,0,0,0,0,0,0}}, 0}},
365         {fmtid_badchar7W, &out, E_INVALIDARG, { {0x12345678,0x1234,0x1234,{0,0,0,0,0,0,0,0}}, 0}},
366         {fmtid_badchar8W, &out, E_INVALIDARG, { {0x12345678,0x1234,0x1234,{0x12,0,0,0,0,0,0,0}}, 0}},
367         {fmtid_baddash4W, &out, E_INVALIDARG, { {0x12345678,0x1234,0x1234,{0x12,0,0,0,0,0,0,0}}, 0}},
368         {fmtid_badchar9W, &out, E_INVALIDARG, { {0x12345678,0x1234,0x1234,{0x12,0x34,0,0,0,0,0,0}}, 0}},
369         {fmtid_badchar9_adjW, &out, E_INVALIDARG, { {0x12345678,0x1234,0x1234,{0x12,0x34,0,0,0,0,0,0}}, 0}},
370         {fmtid_badchar10W, &out, E_INVALIDARG, { {0x12345678,0x1234,0x1234,{0x12,0x34,0x12,0,0,0,0,0}}, 0}},
371         {fmtid_badchar11W, &out, E_INVALIDARG, { {0x12345678,0x1234,0x1234,{0x12,0x34,0x12,0x34,0,0,0,0}}, 0}},
372         {fmtid_badchar12W, &out, E_INVALIDARG, { {0x12345678,0x1234,0x1234,{0x12,0x34,0x12,0x34,0x56,0,0,0}}, 0}},
373         {fmtid_badchar13W, &out, E_INVALIDARG, { {0x12345678,0x1234,0x1234,{0x12,0x34,0x12,0x34,0x56,0x78,0,0}}, 0}},
374         {fmtid_badchar14W, &out, E_INVALIDARG, { {0x12345678,0x1234,0x1234,{0x12,0x34,0x12,0x34,0x56,0x78,0x90,0}}, 0}},
375         {fmtid_badbracket2W, &out, E_INVALIDARG, { {0x12345678,0x1234,0x1234,{0x12,0x34,0x12,0x34,0x56,0x78,0x90,0x00}}, 0 }},
376         {fmtid_spaceW, &out, E_INVALIDARG, {GUID_MEMBERS(GUID_NULL), 0 }},
377         {fmtid_spaceendW, &out, E_INVALIDARG, {GUID_MEMBERS(expect_guid), 0}},
378         {fmtid_spacesendW, &out, E_INVALIDARG, {GUID_MEMBERS(expect_guid), 0}},
379         {fmtid_nopidW, &out, E_INVALIDARG, {GUID_MEMBERS(expect_guid), 0}},
380         {fmtid_badpidW, &out, S_OK, {GUID_MEMBERS(expect_guid), 0}},
381         {fmtid_adjpidW, &out, S_OK, {GUID_MEMBERS(expect_guid), 13579}},
382         {fmtid_spacespidW, &out, S_OK, {GUID_MEMBERS(expect_guid), 13579}},
383         {fmtid_negpidW, &out, S_OK, {GUID_MEMBERS(expect_guid), 13579}},
384         {fmtid_negnegpidW, &out, S_OK, {GUID_MEMBERS(expect_guid), 4294953717U}},
385         {fmtid_negnegnegpidW, &out, S_OK, {GUID_MEMBERS(expect_guid), 0}},
386         {fmtid_negspacepidW, &out, S_OK, {GUID_MEMBERS(expect_guid), 13579}},
387         {fmtid_negspacenegpidW, &out, S_OK, {GUID_MEMBERS(expect_guid), 4294953717U}},
388         {fmtid_negspacespidW, &out, S_OK, {GUID_MEMBERS(expect_guid), 0}},
389         {fmtid_pospidW, &out, S_OK, {GUID_MEMBERS(expect_guid), 0}},
390         {fmtid_posnegpidW, &out, S_OK, {GUID_MEMBERS(expect_guid), 0}},
391         {fmtid_symbolpidW, &out, S_OK, {GUID_MEMBERS(expect_guid), 0}},
392         {fmtid_letterpidW, &out, S_OK, {GUID_MEMBERS(expect_guid), 0}},
393         {fmtid_spacepadpidW, &out, S_OK, {GUID_MEMBERS(expect_guid), 13579}},
394         {fmtid_spacemixpidW, &out, S_OK, {GUID_MEMBERS(expect_guid), 1}},
395         {fmtid_tabpidW, &out, S_OK, {GUID_MEMBERS(expect_guid), 0}},
396         {fmtid_hexpidW, &out, S_OK, {GUID_MEMBERS(expect_guid), 0}},
397         {fmtid_mixedpidW, &out, S_OK, {GUID_MEMBERS(expect_guid), 0}},
398         {fmtid_overflowpidW, &out, S_OK, {GUID_MEMBERS(expect_guid), 3755744309U}},
399         {fmtid_commapidW, &out, S_OK, {GUID_MEMBERS(expect_guid), 13579}},
400         {fmtid_commaspidW, &out, S_OK, {GUID_MEMBERS(expect_guid), 0}},
401         {fmtid_commaspacepidW, &out, S_OK, {GUID_MEMBERS(expect_guid), 13579}},
402         {fmtid_spacecommapidW, &out, S_OK, {GUID_MEMBERS(expect_guid), 13579}},
403         {fmtid_spccommaspcpidW, &out, S_OK, {GUID_MEMBERS(expect_guid), 13579}},
404         {fmtid_spacescommaspidW, &out, S_OK, {GUID_MEMBERS(expect_guid), 0}},
405         {fmtid_commanegpidW, &out, S_OK, {GUID_MEMBERS(expect_guid), 4294953717U}},
406         {fmtid_spccommanegpidW, &out, S_OK, {GUID_MEMBERS(expect_guid), 4294953717U}},
407         {fmtid_commaspcnegpidW, &out, S_OK, {GUID_MEMBERS(expect_guid), 4294953717U}},
408         {fmtid_spccommaspcnegpidW, &out, S_OK, {GUID_MEMBERS(expect_guid), 4294953717U}},
409         {fmtid_commanegspcpidW, &out, S_OK, {GUID_MEMBERS(expect_guid), 0U}},
410         {fmtid_negcommapidW, &out, S_OK, {GUID_MEMBERS(expect_guid), 0}},
411         {fmtid_normalpidW, &out, S_OK, {GUID_MEMBERS(expect_guid), 13579}},
412     };
413 
414     int i;
415 
416     for (i = 0; i < ARRAY_SIZE(testcases); i++)
417     {
418         if (testcases[i].pkey)
419             *testcases[i].pkey = out_init;
420 
421         ret = PSPropertyKeyFromString(testcases[i].pwzString, testcases[i].pkey);
422         ok(ret == testcases[i].hr_expect,
423            "[%d] Expected PSPropertyKeyFromString to return 0x%08x, got 0x%08x\n",
424            i, testcases[i].hr_expect, ret);
425 
426         if (testcases[i].pkey)
427         {
428             ok(IsEqualGUID(&testcases[i].pkey->fmtid, &testcases[i].pkey_expect.fmtid),
429                "[%d] Expected GUID %s, got %s\n",
430                i, wine_dbgstr_guid(&testcases[i].pkey_expect.fmtid), wine_dbgstr_guid(&testcases[i].pkey->fmtid));
431             ok(testcases[i].pkey->pid == testcases[i].pkey_expect.pid,
432                "[%d] Expected property ID %u, got %u\n",
433                i, testcases[i].pkey_expect.pid, testcases[i].pkey->pid);
434         }
435     }
436 }
437 
438 static void test_PSRefreshPropertySchema(void)
439 {
440     HRESULT ret;
441 
442     ret = PSRefreshPropertySchema();
443     todo_wine
444     ok(ret == CO_E_NOTINITIALIZED,
445        "Expected PSRefreshPropertySchema to return CO_E_NOTINITIALIZED, got 0x%08x\n", ret);
446 
447     CoInitialize(NULL);
448 
449     ret = PSRefreshPropertySchema();
450     ok(ret == S_OK,
451        "Expected PSRefreshPropertySchema to return S_OK, got 0x%08x\n", ret);
452 
453     CoUninitialize();
454 }
455 
456 static void test_InitPropVariantFromGUIDAsString(void)
457 {
458     PROPVARIANT propvar;
459     VARIANT var;
460     HRESULT hres;
461     int i;
462 
463     const struct {
464         REFGUID guid;
465         const char *str;
466     } testcases[] = {
467         {&IID_NULL,             "{00000000-0000-0000-0000-000000000000}" },
468         {&dummy_guid,           "{DEADBEEF-DEAD-BEEF-DEAD-BEEFCAFEBABE}" },
469     };
470 
471     hres = InitPropVariantFromGUIDAsString(NULL, &propvar);
472     ok(hres == E_FAIL, "InitPropVariantFromGUIDAsString returned %x\n", hres);
473 
474     if(0) {
475         /* Returns strange data on Win7, crashes on older systems */
476         InitVariantFromGUIDAsString(NULL, &var);
477 
478         /* Crashes on windows */
479         InitPropVariantFromGUIDAsString(&IID_NULL, NULL);
480         InitVariantFromGUIDAsString(&IID_NULL, NULL);
481     }
482 
483     for(i=0; i < ARRAY_SIZE(testcases); i++) {
484         memset(&propvar, 0, sizeof(PROPVARIANT));
485         hres = InitPropVariantFromGUIDAsString(testcases[i].guid, &propvar);
486         ok(hres == S_OK, "%d) InitPropVariantFromGUIDAsString returned %x\n", i, hres);
487         ok(propvar.vt == VT_LPWSTR, "%d) propvar.vt = %d\n", i, propvar.vt);
488         ok(!strcmp_wa(propvar.u.pwszVal, testcases[i].str), "%d) propvar.u.pwszVal = %s\n",
489                 i, wine_dbgstr_w(propvar.u.pwszVal));
490         CoTaskMemFree(propvar.u.pwszVal);
491 
492         memset(&var, 0, sizeof(VARIANT));
493         hres = InitVariantFromGUIDAsString(testcases[i].guid, &var);
494         ok(hres == S_OK, "%d) InitVariantFromGUIDAsString returned %x\n", i, hres);
495         ok(V_VT(&var) == VT_BSTR, "%d) V_VT(&var) = %d\n", i, V_VT(&var));
496         ok(SysStringLen(V_BSTR(&var)) == 38, "SysStringLen returned %d\n",
497                 SysStringLen(V_BSTR(&var)));
498         ok(!strcmp_wa(V_BSTR(&var), testcases[i].str), "%d) V_BSTR(&var) = %s\n",
499                 i, wine_dbgstr_w(V_BSTR(&var)));
500         VariantClear(&var);
501     }
502 }
503 
504 static void test_InitPropVariantFromBuffer(void)
505 {
506     static const char data_in[] = "test";
507     PROPVARIANT propvar;
508     VARIANT var;
509     HRESULT hres;
510     void *data_out;
511     LONG size;
512 
513     hres = InitPropVariantFromBuffer(NULL, 0, &propvar);
514     ok(hres == S_OK, "InitPropVariantFromBuffer returned %x\n", hres);
515     ok(propvar.vt == (VT_VECTOR|VT_UI1), "propvar.vt = %d\n", propvar.vt);
516     ok(propvar.u.caub.cElems == 0, "cElems = %d\n", propvar.u.caub.cElems == 0);
517     PropVariantClear(&propvar);
518 
519     hres = InitPropVariantFromBuffer(data_in, 4, &propvar);
520     ok(hres == S_OK, "InitPropVariantFromBuffer returned %x\n", hres);
521     ok(propvar.vt == (VT_VECTOR|VT_UI1), "propvar.vt = %d\n", propvar.vt);
522     ok(propvar.u.caub.cElems == 4, "cElems = %d\n", propvar.u.caub.cElems == 0);
523     ok(!memcmp(propvar.u.caub.pElems, data_in, 4), "Data inside array is incorrect\n");
524     PropVariantClear(&propvar);
525 
526     hres = InitVariantFromBuffer(NULL, 0, &var);
527     ok(hres == S_OK, "InitVariantFromBuffer returned %x\n", hres);
528     ok(V_VT(&var) == (VT_ARRAY|VT_UI1), "V_VT(&var) = %d\n", V_VT(&var));
529     size = SafeArrayGetDim(V_ARRAY(&var));
530     ok(size == 1, "SafeArrayGetDim returned %d\n", size);
531     hres = SafeArrayGetLBound(V_ARRAY(&var), 1, &size);
532     ok(hres == S_OK, "SafeArrayGetLBound returned %x\n", hres);
533     ok(size == 0, "LBound = %d\n", size);
534     hres = SafeArrayGetUBound(V_ARRAY(&var), 1, &size);
535     ok(hres == S_OK, "SafeArrayGetUBound returned %x\n", hres);
536     ok(size == -1, "UBound = %d\n", size);
537     VariantClear(&var);
538 
539     hres = InitVariantFromBuffer(data_in, 4, &var);
540     ok(hres == S_OK, "InitVariantFromBuffer returned %x\n", hres);
541     ok(V_VT(&var) == (VT_ARRAY|VT_UI1), "V_VT(&var) = %d\n", V_VT(&var));
542     size = SafeArrayGetDim(V_ARRAY(&var));
543     ok(size == 1, "SafeArrayGetDim returned %d\n", size);
544     hres = SafeArrayGetLBound(V_ARRAY(&var), 1, &size);
545     ok(hres == S_OK, "SafeArrayGetLBound returned %x\n", hres);
546     ok(size == 0, "LBound = %d\n", size);
547     hres = SafeArrayGetUBound(V_ARRAY(&var), 1, &size);
548     ok(hres == S_OK, "SafeArrayGetUBound returned %x\n", hres);
549     ok(size == 3, "UBound = %d\n", size);
550     hres = SafeArrayAccessData(V_ARRAY(&var), &data_out);
551     ok(hres == S_OK, "SafeArrayAccessData failed %x\n", hres);
552     ok(!memcmp(data_in, data_out, 4), "Data inside safe array is incorrect\n");
553     hres = SafeArrayUnaccessData(V_ARRAY(&var));
554     ok(hres == S_OK, "SafeArrayUnaccessData failed %x\n", hres);
555     VariantClear(&var);
556 }
557 
558 static void test_PropVariantToGUID(void)
559 {
560     PROPVARIANT propvar;
561     VARIANT var;
562     GUID guid;
563     HRESULT hres;
564 
565     hres = InitPropVariantFromGUIDAsString(&IID_NULL, &propvar);
566     ok(hres == S_OK, "InitPropVariantFromGUIDAsString failed %x\n", hres);
567 
568     hres = PropVariantToGUID(&propvar, &guid);
569     ok(hres == S_OK, "PropVariantToGUID failed %x\n", hres);
570     ok(!memcmp(&IID_NULL, &guid, sizeof(GUID)), "incorrect GUID created: %s\n", wine_dbgstr_guid(&guid));
571     PropVariantClear(&propvar);
572 
573     hres = InitPropVariantFromGUIDAsString(&dummy_guid, &propvar);
574     ok(hres == S_OK, "InitPropVariantFromGUIDAsString failed %x\n", hres);
575 
576     hres = PropVariantToGUID(&propvar, &guid);
577     ok(hres == S_OK, "PropVariantToGUID failed %x\n", hres);
578     ok(!memcmp(&dummy_guid, &guid, sizeof(GUID)), "incorrect GUID created: %s\n", wine_dbgstr_guid(&guid));
579 
580     ok(propvar.vt == VT_LPWSTR, "incorrect PROPVARIANT type: %d\n", propvar.vt);
581     propvar.u.pwszVal[1] = 'd';
582     propvar.u.pwszVal[2] = 'E';
583     propvar.u.pwszVal[3] = 'a';
584     hres = PropVariantToGUID(&propvar, &guid);
585     ok(hres == S_OK, "PropVariantToGUID failed %x\n", hres);
586     ok(!memcmp(&dummy_guid, &guid, sizeof(GUID)), "incorrect GUID created: %s\n", wine_dbgstr_guid(&guid));
587 
588     propvar.u.pwszVal[1] = 'z';
589     hres = PropVariantToGUID(&propvar, &guid);
590     ok(hres == E_INVALIDARG, "PropVariantToGUID returned %x\n", hres);
591     PropVariantClear(&propvar);
592 
593 
594     hres = InitVariantFromGUIDAsString(&IID_NULL, &var);
595     ok(hres == S_OK, "InitVariantFromGUIDAsString failed %x\n", hres);
596 
597     hres = VariantToGUID(&var, &guid);
598     ok(hres == S_OK, "VariantToGUID failed %x\n", hres);
599     ok(!memcmp(&IID_NULL, &guid, sizeof(GUID)), "incorrect GUID created: %s\n", wine_dbgstr_guid(&guid));
600     VariantClear(&var);
601 
602     hres = InitVariantFromGUIDAsString(&dummy_guid, &var);
603     ok(hres == S_OK, "InitVariantFromGUIDAsString failed %x\n", hres);
604 
605     hres = VariantToGUID(&var, &guid);
606     ok(hres == S_OK, "VariantToGUID failed %x\n", hres);
607     ok(!memcmp(&dummy_guid, &guid, sizeof(GUID)), "incorrect GUID created: %s\n", wine_dbgstr_guid(&guid));
608 
609     ok(V_VT(&var) == VT_BSTR, "incorrect VARIANT type: %d\n", V_VT(&var));
610     V_BSTR(&var)[1] = 'z';
611     hres = VariantToGUID(&var, &guid);
612     ok(hres == E_FAIL, "VariantToGUID returned %x\n", hres);
613 
614     V_BSTR(&var)[1] = 'd';
615     propvar.vt = V_VT(&var);
616     propvar.u.bstrVal = V_BSTR(&var);
617     V_VT(&var) = VT_EMPTY;
618     hres = PropVariantToGUID(&propvar, &guid);
619     ok(hres == S_OK, "PropVariantToGUID failed %x\n", hres);
620     ok(!memcmp(&dummy_guid, &guid, sizeof(GUID)), "incorrect GUID created: %s\n", wine_dbgstr_guid(&guid));
621     PropVariantClear(&propvar);
622 }
623 
624 static void test_PropVariantToStringAlloc(void)
625 {
626     PROPVARIANT prop;
627     WCHAR *str;
628     HRESULT hres;
629 
630     prop.vt = VT_NULL;
631     hres = PropVariantToStringAlloc(&prop, &str);
632     ok(hres == S_OK, "returned %x\n", hres);
633     ok(!lstrcmpW(str, emptyW), "got %s\n", wine_dbgstr_w(str));
634     CoTaskMemFree(str);
635 
636     prop.vt = VT_LPSTR;
637     prop.u.pszVal = CoTaskMemAlloc(strlen(topic)+1);
638     strcpy(prop.u.pszVal, topic);
639     hres = PropVariantToStringAlloc(&prop, &str);
640     ok(hres == S_OK, "returned %x\n", hres);
641     ok(!lstrcmpW(str, topicW), "got %s\n", wine_dbgstr_w(str));
642     CoTaskMemFree(str);
643     PropVariantClear(&prop);
644 }
645 
646 static void test_PropVariantCompare(void)
647 {
648     PROPVARIANT empty, null, emptyarray, i2_0, i2_2, i4_large, i4_largeneg, i4_2, str_2, str_02, str_b;
649     INT res;
650     static const WCHAR str_2W[] = {'2', 0};
651     static const WCHAR str_02W[] = {'0', '2', 0};
652     static const WCHAR str_bW[] = {'b', 0};
653     SAFEARRAY emptysafearray;
654 
655     PropVariantInit(&empty);
656     PropVariantInit(&null);
657     PropVariantInit(&emptyarray);
658     PropVariantInit(&i2_0);
659     PropVariantInit(&i2_2);
660     PropVariantInit(&i4_large);
661     PropVariantInit(&i4_largeneg);
662     PropVariantInit(&i4_2);
663     PropVariantInit(&str_2);
664     PropVariantInit(&str_b);
665 
666     empty.vt = VT_EMPTY;
667     null.vt = VT_NULL;
668     emptyarray.vt = VT_ARRAY | VT_I4;
669     emptyarray.u.parray = &emptysafearray;
670     emptysafearray.cDims = 1;
671     emptysafearray.fFeatures = FADF_FIXEDSIZE;
672     emptysafearray.cbElements = 4;
673     emptysafearray.cLocks = 0;
674     emptysafearray.pvData = NULL;
675     emptysafearray.rgsabound[0].cElements = 0;
676     emptysafearray.rgsabound[0].lLbound = 0;
677     i2_0.vt = VT_I2;
678     i2_0.u.iVal = 0;
679     i2_2.vt = VT_I2;
680     i2_2.u.iVal = 2;
681     i4_large.vt = VT_I4;
682     i4_large.u.lVal = 65536;
683     i4_largeneg.vt = VT_I4;
684     i4_largeneg.u.lVal = -65536;
685     i4_2.vt = VT_I4;
686     i4_2.u.lVal = 2;
687     str_2.vt = VT_BSTR;
688     str_2.u.bstrVal = SysAllocString(str_2W);
689     str_02.vt = VT_BSTR;
690     str_02.u.bstrVal = SysAllocString(str_02W);
691     str_b.vt = VT_BSTR;
692     str_b.u.bstrVal = SysAllocString(str_bW);
693 
694     res = PropVariantCompareEx(&empty, &empty, 0, 0);
695     ok(res == 0, "res=%i\n", res);
696 
697     res = PropVariantCompareEx(&empty, &null, 0, 0);
698     ok(res == 0, "res=%i\n", res);
699 
700     res = PropVariantCompareEx(&null, &emptyarray, 0, 0);
701     ok(res == 0, "res=%i\n", res);
702 
703     res = PropVariantCompareEx(&null, &i2_0, 0, 0);
704     ok(res == -1, "res=%i\n", res);
705 
706     res = PropVariantCompareEx(&i2_0, &null, 0, 0);
707     ok(res == 1, "res=%i\n", res);
708 
709     res = PropVariantCompareEx(&null, &i2_0, 0, PVCF_TREATEMPTYASGREATERTHAN);
710     ok(res == 1, "res=%i\n", res);
711 
712     res = PropVariantCompareEx(&i2_0, &null, 0, PVCF_TREATEMPTYASGREATERTHAN);
713     ok(res == -1, "res=%i\n", res);
714 
715     res = PropVariantCompareEx(&i2_2, &i2_0, 0, 0);
716     ok(res == 1, "res=%i\n", res);
717 
718     res = PropVariantCompareEx(&i2_0, &i2_2, 0, 0);
719     ok(res == -1, "res=%i\n", res);
720 
721     /* Always return -1 if second value cannot be converted to first type */
722     res = PropVariantCompareEx(&i2_0, &i4_large, 0, 0);
723     ok(res == -1, "res=%i\n", res);
724 
725     res = PropVariantCompareEx(&i2_0, &i4_largeneg, 0, 0);
726     ok(res == -1, "res=%i\n", res);
727 
728     res = PropVariantCompareEx(&i4_large, &i2_0, 0, 0);
729     ok(res == 1, "res=%i\n", res);
730 
731     res = PropVariantCompareEx(&i4_largeneg, &i2_0, 0, 0);
732     ok(res == -1, "res=%i\n", res);
733 
734     res = PropVariantCompareEx(&i2_2, &i4_2, 0, 0);
735     ok(res == 0, "res=%i\n", res);
736 
737     res = PropVariantCompareEx(&i2_2, &str_2, 0, 0);
738     ok(res == 0, "res=%i\n", res);
739 
740     res = PropVariantCompareEx(&i2_2, &str_02, 0, 0);
741     ok(res == 0, "res=%i\n", res);
742 
743     res = PropVariantCompareEx(&str_2, &i2_2, 0, 0);
744     todo_wine ok(res == 0, "res=%i\n", res);
745 
746     res = PropVariantCompareEx(&str_02, &i2_2, 0, 0);
747     ok(res == -1, "res=%i\n", res);
748 
749     res = PropVariantCompareEx(&str_02, &str_2, 0, 0);
750     ok(res == -1, "res=%i\n", res);
751 
752     res = PropVariantCompareEx(&str_02, &str_b, 0, 0);
753     ok(res == -1, "res=%i\n", res);
754 
755     res = PropVariantCompareEx(&str_2, &str_02, 0, 0);
756     ok(res == 1, "res=%i\n", res);
757 
758     res = PropVariantCompareEx(&i4_large, &str_b, 0, 0);
759     todo_wine ok(res == -5 /* ??? */, "res=%i\n", res);
760 
761     SysFreeString(str_2.u.bstrVal);
762     SysFreeString(str_02.u.bstrVal);
763     SysFreeString(str_b.u.bstrVal);
764 }
765 
766 static void test_intconversions(void)
767 {
768     PROPVARIANT propvar;
769     SHORT sval;
770     USHORT usval;
771     LONG lval;
772     ULONG ulval;
773     LONGLONG llval;
774     ULONGLONG ullval;
775     HRESULT hr;
776 
777     propvar.vt = 0xdead;
778     hr = PropVariantClear(&propvar);
779     ok (FAILED(hr), "PropVariantClear fails on invalid vt.\n");
780 
781     propvar.vt = VT_I8;
782     PropVariantClear(&propvar);
783 
784     propvar.vt = VT_I8;
785     propvar.u.hVal.QuadPart = (ULONGLONG)1 << 63;
786 
787     hr = PropVariantToInt64(&propvar, &llval);
788     ok(hr == S_OK, "hr=%x\n", hr);
789     ok(llval == (ULONGLONG)1 << 63, "got wrong value %s\n", wine_dbgstr_longlong(llval));
790 
791     hr = PropVariantToUInt64(&propvar, &ullval);
792     ok(hr == HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW), "hr=%x\n", hr);
793 
794     hr = PropVariantToInt32(&propvar, &lval);
795     ok(hr == HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW), "hr=%x\n", hr);
796 
797     hr = PropVariantToUInt32(&propvar, &ulval);
798     ok(hr == HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW), "hr=%x\n", hr);
799 
800     hr = PropVariantToInt16(&propvar, &sval);
801     ok(hr == HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW), "hr=%x\n", hr);
802 
803     hr = PropVariantToUInt16(&propvar, &usval);
804     ok(hr == HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW), "hr=%x\n", hr);
805 
806     propvar.vt = VT_UI8;
807     propvar.u.uhVal.QuadPart = 5;
808 
809     hr = PropVariantToInt64(&propvar, &llval);
810     ok(hr == S_OK, "hr=%x\n", hr);
811     ok(llval == 5, "got wrong value %s\n", wine_dbgstr_longlong(llval));
812 
813     hr = PropVariantToUInt64(&propvar, &ullval);
814     ok(hr == S_OK, "hr=%x\n", hr);
815     ok(ullval == 5, "got wrong value %s\n", wine_dbgstr_longlong(ullval));
816 
817     hr = PropVariantToInt32(&propvar, &lval);
818     ok(hr == S_OK, "hr=%x\n", hr);
819     ok(lval == 5, "got wrong value %d\n", lval);
820 
821     hr = PropVariantToUInt32(&propvar, &ulval);
822     ok(hr == S_OK, "hr=%x\n", hr);
823     ok(ulval == 5, "got wrong value %d\n", ulval);
824 
825     hr = PropVariantToInt16(&propvar, &sval);
826     ok(hr == S_OK, "hr=%x\n", hr);
827     ok(sval == 5, "got wrong value %d\n", sval);
828 
829     hr = PropVariantToUInt16(&propvar, &usval);
830     ok(hr == S_OK, "hr=%x\n", hr);
831     ok(usval == 5, "got wrong value %d\n", usval);
832 
833     propvar.vt = VT_I8;
834     propvar.u.hVal.QuadPart = -5;
835 
836     hr = PropVariantToInt64(&propvar, &llval);
837     ok(hr == S_OK, "hr=%x\n", hr);
838     ok(llval == -5, "got wrong value %s\n", wine_dbgstr_longlong(llval));
839 
840     hr = PropVariantToUInt64(&propvar, &ullval);
841     ok(hr == HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW), "hr=%x\n", hr);
842 
843     hr = PropVariantToInt32(&propvar, &lval);
844     ok(hr == S_OK, "hr=%x\n", hr);
845     ok(lval == -5, "got wrong value %d\n", lval);
846 
847     hr = PropVariantToUInt32(&propvar, &ulval);
848     ok(hr == HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW), "hr=%x\n", hr);
849 
850     hr = PropVariantToInt16(&propvar, &sval);
851     ok(hr == S_OK, "hr=%x\n", hr);
852     ok(sval == -5, "got wrong value %d\n", sval);
853 
854     hr = PropVariantToUInt16(&propvar, &usval);
855     ok(hr == HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW), "hr=%x\n", hr);
856 
857     propvar.vt = VT_UI4;
858     propvar.u.ulVal = 6;
859 
860     hr = PropVariantToInt64(&propvar, &llval);
861     ok(hr == S_OK, "hr=%x\n", hr);
862     ok(llval == 6, "got wrong value %s\n", wine_dbgstr_longlong(llval));
863 
864     propvar.vt = VT_I4;
865     propvar.u.lVal = -6;
866 
867     hr = PropVariantToInt64(&propvar, &llval);
868     ok(hr == S_OK, "hr=%x\n", hr);
869     ok(llval == -6, "got wrong value %s\n", wine_dbgstr_longlong(llval));
870 
871     propvar.vt = VT_UI2;
872     propvar.u.uiVal = 7;
873 
874     hr = PropVariantToInt64(&propvar, &llval);
875     ok(hr == S_OK, "hr=%x\n", hr);
876     ok(llval == 7, "got wrong value %s\n", wine_dbgstr_longlong(llval));
877 
878     propvar.vt = VT_I2;
879     propvar.u.iVal = -7;
880 
881     hr = PropVariantToInt64(&propvar, &llval);
882     ok(hr == S_OK, "hr=%x\n", hr);
883     ok(llval == -7, "got wrong value %s\n", wine_dbgstr_longlong(llval));
884 }
885 
886 static void test_PropVariantToBoolean(void)
887 {
888     static WCHAR str_0[] = {'0',0};
889     static WCHAR str_1[] = {'1',0};
890     static WCHAR str_7[] = {'7',0};
891     static WCHAR str_n7[] = {'-','7',0};
892     static WCHAR str_true[] = {'t','r','u','e',0};
893     static WCHAR str_true2[] = {'#','T','R','U','E','#',0};
894     static WCHAR str_true_case[] = {'t','R','U','e',0};
895     static WCHAR str_false[] = {'f','a','l','s','e',0};
896     static WCHAR str_false2[] = {'#','F','A','L','S','E','#',0};
897     static WCHAR str_true_space[] = {'t','r','u','e',' ',0};
898     static WCHAR str_yes[] = {'y','e','s',0};
899     PROPVARIANT propvar;
900     HRESULT hr;
901     BOOL val;
902 
903     /* VT_BOOL */
904     propvar.vt = VT_BOOL;
905     propvar.u.boolVal = VARIANT_FALSE;
906     val = TRUE;
907     hr = PropVariantToBoolean(&propvar, &val);
908     ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
909     ok(val == FALSE, "Unexpected value %d\n", val);
910 
911     propvar.vt = VT_BOOL;
912     propvar.u.boolVal = 1;
913     val = TRUE;
914     hr = PropVariantToBoolean(&propvar, &val);
915     ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
916     ok(val == FALSE, "Unexpected value %d\n", val);
917 
918     propvar.vt = VT_BOOL;
919     propvar.u.boolVal = VARIANT_TRUE;
920     val = FALSE;
921     hr = PropVariantToBoolean(&propvar, &val);
922     ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
923     ok(val == TRUE, "Unexpected value %d\n", val);
924 
925     /* VT_EMPTY */
926     propvar.vt = VT_EMPTY;
927     propvar.u.boolVal = VARIANT_TRUE;
928     val = TRUE;
929     hr = PropVariantToBoolean(&propvar, &val);
930     ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
931     ok(val == FALSE, "Unexpected value %d\n", val);
932 
933     /* test integer conversion */
934     propvar.vt = VT_I4;
935     propvar.u.lVal = 0;
936     val = TRUE;
937     hr = PropVariantToBoolean(&propvar, &val);
938     ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
939     ok(val == FALSE, "Unexpected value %d\n", val);
940 
941     propvar.vt = VT_I4;
942     propvar.u.lVal = 1;
943     val = FALSE;
944     hr = PropVariantToBoolean(&propvar, &val);
945     ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
946     ok(val == TRUE, "Unexpected value %d\n", val);
947 
948     propvar.vt = VT_I4;
949     propvar.u.lVal = 67;
950     val = FALSE;
951     hr = PropVariantToBoolean(&propvar, &val);
952     ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
953     ok(val == TRUE, "Unexpected value %d\n", val);
954 
955     propvar.vt = VT_I4;
956     propvar.u.lVal = -67;
957     val = FALSE;
958     hr = PropVariantToBoolean(&propvar, &val);
959     ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
960     ok(val == TRUE, "Unexpected value %d\n", val);
961 
962     /* test string conversion */
963     propvar.vt = VT_LPWSTR;
964     propvar.u.pwszVal = str_0;
965     val = TRUE;
966     hr = PropVariantToBoolean(&propvar, &val);
967     ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
968     ok(val == FALSE, "Unexpected value %d\n", val);
969 
970     propvar.vt = VT_LPWSTR;
971     propvar.u.pwszVal = str_1;
972     val = FALSE;
973     hr = PropVariantToBoolean(&propvar, &val);
974     ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
975     ok(val == TRUE, "Unexpected value %d\n", val);
976 
977     propvar.vt = VT_LPWSTR;
978     propvar.u.pwszVal = str_7;
979     val = FALSE;
980     hr = PropVariantToBoolean(&propvar, &val);
981     ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
982     ok(val == TRUE, "Unexpected value %d\n", val);
983 
984     propvar.vt = VT_LPWSTR;
985     propvar.u.pwszVal = str_n7;
986     val = FALSE;
987     hr = PropVariantToBoolean(&propvar, &val);
988     ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
989     ok(val == TRUE, "Unexpected value %d\n", val);
990 
991     propvar.vt = VT_LPWSTR;
992     propvar.u.pwszVal = str_true;
993     val = FALSE;
994     hr = PropVariantToBoolean(&propvar, &val);
995     ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
996     ok(val == TRUE, "Unexpected value %d\n", val);
997 
998     propvar.vt = VT_LPWSTR;
999     propvar.u.pwszVal = str_true_case;
1000     val = FALSE;
1001     hr = PropVariantToBoolean(&propvar, &val);
1002     ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
1003     ok(val == TRUE, "Unexpected value %d\n", val);
1004 
1005     propvar.vt = VT_LPWSTR;
1006     propvar.u.pwszVal = str_true2;
1007     val = FALSE;
1008     hr = PropVariantToBoolean(&propvar, &val);
1009     ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
1010     ok(val == TRUE, "Unexpected value %d\n", val);
1011 
1012     propvar.vt = VT_LPWSTR;
1013     propvar.u.pwszVal = str_false;
1014     val = TRUE;
1015     hr = PropVariantToBoolean(&propvar, &val);
1016     ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
1017     ok(val == FALSE, "Unexpected value %d\n", val);
1018 
1019     propvar.vt = VT_LPWSTR;
1020     propvar.u.pwszVal = str_false2;
1021     val = TRUE;
1022     hr = PropVariantToBoolean(&propvar, &val);
1023     ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
1024     ok(val == FALSE, "Unexpected value %d\n", val);
1025 
1026     propvar.vt = VT_LPWSTR;
1027     propvar.u.pwszVal = str_true_space;
1028     val = TRUE;
1029     hr = PropVariantToBoolean(&propvar, &val);
1030     ok(hr == DISP_E_TYPEMISMATCH, "Unexpected hr %#x.\n", hr);
1031     ok(val == FALSE, "Unexpected value %d\n", val);
1032 
1033     propvar.vt = VT_LPWSTR;
1034     propvar.u.pwszVal = str_yes;
1035     val = TRUE;
1036     hr = PropVariantToBoolean(&propvar, &val);
1037     ok(hr == DISP_E_TYPEMISMATCH, "Unexpected hr %#x.\n", hr);
1038     ok(val == FALSE, "Unexpected value %d\n", val);
1039 
1040     propvar.vt = VT_LPWSTR;
1041     propvar.u.pwszVal = NULL;
1042     val = TRUE;
1043     hr = PropVariantToBoolean(&propvar, &val);
1044     ok(hr == DISP_E_TYPEMISMATCH, "Unexpected hr %#x.\n", hr);
1045     ok(val == FALSE, "Unexpected value %d\n", val);
1046 
1047     /* VT_LPSTR */
1048     propvar.vt = VT_LPSTR;
1049     propvar.u.pszVal = (char *)"#TruE#";
1050     val = TRUE;
1051     hr = PropVariantToBoolean(&propvar, &val);
1052     ok(hr == DISP_E_TYPEMISMATCH, "Unexpected hr %#x.\n", hr);
1053     ok(val == FALSE, "Unexpected value %d\n", val);
1054 
1055     propvar.vt = VT_LPSTR;
1056     propvar.u.pszVal = (char *)"#TRUE#";
1057     val = FALSE;
1058     hr = PropVariantToBoolean(&propvar, &val);
1059     ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
1060     ok(val == TRUE, "Unexpected value %d\n", val);
1061 
1062     propvar.vt = VT_LPSTR;
1063     propvar.u.pszVal = (char *)"tRUe";
1064     val = FALSE;
1065     hr = PropVariantToBoolean(&propvar, &val);
1066     ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
1067     ok(val == TRUE, "Unexpected value %d\n", val);
1068 
1069     propvar.vt = VT_LPSTR;
1070     propvar.u.pszVal = (char *)"#FALSE#";
1071     val = TRUE;
1072     hr = PropVariantToBoolean(&propvar, &val);
1073     ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
1074     ok(val == FALSE, "Unexpected value %d\n", val);
1075 
1076     propvar.vt = VT_LPSTR;
1077     propvar.u.pszVal = (char *)"fALSe";
1078     val = TRUE;
1079     hr = PropVariantToBoolean(&propvar, &val);
1080     ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
1081     ok(val == FALSE, "Unexpected value %d\n", val);
1082 
1083     propvar.vt = VT_LPSTR;
1084     propvar.u.pszVal = (char *)"1";
1085     val = FALSE;
1086     hr = PropVariantToBoolean(&propvar, &val);
1087     ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
1088     ok(val == TRUE, "Unexpected value %d\n", val);
1089 
1090     propvar.vt = VT_LPSTR;
1091     propvar.u.pszVal = (char *)"-1";
1092     hr = PropVariantToBoolean(&propvar, &val);
1093     ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
1094     ok(val == TRUE, "Unexpected value %d\n", val);
1095 }
1096 
1097 static void test_PropVariantToStringWithDefault(void)
1098 {
1099     PROPVARIANT propvar;
1100     static WCHAR default_value[] = {'t', 'e', 's', 't', 0};
1101     static WCHAR wstr_test2[] =  {'t', 'e', 's', 't', '2', 0};
1102     static WCHAR wstr_empty[] = {0};
1103     static WCHAR wstr_space[] = {' ', 0};
1104     static CHAR str_test2[] =  "test2";
1105     static CHAR str_empty[] = "";
1106     static CHAR str_space[] = " ";
1107     LPCWSTR result;
1108 
1109     propvar.vt = VT_EMPTY;
1110     result = PropVariantToStringWithDefault(&propvar, default_value);
1111     ok(result == default_value, "Unexpected value %s\n", wine_dbgstr_w(result));
1112 
1113     propvar.vt = VT_NULL;
1114     result = PropVariantToStringWithDefault(&propvar, default_value);
1115     ok(result == default_value, "Unexpected value %s\n", wine_dbgstr_w(result));
1116 
1117     propvar.vt = VT_BOOL;
1118     propvar.u.boolVal = VARIANT_TRUE;
1119     result = PropVariantToStringWithDefault(&propvar, default_value);
1120     ok(result == default_value, "Unexpected value %s\n", wine_dbgstr_w(result));
1121 
1122     propvar.vt = VT_I4;
1123     propvar.u.lVal = 15;
1124     result = PropVariantToStringWithDefault(&propvar, default_value);
1125     ok(result == default_value, "Unexpected value %s\n", wine_dbgstr_w(result));
1126 
1127     /* VT_LPWSTR */
1128 
1129     propvar.vt = VT_LPWSTR;
1130     propvar.u.pwszVal = NULL;
1131     result = PropVariantToStringWithDefault(&propvar, default_value);
1132     ok(result == default_value, "Unexpected value %s\n", wine_dbgstr_w(result));
1133 
1134     propvar.vt = VT_LPWSTR;
1135     propvar.u.pwszVal = wstr_empty;
1136     result = PropVariantToStringWithDefault(&propvar, default_value);
1137     ok(result == wstr_empty, "Unexpected value %s\n", wine_dbgstr_w(result));
1138 
1139     propvar.vt = VT_LPWSTR;
1140     propvar.u.pwszVal = wstr_space;
1141     result = PropVariantToStringWithDefault(&propvar, default_value);
1142     ok(result == wstr_space, "Unexpected value %s\n", wine_dbgstr_w(result));
1143 
1144     propvar.vt = VT_LPWSTR;
1145     propvar.u.pwszVal = wstr_test2;
1146     result = PropVariantToStringWithDefault(&propvar, default_value);
1147     ok(result == wstr_test2, "Unexpected value %s\n", wine_dbgstr_w(result));
1148 
1149     /* VT_LPSTR */
1150 
1151     propvar.vt = VT_LPSTR;
1152     propvar.u.pszVal = NULL;
1153     result = PropVariantToStringWithDefault(&propvar, default_value);
1154     ok(result == default_value, "Unexpected value %s\n", wine_dbgstr_w(result));
1155 
1156     propvar.vt = VT_LPSTR;
1157     propvar.u.pszVal = str_empty;
1158     result = PropVariantToStringWithDefault(&propvar, default_value);
1159     ok(result == default_value, "Unexpected value %s\n", wine_dbgstr_w(result));
1160 
1161     propvar.vt = VT_LPSTR;
1162     propvar.u.pszVal = str_space;
1163     result = PropVariantToStringWithDefault(&propvar, default_value);
1164     ok(result == default_value, "Unexpected value %s\n", wine_dbgstr_w(result));
1165 
1166     propvar.vt = VT_LPSTR;
1167     propvar.u.pszVal = str_test2;
1168     result = PropVariantToStringWithDefault(&propvar, default_value);
1169     ok(result == default_value, "Unexpected value %s\n", wine_dbgstr_w(result));
1170 
1171     /* VT_BSTR */
1172 
1173     propvar.vt = VT_BSTR;
1174     propvar.u.bstrVal = NULL;
1175     result = PropVariantToStringWithDefault(&propvar, default_value);
1176     ok(!lstrcmpW(result, wstr_empty), "Unexpected value %s\n", wine_dbgstr_w(result));
1177 
1178     propvar.vt = VT_BSTR;
1179     propvar.u.bstrVal = SysAllocString(wstr_empty);
1180     result = PropVariantToStringWithDefault(&propvar, default_value);
1181     ok(!lstrcmpW(result, wstr_empty), "Unexpected value %s\n", wine_dbgstr_w(result));
1182     SysFreeString(propvar.u.bstrVal);
1183 
1184     propvar.vt = VT_BSTR;
1185     propvar.u.bstrVal = SysAllocString(wstr_space);
1186     result = PropVariantToStringWithDefault(&propvar, default_value);
1187     ok(!lstrcmpW(result, wstr_space), "Unexpected value %s\n", wine_dbgstr_w(result));
1188     SysFreeString(propvar.u.bstrVal);
1189 
1190     propvar.vt = VT_BSTR;
1191     propvar.u.bstrVal = SysAllocString(wstr_test2);
1192     result = PropVariantToStringWithDefault(&propvar, default_value);
1193     ok(!lstrcmpW(result, wstr_test2), "Unexpected value %s\n", wine_dbgstr_w(result));
1194     SysFreeString(propvar.u.bstrVal);
1195 }
1196 
1197 static void test_PropVariantChangeType_LPWSTR(void)
1198 {
1199     PROPVARIANT dest, src;
1200     HRESULT hr;
1201 
1202     PropVariantInit(&dest);
1203 
1204     src.vt = VT_NULL;
1205     hr = PropVariantChangeType(&dest, &src, 0, VT_LPWSTR);
1206     ok(hr == S_OK, "hr=%x\n", hr);
1207     ok(dest.vt == VT_LPWSTR, "got %d\n", dest.vt);
1208     ok(!lstrcmpW(dest.u.pwszVal, emptyW), "got %s\n", wine_dbgstr_w(dest.u.pwszVal));
1209     PropVariantClear(&dest);
1210     PropVariantClear(&src);
1211 
1212     src.vt = VT_LPSTR;
1213     src.u.pszVal = CoTaskMemAlloc(strlen(topic)+1);
1214     strcpy(src.u.pszVal, topic);
1215     hr = PropVariantChangeType(&dest, &src, 0, VT_LPWSTR);
1216     ok(hr == S_OK, "hr=%x\n", hr);
1217     ok(dest.vt == VT_LPWSTR, "got %d\n", dest.vt);
1218     ok(!lstrcmpW(dest.u.pwszVal, topicW), "got %s\n", wine_dbgstr_w(dest.u.pwszVal));
1219     PropVariantClear(&dest);
1220     PropVariantClear(&src);
1221 
1222     src.vt = VT_LPWSTR;
1223     src.u.pwszVal = CoTaskMemAlloc( (lstrlenW(topicW)+1) * sizeof(WCHAR));
1224     lstrcpyW(src.u.pwszVal, topicW);
1225     hr = PropVariantChangeType(&dest, &src, 0, VT_LPWSTR);
1226     ok(hr == S_OK, "hr=%x\n", hr);
1227     ok(dest.vt == VT_LPWSTR, "got %d\n", dest.vt);
1228     ok(!lstrcmpW(dest.u.pwszVal, topicW), "got %s\n", wine_dbgstr_w(dest.u.pwszVal));
1229     PropVariantClear(&dest);
1230     PropVariantClear(&src);
1231 }
1232 
1233 static void test_InitPropVariantFromCLSID(void)
1234 {
1235     PROPVARIANT propvar;
1236     GUID clsid;
1237     HRESULT hr;
1238 
1239     memset(&propvar, 0, sizeof(propvar));
1240     propvar.vt = VT_I4;
1241     propvar.u.lVal = 15;
1242 
1243     memset(&clsid, 0xcc, sizeof(clsid));
1244     hr = InitPropVariantFromCLSID(&clsid, &propvar);
1245     ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
1246     ok(propvar.vt == VT_CLSID, "Unexpected type %d.\n", propvar.vt);
1247     ok(IsEqualGUID(propvar.u.puuid, &clsid), "Unexpected puuid value.\n");
1248     PropVariantClear(&propvar);
1249 }
1250 
1251 START_TEST(propsys)
1252 {
1253     test_PSStringFromPropertyKey();
1254     test_PSPropertyKeyFromString();
1255     test_PSRefreshPropertySchema();
1256     test_InitPropVariantFromGUIDAsString();
1257     test_InitPropVariantFromBuffer();
1258     test_PropVariantToGUID();
1259     test_PropVariantToStringAlloc();
1260     test_PropVariantCompare();
1261     test_intconversions();
1262     test_PropVariantChangeType_LPWSTR();
1263     test_PropVariantToBoolean();
1264     test_PropVariantToStringWithDefault();
1265     test_InitPropVariantFromCLSID();
1266 }
1267