winemac: Implement the Mac "Window" menu.
[wine] / dlls / propsys / tests / propsys.c
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 static char *show_guid(const GUID *guid, char *buf)
42 {
43     static char static_buf[40];
44
45     if(!buf)
46         buf = static_buf;
47
48     sprintf(buf,
49         "{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
50         guid->Data1, guid->Data2, guid->Data3,
51         guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
52         guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7] );
53
54     return buf;
55 }
56
57 static int strcmp_wa(LPCWSTR strw, const char *stra)
58 {
59     CHAR buf[512];
60     WideCharToMultiByte(CP_ACP, 0, strw, -1, buf, sizeof(buf), NULL, NULL);
61     return lstrcmpA(stra, buf);
62 }
63
64 static void test_PSStringFromPropertyKey(void)
65 {
66     static const WCHAR fillerW[] = {'X','X','X','X','X','X','X','X','X','X','X','X','X','X','X','X','X','X','X','X',
67                                     'X','X','X','X','X','X','X','X','X','X','X','X','X','X','X','X','X','X','X','X',
68                                     'X','X','X','X','X','X','X','X','X','X'};
69     static const WCHAR zero_fillerW[] = {'\0','X','X','X','X','X','X','X','X','X','X','X','X','X','X','X','X','X',
70                                          'X','X','X','X','X','X','X','X','X','X','X','X','X','X','X','X','X','X',
71                                          'X','X','X','X','X','X','X','X','X','X','X','X','X','X'};
72     static const WCHAR zero_truncatedW[] = {'\0','0','0','0','0','0','0','0','0','-','0','0','0','0','-','0','0',
73                                             '0','0','-','0','0','0','0','-','0','0','0','0','0','0','0','0','0',
74                                             '0','0','0','}',' ','\0','9','X','X','X','X','X','X','X','X','X'};
75     static const WCHAR zero_truncated2W[] = {'\0','0','0','0','0','0','0','0','0','-','0','0','0','0','-','0','0',
76                                              '0','0','-','0','0','0','0','-','0','0','0','0','0','0','0','0','0',
77                                              '0','0','0','}',' ','\0','9','2','7','6','9','4','9','2','X','X'};
78     static const WCHAR zero_truncated3W[] = {'\0','0','0','0','0','0','0','0','0','-','0','0','0','0','-','0','0',
79                                             '0','0','-','0','0','0','0','-','0','0','0','0','0','0','0','0','0',
80                                             '0','0','0','}',' ','\0','9','2','7','6','9','4','9','2','4','X'};
81     static const WCHAR zero_truncated4W[] = {'\0','0','0','0','0','0','0','0','0','-','0','0','0','0','-','0','0',
82                                              '0','0','-','0','0','0','0','-','0','0','0','0','0','0','0','0','0',
83                                              '0','0','0','}',' ','\0','7','X','X','X','X','X','X','X','X','X'};
84     static const WCHAR truncatedW[] = {'{','0','0','0','0','0','0','0','0','-','0','0','0','0','-','0','0','0',
85                                         '0','-','0','0','0','0','-','0','0','0','0','0','0','0','0','0','0','0',
86                                         '0','}',' ','\0','9','X','X','X','X','X','X','X','X','X'};
87     static const WCHAR truncated2W[] = {'{','0','0','0','0','0','0','0','0','-','0','0','0','0','-','0','0','0',
88                                         '0','-','0','0','0','0','-','0','0','0','0','0','0','0','0','0','0','0',
89                                         '0','}',' ','\0','9','2','7','6','9','4','9','2','X','X'};
90     static const WCHAR truncated3W[] = {'{','0','0','0','0','0','0','0','0','-','0','0','0','0','-','0','0','0',
91                                        '0','-','0','0','0','0','-','0','0','0','0','0','0','0','0','0','0','0',
92                                        '0','}',' ','\0','9','2','7','6','9','4','9','2','4','X'};
93     static const WCHAR truncated4W[] = {'{','0','0','0','0','0','0','0','0','-','0','0','0','0','-','0','0','0',
94                                         '0','-','0','0','0','0','-','0','0','0','0','0','0','0','0','0','0','0',
95                                         '0','}',' ','\0','7','X','X','X','X','X','X','X','X','X'};
96     static const WCHAR expectedW[] = {'{','0','0','0','0','0','0','0','0','-','0','0','0','0','-','0','0','0',
97                                       '0','-','0','0','0','0','-','0','0','0','0','0','0','0','0','0','0','0',
98                                       '0','}',' ','4','2','9','4','9','6','7','2','9','5',0};
99     static const WCHAR expected2W[] = {'{','0','0','0','0','0','0','0','0','-','0','0','0','0','-','0','0','0',
100                                        '0','-','0','0','0','0','-','0','0','0','0','0','0','0','0','0','0','0',
101                                        '0','}',' ','1','3','5','7','9','\0','X','X','X','X','X'};
102     static const WCHAR expected3W[] = {'{','0','0','0','0','0','0','0','0','-','0','0','0','0','-','0','0','0',
103                                        '0','-','0','0','0','0','-','0','0','0','0','0','0','0','0','0','0','0',
104                                        '0','}',' ','0','\0','X','X','X','X','X','X','X','X','X'};
105     PROPERTYKEY prop = {GUID_NULL, ~0U};
106     PROPERTYKEY prop2 = {GUID_NULL, 13579};
107     PROPERTYKEY prop3 = {GUID_NULL, 0};
108     WCHAR out[PKEYSTR_MAX];
109     HRESULT ret;
110
111     const struct
112     {
113         REFPROPERTYKEY pkey;
114         LPWSTR psz;
115         UINT cch;
116         HRESULT hr_expect;
117         const WCHAR *buf_expect;
118         int hr_broken;
119         HRESULT hr2;
120         int buf_broken;
121         const WCHAR *buf2;
122     } testcases[] =
123     {
124         {NULL, NULL, 0, E_POINTER},
125         {&prop, NULL, 0, E_POINTER},
126         {&prop, NULL, PKEYSTR_MAX, E_POINTER},
127         {NULL, out, 0, HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER), fillerW},
128         {NULL, out, PKEYSTR_MAX, HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER), zero_fillerW, 0, 0, 1, fillerW},
129         {&prop, out, 0, HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER), fillerW},
130         {&prop, out, GUIDSTRING_MAX, HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER), fillerW},
131         {&prop, out, GUIDSTRING_MAX + 1, HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER), fillerW},
132         {&prop, out, GUIDSTRING_MAX + 2, HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER), zero_truncatedW, 1, S_OK, 1, truncatedW},
133         {&prop, out, PKEYSTR_MAX - 2, HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER), zero_truncated2W, 1, S_OK, 1, truncated2W},
134         {&prop, out, PKEYSTR_MAX - 1, HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER), zero_truncated3W, 1, S_OK, 1, truncated3W},
135         {&prop, out, PKEYSTR_MAX, S_OK, expectedW},
136         {&prop2, out, GUIDSTRING_MAX + 2, HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER), zero_truncated4W, 1, S_OK, 1, truncated4W},
137         {&prop2, out, GUIDSTRING_MAX + 6, S_OK, expected2W},
138         {&prop2, out, PKEYSTR_MAX, S_OK, expected2W},
139         {&prop3, out, GUIDSTRING_MAX + 1, HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER), fillerW},
140         {&prop3, out, GUIDSTRING_MAX + 2, S_OK, expected3W},
141         {&prop3, out, PKEYSTR_MAX, S_OK, expected3W},
142     };
143
144     int i;
145
146     for (i = 0; i < sizeof(testcases)/sizeof(testcases[0]); i++)
147     {
148         if (testcases[i].psz)
149             memcpy(testcases[i].psz, fillerW, PKEYSTR_MAX * sizeof(WCHAR));
150
151         ret = PSStringFromPropertyKey(testcases[i].pkey,
152                                       testcases[i].psz,
153                                       testcases[i].cch);
154         ok(ret == testcases[i].hr_expect ||
155            broken(testcases[i].hr_broken && ret == testcases[i].hr2), /* Vista/Win2k8 */
156            "[%d] Expected PSStringFromPropertyKey to return 0x%08x, got 0x%08x\n",
157            i, testcases[i].hr_expect, ret);
158
159         if (testcases[i].psz)
160             ok(!memcmp(testcases[i].psz, testcases[i].buf_expect, PKEYSTR_MAX * sizeof(WCHAR)) ||
161                 broken(testcases[i].buf_broken &&
162                        !memcmp(testcases[i].psz, testcases[i].buf2, PKEYSTR_MAX * sizeof(WCHAR))), /* Vista/Win2k8 */
163                "[%d] Unexpected output contents\n", i);
164     }
165 }
166
167 static void test_PSPropertyKeyFromString(void)
168 {
169     static const WCHAR emptyW[] = {0};
170     static const WCHAR fmtid_clsidW[] = {'S','t','d','F','o','n','t',' ','1',0};
171     static const WCHAR fmtid_truncatedW[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
172                                              '1','2','3','4','-',0};
173     static const WCHAR fmtid_nobracketsW[] = {'1','2','3','4','5','6','7','8','-','1','2','3','4','-',
174                                               '1','2','3','4','-','1','2','3','4','-',
175                                               '1','2','3','4','5','6','7','8','9','0','1','2',0};
176     static const WCHAR fmtid_badbracketW[] = {'X','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
177                                               '1','2','3','4','-','1','2','3','4','-',
178                                               '1','2','3','4','5','6','7','8','9','0','1','2','}',0};
179     static const WCHAR fmtid_badcharW[] = {'{','X','2','3','4','5','6','7','8','-','1','2','3','4','-',
180                                            '1','2','3','4','-','1','2','3','4','-',
181                                            '1','2','3','4','5','6','7','8','9','0','1','2','}',0};
182     static const WCHAR fmtid_badchar2W[] = {'{','1','2','3','4','5','6','7','X','-','1','2','3','4','-',
183                                             '1','2','3','4','-','1','2','3','4','-',
184                                             '1','2','3','4','5','6','7','8','9','0','1','2','}',0};
185     static const WCHAR fmtid_baddashW[] = {'{','1','2','3','4','5','6','7','8','X','1','2','3','4','-',
186                                            '1','2','3','4','-','1','2','3','4','-',
187                                            '1','2','3','4','5','6','7','8','9','0','1','2','}',0};
188     static const WCHAR fmtid_badchar3W[] = {'{','1','2','3','4','5','6','7','8','-','X','2','3','4','-',
189                                             '1','2','3','4','-','1','2','3','4','-',
190                                             '1','2','3','4','5','6','7','8','9','0','1','2','}',0};
191     static const WCHAR fmtid_badchar4W[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','X','-',
192                                             '1','2','3','4','-','1','2','3','4','-',
193                                             '1','2','3','4','5','6','7','8','9','0','1','2','}',0};
194     static const WCHAR fmtid_baddash2W[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','X',
195                                             '1','2','3','4','-','1','2','3','4','-',
196                                             '1','2','3','4','5','6','7','8','9','0','1','2','}',0};
197     static const WCHAR fmtid_badchar5W[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
198                                             'X','2','3','4','-','1','2','3','4','-',
199                                             '1','2','3','4','5','6','7','8','9','0','1','2','}',0};
200     static const WCHAR fmtid_badchar6W[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
201                                             '1','2','3','X','-','1','2','3','4','-',
202                                             '1','2','3','4','5','6','7','8','9','0','1','2','}',0};
203     static const WCHAR fmtid_baddash3W[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
204                                             '1','2','3','4','X','1','2','3','4','-',
205                                             '1','2','3','4','5','6','7','8','9','0','1','2','}',0};
206     static const WCHAR fmtid_badchar7W[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
207                                             '1','2','3','4','-','X','2','3','4','-',
208                                             '1','2','3','4','5','6','7','8','9','0','1','2','}',0};
209     static const WCHAR fmtid_badchar8W[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
210                                             '1','2','3','4','-','1','2','3','X','-',
211                                             '1','2','3','4','5','6','7','8','9','0','1','2','}',0};
212     static const WCHAR fmtid_baddash4W[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
213                                             '1','2','3','4','-','1','2','3','4','X',
214                                             '1','2','3','4','5','6','7','8','9','0','1','2','}',0};
215     static const WCHAR fmtid_badchar9W[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
216                                             '1','2','3','4','-','1','2','3','4','-',
217                                             'X','2','3','4','5','6','7','8','9','0','1','2','}',0};
218     static const WCHAR fmtid_badchar9_adjW[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
219                                                 '1','2','3','4','-','1','2','3','4','-',
220                                                 '1','X','3','4','5','6','7','8','9','0','1','2','}',0};
221     static const WCHAR fmtid_badchar10W[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
222                                              '1','2','3','4','-','1','2','3','4','-',
223                                              '1','2','X','4','5','6','7','8','9','0','1','2','}',0};
224     static const WCHAR fmtid_badchar11W[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
225                                              '1','2','3','4','-','1','2','3','4','-',
226                                              '1','2','3','4','X','6','7','8','9','0','1','2','}',0};
227     static const WCHAR fmtid_badchar12W[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
228                                              '1','2','3','4','-','1','2','3','4','-',
229                                              '1','2','3','4','5','6','X','8','9','0','1','2','}',0};
230     static const WCHAR fmtid_badchar13W[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
231                                              '1','2','3','4','-','1','2','3','4','-',
232                                              '1','2','3','4','5','6','7','8','X','0','1','2','}',0};
233     static const WCHAR fmtid_badchar14W[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
234                                              '1','2','3','4','-','1','2','3','4','-',
235                                              '1','2','3','4','5','6','7','8','9','0','X','2','}',0};
236     static const WCHAR fmtid_badbracket2W[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
237                                                '1','2','3','4','-','1','2','3','4','-',
238                                                '1','2','3','4','5','6','7','8','9','0','1','2','X',0};
239     static const WCHAR fmtid_spaceW[] = {' ','{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
240                                          '1','2','3','4','-','1','2','3','4','-',
241                                          '1','2','3','4','5','6','7','8','9','0','1','2','}',0};
242     static const WCHAR fmtid_spaceendW[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
243                                             '1','2','3','4','-','1','2','3','4','-',
244                                             '1','2','3','4','5','6','7','8','9','0','1','2','}',' ',0};
245     static const WCHAR fmtid_spacesendW[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
246                                              '1','2','3','4','-','1','2','3','4','-',
247                                              '1','2','3','4','5','6','7','8','9','0','1','2','}',' ',' ',' ',0};
248     static const WCHAR fmtid_nopidW[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
249                                          '1','2','3','4','-','1','2','3','4','-',
250                                          '1','2','3','4','5','6','7','8','9','0','1','2','}',0};
251     static const WCHAR fmtid_badpidW[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
252                                           '1','2','3','4','-','1','2','3','4','-',
253                                           '1','2','3','4','5','6','7','8','9','0','1','2','}',' ','D','E','A','D',0};
254     static const WCHAR fmtid_adjpidW[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
255                                           '1','2','3','4','-','1','2','3','4','-',
256                                           '1','2','3','4','5','6','7','8','9','0','1','2','}','1','3','5','7','9',0};
257     static const WCHAR fmtid_spacespidW[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
258                                              '1','2','3','4','-','1','2','3','4','-',
259                                              '1','2','3','4','5','6','7','8','9','0','1','2','}',' ',' ',' ','1','3','5','7','9',0};
260     static const WCHAR fmtid_negpidW[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
261                                           '1','2','3','4','-','1','2','3','4','-',
262                                           '1','2','3','4','5','6','7','8','9','0','1','2','}',' ','-','1','3','5','7','9',0};
263     static const WCHAR fmtid_negnegpidW[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
264                                              '1','2','3','4','-','1','2','3','4','-',
265                                              '1','2','3','4','5','6','7','8','9','0','1','2','}',' ','-','-','1','3','5','7','9',0};
266     static const WCHAR fmtid_negnegnegpidW[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
267                                                 '1','2','3','4','-','1','2','3','4','-',
268                                                 '1','2','3','4','5','6','7','8','9','0','1','2','}',' ','-','-','-','1','3','5','7','9',0};
269     static const WCHAR fmtid_negspacepidW[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
270                                                '1','2','3','4','-','1','2','3','4','-',
271                                                '1','2','3','4','5','6','7','8','9','0','1','2','}',' ','-',' ','1','3','5','7','9',0};
272     static const WCHAR fmtid_negspacenegpidW[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
273                                                '1','2','3','4','-','1','2','3','4','-',
274                                                '1','2','3','4','5','6','7','8','9','0','1','2','}',' ','-',' ','-','1','3','5','7','9',0};
275     static const WCHAR fmtid_negspacespidW[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
276                                                '1','2','3','4','-','1','2','3','4','-',
277                                                '1','2','3','4','5','6','7','8','9','0','1','2','}',' ','-',' ','-',' ','-','1','3','5','7','9',0};
278     static const WCHAR fmtid_pospidW[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
279                                           '1','2','3','4','-','1','2','3','4','-',
280                                           '1','2','3','4','5','6','7','8','9','0','1','2','}',' ','+','1','3','5','7','9',0};
281     static const WCHAR fmtid_posnegpidW[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
282                                              '1','2','3','4','-','1','2','3','4','-',
283                                              '1','2','3','4','5','6','7','8','9','0','1','2','}',' ','+','-','+','-','1','3','5','7','9',0};
284     static const WCHAR fmtid_symbolpidW[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
285                                              '1','2','3','4','-','1','2','3','4','-',
286                                              '1','2','3','4','5','6','7','8','9','0','1','2','}',' ','+','/','$','-','1','3','5','7','9',0};
287     static const WCHAR fmtid_letterpidW[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
288                                              '1','2','3','4','-','1','2','3','4','-',
289                                              '1','2','3','4','5','6','7','8','9','0','1','2','}',' ','A','B','C','D','1','3','5','7','9',0};
290     static const WCHAR fmtid_spacepadpidW[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
291                                                '1','2','3','4','-','1','2','3','4','-',
292                                                '1','2','3','4','5','6','7','8','9','0','1','2','}',' ','1','3','5','7','9',' ',' ',' ',0};
293     static const WCHAR fmtid_spacemixpidW[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
294                                                '1','2','3','4','-','1','2','3','4','-',
295                                                '1','2','3','4','5','6','7','8','9','0','1','2','}',' ','1',' ','3',' ','5','7','9',' ',' ',' ',0};
296     static const WCHAR fmtid_tabpidW[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
297                                           '1','2','3','4','-','1','2','3','4','-',
298                                           '1','2','3','4','5','6','7','8','9','0','1','2','}','\t','1','3','5','7','9',0};
299     static const WCHAR fmtid_hexpidW[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
300                                           '1','2','3','4','-','1','2','3','4','-',
301                                           '1','2','3','4','5','6','7','8','9','0','1','2','}',' ','0','x','D','E','A','D',0};
302     static const WCHAR fmtid_mixedpidW[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
303                                             '1','2','3','4','-','1','2','3','4','-',
304                                             '1','2','3','4','5','6','7','8','9','0','1','2','}',' ','A','9','B','5','C','3','D','1',0};
305     static const WCHAR fmtid_overflowpidW[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
306                                                '1','2','3','4','-','1','2','3','4','-',
307                                                '1','2','3','4','5','6','7','8','9','0','1','2','}',' ','1','2','3','4','5','6','7','8','9','0','1',0};
308     static const WCHAR fmtid_commapidW[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
309                                              '1','2','3','4','-','1','2','3','4','-',
310                                              '1','2','3','4','5','6','7','8','9','0','1','2','}',',','1','3','5','7','9',0};
311     static const WCHAR fmtid_commaspidW[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
312                                              '1','2','3','4','-','1','2','3','4','-',
313                                              '1','2','3','4','5','6','7','8','9','0','1','2','}',',',',',',','1','3','5','7','9',0};
314     static const WCHAR fmtid_commaspacepidW[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
315                                                  '1','2','3','4','-','1','2','3','4','-',
316                                                  '1','2','3','4','5','6','7','8','9','0','1','2','}',',',' ','1','3','5','7','9',0};
317     static const WCHAR fmtid_spacecommapidW[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
318                                                  '1','2','3','4','-','1','2','3','4','-',
319                                                  '1','2','3','4','5','6','7','8','9','0','1','2','}',' ',',','1','3','5','7','9',0};
320     static const WCHAR fmtid_spccommaspcpidW[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
321                                                   '1','2','3','4','-','1','2','3','4','-',
322                                                   '1','2','3','4','5','6','7','8','9','0','1','2','}',' ',',',' ','1','3','5','7','9',0};
323     static const WCHAR fmtid_spacescommaspidW[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
324                                                    '1','2','3','4','-','1','2','3','4','-',
325                                                    '1','2','3','4','5','6','7','8','9','0','1','2','}',' ',',',' ',',','1','3','5','7','9',0};
326     static const WCHAR fmtid_commanegpidW[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
327                                                '1','2','3','4','-','1','2','3','4','-',
328                                                '1','2','3','4','5','6','7','8','9','0','1','2','}',',','-','1','3','5','7','9',0};
329     static const WCHAR fmtid_spccommanegpidW[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
330                                                '1','2','3','4','-','1','2','3','4','-',
331                                                '1','2','3','4','5','6','7','8','9','0','1','2','}',' ',',','-','1','3','5','7','9',0};
332     static const WCHAR fmtid_commaspcnegpidW[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
333                                                '1','2','3','4','-','1','2','3','4','-',
334                                                '1','2','3','4','5','6','7','8','9','0','1','2','}',',',' ','-','1','3','5','7','9',0};
335     static const WCHAR fmtid_spccommaspcnegpidW[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
336                                                '1','2','3','4','-','1','2','3','4','-',
337                                                '1','2','3','4','5','6','7','8','9','0','1','2','}',' ',',',' ','-','1','3','5','7','9',0};
338     static const WCHAR fmtid_commanegspcpidW[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
339                                                '1','2','3','4','-','1','2','3','4','-',
340                                                '1','2','3','4','5','6','7','8','9','0','1','2','}',',','-',' ','1','3','5','7','9',0};
341     static const WCHAR fmtid_negcommapidW[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
342                                                '1','2','3','4','-','1','2','3','4','-',
343                                                '1','2','3','4','5','6','7','8','9','0','1','2','}','-',',','1','3','5','7','9',0};
344     static const WCHAR fmtid_normalpidW[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-',
345                                              '1','2','3','4','-','1','2','3','4','-',
346                                              '1','2','3','4','5','6','7','8','9','0','1','2','}',' ','1','3','5','7','9',0};
347     PROPERTYKEY out_init = {dummy_guid, 0xdeadbeef};
348     PROPERTYKEY out;
349     HRESULT ret;
350     char guid_buf[40], guid_buf2[40];
351
352     const struct
353     {
354         LPCWSTR pwzString;
355         PROPERTYKEY *pkey;
356         HRESULT hr_expect;
357         PROPERTYKEY pkey_expect;
358     } testcases[] =
359     {
360         {NULL, NULL, E_POINTER},
361         {NULL, &out, E_POINTER, out_init},
362         {emptyW, NULL, E_POINTER},
363         {emptyW, &out, E_INVALIDARG, {GUID_NULL, 0}},
364         {fmtid_clsidW, &out, E_INVALIDARG, {GUID_NULL, 0}},
365         {fmtid_truncatedW, &out, E_INVALIDARG, { {0x12345678,0x1234,0x1234,{0,0,0,0,0,0,0,0}}, 0}},
366         {fmtid_nobracketsW, &out, E_INVALIDARG, {GUID_NULL, 0}},
367         {fmtid_badbracketW, &out, E_INVALIDARG, {GUID_NULL, 0}},
368         {fmtid_badcharW, &out, E_INVALIDARG, {GUID_NULL, 0}},
369         {fmtid_badchar2W, &out, E_INVALIDARG, {GUID_NULL, 0}},
370         {fmtid_baddashW, &out, E_INVALIDARG, { {0x12345678,0,0,{0,0,0,0,0,0,0,0}}, 0}},
371         {fmtid_badchar3W, &out, E_INVALIDARG, { {0x12345678,0,0,{0,0,0,0,0,0,0,0}}, 0}},
372         {fmtid_badchar4W, &out, E_INVALIDARG, { {0x12345678,0,0,{0,0,0,0,0,0,0,0}}, 0}},
373         {fmtid_baddash2W, &out, E_INVALIDARG, { {0x12345678,0,0,{0,0,0,0,0,0,0,0}}, 0}},
374         {fmtid_badchar5W, &out, E_INVALIDARG, { {0x12345678,0x1234,0,{0,0,0,0,0,0,0,0}}, 0}},
375         {fmtid_badchar6W, &out, E_INVALIDARG, { {0x12345678,0x1234,0,{0,0,0,0,0,0,0,0}}, 0}},
376         {fmtid_baddash3W, &out, E_INVALIDARG, { {0x12345678,0x1234,0,{0,0,0,0,0,0,0,0}}, 0}},
377         {fmtid_badchar7W, &out, E_INVALIDARG, { {0x12345678,0x1234,0x1234,{0,0,0,0,0,0,0,0}}, 0}},
378         {fmtid_badchar8W, &out, E_INVALIDARG, { {0x12345678,0x1234,0x1234,{0x12,0,0,0,0,0,0,0}}, 0}},
379         {fmtid_baddash4W, &out, E_INVALIDARG, { {0x12345678,0x1234,0x1234,{0x12,0,0,0,0,0,0,0}}, 0}},
380         {fmtid_badchar9W, &out, E_INVALIDARG, { {0x12345678,0x1234,0x1234,{0x12,0x34,0,0,0,0,0,0}}, 0}},
381         {fmtid_badchar9_adjW, &out, E_INVALIDARG, { {0x12345678,0x1234,0x1234,{0x12,0x34,0,0,0,0,0,0}}, 0}},
382         {fmtid_badchar10W, &out, E_INVALIDARG, { {0x12345678,0x1234,0x1234,{0x12,0x34,0x12,0,0,0,0,0}}, 0}},
383         {fmtid_badchar11W, &out, E_INVALIDARG, { {0x12345678,0x1234,0x1234,{0x12,0x34,0x12,0x34,0,0,0,0}}, 0}},
384         {fmtid_badchar12W, &out, E_INVALIDARG, { {0x12345678,0x1234,0x1234,{0x12,0x34,0x12,0x34,0x56,0,0,0}}, 0}},
385         {fmtid_badchar13W, &out, E_INVALIDARG, { {0x12345678,0x1234,0x1234,{0x12,0x34,0x12,0x34,0x56,0x78,0,0}}, 0}},
386         {fmtid_badchar14W, &out, E_INVALIDARG, { {0x12345678,0x1234,0x1234,{0x12,0x34,0x12,0x34,0x56,0x78,0x90,0}}, 0}},
387         {fmtid_badbracket2W, &out, E_INVALIDARG, { {0x12345678,0x1234,0x1234,{0x12,0x34,0x12,0x34,0x56,0x78,0x90,0x00}}, 0 }},
388         {fmtid_spaceW, &out, E_INVALIDARG, {GUID_NULL, 0 }},
389         {fmtid_spaceendW, &out, E_INVALIDARG, {expect_guid, 0}},
390         {fmtid_spacesendW, &out, E_INVALIDARG, {expect_guid, 0}},
391         {fmtid_nopidW, &out, E_INVALIDARG, {expect_guid, 0}},
392         {fmtid_badpidW, &out, S_OK, {expect_guid, 0}},
393         {fmtid_adjpidW, &out, S_OK, {expect_guid, 13579}},
394         {fmtid_spacespidW, &out, S_OK, {expect_guid, 13579}},
395         {fmtid_negpidW, &out, S_OK, {expect_guid, 13579}},
396         {fmtid_negnegpidW, &out, S_OK, {expect_guid, 4294953717U}},
397         {fmtid_negnegnegpidW, &out, S_OK, {expect_guid, 0}},
398         {fmtid_negspacepidW, &out, S_OK, {expect_guid, 13579}},
399         {fmtid_negspacenegpidW, &out, S_OK, {expect_guid, 4294953717U}},
400         {fmtid_negspacespidW, &out, S_OK, {expect_guid, 0}},
401         {fmtid_pospidW, &out, S_OK, {expect_guid, 0}},
402         {fmtid_posnegpidW, &out, S_OK, {expect_guid, 0}},
403         {fmtid_symbolpidW, &out, S_OK, {expect_guid, 0}},
404         {fmtid_letterpidW, &out, S_OK, {expect_guid, 0}},
405         {fmtid_spacepadpidW, &out, S_OK, {expect_guid, 13579}},
406         {fmtid_spacemixpidW, &out, S_OK, {expect_guid, 1}},
407         {fmtid_tabpidW, &out, S_OK, {expect_guid, 0}},
408         {fmtid_hexpidW, &out, S_OK, {expect_guid, 0}},
409         {fmtid_mixedpidW, &out, S_OK, {expect_guid, 0}},
410         {fmtid_overflowpidW, &out, S_OK, {expect_guid, 3755744309U}},
411         {fmtid_commapidW, &out, S_OK, {expect_guid, 13579}},
412         {fmtid_commaspidW, &out, S_OK, {expect_guid, 0}},
413         {fmtid_commaspacepidW, &out, S_OK, {expect_guid, 13579}},
414         {fmtid_spacecommapidW, &out, S_OK, {expect_guid, 13579}},
415         {fmtid_spccommaspcpidW, &out, S_OK, {expect_guid, 13579}},
416         {fmtid_spacescommaspidW, &out, S_OK, {expect_guid, 0}},
417         {fmtid_commanegpidW, &out, S_OK, {expect_guid, 4294953717U}},
418         {fmtid_spccommanegpidW, &out, S_OK, {expect_guid, 4294953717U}},
419         {fmtid_commaspcnegpidW, &out, S_OK, {expect_guid, 4294953717U}},
420         {fmtid_spccommaspcnegpidW, &out, S_OK, {expect_guid, 4294953717U}},
421         {fmtid_commanegspcpidW, &out, S_OK, {expect_guid, 0U}},
422         {fmtid_negcommapidW, &out, S_OK, {expect_guid, 0}},
423         {fmtid_normalpidW, &out, S_OK, {expect_guid, 13579}},
424     };
425
426     int i;
427
428     for (i = 0; i < sizeof(testcases)/sizeof(testcases[0]); i++)
429     {
430         if (testcases[i].pkey)
431             *testcases[i].pkey = out_init;
432
433         ret = PSPropertyKeyFromString(testcases[i].pwzString, testcases[i].pkey);
434         ok(ret == testcases[i].hr_expect,
435            "[%d] Expected PSPropertyKeyFromString to return 0x%08x, got 0x%08x\n",
436            i, testcases[i].hr_expect, ret);
437
438         if (testcases[i].pkey)
439         {
440             ok(IsEqualGUID(&testcases[i].pkey->fmtid, &testcases[i].pkey_expect.fmtid),
441                "[%d] Expected GUID %s, got %s\n",
442                i, show_guid(&testcases[i].pkey_expect.fmtid, guid_buf), show_guid(&testcases[i].pkey->fmtid, guid_buf2));
443             ok(testcases[i].pkey->pid == testcases[i].pkey_expect.pid,
444                "[%d] Expected property ID %u, got %u\n",
445                i, testcases[i].pkey_expect.pid, testcases[i].pkey->pid);
446         }
447     }
448 }
449
450 static void test_PSRefreshPropertySchema(void)
451 {
452     HRESULT ret;
453
454     ret = PSRefreshPropertySchema();
455     todo_wine
456     ok(ret == CO_E_NOTINITIALIZED,
457        "Expected PSRefreshPropertySchema to return CO_E_NOTINITIALIZED, got 0x%08x\n", ret);
458
459     CoInitialize(NULL);
460
461     ret = PSRefreshPropertySchema();
462     ok(ret == S_OK,
463        "Expected PSRefreshPropertySchema to return S_OK, got 0x%08x\n", ret);
464
465     CoUninitialize();
466 }
467
468 static void test_InitPropVariantFromGUIDAsString(void)
469 {
470     PROPVARIANT propvar;
471     VARIANT var;
472     HRESULT hres;
473     int i;
474
475     const struct {
476         REFGUID guid;
477         const char *str;
478     } testcases[] = {
479         {&IID_NULL,             "{00000000-0000-0000-0000-000000000000}" },
480         {&dummy_guid,           "{DEADBEEF-DEAD-BEEF-DEAD-BEEFCAFEBABE}" },
481     };
482
483     hres = InitPropVariantFromGUIDAsString(NULL, &propvar);
484     ok(hres == E_FAIL, "InitPropVariantFromGUIDAsString returned %x\n", hres);
485
486     if(0) {
487         /* Returns strange data on Win7, crashes on older systems */
488         InitVariantFromGUIDAsString(NULL, &var);
489
490         /* Crashes on windows */
491         InitPropVariantFromGUIDAsString(&IID_NULL, NULL);
492         InitVariantFromGUIDAsString(&IID_NULL, NULL);
493     }
494
495     for(i=0; i<sizeof(testcases)/sizeof(testcases[0]); i++) {
496         memset(&propvar, 0, sizeof(PROPVARIANT));
497         hres = InitPropVariantFromGUIDAsString(testcases[i].guid, &propvar);
498         ok(hres == S_OK, "%d) InitPropVariantFromGUIDAsString returned %x\n", i, hres);
499         ok(propvar.vt == VT_LPWSTR, "%d) propvar.vt = %d\n", i, propvar.vt);
500         ok(!strcmp_wa(propvar.u.pwszVal, testcases[i].str), "%d) propvar.u.pwszVal = %s\n",
501                 i, wine_dbgstr_w(propvar.u.pwszVal));
502         CoTaskMemFree(propvar.u.pwszVal);
503
504         memset(&var, 0, sizeof(VARIANT));
505         hres = InitVariantFromGUIDAsString(testcases[i].guid, &var);
506         ok(hres == S_OK, "%d) InitVariantFromGUIDAsString returned %x\n", i, hres);
507         ok(V_VT(&var) == VT_BSTR, "%d) V_VT(&var) = %d\n", i, V_VT(&var));
508         ok(SysStringLen(V_BSTR(&var)) == 38, "SysStringLen returned %d\n",
509                 SysStringLen(V_BSTR(&var)));
510         ok(!strcmp_wa(V_BSTR(&var), testcases[i].str), "%d) V_BSTR(&var) = %s\n",
511                 i, wine_dbgstr_w(V_BSTR(&var)));
512         VariantClear(&var);
513     }
514 }
515
516 static void test_InitPropVariantFromBuffer(void)
517 {
518     static const char data_in[] = "test";
519     PROPVARIANT propvar;
520     VARIANT var;
521     HRESULT hres;
522     void *data_out;
523     LONG size;
524
525     hres = InitPropVariantFromBuffer(NULL, 0, &propvar);
526     ok(hres == S_OK, "InitPropVariantFromBuffer returned %x\n", hres);
527     ok(propvar.vt == (VT_VECTOR|VT_UI1), "propvar.vt = %d\n", propvar.vt);
528     ok(propvar.u.caub.cElems == 0, "cElems = %d\n", propvar.u.caub.cElems == 0);
529     PropVariantClear(&propvar);
530
531     hres = InitPropVariantFromBuffer(data_in, 4, &propvar);
532     ok(hres == S_OK, "InitPropVariantFromBuffer returned %x\n", hres);
533     ok(propvar.vt == (VT_VECTOR|VT_UI1), "propvar.vt = %d\n", propvar.vt);
534     ok(propvar.u.caub.cElems == 4, "cElems = %d\n", propvar.u.caub.cElems == 0);
535     ok(!memcmp(propvar.u.caub.pElems, data_in, 4), "Data inside array is incorrect\n");
536     PropVariantClear(&propvar);
537
538     hres = InitVariantFromBuffer(NULL, 0, &var);
539     ok(hres == S_OK, "InitVariantFromBuffer returned %x\n", hres);
540     ok(V_VT(&var) == (VT_ARRAY|VT_UI1), "V_VT(&var) = %d\n", V_VT(&var));
541     size = SafeArrayGetDim(V_ARRAY(&var));
542     ok(size == 1, "SafeArrayGetDim returned %d\n", size);
543     hres = SafeArrayGetLBound(V_ARRAY(&var), 1, &size);
544     ok(hres == S_OK, "SafeArrayGetLBound returned %x\n", hres);
545     ok(size == 0, "LBound = %d\n", size);
546     hres = SafeArrayGetUBound(V_ARRAY(&var), 1, &size);
547     ok(hres == S_OK, "SafeArrayGetUBound returned %x\n", hres);
548     ok(size == -1, "UBound = %d\n", size);
549     VariantClear(&var);
550
551     hres = InitVariantFromBuffer(data_in, 4, &var);
552     ok(hres == S_OK, "InitVariantFromBuffer returned %x\n", hres);
553     ok(V_VT(&var) == (VT_ARRAY|VT_UI1), "V_VT(&var) = %d\n", V_VT(&var));
554     size = SafeArrayGetDim(V_ARRAY(&var));
555     ok(size == 1, "SafeArrayGetDim returned %d\n", size);
556     hres = SafeArrayGetLBound(V_ARRAY(&var), 1, &size);
557     ok(hres == S_OK, "SafeArrayGetLBound returned %x\n", hres);
558     ok(size == 0, "LBound = %d\n", size);
559     hres = SafeArrayGetUBound(V_ARRAY(&var), 1, &size);
560     ok(hres == S_OK, "SafeArrayGetUBound returned %x\n", hres);
561     ok(size == 3, "UBound = %d\n", size);
562     hres = SafeArrayAccessData(V_ARRAY(&var), &data_out);
563     ok(hres == S_OK, "SafeArrayAccessData failed %x\n", hres);
564     ok(!memcmp(data_in, data_out, 4), "Data inside safe array is incorrect\n");
565     hres = SafeArrayUnaccessData(V_ARRAY(&var));
566     ok(hres == S_OK, "SafeArrayUnaccessData failed %x\n", hres);
567     VariantClear(&var);
568 }
569
570 static void test_PropVariantToGUID(void)
571 {
572     PROPVARIANT propvar;
573     VARIANT var;
574     GUID guid;
575     HRESULT hres;
576
577     hres = InitPropVariantFromGUIDAsString(&IID_NULL, &propvar);
578     ok(hres == S_OK, "InitPropVariantFromGUIDAsString failed %x\n", hres);
579
580     hres = PropVariantToGUID(&propvar, &guid);
581     ok(hres == S_OK, "PropVariantToGUID failed %x\n", hres);
582     ok(!memcmp(&IID_NULL, &guid, sizeof(GUID)), "incorrect GUID created: %s\n", show_guid(&guid, NULL));
583     PropVariantClear(&propvar);
584
585     hres = InitPropVariantFromGUIDAsString(&dummy_guid, &propvar);
586     ok(hres == S_OK, "InitPropVariantFromGUIDAsString failed %x\n", hres);
587
588     hres = PropVariantToGUID(&propvar, &guid);
589     ok(hres == S_OK, "PropVariantToGUID failed %x\n", hres);
590     ok(!memcmp(&dummy_guid, &guid, sizeof(GUID)), "incorrect GUID created: %s\n", show_guid(&guid, NULL));
591
592     ok(propvar.vt == VT_LPWSTR, "incorrect PROPVARIANT type: %d\n", propvar.vt);
593     propvar.u.pwszVal[1] = 'd';
594     propvar.u.pwszVal[2] = 'E';
595     propvar.u.pwszVal[3] = 'a';
596     hres = PropVariantToGUID(&propvar, &guid);
597     ok(hres == S_OK, "PropVariantToGUID failed %x\n", hres);
598     ok(!memcmp(&dummy_guid, &guid, sizeof(GUID)), "incorrect GUID created: %s\n", show_guid(&guid, NULL));
599
600     propvar.u.pwszVal[1] = 'z';
601     hres = PropVariantToGUID(&propvar, &guid);
602     ok(hres == E_INVALIDARG, "PropVariantToGUID returned %x\n", hres);
603     PropVariantClear(&propvar);
604
605
606     hres = InitVariantFromGUIDAsString(&IID_NULL, &var);
607     ok(hres == S_OK, "InitVariantFromGUIDAsString failed %x\n", hres);
608
609     hres = VariantToGUID(&var, &guid);
610     ok(hres == S_OK, "VariantToGUID failed %x\n", hres);
611     ok(!memcmp(&IID_NULL, &guid, sizeof(GUID)), "incorrect GUID created: %s\n", show_guid(&guid, NULL));
612     VariantClear(&var);
613
614     hres = InitVariantFromGUIDAsString(&dummy_guid, &var);
615     ok(hres == S_OK, "InitVariantFromGUIDAsString failed %x\n", hres);
616
617     hres = VariantToGUID(&var, &guid);
618     ok(hres == S_OK, "VariantToGUID failed %x\n", hres);
619     ok(!memcmp(&dummy_guid, &guid, sizeof(GUID)), "incorrect GUID created: %s\n", show_guid(&guid, NULL));
620
621     ok(V_VT(&var) == VT_BSTR, "incorrect VARIANT type: %d\n", V_VT(&var));
622     V_BSTR(&var)[1] = 'z';
623     hres = VariantToGUID(&var, &guid);
624     ok(hres == E_FAIL, "VariantToGUID returned %x\n", hres);
625
626     V_BSTR(&var)[1] = 'd';
627     propvar.vt = V_VT(&var);
628     propvar.u.bstrVal = V_BSTR(&var);
629     V_VT(&var) = VT_EMPTY;
630     hres = PropVariantToGUID(&propvar, &guid);
631     ok(hres == S_OK, "PropVariantToGUID failed %x\n", hres);
632     ok(!memcmp(&dummy_guid, &guid, sizeof(GUID)), "incorrect GUID created: %s\n", show_guid(&guid, NULL));
633     PropVariantClear(&propvar);
634 }
635
636 static void test_PropVariantCompare(void)
637 {
638     PROPVARIANT empty, null, emptyarray, i2_0, i2_2, i4_large, i4_largeneg, i4_2, str_2, str_02, str_b;
639     INT res;
640     static const WCHAR str_2W[] = {'2', 0};
641     static const WCHAR str_02W[] = {'0', '2', 0};
642     static const WCHAR str_bW[] = {'b', 0};
643     SAFEARRAY emptysafearray;
644
645     PropVariantInit(&empty);
646     PropVariantInit(&null);
647     PropVariantInit(&emptyarray);
648     PropVariantInit(&i2_0);
649     PropVariantInit(&i2_2);
650     PropVariantInit(&i4_large);
651     PropVariantInit(&i4_largeneg);
652     PropVariantInit(&i4_2);
653     PropVariantInit(&str_2);
654     PropVariantInit(&str_b);
655
656     empty.vt = VT_EMPTY;
657     null.vt = VT_NULL;
658     emptyarray.vt = VT_ARRAY | VT_I4;
659     emptyarray.u.parray = &emptysafearray;
660     emptysafearray.cDims = 1;
661     emptysafearray.fFeatures = FADF_FIXEDSIZE;
662     emptysafearray.cbElements = 4;
663     emptysafearray.cLocks = 0;
664     emptysafearray.pvData = NULL;
665     emptysafearray.rgsabound[0].cElements = 0;
666     emptysafearray.rgsabound[0].lLbound = 0;
667     i2_0.vt = VT_I2;
668     i2_0.u.iVal = 0;
669     i2_2.vt = VT_I2;
670     i2_2.u.iVal = 2;
671     i4_large.vt = VT_I4;
672     i4_large.u.lVal = 65536;
673     i4_largeneg.vt = VT_I4;
674     i4_largeneg.u.lVal = -65536;
675     i4_2.vt = VT_I4;
676     i4_2.u.lVal = 2;
677     str_2.vt = VT_BSTR;
678     str_2.u.bstrVal = SysAllocString(str_2W);
679     str_02.vt = VT_BSTR;
680     str_02.u.bstrVal = SysAllocString(str_02W);
681     str_b.vt = VT_BSTR;
682     str_b.u.bstrVal = SysAllocString(str_bW);
683
684     res = PropVariantCompareEx(&empty, &empty, 0, 0);
685     ok(res == 0, "res=%i\n", res);
686
687     res = PropVariantCompareEx(&empty, &null, 0, 0);
688     ok(res == 0, "res=%i\n", res);
689
690     res = PropVariantCompareEx(&null, &emptyarray, 0, 0);
691     ok(res == 0, "res=%i\n", res);
692
693     res = PropVariantCompareEx(&null, &i2_0, 0, 0);
694     ok(res == -1, "res=%i\n", res);
695
696     res = PropVariantCompareEx(&i2_0, &null, 0, 0);
697     ok(res == 1, "res=%i\n", res);
698
699     res = PropVariantCompareEx(&null, &i2_0, 0, PVCF_TREATEMPTYASGREATERTHAN);
700     ok(res == 1, "res=%i\n", res);
701
702     res = PropVariantCompareEx(&i2_0, &null, 0, PVCF_TREATEMPTYASGREATERTHAN);
703     ok(res == -1, "res=%i\n", res);
704
705     res = PropVariantCompareEx(&i2_2, &i2_0, 0, 0);
706     ok(res == 1, "res=%i\n", res);
707
708     res = PropVariantCompareEx(&i2_0, &i2_2, 0, 0);
709     ok(res == -1, "res=%i\n", res);
710
711     /* Always return -1 if second value cannot be converted to first type */
712     res = PropVariantCompareEx(&i2_0, &i4_large, 0, 0);
713     ok(res == -1, "res=%i\n", res);
714
715     res = PropVariantCompareEx(&i2_0, &i4_largeneg, 0, 0);
716     ok(res == -1, "res=%i\n", res);
717
718     res = PropVariantCompareEx(&i4_large, &i2_0, 0, 0);
719     ok(res == 1, "res=%i\n", res);
720
721     res = PropVariantCompareEx(&i4_largeneg, &i2_0, 0, 0);
722     ok(res == -1, "res=%i\n", res);
723
724     res = PropVariantCompareEx(&i2_2, &i4_2, 0, 0);
725     ok(res == 0, "res=%i\n", res);
726
727     res = PropVariantCompareEx(&i2_2, &str_2, 0, 0);
728     todo_wine ok(res == 0, "res=%i\n", res);
729
730     res = PropVariantCompareEx(&i2_2, &str_02, 0, 0);
731     todo_wine ok(res == 0, "res=%i\n", res);
732
733     res = PropVariantCompareEx(&str_2, &i2_2, 0, 0);
734     todo_wine ok(res == 0, "res=%i\n", res);
735
736     res = PropVariantCompareEx(&str_02, &i2_2, 0, 0);
737     ok(res == -1, "res=%i\n", res);
738
739     res = PropVariantCompareEx(&str_02, &str_2, 0, 0);
740     ok(res == -1, "res=%i\n", res);
741
742     res = PropVariantCompareEx(&str_02, &str_b, 0, 0);
743     ok(res == -1, "res=%i\n", res);
744
745     res = PropVariantCompareEx(&str_2, &str_02, 0, 0);
746     ok(res == 1, "res=%i\n", res);
747
748     res = PropVariantCompareEx(&i4_large, &str_b, 0, 0);
749     todo_wine ok(res == -5 /* ??? */, "res=%i\n", res);
750
751     SysFreeString(str_2.u.bstrVal);
752     SysFreeString(str_02.u.bstrVal);
753     SysFreeString(str_b.u.bstrVal);
754 }
755
756 static inline const char* debugstr_longlong(ULONGLONG ll)
757 {
758     static char string[17];
759     if (sizeof(ll) > sizeof(unsigned long) && ll >> 32)
760         sprintf(string, "%lx%08lx", (unsigned long)(ll >> 32), (unsigned long)ll);
761     else
762         sprintf(string, "%lx", (unsigned long)ll);
763     return string;
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 = (LONGLONG)1 << 63;
786
787     hr = PropVariantToInt64(&propvar, &llval);
788     ok(hr == S_OK, "hr=%x\n", hr);
789     ok(llval == (LONGLONG)1 << 63, "got wrong value %s\n", debugstr_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", debugstr_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", debugstr_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", debugstr_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", debugstr_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", debugstr_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", debugstr_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", debugstr_longlong(llval));
884 }
885
886 START_TEST(propsys)
887 {
888     test_PSStringFromPropertyKey();
889     test_PSPropertyKeyFromString();
890     test_PSRefreshPropertySchema();
891     test_InitPropVariantFromGUIDAsString();
892     test_InitPropVariantFromBuffer();
893     test_PropVariantToGUID();
894     test_PropVariantCompare();
895     test_intconversions();
896 }