urlmon: Some IUri's don't display the default port in the authority.
[wine] / dlls / urlmon / tests / uri.c
1 /*
2  * UrlMon IUri tests
3  *
4  * Copyright 2010 Thomas Mullaly
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #include <wine/test.h>
22 #include <stdarg.h>
23 #include <stddef.h>
24
25 #define COBJMACROS
26
27 #include "windef.h"
28 #include "winbase.h"
29 #include "urlmon.h"
30 #include "shlwapi.h"
31
32 #define URI_STR_PROPERTY_COUNT Uri_PROPERTY_STRING_LAST+1
33 #define URI_DWORD_PROPERTY_COUNT (Uri_PROPERTY_DWORD_LAST - Uri_PROPERTY_DWORD_START)+1
34 #define URI_BUILDER_STR_PROPERTY_COUNT 7
35
36 static HRESULT (WINAPI *pCreateUri)(LPCWSTR, DWORD, DWORD_PTR, IUri**);
37 static HRESULT (WINAPI *pCreateUriWithFragment)(LPCWSTR, LPCWSTR, DWORD, DWORD_PTR, IUri**);
38 static HRESULT (WINAPI *pCreateIUriBuilder)(IUri*, DWORD, DWORD_PTR, IUriBuilder**);
39 static HRESULT (WINAPI *pCoInternetCombineIUri)(IUri*,IUri*,DWORD,IUri**,DWORD_PTR);
40
41 static const WCHAR http_urlW[] = { 'h','t','t','p',':','/','/','w','w','w','.','w','i','n','e','h','q',
42         '.','o','r','g','/',0};
43 static const WCHAR http_url_fragW[] = { 'h','t','t','p',':','/','/','w','w','w','.','w','i','n','e','h','q',
44         '.','o','r','g','/','#','F','r','a','g',0};
45
46 typedef struct _uri_create_flag_test {
47     DWORD   flags;
48     HRESULT expected;
49 } uri_create_flag_test;
50
51 static const uri_create_flag_test invalid_flag_tests[] = {
52     /* Set of invalid flag combinations to test for. */
53     {Uri_CREATE_DECODE_EXTRA_INFO | Uri_CREATE_NO_DECODE_EXTRA_INFO, E_INVALIDARG},
54     {Uri_CREATE_CANONICALIZE | Uri_CREATE_NO_CANONICALIZE, E_INVALIDARG},
55     {Uri_CREATE_CRACK_UNKNOWN_SCHEMES | Uri_CREATE_NO_CRACK_UNKNOWN_SCHEMES, E_INVALIDARG},
56     {Uri_CREATE_PRE_PROCESS_HTML_URI | Uri_CREATE_NO_PRE_PROCESS_HTML_URI, E_INVALIDARG},
57     {Uri_CREATE_IE_SETTINGS | Uri_CREATE_NO_IE_SETTINGS, E_INVALIDARG}
58 };
59
60 typedef struct _uri_str_property {
61     const char* value;
62     HRESULT     expected;
63     BOOL        todo;
64     const char* broken_value;
65 } uri_str_property;
66
67 typedef struct _uri_dword_property {
68     DWORD   value;
69     HRESULT expected;
70     BOOL    todo;
71 } uri_dword_property;
72
73 typedef struct _uri_properties {
74     const char*         uri;
75     DWORD               create_flags;
76     HRESULT             create_expected;
77     BOOL                create_todo;
78     DWORD               props;
79     BOOL                props_todo;
80
81     uri_str_property    str_props[URI_STR_PROPERTY_COUNT];
82     uri_dword_property  dword_props[URI_DWORD_PROPERTY_COUNT];
83 } uri_properties;
84
85 static const uri_properties uri_tests[] = {
86     {   "http://www.winehq.org/tests/../tests/../..", 0, S_OK, FALSE,
87         /* A flag bitmap containing all the Uri_HAS_* flags that correspond to this uri. */
88         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_HOST|
89         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|
90         Uri_HAS_PORT|Uri_HAS_SCHEME,
91         FALSE,
92         {
93             {"http://www.winehq.org/",S_OK,FALSE},                      /* ABSOLUTE_URI */
94             {"www.winehq.org",S_OK,FALSE},                              /* AUTHORITY */
95             {"http://www.winehq.org/",S_OK,FALSE},                      /* DISPLAY_URI */
96             {"winehq.org",S_OK,FALSE},                                  /* DOMAIN */
97             {"",S_FALSE,FALSE},                                         /* EXTENSION */
98             {"",S_FALSE,FALSE},                                         /* FRAGMENT */
99             {"www.winehq.org",S_OK,FALSE},                              /* HOST */
100             {"",S_FALSE,FALSE},                                         /* PASSWORD */
101             {"/",S_OK,FALSE},                                           /* PATH */
102             {"/",S_OK,FALSE},                                           /* PATH_AND_QUERY */
103             {"",S_FALSE,FALSE},                                         /* QUERY */
104             {"http://www.winehq.org/tests/../tests/../..",S_OK,FALSE},  /* RAW_URI */
105             {"http",S_OK,FALSE},                                        /* SCHEME_NAME */
106             {"",S_FALSE,FALSE},                                         /* USER_INFO */
107             {"",S_FALSE,FALSE}                                          /* USER_NAME */
108         },
109         {
110             {Uri_HOST_DNS,S_OK,FALSE},                                  /* HOST_TYPE */
111             {80,S_OK,FALSE},                                            /* PORT */
112             {URL_SCHEME_HTTP,S_OK,FALSE},                               /* SCHEME */
113             {URLZONE_INVALID,E_NOTIMPL,FALSE}                           /* ZONE */
114         }
115     },
116     {   "http://winehq.org/tests/.././tests", 0, S_OK, FALSE,
117         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_HOST|
118         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|
119         Uri_HAS_PORT|Uri_HAS_SCHEME,
120         FALSE,
121         {
122             {"http://winehq.org/tests",S_OK,FALSE},
123             {"winehq.org",S_OK,FALSE},
124             {"http://winehq.org/tests",S_OK,FALSE},
125             {"winehq.org",S_OK,FALSE},
126             {"",S_FALSE,FALSE},
127             {"",S_FALSE,FALSE},
128             {"winehq.org",S_OK,FALSE},
129             {"",S_FALSE,FALSE},
130             {"/tests",S_OK,FALSE},
131             {"/tests",S_OK,FALSE},
132             {"",S_FALSE,FALSE},
133             {"http://winehq.org/tests/.././tests",S_OK,FALSE},
134             {"http",S_OK,FALSE},
135             {"",S_FALSE,FALSE},
136             {"",S_FALSE,FALSE}
137         },
138         {
139             {Uri_HOST_DNS,S_OK,FALSE},
140             {80,S_OK,FALSE},
141             {URL_SCHEME_HTTP,S_OK,FALSE},
142             {URLZONE_INVALID,E_NOTIMPL,FALSE}
143         }
144     },
145     {   "HtTp://www.winehq.org/tests/..?query=x&return=y", 0, S_OK, FALSE,
146         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_HOST|
147         Uri_HAS_DOMAIN|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_QUERY|Uri_HAS_RAW_URI|
148         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
149         FALSE,
150         {
151             {"http://www.winehq.org/?query=x&return=y",S_OK,FALSE},
152             {"www.winehq.org",S_OK,FALSE},
153             {"http://www.winehq.org/?query=x&return=y",S_OK,FALSE},
154             {"winehq.org",S_OK,FALSE},
155             {"",S_FALSE,FALSE},
156             {"",S_FALSE,FALSE},
157             {"www.winehq.org",S_OK,FALSE},
158             {"",S_FALSE,FALSE},
159             {"/",S_OK,FALSE},
160             {"/?query=x&return=y",S_OK,FALSE},
161             {"?query=x&return=y",S_OK,FALSE},
162             {"HtTp://www.winehq.org/tests/..?query=x&return=y",S_OK,FALSE},
163             {"http",S_OK,FALSE},
164             {"",S_FALSE,FALSE},
165             {"",S_FALSE,FALSE}
166         },
167         {
168             {Uri_HOST_DNS,S_OK,FALSE},
169             {80,S_OK,FALSE},
170             {URL_SCHEME_HTTP,S_OK,FALSE},
171             {URLZONE_INVALID,E_NOTIMPL,FALSE},
172         }
173     },
174     {   "hTTp://us%45r%3Ainfo@examp%4CE.com:80/path/a/b/./c/../%2E%2E/Forbidden'<|> Characters", 0, S_OK, FALSE,
175         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_HOST|Uri_HAS_PATH|
176         Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_USER_INFO|Uri_HAS_USER_NAME|
177         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
178         FALSE,
179         {
180             {"http://usEr%3Ainfo@example.com/path/a/Forbidden'%3C%7C%3E%20Characters",S_OK,FALSE},
181             {"usEr%3Ainfo@example.com",S_OK,FALSE},
182             {"http://example.com/path/a/Forbidden'%3C%7C%3E%20Characters",S_OK,FALSE},
183             {"example.com",S_OK,FALSE},
184             {"",S_FALSE,FALSE},
185             {"",S_FALSE,FALSE},
186             {"example.com",S_OK,FALSE},
187             {"",S_FALSE,FALSE},
188             {"/path/a/Forbidden'%3C%7C%3E%20Characters",S_OK,FALSE},
189             {"/path/a/Forbidden'%3C%7C%3E%20Characters",S_OK,FALSE},
190             {"",S_FALSE,FALSE},
191             {"hTTp://us%45r%3Ainfo@examp%4CE.com:80/path/a/b/./c/../%2E%2E/Forbidden'<|> Characters",S_OK,FALSE},
192             {"http",S_OK,FALSE},
193             {"usEr%3Ainfo",S_OK,FALSE},
194             {"usEr%3Ainfo",S_OK,FALSE}
195         },
196         {
197             {Uri_HOST_DNS,S_OK,FALSE},
198             {80,S_OK,FALSE},
199             {URL_SCHEME_HTTP,S_OK,FALSE},
200             {URLZONE_INVALID,E_NOTIMPL,FALSE},
201         }
202     },
203     {   "ftp://winepass:wine@ftp.winehq.org:9999/dir/foo bar.txt", 0, S_OK, FALSE,
204         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_EXTENSION|
205         Uri_HAS_HOST|Uri_HAS_PASSWORD|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
206         Uri_HAS_SCHEME_NAME|Uri_HAS_USER_INFO|Uri_HAS_USER_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|
207         Uri_HAS_SCHEME,
208         FALSE,
209         {
210             {"ftp://winepass:wine@ftp.winehq.org:9999/dir/foo%20bar.txt",S_OK,FALSE},
211             {"winepass:wine@ftp.winehq.org:9999",S_OK,FALSE},
212             {"ftp://ftp.winehq.org:9999/dir/foo%20bar.txt",S_OK,FALSE},
213             {"winehq.org",S_OK,FALSE},
214             {".txt",S_OK,FALSE},
215             {"",S_FALSE,FALSE},
216             {"ftp.winehq.org",S_OK,FALSE},
217             {"wine",S_OK,FALSE},
218             {"/dir/foo%20bar.txt",S_OK,FALSE},
219             {"/dir/foo%20bar.txt",S_OK,FALSE},
220             {"",S_FALSE,FALSE},
221             {"ftp://winepass:wine@ftp.winehq.org:9999/dir/foo bar.txt",S_OK,FALSE},
222             {"ftp",S_OK,FALSE},
223             {"winepass:wine",S_OK,FALSE},
224             {"winepass",S_OK,FALSE}
225         },
226         {
227             {Uri_HOST_DNS,S_OK,FALSE},
228             {9999,S_OK,FALSE},
229             {URL_SCHEME_FTP,S_OK,FALSE},
230             {URLZONE_INVALID,E_NOTIMPL,FALSE}
231         }
232     },
233     {   "file://c:\\tests\\../tests/foo%20bar.mp3", 0, S_OK, FALSE,
234         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH|
235         Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
236         FALSE,
237         {
238             {"file:///c:/tests/foo%2520bar.mp3",S_OK,FALSE},
239             {"",S_FALSE,FALSE},
240             {"file:///c:/tests/foo%2520bar.mp3",S_OK,FALSE},
241             {"",S_FALSE,FALSE},
242             {".mp3",S_OK,FALSE},
243             {"",S_FALSE,FALSE},
244             {"",S_FALSE,FALSE},
245             {"",S_FALSE,FALSE},
246             {"/c:/tests/foo%2520bar.mp3",S_OK,FALSE},
247             {"/c:/tests/foo%2520bar.mp3",S_OK,FALSE},
248             {"",S_FALSE,FALSE},
249             {"file://c:\\tests\\../tests/foo%20bar.mp3",S_OK,FALSE},
250             {"file",S_OK,FALSE},
251             {"",S_FALSE,FALSE},
252             {"",S_FALSE,FALSE}
253         },
254         {
255             {Uri_HOST_UNKNOWN,S_OK,FALSE},
256             {0,S_FALSE,FALSE},
257             {URL_SCHEME_FILE,S_OK,FALSE},
258             {URLZONE_INVALID,E_NOTIMPL,FALSE}
259         }
260     },
261     {   "FILE://localhost/test dir\\../tests/test%20file.README.txt", 0, S_OK, FALSE,
262         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH|
263         Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
264         FALSE,
265         {
266             {"file:///tests/test%20file.README.txt",S_OK,FALSE},
267             {"",S_FALSE,FALSE},
268             {"file:///tests/test%20file.README.txt",S_OK,FALSE},
269             {"",S_FALSE,FALSE},
270             {".txt",S_OK,FALSE},
271             {"",S_FALSE,FALSE},
272             {"",S_FALSE,FALSE},
273             {"",S_FALSE,FALSE},
274             {"/tests/test%20file.README.txt",S_OK,FALSE},
275             {"/tests/test%20file.README.txt",S_OK,FALSE},
276             {"",S_FALSE,FALSE},
277             {"FILE://localhost/test dir\\../tests/test%20file.README.txt",S_OK,FALSE},
278             {"file",S_OK,FALSE},
279             {"",S_FALSE,FALSE},
280             {"",S_FALSE,FALSE}
281         },
282         {
283             {Uri_HOST_UNKNOWN,S_OK,FALSE},
284             {0,S_FALSE,FALSE},
285             {URL_SCHEME_FILE,S_OK,FALSE},
286             {URLZONE_INVALID,E_NOTIMPL,FALSE}
287         }
288     },
289     {   "urn:nothing:should:happen here", 0, S_OK, FALSE,
290         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|
291         Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
292         FALSE,
293         {
294             {"urn:nothing:should:happen here",S_OK,FALSE},
295             {"",S_FALSE,FALSE},
296             {"urn:nothing:should:happen here",S_OK,FALSE},
297             {"",S_FALSE,FALSE},
298             {"",S_FALSE,FALSE},
299             {"",S_FALSE,FALSE},
300             {"",S_FALSE,FALSE},
301             {"",S_FALSE,FALSE},
302             {"nothing:should:happen here",S_OK,FALSE},
303             {"nothing:should:happen here",S_OK,FALSE},
304             {"",S_FALSE,FALSE},
305             {"urn:nothing:should:happen here",S_OK,FALSE},
306             {"urn",S_OK,FALSE},
307             {"",S_FALSE,FALSE},
308             {"",S_FALSE,FALSE}
309         },
310         {
311             {Uri_HOST_UNKNOWN,S_OK,FALSE},
312             {0,S_FALSE,FALSE},
313             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
314             {URLZONE_INVALID,E_NOTIMPL,FALSE}
315         }
316     },
317     {   "http://127.0.0.1/tests/../test dir/./test.txt", 0, S_OK, FALSE,
318         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|
319         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
320         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
321         FALSE,
322         {
323             {"http://127.0.0.1/test%20dir/test.txt",S_OK,FALSE},
324             {"127.0.0.1",S_OK,FALSE},
325             {"http://127.0.0.1/test%20dir/test.txt",S_OK,FALSE},
326             {"",S_FALSE,FALSE},
327             {".txt",S_OK,FALSE},
328             {"",S_FALSE,FALSE},
329             {"127.0.0.1",S_OK,FALSE},
330             {"",S_FALSE,FALSE},
331             {"/test%20dir/test.txt",S_OK,FALSE},
332             {"/test%20dir/test.txt",S_OK,FALSE},
333             {"",S_FALSE,FALSE},
334             {"http://127.0.0.1/tests/../test dir/./test.txt",S_OK,FALSE},
335             {"http",S_OK,FALSE},
336             {"",S_FALSE,FALSE},
337             {"",S_FALSE,FALSE}
338         },
339         {
340             {Uri_HOST_IPV4,S_OK,FALSE},
341             {80,S_OK,FALSE},
342             {URL_SCHEME_HTTP,S_OK,FALSE},
343             {URLZONE_INVALID,E_NOTIMPL,FALSE}
344         }
345     },
346     {   "http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]", 0, S_OK, FALSE,
347         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
348         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
349         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
350         FALSE,
351         {
352             {"http://[fedc:ba98:7654:3210:fedc:ba98:7654:3210]/",S_OK,FALSE},
353             {"[fedc:ba98:7654:3210:fedc:ba98:7654:3210]",S_OK,FALSE},
354             {"http://[fedc:ba98:7654:3210:fedc:ba98:7654:3210]/",S_OK,FALSE},
355             {"",S_FALSE,FALSE},
356             {"",S_FALSE,FALSE},
357             {"",S_FALSE,FALSE},
358             {"fedc:ba98:7654:3210:fedc:ba98:7654:3210",S_OK,FALSE},
359             {"",S_FALSE,FALSE},
360             {"/",S_OK,FALSE},
361             {"/",S_OK,FALSE},
362             {"",S_FALSE,FALSE},
363             {"http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]",S_OK,FALSE},
364             {"http",S_OK,FALSE},
365             {"",S_FALSE,FALSE},
366             {"",S_FALSE,FALSE}
367         },
368         {
369             {Uri_HOST_IPV6,S_OK,FALSE},
370             {80,S_OK,FALSE},
371             {URL_SCHEME_HTTP,S_OK,FALSE},
372             {URLZONE_INVALID,E_NOTIMPL,FALSE}
373         }
374     },
375     {   "ftp://[::13.1.68.3]", 0, S_OK, FALSE,
376         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
377         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
378         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
379         FALSE,
380         {
381             {"ftp://[::13.1.68.3]/",S_OK,FALSE},
382             {"[::13.1.68.3]",S_OK,FALSE},
383             {"ftp://[::13.1.68.3]/",S_OK,FALSE},
384             {"",S_FALSE,FALSE},
385             {"",S_FALSE,FALSE},
386             {"",S_FALSE,FALSE},
387             {"::13.1.68.3",S_OK,FALSE},
388             {"",S_FALSE,FALSE},
389             {"/",S_OK,FALSE},
390             {"/",S_OK,FALSE},
391             {"",S_FALSE,FALSE},
392             {"ftp://[::13.1.68.3]",S_OK,FALSE},
393             {"ftp",S_OK,FALSE},
394             {"",S_FALSE,FALSE},
395             {"",S_FALSE,FALSE}
396         },
397         {
398             {Uri_HOST_IPV6,S_OK,FALSE},
399             {21,S_OK,FALSE},
400             {URL_SCHEME_FTP,S_OK,FALSE},
401             {URLZONE_INVALID,E_NOTIMPL,FALSE}
402         }
403     },
404     {   "http://[FEDC:BA98:0:0:0:0:0:3210]", 0, S_OK, FALSE,
405         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
406         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
407         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
408         FALSE,
409         {
410             {"http://[fedc:ba98::3210]/",S_OK,FALSE},
411             {"[fedc:ba98::3210]",S_OK,FALSE},
412             {"http://[fedc:ba98::3210]/",S_OK,FALSE},
413             {"",S_FALSE,FALSE},
414             {"",S_FALSE,FALSE},
415             {"",S_FALSE,FALSE},
416             {"fedc:ba98::3210",S_OK,FALSE},
417             {"",S_FALSE,FALSE},
418             {"/",S_OK,FALSE},
419             {"/",S_OK,FALSE},
420             {"",S_FALSE,FALSE},
421             {"http://[FEDC:BA98:0:0:0:0:0:3210]",S_OK,FALSE},
422             {"http",S_OK,FALSE},
423             {"",S_FALSE,FALSE},
424             {"",S_FALSE,FALSE},
425         },
426         {
427             {Uri_HOST_IPV6,S_OK,FALSE},
428             {80,S_OK,FALSE},
429             {URL_SCHEME_HTTP,S_OK,FALSE},
430             {URLZONE_INVALID,E_NOTIMPL,FALSE}
431         }
432     },
433     {   "1234://www.winehq.org", 0, S_OK, FALSE,
434         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
435         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
436         Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
437         FALSE,
438         {
439             {"1234://www.winehq.org/",S_OK,FALSE},
440             {"www.winehq.org",S_OK,FALSE},
441             {"1234://www.winehq.org/",S_OK,FALSE},
442             {"winehq.org",S_OK,FALSE},
443             {"",S_FALSE,FALSE},
444             {"",S_FALSE,FALSE},
445             {"www.winehq.org",S_OK,FALSE},
446             {"",S_FALSE,FALSE},
447             {"/",S_OK,FALSE},
448             {"/",S_OK,FALSE},
449             {"",S_FALSE,FALSE},
450             {"1234://www.winehq.org",S_OK,FALSE},
451             {"1234",S_OK,FALSE},
452             {"",S_FALSE,FALSE},
453             {"",S_FALSE,FALSE}
454         },
455         {
456             {Uri_HOST_DNS,S_OK,FALSE},
457             {0,S_FALSE,FALSE},
458             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
459             {URLZONE_INVALID,E_NOTIMPL,FALSE}
460         }
461     },
462     /* Test's to make sure the parser/canonicalizer handles implicit file schemes correctly. */
463     {   "C:/test/test.mp3", Uri_CREATE_ALLOW_IMPLICIT_FILE_SCHEME, S_OK, FALSE,
464         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH|
465         Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
466         FALSE,
467         {
468             {"file:///C:/test/test.mp3",S_OK,FALSE},
469             {"",S_FALSE,FALSE},
470             {"file:///C:/test/test.mp3",S_OK,FALSE},
471             {"",S_FALSE,FALSE},
472             {".mp3",S_OK,FALSE},
473             {"",S_FALSE,FALSE},
474             {"",S_FALSE,FALSE},
475             {"",S_FALSE,FALSE},
476             {"/C:/test/test.mp3",S_OK,FALSE},
477             {"/C:/test/test.mp3",S_OK,FALSE},
478             {"",S_FALSE,FALSE},
479             {"C:/test/test.mp3",S_OK,FALSE},
480             {"file",S_OK,FALSE},
481             {"",S_FALSE,FALSE},
482             {"",S_FALSE,FALSE}
483         },
484         {
485             {Uri_HOST_UNKNOWN,S_OK,FALSE},
486             {0,S_FALSE,FALSE},
487             {URL_SCHEME_FILE,S_OK,FALSE},
488             {URLZONE_INVALID,E_NOTIMPL,FALSE}
489         }
490     },
491     /* Test's to make sure the parser/canonicalizer handles implicit file schemes correctly. */
492     {   "\\\\Server/test.mp3", Uri_CREATE_ALLOW_IMPLICIT_FILE_SCHEME, S_OK, FALSE,
493         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|
494         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_HOST|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
495         Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
496         FALSE,
497         {
498             {"file://server/test.mp3",S_OK,FALSE},
499             {"server",S_OK,FALSE},
500             {"file://server/test.mp3",S_OK,FALSE},
501             {"",S_FALSE,FALSE},
502             {".mp3",S_OK,FALSE},
503             {"",S_FALSE,FALSE},
504             {"server",S_OK,FALSE},
505             {"",S_FALSE,FALSE},
506             {"/test.mp3",S_OK,FALSE},
507             {"/test.mp3",S_OK,FALSE},
508             {"",S_FALSE,FALSE},
509             {"\\\\Server/test.mp3",S_OK,FALSE},
510             {"file",S_OK,FALSE},
511             {"",S_FALSE,FALSE},
512             {"",S_FALSE,FALSE}
513         },
514         {
515             {Uri_HOST_DNS,S_OK,FALSE},
516             {0,S_FALSE,FALSE},
517             {URL_SCHEME_FILE,S_OK,FALSE},
518             {URLZONE_INVALID,E_NOTIMPL,FALSE}
519         }
520     },
521     {   "www.winehq.org/test", Uri_CREATE_ALLOW_IMPLICIT_WILDCARD_SCHEME, S_OK, FALSE,
522         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_HOST|
523         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|
524         Uri_HAS_SCHEME,
525         FALSE,
526         {
527             {"*:www.winehq.org/test",S_OK,FALSE},
528             {"www.winehq.org",S_OK,FALSE},
529             {"*:www.winehq.org/test",S_OK,FALSE},
530             {"winehq.org",S_OK,FALSE},
531             {"",S_FALSE,FALSE},
532             {"",S_FALSE,FALSE},
533             {"www.winehq.org",S_OK,FALSE},
534             {"",S_FALSE,FALSE},
535             {"/test",S_OK,FALSE},
536             {"/test",S_OK,FALSE},
537             {"",S_FALSE,FALSE},
538             {"www.winehq.org/test",S_OK,FALSE},
539             {"*",S_OK,FALSE},
540             {"",S_FALSE,FALSE},
541             {"",S_FALSE,FALSE}
542         },
543         {
544             {Uri_HOST_DNS,S_OK,FALSE},
545             {0,S_FALSE,FALSE},
546             {URL_SCHEME_WILDCARD,S_OK,FALSE},
547             {URLZONE_INVALID,E_NOTIMPL,FALSE}
548         }
549     },
550     /* Valid since the '*' is the only character in the scheme name. */
551     {   "*:www.winehq.org/test", 0, S_OK, FALSE,
552         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_HOST|
553         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|
554         Uri_HAS_SCHEME,
555         FALSE,
556         {
557             {"*:www.winehq.org/test",S_OK,FALSE},
558             {"www.winehq.org",S_OK,FALSE},
559             {"*:www.winehq.org/test",S_OK,FALSE},
560             {"winehq.org",S_OK,FALSE},
561             {"",S_FALSE,FALSE},
562             {"",S_FALSE,FALSE},
563             {"www.winehq.org",S_OK,FALSE},
564             {"",S_FALSE,FALSE},
565             {"/test",S_OK,FALSE},
566             {"/test",S_OK,FALSE},
567             {"",S_FALSE,FALSE},
568             {"*:www.winehq.org/test",S_OK,FALSE},
569             {"*",S_OK,FALSE},
570             {"",S_FALSE,FALSE},
571             {"",S_FALSE,FALSE}
572         },
573         {
574             {Uri_HOST_DNS,S_OK,FALSE},
575             {0,S_FALSE,FALSE},
576             {URL_SCHEME_WILDCARD,S_OK,FALSE},
577             {URLZONE_INVALID,E_NOTIMPL,FALSE}
578         }
579     },
580     {   "/../some dir/test.ext", Uri_CREATE_ALLOW_RELATIVE, S_OK, FALSE,
581         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH|
582         Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
583         FALSE,
584         {
585             {"/../some dir/test.ext",S_OK,FALSE},
586             {"",S_FALSE,FALSE},
587             {"/../some dir/test.ext",S_OK,FALSE},
588             {"",S_FALSE,FALSE},
589             {".ext",S_OK,FALSE},
590             {"",S_FALSE,FALSE},
591             {"",S_FALSE,FALSE},
592             {"",S_FALSE,FALSE},
593             {"/../some dir/test.ext",S_OK,FALSE},
594             {"/../some dir/test.ext",S_OK,FALSE},
595             {"",S_FALSE,FALSE},
596             {"/../some dir/test.ext",S_OK,FALSE},
597             {"",S_FALSE,FALSE},
598             {"",S_FALSE,FALSE},
599             {"",S_FALSE,FALSE}
600         },
601         {
602             {Uri_HOST_UNKNOWN,S_OK,FALSE},
603             {0,S_FALSE,FALSE},
604             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
605             {URLZONE_INVALID,E_NOTIMPL,FALSE}
606         }
607     },
608     {   "//implicit/wildcard/uri scheme", Uri_CREATE_ALLOW_RELATIVE|Uri_CREATE_ALLOW_IMPLICIT_WILDCARD_SCHEME, S_OK, FALSE,
609         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|Uri_HAS_PATH|
610         Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
611         FALSE,
612         {
613             {"*://implicit/wildcard/uri%20scheme",S_OK,FALSE},
614             {"",S_OK,FALSE},
615             {"*://implicit/wildcard/uri%20scheme",S_OK,FALSE},
616             {"",S_FALSE,FALSE},
617             {"",S_FALSE,FALSE},
618             {"",S_FALSE,FALSE},
619             {"",S_OK,FALSE},
620             {"",S_FALSE,FALSE},
621             {"//implicit/wildcard/uri%20scheme",S_OK,FALSE},
622             {"//implicit/wildcard/uri%20scheme",S_OK,FALSE},
623             {"",S_FALSE,FALSE},
624             {"//implicit/wildcard/uri scheme",S_OK,FALSE},
625             {"*",S_OK,FALSE},
626             {"",S_FALSE,FALSE},
627             {"",S_FALSE,FALSE},
628         },
629         {
630             {Uri_HOST_UNKNOWN,S_OK,FALSE},
631             {0,S_FALSE,FALSE},
632             {URL_SCHEME_WILDCARD,S_OK,FALSE},
633             {URLZONE_INVALID,E_NOTIMPL,FALSE}
634         }
635     },
636     /* URI is considered opaque since CREATE_NO_CRACK_UNKNOWN_SCHEMES is set and its an unknown scheme. */
637     {   "zip://google.com", Uri_CREATE_NO_CRACK_UNKNOWN_SCHEMES, S_OK, FALSE,
638         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH|
639         Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME_NAME|
640         Uri_HAS_SCHEME,
641         FALSE,
642         {
643             {"zip:/.//google.com",S_OK,FALSE},
644             {"",S_FALSE,FALSE},
645             {"zip:/.//google.com",S_OK,FALSE},
646             {"",S_FALSE,FALSE},
647             {".com",S_OK,FALSE},
648             {"",S_FALSE,FALSE},
649             {"",S_FALSE,FALSE},
650             {"",S_FALSE,FALSE},
651             {"/.//google.com",S_OK,FALSE},
652             {"/.//google.com",S_OK,FALSE},
653             {"",S_FALSE,FALSE},
654             {"zip://google.com",S_OK,FALSE},
655             {"zip",S_OK,FALSE},
656             {"",S_FALSE,FALSE},
657             {"",S_FALSE,FALSE}
658         },
659         {
660             {Uri_HOST_UNKNOWN,S_OK,FALSE},
661             {0,S_FALSE,FALSE},
662             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
663             {URLZONE_INVALID,E_NOTIMPL,FALSE}
664         }
665     },
666     /* Windows uses the first occurrence of ':' to delimit the userinfo. */
667     {   "ftp://user:pass:word@winehq.org/", 0, S_OK, FALSE,
668         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
669         Uri_HAS_HOST|Uri_HAS_PASSWORD|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
670         Uri_HAS_SCHEME_NAME|Uri_HAS_USER_INFO|Uri_HAS_USER_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|
671         Uri_HAS_SCHEME,
672         FALSE,
673         {
674             {"ftp://user:pass:word@winehq.org/",S_OK,FALSE},
675             {"user:pass:word@winehq.org",S_OK,FALSE},
676             {"ftp://winehq.org/",S_OK,FALSE},
677             {"winehq.org",S_OK,FALSE},
678             {"",S_FALSE,FALSE},
679             {"",S_FALSE,FALSE},
680             {"winehq.org",S_OK,FALSE},
681             {"pass:word",S_OK,FALSE},
682             {"/",S_OK,FALSE},
683             {"/",S_OK,FALSE},
684             {"",S_FALSE,FALSE},
685             {"ftp://user:pass:word@winehq.org/",S_OK,FALSE},
686             {"ftp",S_OK,FALSE},
687             {"user:pass:word",S_OK,FALSE},
688             {"user",S_OK,FALSE}
689         },
690         {
691             {Uri_HOST_DNS,S_OK,FALSE},
692             {21,S_OK,FALSE},
693             {URL_SCHEME_FTP,S_OK,FALSE},
694             {URLZONE_INVALID,E_NOTIMPL,FALSE}
695         }
696     },
697     /* Make sure % encoded unreserved characters are decoded. */
698     {   "ftp://w%49%4Ee:PA%53%53@ftp.google.com/", 0, S_OK, FALSE,
699         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
700         Uri_HAS_HOST|Uri_HAS_PASSWORD|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
701         Uri_HAS_SCHEME_NAME|Uri_HAS_USER_INFO|Uri_HAS_USER_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|
702         Uri_HAS_SCHEME,
703         FALSE,
704         {
705             {"ftp://wINe:PASS@ftp.google.com/",S_OK,FALSE},
706             {"wINe:PASS@ftp.google.com",S_OK,FALSE},
707             {"ftp://ftp.google.com/",S_OK,FALSE},
708             {"google.com",S_OK,FALSE},
709             {"",S_FALSE,FALSE},
710             {"",S_FALSE,FALSE},
711             {"ftp.google.com",S_OK,FALSE},
712             {"PASS",S_OK,FALSE},
713             {"/",S_OK,FALSE},
714             {"/",S_OK,FALSE},
715             {"",S_FALSE,FALSE},
716             {"ftp://w%49%4Ee:PA%53%53@ftp.google.com/",S_OK,FALSE},
717             {"ftp",S_OK,FALSE},
718             {"wINe:PASS",S_OK,FALSE},
719             {"wINe",S_OK,FALSE}
720         },
721         {
722             {Uri_HOST_DNS,S_OK,FALSE},
723             {21,S_OK,FALSE},
724             {URL_SCHEME_FTP,S_OK,FALSE},
725             {URLZONE_INVALID,E_NOTIMPL,FALSE}
726         }
727     },
728     /* Make sure % encoded characters which are NOT unreserved are NOT decoded. */
729     {   "ftp://w%5D%5Be:PA%7B%7D@ftp.google.com/", 0, S_OK, FALSE,
730         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
731         Uri_HAS_HOST|Uri_HAS_PASSWORD|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
732         Uri_HAS_SCHEME_NAME|Uri_HAS_USER_INFO|Uri_HAS_USER_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|
733         Uri_HAS_SCHEME,
734         FALSE,
735         {
736             {"ftp://w%5D%5Be:PA%7B%7D@ftp.google.com/",S_OK,FALSE},
737             {"w%5D%5Be:PA%7B%7D@ftp.google.com",S_OK,FALSE},
738             {"ftp://ftp.google.com/",S_OK,FALSE},
739             {"google.com",S_OK,FALSE},
740             {"",S_FALSE,FALSE},
741             {"",S_FALSE,FALSE},
742             {"ftp.google.com",S_OK,FALSE},
743             {"PA%7B%7D",S_OK,FALSE},
744             {"/",S_OK,FALSE},
745             {"/",S_OK,FALSE},
746             {"",S_FALSE,FALSE},
747             {"ftp://w%5D%5Be:PA%7B%7D@ftp.google.com/",S_OK,FALSE},
748             {"ftp",S_OK,FALSE},
749             {"w%5D%5Be:PA%7B%7D",S_OK,FALSE},
750             {"w%5D%5Be",S_OK,FALSE}
751         },
752         {
753             {Uri_HOST_DNS,S_OK,FALSE},
754             {21,S_OK,FALSE},
755             {URL_SCHEME_FTP,S_OK,FALSE},
756             {URLZONE_INVALID,E_NOTIMPL,FALSE}
757         }
758     },
759     /* You're allowed to have an empty password portion in the userinfo section. */
760     {   "ftp://empty:@ftp.google.com/", 0, S_OK, FALSE,
761         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
762         Uri_HAS_HOST|Uri_HAS_PASSWORD|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
763         Uri_HAS_SCHEME_NAME|Uri_HAS_USER_INFO|Uri_HAS_USER_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|
764         Uri_HAS_SCHEME,
765         FALSE,
766         {
767             {"ftp://empty:@ftp.google.com/",S_OK,FALSE},
768             {"empty:@ftp.google.com",S_OK,FALSE},
769             {"ftp://ftp.google.com/",S_OK,FALSE},
770             {"google.com",S_OK,FALSE},
771             {"",S_FALSE,FALSE},
772             {"",S_FALSE,FALSE},
773             {"ftp.google.com",S_OK,FALSE},
774             {"",S_OK,FALSE},
775             {"/",S_OK,FALSE},
776             {"/",S_OK,FALSE},
777             {"",S_FALSE,FALSE},
778             {"ftp://empty:@ftp.google.com/",S_OK,FALSE},
779             {"ftp",S_OK,FALSE},
780             {"empty:",S_OK,FALSE},
781             {"empty",S_OK,FALSE}
782         },
783         {
784             {Uri_HOST_DNS,S_OK,FALSE},
785             {21,S_OK,FALSE},
786             {URL_SCHEME_FTP,S_OK,FALSE},
787             {URLZONE_INVALID,E_NOTIMPL,FALSE}
788         }
789     },
790     /* Make sure forbidden characters in "userinfo" get encoded. */
791     {   "ftp://\" \"weird@ftp.google.com/", 0, S_OK, FALSE,
792         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
793         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
794         Uri_HAS_SCHEME_NAME|Uri_HAS_USER_INFO|Uri_HAS_USER_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|
795         Uri_HAS_SCHEME,
796         FALSE,
797         {
798             {"ftp://%22%20%22weird@ftp.google.com/",S_OK,FALSE},
799             {"%22%20%22weird@ftp.google.com",S_OK,FALSE},
800             {"ftp://ftp.google.com/",S_OK,FALSE},
801             {"google.com",S_OK,FALSE},
802             {"",S_FALSE,FALSE},
803             {"",S_FALSE,FALSE},
804             {"ftp.google.com",S_OK,FALSE},
805             {"",S_FALSE,FALSE},
806             {"/",S_OK,FALSE},
807             {"/",S_OK,FALSE},
808             {"",S_FALSE,FALSE},
809             {"ftp://\" \"weird@ftp.google.com/",S_OK,FALSE},
810             {"ftp",S_OK,FALSE},
811             {"%22%20%22weird",S_OK,FALSE},
812             {"%22%20%22weird",S_OK,FALSE}
813         },
814         {
815             {Uri_HOST_DNS,S_OK,FALSE},
816             {21,S_OK,FALSE},
817             {URL_SCHEME_FTP,S_OK,FALSE},
818             {URLZONE_INVALID,E_NOTIMPL,FALSE}
819         }
820     },
821     /* Make sure the forbidden characters don't get percent encoded. */
822     {   "ftp://\" \"weird@ftp.google.com/", Uri_CREATE_NO_ENCODE_FORBIDDEN_CHARACTERS, S_OK, FALSE,
823         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
824         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
825         Uri_HAS_SCHEME_NAME|Uri_HAS_USER_INFO|Uri_HAS_USER_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|
826         Uri_HAS_SCHEME,
827         FALSE,
828         {
829             {"ftp://\" \"weird@ftp.google.com/",S_OK,FALSE},
830             {"\" \"weird@ftp.google.com",S_OK,FALSE},
831             {"ftp://ftp.google.com/",S_OK,FALSE},
832             {"google.com",S_OK,FALSE},
833             {"",S_FALSE,FALSE},
834             {"",S_FALSE,FALSE},
835             {"ftp.google.com",S_OK,FALSE},
836             {"",S_FALSE,FALSE},
837             {"/",S_OK,FALSE},
838             {"/",S_OK,FALSE},
839             {"",S_FALSE,FALSE},
840             {"ftp://\" \"weird@ftp.google.com/",S_OK,FALSE},
841             {"ftp",S_OK,FALSE},
842             {"\" \"weird",S_OK,FALSE},
843             {"\" \"weird",S_OK,FALSE}
844         },
845         {
846             {Uri_HOST_DNS,S_OK,FALSE},
847             {21,S_OK,FALSE},
848             {URL_SCHEME_FTP,S_OK,FALSE},
849             {URLZONE_INVALID,E_NOTIMPL,FALSE}
850         }
851     },
852     /* Allowed to have invalid % encoded because its an unknown scheme type. */
853     {   "zip://%xy:word@winehq.org/", 0, S_OK, FALSE,
854         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
855         Uri_HAS_HOST|Uri_HAS_PASSWORD|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
856         Uri_HAS_SCHEME_NAME|Uri_HAS_USER_INFO|Uri_HAS_USER_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
857         FALSE,
858         {
859             {"zip://%xy:word@winehq.org/",S_OK,FALSE},
860             {"%xy:word@winehq.org",S_OK,FALSE},
861             {"zip://%xy:word@winehq.org/",S_OK,FALSE},
862             {"winehq.org",S_OK,FALSE},
863             {"",S_FALSE,FALSE},
864             {"",S_FALSE,FALSE},
865             {"winehq.org",S_OK,FALSE},
866             {"word",S_OK,FALSE},
867             {"/",S_OK,FALSE},
868             {"/",S_OK,FALSE},
869             {"",S_FALSE,FALSE},
870             {"zip://%xy:word@winehq.org/",S_OK,FALSE},
871             {"zip",S_OK,FALSE},
872             {"%xy:word",S_OK,FALSE},
873             {"%xy",S_OK,FALSE}
874         },
875         {
876             {Uri_HOST_DNS,S_OK,FALSE},
877             {0,S_FALSE,FALSE},
878             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
879             {URLZONE_INVALID,E_NOTIMPL,FALSE}
880         }
881     },
882     /* Unreserved, percent encoded characters aren't decoded in the userinfo becuase the scheme
883      * isn't known.
884      */
885     {   "zip://%2E:%52%53ord@winehq.org/", 0, S_OK, FALSE,
886         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
887         Uri_HAS_HOST|Uri_HAS_PASSWORD|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
888         Uri_HAS_SCHEME_NAME|Uri_HAS_USER_INFO|Uri_HAS_USER_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
889         FALSE,
890         {
891             {"zip://%2E:%52%53ord@winehq.org/",S_OK,FALSE},
892             {"%2E:%52%53ord@winehq.org",S_OK,FALSE},
893             {"zip://%2E:%52%53ord@winehq.org/",S_OK,FALSE},
894             {"winehq.org",S_OK,FALSE},
895             {"",S_FALSE,FALSE},
896             {"",S_FALSE,FALSE},
897             {"winehq.org",S_OK,FALSE},
898             {"%52%53ord",S_OK,FALSE},
899             {"/",S_OK,FALSE},
900             {"/",S_OK,FALSE},
901             {"",S_FALSE,FALSE},
902             {"zip://%2E:%52%53ord@winehq.org/",S_OK,FALSE},
903             {"zip",S_OK,FALSE},
904             {"%2E:%52%53ord",S_OK,FALSE},
905             {"%2E",S_OK,FALSE}
906         },
907         {
908             {Uri_HOST_DNS,S_OK,FALSE},
909             {0,S_FALSE,FALSE},
910             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
911             {URLZONE_INVALID,E_NOTIMPL,FALSE}
912         }
913     },
914     {   "ftp://[](),'test':word@winehq.org/", 0, S_OK, FALSE,
915         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
916         Uri_HAS_HOST|Uri_HAS_PASSWORD|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
917         Uri_HAS_SCHEME_NAME|Uri_HAS_USER_INFO|Uri_HAS_USER_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|
918         Uri_HAS_SCHEME,
919         FALSE,
920         {
921             {"ftp://[](),'test':word@winehq.org/",S_OK,FALSE},
922             {"[](),'test':word@winehq.org",S_OK,FALSE},
923             {"ftp://winehq.org/",S_OK,FALSE},
924             {"winehq.org",S_OK,FALSE},
925             {"",S_FALSE,FALSE},
926             {"",S_FALSE,FALSE},
927             {"winehq.org",S_OK,FALSE},
928             {"word",S_OK,FALSE},
929             {"/",S_OK,FALSE},
930             {"/",S_OK,FALSE},
931             {"",S_FALSE,FALSE},
932             {"ftp://[](),'test':word@winehq.org/",S_OK,FALSE},
933             {"ftp",S_OK,FALSE},
934             {"[](),'test':word",S_OK,FALSE},
935             {"[](),'test'",S_OK,FALSE}
936         },
937         {
938             {Uri_HOST_DNS,S_OK,FALSE},
939             {21,S_OK,FALSE},
940             {URL_SCHEME_FTP,S_OK,FALSE},
941             {URLZONE_INVALID,E_NOTIMPL,FALSE}
942         }
943     },
944     {   "ftp://test?:word@winehq.org/", 0, S_OK, FALSE,
945         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
946         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
947         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
948         FALSE,
949         {
950             {"ftp://test/?:word@winehq.org/",S_OK,FALSE},
951             {"test",S_OK,FALSE},
952             {"ftp://test/?:word@winehq.org/",S_OK,FALSE},
953             {"",S_FALSE,FALSE},
954             {"",S_FALSE,FALSE},
955             {"",S_FALSE,FALSE},
956             {"test",S_OK,FALSE},
957             {"",S_FALSE,FALSE},
958             {"/",S_OK,FALSE},
959             {"/?:word@winehq.org/",S_OK,FALSE},
960             {"?:word@winehq.org/",S_OK,FALSE},
961             {"ftp://test?:word@winehq.org/",S_OK,FALSE},
962             {"ftp",S_OK,FALSE},
963             {"",S_FALSE,FALSE},
964             {"",S_FALSE,FALSE}
965         },
966         {
967             {Uri_HOST_DNS,S_OK,FALSE},
968             {21,S_OK,FALSE},
969             {URL_SCHEME_FTP,S_OK,FALSE},
970             {URLZONE_INVALID,E_NOTIMPL,FALSE}
971         }
972     },
973     {   "ftp://test#:word@winehq.org/", 0, S_OK, FALSE,
974         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_FRAGMENT|Uri_HAS_HOST|
975         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
976         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
977         FALSE,
978         {
979             {"ftp://test/#:word@winehq.org/",S_OK,FALSE},
980             {"test",S_OK,FALSE},
981             {"ftp://test/#:word@winehq.org/",S_OK,FALSE},
982             {"",S_FALSE,FALSE},
983             {"",S_FALSE,FALSE},
984             {"#:word@winehq.org/",S_OK,FALSE},
985             {"test",S_OK,FALSE},
986             {"",S_FALSE,FALSE},
987             {"/",S_OK,FALSE},
988             {"/",S_OK,FALSE},
989             {"",S_FALSE,FALSE},
990             {"ftp://test#:word@winehq.org/",S_OK,FALSE},
991             {"ftp",S_OK,FALSE},
992             {"",S_FALSE,FALSE},
993             {"",S_FALSE,FALSE}
994         },
995         {
996             {Uri_HOST_DNS,S_OK,FALSE},
997             {21,S_OK,FALSE},
998             {URL_SCHEME_FTP,S_OK,FALSE},
999             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1000         }
1001     },
1002     /* Allowed to have a backslash in the userinfo since it's an unknown scheme. */
1003     {   "zip://test\\:word@winehq.org/", 0, S_OK, FALSE,
1004         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_HOST|
1005         Uri_HAS_PASSWORD|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1006         Uri_HAS_USER_INFO|Uri_HAS_USER_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
1007         FALSE,
1008         {
1009             {"zip://test\\:word@winehq.org/",S_OK,FALSE},
1010             {"test\\:word@winehq.org",S_OK,FALSE},
1011             {"zip://test\\:word@winehq.org/",S_OK,FALSE},
1012             {"winehq.org",S_OK,FALSE},
1013             {"",S_FALSE,FALSE},
1014             {"",S_FALSE,FALSE},
1015             {"winehq.org",S_OK,FALSE},
1016             {"word",S_OK,FALSE},
1017             {"/",S_OK,FALSE},
1018             {"/",S_OK,FALSE},
1019             {"",S_FALSE,FALSE},
1020             {"zip://test\\:word@winehq.org/",S_OK,FALSE},
1021             {"zip",S_OK,FALSE},
1022             {"test\\:word",S_OK,FALSE},
1023             {"test\\",S_OK,FALSE}
1024         },
1025         {
1026             {Uri_HOST_DNS,S_OK,FALSE},
1027             {0,S_FALSE,FALSE},
1028             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1029             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1030         }
1031     },
1032     /* It normalizes IPv4 addresses correctly. */
1033     {   "http://127.000.000.100/", 0, S_OK, FALSE,
1034         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
1035         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1036         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1037         FALSE,
1038         {
1039             {"http://127.0.0.100/",S_OK,FALSE},
1040             {"127.0.0.100",S_OK,FALSE},
1041             {"http://127.0.0.100/",S_OK,FALSE},
1042             {"",S_FALSE,FALSE},
1043             {"",S_FALSE,FALSE},
1044             {"",S_FALSE,FALSE},
1045             {"127.0.0.100",S_OK,FALSE},
1046             {"",S_FALSE,FALSE},
1047             {"/",S_OK,FALSE},
1048             {"/",S_OK,FALSE},
1049             {"",S_FALSE,FALSE},
1050             {"http://127.000.000.100/",S_OK,FALSE},
1051             {"http",S_OK,FALSE},
1052             {"",S_FALSE,FALSE},
1053             {"",S_FALSE,FALSE}
1054         },
1055         {
1056             {Uri_HOST_IPV4,S_OK,FALSE},
1057             {80,S_OK,FALSE},
1058             {URL_SCHEME_HTTP,S_OK,FALSE},
1059             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1060         }
1061     },
1062     /* Make sure it normalizes partial IPv4 addresses correctly. */
1063     {   "http://127.0/", 0, S_OK, FALSE,
1064         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
1065         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1066         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1067         FALSE,
1068         {
1069             {"http://127.0.0.0/",S_OK,FALSE},
1070             {"127.0.0.0",S_OK,FALSE},
1071             {"http://127.0.0.0/",S_OK,FALSE},
1072             {"",S_FALSE,FALSE},
1073             {"",S_FALSE,FALSE},
1074             {"",S_FALSE,FALSE},
1075             {"127.0.0.0",S_OK,FALSE},
1076             {"",S_FALSE,FALSE},
1077             {"/",S_OK,FALSE},
1078             {"/",S_OK,FALSE},
1079             {"",S_FALSE,FALSE},
1080             {"http://127.0/",S_OK,FALSE},
1081             {"http",S_OK,FALSE},
1082             {"",S_FALSE,FALSE},
1083             {"",S_FALSE,FALSE}
1084         },
1085         {
1086             {Uri_HOST_IPV4,S_OK,FALSE},
1087             {80,S_OK,FALSE},
1088             {URL_SCHEME_HTTP,S_OK,FALSE},
1089             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1090         }
1091     },
1092     /* Make sure it converts implicit IPv4's correctly. */
1093     {   "http://123456/", 0, S_OK, FALSE,
1094         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
1095         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1096         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1097         FALSE,
1098         {
1099             {"http://0.1.226.64/",S_OK,FALSE},
1100             {"0.1.226.64",S_OK,FALSE},
1101             {"http://0.1.226.64/",S_OK,FALSE},
1102             {"",S_FALSE,FALSE},
1103             {"",S_FALSE,FALSE},
1104             {"",S_FALSE,FALSE},
1105             {"0.1.226.64",S_OK,FALSE},
1106             {"",S_FALSE,FALSE},
1107             {"/",S_OK,FALSE},
1108             {"/",S_OK,FALSE},
1109             {"",S_FALSE,FALSE},
1110             {"http://123456/",S_OK,FALSE},
1111             {"http",S_OK,FALSE},
1112             {"",S_FALSE,FALSE},
1113             {"",S_FALSE,FALSE}
1114         },
1115         {
1116             {Uri_HOST_IPV4,S_OK,FALSE},
1117             {80,S_OK,FALSE},
1118             {URL_SCHEME_HTTP,S_OK,FALSE},
1119             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1120         }
1121     },
1122     /* UINT_MAX */
1123     {   "http://4294967295/", 0, S_OK, FALSE,
1124         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
1125         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1126         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1127         FALSE,
1128         {
1129             {"http://255.255.255.255/",S_OK,FALSE},
1130             {"255.255.255.255",S_OK,FALSE},
1131             {"http://255.255.255.255/",S_OK,FALSE},
1132             {"",S_FALSE,FALSE},
1133             {"",S_FALSE,FALSE},
1134             {"",S_FALSE,FALSE},
1135             {"255.255.255.255",S_OK,FALSE},
1136             {"",S_FALSE,FALSE},
1137             {"/",S_OK,FALSE},
1138             {"/",S_OK,FALSE},
1139             {"",S_FALSE,FALSE},
1140             {"http://4294967295/",S_OK,FALSE},
1141             {"http",S_OK,FALSE},
1142             {"",S_FALSE,FALSE},
1143             {"",S_FALSE,FALSE}
1144         },
1145         {
1146             {Uri_HOST_IPV4,S_OK,FALSE},
1147             {80,S_OK,FALSE},
1148             {URL_SCHEME_HTTP,S_OK,FALSE},
1149             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1150         }
1151     },
1152     /* UINT_MAX+1 */
1153     {   "http://4294967296/", 0, S_OK, FALSE,
1154         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
1155         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1156         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1157         FALSE,
1158         {
1159             {"http://4294967296/",S_OK,FALSE},
1160             {"4294967296",S_OK,FALSE},
1161             {"http://4294967296/",S_OK,FALSE},
1162             {"",S_FALSE,FALSE},
1163             {"",S_FALSE,FALSE},
1164             {"",S_FALSE,FALSE},
1165             {"4294967296",S_OK,FALSE},
1166             {"",S_FALSE,FALSE},
1167             {"/",S_OK,FALSE},
1168             {"/",S_OK,FALSE},
1169             {"",S_FALSE,FALSE},
1170             {"http://4294967296/",S_OK,FALSE},
1171             {"http",S_OK,FALSE},
1172             {"",S_FALSE,FALSE},
1173             {"",S_FALSE,FALSE}
1174         },
1175         {
1176             {Uri_HOST_DNS,S_OK,FALSE},
1177             {80,S_OK,FALSE},
1178             {URL_SCHEME_HTTP,S_OK,FALSE},
1179             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1180         }
1181     },
1182     /* Window's doesn't normalize IP address for unknown schemes. */
1183     {   "1234://4294967295/", 0, S_OK, FALSE,
1184         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
1185         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1186         Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
1187         FALSE,
1188         {
1189             {"1234://4294967295/",S_OK,FALSE},
1190             {"4294967295",S_OK,FALSE},
1191             {"1234://4294967295/",S_OK,FALSE},
1192             {"",S_FALSE,FALSE},
1193             {"",S_FALSE,FALSE},
1194             {"",S_FALSE,FALSE},
1195             {"4294967295",S_OK,FALSE},
1196             {"",S_FALSE,FALSE},
1197             {"/",S_OK,FALSE},
1198             {"/",S_OK,FALSE},
1199             {"",S_FALSE,FALSE},
1200             {"1234://4294967295/",S_OK,FALSE},
1201             {"1234",S_OK,FALSE},
1202             {"",S_FALSE,FALSE},
1203             {"",S_FALSE,FALSE}
1204         },
1205         {
1206             {Uri_HOST_IPV4,S_OK,FALSE},
1207             {0,S_FALSE,FALSE},
1208             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1209             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1210         }
1211     },
1212     /* Window's doesn't normalize IP address for unknown schemes. */
1213     {   "1234://127.001/", 0, S_OK, FALSE,
1214         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
1215         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1216         Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
1217         FALSE,
1218         {
1219             {"1234://127.001/",S_OK,FALSE},
1220             {"127.001",S_OK,FALSE},
1221             {"1234://127.001/",S_OK,FALSE},
1222             {"",S_FALSE,FALSE},
1223             {"",S_FALSE,FALSE},
1224             {"",S_FALSE,FALSE},
1225             {"127.001",S_OK,FALSE},
1226             {"",S_FALSE,FALSE},
1227             {"/",S_OK,FALSE},
1228             {"/",S_OK,FALSE},
1229             {"",S_FALSE,FALSE},
1230             {"1234://127.001/",S_OK,FALSE},
1231             {"1234",S_OK,FALSE},
1232             {"",S_FALSE,FALSE},
1233             {"",S_FALSE,FALSE}
1234         },
1235         {
1236             {Uri_HOST_IPV4,S_OK,FALSE},
1237             {0,S_FALSE,FALSE},
1238             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1239             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1240         }
1241     },
1242     {   "http://[FEDC:BA98::3210]", 0, S_OK, FALSE,
1243         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
1244         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1245         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1246         FALSE,
1247         {
1248             {"http://[fedc:ba98::3210]/",S_OK,FALSE},
1249             {"[fedc:ba98::3210]",S_OK,FALSE},
1250             {"http://[fedc:ba98::3210]/",S_OK,FALSE},
1251             {"",S_FALSE,FALSE},
1252             {"",S_FALSE,FALSE},
1253             {"",S_FALSE,FALSE},
1254             {"fedc:ba98::3210",S_OK,FALSE},
1255             {"",S_FALSE,FALSE},
1256             {"/",S_OK,FALSE},
1257             {"/",S_OK,FALSE},
1258             {"",S_FALSE,FALSE},
1259             {"http://[FEDC:BA98::3210]",S_OK,FALSE},
1260             {"http",S_OK,FALSE},
1261             {"",S_FALSE,FALSE},
1262             {"",S_FALSE,FALSE},
1263         },
1264         {
1265             {Uri_HOST_IPV6,S_OK,FALSE},
1266             {80,S_OK,FALSE},
1267             {URL_SCHEME_HTTP,S_OK,FALSE},
1268             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1269         }
1270     },
1271     {   "http://[::]", 0, S_OK, FALSE,
1272         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
1273         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1274         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1275         FALSE,
1276         {
1277             {"http://[::]/",S_OK,FALSE},
1278             {"[::]",S_OK,FALSE},
1279             {"http://[::]/",S_OK,FALSE},
1280             {"",S_FALSE,FALSE},
1281             {"",S_FALSE,FALSE},
1282             {"",S_FALSE,FALSE},
1283             {"::",S_OK,FALSE},
1284             {"",S_FALSE,FALSE},
1285             {"/",S_OK,FALSE},
1286             {"/",S_OK,FALSE},
1287             {"",S_FALSE,FALSE},
1288             {"http://[::]",S_OK,FALSE},
1289             {"http",S_OK,FALSE},
1290             {"",S_FALSE,FALSE},
1291             {"",S_FALSE,FALSE},
1292         },
1293         {
1294             {Uri_HOST_IPV6,S_OK,FALSE},
1295             {80,S_OK,FALSE},
1296             {URL_SCHEME_HTTP,S_OK,FALSE},
1297             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1298         }
1299     },
1300     {   "http://[FEDC:BA98::]", 0, S_OK, FALSE,
1301         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
1302         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1303         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1304         FALSE,
1305         {
1306             {"http://[fedc:ba98::]/",S_OK,FALSE},
1307             {"[fedc:ba98::]",S_OK,FALSE},
1308             {"http://[fedc:ba98::]/",S_OK,FALSE},
1309             {"",S_FALSE,FALSE},
1310             {"",S_FALSE,FALSE},
1311             {"",S_FALSE,FALSE},
1312             {"fedc:ba98::",S_OK,FALSE},
1313             {"",S_FALSE,FALSE},
1314             {"/",S_OK,FALSE},
1315             {"/",S_OK,FALSE},
1316             {"",S_FALSE,FALSE},
1317             {"http://[FEDC:BA98::]",S_OK,FALSE},
1318             {"http",S_OK,FALSE},
1319             {"",S_FALSE,FALSE},
1320             {"",S_FALSE,FALSE},
1321         },
1322         {
1323             {Uri_HOST_IPV6,S_OK,FALSE},
1324             {80,S_OK,FALSE},
1325             {URL_SCHEME_HTTP,S_OK,FALSE},
1326             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1327         }
1328     },
1329     /* Valid even with 2 byte elision because it doesn't appear the beginning or end. */
1330     {   "http://[1::3:4:5:6:7:8]", 0, S_OK, FALSE,
1331         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
1332         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1333         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1334         FALSE,
1335         {
1336             {"http://[1:0:3:4:5:6:7:8]/",S_OK,FALSE},
1337             {"[1:0:3:4:5:6:7:8]",S_OK,FALSE},
1338             {"http://[1:0:3:4:5:6:7:8]/",S_OK,FALSE},
1339             {"",S_FALSE,FALSE},
1340             {"",S_FALSE,FALSE},
1341             {"",S_FALSE,FALSE},
1342             {"1:0:3:4:5:6:7:8",S_OK,FALSE},
1343             {"",S_FALSE,FALSE},
1344             {"/",S_OK,FALSE},
1345             {"/",S_OK,FALSE},
1346             {"",S_FALSE,FALSE},
1347             {"http://[1::3:4:5:6:7:8]",S_OK,FALSE},
1348             {"http",S_OK,FALSE},
1349             {"",S_FALSE,FALSE},
1350             {"",S_FALSE,FALSE},
1351         },
1352         {
1353             {Uri_HOST_IPV6,S_OK,FALSE},
1354             {80,S_OK,FALSE},
1355             {URL_SCHEME_HTTP,S_OK,FALSE},
1356             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1357         }
1358     },
1359     {   "http://[v2.34]/", 0, S_OK, FALSE,
1360         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
1361         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1362         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1363         FALSE,
1364         {
1365             {"http://[v2.34]/",S_OK,FALSE},
1366             {"[v2.34]",S_OK,FALSE},
1367             {"http://[v2.34]/",S_OK,FALSE},
1368             {"",S_FALSE,FALSE},
1369             {"",S_FALSE,FALSE},
1370             {"",S_FALSE,FALSE},
1371             {"[v2.34]",S_OK,FALSE},
1372             {"",S_FALSE,FALSE},
1373             {"/",S_OK,FALSE},
1374             {"/",S_OK,FALSE},
1375             {"",S_FALSE,FALSE},
1376             {"http://[v2.34]/",S_OK,FALSE},
1377             {"http",S_OK,FALSE},
1378             {"",S_FALSE,FALSE},
1379             {"",S_FALSE,FALSE}
1380         },
1381         {
1382             {Uri_HOST_UNKNOWN,S_OK,FALSE},
1383             {80,S_OK,FALSE},
1384             {URL_SCHEME_HTTP,S_OK,FALSE},
1385             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1386         }
1387     },
1388     /* Windows ignores ':' if they appear after a '[' on a non-IPLiteral host. */
1389     {   "http://[xyz:12345.com/test", 0, S_OK, FALSE,
1390         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
1391         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
1392         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1393         FALSE,
1394         {
1395             {"http://[xyz:12345.com/test",S_OK,FALSE},
1396             {"[xyz:12345.com",S_OK,FALSE},
1397             {"http://[xyz:12345.com/test",S_OK,FALSE},
1398             {"[xyz:12345.com",S_OK,FALSE},
1399             {"",S_FALSE,FALSE},
1400             {"",S_FALSE,FALSE},
1401             {"[xyz:12345.com",S_OK,FALSE},
1402             {"",S_FALSE,FALSE},
1403             {"/test",S_OK,FALSE},
1404             {"/test",S_OK,FALSE},
1405             {"",S_FALSE,FALSE},
1406             {"http://[xyz:12345.com/test",S_OK,FALSE},
1407             {"http",S_OK,FALSE},
1408             {"",S_FALSE,FALSE},
1409             {"",S_FALSE,FALSE}
1410         },
1411         {
1412             {Uri_HOST_DNS,S_OK,FALSE},
1413             {80,S_OK,FALSE},
1414             {URL_SCHEME_HTTP,S_OK,FALSE},
1415             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1416         }
1417     },
1418     /* Valid URI since the '[' and ']' don't appear at the beginning and end
1419      * of the host name (respectively).
1420      */
1421     {   "ftp://www.[works].com/", 0, S_OK, FALSE,
1422         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
1423         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
1424         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1425         FALSE,
1426         {
1427             {"ftp://www.[works].com/",S_OK,FALSE},
1428             {"www.[works].com",S_OK,FALSE},
1429             {"ftp://www.[works].com/",S_OK,FALSE},
1430             {"[works].com",S_OK,FALSE},
1431             {"",S_FALSE,FALSE},
1432             {"",S_FALSE,FALSE},
1433             {"www.[works].com",S_OK,FALSE},
1434             {"",S_FALSE,FALSE},
1435             {"/",S_OK,FALSE},
1436             {"/",S_OK,FALSE},
1437             {"",S_FALSE,FALSE},
1438             {"ftp://www.[works].com/",S_OK,FALSE},
1439             {"ftp",S_OK,FALSE},
1440             {"",S_FALSE,FALSE},
1441             {"",S_FALSE,FALSE}
1442         },
1443         {
1444             {Uri_HOST_DNS,S_OK,FALSE},
1445             {21,S_OK,FALSE},
1446             {URL_SCHEME_FTP,S_OK,FALSE},
1447             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1448         }
1449     },
1450     /* Considers ':' a delimiter since it appears after the ']'. */
1451     {   "http://www.google.com]:12345/", 0, S_OK, FALSE,
1452         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
1453         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
1454         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1455         FALSE,
1456         {
1457             {"http://www.google.com]:12345/",S_OK,FALSE},
1458             {"www.google.com]:12345",S_OK,FALSE},
1459             {"http://www.google.com]:12345/",S_OK,FALSE},
1460             {"google.com]",S_OK,FALSE},
1461             {"",S_FALSE,FALSE},
1462             {"",S_FALSE,FALSE},
1463             {"www.google.com]",S_OK,FALSE},
1464             {"",S_FALSE,FALSE},
1465             {"/",S_OK,FALSE},
1466             {"/",S_OK,FALSE},
1467             {"",S_FALSE,FALSE},
1468             {"http://www.google.com]:12345/",S_OK,FALSE},
1469             {"http",S_OK,FALSE},
1470             {"",S_FALSE,FALSE},
1471             {"",S_FALSE,FALSE}
1472         },
1473         {
1474             {Uri_HOST_DNS,S_OK,FALSE},
1475             {12345,S_OK,FALSE},
1476             {URL_SCHEME_HTTP,S_OK,FALSE},
1477             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1478         }
1479     },
1480     /* Unknown scheme types can have invalid % encoded data in the hostname. */
1481     {   "zip://w%XXw%GEw.google.com/", 0, S_OK, FALSE,
1482         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
1483         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
1484         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
1485         FALSE,
1486         {
1487             {"zip://w%XXw%GEw.google.com/",S_OK,FALSE},
1488             {"w%XXw%GEw.google.com",S_OK,FALSE},
1489             {"zip://w%XXw%GEw.google.com/",S_OK,FALSE},
1490             {"google.com",S_OK,FALSE},
1491             {"",S_FALSE,FALSE},
1492             {"",S_FALSE,FALSE},
1493             {"w%XXw%GEw.google.com",S_OK,FALSE},
1494             {"",S_FALSE,FALSE},
1495             {"/",S_OK,FALSE},
1496             {"/",S_OK,FALSE},
1497             {"",S_FALSE,FALSE},
1498             {"zip://w%XXw%GEw.google.com/",S_OK,FALSE},
1499             {"zip",S_OK,FALSE},
1500             {"",S_FALSE,FALSE},
1501             {"",S_FALSE,FALSE}
1502         },
1503         {
1504             {Uri_HOST_DNS,S_OK,FALSE},
1505             {0,S_FALSE,FALSE},
1506             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1507             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1508         }
1509     },
1510     /* Unknown scheme types hostname doesn't get lower cased. */
1511     {   "zip://GOOGLE.com/", 0, S_OK, FALSE,
1512         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
1513         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
1514         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
1515         FALSE,
1516         {
1517             {"zip://GOOGLE.com/",S_OK,FALSE},
1518             {"GOOGLE.com",S_OK,FALSE},
1519             {"zip://GOOGLE.com/",S_OK,FALSE},
1520             {"GOOGLE.com",S_OK,FALSE},
1521             {"",S_FALSE,FALSE},
1522             {"",S_FALSE,FALSE},
1523             {"GOOGLE.com",S_OK,FALSE},
1524             {"",S_FALSE,FALSE},
1525             {"/",S_OK,FALSE},
1526             {"/",S_OK,FALSE},
1527             {"",S_FALSE,FALSE},
1528             {"zip://GOOGLE.com/",S_OK,FALSE},
1529             {"zip",S_OK,FALSE},
1530             {"",S_FALSE,FALSE},
1531             {"",S_FALSE,FALSE}
1532         },
1533         {
1534             {Uri_HOST_DNS,S_OK,FALSE},
1535             {0,S_FALSE,FALSE},
1536             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1537             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1538         }
1539     },
1540     /* Hostname get's lower cased for known scheme types. */
1541     {   "http://WWW.GOOGLE.com/", 0, S_OK, FALSE,
1542         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
1543         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
1544         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1545         FALSE,
1546         {
1547             {"http://www.google.com/",S_OK,FALSE},
1548             {"www.google.com",S_OK,FALSE},
1549             {"http://www.google.com/",S_OK,FALSE},
1550             {"google.com",S_OK,FALSE},
1551             {"",S_FALSE,FALSE},
1552             {"",S_FALSE,FALSE},
1553             {"www.google.com",S_OK,FALSE},
1554             {"",S_FALSE,FALSE},
1555             {"/",S_OK,FALSE},
1556             {"/",S_OK,FALSE},
1557             {"",S_FALSE,FALSE},
1558             {"http://WWW.GOOGLE.com/",S_OK,FALSE},
1559             {"http",S_OK,FALSE},
1560             {"",S_FALSE,FALSE},
1561             {"",S_FALSE,FALSE}
1562         },
1563         {
1564             {Uri_HOST_DNS,S_OK,FALSE},
1565             {80,S_OK,FALSE},
1566             {URL_SCHEME_HTTP,S_OK,FALSE},
1567             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1568         }
1569     },
1570     /* Characters that get % encoded in the hostname also have their percent
1571      * encoded forms lower cased.
1572      */
1573     {   "http://www.%7Cgoogle|.com/", 0, S_OK, FALSE,
1574         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
1575         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
1576         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1577         FALSE,
1578         {
1579             {"http://www.%7cgoogle%7c.com/",S_OK,FALSE},
1580             {"www.%7cgoogle%7c.com",S_OK,FALSE},
1581             {"http://www.%7cgoogle%7c.com/",S_OK,FALSE},
1582             {"%7cgoogle%7c.com",S_OK,FALSE},
1583             {"",S_FALSE,FALSE},
1584             {"",S_FALSE,FALSE},
1585             {"www.%7cgoogle%7c.com",S_OK,FALSE},
1586             {"",S_FALSE,FALSE},
1587             {"/",S_OK,FALSE},
1588             {"/",S_OK,FALSE},
1589             {"",S_FALSE,FALSE},
1590             {"http://www.%7Cgoogle|.com/",S_OK,FALSE},
1591             {"http",S_OK,FALSE},
1592             {"",S_FALSE,FALSE},
1593             {"",S_FALSE,FALSE}
1594         },
1595         {
1596             {Uri_HOST_DNS,S_OK,FALSE},
1597             {80,S_OK,FALSE},
1598             {URL_SCHEME_HTTP,S_OK,FALSE},
1599             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1600         }
1601     },
1602     /* IPv4 addresses attached to IPv6 can be included in elisions. */
1603     {   "http://[1:2:3:4:5:6:0.0.0.0]", 0, S_OK, FALSE,
1604         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
1605         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1606         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1607         FALSE,
1608         {
1609             {"http://[1:2:3:4:5:6::]/",S_OK,FALSE},
1610             {"[1:2:3:4:5:6::]",S_OK,FALSE},
1611             {"http://[1:2:3:4:5:6::]/",S_OK,FALSE},
1612             {"",S_FALSE,FALSE},
1613             {"",S_FALSE,FALSE},
1614             {"",S_FALSE,FALSE},
1615             {"1:2:3:4:5:6::",S_OK,FALSE},
1616             {"",S_FALSE,FALSE},
1617             {"/",S_OK,FALSE},
1618             {"/",S_OK,FALSE},
1619             {"",S_FALSE,FALSE},
1620             {"http://[1:2:3:4:5:6:0.0.0.0]",S_OK,FALSE},
1621             {"http",S_OK,FALSE},
1622             {"",S_FALSE,FALSE},
1623             {"",S_FALSE,FALSE},
1624         },
1625         {
1626             {Uri_HOST_IPV6,S_OK,FALSE},
1627             {80,S_OK,FALSE},
1628             {URL_SCHEME_HTTP,S_OK,FALSE},
1629             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1630         }
1631     },
1632     /* IPv4 addresses get normalized. */
1633     {   "http://[::001.002.003.000]", 0, S_OK, FALSE,
1634         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
1635         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1636         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1637         FALSE,
1638         {
1639             {"http://[::1.2.3.0]/",S_OK,FALSE},
1640             {"[::1.2.3.0]",S_OK,FALSE},
1641             {"http://[::1.2.3.0]/",S_OK,FALSE},
1642             {"",S_FALSE,FALSE},
1643             {"",S_FALSE,FALSE},
1644             {"",S_FALSE,FALSE},
1645             {"::1.2.3.0",S_OK,FALSE},
1646             {"",S_FALSE,FALSE},
1647             {"/",S_OK,FALSE},
1648             {"/",S_OK,FALSE},
1649             {"",S_FALSE,FALSE},
1650             {"http://[::001.002.003.000]",S_OK,FALSE},
1651             {"http",S_OK,FALSE},
1652             {"",S_FALSE,FALSE},
1653             {"",S_FALSE,FALSE},
1654         },
1655         {
1656             {Uri_HOST_IPV6,S_OK,FALSE},
1657             {80,S_OK,FALSE},
1658             {URL_SCHEME_HTTP,S_OK,FALSE},
1659             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1660         }
1661     },
1662     /* Windows doesn't do anything to IPv6's in unknown schemes. */
1663     {   "zip://[0001:0:000:0004:0005:0006:001.002.003.000]", 0, S_OK, FALSE,
1664         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
1665         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1666         Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
1667         FALSE,
1668         {
1669             {"zip://[0001:0:000:0004:0005:0006:001.002.003.000]/",S_OK,FALSE},
1670             {"[0001:0:000:0004:0005:0006:001.002.003.000]",S_OK,FALSE},
1671             {"zip://[0001:0:000:0004:0005:0006:001.002.003.000]/",S_OK,FALSE},
1672             {"",S_FALSE,FALSE},
1673             {"",S_FALSE,FALSE},
1674             {"",S_FALSE,FALSE},
1675             {"0001:0:000:0004:0005:0006:001.002.003.000",S_OK,FALSE},
1676             {"",S_FALSE,FALSE},
1677             {"/",S_OK,FALSE},
1678             {"/",S_OK,FALSE},
1679             {"",S_FALSE,FALSE},
1680             {"zip://[0001:0:000:0004:0005:0006:001.002.003.000]",S_OK,FALSE},
1681             {"zip",S_OK,FALSE},
1682             {"",S_FALSE,FALSE},
1683             {"",S_FALSE,FALSE},
1684         },
1685         {
1686             {Uri_HOST_IPV6,S_OK,FALSE},
1687             {0,S_FALSE,FALSE},
1688             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1689             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1690         }
1691     },
1692     /* IPv4 address is converted into 2 h16 components. */
1693     {   "http://[ffff::192.222.111.32]", 0, S_OK, FALSE,
1694         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
1695         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1696         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1697         FALSE,
1698         {
1699             {"http://[ffff::c0de:6f20]/",S_OK,FALSE},
1700             {"[ffff::c0de:6f20]",S_OK,FALSE},
1701             {"http://[ffff::c0de:6f20]/",S_OK,FALSE},
1702             {"",S_FALSE,FALSE},
1703             {"",S_FALSE,FALSE},
1704             {"",S_FALSE,FALSE},
1705             {"ffff::c0de:6f20",S_OK,FALSE},
1706             {"",S_FALSE,FALSE},
1707             {"/",S_OK,FALSE},
1708             {"/",S_OK,FALSE},
1709             {"",S_FALSE,FALSE},
1710             {"http://[ffff::192.222.111.32]",S_OK,FALSE},
1711             {"http",S_OK,FALSE},
1712             {"",S_FALSE,FALSE},
1713             {"",S_FALSE,FALSE},
1714         },
1715         {
1716             {Uri_HOST_IPV6,S_OK,FALSE},
1717             {80,S_OK,FALSE},
1718             {URL_SCHEME_HTTP,S_OK,FALSE},
1719             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1720         }
1721     },
1722     /* Max value for a port. */
1723     {   "http://google.com:65535", 0, S_OK, FALSE,
1724         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
1725         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1726         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1727         FALSE,
1728         {
1729             {"http://google.com:65535/",S_OK,FALSE},
1730             {"google.com:65535",S_OK,FALSE},
1731             {"http://google.com:65535/",S_OK,FALSE},
1732             {"google.com",S_OK,FALSE},
1733             {"",S_FALSE,FALSE},
1734             {"",S_FALSE,FALSE},
1735             {"google.com",S_OK,FALSE},
1736             {"",S_FALSE,FALSE},
1737             {"/",S_OK,FALSE},
1738             {"/",S_OK,FALSE},
1739             {"",S_FALSE,FALSE},
1740             {"http://google.com:65535",S_OK,FALSE},
1741             {"http",S_OK,FALSE},
1742             {"",S_FALSE,FALSE},
1743             {"",S_FALSE,FALSE}
1744         },
1745         {
1746             {Uri_HOST_DNS,S_OK,FALSE},
1747             {65535,S_OK,FALSE},
1748             {URL_SCHEME_HTTP,S_OK,FALSE},
1749             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1750         }
1751     },
1752     {   "zip://google.com:65536", 0, S_OK, FALSE,
1753         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
1754         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1755         Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
1756         FALSE,
1757         {
1758             {"zip://google.com:65536/",S_OK,FALSE},
1759             {"google.com:65536",S_OK,FALSE},
1760             {"zip://google.com:65536/",S_OK,FALSE},
1761             {"google.com:65536",S_OK,FALSE},
1762             {"",S_FALSE,FALSE},
1763             {"",S_FALSE,FALSE},
1764             {"google.com:65536",S_OK,FALSE},
1765             {"",S_FALSE,FALSE},
1766             {"/",S_OK,FALSE},
1767             {"/",S_OK,FALSE},
1768             {"",S_FALSE,FALSE},
1769             {"zip://google.com:65536",S_OK,FALSE},
1770             {"zip",S_OK,FALSE},
1771             {"",S_FALSE,FALSE},
1772             {"",S_FALSE,FALSE}
1773         },
1774         {
1775             {Uri_HOST_DNS,S_OK,FALSE},
1776             {0,S_FALSE,FALSE},
1777             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1778             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1779         }
1780     },
1781     {   "zip://google.com:65536:25", 0, S_OK, FALSE,
1782         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
1783         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1784         Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
1785         FALSE,
1786         {
1787             {"zip://google.com:65536:25/",S_OK,FALSE},
1788             {"google.com:65536:25",S_OK,FALSE},
1789             {"zip://google.com:65536:25/",S_OK,FALSE},
1790             {"google.com:65536:25",S_OK,FALSE},
1791             {"",S_FALSE,FALSE},
1792             {"",S_FALSE,FALSE},
1793             {"google.com:65536:25",S_OK,FALSE},
1794             {"",S_FALSE,FALSE},
1795             {"/",S_OK,FALSE},
1796             {"/",S_OK,FALSE},
1797             {"",S_FALSE,FALSE},
1798             {"zip://google.com:65536:25",S_OK,FALSE},
1799             {"zip",S_OK,FALSE},
1800             {"",S_FALSE,FALSE},
1801             {"",S_FALSE,FALSE}
1802         },
1803         {
1804             {Uri_HOST_DNS,S_OK,FALSE},
1805             {0,S_FALSE,FALSE},
1806             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1807             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1808         }
1809     },
1810     {   "zip://[::ffff]:abcd", 0, S_OK, FALSE,
1811         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|
1812         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1813         Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
1814         FALSE,
1815         {
1816             {"zip://[::ffff]:abcd/",S_OK,FALSE},
1817             {"[::ffff]:abcd",S_OK,FALSE},
1818             {"zip://[::ffff]:abcd/",S_OK,FALSE},
1819             {"",S_FALSE,FALSE},
1820             {"",S_FALSE,FALSE},
1821             {"",S_FALSE,FALSE},
1822             {"[::ffff]:abcd",S_OK,FALSE},
1823             {"",S_FALSE,FALSE},
1824             {"/",S_OK,FALSE},
1825             {"/",S_OK,FALSE},
1826             {"",S_FALSE,FALSE},
1827             {"zip://[::ffff]:abcd",S_OK,FALSE},
1828             {"zip",S_OK,FALSE},
1829             {"",S_FALSE,FALSE},
1830             {"",S_FALSE,FALSE}
1831         },
1832         {
1833             {Uri_HOST_DNS,S_OK,FALSE},
1834             {0,S_FALSE,FALSE},
1835             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1836             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1837         }
1838     },
1839     {   "zip://127.0.0.1:abcd", 0, S_OK, FALSE,
1840         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
1841         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1842         Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
1843         FALSE,
1844         {
1845             {"zip://127.0.0.1:abcd/",S_OK,FALSE},
1846             {"127.0.0.1:abcd",S_OK,FALSE},
1847             {"zip://127.0.0.1:abcd/",S_OK,FALSE},
1848             {"0.1:abcd",S_OK,FALSE},
1849             {"",S_FALSE,FALSE},
1850             {"",S_FALSE,FALSE},
1851             {"127.0.0.1:abcd",S_OK,FALSE},
1852             {"",S_FALSE,FALSE},
1853             {"/",S_OK,FALSE},
1854             {"/",S_OK,FALSE},
1855             {"",S_FALSE,FALSE},
1856             {"zip://127.0.0.1:abcd",S_OK,FALSE},
1857             {"zip",S_OK,FALSE},
1858             {"",S_FALSE,FALSE},
1859             {"",S_FALSE,FALSE}
1860         },
1861         {
1862             {Uri_HOST_DNS,S_OK,FALSE},
1863             {0,S_FALSE,FALSE},
1864             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1865             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1866         }
1867     },
1868     /* Port is just copied over. */
1869     {   "http://google.com:00035", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
1870         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
1871         Uri_HAS_HOST|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1872         FALSE,
1873         {
1874             {"http://google.com:00035",S_OK,FALSE},
1875             {"google.com:00035",S_OK,FALSE},
1876             {"http://google.com:00035",S_OK,FALSE,"http://google.com:35"},
1877             {"google.com",S_OK,FALSE},
1878             {"",S_FALSE,FALSE},
1879             {"",S_FALSE,FALSE},
1880             {"google.com",S_OK,FALSE},
1881             {"",S_FALSE,FALSE},
1882             {"",S_FALSE,FALSE},
1883             {"",S_FALSE,FALSE},
1884             {"",S_FALSE,FALSE},
1885             {"http://google.com:00035",S_OK,FALSE},
1886             {"http",S_OK,FALSE},
1887             {"",S_FALSE,FALSE},
1888             {"",S_FALSE,FALSE}
1889         },
1890         {
1891             {Uri_HOST_DNS,S_OK,FALSE},
1892             {35,S_OK,FALSE},
1893             {URL_SCHEME_HTTP,S_OK,FALSE},
1894             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1895         }
1896     },
1897     /* Default port is copied over. */
1898     {   "http://google.com:80", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
1899         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
1900         Uri_HAS_HOST|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1901         FALSE,
1902         {
1903             {"http://google.com:80",S_OK,FALSE},
1904             {"google.com:80",S_OK,FALSE},
1905             {"http://google.com:80",S_OK,FALSE},
1906             {"google.com",S_OK,FALSE},
1907             {"",S_FALSE,FALSE},
1908             {"",S_FALSE,FALSE},
1909             {"google.com",S_OK,FALSE},
1910             {"",S_FALSE,FALSE},
1911             {"",S_FALSE,FALSE},
1912             {"",S_FALSE,FALSE},
1913             {"",S_FALSE,FALSE},
1914             {"http://google.com:80",S_OK,FALSE},
1915             {"http",S_OK,FALSE},
1916             {"",S_FALSE,FALSE},
1917             {"",S_FALSE,FALSE}
1918         },
1919         {
1920             {Uri_HOST_DNS,S_OK,FALSE},
1921             {80,S_OK,FALSE},
1922             {URL_SCHEME_HTTP,S_OK,FALSE},
1923             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1924         }
1925     },
1926     {   "http://google.com.uk", 0, S_OK, FALSE,
1927         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
1928         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1929         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1930         FALSE,
1931         {
1932             {"http://google.com.uk/",S_OK,FALSE},
1933             {"google.com.uk",S_OK,FALSE},
1934             {"http://google.com.uk/",S_OK,FALSE},
1935             {"google.com.uk",S_OK,FALSE},
1936             {"",S_FALSE,FALSE},
1937             {"",S_FALSE,FALSE},
1938             {"google.com.uk",S_OK,FALSE},
1939             {"",S_FALSE,FALSE},
1940             {"/",S_OK,FALSE},
1941             {"/",S_OK,FALSE},
1942             {"",S_FALSE,FALSE},
1943             {"http://google.com.uk",S_OK,FALSE},
1944             {"http",S_OK,FALSE},
1945             {"",S_FALSE,FALSE},
1946             {"",S_FALSE,FALSE}
1947         },
1948         {
1949             {Uri_HOST_DNS,S_OK,FALSE},
1950             {80,S_OK,FALSE},
1951             {URL_SCHEME_HTTP,S_OK,FALSE},
1952             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1953         }
1954     },
1955     {   "http://google.com.com", 0, S_OK, FALSE,
1956         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
1957         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1958         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1959         FALSE,
1960         {
1961             {"http://google.com.com/",S_OK,FALSE},
1962             {"google.com.com",S_OK,FALSE},
1963             {"http://google.com.com/",S_OK,FALSE},
1964             {"com.com",S_OK,FALSE},
1965             {"",S_FALSE,FALSE},
1966             {"",S_FALSE,FALSE},
1967             {"google.com.com",S_OK,FALSE},
1968             {"",S_FALSE,FALSE},
1969             {"/",S_OK,FALSE},
1970             {"/",S_OK,FALSE},
1971             {"",S_FALSE,FALSE},
1972             {"http://google.com.com",S_OK,FALSE},
1973             {"http",S_OK,FALSE},
1974             {"",S_FALSE,FALSE},
1975             {"",S_FALSE,FALSE}
1976         },
1977         {
1978             {Uri_HOST_DNS,S_OK,FALSE},
1979             {80,S_OK,FALSE},
1980             {URL_SCHEME_HTTP,S_OK,FALSE},
1981             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1982         }
1983     },
1984     {   "http://google.uk.1", 0, S_OK, FALSE,
1985         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
1986         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1987         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1988         FALSE,
1989         {
1990             {"http://google.uk.1/",S_OK,FALSE},
1991             {"google.uk.1",S_OK,FALSE},
1992             {"http://google.uk.1/",S_OK,FALSE},
1993             {"google.uk.1",S_OK,FALSE},
1994             {"",S_FALSE,FALSE},
1995             {"",S_FALSE,FALSE},
1996             {"google.uk.1",S_OK,FALSE},
1997             {"",S_FALSE,FALSE},
1998             {"/",S_OK,FALSE},
1999             {"/",S_OK,FALSE},
2000             {"",S_FALSE,FALSE},
2001             {"http://google.uk.1",S_OK,FALSE},
2002             {"http",S_OK,FALSE},
2003             {"",S_FALSE,FALSE},
2004             {"",S_FALSE,FALSE}
2005         },
2006         {
2007             {Uri_HOST_DNS,S_OK,FALSE},
2008             {80,S_OK,FALSE},
2009             {URL_SCHEME_HTTP,S_OK,FALSE},
2010             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2011         }
2012     },
2013     /* Since foo isn't a recognized 3 character TLD its considered the domain name. */
2014     {   "http://google.foo.uk", 0, S_OK, FALSE,
2015         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
2016         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
2017         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
2018         FALSE,
2019         {
2020             {"http://google.foo.uk/",S_OK,FALSE},
2021             {"google.foo.uk",S_OK,FALSE},
2022             {"http://google.foo.uk/",S_OK,FALSE},
2023             {"foo.uk",S_OK,FALSE},
2024             {"",S_FALSE,FALSE},
2025             {"",S_FALSE,FALSE},
2026             {"google.foo.uk",S_OK,FALSE},
2027             {"",S_FALSE,FALSE},
2028             {"/",S_OK,FALSE},
2029             {"/",S_OK,FALSE},
2030             {"",S_FALSE,FALSE},
2031             {"http://google.foo.uk",S_OK,FALSE},
2032             {"http",S_OK,FALSE},
2033             {"",S_FALSE,FALSE},
2034             {"",S_FALSE,FALSE}
2035         },
2036         {
2037             {Uri_HOST_DNS,S_OK,FALSE},
2038             {80,S_OK,FALSE},
2039             {URL_SCHEME_HTTP,S_OK,FALSE},
2040             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2041         }
2042     },
2043     {   "http://.com", 0, S_OK, FALSE,
2044         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
2045         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
2046         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
2047         FALSE,
2048         {
2049             {"http://.com/",S_OK,FALSE},
2050             {".com",S_OK,FALSE},
2051             {"http://.com/",S_OK,FALSE},
2052             {".com",S_OK,FALSE},
2053             {"",S_FALSE,FALSE},
2054             {"",S_FALSE,FALSE},
2055             {".com",S_OK,FALSE},
2056             {"",S_FALSE,FALSE},
2057             {"/",S_OK,FALSE},
2058             {"/",S_OK,FALSE},
2059             {"",S_FALSE,FALSE},
2060             {"http://.com",S_OK,FALSE},
2061             {"http",S_OK,FALSE},
2062             {"",S_FALSE,FALSE},
2063             {"",S_FALSE,FALSE}
2064         },
2065         {
2066             {Uri_HOST_DNS,S_OK,FALSE},
2067             {80,S_OK,FALSE},
2068             {URL_SCHEME_HTTP,S_OK,FALSE},
2069             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2070         }
2071     },
2072     {   "http://.uk", 0, S_OK, FALSE,
2073         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
2074         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
2075         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
2076         FALSE,
2077         {
2078             {"http://.uk/",S_OK,FALSE},
2079             {".uk",S_OK,FALSE},
2080             {"http://.uk/",S_OK,FALSE},
2081             {"",S_FALSE,FALSE},
2082             {"",S_FALSE,FALSE},
2083             {"",S_FALSE,FALSE},
2084             {".uk",S_OK,FALSE},
2085             {"",S_FALSE,FALSE},
2086             {"/",S_OK,FALSE},
2087             {"/",S_OK,FALSE},
2088             {"",S_FALSE,FALSE},
2089             {"http://.uk",S_OK,FALSE},
2090             {"http",S_OK,FALSE},
2091             {"",S_FALSE,FALSE},
2092             {"",S_FALSE,FALSE}
2093         },
2094         {
2095             {Uri_HOST_DNS,S_OK,FALSE},
2096             {80,S_OK,FALSE},
2097             {URL_SCHEME_HTTP,S_OK,FALSE},
2098             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2099         }
2100     },
2101     {   "http://www.co.google.com.[]", 0, S_OK, FALSE,
2102         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
2103         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
2104         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
2105         FALSE,
2106         {
2107             {"http://www.co.google.com.[]/",S_OK,FALSE},
2108             {"www.co.google.com.[]",S_OK,FALSE},
2109             {"http://www.co.google.com.[]/",S_OK,FALSE},
2110             {"google.com.[]",S_OK,FALSE},
2111             {"",S_FALSE,FALSE},
2112             {"",S_FALSE,FALSE},
2113             {"www.co.google.com.[]",S_OK,FALSE},
2114             {"",S_FALSE,FALSE},
2115             {"/",S_OK,FALSE},
2116             {"/",S_OK,FALSE},
2117             {"",S_FALSE,FALSE},
2118             {"http://www.co.google.com.[]",S_OK,FALSE},
2119             {"http",S_OK,FALSE},
2120             {"",S_FALSE,FALSE},
2121             {"",S_FALSE,FALSE}
2122         },
2123         {
2124             {Uri_HOST_DNS,S_OK,FALSE},
2125             {80,S_OK,FALSE},
2126             {URL_SCHEME_HTTP,S_OK,FALSE},
2127             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2128         }
2129     },
2130     {   "http://co.uk", 0, S_OK, FALSE,
2131         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
2132         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
2133         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
2134         FALSE,
2135         {
2136             {"http://co.uk/",S_OK,FALSE},
2137             {"co.uk",S_OK,FALSE},
2138             {"http://co.uk/",S_OK,FALSE},
2139             {"",S_FALSE,FALSE},
2140             {"",S_FALSE,FALSE},
2141             {"",S_FALSE,FALSE},
2142             {"co.uk",S_OK,FALSE},
2143             {"",S_FALSE,FALSE},
2144             {"/",S_OK,FALSE},
2145             {"/",S_OK,FALSE},
2146             {"",S_FALSE,FALSE},
2147             {"http://co.uk",S_OK,FALSE},
2148             {"http",S_OK,FALSE},
2149             {"",S_FALSE,FALSE},
2150             {"",S_FALSE,FALSE}
2151         },
2152         {
2153             {Uri_HOST_DNS,S_OK,FALSE},
2154             {80,S_OK,FALSE},
2155             {URL_SCHEME_HTTP,S_OK,FALSE},
2156             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2157         }
2158     },
2159     {   "http://www.co.google.us.test", 0, S_OK, FALSE,
2160         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
2161         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
2162         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
2163         FALSE,
2164         {
2165             {"http://www.co.google.us.test/",S_OK,FALSE},
2166             {"www.co.google.us.test",S_OK,FALSE},
2167             {"http://www.co.google.us.test/",S_OK,FALSE},
2168             {"us.test",S_OK,FALSE},
2169             {"",S_FALSE,FALSE},
2170             {"",S_FALSE,FALSE},
2171             {"www.co.google.us.test",S_OK,FALSE},
2172             {"",S_FALSE,FALSE},
2173             {"/",S_OK,FALSE},
2174             {"/",S_OK,FALSE},
2175             {"",S_FALSE,FALSE},
2176             {"http://www.co.google.us.test",S_OK,FALSE},
2177             {"http",S_OK,FALSE},
2178             {"",S_FALSE,FALSE},
2179             {"",S_FALSE,FALSE}
2180         },
2181         {
2182             {Uri_HOST_DNS,S_OK,FALSE},
2183             {80,S_OK,FALSE},
2184             {URL_SCHEME_HTTP,S_OK,FALSE},
2185             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2186         }
2187     },
2188     {   "http://gov.uk", 0, S_OK, FALSE,
2189         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
2190         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
2191         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
2192         FALSE,
2193         {
2194             {"http://gov.uk/",S_OK,FALSE},
2195             {"gov.uk",S_OK,FALSE},
2196             {"http://gov.uk/",S_OK,FALSE},
2197             {"",S_FALSE,FALSE},
2198             {"",S_FALSE,FALSE},
2199             {"",S_FALSE,FALSE},
2200             {"gov.uk",S_OK,FALSE},
2201             {"",S_FALSE,FALSE},
2202             {"/",S_OK,FALSE},
2203             {"/",S_OK,FALSE},
2204             {"",S_FALSE,FALSE},
2205             {"http://gov.uk",S_OK,FALSE},
2206             {"http",S_OK,FALSE},
2207             {"",S_FALSE,FALSE},
2208             {"",S_FALSE,FALSE}
2209         },
2210         {
2211             {Uri_HOST_DNS,S_OK,FALSE},
2212             {80,S_OK,FALSE},
2213             {URL_SCHEME_HTTP,S_OK,FALSE},
2214             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2215         }
2216     },
2217     {   "zip://www.google.com\\test", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
2218         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
2219         Uri_HAS_HOST|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
2220         FALSE,
2221         {
2222             {"zip://www.google.com\\test",S_OK,FALSE},
2223             {"www.google.com\\test",S_OK,FALSE},
2224             {"zip://www.google.com\\test",S_OK,FALSE},
2225             {"google.com\\test",S_OK,FALSE},
2226             {"",S_FALSE,FALSE},
2227             {"",S_FALSE,FALSE},
2228             {"www.google.com\\test",S_OK,FALSE},
2229             {"",S_FALSE,FALSE},
2230             {"",S_FALSE,FALSE},
2231             {"",S_FALSE,FALSE},
2232             {"",S_FALSE,FALSE},
2233             {"zip://www.google.com\\test",S_OK,FALSE},
2234             {"zip",S_OK,FALSE},
2235             {"",S_FALSE,FALSE},
2236             {"",S_FALSE,FALSE}
2237         },
2238         {
2239             {Uri_HOST_DNS,S_OK,FALSE},
2240             {0,S_FALSE,FALSE},
2241             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2242             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2243         }
2244     },
2245     {   "urn:excepts:bad:%XY:encoded", 0, S_OK, FALSE,
2246         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|
2247         Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
2248         FALSE,
2249         {
2250             {"urn:excepts:bad:%XY:encoded",S_OK,FALSE},
2251             {"",S_FALSE,FALSE},
2252             {"urn:excepts:bad:%XY:encoded",S_OK,FALSE},
2253             {"",S_FALSE,FALSE},
2254             {"",S_FALSE,FALSE},
2255             {"",S_FALSE,FALSE},
2256             {"",S_FALSE,FALSE},
2257             {"",S_FALSE,FALSE},
2258             {"excepts:bad:%XY:encoded",S_OK,FALSE},
2259             {"excepts:bad:%XY:encoded",S_OK,FALSE},
2260             {"",S_FALSE,FALSE},
2261             {"urn:excepts:bad:%XY:encoded",S_OK,FALSE},
2262             {"urn",S_OK,FALSE},
2263             {"",S_FALSE,FALSE},
2264             {"",S_FALSE,FALSE}
2265         },
2266         {
2267             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2268             {0,S_FALSE,FALSE},
2269             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2270             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2271         }
2272     },
2273     /* Since the original URI doesn't contain an extra '/' before the path no % encoded values
2274      * are decoded and all '%' are encoded.
2275      */
2276     {   "file://C:/te%3Es%2Et/tes%t.mp3", 0, S_OK, FALSE,
2277         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH|
2278         Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
2279         FALSE,
2280         {
2281             {"file:///C:/te%253Es%252Et/tes%25t.mp3",S_OK,FALSE},
2282             {"",S_FALSE,FALSE},
2283             {"file:///C:/te%253Es%252Et/tes%25t.mp3",S_OK,FALSE},
2284             {"",S_FALSE,FALSE},
2285             {".mp3",S_OK,FALSE},
2286             {"",S_FALSE,FALSE},
2287             {"",S_FALSE,FALSE},
2288             {"",S_FALSE,FALSE},
2289             {"/C:/te%253Es%252Et/tes%25t.mp3",S_OK,FALSE},
2290             {"/C:/te%253Es%252Et/tes%25t.mp3",S_OK,FALSE},
2291             {"",S_FALSE,FALSE},
2292             {"file://C:/te%3Es%2Et/tes%t.mp3",S_OK,FALSE},
2293             {"file",S_OK,FALSE},
2294             {"",S_FALSE,FALSE},
2295             {"",S_FALSE,FALSE}
2296         },
2297         {
2298             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2299             {0,S_FALSE,FALSE},
2300             {URL_SCHEME_FILE,S_OK,FALSE},
2301             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2302         }
2303     },
2304     /* Since there's a '/' in front of the drive letter, any percent encoded, non-forbidden character
2305      * is decoded and only %'s in front of invalid hex digits are encoded.
2306      */
2307     {   "file:///C:/te%3Es%2Et/t%23es%t.mp3", 0, S_OK, FALSE,
2308         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH|
2309         Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
2310         FALSE,
2311         {
2312             {"file:///C:/te%3Es.t/t#es%25t.mp3",S_OK,FALSE},
2313             {"",S_FALSE,FALSE},
2314             {"file:///C:/te%3Es.t/t#es%25t.mp3",S_OK,FALSE},
2315             {"",S_FALSE,FALSE},
2316             {".mp3",S_OK,FALSE},
2317             {"",S_FALSE,FALSE},
2318             {"",S_FALSE,FALSE},
2319             {"",S_FALSE,FALSE},
2320             {"/C:/te%3Es.t/t#es%25t.mp3",S_OK,FALSE},
2321             {"/C:/te%3Es.t/t#es%25t.mp3",S_OK,FALSE},
2322             {"",S_FALSE,FALSE},
2323             {"file:///C:/te%3Es%2Et/t%23es%t.mp3",S_OK,FALSE},
2324             {"file",S_OK,FALSE},
2325             {"",S_FALSE,FALSE},
2326             {"",S_FALSE,FALSE}
2327         },
2328         {
2329             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2330             {0,S_FALSE,FALSE},
2331             {URL_SCHEME_FILE,S_OK,FALSE},
2332             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2333         }
2334     },
2335     /* Only unreserved percent encoded characters are decoded for known schemes that aren't file. */
2336     {   "http://[::001.002.003.000]/%3F%23%2E%54/test", 0, S_OK, FALSE,
2337         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
2338         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
2339         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
2340         FALSE,
2341         {
2342             {"http://[::1.2.3.0]/%3F%23.T/test",S_OK,FALSE},
2343             {"[::1.2.3.0]",S_OK,FALSE},
2344             {"http://[::1.2.3.0]/%3F%23.T/test",S_OK,FALSE},
2345             {"",S_FALSE,FALSE},
2346             {"",S_FALSE,FALSE},
2347             {"",S_FALSE,FALSE},
2348             {"::1.2.3.0",S_OK,FALSE},
2349             {"",S_FALSE,FALSE},
2350             {"/%3F%23.T/test",S_OK,FALSE},
2351             {"/%3F%23.T/test",S_OK,FALSE},
2352             {"",S_FALSE,FALSE},
2353             {"http://[::001.002.003.000]/%3F%23%2E%54/test",S_OK,FALSE},
2354             {"http",S_OK,FALSE},
2355             {"",S_FALSE,FALSE},
2356             {"",S_FALSE,FALSE},
2357         },
2358         {
2359             {Uri_HOST_IPV6,S_OK,FALSE},
2360             {80,S_OK,FALSE},
2361             {URL_SCHEME_HTTP,S_OK,FALSE},
2362             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2363         }
2364     },
2365     /* Forbidden characters are always encoded for file URIs. */
2366     {   "file:///C:/\"test\"/test.mp3", Uri_CREATE_NO_ENCODE_FORBIDDEN_CHARACTERS, S_OK, FALSE,
2367         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH|
2368         Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
2369         FALSE,
2370         {
2371             {"file:///C:/%22test%22/test.mp3",S_OK,FALSE},
2372             {"",S_FALSE,FALSE},
2373             {"file:///C:/%22test%22/test.mp3",S_OK,FALSE},
2374             {"",S_FALSE,FALSE},
2375             {".mp3",S_OK,FALSE},
2376             {"",S_FALSE,FALSE},
2377             {"",S_FALSE,FALSE},
2378             {"",S_FALSE,FALSE},
2379             {"/C:/%22test%22/test.mp3",S_OK,FALSE},
2380             {"/C:/%22test%22/test.mp3",S_OK,FALSE},
2381             {"",S_FALSE,FALSE},
2382             {"file:///C:/\"test\"/test.mp3",S_OK,FALSE},
2383             {"file",S_OK,FALSE},
2384             {"",S_FALSE,FALSE},
2385             {"",S_FALSE,FALSE}
2386         },
2387         {
2388             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2389             {0,S_FALSE,FALSE},
2390             {URL_SCHEME_FILE,S_OK,FALSE},
2391             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2392         }
2393     },
2394     /* Forbidden characters are never encoded for unknown scheme types. */
2395     {   "1234://4294967295/<|>\" test<|>", 0, S_OK, FALSE,
2396         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
2397         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
2398         Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
2399         FALSE,
2400         {
2401             {"1234://4294967295/<|>\" test<|>",S_OK,FALSE},
2402             {"4294967295",S_OK,FALSE},
2403             {"1234://4294967295/<|>\" test<|>",S_OK,FALSE},
2404             {"",S_FALSE,FALSE},
2405             {"",S_FALSE,FALSE},
2406             {"",S_FALSE,FALSE},
2407             {"4294967295",S_OK,FALSE},
2408             {"",S_FALSE,FALSE},
2409             {"/<|>\" test<|>",S_OK,FALSE},
2410             {"/<|>\" test<|>",S_OK,FALSE},
2411             {"",S_FALSE,FALSE},
2412             {"1234://4294967295/<|>\" test<|>",S_OK,FALSE},
2413             {"1234",S_OK,FALSE},
2414             {"",S_FALSE,FALSE},
2415             {"",S_FALSE,FALSE}
2416         },
2417         {
2418             {Uri_HOST_IPV4,S_OK,FALSE},
2419             {0,S_FALSE,FALSE},
2420             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2421             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2422         }
2423     },
2424     /* Make sure forbidden characters are percent encoded. */
2425     {   "http://gov.uk/<|> test<|>", 0, S_OK, FALSE,
2426         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
2427         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
2428         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
2429         FALSE,
2430         {
2431             {"http://gov.uk/%3C%7C%3E%20test%3C%7C%3E",S_OK,FALSE},
2432             {"gov.uk",S_OK,FALSE},
2433             {"http://gov.uk/%3C%7C%3E%20test%3C%7C%3E",S_OK,FALSE},
2434             {"",S_FALSE,FALSE},
2435             {"",S_FALSE,FALSE},
2436             {"",S_FALSE,FALSE},
2437             {"gov.uk",S_OK,FALSE},
2438             {"",S_FALSE,FALSE},
2439             {"/%3C%7C%3E%20test%3C%7C%3E",S_OK,FALSE},
2440             {"/%3C%7C%3E%20test%3C%7C%3E",S_OK,FALSE},
2441             {"",S_FALSE,FALSE},
2442             {"http://gov.uk/<|> test<|>",S_OK,FALSE},
2443             {"http",S_OK,FALSE},
2444             {"",S_FALSE,FALSE},
2445             {"",S_FALSE,FALSE}
2446         },
2447         {
2448             {Uri_HOST_DNS,S_OK,FALSE},
2449             {80,S_OK,FALSE},
2450             {URL_SCHEME_HTTP,S_OK,FALSE},
2451             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2452         }
2453     },
2454     {   "http://gov.uk/test/../test2/././../test3/.././././", 0, S_OK, FALSE,
2455         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
2456         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
2457         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
2458         FALSE,
2459         {
2460             {"http://gov.uk/",S_OK,FALSE},
2461             {"gov.uk",S_OK,FALSE},
2462             {"http://gov.uk/",S_OK,FALSE},
2463             {"",S_FALSE,FALSE},
2464             {"",S_FALSE,FALSE},
2465             {"",S_FALSE,FALSE},
2466             {"gov.uk",S_OK,FALSE},
2467             {"",S_FALSE,FALSE},
2468             {"/",S_OK,FALSE},
2469             {"/",S_OK,FALSE},
2470             {"",S_FALSE,FALSE},
2471             {"http://gov.uk/test/../test2/././../test3/.././././",S_OK,FALSE},
2472             {"http",S_OK,FALSE},
2473             {"",S_FALSE,FALSE},
2474             {"",S_FALSE,FALSE}
2475         },
2476         {
2477             {Uri_HOST_DNS,S_OK,FALSE},
2478             {80,S_OK,FALSE},
2479             {URL_SCHEME_HTTP,S_OK,FALSE},
2480             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2481         }
2482     },
2483     {   "http://gov.uk/test/test2/../../..", 0, S_OK, FALSE,
2484         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
2485         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
2486         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
2487         FALSE,
2488         {
2489             {"http://gov.uk/",S_OK,FALSE},
2490             {"gov.uk",S_OK,FALSE},
2491             {"http://gov.uk/",S_OK,FALSE},
2492             {"",S_FALSE,FALSE},
2493             {"",S_FALSE,FALSE},
2494             {"",S_FALSE,FALSE},
2495             {"gov.uk",S_OK,FALSE},
2496             {"",S_FALSE,FALSE},
2497             {"/",S_OK,FALSE},
2498             {"/",S_OK,FALSE},
2499             {"",S_FALSE,FALSE},
2500             {"http://gov.uk/test/test2/../../..",S_OK,FALSE},
2501             {"http",S_OK,FALSE},
2502             {"",S_FALSE,FALSE},
2503             {"",S_FALSE,FALSE}
2504         },
2505         {
2506             {Uri_HOST_DNS,S_OK,FALSE},
2507             {80,S_OK,FALSE},
2508             {URL_SCHEME_HTTP,S_OK,FALSE},
2509             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2510         }
2511     },
2512     {   "http://gov.uk/test/test2/../../.", 0, S_OK, FALSE,
2513         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
2514         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
2515         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
2516         FALSE,
2517         {
2518             {"http://gov.uk/",S_OK,FALSE},
2519             {"gov.uk",S_OK,FALSE},
2520             {"http://gov.uk/",S_OK,FALSE},
2521             {"",S_FALSE,FALSE},
2522             {"",S_FALSE,FALSE},
2523             {"",S_FALSE,FALSE},
2524             {"gov.uk",S_OK,FALSE},
2525             {"",S_FALSE,FALSE},
2526             {"/",S_OK,FALSE},
2527             {"/",S_OK,FALSE},
2528             {"",S_FALSE,FALSE},
2529             {"http://gov.uk/test/test2/../../.",S_OK,FALSE},
2530             {"http",S_OK,FALSE},
2531             {"",S_FALSE,FALSE},
2532             {"",S_FALSE,FALSE}
2533         },
2534         {
2535             {Uri_HOST_DNS,S_OK,FALSE},
2536             {80,S_OK,FALSE},
2537             {URL_SCHEME_HTTP,S_OK,FALSE},
2538             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2539         }
2540     },
2541     {   "file://c:\\tests\\../tests\\./.\\..\\foo%20bar.mp3", 0, S_OK, FALSE,
2542         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH|
2543         Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
2544         FALSE,
2545         {
2546             {"file:///c:/foo%2520bar.mp3",S_OK,FALSE},
2547             {"",S_FALSE,FALSE},
2548             {"file:///c:/foo%2520bar.mp3",S_OK,FALSE},
2549             {"",S_FALSE,FALSE},
2550             {".mp3",S_OK,FALSE},
2551             {"",S_FALSE,FALSE},
2552             {"",S_FALSE,FALSE},
2553             {"",S_FALSE,FALSE},
2554             {"/c:/foo%2520bar.mp3",S_OK,FALSE},
2555             {"/c:/foo%2520bar.mp3",S_OK,FALSE},
2556             {"",S_FALSE,FALSE},
2557             {"file://c:\\tests\\../tests\\./.\\..\\foo%20bar.mp3",S_OK,FALSE},
2558             {"file",S_OK,FALSE},
2559             {"",S_FALSE,FALSE},
2560             {"",S_FALSE,FALSE}
2561         },
2562         {
2563             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2564             {0,S_FALSE,FALSE},
2565             {URL_SCHEME_FILE,S_OK,FALSE},
2566             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2567         }
2568     },
2569     /* Dot removal happens for unknown scheme types. */
2570     {   "zip://gov.uk/test/test2/../../.", 0, S_OK, FALSE,
2571         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
2572         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
2573         Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
2574         FALSE,
2575         {
2576             {"zip://gov.uk/",S_OK,FALSE},
2577             {"gov.uk",S_OK,FALSE},
2578             {"zip://gov.uk/",S_OK,FALSE},
2579             {"",S_FALSE,FALSE},
2580             {"",S_FALSE,FALSE},
2581             {"",S_FALSE,FALSE},
2582             {"gov.uk",S_OK,FALSE},
2583             {"",S_FALSE,FALSE},
2584             {"/",S_OK,FALSE},
2585             {"/",S_OK,FALSE},
2586             {"",S_FALSE,FALSE},
2587             {"zip://gov.uk/test/test2/../../.",S_OK,FALSE},
2588             {"zip",S_OK,FALSE},
2589             {"",S_FALSE,FALSE},
2590             {"",S_FALSE,FALSE}
2591         },
2592         {
2593             {Uri_HOST_DNS,S_OK,FALSE},
2594             {0,S_FALSE,FALSE},
2595             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2596             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2597         }
2598     },
2599     /* Dot removal doesn't happen if NO_CANONICALIZE is set. */
2600     {   "http://gov.uk/test/test2/../../.", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
2601         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|
2602         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
2603         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
2604         FALSE,
2605         {
2606             {"http://gov.uk/test/test2/../../.",S_OK,FALSE},
2607             {"gov.uk",S_OK,FALSE},
2608             {"http://gov.uk/test/test2/../../.",S_OK,FALSE},
2609             {"",S_FALSE,FALSE},
2610             {".",S_OK,FALSE},
2611             {"",S_FALSE,FALSE},
2612             {"gov.uk",S_OK,FALSE},
2613             {"",S_FALSE,FALSE},
2614             {"/test/test2/../../.",S_OK,FALSE},
2615             {"/test/test2/../../.",S_OK,FALSE},
2616             {"",S_FALSE,FALSE},
2617             {"http://gov.uk/test/test2/../../.",S_OK,FALSE},
2618             {"http",S_OK,FALSE},
2619             {"",S_FALSE,FALSE},
2620             {"",S_FALSE,FALSE}
2621         },
2622         {
2623             {Uri_HOST_DNS,S_OK,FALSE},
2624             {80,S_OK,FALSE},
2625             {URL_SCHEME_HTTP,S_OK,FALSE},
2626             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2627         }
2628     },
2629     /* Dot removal doesn't happen for wildcard scheme types. */
2630     {   "*:gov.uk/test/test2/../../.", 0, S_OK, FALSE,
2631         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|
2632         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
2633         Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
2634         FALSE,
2635         {
2636             {"*:gov.uk/test/test2/../../.",S_OK,FALSE},
2637             {"gov.uk",S_OK,FALSE},
2638             {"*:gov.uk/test/test2/../../.",S_OK,FALSE},
2639             {"",S_FALSE,FALSE},
2640             {".",S_OK,FALSE},
2641             {"",S_FALSE,FALSE},
2642             {"gov.uk",S_OK,FALSE},
2643             {"",S_FALSE,FALSE},
2644             {"/test/test2/../../.",S_OK,FALSE},
2645             {"/test/test2/../../.",S_OK,FALSE},
2646             {"",S_FALSE,FALSE},
2647             {"*:gov.uk/test/test2/../../.",S_OK,FALSE},
2648             {"*",S_OK,FALSE},
2649             {"",S_FALSE,FALSE},
2650             {"",S_FALSE,FALSE}
2651         },
2652         {
2653             {Uri_HOST_DNS,S_OK,FALSE},
2654             {0,S_FALSE,FALSE},
2655             {URL_SCHEME_WILDCARD,S_OK,FALSE},
2656             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2657         }
2658     },
2659     /* Forbidden characters are encoded for opaque known scheme types. */
2660     {   "mailto:\"acco<|>unt@example.com\"", 0, S_OK, FALSE,
2661         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|
2662         Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
2663         FALSE,
2664         {
2665             {"mailto:%22acco%3C%7C%3Eunt@example.com%22",S_OK,FALSE},
2666             {"",S_FALSE,FALSE},
2667             {"mailto:%22acco%3C%7C%3Eunt@example.com%22",S_OK,FALSE},
2668             {"",S_FALSE,FALSE},
2669             {".com%22",S_OK,FALSE},
2670             {"",S_FALSE,FALSE},
2671             {"",S_FALSE,FALSE},
2672             {"",S_FALSE,FALSE},
2673             {"%22acco%3C%7C%3Eunt@example.com%22",S_OK,FALSE},
2674             {"%22acco%3C%7C%3Eunt@example.com%22",S_OK,FALSE},
2675             {"",S_FALSE,FALSE},
2676             {"mailto:\"acco<|>unt@example.com\"",S_OK,FALSE},
2677             {"mailto",S_OK,FALSE},
2678             {"",S_FALSE,FALSE},
2679             {"",S_FALSE,FALSE}
2680         },
2681         {
2682             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2683             {0,S_FALSE,FALSE},
2684             {URL_SCHEME_MAILTO,S_OK,FALSE},
2685             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2686         }
2687     },
2688     {   "news:test.tes<|>t.com", 0, S_OK, FALSE,
2689         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|
2690         Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
2691         FALSE,
2692         {
2693             {"news:test.tes%3C%7C%3Et.com",S_OK,FALSE},
2694             {"",S_FALSE,FALSE},
2695             {"news:test.tes%3C%7C%3Et.com",S_OK,FALSE},
2696             {"",S_FALSE,FALSE},
2697             {".com",S_OK,FALSE},
2698             {"",S_FALSE,FALSE},
2699             {"",S_FALSE,FALSE},
2700             {"",S_FALSE,FALSE},
2701             {"test.tes%3C%7C%3Et.com",S_OK,FALSE},
2702             {"test.tes%3C%7C%3Et.com",S_OK,FALSE},
2703             {"",S_FALSE,FALSE},
2704             {"news:test.tes<|>t.com",S_OK,FALSE},
2705             {"news",S_OK,FALSE},
2706             {"",S_FALSE,FALSE},
2707             {"",S_FALSE,FALSE}
2708         },
2709         {
2710             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2711             {0,S_FALSE,FALSE},
2712             {URL_SCHEME_NEWS,S_OK,FALSE},
2713             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2714         }
2715     },
2716     /* Don't encode forbidden characters. */
2717     {   "news:test.tes<|>t.com", Uri_CREATE_NO_ENCODE_FORBIDDEN_CHARACTERS, S_OK, FALSE,
2718         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|
2719         Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
2720         FALSE,
2721         {
2722             {"news:test.tes<|>t.com",S_OK,FALSE},
2723             {"",S_FALSE,FALSE},
2724             {"news:test.tes<|>t.com",S_OK,FALSE},
2725             {"",S_FALSE,FALSE},
2726             {".com",S_OK,FALSE},
2727             {"",S_FALSE,FALSE},
2728             {"",S_FALSE,FALSE},
2729             {"",S_FALSE,FALSE},
2730             {"test.tes<|>t.com",S_OK,FALSE},
2731             {"test.tes<|>t.com",S_OK,FALSE},
2732             {"",S_FALSE,FALSE},
2733             {"news:test.tes<|>t.com",S_OK,FALSE},
2734             {"news",S_OK,FALSE},
2735             {"",S_FALSE,FALSE},
2736             {"",S_FALSE,FALSE}
2737         },
2738         {
2739             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2740             {0,S_FALSE,FALSE},
2741             {URL_SCHEME_NEWS,S_OK,FALSE},
2742             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2743         }
2744     },
2745     /* Forbidden characters aren't encoded for unknown, opaque URIs. */
2746     {   "urn:test.tes<|>t.com", 0, S_OK, FALSE,
2747         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|
2748         Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
2749         FALSE,
2750         {
2751             {"urn:test.tes<|>t.com",S_OK,FALSE},
2752             {"",S_FALSE,FALSE},
2753             {"urn:test.tes<|>t.com",S_OK,FALSE},
2754             {"",S_FALSE,FALSE},
2755             {".com",S_OK,FALSE},
2756             {"",S_FALSE,FALSE},
2757             {"",S_FALSE,FALSE},
2758             {"",S_FALSE,FALSE},
2759             {"test.tes<|>t.com",S_OK,FALSE},
2760             {"test.tes<|>t.com",S_OK,FALSE},
2761             {"",S_FALSE,FALSE},
2762             {"urn:test.tes<|>t.com",S_OK,FALSE},
2763             {"urn",S_OK,FALSE},
2764             {"",S_FALSE,FALSE},
2765             {"",S_FALSE,FALSE}
2766         },
2767         {
2768             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2769             {0,S_FALSE,FALSE},
2770             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2771             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2772         }
2773     },
2774     /* Percent encoded unreserved characters are decoded for known opaque URIs. */
2775     {   "news:test.%74%65%73%74.com", 0, S_OK, FALSE,
2776         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|
2777         Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
2778         FALSE,
2779         {
2780             {"news:test.test.com",S_OK,FALSE},
2781             {"",S_FALSE,FALSE},
2782             {"news:test.test.com",S_OK,FALSE},
2783             {"",S_FALSE,FALSE},
2784             {".com",S_OK,FALSE},
2785             {"",S_FALSE,FALSE},
2786             {"",S_FALSE,FALSE},
2787             {"",S_FALSE,FALSE},
2788             {"test.test.com",S_OK,FALSE},
2789             {"test.test.com",S_OK,FALSE},
2790             {"",S_FALSE,FALSE},
2791             {"news:test.%74%65%73%74.com",S_OK,FALSE},
2792             {"news",S_OK,FALSE},
2793             {"",S_FALSE,FALSE},
2794             {"",S_FALSE,FALSE}
2795         },
2796         {
2797             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2798             {0,S_FALSE,FALSE},
2799             {URL_SCHEME_NEWS,S_OK,FALSE},
2800             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2801         }
2802     },
2803     /* Percent encoded characters are still decoded for known scheme types. */
2804     {   "news:test.%74%65%73%74.com", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
2805         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|
2806         Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
2807         FALSE,
2808         {
2809             {"news:test.test.com",S_OK,FALSE},
2810             {"",S_FALSE,FALSE},
2811             {"news:test.test.com",S_OK,FALSE},
2812             {"",S_FALSE,FALSE},
2813             {".com",S_OK,FALSE},
2814             {"",S_FALSE,FALSE},
2815             {"",S_FALSE,FALSE},
2816             {"",S_FALSE,FALSE},
2817             {"test.test.com",S_OK,FALSE},
2818             {"test.test.com",S_OK,FALSE},
2819             {"",S_FALSE,FALSE},
2820             {"news:test.%74%65%73%74.com",S_OK,FALSE},
2821             {"news",S_OK,FALSE},
2822             {"",S_FALSE,FALSE},
2823             {"",S_FALSE,FALSE}
2824         },
2825         {
2826             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2827             {0,S_FALSE,FALSE},
2828             {URL_SCHEME_NEWS,S_OK,FALSE},
2829             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2830         }
2831     },
2832     /* Percent encoded characters aren't decoded for unknown scheme types. */
2833     {   "urn:test.%74%65%73%74.com", 0, S_OK, FALSE,
2834         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|
2835         Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
2836         FALSE,
2837         {
2838             {"urn:test.%74%65%73%74.com",S_OK,FALSE},
2839             {"",S_FALSE,FALSE},
2840             {"urn:test.%74%65%73%74.com",S_OK,FALSE},
2841             {"",S_FALSE,FALSE},
2842             {".com",S_OK,FALSE},
2843             {"",S_FALSE,FALSE},
2844             {"",S_FALSE,FALSE},
2845             {"",S_FALSE,FALSE},
2846             {"test.%74%65%73%74.com",S_OK,FALSE},
2847             {"test.%74%65%73%74.com",S_OK,FALSE},
2848             {"",S_FALSE,FALSE},
2849             {"urn:test.%74%65%73%74.com",S_OK,FALSE},
2850             {"urn",S_OK,FALSE},
2851             {"",S_FALSE,FALSE},
2852             {"",S_FALSE,FALSE}
2853         },
2854         {
2855             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2856             {0,S_FALSE,FALSE},
2857             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2858             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2859         }
2860     },
2861     /* Unknown scheme types can have invalid % encoded data in query string. */
2862     {   "zip://www.winehq.org/tests/..?query=%xx&return=y", 0, S_OK, FALSE,
2863         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_HOST|
2864         Uri_HAS_DOMAIN|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_QUERY|Uri_HAS_RAW_URI|
2865         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
2866         FALSE,
2867         {
2868             {"zip://www.winehq.org/?query=%xx&return=y",S_OK,FALSE},
2869             {"www.winehq.org",S_OK,FALSE},
2870             {"zip://www.winehq.org/?query=%xx&return=y",S_OK,FALSE},
2871             {"winehq.org",S_OK,FALSE},
2872             {"",S_FALSE,FALSE},
2873             {"",S_FALSE,FALSE},
2874             {"www.winehq.org",S_OK,FALSE},
2875             {"",S_FALSE,FALSE},
2876             {"/",S_OK,FALSE},
2877             {"/?query=%xx&return=y",S_OK,FALSE},
2878             {"?query=%xx&return=y",S_OK,FALSE},
2879             {"zip://www.winehq.org/tests/..?query=%xx&return=y",S_OK,FALSE},
2880             {"zip",S_OK,FALSE},
2881             {"",S_FALSE,FALSE},
2882             {"",S_FALSE,FALSE}
2883         },
2884         {
2885             {Uri_HOST_DNS,S_OK,FALSE},
2886             {0,S_FALSE,FALSE},
2887             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2888             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2889         }
2890     },
2891     /* Known scheme types can have invalid % encoded data with the right flags. */
2892     {   "http://www.winehq.org/tests/..?query=%xx&return=y", Uri_CREATE_NO_DECODE_EXTRA_INFO, S_OK, FALSE,
2893         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_HOST|
2894         Uri_HAS_DOMAIN|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_PORT|Uri_HAS_QUERY|Uri_HAS_RAW_URI|
2895         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
2896         FALSE,
2897         {
2898             {"http://www.winehq.org/?query=%xx&return=y",S_OK,FALSE},
2899             {"www.winehq.org",S_OK,FALSE},
2900             {"http://www.winehq.org/?query=%xx&return=y",S_OK,FALSE},
2901             {"winehq.org",S_OK,FALSE},
2902             {"",S_FALSE,FALSE},
2903             {"",S_FALSE,FALSE},
2904             {"www.winehq.org",S_OK,FALSE},
2905             {"",S_FALSE,FALSE},
2906             {"/",S_OK,FALSE},
2907             {"/?query=%xx&return=y",S_OK,FALSE},
2908             {"?query=%xx&return=y",S_OK,FALSE},
2909             {"http://www.winehq.org/tests/..?query=%xx&return=y",S_OK,FALSE},
2910             {"http",S_OK,FALSE},
2911             {"",S_FALSE,FALSE},
2912             {"",S_FALSE,FALSE}
2913         },
2914         {
2915             {Uri_HOST_DNS,S_OK,FALSE},
2916             {80,S_OK,FALSE},
2917             {URL_SCHEME_HTTP,S_OK,FALSE},
2918             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2919         }
2920     },
2921     /* Forbidden characters in query aren't percent encoded for known scheme types with this flag. */
2922     {   "http://www.winehq.org/tests/..?query=<|>&return=y", Uri_CREATE_NO_DECODE_EXTRA_INFO, S_OK, FALSE,
2923         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_HOST|
2924         Uri_HAS_DOMAIN|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_PORT|Uri_HAS_QUERY|Uri_HAS_RAW_URI|
2925         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
2926         FALSE,
2927         {
2928             {"http://www.winehq.org/?query=<|>&return=y",S_OK,FALSE},
2929             {"www.winehq.org",S_OK,FALSE},
2930             {"http://www.winehq.org/?query=<|>&return=y",S_OK,FALSE},
2931             {"winehq.org",S_OK,FALSE},
2932             {"",S_FALSE,FALSE},
2933             {"",S_FALSE,FALSE},
2934             {"www.winehq.org",S_OK,FALSE},
2935             {"",S_FALSE,FALSE},
2936             {"/",S_OK,FALSE},
2937             {"/?query=<|>&return=y",S_OK,FALSE},
2938             {"?query=<|>&return=y",S_OK,FALSE},
2939             {"http://www.winehq.org/tests/..?query=<|>&return=y",S_OK,FALSE},
2940             {"http",S_OK,FALSE},
2941             {"",S_FALSE,FALSE},
2942             {"",S_FALSE,FALSE}
2943         },
2944         {
2945             {Uri_HOST_DNS,S_OK,FALSE},
2946             {80,S_OK,FALSE},
2947             {URL_SCHEME_HTTP,S_OK,FALSE},
2948             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2949         }
2950     },
2951     /* Forbidden characters in query aren't percent encoded for known scheme types with this flag. */
2952     {   "http://www.winehq.org/tests/..?query=<|>&return=y", Uri_CREATE_NO_ENCODE_FORBIDDEN_CHARACTERS, S_OK, FALSE,
2953         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_HOST|
2954         Uri_HAS_DOMAIN|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_PORT|Uri_HAS_QUERY|Uri_HAS_RAW_URI|
2955         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
2956         FALSE,
2957         {
2958             {"http://www.winehq.org/?query=<|>&return=y",S_OK,FALSE},
2959             {"www.winehq.org",S_OK,FALSE},
2960             {"http://www.winehq.org/?query=<|>&return=y",S_OK,FALSE},
2961             {"winehq.org",S_OK,FALSE},
2962             {"",S_FALSE,FALSE},
2963             {"",S_FALSE,FALSE},
2964             {"www.winehq.org",S_OK,FALSE},
2965             {"",S_FALSE,FALSE},
2966             {"/",S_OK,FALSE},
2967             {"/?query=<|>&return=y",S_OK,FALSE},
2968             {"?query=<|>&return=y",S_OK,FALSE},
2969             {"http://www.winehq.org/tests/..?query=<|>&return=y",S_OK,FALSE},
2970             {"http",S_OK,FALSE},
2971             {"",S_FALSE,FALSE},
2972             {"",S_FALSE,FALSE}
2973         },
2974         {
2975             {Uri_HOST_DNS,S_OK,FALSE},
2976             {80,S_OK,FALSE},
2977             {URL_SCHEME_HTTP,S_OK,FALSE},
2978             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2979         }
2980     },
2981     /* Forbidden characters are encoded for known scheme types. */
2982     {   "http://www.winehq.org/tests/..?query=<|>&return=y", 0, S_OK, FALSE,
2983         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_HOST|
2984         Uri_HAS_DOMAIN|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_PORT|Uri_HAS_QUERY|Uri_HAS_RAW_URI|
2985         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
2986         FALSE,
2987         {
2988             {"http://www.winehq.org/?query=%3C%7C%3E&return=y",S_OK,FALSE},
2989             {"www.winehq.org",S_OK,FALSE},
2990             {"http://www.winehq.org/?query=%3C%7C%3E&return=y",S_OK,FALSE},
2991             {"winehq.org",S_OK,FALSE},
2992             {"",S_FALSE,FALSE},
2993             {"",S_FALSE,FALSE},
2994             {"www.winehq.org",S_OK,FALSE},
2995             {"",S_FALSE,FALSE},
2996             {"/",S_OK,FALSE},
2997             {"/?query=%3C%7C%3E&return=y",S_OK,FALSE},
2998             {"?query=%3C%7C%3E&return=y",S_OK,FALSE},
2999             {"http://www.winehq.org/tests/..?query=<|>&return=y",S_OK,FALSE},
3000             {"http",S_OK,FALSE},
3001             {"",S_FALSE,FALSE},
3002             {"",S_FALSE,FALSE}
3003         },
3004         {
3005             {Uri_HOST_DNS,S_OK,FALSE},
3006             {80,S_OK,FALSE},
3007             {URL_SCHEME_HTTP,S_OK,FALSE},
3008             {URLZONE_INVALID,E_NOTIMPL,FALSE},
3009         }
3010     },
3011     /* Forbidden characters are not encoded for unknown scheme types. */
3012     {   "zip://www.winehq.org/tests/..?query=<|>&return=y", 0, S_OK, FALSE,
3013         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_HOST|
3014         Uri_HAS_DOMAIN|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_QUERY|Uri_HAS_RAW_URI|
3015         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
3016         FALSE,
3017         {
3018             {"zip://www.winehq.org/?query=<|>&return=y",S_OK,FALSE},
3019             {"www.winehq.org",S_OK,FALSE},
3020             {"zip://www.winehq.org/?query=<|>&return=y",S_OK,FALSE},
3021             {"winehq.org",S_OK,FALSE},
3022             {"",S_FALSE,FALSE},
3023             {"",S_FALSE,FALSE},
3024             {"www.winehq.org",S_OK,FALSE},
3025             {"",S_FALSE,FALSE},
3026             {"/",S_OK,FALSE},
3027             {"/?query=<|>&return=y",S_OK,FALSE},
3028             {"?query=<|>&return=y",S_OK,FALSE},
3029             {"zip://www.winehq.org/tests/..?query=<|>&return=y",S_OK,FALSE},
3030             {"zip",S_OK,FALSE},
3031             {"",S_FALSE,FALSE},
3032             {"",S_FALSE,FALSE}
3033         },
3034         {
3035             {Uri_HOST_DNS,S_OK,FALSE},
3036             {0,S_FALSE,FALSE},
3037             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
3038             {URLZONE_INVALID,E_NOTIMPL,FALSE},
3039         }
3040     },
3041     /* Percent encoded, unreserved characters are decoded for known scheme types. */
3042     {   "http://www.winehq.org/tests/..?query=%30%31&return=y", 0, S_OK, FALSE,
3043         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_HOST|
3044         Uri_HAS_DOMAIN|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_PORT|Uri_HAS_QUERY|Uri_HAS_RAW_URI|
3045         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
3046         FALSE,
3047         {
3048             {"http://www.winehq.org/?query=01&return=y",S_OK,FALSE},
3049             {"www.winehq.org",S_OK,FALSE},
3050             {"http://www.winehq.org/?query=01&return=y",S_OK,FALSE},
3051             {"winehq.org",S_OK,FALSE},
3052             {"",S_FALSE,FALSE},
3053             {"",S_FALSE,FALSE},
3054             {"www.winehq.org",S_OK,FALSE},
3055             {"",S_FALSE,FALSE},
3056             {"/",S_OK,FALSE},
3057             {"/?query=01&return=y",S_OK,FALSE},
3058             {"?query=01&return=y",S_OK,FALSE},
3059             {"http://www.winehq.org/tests/..?query=%30%31&return=y",S_OK,FALSE},
3060             {"http",S_OK,FALSE},
3061             {"",S_FALSE,FALSE},
3062             {"",S_FALSE,FALSE}
3063         },
3064         {
3065             {Uri_HOST_DNS,S_OK,FALSE},
3066             {80,S_OK,FALSE},
3067             {URL_SCHEME_HTTP,S_OK,FALSE},
3068             {URLZONE_INVALID,E_NOTIMPL,FALSE},
3069         }
3070     },
3071     /* Percent encoded, unreserved characters aren't decoded for unknown scheme types. */
3072     {   "zip://www.winehq.org/tests/..?query=%30%31&return=y", 0, S_OK, FALSE,
3073         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_HOST|
3074         Uri_HAS_DOMAIN|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_QUERY|Uri_HAS_RAW_URI|
3075         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
3076         FALSE,
3077         {
3078             {"zip://www.winehq.org/?query=%30%31&return=y",S_OK,FALSE},
3079             {"www.winehq.org",S_OK,FALSE},
3080             {"zip://www.winehq.org/?query=%30%31&return=y",S_OK,FALSE},
3081             {"winehq.org",S_OK,FALSE},
3082             {"",S_FALSE,FALSE},
3083             {"",S_FALSE,FALSE},
3084             {"www.winehq.org",S_OK,FALSE},
3085             {"",S_FALSE,FALSE},
3086             {"/",S_OK,FALSE},
3087             {"/?query=%30%31&return=y",S_OK,FALSE},
3088             {"?query=%30%31&return=y",S_OK,FALSE},
3089             {"zip://www.winehq.org/tests/..?query=%30%31&return=y",S_OK,FALSE},
3090             {"zip",S_OK,FALSE},
3091             {"",S_FALSE,FALSE},
3092             {"",S_FALSE,FALSE}
3093         },
3094         {
3095             {Uri_HOST_DNS,S_OK,FALSE},
3096             {0,S_FALSE,FALSE},
3097             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
3098             {URLZONE_INVALID,E_NOTIMPL,FALSE},
3099         }
3100     },
3101     /* Percent encoded characters aren't decoded when NO_DECODE_EXTRA_INFO is set. */
3102     {   "http://www.winehq.org/tests/..?query=%30%31&return=y", Uri_CREATE_NO_DECODE_EXTRA_INFO, S_OK, FALSE,
3103         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_HOST|
3104         Uri_HAS_DOMAIN|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_PORT|Uri_HAS_QUERY|Uri_HAS_RAW_URI|
3105         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
3106         FALSE,
3107         {
3108             {"http://www.winehq.org/?query=%30%31&return=y",S_OK,FALSE},
3109             {"www.winehq.org",S_OK,FALSE},
3110             {"http://www.winehq.org/?query=%30%31&return=y",S_OK,FALSE},
3111             {"winehq.org",S_OK,FALSE},
3112             {"",S_FALSE,FALSE},
3113             {"",S_FALSE,FALSE},
3114             {"www.winehq.org",S_OK,FALSE},
3115             {"",S_FALSE,FALSE},
3116             {"/",S_OK,FALSE},
3117             {"/?query=%30%31&return=y",S_OK,FALSE},
3118             {"?query=%30%31&return=y",S_OK,FALSE},
3119             {"http://www.winehq.org/tests/..?query=%30%31&return=y",S_OK,FALSE},
3120             {"http",S_OK,FALSE},
3121             {"",S_FALSE,FALSE},
3122             {"",S_FALSE,FALSE}
3123         },
3124         {
3125             {Uri_HOST_DNS,S_OK,FALSE},
3126             {80,S_OK,FALSE},
3127             {URL_SCHEME_HTTP,S_OK,FALSE},
3128             {URLZONE_INVALID,E_NOTIMPL,FALSE},
3129         }
3130     },
3131     {   "http://www.winehq.org?query=12&return=y", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
3132         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_HOST|
3133         Uri_HAS_DOMAIN|Uri_HAS_PATH_AND_QUERY|Uri_HAS_PORT|Uri_HAS_QUERY|Uri_HAS_RAW_URI|
3134         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
3135         FALSE,
3136         {
3137             {"http://www.winehq.org?query=12&return=y",S_OK,FALSE},
3138             {"www.winehq.org",S_OK,FALSE},
3139             {"http://www.winehq.org?query=12&return=y",S_OK,FALSE},
3140             {"winehq.org",S_OK,FALSE},
3141             {"",S_FALSE,FALSE},
3142             {"",S_FALSE,FALSE},
3143             {"www.winehq.org",S_OK,FALSE},
3144             {"",S_FALSE,FALSE},
3145             {"",S_FALSE,FALSE},
3146             {"?query=12&return=y",S_OK,FALSE},
3147             {"?query=12&return=y",S_OK,FALSE},
3148             {"http://www.winehq.org?query=12&return=y",S_OK,FALSE},
3149             {"http",S_OK,FALSE},
3150             {"",S_FALSE,FALSE},
3151             {"",S_FALSE,FALSE}
3152         },
3153         {
3154             {Uri_HOST_DNS,S_OK,FALSE},
3155             {80,S_OK,FALSE},
3156             {URL_SCHEME_HTTP,S_OK,FALSE},
3157             {URLZONE_INVALID,E_NOTIMPL,FALSE},
3158         }
3159     },
3160     /* Unknown scheme types can have invalid % encoded data in fragments. */
3161     {   "zip://www.winehq.org/tests/#Te%xx", 0, S_OK, FALSE,
3162         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_FRAGMENT|
3163         Uri_HAS_HOST|Uri_HAS_DOMAIN|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
3164         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
3165         FALSE,
3166         {
3167             {"zip://www.winehq.org/tests/#Te%xx",S_OK,FALSE},
3168             {"www.winehq.org",S_OK,FALSE},
3169             {"zip://www.winehq.org/tests/#Te%xx",S_OK,FALSE},
3170             {"winehq.org",S_OK,FALSE},
3171             {"",S_FALSE,FALSE},
3172             {"#Te%xx",S_OK,FALSE},
3173             {"www.winehq.org",S_OK,FALSE},
3174             {"",S_FALSE,FALSE},
3175             {"/tests/",S_OK,FALSE},
3176             {"/tests/",S_OK,FALSE},
3177             {"",S_FALSE,FALSE},
3178             {"zip://www.winehq.org/tests/#Te%xx",S_OK,FALSE},
3179             {"zip",S_OK,FALSE},
3180             {"",S_FALSE,FALSE},
3181             {"",S_FALSE,FALSE}
3182         },
3183         {
3184             {Uri_HOST_DNS,S_OK,FALSE},
3185             {0,S_FALSE,FALSE},
3186             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
3187             {URLZONE_INVALID,E_NOTIMPL,FALSE},
3188         }
3189     },
3190     /* Forbidden characters in fragment aren't encoded for unknown schemes. */
3191     {   "zip://www.winehq.org/tests/#Te<|>", 0, S_OK, FALSE,
3192         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_FRAGMENT|
3193         Uri_HAS_HOST|Uri_HAS_DOMAIN|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
3194         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
3195         FALSE,
3196         {
3197             {"zip://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
3198             {"www.winehq.org",S_OK,FALSE},
3199             {"zip://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
3200             {"winehq.org",S_OK,FALSE},
3201             {"",S_FALSE,FALSE},
3202             {"#Te<|>",S_OK,FALSE},
3203             {"www.winehq.org",S_OK,FALSE},
3204             {"",S_FALSE,FALSE},
3205             {"/tests/",S_OK,FALSE},
3206             {"/tests/",S_OK,FALSE},
3207             {"",S_FALSE,FALSE},
3208             {"zip://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
3209             {"zip",S_OK,FALSE},
3210             {"",S_FALSE,FALSE},
3211             {"",S_FALSE,FALSE}
3212         },
3213         {
3214             {Uri_HOST_DNS,S_OK,FALSE},
3215             {0,S_FALSE,FALSE},
3216             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
3217             {URLZONE_INVALID,E_NOTIMPL,FALSE},
3218         }
3219     },
3220     /* Forbidden characters in the fragment are percent encoded for known schemes. */
3221     {   "http://www.winehq.org/tests/#Te<|>", 0, S_OK, FALSE,
3222         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_FRAGMENT|
3223         Uri_HAS_HOST|Uri_HAS_DOMAIN|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
3224         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
3225         FALSE,
3226         {
3227             {"http://www.winehq.org/tests/#Te%3C%7C%3E",S_OK,FALSE},
3228             {"www.winehq.org",S_OK,FALSE},
3229             {"http://www.winehq.org/tests/#Te%3C%7C%3E",S_OK,FALSE},
3230             {"winehq.org",S_OK,FALSE},
3231             {"",S_FALSE,FALSE},
3232             {"#Te%3C%7C%3E",S_OK,FALSE},
3233             {"www.winehq.org",S_OK,FALSE},
3234             {"",S_FALSE,FALSE},
3235             {"/tests/",S_OK,FALSE},
3236             {"/tests/",S_OK,FALSE},
3237             {"",S_FALSE,FALSE},
3238             {"http://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
3239             {"http",S_OK,FALSE},
3240             {"",S_FALSE,FALSE},
3241             {"",S_FALSE,FALSE}
3242         },
3243         {
3244             {Uri_HOST_DNS,S_OK,FALSE},
3245             {80,S_OK,FALSE},
3246             {URL_SCHEME_HTTP,S_OK,FALSE},
3247             {URLZONE_INVALID,E_NOTIMPL,FALSE},
3248         }
3249     },
3250     /* Forbidden characters aren't encoded in the fragment with this flag. */
3251     {   "http://www.winehq.org/tests/#Te<|>", Uri_CREATE_NO_DECODE_EXTRA_INFO, S_OK, FALSE,
3252         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_FRAGMENT|
3253         Uri_HAS_HOST|Uri_HAS_DOMAIN|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
3254         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
3255         FALSE,
3256         {
3257             {"http://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
3258             {"www.winehq.org",S_OK,FALSE},
3259             {"http://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
3260             {"winehq.org",S_OK,FALSE},
3261             {"",S_FALSE,FALSE},
3262             {"#Te<|>",S_OK,FALSE},
3263             {"www.winehq.org",S_OK,FALSE},
3264             {"",S_FALSE,FALSE},
3265             {"/tests/",S_OK,FALSE},
3266             {"/tests/",S_OK,FALSE},
3267             {"",S_FALSE,FALSE},
3268             {"http://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
3269             {"http",S_OK,FALSE},
3270             {"",S_FALSE,FALSE},
3271             {"",S_FALSE,FALSE}
3272         },
3273         {
3274             {Uri_HOST_DNS,S_OK,FALSE},
3275             {80,S_OK,FALSE},
3276             {URL_SCHEME_HTTP,S_OK,FALSE},
3277             {URLZONE_INVALID,E_NOTIMPL,FALSE},
3278         }
3279     },
3280     /* Forbidden characters aren't encoded in the fragment with this flag. */
3281     {   "http://www.winehq.org/tests/#Te<|>", Uri_CREATE_NO_ENCODE_FORBIDDEN_CHARACTERS, S_OK, FALSE,
3282         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_FRAGMENT|
3283         Uri_HAS_HOST|Uri_HAS_DOMAIN|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
3284         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
3285         FALSE,
3286         {
3287             {"http://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
3288             {"www.winehq.org",S_OK,FALSE},
3289             {"http://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
3290             {"winehq.org",S_OK,FALSE},
3291             {"",S_FALSE,FALSE},
3292             {"#Te<|>",S_OK,FALSE},
3293             {"www.winehq.org",S_OK,FALSE},
3294             {"",S_FALSE,FALSE},
3295             {"/tests/",S_OK,FALSE},
3296             {"/tests/",S_OK,FALSE},
3297             {"",S_FALSE,FALSE},
3298             {"http://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
3299             {"http",S_OK,FALSE},
3300             {"",S_FALSE,FALSE},
3301             {"",S_FALSE,FALSE}
3302         },
3303         {
3304             {Uri_HOST_DNS,S_OK,FALSE},
3305             {80,S_OK,FALSE},
3306             {URL_SCHEME_HTTP,S_OK,FALSE},
3307             {URLZONE_INVALID,E_NOTIMPL,FALSE},
3308         }
3309     },
3310     /* Percent encoded, unreserved characters aren't decoded for known scheme types. */
3311     {   "zip://www.winehq.org/tests/#Te%30%31%32", 0, S_OK, FALSE,
3312         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_FRAGMENT|
3313         Uri_HAS_HOST|Uri_HAS_DOMAIN|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
3314         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
3315         FALSE,
3316         {
3317             {"zip://www.winehq.org/tests/#Te%30%31%32",S_OK,FALSE},
3318             {"www.winehq.org",S_OK,FALSE},
3319             {"zip://www.winehq.org/tests/#Te%30%31%32",S_OK,FALSE},
3320             {"winehq.org",S_OK,FALSE},
3321             {"",S_FALSE,FALSE},
3322             {"#Te%30%31%32",S_OK,FALSE},
3323             {"www.winehq.org",S_OK,FALSE},
3324             {"",S_FALSE,FALSE},
3325             {"/tests/",S_OK,FALSE},
3326             {"/tests/",S_OK,FALSE},
3327             {"",S_FALSE,FALSE},
3328             {"zip://www.winehq.org/tests/#Te%30%31%32",S_OK,FALSE},
3329             {"zip",S_OK,FALSE},
3330             {"",S_FALSE,FALSE},
3331             {"",S_FALSE,FALSE}
3332         },
3333         {
3334             {Uri_HOST_DNS,S_OK,FALSE},
3335             {0,S_FALSE,FALSE},
3336             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
3337             {URLZONE_INVALID,E_NOTIMPL,FALSE},
3338         }
3339     },
3340     /* Percent encoded, unreserved characters are decoded for known schemes. */
3341     {   "http://www.winehq.org/tests/#Te%30%31%32", 0, S_OK, FALSE,
3342         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_FRAGMENT|
3343         Uri_HAS_HOST|Uri_HAS_DOMAIN|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
3344         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
3345         FALSE,
3346         {
3347             {"http://www.winehq.org/tests/#Te012",S_OK,FALSE},
3348             {"www.winehq.org",S_OK,FALSE},
3349             {"http://www.winehq.org/tests/#Te012",S_OK,FALSE},
3350             {"winehq.org",S_OK,FALSE},
3351             {"",S_FALSE,FALSE},
3352             {"#Te012",S_OK,FALSE},
3353             {"www.winehq.org",S_OK,FALSE},
3354             {"",S_FALSE,FALSE},
3355             {"/tests/",S_OK,FALSE},
3356             {"/tests/",S_OK,FALSE},
3357             {"",S_FALSE,FALSE},
3358             {"http://www.winehq.org/tests/#Te%30%31%32",S_OK,FALSE},
3359             {"http",S_OK,FALSE},
3360             {"",S_FALSE,FALSE},
3361             {"",S_FALSE,FALSE}
3362         },
3363         {
3364             {Uri_HOST_DNS,S_OK,FALSE},
3365             {80,S_OK,FALSE},
3366             {URL_SCHEME_HTTP,S_OK,FALSE},
3367             {URLZONE_INVALID,E_NOTIMPL,FALSE},
3368         }
3369     },
3370     /* Percent encoded, unreserved characters are decoded even if NO_CANONICALIZE is set. */
3371     {   "http://www.winehq.org/tests/#Te%30%31%32", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
3372         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_FRAGMENT|
3373         Uri_HAS_HOST|Uri_HAS_DOMAIN|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
3374         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
3375         FALSE,
3376         {
3377             {"http://www.winehq.org/tests/#Te012",S_OK,FALSE},
3378             {"www.winehq.org",S_OK,FALSE},
3379             {"http://www.winehq.org/tests/#Te012",S_OK,FALSE},
3380             {"winehq.org",S_OK,FALSE},
3381             {"",S_FALSE,FALSE},
3382             {"#Te012",S_OK,FALSE},
3383             {"www.winehq.org",S_OK,FALSE},
3384             {"",S_FALSE,FALSE},
3385             {"/tests/",S_OK,FALSE},
3386             {"/tests/",S_OK,FALSE},
3387             {"",S_FALSE,FALSE},
3388             {"http://www.winehq.org/tests/#Te%30%31%32",S_OK,FALSE},
3389             {"http",S_OK,FALSE},
3390             {"",S_FALSE,FALSE},
3391             {"",S_FALSE,FALSE}
3392         },
3393         {
3394             {Uri_HOST_DNS,S_OK,FALSE},
3395             {80,S_OK,FALSE},
3396             {URL_SCHEME_HTTP,S_OK,FALSE},
3397             {URLZONE_INVALID,E_NOTIMPL,FALSE},
3398         }
3399     },
3400     /* Percent encoded, unreserved characters aren't decoded when NO_DECODE_EXTRA is set. */
3401     {   "http://www.winehq.org/tests/#Te%30%31%32", Uri_CREATE_NO_DECODE_EXTRA_INFO, S_OK, FALSE,
3402         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_FRAGMENT|
3403         Uri_HAS_HOST|Uri_HAS_DOMAIN|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
3404         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
3405         FALSE,
3406         {
3407             {"http://www.winehq.org/tests/#Te%30%31%32",S_OK,FALSE},
3408             {"www.winehq.org",S_OK,FALSE},
3409             {"http://www.winehq.org/tests/#Te%30%31%32",S_OK,FALSE},
3410             {"winehq.org",S_OK,FALSE},
3411             {"",S_FALSE,FALSE},
3412             {"#Te%30%31%32",S_OK,FALSE},
3413             {"www.winehq.org",S_OK,FALSE},
3414             {"",S_FALSE,FALSE},
3415             {"/tests/",S_OK,FALSE},
3416             {"/tests/",S_OK,FALSE},
3417             {"",S_FALSE,FALSE},
3418             {"http://www.winehq.org/tests/#Te%30%31%32",S_OK,FALSE},
3419             {"http",S_OK,FALSE},
3420             {"",S_FALSE,FALSE},
3421             {"",S_FALSE,FALSE}
3422         },
3423         {
3424             {Uri_HOST_DNS,S_OK,FALSE},
3425             {80,S_OK,FALSE},
3426             {URL_SCHEME_HTTP,S_OK,FALSE},
3427             {URLZONE_INVALID,E_NOTIMPL,FALSE},
3428         }
3429     },
3430     /* Leading/Trailing whitespace is removed. */
3431     {   "    http://google.com/     ", 0, S_OK, FALSE,
3432         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
3433         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
3434         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
3435         FALSE,
3436         {
3437             {"http://google.com/",S_OK,FALSE},
3438             {"google.com",S_OK,FALSE},
3439             {"http://google.com/",S_OK,FALSE},
3440             {"google.com",S_OK,FALSE},
3441             {"",S_FALSE,FALSE},
3442             {"",S_FALSE,FALSE},
3443             {"google.com",S_OK,FALSE},
3444             {"",S_FALSE,FALSE},
3445             {"/",S_OK,FALSE},
3446             {"/",S_OK,FALSE},
3447             {"",S_FALSE,FALSE},
3448             {"http://google.com/",S_OK,FALSE},
3449             {"http",S_OK,FALSE},
3450             {"",S_FALSE,FALSE},
3451             {"",S_FALSE,FALSE}
3452         },
3453         {
3454             {Uri_HOST_DNS,S_OK,FALSE},
3455             {80,S_OK,FALSE},
3456             {URL_SCHEME_HTTP,S_OK,FALSE},
3457             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3458         }
3459     },
3460     {   "\t\t\r\nhttp\n://g\noogle.co\rm/\n\n\n", 0, S_OK, FALSE,
3461         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
3462         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
3463         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
3464         FALSE,
3465         {
3466             {"http://google.com/",S_OK,FALSE},
3467             {"google.com",S_OK,FALSE},
3468             {"http://google.com/",S_OK,FALSE},
3469             {"google.com",S_OK,FALSE},
3470             {"",S_FALSE,FALSE},
3471             {"",S_FALSE,FALSE},
3472             {"google.com",S_OK,FALSE},
3473             {"",S_FALSE,FALSE},
3474             {"/",S_OK,FALSE},
3475             {"/",S_OK,FALSE},
3476             {"",S_FALSE,FALSE},
3477             {"http://google.com/",S_OK,FALSE},
3478             {"http",S_OK,FALSE},
3479             {"",S_FALSE,FALSE},
3480             {"",S_FALSE,FALSE}
3481         },
3482         {
3483             {Uri_HOST_DNS,S_OK,FALSE},
3484             {80,S_OK,FALSE},
3485             {URL_SCHEME_HTTP,S_OK,FALSE},
3486             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3487         }
3488     },
3489     {   "http://g\noogle.co\rm/\n\n\n", Uri_CREATE_NO_PRE_PROCESS_HTML_URI, S_OK, FALSE,
3490         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
3491         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
3492         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
3493         FALSE,
3494         {
3495             {"http://g%0aoogle.co%0dm/%0A%0A%0A",S_OK,FALSE},
3496             {"g%0aoogle.co%0dm",S_OK,FALSE},
3497             {"http://g%0aoogle.co%0dm/%0A%0A%0A",S_OK,FALSE},
3498             {"g%0aoogle.co%0dm",S_OK,FALSE},
3499             {"",S_FALSE,FALSE},
3500             {"",S_FALSE,FALSE},
3501             {"g%0aoogle.co%0dm",S_OK,FALSE},
3502             {"",S_FALSE,FALSE},
3503             {"/%0A%0A%0A",S_OK,FALSE},
3504             {"/%0A%0A%0A",S_OK,FALSE},
3505             {"",S_FALSE,FALSE},
3506             {"http://g\noogle.co\rm/\n\n\n",S_OK,FALSE},
3507             {"http",S_OK,FALSE},
3508             {"",S_FALSE,FALSE},
3509             {"",S_FALSE,FALSE}
3510         },
3511         {
3512             {Uri_HOST_DNS,S_OK,FALSE},
3513             {80,S_OK,FALSE},
3514             {URL_SCHEME_HTTP,S_OK,FALSE},
3515             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3516         }
3517     },
3518     {   "zip://g\noogle.co\rm/\n\n\n", Uri_CREATE_NO_PRE_PROCESS_HTML_URI, S_OK, FALSE,
3519         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
3520         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
3521         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
3522         FALSE,
3523         {
3524             {"zip://g\noogle.co\rm/\n\n\n",S_OK,FALSE},
3525             {"g\noogle.co\rm",S_OK,FALSE},
3526             {"zip://g\noogle.co\rm/\n\n\n",S_OK,FALSE},
3527             {"g\noogle.co\rm",S_OK,FALSE},
3528             {"",S_FALSE,FALSE},
3529             {"",S_FALSE,FALSE},
3530             {"g\noogle.co\rm",S_OK,FALSE},
3531             {"",S_FALSE,FALSE},
3532             {"/\n\n\n",S_OK,FALSE},
3533             {"/\n\n\n",S_OK,FALSE},
3534             {"",S_FALSE,FALSE},
3535             {"zip://g\noogle.co\rm/\n\n\n",S_OK,FALSE},
3536             {"zip",S_OK,FALSE},
3537             {"",S_FALSE,FALSE},
3538             {"",S_FALSE,FALSE}
3539         },
3540         {
3541             {Uri_HOST_DNS,S_OK,FALSE},
3542             {0,S_FALSE,FALSE},
3543             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
3544             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3545         }
3546     },
3547     /* Since file URLs are usually hierarchical, it returns an empty string
3548      * for the absolute URI property since it was declared as an opaque URI.
3549      */
3550     {   "file:index.html", 0, S_OK, FALSE,
3551         Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY
3552         |Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME, FALSE,
3553         {
3554             {"",S_FALSE,FALSE},
3555             {"",S_FALSE,FALSE},
3556             {"file:index.html",S_OK,FALSE},
3557             {"",S_FALSE,FALSE},
3558             {".html",S_OK,FALSE},
3559             {"",S_FALSE,FALSE},
3560             {"",S_FALSE,FALSE},
3561             {"",S_FALSE,FALSE},
3562             {"index.html",S_OK,FALSE},
3563             {"index.html",S_OK,FALSE},
3564             {"",S_FALSE,FALSE},
3565             {"file:index.html",S_OK,FALSE},
3566             {"file",S_OK,FALSE},
3567             {"",S_FALSE,FALSE},
3568             {"",S_FALSE,FALSE}
3569         },
3570         {
3571             {0,S_OK,FALSE},
3572             {0,S_FALSE,FALSE},
3573             {URL_SCHEME_FILE,S_OK,FALSE},
3574             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3575         }
3576     },
3577     /* Doesn't have an absolute since it's opaque, but gets it port set. */
3578     {   "http:test.com/index.html", 0, S_OK, FALSE,
3579         Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY
3580         |Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME, FALSE,
3581         {
3582             {"",S_FALSE,FALSE},
3583             {"",S_FALSE,FALSE},
3584             {"http:test.com/index.html",S_OK,FALSE},
3585             {"",S_FALSE,FALSE},
3586             {".html",S_OK,FALSE},
3587             {"",S_FALSE,FALSE},
3588             {"",S_FALSE,FALSE},
3589             {"",S_FALSE,FALSE},
3590             {"test.com/index.html",S_OK,FALSE},
3591             {"test.com/index.html",S_OK,FALSE},
3592             {"",S_FALSE,FALSE},
3593             {"http:test.com/index.html",S_OK,FALSE},
3594             {"http",S_OK,FALSE},
3595             {"",S_FALSE,FALSE},
3596             {"",S_FALSE,FALSE}
3597         },
3598         {
3599             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3600             {80,S_OK,FALSE},
3601             {URL_SCHEME_HTTP,S_OK,FALSE},
3602             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3603         }
3604     },
3605     {   "ftp:test.com/index.html", 0, S_OK, FALSE,
3606         Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY
3607         |Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME, FALSE,
3608         {
3609             {"",S_FALSE,FALSE},
3610             {"",S_FALSE,FALSE},
3611             {"ftp:test.com/index.html",S_OK,FALSE},
3612             {"",S_FALSE,FALSE},
3613             {".html",S_OK,FALSE},
3614             {"",S_FALSE,FALSE},
3615             {"",S_FALSE,FALSE},
3616             {"",S_FALSE,FALSE},
3617             {"test.com/index.html",S_OK,FALSE},
3618             {"test.com/index.html",S_OK,FALSE},
3619             {"",S_FALSE,FALSE},
3620             {"ftp:test.com/index.html",S_OK,FALSE},
3621             {"ftp",S_OK,FALSE},
3622             {"",S_FALSE,FALSE},
3623             {"",S_FALSE,FALSE}
3624         },
3625         {
3626             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3627             {21,S_OK,FALSE},
3628             {URL_SCHEME_FTP,S_OK,FALSE},
3629             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3630         }
3631     },
3632     {   "file://C|/test.mp3", 0, S_OK, FALSE,
3633         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH|
3634         Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
3635         FALSE,
3636         {
3637             {"file:///C:/test.mp3",S_OK,FALSE},
3638             {"",S_FALSE,FALSE},
3639             {"file:///C:/test.mp3",S_OK,FALSE},
3640             {"",S_FALSE,FALSE},
3641             {".mp3",S_OK,FALSE},
3642             {"",S_FALSE,FALSE},
3643             {"",S_FALSE,FALSE},
3644             {"",S_FALSE,FALSE},
3645             {"/C:/test.mp3",S_OK,FALSE},
3646             {"/C:/test.mp3",S_OK,FALSE},
3647             {"",S_FALSE,FALSE},
3648             {"file://C|/test.mp3",S_OK,FALSE},
3649             {"file",S_OK,FALSE},
3650             {"",S_FALSE,FALSE},
3651             {"",S_FALSE,FALSE}
3652         },
3653         {
3654             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3655             {0,S_FALSE,FALSE},
3656             {URL_SCHEME_FILE,S_OK,FALSE},
3657             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3658         }
3659     },
3660     {   "file:///C|/test.mp3", 0, S_OK, FALSE,
3661         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH|
3662         Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
3663         FALSE,
3664         {
3665             {"file:///C:/test.mp3",S_OK,FALSE},
3666             {"",S_FALSE,FALSE},
3667             {"file:///C:/test.mp3",S_OK,FALSE},
3668             {"",S_FALSE,FALSE},
3669             {".mp3",S_OK,FALSE},
3670             {"",S_FALSE,FALSE},
3671             {"",S_FALSE,FALSE},
3672             {"",S_FALSE,FALSE},
3673             {"/C:/test.mp3",S_OK,FALSE},
3674             {"/C:/test.mp3",S_OK,FALSE},
3675             {"",S_FALSE,FALSE},
3676             {"file:///C|/test.mp3",S_OK,FALSE},
3677             {"file",S_OK,FALSE},
3678             {"",S_FALSE,FALSE},
3679             {"",S_FALSE,FALSE}
3680         },
3681         {
3682             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3683             {0,S_FALSE,FALSE},
3684             {URL_SCHEME_FILE,S_OK,FALSE},
3685             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3686         }
3687     },
3688     /* Extra '/' isn't added before "c:" since USE_DOS_PATH is set and '/' are converted
3689      * to '\\'.
3690      */
3691     {   "file://c:/dir/index.html", Uri_CREATE_FILE_USE_DOS_PATH, S_OK, FALSE,
3692         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH
3693         |Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE
3694         |Uri_HAS_SCHEME, FALSE,
3695         {
3696             {"file://c:\\dir\\index.html",S_OK,FALSE},
3697             {"",S_FALSE,FALSE},
3698             {"file://c:\\dir\\index.html",S_OK,FALSE},
3699             {"",S_FALSE,FALSE},
3700             {".html",S_OK,FALSE},
3701             {"",S_FALSE,FALSE},
3702             {"",S_FALSE,FALSE},
3703             {"",S_FALSE,FALSE},
3704             {"c:\\dir\\index.html",S_OK,FALSE},
3705             {"c:\\dir\\index.html",S_OK,FALSE},
3706             {"",S_FALSE,FALSE},
3707             {"file://c:/dir/index.html",S_OK,FALSE},
3708             {"file",S_OK,FALSE},
3709             {"",S_FALSE,FALSE},
3710             {"",S_FALSE,FALSE}
3711         },
3712         {
3713             {0,S_OK,FALSE},
3714             {0,S_FALSE,FALSE},
3715             {URL_SCHEME_FILE,S_OK,FALSE},
3716             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3717         }
3718     },
3719     /* Extra '/' after "file://" is removed. */
3720     {   "file:///c:/dir/index.html", Uri_CREATE_FILE_USE_DOS_PATH, S_OK, FALSE,
3721         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH
3722         |Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE
3723         |Uri_HAS_SCHEME, FALSE,
3724         {
3725             {"file://c:\\dir\\index.html",S_OK,FALSE},
3726             {"",S_FALSE,FALSE},
3727             {"file://c:\\dir\\index.html",S_OK,FALSE},
3728             {"",S_FALSE,FALSE},
3729             {".html",S_OK,FALSE},
3730             {"",S_FALSE,FALSE},
3731             {"",S_FALSE,FALSE},
3732             {"",S_FALSE,FALSE},
3733             {"c:\\dir\\index.html",S_OK,FALSE},
3734             {"c:\\dir\\index.html",S_OK,FALSE},
3735             {"",S_FALSE,FALSE},
3736             {"file:///c:/dir/index.html",S_OK,FALSE},
3737             {"file",S_OK,FALSE},
3738             {"",S_FALSE,FALSE},
3739             {"",S_FALSE,FALSE}
3740         },
3741         {
3742             {0,S_OK,FALSE},
3743             {0,S_FALSE,FALSE},
3744             {URL_SCHEME_FILE,S_OK,FALSE},
3745             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3746         }
3747     },
3748     /* Allow more characters when Uri_CREATE_FILE_USE_DOS_PATH is specified */
3749     {   "file:///c:/dir\%%61%20%5Fname/file%2A.html", Uri_CREATE_FILE_USE_DOS_PATH, S_OK, FALSE,
3750         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH
3751         |Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE
3752         |Uri_HAS_SCHEME, FALSE,
3753         {
3754             {"file://c:\\dir\%a _name\\file*.html",S_OK,FALSE},
3755             {"",S_FALSE,FALSE},
3756             {"file://c:\\dir\%a _name\\file*.html",S_OK,FALSE},
3757             {"",S_FALSE,FALSE},
3758             {".html",S_OK,FALSE},
3759             {"",S_FALSE,FALSE},
3760             {"",S_FALSE,FALSE},
3761             {"",S_FALSE,FALSE},
3762             {"c:\\dir\%a _name\\file*.html",S_OK,FALSE},
3763             {"c:\\dir\%a _name\\file*.html",S_OK,FALSE},
3764             {"",S_FALSE,FALSE},
3765             {"file:///c:/dir\%%61%20%5Fname/file%2A.html",S_OK,FALSE},
3766             {"file",S_OK,FALSE},
3767             {"",S_FALSE,FALSE},
3768             {"",S_FALSE,FALSE}
3769         },
3770         {
3771             {0,S_OK,FALSE},
3772             {0,S_FALSE,FALSE},
3773             {URL_SCHEME_FILE,S_OK,FALSE},
3774             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3775         }
3776     },
3777     {   "file://c|/dir\\index.html", Uri_CREATE_FILE_USE_DOS_PATH, S_OK, FALSE,
3778         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH
3779         |Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE
3780         |Uri_HAS_SCHEME, FALSE,
3781         {
3782             {"file://c:\\dir\\index.html",S_OK,FALSE},
3783             {"",S_FALSE,FALSE},
3784             {"file://c:\\dir\\index.html",S_OK,FALSE},
3785             {"",S_FALSE,FALSE},
3786             {".html",S_OK,FALSE},
3787             {"",S_FALSE,FALSE},
3788             {"",S_FALSE,FALSE},
3789             {"",S_FALSE,FALSE},
3790             {"c:\\dir\\index.html",S_OK,FALSE},
3791             {"c:\\dir\\index.html",S_OK,FALSE},
3792             {"",S_FALSE,FALSE},
3793             {"file://c|/dir\\index.html",S_OK,FALSE},
3794             {"file",S_OK,FALSE},
3795             {"",S_FALSE,FALSE},
3796             {"",S_FALSE,FALSE}
3797         },
3798         {
3799             {0,S_OK,FALSE},
3800             {0,S_FALSE,FALSE},
3801             {URL_SCHEME_FILE,S_OK,FALSE},
3802             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3803         }
3804     },
3805     /* The backslashes after the scheme name are converted to forward slashes. */
3806     {   "file:\\\\c:\\dir\\index.html", Uri_CREATE_FILE_USE_DOS_PATH, S_OK, FALSE,
3807         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH
3808         |Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE
3809         |Uri_HAS_SCHEME, FALSE,
3810         {
3811             {"file://c:\\dir\\index.html",S_OK,FALSE},
3812             {"",S_FALSE,FALSE},
3813             {"file://c:\\dir\\index.html",S_OK,FALSE},
3814             {"",S_FALSE,FALSE},
3815             {".html",S_OK,FALSE},
3816             {"",S_FALSE,FALSE},
3817             {"",S_FALSE,FALSE},
3818             {"",S_FALSE,FALSE},
3819             {"c:\\dir\\index.html",S_OK,FALSE},
3820             {"c:\\dir\\index.html",S_OK,FALSE},
3821             {"",S_FALSE,FALSE},
3822             {"file:\\\\c:\\dir\\index.html",S_OK,FALSE},
3823             {"file",S_OK,FALSE},
3824             {"",S_FALSE,FALSE},
3825             {"",S_FALSE,FALSE}
3826         },
3827         {
3828             {0,S_OK,FALSE},
3829             {0,S_FALSE,FALSE},
3830             {URL_SCHEME_FILE,S_OK,FALSE},
3831             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3832         }
3833     },
3834     {   "file:\\\\c:/dir/index.html", 0, S_OK, FALSE,
3835         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH
3836         |Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE
3837         |Uri_HAS_SCHEME, FALSE,
3838         {
3839             {"file:///c:/dir/index.html",S_OK,FALSE},
3840             {"",S_FALSE,FALSE},
3841             {"file:///c:/dir/index.html",S_OK,FALSE},
3842             {"",S_FALSE,FALSE},
3843             {".html",S_OK,FALSE},
3844             {"",S_FALSE,FALSE},
3845             {"",S_FALSE,FALSE},
3846             {"",S_FALSE,FALSE},
3847             {"/c:/dir/index.html",S_OK,FALSE},
3848             {"/c:/dir/index.html",S_OK,FALSE},
3849             {"",S_FALSE,FALSE},
3850             {"file:\\\\c:/dir/index.html",S_OK,FALSE},
3851             {"file",S_OK,FALSE},
3852             {"",S_FALSE,FALSE},
3853             {"",S_FALSE,FALSE}
3854         },
3855         {
3856             {0,S_OK,FALSE},
3857             {0,S_FALSE,FALSE},
3858             {URL_SCHEME_FILE,S_OK,FALSE},
3859             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3860         }
3861     },
3862     {   "http:\\\\google.com", 0, S_OK, FALSE,
3863         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
3864         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
3865         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
3866         FALSE,
3867         {
3868             {"http://google.com/",S_OK,FALSE},
3869             {"google.com",S_OK,FALSE},
3870             {"http://google.com/",S_OK,FALSE},
3871             {"google.com",S_OK,FALSE},
3872             {"",S_FALSE,FALSE},
3873             {"",S_FALSE,FALSE},
3874             {"google.com",S_OK,FALSE},
3875             {"",S_FALSE,FALSE},
3876             {"/",S_OK,FALSE},
3877             {"/",S_OK,FALSE},
3878             {"",S_FALSE,FALSE},
3879             {"http:\\\\google.com",S_OK,FALSE},
3880             {"http",S_OK,FALSE},
3881             {"",S_FALSE,FALSE},
3882             {"",S_FALSE,FALSE}
3883         },
3884         {
3885             {Uri_HOST_DNS,S_OK,FALSE},
3886             {80,S_OK,FALSE},
3887             {URL_SCHEME_HTTP,S_OK,FALSE},
3888             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3889         }
3890     },
3891     /* the "\\\\" aren't converted to "//" for unknown scheme types and it's considered opaque. */
3892     {   "zip:\\\\google.com", 0, S_OK, FALSE,
3893         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH|
3894         Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_SCHEME|
3895         Uri_HAS_HOST_TYPE,
3896         FALSE,
3897         {
3898             {"zip:\\\\google.com",S_OK,FALSE},
3899             {"",S_FALSE,FALSE},
3900             {"zip:\\\\google.com",S_OK,FALSE},
3901             {"",S_FALSE,FALSE},
3902             {".com",S_OK,FALSE},
3903             {"",S_FALSE,FALSE},
3904             {"",S_FALSE,FALSE},
3905             {"",S_FALSE,FALSE},
3906             {"\\\\google.com",S_OK,FALSE},
3907             {"\\\\google.com",S_OK,FALSE},
3908             {"",S_FALSE,FALSE},
3909             {"zip:\\\\google.com",S_OK,FALSE},
3910             {"zip",S_OK,FALSE},
3911             {"",S_FALSE,FALSE},
3912             {"",S_FALSE,FALSE}
3913         },
3914         {
3915             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3916             {0,S_FALSE,FALSE},
3917             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
3918             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3919         }
3920     },
3921     /* Dot segments aren't removed. */
3922     {   "file://c:\\dir\\../..\\./index.html", Uri_CREATE_FILE_USE_DOS_PATH, S_OK, FALSE,
3923         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH
3924         |Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE
3925         |Uri_HAS_SCHEME, FALSE,
3926         {
3927             {"file://c:\\dir\\..\\..\\.\\index.html",S_OK,FALSE},
3928             {"",S_FALSE,FALSE},
3929             {"file://c:\\dir\\..\\..\\.\\index.html",S_OK,FALSE},
3930             {"",S_FALSE,FALSE},
3931             {".html",S_OK,FALSE},
3932             {"",S_FALSE,FALSE},
3933             {"",S_FALSE,FALSE},
3934             {"",S_FALSE,FALSE},
3935             {"c:\\dir\\..\\..\\.\\index.html",S_OK,FALSE},
3936             {"c:\\dir\\..\\..\\.\\index.html",S_OK,FALSE},
3937             {"",S_FALSE,FALSE},
3938             {"file://c:\\dir\\../..\\./index.html",S_OK,FALSE},
3939             {"file",S_OK,FALSE},
3940             {"",S_FALSE,FALSE},
3941             {"",S_FALSE,FALSE}
3942         },
3943         {
3944             {0,S_OK,FALSE},
3945             {0,S_FALSE,FALSE},
3946             {URL_SCHEME_FILE,S_OK,FALSE},
3947             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3948         }
3949     },
3950     /* Forbidden characters aren't percent encoded. */
3951     {   "file://c:\\dir\\i^|ndex.html", Uri_CREATE_FILE_USE_DOS_PATH, S_OK, FALSE,
3952         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH
3953         |Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE
3954         |Uri_HAS_SCHEME, FALSE,
3955         {
3956             {"file://c:\\dir\\i^|ndex.html",S_OK,FALSE},
3957             {"",S_FALSE,FALSE},
3958             {"file://c:\\dir\\i^|ndex.html",S_OK,FALSE},
3959             {"",S_FALSE,FALSE},
3960             {".html",S_OK,FALSE},
3961             {"",S_FALSE,FALSE},
3962             {"",S_FALSE,FALSE},
3963             {"",S_FALSE,FALSE},
3964             {"c:\\dir\\i^|ndex.html",S_OK,FALSE},
3965             {"c:\\dir\\i^|ndex.html",S_OK,FALSE},
3966             {"",S_FALSE,FALSE},
3967             {"file://c:\\dir\\i^|ndex.html",S_OK,FALSE},
3968             {"file",S_OK,FALSE},
3969             {"",S_FALSE,FALSE},
3970             {"",S_FALSE,FALSE}
3971         },
3972         {
3973             {0,S_OK,FALSE},
3974             {0,S_FALSE,FALSE},
3975             {URL_SCHEME_FILE,S_OK,FALSE},
3976             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3977         }
3978     },
3979     /* The '\' are still converted to '/' even though it's an opaque file URI. */
3980     {   "file:c:\\dir\\../..\\index.html", 0, S_OK, FALSE,
3981         Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY
3982         |Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME, FALSE,
3983         {
3984             {"",S_FALSE,FALSE},
3985             {"",S_FALSE,FALSE},
3986             {"file:c:/dir/../../index.html",S_OK,FALSE},
3987             {"",S_FALSE,FALSE},
3988             {".html",S_OK,FALSE},
3989             {"",S_FALSE,FALSE},
3990             {"",S_FALSE,FALSE},
3991             {"",S_FALSE,FALSE},
3992             {"c:/dir/../../index.html",S_OK,FALSE},
3993             {"c:/dir/../../index.html",S_OK,FALSE},
3994             {"",S_FALSE,FALSE},
3995             {"file:c:\\dir\\../..\\index.html",S_OK,FALSE},
3996             {"file",S_OK,FALSE},
3997             {"",S_FALSE,FALSE},
3998             {"",S_FALSE,FALSE}
3999         },
4000         {
4001             {0,S_OK,FALSE},
4002             {0,S_FALSE,FALSE},
4003             {URL_SCHEME_FILE,S_OK,FALSE},
4004             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4005         }
4006     },
4007     /* '/' are still converted to '\' even though it's an opaque URI. */
4008     {   "file:c:/dir\\../..\\index.html", Uri_CREATE_FILE_USE_DOS_PATH, S_OK, FALSE,
4009         Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY
4010         |Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME, FALSE,
4011         {
4012             {"",S_FALSE,FALSE},
4013             {"",S_FALSE,FALSE},
4014             {"file:c:\\dir\\..\\..\\index.html",S_OK,FALSE},
4015             {"",S_FALSE,FALSE},
4016             {".html",S_OK,FALSE},
4017             {"",S_FALSE,FALSE},
4018             {"",S_FALSE,FALSE},
4019             {"",S_FALSE,FALSE},
4020             {"c:\\dir\\..\\..\\index.html",S_OK,FALSE},
4021             {"c:\\dir\\..\\..\\index.html",S_OK,FALSE},
4022             {"",S_FALSE,FALSE},
4023             {"file:c:/dir\\../..\\index.html",S_OK,FALSE},
4024             {"file",S_OK,FALSE},
4025             {"",S_FALSE,FALSE},
4026             {"",S_FALSE,FALSE}
4027         },
4028         {
4029             {0,S_OK,FALSE},
4030             {0,S_FALSE,FALSE},
4031             {URL_SCHEME_FILE,S_OK,FALSE},
4032             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4033         }
4034     },
4035     /* Forbidden characters aren't percent encoded. */
4036     {   "file:c:\\in^|dex.html", Uri_CREATE_FILE_USE_DOS_PATH, S_OK, FALSE,
4037         Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY
4038         |Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME, FALSE,
4039         {
4040             {"",S_FALSE,FALSE},
4041             {"",S_FALSE,FALSE},
4042             {"file:c:\\in^|dex.html",S_OK,FALSE},
4043             {"",S_FALSE,FALSE},
4044             {".html",S_OK,FALSE},
4045             {"",S_FALSE,FALSE},
4046             {"",S_FALSE,FALSE},
4047             {"",S_FALSE,FALSE},
4048             {"c:\\in^|dex.html",S_OK,FALSE},
4049             {"c:\\in^|dex.html",S_OK,FALSE},
4050             {"",S_FALSE,FALSE},
4051             {"file:c:\\in^|dex.html",S_OK,FALSE},
4052             {"file",S_OK,FALSE},
4053             {"",S_FALSE,FALSE},
4054             {"",S_FALSE,FALSE}
4055         },
4056         {
4057             {0,S_OK,FALSE},
4058             {0,S_FALSE,FALSE},
4059             {URL_SCHEME_FILE,S_OK,FALSE},
4060             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4061         }
4062     },
4063     /* Doesn't have a UserName since the ':' appears at the beginning of the
4064      * userinfo section.
4065      */
4066     {   "http://:password@gov.uk", 0, S_OK, FALSE,
4067         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
4068         Uri_HAS_PASSWORD|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
4069         Uri_HAS_USER_INFO|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
4070         FALSE,
4071         {
4072             {"http://:password@gov.uk/",S_OK,FALSE},
4073             {":password@gov.uk",S_OK,FALSE},
4074             {"http://gov.uk/",S_OK,FALSE},
4075             {"",S_FALSE,FALSE},
4076             {"",S_FALSE,FALSE},
4077             {"",S_FALSE,FALSE},
4078             {"gov.uk",S_OK,FALSE},
4079             {"password",S_OK,FALSE},
4080             {"/",S_OK,FALSE},
4081             {"/",S_OK,FALSE},
4082             {"",S_FALSE,FALSE},
4083             {"http://:password@gov.uk",S_OK,FALSE},
4084             {"http",S_OK,FALSE},
4085             {":password",S_OK,FALSE},
4086             {"",S_FALSE,FALSE}
4087         },
4088         {
4089             {Uri_HOST_DNS,S_OK,FALSE},
4090             {80,S_OK,FALSE},
4091             {URL_SCHEME_HTTP,S_OK,FALSE},
4092             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4093         }
4094     },
4095     /* Has a UserName since the userinfo section doesn't contain a password. */
4096     {   "http://@gov.uk", 0, S_OK, FALSE,
4097         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
4098         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
4099         Uri_HAS_USER_INFO|Uri_HAS_USER_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
4100         FALSE,
4101         {
4102             {"http://gov.uk/",S_OK,FALSE,"http://@gov.uk/"},
4103             {"@gov.uk",S_OK,FALSE},
4104             {"http://gov.uk/",S_OK,FALSE},
4105             {"",S_FALSE,FALSE},
4106             {"",S_FALSE,FALSE},
4107             {"",S_FALSE,FALSE},
4108             {"gov.uk",S_OK,FALSE},
4109             {"",S_FALSE,FALSE},
4110             {"/",S_OK,FALSE},
4111             {"/",S_OK,FALSE},
4112             {"",S_FALSE,FALSE},
4113             {"http://@gov.uk",S_OK,FALSE},
4114             {"http",S_OK,FALSE},
4115             {"",S_OK,FALSE},
4116             {"",S_OK,FALSE}
4117         },
4118         {
4119             {Uri_HOST_DNS,S_OK,FALSE},
4120             {80,S_OK,FALSE},
4121             {URL_SCHEME_HTTP,S_OK,FALSE},
4122             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4123         }
4124     },
4125     /* ":@" not included in the absolute URI. */
4126     {   "http://:@gov.uk", 0, S_OK, FALSE,
4127         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
4128         Uri_HAS_PASSWORD|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
4129         Uri_HAS_USER_INFO|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
4130         FALSE,
4131         {
4132             {"http://gov.uk/",S_OK,FALSE,"http://:@gov.uk/"},
4133             {":@gov.uk",S_OK,FALSE},
4134             {"http://gov.uk/",S_OK,FALSE},
4135             {"",S_FALSE,FALSE},
4136             {"",S_FALSE,FALSE},
4137             {"",S_FALSE,FALSE},
4138             {"gov.uk",S_OK,FALSE},
4139             {"",S_OK,FALSE},
4140             {"/",S_OK,FALSE},
4141             {"/",S_OK,FALSE},
4142             {"",S_FALSE,FALSE},
4143             {"http://:@gov.uk",S_OK,FALSE},
4144             {"http",S_OK,FALSE},
4145             {":",S_OK,FALSE},
4146             {"",S_FALSE,FALSE}
4147         },
4148         {
4149             {Uri_HOST_DNS,S_OK,FALSE},
4150             {80,S_OK,FALSE},
4151             {URL_SCHEME_HTTP,S_OK,FALSE},
4152             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4153         }
4154     },
4155     /* '@' is included because it's an unknown scheme type. */
4156     {   "zip://@gov.uk", 0, S_OK, FALSE,
4157         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
4158         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
4159         Uri_HAS_USER_INFO|Uri_HAS_USER_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
4160         FALSE,
4161         {
4162             {"zip://@gov.uk/",S_OK,FALSE},
4163             {"@gov.uk",S_OK,FALSE},
4164             {"zip://@gov.uk/",S_OK,FALSE},
4165             {"",S_FALSE,FALSE},
4166             {"",S_FALSE,FALSE},
4167             {"",S_FALSE,FALSE},
4168             {"gov.uk",S_OK,FALSE},
4169             {"",S_FALSE,FALSE},
4170             {"/",S_OK,FALSE},
4171             {"/",S_OK,FALSE},
4172             {"",S_FALSE,FALSE},
4173             {"zip://@gov.uk",S_OK,FALSE},
4174             {"zip",S_OK,FALSE},
4175             {"",S_OK,FALSE},
4176             {"",S_OK,FALSE}
4177         },
4178         {
4179             {Uri_HOST_DNS,S_OK,FALSE},
4180             {0,S_FALSE,FALSE},
4181             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
4182             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4183         }
4184     },
4185     /* ":@" are included because it's an unknown scheme type. */
4186     {   "zip://:@gov.uk", 0, S_OK, FALSE,
4187         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
4188         Uri_HAS_PASSWORD|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
4189         Uri_HAS_SCHEME_NAME|Uri_HAS_USER_INFO|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
4190         FALSE,
4191         {
4192             {"zip://:@gov.uk/",S_OK,FALSE},
4193             {":@gov.uk",S_OK,FALSE},
4194             {"zip://:@gov.uk/",S_OK,FALSE},
4195             {"",S_FALSE,FALSE},
4196             {"",S_FALSE,FALSE},
4197             {"",S_FALSE,FALSE},
4198             {"gov.uk",S_OK,FALSE},
4199             {"",S_OK,FALSE},
4200             {"/",S_OK,FALSE},
4201             {"/",S_OK,FALSE},
4202             {"",S_FALSE,FALSE},
4203             {"zip://:@gov.uk",S_OK,FALSE},
4204             {"zip",S_OK,FALSE},
4205             {":",S_OK,FALSE},
4206             {"",S_FALSE,FALSE}
4207         },
4208         {
4209             {Uri_HOST_DNS,S_OK,FALSE},
4210             {0,S_FALSE,FALSE},
4211             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
4212             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4213         }
4214     },
4215     {   "about:blank", 0, S_OK, FALSE,
4216         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
4217         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
4218         FALSE,
4219         {
4220             {"about:blank",S_OK,FALSE},
4221             {"",S_FALSE,FALSE},
4222             {"about:blank",S_OK,FALSE},
4223             {"",S_FALSE,FALSE},
4224             {"",S_FALSE,FALSE},
4225             {"",S_FALSE,FALSE},
4226             {"",S_FALSE,FALSE},
4227             {"",S_FALSE,FALSE},
4228             {"blank",S_OK,FALSE},
4229             {"blank",S_OK,FALSE},
4230             {"",S_FALSE,FALSE},
4231             {"about:blank",S_OK,FALSE},
4232             {"about",S_OK,FALSE},
4233             {"",S_FALSE,FALSE},
4234             {"",S_FALSE,FALSE}
4235         },
4236         {
4237             {0,S_OK,FALSE},
4238             {0,S_FALSE,FALSE},
4239             {URL_SCHEME_ABOUT,S_OK,FALSE},
4240             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4241         }
4242     },
4243     {   "mk:@MSITStore:C:\\Program Files/AutoCAD 2008\\Help/acad_acg.chm::/WSfacf1429558a55de1a7524c1004e616f8b-322b.htm",0,S_OK,FALSE,
4244         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|
4245         Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
4246         FALSE,
4247         {
4248             {"mk:@MSITStore:C:\\Program%20Files/AutoCAD%202008\\Help/acad_acg.chm::/WSfacf1429558a55de1a7524c1004e616f8b-322b.htm",S_OK,FALSE},
4249             {"",S_FALSE,FALSE},
4250             {"mk:@MSITStore:C:\\Program%20Files/AutoCAD%202008\\Help/acad_acg.chm::/WSfacf1429558a55de1a7524c1004e616f8b-322b.htm",S_OK,FALSE},
4251             {"",S_FALSE,FALSE},
4252             {".htm",S_OK,FALSE},
4253             {"",S_FALSE,FALSE},
4254             {"",S_FALSE,FALSE},
4255             {"",S_FALSE,FALSE},
4256             {"@MSITStore:C:\\Program%20Files/AutoCAD%202008\\Help/acad_acg.chm::/WSfacf1429558a55de1a7524c1004e616f8b-322b.htm",S_OK,FALSE},
4257             {"@MSITStore:C:\\Program%20Files/AutoCAD%202008\\Help/acad_acg.chm::/WSfacf1429558a55de1a7524c1004e616f8b-322b.htm",S_OK,FALSE},
4258             {"",S_FALSE,FALSE},
4259             {"mk:@MSITStore:C:\\Program Files/AutoCAD 2008\\Help/acad_acg.chm::/WSfacf1429558a55de1a7524c1004e616f8b-322b.htm",S_OK,FALSE},
4260             {"mk",S_OK,FALSE},
4261             {"",S_FALSE,FALSE},
4262             {"",S_FALSE,FALSE}
4263         },
4264         {
4265             {Uri_HOST_UNKNOWN,S_OK,FALSE},
4266             {0,S_FALSE,FALSE},
4267             {URL_SCHEME_MK,S_OK,FALSE},
4268             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4269         }
4270     },
4271     {   "mk:@MSITStore:Z:\\home\\test\\chm\\silqhelp.chm::/thesilqquickstartguide.htm",0,S_OK,FALSE,
4272         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|
4273         Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
4274         FALSE,
4275         {
4276             {"mk:@MSITStore:Z:\\home\\test\\chm\\silqhelp.chm::/thesilqquickstartguide.htm",S_OK,FALSE},
4277             {"",S_FALSE,FALSE},
4278             {"mk:@MSITStore:Z:\\home\\test\\chm\\silqhelp.chm::/thesilqquickstartguide.htm",S_OK,FALSE},
4279             {"",S_FALSE,FALSE},
4280             {".htm",S_OK,FALSE},
4281             {"",S_FALSE,FALSE},
4282             {"",S_FALSE,FALSE},
4283             {"",S_FALSE,FALSE},
4284             {"@MSITStore:Z:\\home\\test\\chm\\silqhelp.chm::/thesilqquickstartguide.htm",S_OK,FALSE},
4285             {"@MSITStore:Z:\\home\\test\\chm\\silqhelp.chm::/thesilqquickstartguide.htm",S_OK,FALSE},
4286             {"",S_FALSE,FALSE},
4287             {"mk:@MSITStore:Z:\\home\\test\\chm\\silqhelp.chm::/thesilqquickstartguide.htm",S_OK,FALSE},
4288             {"mk",S_OK,FALSE},
4289             {"",S_FALSE,FALSE},
4290             {"",S_FALSE,FALSE}
4291         },
4292         {
4293             {Uri_HOST_UNKNOWN,S_OK,FALSE},
4294             {0,S_FALSE,FALSE},
4295             {URL_SCHEME_MK,S_OK,FALSE},
4296             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4297         }
4298     },
4299     /* Two '\' are added to the URI when USE_DOS_PATH is set, and it's a UNC path. */
4300     {   "file://server/dir/index.html", Uri_CREATE_FILE_USE_DOS_PATH, S_OK, FALSE,
4301         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_HOST|
4302         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|
4303         Uri_HAS_SCHEME, FALSE,
4304         {
4305             {"file://\\\\server\\dir\\index.html",S_OK,FALSE},
4306             {"server",S_OK,FALSE},
4307             {"file://\\\\server\\dir\\index.html",S_OK,FALSE},
4308             {"",S_FALSE,FALSE},
4309             {".html",S_OK,FALSE},
4310             {"",S_FALSE,FALSE},
4311             {"server",S_OK,FALSE},
4312             {"",S_FALSE,FALSE},
4313             {"\\dir\\index.html",S_OK,FALSE},
4314             {"\\dir\\index.html",S_OK,FALSE},
4315             {"",S_FALSE,FALSE},
4316             {"file://server/dir/index.html",S_OK,FALSE},
4317             {"file",S_OK,FALSE},
4318             {"",S_FALSE,FALSE},
4319             {"",S_FALSE,FALSE}
4320         },
4321         {
4322             {Uri_HOST_DNS,S_OK,FALSE},
4323             {0,S_FALSE,FALSE},
4324             {URL_SCHEME_FILE,S_OK,FALSE},
4325             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4326         }
4327     },
4328     /* When CreateUri generates an IUri, it still displays the default port in the
4329      * authority.
4330      */
4331     {   "http://google.com:80/", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
4332         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
4333         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
4334         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
4335         FALSE,
4336         {
4337             {"http://google.com:80/",S_OK,FALSE},
4338             {"google.com:80",S_OK,FALSE},
4339             {"http://google.com:80/",S_OK,FALSE},
4340             {"google.com",S_OK,FALSE},
4341             {"",S_FALSE,FALSE},
4342             {"",S_FALSE,FALSE},
4343             {"google.com",S_OK,FALSE},
4344             {"",S_FALSE,FALSE},
4345             {"/",S_OK,FALSE},
4346             {"/",S_OK,FALSE},
4347             {"",S_FALSE,FALSE},
4348             {"http://google.com:80/",S_OK,FALSE},
4349             {"http",S_OK,FALSE},
4350             {"",S_FALSE,FALSE},
4351             {"",S_FALSE,FALSE}
4352         },
4353         {
4354             {Uri_HOST_DNS,S_OK,FALSE},
4355             {80,S_OK,FALSE},
4356             {URL_SCHEME_HTTP,S_OK,FALSE},
4357             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4358         }
4359     }
4360 };
4361
4362 typedef struct _invalid_uri {
4363     const char* uri;
4364     DWORD       flags;
4365     BOOL        todo;
4366 } invalid_uri;
4367
4368 static const invalid_uri invalid_uri_tests[] = {
4369     /* Has to have a scheme name. */
4370     {"://www.winehq.org",0,FALSE},
4371     /* Window's doesn't like URI's which are implicitly file paths without the
4372      * ALLOW_IMPLICIT_FILE_SCHEME flag set.
4373      */
4374     {"C:/test/test.mp3",0,FALSE},
4375     {"\\\\Server/test/test.mp3",0,FALSE},
4376     {"C:/test/test.mp3",Uri_CREATE_ALLOW_IMPLICIT_WILDCARD_SCHEME,FALSE},
4377     {"\\\\Server/test/test.mp3",Uri_CREATE_ALLOW_RELATIVE,FALSE},
4378     /* Invalid schemes. */
4379     {"*abcd://not.valid.com",0,FALSE},
4380     {"*a*b*c*d://not.valid.com",0,FALSE},
4381     /* Not allowed to have invalid % encoded data. */
4382     {"ftp://google.co%XX/",0,FALSE},
4383     /* To many h16 components. */
4384     {"http://[1:2:3:4:5:6:7:8:9]",0,FALSE},
4385     /* Not enough room for IPv4 address. */
4386     {"http://[1:2:3:4:5:6:7:192.0.1.0]",0,FALSE},
4387     /* Not enough h16 components. */
4388     {"http://[1:2:3:4]",0,FALSE},
4389     /* Not enough components including IPv4. */
4390     {"http://[1:192.0.1.0]",0,FALSE},
4391     /* Not allowed to have partial IPv4 in IPv6. */
4392     {"http://[::192.0]",0,FALSE},
4393     /* Can't have elision of 1 h16 at beginning of address. */
4394     {"http://[::2:3:4:5:6:7:8]",0,FALSE},
4395     /* Can't have elision of 1 h16 at end of address. */
4396     {"http://[1:2:3:4:5:6:7::]",0,FALSE},
4397     /* Expects a valid IP Literal. */
4398     {"ftp://[not.valid.uri]/",0,FALSE},
4399     /* Expects valid port for a known scheme type. */
4400     {"ftp://www.winehq.org:123fgh",0,FALSE},
4401     /* Port exceeds USHORT_MAX for known scheme type. */
4402     {"ftp://www.winehq.org:65536",0,FALSE},
4403     /* Invalid port with IPv4 address. */
4404     {"http://www.winehq.org:1abcd",0,FALSE},
4405     /* Invalid port with IPv6 address. */
4406     {"http://[::ffff]:32xy",0,FALSE},
4407     /* Not allowed to have backslashes with NO_CANONICALIZE. */
4408     {"gopher://www.google.com\\test",Uri_CREATE_NO_CANONICALIZE,FALSE},
4409     /* Not allowed to have invalid % encoded data in opaque URI path. */
4410     {"news:test%XX",0,FALSE},
4411     {"mailto:wine@winehq%G8.com",0,FALSE},
4412     /* Known scheme types can't have invalid % encoded data in query string. */
4413     {"http://google.com/?query=te%xx",0,FALSE},
4414     /* Invalid % encoded data in fragment of know scheme type. */
4415     {"ftp://google.com/#Test%xx",0,FALSE},
4416     {"  http://google.com/",Uri_CREATE_NO_PRE_PROCESS_HTML_URI,FALSE},
4417     {"\n\nhttp://google.com/",Uri_CREATE_NO_PRE_PROCESS_HTML_URI,FALSE},
4418     {"file://c:\\test<test",Uri_CREATE_FILE_USE_DOS_PATH,FALSE},
4419     {"file://c:\\test>test",Uri_CREATE_FILE_USE_DOS_PATH,FALSE},
4420     {"file://c:\\test\"test",Uri_CREATE_FILE_USE_DOS_PATH,FALSE},
4421     {"file:c:\\test<test",Uri_CREATE_FILE_USE_DOS_PATH,FALSE},
4422     {"file:c:\\test>test",Uri_CREATE_FILE_USE_DOS_PATH,FALSE},
4423     {"file:c:\\test\"test",Uri_CREATE_FILE_USE_DOS_PATH,FALSE}
4424 };
4425
4426 typedef struct _uri_equality {
4427     const char* a;
4428     DWORD       create_flags_a;
4429     BOOL        create_todo_a;
4430     const char* b;
4431     DWORD       create_flags_b;
4432     BOOL        create_todo_b;
4433     BOOL        equal;
4434     BOOL        todo;
4435 } uri_equality;
4436
4437 static const uri_equality equality_tests[] = {
4438     {
4439         "HTTP://www.winehq.org/test dir/./",0,FALSE,
4440         "http://www.winehq.org/test dir/../test dir/",0,FALSE,
4441         TRUE, FALSE
4442     },
4443     {
4444         /* http://www.winehq.org/test%20dir */
4445         "http://%77%77%77%2E%77%69%6E%65%68%71%2E%6F%72%67/%74%65%73%74%20%64%69%72",0,FALSE,
4446         "http://www.winehq.org/test dir",0,FALSE,
4447         TRUE, FALSE
4448     },
4449     {
4450         "c:\\test.mp3",Uri_CREATE_ALLOW_IMPLICIT_FILE_SCHEME,FALSE,
4451         "file:///c:/test.mp3",0,FALSE,
4452         TRUE, FALSE
4453     },
4454     {
4455         "ftp://ftp.winehq.org/",0,FALSE,
4456         "ftp://ftp.winehq.org",0,FALSE,
4457         TRUE, FALSE
4458     },
4459     {
4460         "ftp://ftp.winehq.org/test/test2/../../testB/",0,FALSE,
4461         "ftp://ftp.winehq.org/t%45stB/",0,FALSE,
4462         FALSE, FALSE
4463     },
4464     {
4465         "http://google.com/TEST",0,FALSE,
4466         "http://google.com/test",0,FALSE,
4467         FALSE, FALSE
4468     },
4469     {
4470         "http://GOOGLE.com/",0,FALSE,
4471         "http://google.com/",0,FALSE,
4472         TRUE, FALSE
4473     },
4474     /* Performs case insensitive compare of host names (for known scheme types). */
4475     {
4476         "ftp://GOOGLE.com/",Uri_CREATE_NO_CANONICALIZE,FALSE,
4477         "ftp://google.com/",0,FALSE,
4478         TRUE, FALSE
4479     },
4480     {
4481         "zip://GOOGLE.com/",0,FALSE,
4482         "zip://google.com/",0,FALSE,
4483         FALSE, FALSE
4484     },
4485     {
4486         "file:///c:/TEST/TeST/",0,FALSE,
4487         "file:///c:/test/test/",0,FALSE,
4488         TRUE, FALSE
4489     },
4490     {
4491         "file:///server/TEST",0,FALSE,
4492         "file:///SERVER/TEST",0,FALSE,
4493         TRUE, FALSE
4494     },
4495     {
4496         "http://google.com",Uri_CREATE_NO_CANONICALIZE,FALSE,
4497         "http://google.com/",0,FALSE,
4498         TRUE, FALSE
4499     },
4500     {
4501         "ftp://google.com:21/",0,FALSE,
4502         "ftp://google.com/",0,FALSE,
4503         TRUE, FALSE
4504     },
4505     {
4506         "http://google.com:80/",Uri_CREATE_NO_CANONICALIZE,FALSE,
4507         "http://google.com/",0,FALSE,
4508         TRUE, FALSE
4509     },
4510     {
4511         "http://google.com:70/",0,FALSE,
4512         "http://google.com:71/",0,FALSE,
4513         FALSE, FALSE
4514     }
4515 };
4516
4517 typedef struct _uri_with_fragment {
4518     const char* uri;
4519     const char* fragment;
4520     DWORD       create_flags;
4521     HRESULT     create_expected;
4522     BOOL        create_todo;
4523
4524     const char* expected_uri;
4525     BOOL        expected_todo;
4526 } uri_with_fragment;
4527
4528 static const uri_with_fragment uri_fragment_tests[] = {
4529     {
4530         "http://google.com/","#fragment",0,S_OK,FALSE,
4531         "http://google.com/#fragment",FALSE
4532     },
4533     {
4534         "http://google.com/","fragment",0,S_OK,FALSE,
4535         "http://google.com/#fragment",FALSE
4536     },
4537     {
4538         "zip://test.com/","?test",0,S_OK,FALSE,
4539         "zip://test.com/#?test",FALSE
4540     },
4541     /* The fragment can be empty. */
4542     {
4543         "ftp://ftp.google.com/","",0,S_OK,FALSE,
4544         "ftp://ftp.google.com/#",FALSE
4545     }
4546 };
4547
4548 typedef struct _uri_builder_property {
4549     BOOL            change;
4550     const char      *value;
4551     const char      *expected_value;
4552     Uri_PROPERTY    property;
4553     HRESULT         expected;
4554     BOOL            todo;
4555 } uri_builder_property;
4556
4557 typedef struct _uri_builder_port {
4558     BOOL    change;
4559     BOOL    set;
4560     DWORD   value;
4561     HRESULT expected;
4562     BOOL    todo;
4563 } uri_builder_port;
4564
4565 typedef struct _uri_builder_str_property {
4566     const char* expected;
4567     HRESULT     result;
4568     BOOL        todo;
4569 } uri_builder_str_property;
4570
4571 typedef struct _uri_builder_dword_property {
4572     DWORD   expected;
4573     HRESULT result;
4574     BOOL    todo;
4575 } uri_builder_dword_property;
4576
4577 typedef struct _uri_builder_test {
4578     const char                  *uri;
4579     DWORD                       create_flags;
4580     HRESULT                     create_builder_expected;
4581     BOOL                        create_builder_todo;
4582
4583     uri_builder_property        properties[URI_BUILDER_STR_PROPERTY_COUNT];
4584
4585     uri_builder_port            port_prop;
4586
4587     DWORD                       uri_flags;
4588     HRESULT                     uri_hres;
4589     BOOL                        uri_todo;
4590
4591     DWORD                       uri_simple_encode_flags;
4592     HRESULT                     uri_simple_hres;
4593     BOOL                        uri_simple_todo;
4594
4595     DWORD                       uri_with_flags;
4596     DWORD                       uri_with_builder_flags;
4597     DWORD                       uri_with_encode_flags;
4598     HRESULT                     uri_with_hres;
4599     BOOL                        uri_with_todo;
4600
4601     uri_builder_str_property    expected_str_props[URI_STR_PROPERTY_COUNT];
4602     uri_builder_dword_property  expected_dword_props[URI_DWORD_PROPERTY_COUNT];
4603 } uri_builder_test;
4604
4605 static const uri_builder_test uri_builder_tests[] = {
4606     {   "http://google.com/",0,S_OK,FALSE,
4607         {
4608             {TRUE,"#fragment",NULL,Uri_PROPERTY_FRAGMENT,S_OK,FALSE},
4609             {TRUE,"password",NULL,Uri_PROPERTY_PASSWORD,S_OK,FALSE},
4610             {TRUE,"?query=x",NULL,Uri_PROPERTY_QUERY,S_OK,FALSE},
4611             {TRUE,"username",NULL,Uri_PROPERTY_USER_NAME,S_OK,FALSE}
4612         },
4613         {FALSE},
4614         0,S_OK,FALSE,
4615         0,S_OK,FALSE,
4616         0,0,0,S_OK,FALSE,
4617         {
4618             {"http://username:password@google.com/?query=x#fragment",S_OK},
4619             {"username:password@google.com",S_OK},
4620             {"http://google.com/?query=x#fragment",S_OK},
4621             {"google.com",S_OK},
4622             {"",S_FALSE},
4623             {"#fragment",S_OK},
4624             {"google.com",S_OK},
4625             {"password",S_OK},
4626             {"/",S_OK},
4627             {"/?query=x",S_OK},
4628             {"?query=x",S_OK},
4629             {"http://username:password@google.com/?query=x#fragment",S_OK},
4630             {"http",S_OK},
4631             {"username:password",S_OK},
4632             {"username",S_OK}
4633         },
4634         {
4635             {Uri_HOST_DNS,S_OK},
4636             {80,S_OK},
4637             {URL_SCHEME_HTTP,S_OK},
4638             {URLZONE_INVALID,E_NOTIMPL}
4639         }
4640     },
4641     {   "http://google.com/",0,S_OK,FALSE,
4642         {
4643             {TRUE,"test",NULL,Uri_PROPERTY_SCHEME_NAME,S_OK,FALSE}
4644         },
4645         {TRUE,TRUE,120,S_OK,FALSE},
4646         0,S_OK,FALSE,
4647         0,S_OK,FALSE,
4648         0,0,0,S_OK,FALSE,
4649         {
4650             {"test://google.com:120/",S_OK},
4651             {"google.com:120",S_OK},
4652             {"test://google.com:120/",S_OK},
4653             {"google.com",S_OK},
4654             {"",S_FALSE},
4655             {"",S_FALSE},
4656             {"google.com",S_OK},
4657             {"",S_FALSE},
4658             {"/",S_OK},
4659             {"/",S_OK},
4660             {"",S_FALSE},
4661             {"test://google.com:120/",S_OK},
4662             {"test",S_OK},
4663             {"",S_FALSE},
4664             {"",S_FALSE}
4665         },
4666         {
4667             {Uri_HOST_DNS,S_OK},
4668             {120,S_OK},
4669             {URL_SCHEME_UNKNOWN,S_OK},
4670             {URLZONE_INVALID,E_NOTIMPL}
4671         }
4672     },
4673     {   "/Test/test dir",Uri_CREATE_ALLOW_RELATIVE,S_OK,FALSE,
4674         {
4675             {TRUE,"http",NULL,Uri_PROPERTY_SCHEME_NAME,S_OK,FALSE},
4676             {TRUE,"::192.2.3.4",NULL,Uri_PROPERTY_HOST,S_OK,FALSE},
4677             {TRUE,NULL,NULL,Uri_PROPERTY_PATH,S_OK,FALSE}
4678         },
4679         {FALSE},
4680         0,S_OK,FALSE,
4681         0,S_OK,FALSE,
4682         0,0,0,S_OK,FALSE,
4683         {
4684             {"http://[::192.2.3.4]/",S_OK},
4685             {"[::192.2.3.4]",S_OK},
4686             {"http://[::192.2.3.4]/",S_OK},
4687             {"",S_FALSE},
4688             {"",S_FALSE},
4689             {"",S_FALSE},
4690             {"::192.2.3.4",S_OK},
4691             {"",S_FALSE},
4692             {"/",S_OK},
4693             {"/",S_OK},
4694             {"",S_FALSE},
4695             {"http://[::192.2.3.4]/",S_OK},
4696             {"http",S_OK},
4697             {"",S_FALSE},
4698             {"",S_FALSE}
4699         },
4700         {
4701             {Uri_HOST_IPV6,S_OK},
4702             {80,S_OK},
4703             {URL_SCHEME_HTTP,S_OK},
4704             {URLZONE_INVALID,E_NOTIMPL}
4705         }
4706     },
4707     {   "http://google.com/",0,S_OK,FALSE,
4708         {
4709             {TRUE,"Frag","#Frag",Uri_PROPERTY_FRAGMENT,S_OK,FALSE}
4710         },
4711         {FALSE},
4712         0,S_OK,FALSE,
4713         0,S_OK,FALSE,
4714         0,0,0,S_OK,FALSE,
4715         {
4716             {"http://google.com/#Frag",S_OK},
4717             {"google.com",S_OK},
4718             {"http://google.com/#Frag",S_OK},
4719             {"google.com",S_OK},
4720             {"",S_FALSE},
4721             {"#Frag",S_OK},
4722             {"google.com",S_OK},
4723             {"",S_FALSE},
4724             {"/",S_OK},
4725             {"/",S_OK},
4726             {"",S_FALSE},
4727             {"http://google.com/#Frag",S_OK},
4728             {"http",S_OK},
4729             {"",S_FALSE},
4730             {"",S_FALSE}
4731         },
4732         {
4733             {Uri_HOST_DNS,S_OK},
4734             {80,S_OK},
4735             {URL_SCHEME_HTTP,S_OK},
4736             {URLZONE_INVALID,E_NOTIMPL}
4737         }
4738     },
4739     {   "http://google.com/",0,S_OK,FALSE,
4740         {
4741             {TRUE,"","#",Uri_PROPERTY_FRAGMENT,S_OK,FALSE},
4742         },
4743         {FALSE},
4744         0,S_OK,FALSE,
4745         0,S_OK,FALSE,
4746         0,0,0,S_OK,FALSE,
4747         {
4748             {"http://google.com/#",S_OK},
4749             {"google.com",S_OK},
4750             {"http://google.com/#",S_OK},
4751             {"google.com",S_OK},
4752             {"",S_FALSE},
4753             {"#",S_OK},
4754             {"google.com",S_OK},
4755             {"",S_FALSE},
4756             {"/",S_OK},
4757             {"/",S_OK},
4758             {"",S_FALSE},
4759             {"http://google.com/#",S_OK},
4760             {"http",S_OK},
4761             {"",S_FALSE},
4762             {"",S_FALSE}
4763         },
4764         {
4765             {Uri_HOST_DNS,S_OK},
4766             {80,S_OK},
4767             {URL_SCHEME_HTTP,S_OK},
4768             {URLZONE_INVALID,E_NOTIMPL}
4769         }
4770     },
4771     {   "http://google.com/",0,S_OK,FALSE,
4772         {
4773             {TRUE,":password",NULL,Uri_PROPERTY_PASSWORD,S_OK,FALSE}
4774         },
4775         {FALSE},
4776         0,S_OK,FALSE,
4777         0,S_OK,FALSE,
4778         0,0,0,S_OK,FALSE,
4779         {
4780             {"http://::password@google.com/",S_OK},
4781             {"::password@google.com",S_OK},
4782             {"http://google.com/",S_OK},
4783             {"google.com",S_OK},
4784             {"",S_FALSE},
4785             {"",S_FALSE},
4786             {"google.com",S_OK},
4787             {":password",S_OK},
4788             {"/",S_OK},
4789             {"/",S_OK},
4790             {"",S_FALSE},
4791             {"http://::password@google.com/",S_OK},
4792             {"http",S_OK},
4793             {"::password",S_OK},
4794             {"",S_FALSE}
4795         },
4796         {
4797             {Uri_HOST_DNS,S_OK},
4798             {80,S_OK},
4799             {URL_SCHEME_HTTP,S_OK},
4800             {URLZONE_INVALID,E_NOTIMPL}
4801         }
4802     },
4803     {   "test/test",Uri_CREATE_ALLOW_RELATIVE,S_OK,FALSE,
4804         {
4805             {TRUE,"password",NULL,Uri_PROPERTY_PASSWORD,S_OK,FALSE}
4806         },
4807         {FALSE},
4808         Uri_CREATE_ALLOW_RELATIVE,S_OK,FALSE,
4809         0,S_OK,FALSE,
4810         Uri_CREATE_ALLOW_RELATIVE,0,0,S_OK,FALSE,
4811         {
4812             {":password@test/test",S_OK},
4813             {":password@",S_OK},
4814             {":password@test/test",S_OK},
4815             {"",S_FALSE},
4816             {"",S_FALSE},
4817             {"",S_FALSE},
4818             {"",S_FALSE},
4819             {"password",S_OK},
4820             {"test/test",S_OK},
4821             {"test/test",S_OK},
4822             {"",S_FALSE},
4823             {":password@test/test",S_OK},
4824             {"",S_FALSE},
4825             {":password",S_OK},
4826             {"",S_FALSE}
4827         },
4828         {
4829             {Uri_HOST_UNKNOWN,S_OK},
4830             {0,S_FALSE},
4831             {URL_SCHEME_UNKNOWN,S_OK},
4832             {URLZONE_INVALID,E_NOTIMPL}
4833         }
4834     },
4835     {   "http://google.com/",0,S_OK,FALSE,
4836         {
4837             {TRUE,"test/test",NULL,Uri_PROPERTY_PATH,S_OK,FALSE},
4838         },
4839         {FALSE},
4840         0,S_OK,FALSE,
4841         0,S_OK,FALSE,
4842         0,0,0,S_OK,FALSE,
4843         {
4844             {"http://google.com/test/test",S_OK},
4845             {"google.com",S_OK},
4846             {"http://google.com/test/test",S_OK},
4847             {"google.com",S_OK},
4848             {"",S_FALSE},
4849             {"",S_FALSE},
4850             {"google.com",S_OK},
4851             {"",S_FALSE},
4852             {"/test/test",S_OK},
4853             {"/test/test",S_OK},
4854             {"",S_FALSE},
4855             {"http://google.com/test/test",S_OK},
4856             {"http",S_OK},
4857             {"",S_FALSE},
4858             {"",S_FALSE}
4859         },
4860         {
4861             {Uri_HOST_DNS,S_OK},
4862             {80,S_OK},
4863             {URL_SCHEME_HTTP,S_OK},
4864             {URLZONE_INVALID,E_NOTIMPL}
4865         }
4866     },
4867     {   "zip:testing/test",0,S_OK,FALSE,
4868         {
4869             {TRUE,"test",NULL,Uri_PROPERTY_PATH,S_OK,FALSE},
4870         },
4871         {FALSE},
4872         0,S_OK,FALSE,
4873         0,S_OK,FALSE,
4874         0,0,0,S_OK,FALSE,
4875         {
4876             {"zip:test",S_OK},
4877             {"",S_FALSE},
4878             {"zip:test",S_OK},
4879             {"",S_FALSE},
4880             {"",S_FALSE},
4881             {"",S_FALSE},
4882             {"",S_FALSE},
4883             {"",S_FALSE},
4884             {"test",S_OK},
4885             {"test",S_OK},
4886             {"",S_FALSE},
4887             {"zip:test",S_OK},
4888             {"zip",S_OK},
4889             {"",S_FALSE},
4890             {"",S_FALSE}
4891         },
4892         {
4893             {Uri_HOST_UNKNOWN,S_OK},
4894             {0,S_FALSE},
4895             {URL_SCHEME_UNKNOWN,S_OK},
4896             {URLZONE_INVALID,E_NOTIMPL}
4897         }
4898     },
4899     {   "http://google.com/",0,S_OK,FALSE,
4900         {
4901             {FALSE},
4902         },
4903         /* 555 will be returned from GetPort even though FALSE was passed as the hasPort parameter. */
4904         {TRUE,FALSE,555,S_OK,FALSE},
4905         0,S_OK,FALSE,
4906         0,S_OK,FALSE,
4907         0,0,0,S_OK,FALSE,
4908         {
4909             {"http://google.com/",S_OK},
4910             {"google.com",S_OK},
4911             {"http://google.com/",S_OK},
4912             {"google.com",S_OK},
4913             {"",S_FALSE},
4914             {"",S_FALSE},
4915             {"google.com",S_OK},
4916             {"",S_FALSE},
4917             {"/",S_OK},
4918             {"/",S_OK},
4919             {"",S_FALSE},
4920             {"http://google.com/",S_OK},
4921             {"http",S_OK},
4922             {"",S_FALSE},
4923             {"",S_FALSE}
4924         },
4925         {
4926             {Uri_HOST_DNS,S_OK},
4927             /* Still returns 80, even though earlier the port was disabled. */
4928             {80,S_OK},
4929             {URL_SCHEME_HTTP,S_OK},
4930             {URLZONE_INVALID,E_NOTIMPL}
4931         }
4932     },
4933     {   "http://google.com/",0,S_OK,FALSE,
4934         {
4935             {FALSE},
4936         },
4937         /* Instead of getting "TRUE" back as the "hasPort" parameter in GetPort,
4938          * you'll get 122345 instead.
4939          */
4940         {TRUE,122345,222,S_OK,FALSE},
4941         0,S_OK,FALSE,
4942         0,S_OK,FALSE,
4943         0,0,0,S_OK,FALSE,
4944         {
4945             {"http://google.com:222/",S_OK},
4946             {"google.com:222",S_OK},
4947             {"http://google.com:222/",S_OK},
4948             {"google.com",S_OK},
4949             {"",S_FALSE},
4950             {"",S_FALSE},
4951             {"google.com",S_OK},
4952             {"",S_FALSE},
4953             {"/",S_OK},
4954             {"/",S_OK},
4955             {"",S_FALSE},
4956             {"http://google.com:222/",S_OK},
4957             {"http",S_OK},
4958             {"",S_FALSE},
4959             {"",S_FALSE}
4960         },
4961         {
4962             {Uri_HOST_DNS,S_OK},
4963             {222,S_OK},
4964             {URL_SCHEME_HTTP,S_OK},
4965             {URLZONE_INVALID,E_NOTIMPL}
4966         }
4967     },
4968     /* IUri's created with the IUriBuilder can have ports that exceed USHORT_MAX. */
4969     {   "http://google.com/",0,S_OK,FALSE,
4970         {
4971             {FALSE},
4972         },
4973         {TRUE,TRUE,999999,S_OK,FALSE},
4974         0,S_OK,FALSE,
4975         0,S_OK,FALSE,
4976         0,0,0,S_OK,FALSE,
4977         {
4978             {"http://google.com:999999/",S_OK},
4979             {"google.com:999999",S_OK},
4980             {"http://google.com:999999/",S_OK},
4981             {"google.com",S_OK},
4982             {"",S_FALSE},
4983             {"",S_FALSE},
4984             {"google.com",S_OK},
4985             {"",S_FALSE},
4986             {"/",S_OK},
4987             {"/",S_OK},
4988             {"",S_FALSE},
4989             {"http://google.com:999999/",S_OK},
4990             {"http",S_OK},
4991             {"",S_FALSE},
4992             {"",S_FALSE}
4993         },
4994         {
4995             {Uri_HOST_DNS,S_OK},
4996             {999999,S_OK},
4997             {URL_SCHEME_HTTP,S_OK},
4998             {URLZONE_INVALID,E_NOTIMPL}
4999         }
5000     },
5001     {   "http://google.com/",0,S_OK,FALSE,
5002         {
5003             {TRUE,"test","?test",Uri_PROPERTY_QUERY,S_OK,FALSE},
5004         },
5005
5006         {FALSE},
5007         0,S_OK,FALSE,
5008         0,S_OK,FALSE,
5009         0,0,0,S_OK,FALSE,
5010         {
5011             {"http://google.com/?test",S_OK},
5012             {"google.com",S_OK},
5013             {"http://google.com/?test",S_OK},
5014             {"google.com",S_OK},
5015             {"",S_FALSE},
5016             {"",S_FALSE},
5017             {"google.com",S_OK},
5018             {"",S_FALSE},
5019             {"/",S_OK},
5020             {"/?test",S_OK},
5021             {"?test",S_OK},
5022             {"http://google.com/?test",S_OK},
5023             {"http",S_OK},
5024             {"",S_FALSE},
5025             {"",S_FALSE}
5026         },
5027         {
5028             {Uri_HOST_DNS,S_OK},
5029             {80,S_OK},
5030             {URL_SCHEME_HTTP,S_OK},
5031             {URLZONE_INVALID,E_NOTIMPL}
5032         }
5033     },
5034     {   "http://:password@google.com/",0,S_OK,FALSE,
5035         {
5036             {FALSE},
5037         },
5038         {FALSE},
5039         0,S_OK,FALSE,
5040         0,S_OK,FALSE,
5041         0,0,0,S_OK,FALSE,
5042         {
5043             {"http://:password@google.com/",S_OK},
5044             {":password@google.com",S_OK},
5045             {"http://google.com/",S_OK},
5046             {"google.com",S_OK},
5047             {"",S_FALSE},
5048             {"",S_FALSE},
5049             {"google.com",S_OK},
5050             {"password",S_OK},
5051             {"/",S_OK},
5052             {"/",S_OK},
5053             {"",S_FALSE},
5054             {"http://:password@google.com/",S_OK},
5055             {"http",S_OK},
5056             {":password",S_OK},
5057             {"",S_FALSE}
5058         },
5059         {
5060             {Uri_HOST_DNS,S_OK},
5061             {80,S_OK},
5062             {URL_SCHEME_HTTP,S_OK},
5063             {URLZONE_INVALID,E_NOTIMPL}
5064         }
5065     },
5066     /* IUriBuilder doesn't need a base IUri to build a IUri. */
5067     {   NULL,0,S_OK,FALSE,
5068         {
5069             {TRUE,"http",NULL,Uri_PROPERTY_SCHEME_NAME,S_OK,FALSE},
5070             {TRUE,"google.com",NULL,Uri_PROPERTY_HOST,S_OK,FALSE}
5071         },
5072         {FALSE},
5073         0,S_OK,FALSE,
5074         0,S_OK,FALSE,
5075         0,0,0,S_OK,FALSE,
5076         {
5077             {"http://google.com/",S_OK},
5078             {"google.com",S_OK},
5079             {"http://google.com/",S_OK},
5080             {"google.com",S_OK},
5081             {"",S_FALSE},
5082             {"",S_FALSE},
5083             {"google.com",S_OK},
5084             {"",S_FALSE},
5085             {"/",S_OK},
5086             {"/",S_OK},
5087             {"",S_FALSE},
5088             {"http://google.com/",S_OK},
5089             {"http",S_OK},
5090             {"",S_FALSE},
5091             {"",S_FALSE}
5092         },
5093         {
5094             {Uri_HOST_DNS,S_OK},
5095             {80,S_OK},
5096             {URL_SCHEME_HTTP,S_OK},
5097             {URLZONE_INVALID,E_NOTIMPL}
5098         }
5099     },
5100     /* Can't set the scheme name to NULL. */
5101     {   "zip://google.com/",0,S_OK,FALSE,
5102         {
5103             {TRUE,NULL,"zip",Uri_PROPERTY_SCHEME_NAME,E_INVALIDARG,FALSE}
5104         },
5105         {FALSE},
5106         0,S_OK,FALSE,
5107         0,S_OK,FALSE,
5108         0,0,0,S_OK,FALSE,
5109         {
5110             {"zip://google.com/",S_OK},
5111             {"google.com",S_OK},
5112             {"zip://google.com/",S_OK},
5113             {"google.com",S_OK},
5114             {"",S_FALSE},
5115             {"",S_FALSE},
5116             {"google.com",S_OK},
5117             {"",S_FALSE},
5118             {"/",S_OK},
5119             {"/",S_OK},
5120             {"",S_FALSE},
5121             {"zip://google.com/",S_OK},
5122             {"zip",S_OK},
5123             {"",S_FALSE},
5124             {"",S_FALSE}
5125         },
5126         {
5127             {Uri_HOST_DNS,S_OK},
5128             {0,S_FALSE},
5129             {URL_SCHEME_UNKNOWN,S_OK},
5130             {URLZONE_INVALID,E_NOTIMPL}
5131         }
5132     },
5133     /* Can't set the scheme name to an empty string. */
5134     {   "zip://google.com/",0,S_OK,FALSE,
5135         {
5136             {TRUE,"","zip",Uri_PROPERTY_SCHEME_NAME,E_INVALIDARG,FALSE}
5137         },
5138         {FALSE},
5139         0,S_OK,FALSE,
5140         0,S_OK,FALSE,
5141         0,0,0,S_OK,FALSE,
5142         {
5143             {"zip://google.com/",S_OK},
5144             {"google.com",S_OK},
5145             {"zip://google.com/",S_OK},
5146             {"google.com",S_OK},
5147             {"",S_FALSE},
5148             {"",S_FALSE},
5149             {"google.com",S_OK},
5150             {"",S_FALSE},
5151             {"/",S_OK},
5152             {"/",S_OK},
5153             {"",S_FALSE},
5154             {"zip://google.com/",S_OK},
5155             {"zip",S_OK},
5156             {"",S_FALSE},
5157             {"",S_FALSE}
5158         },
5159         {
5160             {Uri_HOST_DNS,S_OK},
5161             {0,S_FALSE},
5162             {URL_SCHEME_UNKNOWN,S_OK},
5163             {URLZONE_INVALID,E_NOTIMPL}
5164         }
5165     },
5166     /* -1 to CreateUri makes it use the same flags as the base IUri was created with.
5167      * CreateUriSimple always uses the flags the base IUri was created with (if any).
5168      */
5169     {   "http://google.com/../../",Uri_CREATE_NO_CANONICALIZE,S_OK,FALSE,
5170         {{FALSE}},
5171         {FALSE},
5172         -1,S_OK,FALSE,
5173         0,S_OK,FALSE,
5174         0,UriBuilder_USE_ORIGINAL_FLAGS,0,S_OK,FALSE,
5175         {
5176             {"http://google.com/../../",S_OK},
5177             {"google.com",S_OK},
5178             {"http://google.com/../../",S_OK},
5179             {"google.com",S_OK},
5180             {"",S_FALSE},
5181             {"",S_FALSE},
5182             {"google.com",S_OK},
5183             {"",S_FALSE},
5184             {"/../../",S_OK},
5185             {"/../../",S_OK},
5186             {"",S_FALSE},
5187             {"http://google.com/../../",S_OK},
5188             {"http",S_OK},
5189             {"",S_FALSE},
5190             {"",S_FALSE}
5191         },
5192         {
5193             {Uri_HOST_DNS,S_OK},
5194             {80,S_OK},
5195             {URL_SCHEME_HTTP,S_OK},
5196             {URLZONE_INVALID,E_NOTIMPL}
5197         }
5198     },
5199     {   "http://google.com/",0,S_OK,FALSE,
5200         {
5201             {TRUE,"#Fr<|>g",NULL,Uri_PROPERTY_FRAGMENT,S_OK,FALSE}
5202         },
5203         {FALSE},
5204         -1,S_OK,FALSE,
5205         0,S_OK,FALSE,
5206         Uri_CREATE_NO_DECODE_EXTRA_INFO,UriBuilder_USE_ORIGINAL_FLAGS,0,S_OK,FALSE,
5207         {
5208             {"http://google.com/#Fr%3C%7C%3Eg",S_OK},
5209             {"google.com",S_OK},
5210             {"http://google.com/#Fr%3C%7C%3Eg",S_OK},
5211             {"google.com",S_OK},
5212             {"",S_FALSE},
5213             {"#Fr%3C%7C%3Eg",S_OK},
5214             {"google.com",S_OK},
5215             {"",S_FALSE},
5216             {"/",S_OK},
5217             {"/",S_OK},
5218             {"",S_FALSE},
5219             {"http://google.com/#Fr<|>g",S_OK},
5220             {"http",S_OK},
5221             {"",S_FALSE},
5222             {"",S_FALSE}
5223         },
5224         {
5225             {Uri_HOST_DNS,S_OK},
5226             {80,S_OK},
5227             {URL_SCHEME_HTTP,S_OK},
5228             {URLZONE_INVALID,E_NOTIMPL}
5229         }
5230     },
5231     {   "http://google.com/",0,S_OK,FALSE,
5232         {
5233             {TRUE,"#Fr<|>g",NULL,Uri_PROPERTY_FRAGMENT,S_OK,FALSE}
5234         },
5235         {FALSE},
5236         Uri_CREATE_CANONICALIZE|Uri_CREATE_NO_CANONICALIZE,E_INVALIDARG,FALSE,
5237         0,S_OK,FALSE,
5238         Uri_CREATE_CANONICALIZE|Uri_CREATE_NO_CANONICALIZE,UriBuilder_USE_ORIGINAL_FLAGS,0,S_OK,FALSE,
5239         {
5240             {"http://google.com/#Fr%3C%7C%3Eg",S_OK},
5241             {"google.com",S_OK},
5242             {"http://google.com/#Fr%3C%7C%3Eg",S_OK},
5243             {"google.com",S_OK},
5244             {"",S_FALSE},
5245             {"#Fr%3C%7C%3Eg",S_OK},
5246             {"google.com",S_OK},
5247             {"",S_FALSE},
5248             {"/",S_OK},
5249             {"/",S_OK},
5250             {"",S_FALSE},
5251             {"http://google.com/#Fr<|>g",S_OK},
5252             {"http",S_OK},
5253             {"",S_FALSE},
5254             {"",S_FALSE}
5255         },
5256         {
5257             {Uri_HOST_DNS,S_OK},
5258             {80,S_OK},
5259             {URL_SCHEME_HTTP,S_OK},
5260             {URLZONE_INVALID,E_NOTIMPL}
5261         }
5262     },
5263     {   NULL,0,S_OK,FALSE,
5264         {
5265             {TRUE,"/test/test/",NULL,Uri_PROPERTY_PATH,S_OK,FALSE},
5266             {TRUE,"#Fr<|>g",NULL,Uri_PROPERTY_FRAGMENT,S_OK,FALSE}
5267         },
5268         {FALSE},
5269         0,INET_E_INVALID_URL,FALSE,
5270         0,INET_E_INVALID_URL,FALSE,
5271         0,0,0,INET_E_INVALID_URL,FALSE
5272     },
5273     {   "http://google.com/",0,S_OK,FALSE,
5274         {
5275             {TRUE,"ht%xxtp",NULL,Uri_PROPERTY_SCHEME_NAME,S_OK,FALSE}
5276         },
5277         {FALSE},
5278         0,INET_E_INVALID_URL,FALSE,
5279         0,INET_E_INVALID_URL,FALSE,
5280         0,0,0,INET_E_INVALID_URL,FALSE
5281     },
5282     /* File scheme's can't have a username set. */
5283     {   "file://google.com/",0,S_OK,FALSE,
5284         {
5285             {TRUE,"username",NULL,Uri_PROPERTY_USER_NAME,S_OK,FALSE}
5286         },
5287         {FALSE},
5288         0,INET_E_INVALID_URL,FALSE,
5289         0,INET_E_INVALID_URL,FALSE,
5290         0,0,0,INET_E_INVALID_URL,FALSE
5291     },
5292     /* File schemes can't have a password set. */
5293     {   "file://google.com/",0,S_OK,FALSE,
5294         {
5295             {TRUE,"password",NULL,Uri_PROPERTY_PASSWORD,S_OK,FALSE}
5296         },
5297         {FALSE},
5298         0,INET_E_INVALID_URL,FALSE,
5299         0,INET_E_INVALID_URL,FALSE,
5300         0,0,0,INET_E_INVALID_URL,FALSE
5301     },
5302     /* UserName can't contain any character that is a delimeter for another
5303      * component that appears after it in a normal URI.
5304      */
5305     {   "http://google.com/",0,S_OK,FALSE,
5306         {
5307             {TRUE,"user:pass",NULL,Uri_PROPERTY_USER_NAME,S_OK,FALSE}
5308         },
5309         {FALSE},
5310         0,INET_E_INVALID_URL,FALSE,
5311         0,INET_E_INVALID_URL,FALSE,
5312         0,0,0,INET_E_INVALID_URL,FALSE
5313     },
5314     {   "http://google.com/",0,S_OK,FALSE,
5315         {
5316             {TRUE,"user@google.com",NULL,Uri_PROPERTY_USER_NAME,S_OK,FALSE}
5317         },
5318         {FALSE},
5319         0,INET_E_INVALID_URL,FALSE,
5320         0,INET_E_INVALID_URL,FALSE,
5321         0,0,0,INET_E_INVALID_URL,FALSE
5322     },
5323     {   "http://google.com/",0,S_OK,FALSE,
5324         {
5325             {TRUE,"user/path",NULL,Uri_PROPERTY_USER_NAME,S_OK,FALSE}
5326         },
5327         {FALSE},
5328         0,INET_E_INVALID_URL,FALSE,
5329         0,INET_E_INVALID_URL,FALSE,
5330         0,0,0,INET_E_INVALID_URL,FALSE
5331     },
5332     {   "http://google.com/",0,S_OK,FALSE,
5333         {
5334             {TRUE,"user?Query",NULL,Uri_PROPERTY_USER_NAME,S_OK,FALSE}
5335         },
5336         {FALSE},
5337         0,INET_E_INVALID_URL,FALSE,
5338         0,INET_E_INVALID_URL,FALSE,
5339         0,0,0,INET_E_INVALID_URL,FALSE
5340     },
5341     {   "http://google.com/",0,S_OK,FALSE,
5342         {
5343             {TRUE,"user#Frag",NULL,Uri_PROPERTY_USER_NAME,S_OK,FALSE}
5344         },
5345         {FALSE},
5346         0,INET_E_INVALID_URL,FALSE,
5347         0,INET_E_INVALID_URL,FALSE,
5348         0,0,0,INET_E_INVALID_URL,FALSE
5349     },
5350     {   "http://google.com/",0,S_OK,FALSE,
5351         {
5352             {TRUE,"pass@google.com",NULL,Uri_PROPERTY_PASSWORD,S_OK,FALSE}
5353         },
5354         {FALSE},
5355         0,INET_E_INVALID_URL,FALSE,
5356         0,INET_E_INVALID_URL,FALSE,
5357         0,0,0,INET_E_INVALID_URL,FALSE
5358     },
5359     {   "http://google.com/",0,S_OK,FALSE,
5360         {
5361             {TRUE,"pass/path",NULL,Uri_PROPERTY_PASSWORD,S_OK,FALSE}
5362         },
5363         {FALSE},
5364         0,INET_E_INVALID_URL,FALSE,
5365         0,INET_E_INVALID_URL,FALSE,
5366         0,0,0,INET_E_INVALID_URL,FALSE
5367     },
5368     {   "http://google.com/",0,S_OK,FALSE,
5369         {
5370             {TRUE,"pass?query",NULL,Uri_PROPERTY_PASSWORD,S_OK,FALSE}
5371         },
5372         {FALSE},
5373         0,INET_E_INVALID_URL,FALSE,
5374         0,INET_E_INVALID_URL,FALSE,
5375        0,0,0,INET_E_INVALID_URL,FALSE
5376     },
5377     {   "http://google.com/",0,S_OK,FALSE,
5378         {
5379             {TRUE,"pass#frag",NULL,Uri_PROPERTY_PASSWORD,S_OK,FALSE}
5380         },
5381         {FALSE},
5382         0,INET_E_INVALID_URL,FALSE,
5383         0,INET_E_INVALID_URL,FALSE,
5384         0,0,0,INET_E_INVALID_URL,FALSE
5385     },
5386     {   "http://google.com/",0,S_OK,FALSE,
5387         {
5388             {TRUE,"winehq.org/test",NULL,Uri_PROPERTY_HOST,S_OK,FALSE}
5389         },
5390         {FALSE},
5391         0,INET_E_INVALID_URL,FALSE,
5392         0,INET_E_INVALID_URL,FALSE,
5393         0,0,0,INET_E_INVALID_URL,FALSE
5394     },
5395     {   "http://google.com/",0,S_OK,FALSE,
5396         {
5397             {TRUE,"winehq.org?test",NULL,Uri_PROPERTY_HOST,S_OK,FALSE}
5398         },
5399         {FALSE},
5400         0,INET_E_INVALID_URL,FALSE,
5401         0,INET_E_INVALID_URL,FALSE,
5402         0,0,0,INET_E_INVALID_URL,FALSE
5403     },
5404     {   "http://google.com/",0,S_OK,FALSE,
5405         {
5406             {TRUE,"winehq.org#test",NULL,Uri_PROPERTY_HOST,S_OK,FALSE}
5407         },
5408         {FALSE},
5409         0,INET_E_INVALID_URL,FALSE,
5410         0,INET_E_INVALID_URL,FALSE,
5411         0,0,0,INET_E_INVALID_URL,FALSE
5412     },
5413     /* Hostname is allowed to contain a ':' (even for known scheme types). */
5414     {   "http://google.com/",0,S_OK,FALSE,
5415         {
5416             {TRUE,"winehq.org:test",NULL,Uri_PROPERTY_HOST,S_OK,FALSE},
5417         },
5418         {FALSE},
5419         0,S_OK,FALSE,
5420         0,S_OK,FALSE,
5421         0,0,0,S_OK,FALSE,
5422         {
5423             {"http://winehq.org:test/",S_OK},
5424             {"winehq.org:test",S_OK},
5425             {"http://winehq.org:test/",S_OK},
5426             {"winehq.org:test",S_OK},
5427             {"",S_FALSE},
5428             {"",S_FALSE},
5429             {"winehq.org:test",S_OK},
5430             {"",S_FALSE},
5431             {"/",S_OK},
5432             {"/",S_OK},
5433             {"",S_FALSE},
5434             {"http://winehq.org:test/",S_OK},
5435             {"http",S_OK},
5436             {"",S_FALSE},
5437             {"",S_FALSE}
5438         },
5439         {
5440             {Uri_HOST_DNS,S_OK},
5441             {80,S_OK},
5442             {URL_SCHEME_HTTP,S_OK},
5443             {URLZONE_INVALID,E_NOTIMPL}
5444         }
5445     },
5446     /* Can't set the host name to NULL. */
5447     {   "http://google.com/",0,S_OK,FALSE,
5448         {
5449             {TRUE,NULL,"google.com",Uri_PROPERTY_HOST,E_INVALIDARG,FALSE}
5450         },
5451         {FALSE},
5452         0,S_OK,FALSE,
5453         0,S_OK,FALSE,
5454         0,0,0,S_OK,FALSE,
5455         {
5456             {"http://google.com/",S_OK},
5457             {"google.com",S_OK},
5458             {"http://google.com/",S_OK},
5459             {"google.com",S_OK},
5460             {"",S_FALSE},
5461             {"",S_FALSE},
5462             {"google.com",S_OK},
5463             {"",S_FALSE},
5464             {"/",S_OK},
5465             {"/",S_OK},
5466             {"",S_FALSE},
5467             {"http://google.com/",S_OK},
5468             {"http",S_OK},
5469             {"",S_FALSE},
5470             {"",S_FALSE}
5471         },
5472         {
5473             {Uri_HOST_DNS,S_OK},
5474             {80,S_OK},
5475             {URL_SCHEME_HTTP,S_OK},
5476             {URLZONE_INVALID,E_NOTIMPL}
5477         }
5478     },
5479     /* Can set the host name to an empty string. */
5480     {   "http://google.com/",0,S_OK,FALSE,
5481         {
5482             {TRUE,"",NULL,Uri_PROPERTY_HOST,S_OK,FALSE}
5483         },
5484         {FALSE},
5485         0,S_OK,FALSE,
5486         0,S_OK,FALSE,
5487         0,0,0,S_OK,FALSE,
5488         {
5489             {"http:///",S_OK},
5490             {"",S_OK},
5491             {"http:///",S_OK},
5492             {"",S_FALSE},
5493             {"",S_FALSE},
5494             {"",S_FALSE},
5495             {"",S_OK},
5496             {"",S_FALSE},
5497             {"/",S_OK},
5498             {"/",S_OK},
5499             {"",S_FALSE},
5500             {"http:///",S_OK},
5501             {"http",S_OK},
5502             {"",S_FALSE},
5503             {"",S_FALSE}
5504         },
5505         {
5506             {Uri_HOST_UNKNOWN,S_OK},
5507             {80,S_OK},
5508             {URL_SCHEME_HTTP,S_OK},
5509             {URLZONE_INVALID,E_NOTIMPL}
5510         }
5511     },
5512     {   "http://google.com/",0,S_OK,FALSE,
5513         {
5514             {TRUE,"/path?query",NULL,Uri_PROPERTY_PATH,S_OK,FALSE}
5515         },
5516         {FALSE},
5517         0,INET_E_INVALID_URL,FALSE,
5518         0,INET_E_INVALID_URL,FALSE,
5519         0,0,0,INET_E_INVALID_URL,FALSE
5520     },
5521     {   "http://google.com/",0,S_OK,FALSE,
5522         {
5523             {TRUE,"/path#test",NULL,Uri_PROPERTY_PATH,S_OK,FALSE}
5524         },
5525         {FALSE},
5526         0,INET_E_INVALID_URL,FALSE,
5527         0,INET_E_INVALID_URL,FALSE,
5528         0,0,0,INET_E_INVALID_URL,FALSE
5529     },
5530     {   "http://google.com/",0,S_OK,FALSE,
5531         {
5532             {TRUE,"?path#test",NULL,Uri_PROPERTY_QUERY,S_OK,FALSE}
5533         },
5534         {FALSE},
5535         0,INET_E_INVALID_URL,FALSE,
5536         0,INET_E_INVALID_URL,FALSE,
5537         0,0,0,INET_E_INVALID_URL,FALSE
5538     }
5539 };
5540
5541 typedef struct _uri_builder_remove_test {
5542     const char  *uri;
5543     DWORD       create_flags;
5544     HRESULT     create_builder_expected;
5545     BOOL        create_builder_todo;
5546
5547     DWORD       remove_properties;
5548     HRESULT     remove_expected;
5549     BOOL        remove_todo;
5550
5551     const char  *expected_uri;
5552     DWORD       expected_flags;
5553     HRESULT     expected_hres;
5554     BOOL        expected_todo;
5555 } uri_builder_remove_test;
5556
5557 static const uri_builder_remove_test uri_builder_remove_tests[] = {
5558     {   "http://google.com/test?test=y#Frag",0,S_OK,FALSE,
5559         Uri_HAS_FRAGMENT|Uri_HAS_PATH|Uri_HAS_QUERY,S_OK,FALSE,
5560         "http://google.com/",0,S_OK,FALSE
5561     },
5562     {   "http://user:pass@winehq.org/",0,S_OK,FALSE,
5563         Uri_HAS_USER_NAME|Uri_HAS_PASSWORD,S_OK,FALSE,
5564         "http://winehq.org/",0,S_OK,FALSE
5565     },
5566     {   "zip://google.com?Test=x",0,S_OK,FALSE,
5567         Uri_HAS_HOST,S_OK,FALSE,
5568         "zip:/?Test=x",0,S_OK,FALSE
5569     },
5570     /* Doesn't remove the whole userinfo component. */
5571     {   "http://username:pass@google.com/",0,S_OK,FALSE,
5572         Uri_HAS_USER_INFO,S_OK,FALSE,
5573         "http://username:pass@google.com/",0,S_OK,FALSE
5574     },
5575     /* Doesn't remove the domain. */
5576     {   "http://google.com/",0,S_OK,FALSE,
5577         Uri_HAS_DOMAIN,S_OK,FALSE,
5578         "http://google.com/",0,S_OK,FALSE
5579     },
5580     {   "http://google.com:120/",0,S_OK,FALSE,
5581         Uri_HAS_AUTHORITY,S_OK,FALSE,
5582         "http://google.com:120/",0,S_OK,FALSE
5583     },
5584     {   "http://google.com/test.com/",0,S_OK,FALSE,
5585         Uri_HAS_EXTENSION,S_OK,FALSE,
5586         "http://google.com/test.com/",0,S_OK,FALSE
5587     },
5588     {   "http://google.com/?test=x",0,S_OK,FALSE,
5589         Uri_HAS_PATH_AND_QUERY,S_OK,FALSE,
5590         "http://google.com/?test=x",0,S_OK,FALSE
5591     },
5592     /* Can't remove the scheme name. */
5593     {   "http://google.com/?test=x",0,S_OK,FALSE,
5594         Uri_HAS_SCHEME_NAME|Uri_HAS_QUERY,E_INVALIDARG,FALSE,
5595         "http://google.com/?test=x",0,S_OK,FALSE
5596     }
5597 };
5598
5599 typedef struct _uri_combine_test {
5600     const char  *base_uri;
5601     DWORD       base_create_flags;
5602     const char  *relative_uri;
5603     DWORD       relative_create_flags;
5604     DWORD       combine_flags;
5605     HRESULT     expected;
5606     BOOL        todo;
5607
5608     uri_str_property    str_props[URI_STR_PROPERTY_COUNT];
5609     uri_dword_property  dword_props[URI_DWORD_PROPERTY_COUNT];
5610 } uri_combine_test;
5611
5612 static const uri_combine_test uri_combine_tests[] = {
5613     {   "http://google.com/fun/stuff",0,
5614         "../not/fun/stuff",Uri_CREATE_ALLOW_RELATIVE,
5615         0,S_OK,TRUE,
5616         {
5617             {"http://google.com/not/fun/stuff",S_OK},
5618             {"google.com",S_OK},
5619             {"http://google.com/not/fun/stuff",S_OK},
5620             {"google.com",S_OK},
5621             {"",S_FALSE},
5622             {"",S_FALSE},
5623             {"google.com",S_OK},
5624             {"",S_FALSE},
5625             {"/not/fun/stuff",S_OK},
5626             {"/not/fun/stuff",S_OK},
5627             {"",S_FALSE},
5628             {"http://google.com/not/fun/stuff",S_OK},
5629             {"http",S_OK},
5630             {"",S_FALSE},
5631             {"",S_FALSE}
5632         },
5633         {
5634             {Uri_HOST_DNS,S_OK},
5635             {80,S_OK},
5636             {URL_SCHEME_HTTP,S_OK},
5637             {URLZONE_INVALID,E_NOTIMPL}
5638         }
5639     },
5640     {   "http://google.com/test",0,
5641         "zip://test.com/cool",0,
5642         0,S_OK,FALSE,
5643         {
5644             {"zip://test.com/cool",S_OK},
5645             {"test.com",S_OK},
5646             {"zip://test.com/cool",S_OK},
5647             {"test.com",S_OK},
5648             {"",S_FALSE},
5649             {"",S_FALSE},
5650             {"test.com",S_OK},
5651             {"",S_FALSE},
5652             {"/cool",S_OK},
5653             {"/cool",S_OK},
5654             {"",S_FALSE},
5655             {"zip://test.com/cool",S_OK},
5656             {"zip",S_OK},
5657             {"",S_FALSE},
5658             {"",S_FALSE}
5659         },
5660         {
5661             {Uri_HOST_DNS,S_OK},
5662             {0,S_FALSE},
5663             {URL_SCHEME_UNKNOWN,S_OK},
5664             {URLZONE_INVALID,E_NOTIMPL}
5665         }
5666     },
5667     {   "http://google.com/use/base/path",0,
5668         "?relative",Uri_CREATE_ALLOW_RELATIVE,
5669         0,S_OK,FALSE,
5670         {
5671             {"http://google.com/use/base/path?relative",S_OK},
5672             {"google.com",S_OK},
5673             {"http://google.com/use/base/path?relative",S_OK},
5674             {"google.com",S_OK},
5675             {"",S_FALSE},
5676             {"",S_FALSE},
5677             {"google.com",S_OK},
5678             {"",S_FALSE},
5679             {"/use/base/path",S_OK},
5680             {"/use/base/path?relative",S_OK},
5681             {"?relative",S_OK},
5682             {"http://google.com/use/base/path?relative",S_OK},
5683             {"http",S_OK},
5684             {"",S_FALSE},
5685             {"",S_FALSE}
5686         },
5687         {
5688             {Uri_HOST_DNS,S_OK},
5689             {80,S_OK},
5690             {URL_SCHEME_HTTP,S_OK},
5691             {URLZONE_INVALID,E_NOTIMPL}
5692         }
5693     },
5694     {   "http://google.com/path",0,
5695         "/test/../test/.././testing",Uri_CREATE_ALLOW_RELATIVE,
5696         0,S_OK,TRUE,
5697         {
5698             {"http://google.com/testing",S_OK},
5699             {"google.com",S_OK},
5700             {"http://google.com/testing",S_OK},
5701             {"google.com",S_OK},
5702             {"",S_FALSE},
5703             {"",S_FALSE},
5704             {"google.com",S_OK},
5705             {"",S_FALSE},
5706             {"/testing",S_OK},
5707             {"/testing",S_OK},
5708             {"",S_FALSE},
5709             {"http://google.com/testing",S_OK},
5710             {"http",S_OK},
5711             {"",S_FALSE},
5712             {"",S_FALSE}
5713         },
5714         {
5715             {Uri_HOST_DNS,S_OK},
5716             {80,S_OK},
5717             {URL_SCHEME_HTTP,S_OK},
5718             {URLZONE_INVALID,E_NOTIMPL}
5719         }
5720     },
5721     {   "http://google.com/path",0,
5722         "/test/../test/.././testing",Uri_CREATE_ALLOW_RELATIVE,
5723         URL_DONT_SIMPLIFY,S_OK,TRUE,
5724         {
5725             {"http://google.com:80/test/../test/.././testing",S_OK},
5726             {"google.com",S_OK},
5727             {"http://google.com:80/test/../test/.././testing",S_OK},
5728             {"google.com",S_OK},
5729             {"",S_FALSE},
5730             {"",S_FALSE},
5731             {"google.com",S_OK},
5732             {"",S_FALSE},
5733             {"/test/../test/.././testing",S_OK},
5734             {"/test/../test/.././testing",S_OK},
5735             {"",S_FALSE},
5736             {"http://google.com:80/test/../test/.././testing",S_OK},
5737             {"http",S_OK},
5738             {"",S_FALSE},
5739             {"",S_FALSE}
5740         },
5741         {
5742             {Uri_HOST_DNS,S_OK},
5743             {80,S_OK},
5744             {URL_SCHEME_HTTP,S_OK},
5745             {URLZONE_INVALID,E_NOTIMPL}
5746         }
5747     },
5748     {   "http://winehq.org/test/abc",0,
5749         "testing/abc/../test",Uri_CREATE_ALLOW_RELATIVE,
5750         0,S_OK,TRUE,
5751         {
5752             {"http://winehq.org/test/testing/test",S_OK},
5753             {"winehq.org",S_OK},
5754             {"http://winehq.org/test/testing/test",S_OK},
5755             {"winehq.org",S_OK},
5756             {"",S_FALSE},
5757             {"",S_FALSE},
5758             {"winehq.org",S_OK},
5759             {"",S_FALSE},
5760             {"/test/testing/test",S_OK},
5761             {"/test/testing/test",S_OK},
5762             {"",S_FALSE},
5763             {"http://winehq.org/test/testing/test",S_OK},
5764             {"http",S_OK},
5765             {"",S_FALSE},
5766             {"",S_FALSE}
5767         },
5768         {
5769             {Uri_HOST_DNS,S_OK},
5770             {80,S_OK},
5771             {URL_SCHEME_HTTP,S_OK},
5772             {URLZONE_INVALID,E_NOTIMPL}
5773         }
5774     },
5775     {   "http://winehq.org/test/abc",0,
5776         "testing/abc/../test",Uri_CREATE_ALLOW_RELATIVE,
5777         URL_DONT_SIMPLIFY,S_OK,TRUE,
5778         {
5779             {"http://winehq.org:80/test/testing/abc/../test",S_OK},
5780             /* Default port is hidden in the authority. */
5781             {"winehq.org",S_OK},
5782             {"http://winehq.org:80/test/testing/abc/../test",S_OK},
5783             {"winehq.org",S_OK},
5784             {"",S_FALSE},
5785             {"",S_FALSE},
5786             {"winehq.org",S_OK},
5787             {"",S_FALSE},
5788             {"/test/testing/abc/../test",S_OK},
5789             {"/test/testing/abc/../test",S_OK},
5790             {"",S_FALSE},
5791             {"http://winehq.org:80/test/testing/abc/../test",S_OK},
5792             {"http",S_OK},
5793             {"",S_FALSE},
5794             {"",S_FALSE}
5795         },
5796         {
5797             {Uri_HOST_DNS,S_OK},
5798             {80,S_OK},
5799             {URL_SCHEME_HTTP,S_OK},
5800             {URLZONE_INVALID,E_NOTIMPL}
5801         }
5802     },
5803     {   "http://winehq.org/test?query",0,
5804         "testing",Uri_CREATE_ALLOW_RELATIVE,
5805         0,S_OK,TRUE,
5806         {
5807             {"http://winehq.org/testing",S_OK},
5808             {"winehq.org",S_OK},
5809             {"http://winehq.org/testing",S_OK},
5810             {"winehq.org",S_OK},
5811             {"",S_FALSE},
5812             {"",S_FALSE},
5813             {"winehq.org",S_OK},
5814             {"",S_FALSE},
5815             {"/testing",S_OK},
5816             {"/testing",S_OK},
5817             {"",S_FALSE},
5818             {"http://winehq.org/testing",S_OK},
5819             {"http",S_OK},
5820             {"",S_FALSE},
5821             {"",S_FALSE}
5822         },
5823         {
5824             {Uri_HOST_DNS,S_OK},
5825             {80,S_OK},
5826             {URL_SCHEME_HTTP,S_OK},
5827             {URLZONE_INVALID,E_NOTIMPL}
5828         }
5829     },
5830     {   "http://winehq.org/test#frag",0,
5831         "testing",Uri_CREATE_ALLOW_RELATIVE,
5832         0,S_OK,TRUE,
5833         {
5834             {"http://winehq.org/testing",S_OK},
5835             {"winehq.org",S_OK},
5836             {"http://winehq.org/testing",S_OK},
5837             {"winehq.org",S_OK},
5838             {"",S_FALSE},
5839             {"",S_FALSE},
5840             {"winehq.org",S_OK},
5841             {"",S_FALSE},
5842             {"/testing",S_OK},
5843             {"/testing",S_OK},
5844             {"",S_FALSE},
5845             {"http://winehq.org/testing",S_OK},
5846             {"http",S_OK},
5847             {"",S_FALSE},
5848             {"",S_FALSE}
5849         },
5850         {
5851             {Uri_HOST_DNS,S_OK},
5852             {80,S_OK},
5853             {URL_SCHEME_HTTP,S_OK},
5854             {URLZONE_INVALID,E_NOTIMPL}
5855         }
5856     },
5857     {   "testing?query#frag",Uri_CREATE_ALLOW_RELATIVE,
5858         "test",Uri_CREATE_ALLOW_RELATIVE,
5859         0,S_OK,TRUE,
5860         {
5861             {"test",S_OK},
5862             {"",S_FALSE},
5863             {"test",S_OK},
5864             {"",S_FALSE},
5865             {"",S_FALSE},
5866             {"",S_FALSE},
5867             {"",S_FALSE},
5868             {"",S_FALSE},
5869             {"test",S_OK},
5870             {"test",S_OK},
5871             {"",S_FALSE},
5872             {"test",S_OK},
5873             {"",S_FALSE},
5874             {"",S_FALSE},
5875             {"",S_FALSE}
5876         },
5877         {
5878             {Uri_HOST_UNKNOWN,S_OK},
5879             {0,S_FALSE},
5880             {URL_SCHEME_UNKNOWN,S_OK},
5881             {URLZONE_INVALID,E_NOTIMPL}
5882         }
5883     },
5884     {   "file:///c:/test/test",0,
5885         "/testing.mp3",Uri_CREATE_ALLOW_RELATIVE,
5886         URL_FILE_USE_PATHURL,S_OK,TRUE,
5887         {
5888             {"file://c:\\testing.mp3",S_OK},
5889             {"",S_FALSE},
5890             {"file://c:\\testing.mp3",S_OK},
5891             {"",S_FALSE},
5892             {".mp3",S_OK},
5893             {"",S_FALSE},
5894             {"",S_FALSE},
5895             {"",S_FALSE},
5896             {"c:\\testing.mp3",S_OK},
5897             {"c:\\testing.mp3",S_OK},
5898             {"",S_FALSE},
5899             {"file://c:\\testing.mp3",S_OK},
5900             {"file",S_OK},
5901             {"",S_FALSE},
5902             {"",S_FALSE}
5903         },
5904         {
5905             {Uri_HOST_UNKNOWN,S_OK},
5906             {0,S_FALSE},
5907             {URL_SCHEME_FILE,S_OK},
5908             {URLZONE_INVALID,E_NOTIMPL}
5909         }
5910     },
5911     {   "file:///c:/test/test",0,
5912         "/testing.mp3",Uri_CREATE_ALLOW_RELATIVE,
5913         0,S_OK,TRUE,
5914         {
5915             {"file:///c:/testing.mp3",S_OK},
5916             {"",S_FALSE},
5917             {"file:///c:/testing.mp3",S_OK},
5918             {"",S_FALSE},
5919             {".mp3",S_OK},
5920             {"",S_FALSE},
5921             {"",S_FALSE},
5922             {"",S_FALSE},
5923             {"/c:/testing.mp3",S_OK},
5924             {"/c:/testing.mp3",S_OK},
5925             {"",S_FALSE},
5926             {"file:///c:/testing.mp3",S_OK},
5927             {"file",S_OK},
5928             {"",S_FALSE},
5929             {"",S_FALSE}
5930         },
5931         {
5932             {Uri_HOST_UNKNOWN,S_OK},
5933             {0,S_FALSE},
5934             {URL_SCHEME_FILE,S_OK},
5935             {URLZONE_INVALID,E_NOTIMPL}
5936         }
5937     },
5938     {   "file://test.com/test/test",0,
5939         "/testing.mp3",Uri_CREATE_ALLOW_RELATIVE,
5940         URL_FILE_USE_PATHURL,S_OK,TRUE,
5941         {
5942             {"file://\\\\test.com\\testing.mp3",S_OK},
5943             {"test.com",S_OK},
5944             {"file://\\\\test.com\\testing.mp3",S_OK},
5945             {"test.com",S_OK},
5946             {".mp3",S_OK},
5947             {"",S_FALSE},
5948             {"test.com",S_OK},
5949             {"",S_FALSE},
5950             {"\\testing.mp3",S_OK},
5951             {"\\testing.mp3",S_OK},
5952             {"",S_FALSE},
5953             {"file://\\\\test.com\\testing.mp3",S_OK},
5954             {"file",S_OK},
5955             {"",S_FALSE},
5956             {"",S_FALSE}
5957         },
5958         {
5959             {Uri_HOST_DNS,S_OK},
5960             {0,S_FALSE},
5961             {URL_SCHEME_FILE,S_OK},
5962             {URLZONE_INVALID,E_NOTIMPL}
5963         }
5964     },
5965     /* URL_DONT_SIMPLIFY has no effect. */
5966     {   "http://google.com/test",0,
5967         "zip://test.com/cool/../cool/test",0,
5968         URL_DONT_SIMPLIFY,S_OK,FALSE,
5969         {
5970             {"zip://test.com/cool/test",S_OK},
5971             {"test.com",S_OK},
5972             {"zip://test.com/cool/test",S_OK},
5973             {"test.com",S_OK},
5974             {"",S_FALSE},
5975             {"",S_FALSE},
5976             {"test.com",S_OK},
5977             {"",S_FALSE},
5978             {"/cool/test",S_OK},
5979             {"/cool/test",S_OK},
5980             {"",S_FALSE},
5981             /* The resulting IUri has the same Raw URI as the relative URI (only IE 8).
5982              * On IE 7 it reduces the path in the Raw URI.
5983              */
5984             {"zip://test.com/cool/../cool/test",S_OK,FALSE,"zip://test.com/cool/test"},
5985             {"zip",S_OK},
5986             {"",S_FALSE},
5987             {"",S_FALSE}
5988         },
5989         {
5990             {Uri_HOST_DNS,S_OK},
5991             {0,S_FALSE},
5992             {URL_SCHEME_UNKNOWN,S_OK},
5993             {URLZONE_INVALID,E_NOTIMPL}
5994         }
5995     },
5996     /* FILE_USE_PATHURL has no effect in IE 8, in IE 7 the
5997      * resulting URI is converted into a dos path.
5998      */
5999     {   "http://google.com/test",0,
6000         "file:///c:/test/",0,
6001         URL_FILE_USE_PATHURL,S_OK,FALSE,
6002         {
6003             {"file:///c:/test/",S_OK,FALSE,"file://c:\\test\\"},
6004             {"",S_FALSE},
6005             {"file:///c:/test/",S_OK,FALSE,"file://c:\\test\\"},
6006             {"",S_FALSE},
6007             {"",S_FALSE},
6008             {"",S_FALSE},
6009             {"",S_FALSE},
6010             {"",S_FALSE},
6011             {"/c:/test/",S_OK,FALSE,"c:\\test\\"},
6012             {"/c:/test/",S_OK,FALSE,"c:\\test\\"},
6013             {"",S_FALSE},
6014             {"file:///c:/test/",S_OK,FALSE,"file://c:\\test\\"},
6015             {"file",S_OK},
6016             {"",S_FALSE},
6017             {"",S_FALSE}
6018         },
6019         {
6020             {Uri_HOST_UNKNOWN,S_OK},
6021             {0,S_FALSE},
6022             {URL_SCHEME_FILE,S_OK},
6023             {URLZONE_INVALID,E_NOTIMPL}
6024         }
6025     },
6026     {   "http://google.com/test",0,
6027         "http://test.com/test#%30test",0,
6028         URL_DONT_UNESCAPE_EXTRA_INFO,S_OK,FALSE,
6029         {
6030             {"http://test.com/test#0test",S_OK},
6031             {"test.com",S_OK},
6032             {"http://test.com/test#0test",S_OK},
6033             {"test.com",S_OK},
6034             {"",S_FALSE},
6035             {"#0test",S_OK},
6036             {"test.com",S_OK},
6037             {"",S_FALSE},
6038             {"/test",S_OK},
6039             {"/test",S_OK},
6040             {"",S_FALSE},
6041             /* IE 7 decodes the %30 to a 0 in the Raw URI. */
6042             {"http://test.com/test#%30test",S_OK,FALSE,"http://test.com/test#0test"},
6043             {"http",S_OK},
6044             {"",S_FALSE},
6045             {"",S_FALSE}
6046         },
6047         {
6048             {Uri_HOST_DNS,S_OK},
6049             {80,S_OK},
6050             {URL_SCHEME_HTTP,S_OK},
6051             {URLZONE_INVALID,E_NOTIMPL}
6052         }
6053     },
6054     /* Windows validates the path component from the relative Uri. */
6055     {   "http://google.com/test",0,
6056         "/Te%XXst",Uri_CREATE_ALLOW_RELATIVE,
6057         0,E_INVALIDARG,TRUE
6058     },
6059     /* Windows doesn't validate the query from the relative Uri. */
6060     {   "http://google.com/test",0,
6061         "?Tes%XXt",Uri_CREATE_ALLOW_RELATIVE,
6062         0,S_OK,FALSE,
6063         {
6064             {"http://google.com/test?Tes%XXt",S_OK},
6065             {"google.com",S_OK},
6066             {"http://google.com/test?Tes%XXt",S_OK},
6067             {"google.com",S_OK},
6068             {"",S_FALSE},
6069             {"",S_FALSE},
6070             {"google.com",S_OK},
6071             {"",S_FALSE},
6072             {"/test",S_OK},
6073             {"/test?Tes%XXt",S_OK},
6074             {"?Tes%XXt",S_OK},
6075             {"http://google.com/test?Tes%XXt",S_OK},
6076             {"http",S_OK},
6077             {"",S_FALSE},
6078             {"",S_FALSE}
6079         },
6080         {
6081             {Uri_HOST_DNS,S_OK},
6082             {80,S_OK},
6083             {URL_SCHEME_HTTP,S_OK},
6084             {URLZONE_INVALID,E_NOTIMPL}
6085         }
6086     },
6087     /* Windows doesn't validate the fragment from the relative Uri. */
6088     {   "http://google.com/test",0,
6089         "#Tes%XXt",Uri_CREATE_ALLOW_RELATIVE,
6090         0,S_OK,FALSE,
6091         {
6092             {"http://google.com/test#Tes%XXt",S_OK},
6093             {"google.com",S_OK},
6094             {"http://google.com/test#Tes%XXt",S_OK},
6095             {"google.com",S_OK},
6096             {"",S_FALSE},
6097             {"#Tes%XXt",S_OK},
6098             {"google.com",S_OK},
6099             {"",S_FALSE},
6100             {"/test",S_OK},
6101             {"/test",S_OK},
6102             {"",S_FALSE},
6103             {"http://google.com/test#Tes%XXt",S_OK},
6104             {"http",S_OK},
6105             {"",S_FALSE},
6106             {"",S_FALSE}
6107         },
6108         {
6109             {Uri_HOST_DNS,S_OK},
6110             {80,S_OK},
6111             {URL_SCHEME_HTTP,S_OK},
6112             {URLZONE_INVALID,E_NOTIMPL}
6113         }
6114     },
6115     /* Creates an IUri which contains an invalid dos path char. */
6116     {   "file:///c:/test",0,
6117         "/test<ing",Uri_CREATE_ALLOW_RELATIVE,
6118         URL_FILE_USE_PATHURL,S_OK,TRUE,
6119         {
6120             {"file://c:\\test<ing",S_OK},
6121             {"",S_FALSE},
6122             {"file://c:\\test<ing",S_OK},
6123             {"",S_FALSE},
6124             {"",S_FALSE},
6125             {"",S_FALSE},
6126             {"",S_FALSE},
6127             {"",S_FALSE},
6128             {"c:\\test<ing",S_OK},
6129             {"c:\\test<ing",S_OK},
6130             {"",S_FALSE},
6131             {"file://c:\\test<ing",S_OK},
6132             {"file",S_OK},
6133             {"",S_FALSE},
6134             {"",S_FALSE}
6135         },
6136         {
6137             {Uri_HOST_UNKNOWN,S_OK},
6138             {0,S_FALSE},
6139             {URL_SCHEME_FILE,S_OK},
6140             {URLZONE_INVALID,E_NOTIMPL}
6141         }
6142     },
6143     /* Appends the path after the drive letter (if any). */
6144     {   "file:///c:/test",0,
6145         "/c:/testing",Uri_CREATE_ALLOW_RELATIVE,
6146         0,S_OK,TRUE,
6147         {
6148             {"file:///c:/c:/testing",S_OK},
6149             {"",S_FALSE},
6150             {"file:///c:/c:/testing",S_OK},
6151             {"",S_FALSE},
6152             {"",S_FALSE},
6153             {"",S_FALSE},
6154             {"",S_FALSE},
6155             {"",S_FALSE},
6156             {"/c:/c:/testing",S_OK},
6157             {"/c:/c:/testing",S_OK},
6158             {"",S_FALSE},
6159             {"file:///c:/c:/testing",S_OK},
6160             {"file",S_OK},
6161             {"",S_FALSE},
6162             {"",S_FALSE}
6163         },
6164         {
6165             {Uri_HOST_UNKNOWN,S_OK},
6166             {0,S_FALSE},
6167             {URL_SCHEME_FILE,S_OK},
6168             {URLZONE_INVALID,E_NOTIMPL}
6169         }
6170     },
6171     /* A '/' is added if the base URI doesn't have a path and the
6172      * relative URI doesn't contain a path (since the base URI is
6173      * hierarchical.
6174      */
6175     {   "http://google.com",Uri_CREATE_NO_CANONICALIZE,
6176         "?test",Uri_CREATE_ALLOW_RELATIVE,
6177         0,S_OK,FALSE,
6178         {
6179             {"http://google.com/?test",S_OK},
6180             {"google.com",S_OK},
6181             {"http://google.com/?test",S_OK},
6182             {"google.com",S_OK},
6183             {"",S_FALSE},
6184             {"",S_FALSE},
6185             {"google.com",S_OK},
6186             {"",S_FALSE},
6187             {"/",S_OK},
6188             {"/?test",S_OK},
6189             {"?test",S_OK},
6190             {"http://google.com/?test",S_OK},
6191             {"http",S_OK},
6192             {"",S_FALSE},
6193             {"",S_FALSE}
6194         },
6195         {
6196             {Uri_HOST_DNS,S_OK},
6197             {80,S_OK},
6198             {URL_SCHEME_HTTP,S_OK},
6199             {URLZONE_INVALID,E_NOTIMPL}
6200         }
6201     },
6202     {   "zip://google.com",Uri_CREATE_NO_CANONICALIZE,
6203         "?test",Uri_CREATE_ALLOW_RELATIVE,
6204         0,S_OK,FALSE,
6205         {
6206             {"zip://google.com/?test",S_OK},
6207             {"google.com",S_OK},
6208             {"zip://google.com/?test",S_OK},
6209             {"google.com",S_OK},
6210             {"",S_FALSE},
6211             {"",S_FALSE},
6212             {"google.com",S_OK},
6213             {"",S_FALSE},
6214             {"/",S_OK},
6215             {"/?test",S_OK},
6216             {"?test",S_OK},
6217             {"zip://google.com/?test",S_OK},
6218             {"zip",S_OK},
6219             {"",S_FALSE},
6220             {"",S_FALSE}
6221         },
6222         {
6223             {Uri_HOST_DNS,S_OK},
6224             {0,S_FALSE},
6225             {URL_SCHEME_UNKNOWN,S_OK},
6226             {URLZONE_INVALID,E_NOTIMPL}
6227         }
6228     },
6229     /* No path is appended since the base URI is opaque. */
6230     {   "zip:?testing",0,
6231         "?test",Uri_CREATE_ALLOW_RELATIVE,
6232         0,S_OK,FALSE,
6233         {
6234             {"zip:?test",S_OK},
6235             {"",S_FALSE},
6236             {"zip:?test",S_OK},
6237             {"",S_FALSE},
6238             {"",S_FALSE},
6239             {"",S_FALSE},
6240             {"",S_FALSE},
6241             {"",S_FALSE},
6242             {"",S_OK},
6243             {"?test",S_OK},
6244             {"?test",S_OK},
6245             {"zip:?test",S_OK},
6246             {"zip",S_OK},
6247             {"",S_FALSE},
6248             {"",S_FALSE}
6249         },
6250         {
6251             {Uri_HOST_UNKNOWN,S_OK},
6252             {0,S_FALSE},
6253             {URL_SCHEME_UNKNOWN,S_OK},
6254             {URLZONE_INVALID,E_NOTIMPL}
6255         }
6256     }
6257 };
6258
6259 static inline LPWSTR a2w(LPCSTR str) {
6260     LPWSTR ret = NULL;
6261
6262     if(str) {
6263         DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
6264         ret = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
6265         MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len);
6266     }
6267
6268     return ret;
6269 }
6270
6271 static inline BOOL heap_free(void* mem) {
6272     return HeapFree(GetProcessHeap(), 0, mem);
6273 }
6274
6275 static inline DWORD strcmp_aw(LPCSTR strA, LPCWSTR strB) {
6276     LPWSTR strAW = a2w(strA);
6277     DWORD ret = lstrcmpW(strAW, strB);
6278     heap_free(strAW);
6279     return ret;
6280 }
6281
6282 static inline ULONG get_refcnt(IUri *uri) {
6283     IUri_AddRef(uri);
6284     return IUri_Release(uri);
6285 }
6286
6287 static void change_property(IUriBuilder *builder, const uri_builder_property *prop,
6288                             DWORD test_index) {
6289     HRESULT hr;
6290     LPWSTR valueW;
6291
6292     valueW = a2w(prop->value);
6293     switch(prop->property) {
6294     case Uri_PROPERTY_FRAGMENT:
6295         hr = IUriBuilder_SetFragment(builder, valueW);
6296         if(prop->todo) {
6297             todo_wine {
6298                 ok(hr == prop->expected,
6299                     "Error: IUriBuilder_SetFragment returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6300                     hr, prop->expected, test_index);
6301             }
6302         } else {
6303             ok(hr == prop->expected,
6304                 "Error: IUriBuilder_SetFragment returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6305                 hr, prop->expected, test_index);
6306         }
6307         break;
6308     case Uri_PROPERTY_HOST:
6309         hr = IUriBuilder_SetHost(builder, valueW);
6310         if(prop->todo) {
6311             todo_wine {
6312                 ok(hr == prop->expected,
6313                     "Error: IUriBuilder_SetHost returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6314                     hr, prop->expected, test_index);
6315             }
6316         } else {
6317             ok(hr == prop->expected,
6318                 "Error: IUriBuilder_SetHost returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6319                 hr, prop->expected, test_index);
6320         }
6321         break;
6322     case Uri_PROPERTY_PASSWORD:
6323         hr = IUriBuilder_SetPassword(builder, valueW);
6324         if(prop->todo) {
6325             todo_wine {
6326                 ok(hr == prop->expected,
6327                     "Error: IUriBuilder_SetPassword returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6328                     hr, prop->expected, test_index);
6329             }
6330         } else {
6331             ok(hr == prop->expected,
6332                 "Error: IUriBuilder_SetPassword returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6333                 hr, prop->expected, test_index);
6334         }
6335         break;
6336     case Uri_PROPERTY_PATH:
6337         hr = IUriBuilder_SetPath(builder, valueW);
6338         if(prop->todo) {
6339             todo_wine {
6340                 ok(hr == prop->expected,
6341                     "Error: IUriBuilder_SetPath returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6342                     hr, prop->expected, test_index);
6343             }
6344         } else {
6345             ok(hr == prop->expected,
6346                 "Error: IUriBuilder_SetPath returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6347                 hr, prop->expected, test_index);
6348         }
6349         break;
6350     case Uri_PROPERTY_QUERY:
6351         hr = IUriBuilder_SetQuery(builder, valueW);
6352         if(prop->todo) {
6353             todo_wine {
6354                 ok(hr == prop->expected,
6355                     "Error: IUriBuilder_SetQuery returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6356                     hr, prop->expected, test_index);
6357             }
6358         } else {
6359             ok(hr == prop->expected,
6360                 "Error: IUriBuilder_SetQuery returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6361                 hr, prop->expected, test_index);
6362         }
6363         break;
6364     case Uri_PROPERTY_SCHEME_NAME:
6365         hr = IUriBuilder_SetSchemeName(builder, valueW);
6366         if(prop->todo) {
6367             todo_wine {
6368                 ok(hr == prop->expected,
6369                     "Error: IUriBuilder_SetSchemeName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6370                     hr, prop->expected, test_index);
6371             }
6372         } else {
6373             ok(hr == prop->expected,
6374                 "Error: IUriBuilder_SetSchemeName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6375                 hr, prop->expected, test_index);
6376         }
6377         break;
6378     case Uri_PROPERTY_USER_NAME:
6379         hr = IUriBuilder_SetUserName(builder, valueW);
6380         if(prop->todo) {
6381             todo_wine {
6382                 ok(hr == prop->expected,
6383                     "Error: IUriBuilder_SetUserName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6384                     hr, prop->expected, test_index);
6385             }
6386         } else {
6387             ok(hr == prop->expected,
6388                 "Error: IUriBuilder_SetUserName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6389                 hr, prop->expected, test_index);
6390         }
6391         break;
6392     default:
6393         trace("Unsupported operation for %d on uri_builder_tests[%d].\n", prop->property, test_index);
6394     }
6395
6396     heap_free(valueW);
6397 }
6398
6399 /*
6400  * Simple tests to make sure the CreateUri function handles invalid flag combinations
6401  * correctly.
6402  */
6403 static void test_CreateUri_InvalidFlags(void) {
6404     DWORD i;
6405
6406     for(i = 0; i < sizeof(invalid_flag_tests)/sizeof(invalid_flag_tests[0]); ++i) {
6407         HRESULT hr;
6408         IUri *uri = (void*) 0xdeadbeef;
6409
6410         hr = pCreateUri(http_urlW, invalid_flag_tests[i].flags, 0, &uri);
6411         ok(hr == invalid_flag_tests[i].expected, "Error: CreateUri returned 0x%08x, expected 0x%08x, flags=0x%08x\n",
6412                 hr, invalid_flag_tests[i].expected, invalid_flag_tests[i].flags);
6413         ok(uri == NULL, "Error: expected the IUri to be NULL, but it was %p instead\n", uri);
6414     }
6415 }
6416
6417 static void test_CreateUri_InvalidArgs(void) {
6418     HRESULT hr;
6419     IUri *uri = (void*) 0xdeadbeef;
6420
6421     const WCHAR invalidW[] = {'i','n','v','a','l','i','d',0};
6422     static const WCHAR emptyW[] = {0};
6423
6424     hr = pCreateUri(http_urlW, 0, 0, NULL);
6425     ok(hr == E_INVALIDARG, "Error: CreateUri returned 0x%08x, expected 0x%08x\n", hr, E_INVALIDARG);
6426
6427     hr = pCreateUri(NULL, 0, 0, &uri);
6428     ok(hr == E_INVALIDARG, "Error: CreateUri returned 0x%08x, expected 0x%08x\n", hr, E_INVALIDARG);
6429     ok(uri == NULL, "Error: Expected the IUri to be NULL, but it was %p instead\n", uri);
6430
6431     uri = (void*) 0xdeadbeef;
6432     hr = pCreateUri(invalidW, 0, 0, &uri);
6433     ok(hr == E_INVALIDARG, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
6434     ok(uri == NULL, "Error: Expected the IUri to be NULL, but it was %p instead\n", uri);
6435
6436     uri = (void*) 0xdeadbeef;
6437     hr = pCreateUri(emptyW, 0, 0, &uri);
6438     ok(hr == E_INVALIDARG, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
6439     ok(uri == NULL, "Error: Expected the IUri to be NULL, but it was %p instead\n", uri);
6440 }
6441
6442 static void test_CreateUri_InvalidUri(void) {
6443     DWORD i;
6444
6445     for(i = 0; i < sizeof(invalid_uri_tests)/sizeof(invalid_uri_tests[0]); ++i) {
6446         invalid_uri test = invalid_uri_tests[i];
6447         IUri *uri = NULL;
6448         LPWSTR uriW;
6449         HRESULT hr;
6450
6451         uriW = a2w(test.uri);
6452         hr = pCreateUri(uriW, test.flags, 0, &uri);
6453         if(test.todo) {
6454             todo_wine {
6455                 ok(hr == E_INVALIDARG, "Error: CreateUri returned 0x%08x, expected 0x%08x on invalid_uri_tests[%d].\n",
6456                     hr, E_INVALIDARG, i);
6457             }
6458         } else {
6459             ok(hr == E_INVALIDARG, "Error: CreateUri returned 0x%08x, expected 0x%08x on invalid_uri_tests[%d].\n",
6460                 hr, E_INVALIDARG, i);
6461         }
6462         if(uri) IUri_Release(uri);
6463
6464         heap_free(uriW);
6465     }
6466 }
6467
6468 static void test_IUri_GetPropertyBSTR(void) {
6469     IUri *uri = NULL;
6470     HRESULT hr;
6471     DWORD i;
6472
6473     /* Make sure GetPropertyBSTR handles invalid args correctly. */
6474     hr = pCreateUri(http_urlW, 0, 0, &uri);
6475     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
6476     if(SUCCEEDED(hr)) {
6477         BSTR received = NULL;
6478
6479         hr = IUri_GetPropertyBSTR(uri, Uri_PROPERTY_RAW_URI, NULL, 0);
6480         ok(hr == E_POINTER, "Error: GetPropertyBSTR returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
6481
6482         /* Make sure it handles a invalid Uri_PROPERTY's correctly. */
6483         hr = IUri_GetPropertyBSTR(uri, Uri_PROPERTY_PORT, &received, 0);
6484         ok(hr == S_OK, "Error: GetPropertyBSTR returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
6485         ok(received != NULL, "Error: Expected the string not to be NULL.\n");
6486         ok(!SysStringLen(received), "Error: Expected the string to be of len=0 but it was %d instead.\n", SysStringLen(received));
6487         SysFreeString(received);
6488
6489         /* Make sure it handles the ZONE property correctly. */
6490         received = NULL;
6491         hr = IUri_GetPropertyBSTR(uri, Uri_PROPERTY_ZONE, &received, 0);
6492         ok(hr == S_FALSE, "Error: GetPropertyBSTR returned 0x%08x, expected 0x%08x.\n", hr, S_FALSE);
6493         ok(received != NULL, "Error: Expected the string not to be NULL.\n");
6494         ok(!SysStringLen(received), "Error: Expected the string to be of len=0 but it was %d instead.\n", SysStringLen(received));
6495         SysFreeString(received);
6496     }
6497     if(uri) IUri_Release(uri);
6498
6499     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
6500         uri_properties test = uri_tests[i];
6501         LPWSTR uriW;
6502         uri = NULL;
6503
6504         uriW = a2w(test.uri);
6505         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
6506         if(test.create_todo) {
6507             todo_wine {
6508                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x. Failed on uri_tests[%d].\n",
6509                         hr, test.create_expected, i);
6510             }
6511         } else {
6512             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x. Failed on uri_tests[%d].\n",
6513                     hr, test.create_expected, i);
6514         }
6515
6516         if(SUCCEEDED(hr)) {
6517             DWORD j;
6518
6519             /* Checks all the string properties of the uri. */
6520             for(j = Uri_PROPERTY_STRING_START; j <= Uri_PROPERTY_STRING_LAST; ++j) {
6521                 BSTR received = NULL;
6522                 uri_str_property prop = test.str_props[j];
6523
6524                 hr = IUri_GetPropertyBSTR(uri, j, &received, 0);
6525                 if(prop.todo) {
6526                     todo_wine {
6527                         ok(hr == prop.expected, "GetPropertyBSTR returned 0x%08x, expected 0x%08x. On uri_tests[%d].str_props[%d].\n",
6528                                 hr, prop.expected, i, j);
6529                     }
6530                     todo_wine {
6531                         ok(!strcmp_aw(prop.value, received) || broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
6532                                 "Expected %s but got %s on uri_tests[%d].str_props[%d].\n",
6533                                 prop.value, wine_dbgstr_w(received), i, j);
6534                     }
6535                 } else {
6536                     ok(hr == prop.expected, "GetPropertyBSTR returned 0x%08x, expected 0x%08x. On uri_tests[%d].str_props[%d].\n",
6537                             hr, prop.expected, i, j);
6538                     ok(!strcmp_aw(prop.value, received) || broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
6539                             "Expected %s but got %s on uri_tests[%d].str_props[%d].\n",
6540                             prop.value, wine_dbgstr_w(received), i, j);
6541                 }
6542
6543                 SysFreeString(received);
6544             }
6545         }
6546
6547         if(uri) IUri_Release(uri);
6548
6549         heap_free(uriW);
6550     }
6551 }
6552
6553 static void test_IUri_GetPropertyDWORD(void) {
6554     IUri *uri = NULL;
6555     HRESULT hr;
6556     DWORD i;
6557
6558     hr = pCreateUri(http_urlW, 0, 0, &uri);
6559     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
6560     if(SUCCEEDED(hr)) {
6561         DWORD received = 0xdeadbeef;
6562
6563         hr = IUri_GetPropertyDWORD(uri, Uri_PROPERTY_DWORD_START, NULL, 0);
6564         ok(hr == E_INVALIDARG, "Error: GetPropertyDWORD returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
6565
6566         hr = IUri_GetPropertyDWORD(uri, Uri_PROPERTY_ABSOLUTE_URI, &received, 0);
6567         ok(hr == E_INVALIDARG, "Error: GetPropertyDWORD returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
6568         ok(received == 0, "Error: Expected received=%d but instead received=%d.\n", 0, received);
6569     }
6570     if(uri) IUri_Release(uri);
6571
6572     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
6573         uri_properties test = uri_tests[i];
6574         LPWSTR uriW;
6575         uri = NULL;
6576
6577         uriW = a2w(test.uri);
6578         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
6579         if(test.create_todo) {
6580             todo_wine {
6581                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x. Failed on uri_tests[%d].\n",
6582                         hr, test.create_expected, i);
6583             }
6584         } else {
6585             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x. Failed on uri_tests[%d].\n",
6586                     hr, test.create_expected, i);
6587         }
6588
6589         if(SUCCEEDED(hr)) {
6590             DWORD j;
6591
6592             /* Checks all the DWORD properties of the uri. */
6593             for(j = 0; j < sizeof(test.dword_props)/sizeof(test.dword_props[0]); ++j) {
6594                 DWORD received;
6595                 uri_dword_property prop = test.dword_props[j];
6596
6597                 hr = IUri_GetPropertyDWORD(uri, j+Uri_PROPERTY_DWORD_START, &received, 0);
6598                 if(prop.todo) {
6599                     todo_wine {
6600                         ok(hr == prop.expected, "GetPropertyDWORD returned 0x%08x, expected 0x%08x. On uri_tests[%d].dword_props[%d].\n",
6601                                 hr, prop.expected, i, j);
6602                     }
6603                     todo_wine {
6604                         ok(prop.value == received, "Expected %d but got %d on uri_tests[%d].dword_props[%d].\n",
6605                                 prop.value, received, i, j);
6606                     }
6607                 } else {
6608                     ok(hr == prop.expected, "GetPropertyDWORD returned 0x%08x, expected 0x%08x. On uri_tests[%d].dword_props[%d].\n",
6609                             hr, prop.expected, i, j);
6610                     ok(prop.value == received, "Expected %d but got %d on uri_tests[%d].dword_props[%d].\n",
6611                             prop.value, received, i, j);
6612                 }
6613             }
6614         }
6615
6616         if(uri) IUri_Release(uri);
6617
6618         heap_free(uriW);
6619     }
6620 }
6621
6622 /* Tests all the 'Get*' property functions which deal with strings. */
6623 static void test_IUri_GetStrProperties(void) {
6624     IUri *uri = NULL;
6625     HRESULT hr;
6626     DWORD i;
6627
6628     /* Make sure all the 'Get*' string property functions handle invalid args correctly. */
6629     hr = pCreateUri(http_urlW, 0, 0, &uri);
6630     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
6631     if(SUCCEEDED(hr)) {
6632         hr = IUri_GetAbsoluteUri(uri, NULL);
6633         ok(hr == E_POINTER, "Error: GetAbsoluteUri returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
6634
6635         hr = IUri_GetAuthority(uri, NULL);
6636         ok(hr == E_POINTER, "Error: GetAuthority returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
6637
6638         hr = IUri_GetDisplayUri(uri, NULL);
6639         ok(hr == E_POINTER, "Error: GetDisplayUri returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
6640
6641         hr = IUri_GetDomain(uri, NULL);
6642         ok(hr == E_POINTER, "Error: GetDomain returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
6643
6644         hr = IUri_GetExtension(uri, NULL);
6645         ok(hr == E_POINTER, "Error: GetExtension returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
6646
6647         hr = IUri_GetFragment(uri, NULL);
6648         ok(hr == E_POINTER, "Error: GetFragment returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
6649
6650         hr = IUri_GetHost(uri, NULL);
6651         ok(hr == E_POINTER, "Error: GetHost returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
6652
6653         hr = IUri_GetPassword(uri, NULL);
6654         ok(hr == E_POINTER, "Error: GetPassword returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
6655
6656         hr = IUri_GetPath(uri, NULL);
6657         ok(hr == E_POINTER, "Error: GetPath returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
6658
6659         hr = IUri_GetPathAndQuery(uri, NULL);
6660         ok(hr == E_POINTER, "Error: GetPathAndQuery returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
6661
6662         hr = IUri_GetQuery(uri, NULL);
6663         ok(hr == E_POINTER, "Error: GetQuery returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
6664
6665         hr = IUri_GetRawUri(uri, NULL);
6666         ok(hr == E_POINTER, "Error: GetRawUri returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
6667
6668         hr = IUri_GetSchemeName(uri, NULL);
6669         ok(hr == E_POINTER, "Error: GetSchemeName returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
6670
6671         hr = IUri_GetUserInfo(uri, NULL);
6672         ok(hr == E_POINTER, "Error: GetUserInfo returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
6673
6674         hr = IUri_GetUserName(uri, NULL);
6675         ok(hr == E_POINTER, "Error: GetUserName returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
6676     }
6677     if(uri) IUri_Release(uri);
6678
6679     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
6680         uri_properties test = uri_tests[i];
6681         LPWSTR uriW;
6682         uri = NULL;
6683
6684         uriW = a2w(test.uri);
6685         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
6686         if(test.create_todo) {
6687             todo_wine {
6688                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6689                         hr, test.create_expected, i);
6690             }
6691         } else {
6692             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6693                     hr, test.create_expected, i);
6694         }
6695
6696         if(SUCCEEDED(hr)) {
6697             uri_str_property prop;
6698             BSTR received = NULL;
6699
6700             /* GetAbsoluteUri() tests. */
6701             prop = test.str_props[Uri_PROPERTY_ABSOLUTE_URI];
6702             hr = IUri_GetAbsoluteUri(uri, &received);
6703             if(prop.todo) {
6704                 todo_wine {
6705                     ok(hr == prop.expected, "Error: GetAbsoluteUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6706                             hr, prop.expected, i);
6707                 }
6708                 todo_wine {
6709                     ok(!strcmp_aw(prop.value, received) || broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
6710                             "Error: Expected %s but got %s on uri_tests[%d].\n",
6711                             prop.value, wine_dbgstr_w(received), i);
6712                 }
6713             } else {
6714                 ok(hr == prop.expected, "Error: GetAbsoluteUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6715                         hr, prop.expected, i);
6716                 ok(!strcmp_aw(prop.value, received) || broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
6717                         "Error: Expected %s but got %s on uri_tests[%d].\n",
6718                         prop.value, wine_dbgstr_w(received), i);
6719             }
6720             SysFreeString(received);
6721             received = NULL;
6722
6723             /* GetAuthority() tests. */
6724             prop = test.str_props[Uri_PROPERTY_AUTHORITY];
6725             hr = IUri_GetAuthority(uri, &received);
6726             if(prop.todo) {
6727                 todo_wine {
6728                     ok(hr == prop.expected, "Error: GetAuthority returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6729                             hr, prop.expected, i);
6730                 }
6731                 todo_wine {
6732                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6733                             prop.value, wine_dbgstr_w(received), i);
6734                 }
6735             } else {
6736                 ok(hr == prop.expected, "Error: GetAuthority returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6737                         hr, prop.expected, i);
6738                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6739                         prop.value, wine_dbgstr_w(received), i);
6740             }
6741             SysFreeString(received);
6742             received = NULL;
6743
6744             /* GetDisplayUri() tests. */
6745             prop = test.str_props[Uri_PROPERTY_DISPLAY_URI];
6746             hr = IUri_GetDisplayUri(uri, &received);
6747             if(prop.todo) {
6748                 todo_wine {
6749                     ok(hr == prop.expected, "Error: GetDisplayUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6750                             hr, prop.expected, i);
6751                 }
6752                 todo_wine {
6753                     ok(!strcmp_aw(prop.value, received) || broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
6754                             "Error: Expected %s but got %s on uri_test[%d].\n",
6755                             prop.value, wine_dbgstr_w(received), i);
6756                 }
6757             } else {
6758                 ok(hr == prop.expected, "Error: GetDisplayUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6759                         hr, prop.expected, i);
6760                 ok(!strcmp_aw(prop.value, received) || broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
6761                         "Error: Expected %s but got %s on uri_tests[%d].\n",
6762                         prop.value, wine_dbgstr_w(received), i);
6763             }
6764             SysFreeString(received);
6765             received = NULL;
6766
6767             /* GetDomain() tests. */
6768             prop = test.str_props[Uri_PROPERTY_DOMAIN];
6769             hr = IUri_GetDomain(uri, &received);
6770             if(prop.todo) {
6771                 todo_wine {
6772                     ok(hr == prop.expected, "Error: GetDomain returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6773                             hr, prop.expected, i);
6774                 }
6775                 todo_wine {
6776                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6777                             prop.value, wine_dbgstr_w(received), i);
6778                 }
6779             } else {
6780                 ok(hr == prop.expected, "Error: GetDomain returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6781                         hr, prop.expected, i);
6782                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6783                         prop.value, wine_dbgstr_w(received), i);
6784             }
6785             SysFreeString(received);
6786             received = NULL;
6787
6788             /* GetExtension() tests. */
6789             prop = test.str_props[Uri_PROPERTY_EXTENSION];
6790             hr = IUri_GetExtension(uri, &received);
6791             if(prop.todo) {
6792                 todo_wine {
6793                     ok(hr == prop.expected, "Error: GetExtension returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6794                             hr, prop.expected, i);
6795                 }
6796                 todo_wine {
6797                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6798                             prop.value, wine_dbgstr_w(received), i);
6799                 }
6800             } else {
6801                 ok(hr == prop.expected, "Error: GetExtension returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6802                         hr, prop.expected, i);
6803                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6804                         prop.value, wine_dbgstr_w(received), i);
6805             }
6806             SysFreeString(received);
6807             received = NULL;
6808
6809             /* GetFragment() tests. */
6810             prop = test.str_props[Uri_PROPERTY_FRAGMENT];
6811             hr = IUri_GetFragment(uri, &received);
6812             if(prop.todo) {
6813                 todo_wine {
6814                     ok(hr == prop.expected, "Error: GetFragment returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6815                             hr, prop.expected, i);
6816                 }
6817                 todo_wine {
6818                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6819                             prop.value, wine_dbgstr_w(received), i);
6820                 }
6821             } else {
6822                 ok(hr == prop.expected, "Error: GetFragment returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6823                         hr, prop.expected, i);
6824                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6825                         prop.value, wine_dbgstr_w(received), i);
6826             }
6827             SysFreeString(received);
6828             received = NULL;
6829
6830             /* GetHost() tests. */
6831             prop = test.str_props[Uri_PROPERTY_HOST];
6832             hr = IUri_GetHost(uri, &received);
6833             if(prop.todo) {
6834                 todo_wine {
6835                     ok(hr == prop.expected, "Error: GetHost returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6836                             hr, prop.expected, i);
6837                 }
6838                 todo_wine {
6839                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6840                             prop.value, wine_dbgstr_w(received), i);
6841                 }
6842             } else {
6843                 ok(hr == prop.expected, "Error: GetHost returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6844                         hr, prop.expected, i);
6845                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6846                         prop.value, wine_dbgstr_w(received), i);
6847             }
6848             SysFreeString(received);
6849             received = NULL;
6850
6851             /* GetPassword() tests. */
6852             prop = test.str_props[Uri_PROPERTY_PASSWORD];
6853             hr = IUri_GetPassword(uri, &received);
6854             if(prop.todo) {
6855                 todo_wine {
6856                     ok(hr == prop.expected, "Error: GetPassword returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6857                             hr, prop.expected, i);
6858                 }
6859                 todo_wine {
6860                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6861                             prop.value, wine_dbgstr_w(received), i);
6862                 }
6863             } else {
6864                 ok(hr == prop.expected, "Error: GetPassword returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6865                         hr, prop.expected, i);
6866                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6867                         prop.value, wine_dbgstr_w(received), i);
6868             }
6869             SysFreeString(received);
6870             received = NULL;
6871
6872             /* GetPath() tests. */
6873             prop = test.str_props[Uri_PROPERTY_PATH];
6874             hr = IUri_GetPath(uri, &received);
6875             if(prop.todo) {
6876                 todo_wine {
6877                     ok(hr == prop.expected, "Error: GetPath returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6878                             hr, prop.expected, i);
6879                 }
6880                 todo_wine {
6881                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6882                             prop.value, wine_dbgstr_w(received), i);
6883                 }
6884             } else {
6885                 ok(hr == prop.expected, "Error: GetPath returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6886                         hr, prop.expected, i);
6887                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6888                         prop.value, wine_dbgstr_w(received), i);
6889             }
6890             SysFreeString(received);
6891             received = NULL;
6892
6893             /* GetPathAndQuery() tests. */
6894             prop = test.str_props[Uri_PROPERTY_PATH_AND_QUERY];
6895             hr = IUri_GetPathAndQuery(uri, &received);
6896             if(prop.todo) {
6897                 todo_wine {
6898                     ok(hr == prop.expected, "Error: GetPathAndQuery returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6899                             hr, prop.expected, i);
6900                 }
6901                 todo_wine {
6902                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6903                             prop.value, wine_dbgstr_w(received), i);
6904                 }
6905             } else {
6906                 ok(hr == prop.expected, "Error: GetPathAndQuery returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6907                         hr, prop.expected, i);
6908                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6909                         prop.value, wine_dbgstr_w(received), i);
6910             }
6911             SysFreeString(received);
6912             received = NULL;
6913
6914             /* GetQuery() tests. */
6915             prop = test.str_props[Uri_PROPERTY_QUERY];
6916             hr = IUri_GetQuery(uri, &received);
6917             if(prop.todo) {
6918                 todo_wine {
6919                     ok(hr == prop.expected, "Error: GetQuery returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6920                             hr, prop.expected, i);
6921                 }
6922                 todo_wine {
6923                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6924                             prop.value, wine_dbgstr_w(received), i);
6925                 }
6926             } else {
6927                 ok(hr == prop.expected, "Error: GetQuery returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6928                         hr, prop.expected, i);
6929                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6930                         prop.value, wine_dbgstr_w(received), i);
6931             }
6932             SysFreeString(received);
6933             received = NULL;
6934
6935             /* GetRawUri() tests. */
6936             prop = test.str_props[Uri_PROPERTY_RAW_URI];
6937             hr = IUri_GetRawUri(uri, &received);
6938             if(prop.todo) {
6939                 todo_wine {
6940                     ok(hr == prop.expected, "Error: GetRawUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6941                             hr, prop.expected, i);
6942                 }
6943                 todo_wine {
6944                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6945                             prop.value, wine_dbgstr_w(received), i);
6946                 }
6947             } else {
6948                 ok(hr == prop.expected, "Error: GetRawUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6949                         hr, prop.expected, i);
6950                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6951                         prop.value, wine_dbgstr_w(received), i);
6952             }
6953             SysFreeString(received);
6954             received = NULL;
6955
6956             /* GetSchemeName() tests. */
6957             prop = test.str_props[Uri_PROPERTY_SCHEME_NAME];
6958             hr = IUri_GetSchemeName(uri, &received);
6959             if(prop.todo) {
6960                 todo_wine {
6961                     ok(hr == prop.expected, "Error: GetSchemeName returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6962                             hr, prop.expected, i);
6963                 }
6964                 todo_wine {
6965                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6966                             prop.value, wine_dbgstr_w(received), i);
6967                 }
6968             } else {
6969                 ok(hr == prop.expected, "Error: GetSchemeName returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6970                         hr, prop.expected, i);
6971                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6972                         prop.value, wine_dbgstr_w(received), i);
6973             }
6974             SysFreeString(received);
6975             received = NULL;
6976
6977             /* GetUserInfo() tests. */
6978             prop = test.str_props[Uri_PROPERTY_USER_INFO];
6979             hr = IUri_GetUserInfo(uri, &received);
6980             if(prop.todo) {
6981                 todo_wine {
6982                     ok(hr == prop.expected, "Error: GetUserInfo returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6983                             hr, prop.expected, i);
6984                 }
6985                 todo_wine {
6986                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6987                             prop.value, wine_dbgstr_w(received), i);
6988                 }
6989             } else {
6990                 ok(hr == prop.expected, "Error: GetUserInfo returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6991                         hr, prop.expected, i);
6992                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6993                         prop.value, wine_dbgstr_w(received), i);
6994             }
6995             SysFreeString(received);
6996             received = NULL;
6997
6998             /* GetUserName() tests. */
6999             prop = test.str_props[Uri_PROPERTY_USER_NAME];
7000             hr = IUri_GetUserName(uri, &received);
7001             if(prop.todo) {
7002                 todo_wine {
7003                     ok(hr == prop.expected, "Error: GetUserName returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7004                             hr, prop.expected, i);
7005                 }
7006                 todo_wine {
7007                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
7008                             prop.value, wine_dbgstr_w(received), i);
7009                 }
7010             } else {
7011                 ok(hr == prop.expected, "Error: GetUserName returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7012                         hr, prop.expected, i);
7013                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
7014                         prop.value, wine_dbgstr_w(received), i);
7015             }
7016             SysFreeString(received);
7017         }
7018
7019         if(uri) IUri_Release(uri);
7020
7021         heap_free(uriW);
7022     }
7023 }
7024
7025 static void test_IUri_GetDwordProperties(void) {
7026     IUri *uri = NULL;
7027     HRESULT hr;
7028     DWORD i;
7029
7030     /* Make sure all the 'Get*' dword property functions handle invalid args correctly. */
7031     hr = pCreateUri(http_urlW, 0, 0, &uri);
7032     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7033     if(SUCCEEDED(hr)) {
7034         hr = IUri_GetHostType(uri, NULL);
7035         ok(hr == E_INVALIDARG, "Error: GetHostType returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
7036
7037         hr = IUri_GetPort(uri, NULL);
7038         ok(hr == E_INVALIDARG, "Error: GetPort returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
7039
7040         hr = IUri_GetScheme(uri, NULL);
7041         ok(hr == E_INVALIDARG, "Error: GetScheme returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
7042
7043         hr = IUri_GetZone(uri, NULL);
7044         ok(hr == E_INVALIDARG, "Error: GetZone returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
7045     }
7046     if(uri) IUri_Release(uri);
7047
7048     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
7049         uri_properties test = uri_tests[i];
7050         LPWSTR uriW;
7051         uri = NULL;
7052
7053         uriW = a2w(test.uri);
7054         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
7055         if(test.create_todo) {
7056             todo_wine {
7057                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7058                         hr, test.create_expected, i);
7059             }
7060         } else {
7061             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7062                     hr, test.create_expected, i);
7063         }
7064
7065         if(SUCCEEDED(hr)) {
7066             uri_dword_property prop;
7067             DWORD received;
7068
7069             /* Assign an insane value so tests don't accidentally pass when
7070              * they shouldn't!
7071              */
7072             received = -9999999;
7073
7074             /* GetHostType() tests. */
7075             prop = test.dword_props[Uri_PROPERTY_HOST_TYPE-Uri_PROPERTY_DWORD_START];
7076             hr = IUri_GetHostType(uri, &received);
7077             if(prop.todo) {
7078                 todo_wine {
7079                     ok(hr == prop.expected, "Error: GetHostType returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7080                             hr, prop.expected, i);
7081                 }
7082                 todo_wine {
7083                     ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
7084                 }
7085             } else {
7086                 ok(hr == prop.expected, "Error: GetHostType returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7087                         hr, prop.expected, i);
7088                 ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
7089             }
7090             received = -9999999;
7091
7092             /* GetPort() tests. */
7093             prop = test.dword_props[Uri_PROPERTY_PORT-Uri_PROPERTY_DWORD_START];
7094             hr = IUri_GetPort(uri, &received);
7095             if(prop.todo) {
7096                 todo_wine {
7097                     ok(hr == prop.expected, "Error: GetPort returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7098                             hr, prop.expected, i);
7099                 }
7100                 todo_wine {
7101                     ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
7102                 }
7103             } else {
7104                 ok(hr == prop.expected, "Error: GetPort returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7105                         hr, prop.expected, i);
7106                 ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
7107             }
7108             received = -9999999;
7109
7110             /* GetScheme() tests. */
7111             prop = test.dword_props[Uri_PROPERTY_SCHEME-Uri_PROPERTY_DWORD_START];
7112             hr = IUri_GetScheme(uri, &received);
7113             if(prop.todo) {
7114                 todo_wine {
7115                     ok(hr == prop.expected, "Error: GetScheme returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7116                             hr, prop.expected, i);
7117                 }
7118                 todo_wine {
7119                     ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
7120                 }
7121             } else {
7122                 ok(hr == prop.expected, "Error: GetScheme returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7123                         hr, prop.expected, i);
7124                 ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
7125             }
7126             received = -9999999;
7127
7128             /* GetZone() tests. */
7129             prop = test.dword_props[Uri_PROPERTY_ZONE-Uri_PROPERTY_DWORD_START];
7130             hr = IUri_GetZone(uri, &received);
7131             if(prop.todo) {
7132                 todo_wine {
7133                     ok(hr == prop.expected, "Error: GetZone returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7134                             hr, prop.expected, i);
7135                 }
7136                 todo_wine {
7137                     ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
7138                 }
7139             } else {
7140                 ok(hr == prop.expected, "Error: GetZone returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7141                         hr, prop.expected, i);
7142                 ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
7143             }
7144         }
7145
7146         if(uri) IUri_Release(uri);
7147
7148         heap_free(uriW);
7149     }
7150 }
7151
7152 static void test_IUri_GetPropertyLength(void) {
7153     IUri *uri = NULL;
7154     HRESULT hr;
7155     DWORD i;
7156
7157     /* Make sure it handles invalid args correctly. */
7158     hr = pCreateUri(http_urlW, 0, 0, &uri);
7159     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7160     if(SUCCEEDED(hr)) {
7161         DWORD received = 0xdeadbeef;
7162
7163         hr = IUri_GetPropertyLength(uri, Uri_PROPERTY_STRING_START, NULL, 0);
7164         ok(hr == E_INVALIDARG, "Error: GetPropertyLength returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
7165
7166         hr = IUri_GetPropertyLength(uri, Uri_PROPERTY_DWORD_START, &received, 0);
7167         ok(hr == E_INVALIDARG, "Error: GetPropertyLength return 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
7168         ok(received == 0xdeadbeef, "Error: Expected 0xdeadbeef but got 0x%08x.\n", received);
7169     }
7170     if(uri) IUri_Release(uri);
7171
7172     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
7173         uri_properties test = uri_tests[i];
7174         LPWSTR uriW;
7175         uri = NULL;
7176
7177         uriW = a2w(test.uri);
7178         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
7179         if(test.create_todo) {
7180             todo_wine {
7181                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7182                         hr, test.create_expected, i);
7183             }
7184         } else {
7185             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_test[%d].\n",
7186                     hr, test.create_expected, i);
7187         }
7188
7189         if(SUCCEEDED(hr)) {
7190             DWORD j;
7191
7192             for(j = Uri_PROPERTY_STRING_START; j <= Uri_PROPERTY_STRING_LAST; ++j) {
7193                 DWORD expectedLen, brokenLen, receivedLen;
7194                 uri_str_property prop = test.str_props[j];
7195
7196                 expectedLen = lstrlen(prop.value);
7197                 brokenLen = lstrlen(prop.broken_value);
7198
7199                 /* This won't be necessary once GetPropertyLength is implemented. */
7200                 receivedLen = -1;
7201
7202                 hr = IUri_GetPropertyLength(uri, j, &receivedLen, 0);
7203                 if(prop.todo) {
7204                     todo_wine {
7205                         ok(hr == prop.expected, "Error: GetPropertyLength returned 0x%08x, expected 0x%08x on uri_tests[%d].str_props[%d].\n",
7206                                 hr, prop.expected, i, j);
7207                     }
7208                     todo_wine {
7209                         ok(receivedLen == expectedLen || broken(receivedLen == brokenLen),
7210                                 "Error: Expected a length of %d but got %d on uri_tests[%d].str_props[%d].\n",
7211                                 expectedLen, receivedLen, i, j);
7212                     }
7213                 } else {
7214                     ok(hr == prop.expected, "Error: GetPropertyLength returned 0x%08x, expected 0x%08x on uri_tests[%d].str_props[%d].\n",
7215                             hr, prop.expected, i, j);
7216                     ok(receivedLen == expectedLen || broken(receivedLen == brokenLen),
7217                             "Error: Expected a length of %d but got %d on uri_tests[%d].str_props[%d].\n",
7218                             expectedLen, receivedLen, i, j);
7219                 }
7220             }
7221         }
7222
7223         if(uri) IUri_Release(uri);
7224
7225         heap_free(uriW);
7226     }
7227 }
7228
7229 static void test_IUri_GetProperties(void) {
7230     IUri *uri = NULL;
7231     HRESULT hr;
7232     DWORD i;
7233
7234     hr = pCreateUri(http_urlW, 0, 0, &uri);
7235     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7236     if(SUCCEEDED(hr)) {
7237         hr = IUri_GetProperties(uri, NULL);
7238         ok(hr == E_INVALIDARG, "Error: GetProperties returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
7239     }
7240     if(uri) IUri_Release(uri);
7241
7242     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
7243         uri_properties test = uri_tests[i];
7244         LPWSTR uriW;
7245         uri = NULL;
7246
7247         uriW = a2w(test.uri);
7248         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
7249         if(test.create_todo) {
7250             todo_wine {
7251                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, test.create_expected);
7252             }
7253         } else {
7254             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, test.create_expected);
7255         }
7256
7257         if(SUCCEEDED(hr)) {
7258             DWORD received = 0;
7259             DWORD j;
7260
7261             hr = IUri_GetProperties(uri, &received);
7262             if(test.props_todo) {
7263                 todo_wine {
7264                     ok(hr == S_OK, "Error: GetProperties returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7265                 }
7266             } else {
7267                 ok(hr == S_OK, "Error: GetProperties returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7268             }
7269
7270             for(j = 0; j <= Uri_PROPERTY_DWORD_LAST; ++j) {
7271                 /* (1 << j) converts a Uri_PROPERTY to its corresponding Uri_HAS_* flag mask. */
7272                 if(test.props & (1 << j)) {
7273                     if(test.props_todo) {
7274                         todo_wine {
7275                             ok(received & (1 << j), "Error: Expected flag for property %d on uri_tests[%d].\n", j, i);
7276                         }
7277                     } else {
7278                         ok(received & (1 << j), "Error: Expected flag for property %d on uri_tests[%d].\n", j, i);
7279                     }
7280                 } else {
7281                     /* NOTE: Since received is initialized to 0, this test will always pass while
7282                      * GetProperties is unimplemented.
7283                      */
7284                     ok(!(received & (1 << j)), "Error: Received flag for property %d when not expected on uri_tests[%d].\n", j, i);
7285                 }
7286             }
7287         }
7288
7289         if(uri) IUri_Release(uri);
7290
7291         heap_free(uriW);
7292     }
7293 }
7294
7295 static void test_IUri_HasProperty(void) {
7296     IUri *uri = NULL;
7297     HRESULT hr;
7298     DWORD i;
7299
7300     hr = pCreateUri(http_urlW, 0, 0, &uri);
7301     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7302     if(SUCCEEDED(hr)) {
7303         hr = IUri_HasProperty(uri, Uri_PROPERTY_RAW_URI, NULL);
7304         ok(hr == E_INVALIDARG, "Error: HasProperty returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
7305     }
7306     if(uri) IUri_Release(uri);
7307
7308     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
7309         uri_properties test = uri_tests[i];
7310         LPWSTR uriW;
7311         uri = NULL;
7312
7313         uriW = a2w(test.uri);
7314
7315         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
7316         if(test.create_todo) {
7317             todo_wine {
7318                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, test.create_expected);
7319             }
7320         } else {
7321             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, test.create_expected);
7322         }
7323
7324         if(SUCCEEDED(hr)) {
7325             DWORD j;
7326
7327             for(j = 0; j <= Uri_PROPERTY_DWORD_LAST; ++j) {
7328                 /* Assign -1, then explicitly test for TRUE or FALSE later. */
7329                 BOOL received = -1;
7330
7331                 hr = IUri_HasProperty(uri, j, &received);
7332                 if(test.props_todo) {
7333                     todo_wine {
7334                         ok(hr == S_OK, "Error: HasProperty returned 0x%08x, expected 0x%08x for property %d on uri_tests[%d].\n",
7335                                 hr, S_OK, j, i);
7336                     }
7337
7338                     /* Check if the property should be true. */
7339                     if(test.props & (1 << j)) {
7340                         todo_wine {
7341                             ok(received == TRUE, "Error: Expected to have property %d on uri_tests[%d].\n", j, i);
7342                         }
7343                     } else {
7344                         todo_wine {
7345                             ok(received == FALSE, "Error: Wasn't expecting to have property %d on uri_tests[%d].\n", j, i);
7346                         }
7347                     }
7348                 } else {
7349                     ok(hr == S_OK, "Error: HasProperty returned 0x%08x, expected 0x%08x for property %d on uri_tests[%d].\n",
7350                             hr, S_OK, j, i);
7351
7352                     if(test.props & (1 << j)) {
7353                         ok(received == TRUE, "Error: Expected to have property %d on uri_tests[%d].\n", j, i);
7354                     } else {
7355                         ok(received == FALSE, "Error: Wasn't expecting to have property %d on uri_tests[%d].\n", j, i);
7356                     }
7357                 }
7358             }
7359         }
7360
7361         if(uri) IUri_Release(uri);
7362
7363         heap_free(uriW);
7364     }
7365 }
7366
7367 static void test_IUri_IsEqual(void) {
7368     IUri *uriA, *uriB;
7369     HRESULT hrA, hrB;
7370     DWORD i;
7371
7372     uriA = uriB = NULL;
7373
7374     /* Make sure IsEqual handles invalid args correctly. */
7375     hrA = pCreateUri(http_urlW, 0, 0, &uriA);
7376     hrB = pCreateUri(http_urlW, 0, 0, &uriB);
7377     ok(hrA == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hrA, S_OK);
7378     ok(hrB == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hrB, S_OK);
7379     if(SUCCEEDED(hrA) && SUCCEEDED(hrB)) {
7380         BOOL equal = -1;
7381         hrA = IUri_IsEqual(uriA, NULL, &equal);
7382         ok(hrA == S_OK, "Error: IsEqual returned 0x%08x, expected 0x%08x.\n", hrA, S_OK);
7383         ok(equal == FALSE, "Error: Expected equal to be FALSE, but was %d instead.\n", equal);
7384
7385         hrA = IUri_IsEqual(uriA, uriB, NULL);
7386         ok(hrA == E_POINTER, "Error: IsEqual returned 0x%08x, expected 0x%08x.\n", hrA, E_POINTER);
7387     }
7388     if(uriA) IUri_Release(uriA);
7389     if(uriB) IUri_Release(uriB);
7390
7391     for(i = 0; i < sizeof(equality_tests)/sizeof(equality_tests[0]); ++i) {
7392         uri_equality test = equality_tests[i];
7393         LPWSTR uriA_W, uriB_W;
7394
7395         uriA = uriB = NULL;
7396
7397         uriA_W = a2w(test.a);
7398         uriB_W = a2w(test.b);
7399
7400         hrA = pCreateUri(uriA_W, test.create_flags_a, 0, &uriA);
7401         if(test.create_todo_a) {
7402             todo_wine {
7403                 ok(hrA == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x on equality_tests[%d].a\n",
7404                         hrA, S_OK, i);
7405             }
7406         } else {
7407             ok(hrA == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x on equality_tests[%d].a\n",
7408                     hrA, S_OK, i);
7409         }
7410
7411         hrB = pCreateUri(uriB_W, test.create_flags_b, 0, &uriB);
7412         if(test.create_todo_b) {
7413             todo_wine {
7414                 ok(hrB == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x on equality_tests[%d].b\n",
7415                         hrB, S_OK, i);
7416             }
7417         } else {
7418             ok(hrB == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x on equality_tests[%d].b\n",
7419                     hrB, S_OK, i);
7420         }
7421
7422         if(SUCCEEDED(hrA) && SUCCEEDED(hrB)) {
7423             BOOL equal = -1;
7424
7425             hrA = IUri_IsEqual(uriA, uriB, &equal);
7426             if(test.todo) {
7427                 todo_wine {
7428                     ok(hrA == S_OK, "Error: IsEqual returned 0x%08x, expected 0x%08x on equality_tests[%d].\n",
7429                             hrA, S_OK, i);
7430                 }
7431                 todo_wine {
7432                     ok(equal == test.equal, "Error: Expected the comparison to be %d on equality_tests[%d].\n", test.equal, i);
7433                 }
7434             } else {
7435                 ok(hrA == S_OK, "Error: IsEqual returned 0x%08x, expected 0x%08x on equality_tests[%d].\n", hrA, S_OK, i);
7436                 ok(equal == test.equal, "Error: Expected the comparison to be %d on equality_tests[%d].\n", test.equal, i);
7437             }
7438         }
7439         if(uriA) IUri_Release(uriA);
7440         if(uriB) IUri_Release(uriB);
7441
7442         heap_free(uriA_W);
7443         heap_free(uriB_W);
7444     }
7445 }
7446
7447 static void test_CreateUriWithFragment_InvalidArgs(void) {
7448     HRESULT hr;
7449     IUri *uri = (void*) 0xdeadbeef;
7450     const WCHAR fragmentW[] = {'#','f','r','a','g','m','e','n','t',0};
7451
7452     hr = pCreateUriWithFragment(NULL, fragmentW, 0, 0, &uri);
7453     ok(hr == E_INVALIDARG, "Error: CreateUriWithFragment returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
7454     ok(uri == NULL, "Error: Expected uri to be NULL, but was %p instead.\n", uri);
7455
7456     hr = pCreateUriWithFragment(http_urlW, fragmentW, 0, 0, NULL);
7457     ok(hr == E_INVALIDARG, "Error: CreateUriWithFragment returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
7458
7459     /* Original URI can't already contain a fragment component. */
7460     uri = (void*) 0xdeadbeef;
7461     hr = pCreateUriWithFragment(http_url_fragW, fragmentW, 0, 0, &uri);
7462     ok(hr == E_INVALIDARG, "Error: CreateUriWithFragment returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
7463     ok(uri == NULL, "Error: Expected uri to be NULL, but was %p instead.\n", uri);
7464 }
7465
7466 /* CreateUriWithFragment has the same invalid flag combinations as CreateUri. */
7467 static void test_CreateUriWithFragment_InvalidFlags(void) {
7468     DWORD i;
7469
7470     for(i = 0; i < sizeof(invalid_flag_tests)/sizeof(invalid_flag_tests[0]); ++i) {
7471         HRESULT hr;
7472         IUri *uri = (void*) 0xdeadbeef;
7473
7474         hr = pCreateUriWithFragment(http_urlW, NULL, invalid_flag_tests[i].flags, 0, &uri);
7475         ok(hr == invalid_flag_tests[i].expected, "Error: CreateUriWithFragment returned 0x%08x, expected 0x%08x. flags=0x%08x.\n",
7476             hr, invalid_flag_tests[i].expected, invalid_flag_tests[i].flags);
7477         ok(uri == NULL, "Error: Expected uri to be NULL, but was %p instead.\n", uri);
7478     }
7479 }
7480
7481 static void test_CreateUriWithFragment(void) {
7482     DWORD i;
7483
7484     for(i = 0; i < sizeof(uri_fragment_tests)/sizeof(uri_fragment_tests[0]); ++i) {
7485         HRESULT hr;
7486         IUri *uri = NULL;
7487         LPWSTR uriW, fragW;
7488         uri_with_fragment test = uri_fragment_tests[i];
7489
7490         uriW = a2w(test.uri);
7491         fragW = a2w(test.fragment);
7492
7493         hr = pCreateUriWithFragment(uriW, fragW, test.create_flags, 0, &uri);
7494         if(test.expected_todo) {
7495             todo_wine {
7496                 ok(hr == test.create_expected,
7497                     "Error: CreateUriWithFragment returned 0x%08x, expected 0x%08x on uri_fragment_tests[%d].\n",
7498                     hr, test.create_expected, i);
7499             }
7500         } else
7501             ok(hr == test.create_expected,
7502                 "Error: CreateUriWithFragment returned 0x%08x, expected 0x%08x on uri_fragment_tests[%d].\n",
7503                 hr, test.create_expected, i);
7504
7505         if(SUCCEEDED(hr)) {
7506             BSTR received = NULL;
7507
7508             hr = IUri_GetAbsoluteUri(uri, &received);
7509             if(test.expected_todo) {
7510                 todo_wine {
7511                     ok(hr == S_OK,
7512                         "Error: GetAbsoluteUri returned 0x%08x, expected 0x%08x on uri_fragment_tests[%d].\n",
7513                         hr, S_OK, i);
7514                 }
7515                 todo_wine {
7516                     ok(!strcmp_aw(test.expected_uri, received),
7517                         "Error: Expected %s but got %s on uri_fragment_tests[%d].\n",
7518                         test.expected_uri, wine_dbgstr_w(received), i);
7519                 }
7520             } else {
7521                 ok(hr == S_OK, "Error: GetAbsoluteUri returned 0x%08x, expected 0x%08x on uri_fragment_tests[%d].\n",
7522                     hr, S_OK, i);
7523                 ok(!strcmp_aw(test.expected_uri, received), "Error: Expected %s but got %s on uri_fragment_tests[%d].\n",
7524                     test.expected_uri, wine_dbgstr_w(received), i);
7525             }
7526
7527             SysFreeString(received);
7528         }
7529
7530         if(uri) IUri_Release(uri);
7531         heap_free(uriW);
7532     }
7533 }
7534
7535 static void test_CreateIUriBuilder(void) {
7536     HRESULT hr;
7537     IUriBuilder *builder = NULL;
7538     IUri *uri;
7539
7540     hr = pCreateIUriBuilder(NULL, 0, 0, NULL);
7541     ok(hr == E_POINTER, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x\n",
7542         hr, E_POINTER);
7543
7544     /* CreateIUriBuilder increases the ref count of the IUri it receives. */
7545     hr = pCreateUri(http_urlW, 0, 0, &uri);
7546     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7547     if(SUCCEEDED(hr)) {
7548         ULONG cur_count, orig_count;
7549
7550         orig_count = get_refcnt(uri);
7551         hr = pCreateIUriBuilder(uri, 0, 0, &builder);
7552         ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7553         ok(builder != NULL, "Error: Expecting builder not to be NULL\n");
7554
7555         cur_count = get_refcnt(uri);
7556         ok(cur_count == orig_count+1, "Error: Expected the ref count to be %u, but was %u instead.\n", orig_count+1, cur_count);
7557
7558         if(builder) IUriBuilder_Release(builder);
7559         cur_count = get_refcnt(uri);
7560         ok(cur_count == orig_count, "Error: Expected the ref count to be %u, but was %u instead.\n", orig_count, cur_count);
7561     }
7562     if(uri) IUri_Release(uri);
7563 }
7564
7565 static void test_IUriBuilder_CreateUri(IUriBuilder *builder, const uri_builder_test *test,
7566                                        DWORD test_index) {
7567     HRESULT hr;
7568     IUri *uri = NULL;
7569
7570     hr = IUriBuilder_CreateUri(builder, test->uri_flags, 0, 0, &uri);
7571     if(test->uri_todo) {
7572         todo_wine {
7573             ok(hr == test->uri_hres,
7574                 "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7575                 hr, test->uri_hres, test_index);
7576         }
7577     } else {
7578         ok(hr == test->uri_hres,
7579             "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7580             hr, test->uri_hres, test_index);
7581     }
7582
7583     if(SUCCEEDED(hr)) {
7584         DWORD i;
7585
7586         for(i = 0; i < sizeof(test->expected_str_props)/sizeof(test->expected_str_props[0]); ++i) {
7587             uri_builder_str_property prop = test->expected_str_props[i];
7588             BSTR received = NULL;
7589
7590             hr = IUri_GetPropertyBSTR(uri, i, &received, 0);
7591             if(prop.todo) {
7592                 todo_wine {
7593                     ok(hr == prop.result,
7594                         "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_str_props[%d].\n",
7595                         hr, prop.result, test_index, i);
7596                 }
7597             } else {
7598                 ok(hr == prop.result,
7599                     "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_str_props[%d].\n",
7600                     hr, prop.result, test_index, i);
7601             }
7602             if(SUCCEEDED(hr)) {
7603                 if(prop.todo) {
7604                     todo_wine {
7605                         ok(!strcmp_aw(prop.expected, received),
7606                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].expected_str_props[%d].\n",
7607                             prop.expected, wine_dbgstr_w(received), test_index, i);
7608                     }
7609                 } else {
7610                     ok(!strcmp_aw(prop.expected, received),
7611                         "Error: Expected %s but got %s instead on uri_builder_tests[%d].expected_str_props[%d].\n",
7612                         prop.expected, wine_dbgstr_w(received), test_index, i);
7613                 }
7614             }
7615             SysFreeString(received);
7616         }
7617
7618         for(i = 0; i < sizeof(test->expected_dword_props)/sizeof(test->expected_dword_props[0]); ++i) {
7619             uri_builder_dword_property prop = test->expected_dword_props[i];
7620             DWORD received = -2;
7621
7622             hr = IUri_GetPropertyDWORD(uri, i+Uri_PROPERTY_DWORD_START, &received, 0);
7623             if(prop.todo) {
7624                 todo_wine {
7625                     ok(hr == prop.result,
7626                         "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_dword_props[%d].\n",
7627                         hr, prop.result, test_index, i);
7628                 }
7629             } else {
7630                 ok(hr == prop.result,
7631                     "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_dword_props[%d].\n",
7632                     hr, prop.result, test_index, i);
7633             }
7634             if(SUCCEEDED(hr)) {
7635                 if(prop.todo) {
7636                     todo_wine {
7637                         ok(received == prop.expected,
7638                             "Error: Expected %d but got %d instead on uri_builder_tests[%d].expected_dword_props[%d].\n",
7639                             prop.expected, received, test_index, i);
7640                     }
7641                 } else {
7642                     ok(received == prop.expected,
7643                         "Error: Expected %d but got %d instead on uri_builder_tests[%d].expected_dword_props[%d].\n",
7644                         prop.expected, received, test_index, i);
7645                 }
7646             }
7647         }
7648     }
7649     if(uri) IUri_Release(uri);
7650 }
7651
7652 static void test_IUriBuilder_CreateUriSimple(IUriBuilder *builder, const uri_builder_test *test,
7653                                        DWORD test_index) {
7654     HRESULT hr;
7655     IUri *uri = NULL;
7656
7657     hr = IUriBuilder_CreateUriSimple(builder, test->uri_simple_encode_flags, 0, &uri);
7658     if(test->uri_simple_todo) {
7659         todo_wine {
7660             ok(hr == test->uri_simple_hres,
7661                 "Error: IUriBuilder_CreateUriSimple returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7662                 hr, test->uri_simple_hres, test_index);
7663         }
7664     } else {
7665         ok(hr == test->uri_simple_hres,
7666             "Error: IUriBuilder_CreateUriSimple returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7667             hr, test->uri_simple_hres, test_index);
7668     }
7669
7670     if(SUCCEEDED(hr)) {
7671         DWORD i;
7672
7673         for(i = 0; i < sizeof(test->expected_str_props)/sizeof(test->expected_str_props[0]); ++i) {
7674             uri_builder_str_property prop = test->expected_str_props[i];
7675             BSTR received = NULL;
7676
7677             hr = IUri_GetPropertyBSTR(uri, i, &received, 0);
7678             if(prop.todo) {
7679                 todo_wine {
7680                     ok(hr == prop.result,
7681                         "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_str_props[%d].\n",
7682                         hr, prop.result, test_index, i);
7683                 }
7684             } else {
7685                 ok(hr == prop.result,
7686                     "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_str_props[%d].\n",
7687                     hr, prop.result, test_index, i);
7688             }
7689             if(SUCCEEDED(hr)) {
7690                 if(prop.todo) {
7691                     todo_wine {
7692                         ok(!strcmp_aw(prop.expected, received),
7693                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].expected_str_props[%d].\n",
7694                             prop.expected, wine_dbgstr_w(received), test_index, i);
7695                     }
7696                 } else {
7697                     ok(!strcmp_aw(prop.expected, received),
7698                         "Error: Expected %s but got %s instead on uri_builder_tests[%d].expected_str_props[%d].\n",
7699                         prop.expected, wine_dbgstr_w(received), test_index, i);
7700                 }
7701             }
7702             SysFreeString(received);
7703         }
7704
7705         for(i = 0; i < sizeof(test->expected_dword_props)/sizeof(test->expected_dword_props[0]); ++i) {
7706             uri_builder_dword_property prop = test->expected_dword_props[i];
7707             DWORD received = -2;
7708
7709             hr = IUri_GetPropertyDWORD(uri, i+Uri_PROPERTY_DWORD_START, &received, 0);
7710             if(prop.todo) {
7711                 todo_wine {
7712                     ok(hr == prop.result,
7713                         "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_dword_props[%d].\n",
7714                         hr, prop.result, test_index, i);
7715                 }
7716             } else {
7717                 ok(hr == prop.result,
7718                     "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_dword_props[%d].\n",
7719                     hr, prop.result, test_index, i);
7720             }
7721             if(SUCCEEDED(hr)) {
7722                 if(prop.todo) {
7723                     todo_wine {
7724                         ok(received == prop.expected,
7725                             "Error: Expected %d but got %d instead on uri_builder_tests[%d].expected_dword_props[%d].\n",
7726                             prop.expected, received, test_index, i);
7727                     }
7728                 } else {
7729                     ok(received == prop.expected,
7730                         "Error: Expected %d but got %d instead on uri_builder_tests[%d].expected_dword_props[%d].\n",
7731                         prop.expected, received, test_index, i);
7732                 }
7733             }
7734         }
7735     }
7736     if(uri) IUri_Release(uri);
7737 }
7738
7739 static void test_IUriBuilder_CreateUriWithFlags(IUriBuilder *builder, const uri_builder_test *test,
7740                                                 DWORD test_index) {
7741     HRESULT hr;
7742     IUri *uri = NULL;
7743
7744     hr = IUriBuilder_CreateUriWithFlags(builder, test->uri_with_flags, test->uri_with_builder_flags,
7745                                         test->uri_with_encode_flags, 0, &uri);
7746     if(test->uri_with_todo) {
7747         todo_wine {
7748             ok(hr == test->uri_with_hres,
7749                 "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7750                 hr, test->uri_with_hres, test_index);
7751         }
7752     } else {
7753         ok(hr == test->uri_with_hres,
7754             "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7755             hr, test->uri_with_hres, test_index);
7756     }
7757
7758     if(SUCCEEDED(hr)) {
7759         DWORD i;
7760
7761         for(i = 0; i < sizeof(test->expected_str_props)/sizeof(test->expected_str_props[0]); ++i) {
7762             uri_builder_str_property prop = test->expected_str_props[i];
7763             BSTR received = NULL;
7764
7765             hr = IUri_GetPropertyBSTR(uri, i, &received, 0);
7766             if(prop.todo) {
7767                 todo_wine {
7768                     ok(hr == prop.result,
7769                         "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_str_props[%d].\n",
7770                         hr, prop.result, test_index, i);
7771                 }
7772             } else {
7773                 ok(hr == prop.result,
7774                     "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_str_props[%d].\n",
7775                     hr, prop.result, test_index, i);
7776             }
7777             if(SUCCEEDED(hr)) {
7778                 if(prop.todo) {
7779                     todo_wine {
7780                         ok(!strcmp_aw(prop.expected, received),
7781                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].expected_str_props[%d].\n",
7782                             prop.expected, wine_dbgstr_w(received), test_index, i);
7783                     }
7784                 } else {
7785                     ok(!strcmp_aw(prop.expected, received),
7786                         "Error: Expected %s but got %s instead on uri_builder_tests[%d].expected_str_props[%d].\n",
7787                         prop.expected, wine_dbgstr_w(received), test_index, i);
7788                 }
7789             }
7790             SysFreeString(received);
7791         }
7792
7793         for(i = 0; i < sizeof(test->expected_dword_props)/sizeof(test->expected_dword_props[0]); ++i) {
7794             uri_builder_dword_property prop = test->expected_dword_props[i];
7795             DWORD received = -2;
7796
7797             hr = IUri_GetPropertyDWORD(uri, i+Uri_PROPERTY_DWORD_START, &received, 0);
7798             if(prop.todo) {
7799                 todo_wine {
7800                     ok(hr == prop.result,
7801                         "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_dword_props[%d].\n",
7802                         hr, prop.result, test_index, i);
7803                 }
7804             } else {
7805                 ok(hr == prop.result,
7806                     "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_dword_props[%d].\n",
7807                     hr, prop.result, test_index, i);
7808             }
7809             if(SUCCEEDED(hr)) {
7810                 if(prop.todo) {
7811                     todo_wine {
7812                         ok(received == prop.expected,
7813                             "Error: Expected %d but got %d instead on uri_builder_tests[%d].expected_dword_props[%d].\n",
7814                             prop.expected, received, test_index, i);
7815                     }
7816                 } else {
7817                     ok(received == prop.expected,
7818                         "Error: Expected %d but got %d instead on uri_builder_tests[%d].expected_dword_props[%d].\n",
7819                         prop.expected, received, test_index, i);
7820                 }
7821             }
7822         }
7823     }
7824     if(uri) IUri_Release(uri);
7825 }
7826
7827 static void test_IUriBuilder_CreateInvalidArgs(void) {
7828     IUriBuilder *builder;
7829     HRESULT hr;
7830
7831     hr = pCreateIUriBuilder(NULL, 0, 0, &builder);
7832     ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7833     if(SUCCEEDED(hr)) {
7834         IUri *test = NULL, *uri = (void*) 0xdeadbeef;
7835
7836         /* Test what happens if the IUriBuilder doesn't have a IUri set. */
7837         hr = IUriBuilder_CreateUri(builder, 0, 0, 0, NULL);
7838         ok(hr == E_POINTER, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
7839
7840         uri = (void*) 0xdeadbeef;
7841         hr = IUriBuilder_CreateUri(builder, 0, Uri_HAS_USER_NAME, 0, &uri);
7842         ok(hr == E_NOTIMPL, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, E_NOTIMPL);
7843         ok(uri == NULL, "Error: expected uri to be NULL, but was %p instead.\n", uri);
7844
7845         hr = IUriBuilder_CreateUriSimple(builder, 0, 0, NULL);
7846         ok(hr == E_POINTER, "Error: IUriBuilder_CreateUriSimple returned 0x%08x, expected 0x%08x.\n",
7847             hr, E_POINTER);
7848
7849         uri = (void*) 0xdeadbeef;
7850         hr = IUriBuilder_CreateUriSimple(builder, Uri_HAS_USER_NAME, 0, &uri);
7851         ok(hr == E_NOTIMPL, "Error: IUriBuilder_CreateUriSimple returned 0x%08x, expected 0x%08x.\n",
7852             hr, E_NOTIMPL);
7853         ok(!uri, "Error: Expected uri to NULL, but was %p instead.\n", uri);
7854
7855         hr = IUriBuilder_CreateUriWithFlags(builder, 0, 0, 0, 0, NULL);
7856         ok(hr == E_POINTER, "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x.\n",
7857             hr, E_POINTER);
7858
7859         uri = (void*) 0xdeadbeef;
7860         hr = IUriBuilder_CreateUriWithFlags(builder, 0, 0, Uri_HAS_USER_NAME, 0, &uri);
7861         ok(hr == E_NOTIMPL, "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x.\n",
7862             hr, E_NOTIMPL);
7863         ok(!uri, "Error: Expected uri to be NULL, but was %p instead.\n", uri);
7864
7865         hr = pCreateUri(http_urlW, 0, 0, &test);
7866         ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7867         if(SUCCEEDED(hr)) {
7868             hr = IUriBuilder_SetIUri(builder, test);
7869             ok(hr == S_OK, "Error: IUriBuilder_SetIUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7870
7871             /* No longer returns E_NOTIMPL, since a IUri has been set and hasn't been modified. */
7872             uri = NULL;
7873             hr = IUriBuilder_CreateUri(builder, 0, Uri_HAS_USER_NAME, 0, &uri);
7874             ok(hr == S_OK, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7875             ok(uri != NULL, "Error: The uri was NULL.\n");
7876             if(uri) IUri_Release(uri);
7877
7878             uri = NULL;
7879             hr = IUriBuilder_CreateUriSimple(builder, Uri_HAS_USER_NAME, 0, &uri);
7880             ok(hr == S_OK, "Error: IUriBuilder_CreateUriSimple returned 0x%08x, expected 0x%08x.\n",
7881                 hr, S_OK);
7882             ok(uri != NULL, "Error: uri was NULL.\n");
7883             if(uri) IUri_Release(uri);
7884
7885             uri = NULL;
7886             hr = IUriBuilder_CreateUriWithFlags(builder, 0, 0, 0, 0, &uri);
7887             ok(hr == S_OK, "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x.\n",
7888                 hr, S_OK);
7889             ok(uri != NULL, "Error: uri was NULL.\n");
7890             if(uri) IUri_Release(uri);
7891
7892             hr = IUriBuilder_SetFragment(builder, NULL);
7893             ok(hr == S_OK, "Error: IUriBuilder_SetFragment returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7894
7895             /* The IUriBuilder is changed, so it returns E_NOTIMPL again. */
7896             uri = (void*) 0xdeadbeef;
7897             hr = IUriBuilder_CreateUri(builder, 0, Uri_HAS_USER_NAME, 0, &uri);
7898             ok(hr == E_NOTIMPL, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7899             ok(!uri, "Error: Expected uri to be NULL but was %p instead.\n", uri);
7900
7901             uri = (void*) 0xdeadbeef;
7902             hr = IUriBuilder_CreateUriSimple(builder, Uri_HAS_USER_NAME, 0, &uri);
7903             ok(hr == E_NOTIMPL, "Error: IUriBuilder_CreateUriSimple returned 0x%08x, expected 0x%08x.\n",
7904                 hr, S_OK);
7905             ok(!uri, "Error: Expected uri to be NULL, but was %p instead.\n", uri);
7906
7907             uri = (void*) 0xdeadbeef;
7908             hr = IUriBuilder_CreateUriWithFlags(builder, 0, 0, Uri_HAS_USER_NAME, 0, &uri);
7909             ok(hr == E_NOTIMPL, "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x.\n",
7910                 hr, E_NOTIMPL);
7911             ok(!uri, "Error: Expected uri to be NULL, but was %p instead.\n", uri);
7912         }
7913         if(test) IUri_Release(test);
7914     }
7915     if(builder) IUriBuilder_Release(builder);
7916 }
7917
7918 /* Tests invalid args to the "Get*" functions. */
7919 static void test_IUriBuilder_GetInvalidArgs(void) {
7920     IUriBuilder *builder = NULL;
7921     HRESULT hr;
7922
7923     hr = pCreateIUriBuilder(NULL, 0, 0, &builder);
7924     ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7925     if(SUCCEEDED(hr)) {
7926         LPCWSTR received = (void*) 0xdeadbeef;
7927         DWORD len = -1, port = -1;
7928         BOOL set = -1;
7929
7930         hr = IUriBuilder_GetFragment(builder, NULL, NULL);
7931         ok(hr == E_POINTER, "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x.\n",
7932             hr, E_POINTER);
7933         hr = IUriBuilder_GetFragment(builder, NULL, &received);
7934         ok(hr == E_POINTER, "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x.\n",
7935             hr, E_POINTER);
7936         ok(!received, "Error: Expected received to be NULL, but was %p instead.\n", received);
7937         hr = IUriBuilder_GetFragment(builder, &len, NULL);
7938         ok(hr == E_POINTER, "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x.\n",
7939             hr, E_POINTER);
7940         ok(!len, "Error: Expected len to be 0, but was %d instead.\n", len);
7941
7942         hr = IUriBuilder_GetHost(builder, NULL, NULL);
7943         ok(hr == E_POINTER, "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x.\n",
7944             hr, E_POINTER);
7945         received = (void*) 0xdeadbeef;
7946         hr = IUriBuilder_GetHost(builder, NULL, &received);
7947         ok(hr == E_POINTER, "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x.\n",
7948             hr, E_POINTER);
7949         ok(!received, "Error: Expected received to be NULL, but was %p instead.\n", received);
7950         len = -1;
7951         hr = IUriBuilder_GetHost(builder, &len, NULL);
7952         ok(hr == E_POINTER, "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x.\n",
7953             hr, E_POINTER);
7954         ok(!len, "Error: Expected len to be 0, but was %d instead.\n", len);
7955
7956         hr = IUriBuilder_GetPassword(builder, NULL, NULL);
7957         ok(hr == E_POINTER, "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x.\n",
7958             hr, E_POINTER);
7959         received = (void*) 0xdeadbeef;
7960         hr = IUriBuilder_GetPassword(builder, NULL, &received);
7961         ok(hr == E_POINTER, "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x.\n",
7962             hr, E_POINTER);
7963         ok(!received, "Error: Expected received to be NULL, but was %p instead.\n", received);
7964         len = -1;
7965         hr = IUriBuilder_GetPassword(builder, &len, NULL);
7966         ok(hr == E_POINTER, "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x.\n",
7967             hr, E_POINTER);
7968         ok(!len, "Error: Expected len to be 0, but was %d instead.\n", len);
7969
7970         hr = IUriBuilder_GetPath(builder, NULL, NULL);
7971         ok(hr == E_POINTER, "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x.\n",
7972             hr, E_POINTER);
7973         received = (void*) 0xdeadbeef;
7974         hr = IUriBuilder_GetPath(builder, NULL, &received);
7975         ok(hr == E_POINTER, "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x.\n",
7976             hr, E_POINTER);
7977         ok(!received, "Error: Expected received to be NULL, but was %p instead.\n", received);
7978         len = -1;
7979         hr = IUriBuilder_GetPath(builder, &len, NULL);
7980         ok(hr == E_POINTER, "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x.\n",
7981             hr, E_POINTER);
7982         ok(!len, "Error: Expected len to be 0, but was %d instead.\n", len);
7983
7984         hr = IUriBuilder_GetPort(builder, NULL, NULL);
7985         ok(hr == E_POINTER, "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x.\n",
7986             hr, E_POINTER);
7987         hr = IUriBuilder_GetPort(builder, NULL, &port);
7988         ok(hr == E_POINTER, "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x.\n",
7989             hr, E_POINTER);
7990         ok(!port, "Error: Expected port to be 0, but was %d instead.\n", port);
7991         hr = IUriBuilder_GetPort(builder, &set, NULL);
7992         ok(hr == E_POINTER, "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x.\n",
7993             hr, E_POINTER);
7994         ok(!set, "Error: Expected set to be FALSE, but was %d instead.\n", set);
7995
7996         hr = IUriBuilder_GetQuery(builder, NULL, NULL);
7997         ok(hr == E_POINTER, "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x.\n",
7998             hr, E_POINTER);
7999         received = (void*) 0xdeadbeef;
8000         hr = IUriBuilder_GetQuery(builder, NULL, &received);
8001         ok(hr == E_POINTER, "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x.\n",
8002             hr, E_POINTER);
8003         ok(!received, "Error: Expected received to be NULL, but was %p instead.\n", received);
8004         len = -1;
8005         hr = IUriBuilder_GetQuery(builder, &len, NULL);
8006         ok(hr == E_POINTER, "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x.\n",
8007             hr, E_POINTER);
8008         ok(!len, "Error: Expected len to be 0, but was %d instead.\n", len);
8009
8010         hr = IUriBuilder_GetSchemeName(builder, NULL, NULL);
8011         ok(hr == E_POINTER, "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x.\n",
8012             hr, E_POINTER);
8013         received = (void*) 0xdeadbeef;
8014         hr = IUriBuilder_GetSchemeName(builder, NULL, &received);
8015         ok(hr == E_POINTER, "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x.\n",
8016             hr, E_POINTER);
8017         ok(!received, "Error: Expected received to be NULL, but was %p instead.\n", received);
8018         len = -1;
8019         hr = IUriBuilder_GetSchemeName(builder, &len, NULL);
8020         ok(hr == E_POINTER, "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x.\n",
8021             hr, E_POINTER);
8022         ok(!len, "Error: Expected len to be 0, but was %d instead.\n", len);
8023
8024         hr = IUriBuilder_GetUserName(builder, NULL, NULL);
8025         ok(hr == E_POINTER, "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x.\n",
8026             hr, E_POINTER);
8027         received = (void*) 0xdeadbeef;
8028         hr = IUriBuilder_GetUserName(builder, NULL, &received);
8029         ok(hr == E_POINTER, "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x.\n",
8030             hr, E_POINTER);
8031         ok(!received, "Error: Expected received to be NULL, but was %p instead.\n", received);
8032         len = -1;
8033         hr = IUriBuilder_GetUserName(builder, &len, NULL);
8034         ok(hr == E_POINTER, "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x.\n",
8035             hr, E_POINTER);
8036         ok(!len, "Error: Expected len to be 0, but was %d instead.\n", len);
8037     }
8038     if(builder) IUriBuilder_Release(builder);
8039 }
8040
8041 static void test_IUriBuilder_GetFragment(IUriBuilder *builder, const uri_builder_test *test,
8042                                          DWORD test_index) {
8043     HRESULT hr;
8044     DWORD i;
8045     LPCWSTR received = NULL;
8046     DWORD len = -1;
8047     const uri_builder_property *prop = NULL;
8048
8049     /* Check if the property was set earlier. */
8050     for(i = 0; i < sizeof(test->properties)/sizeof(test->properties[0]); ++i) {
8051         if(test->properties[i].change && test->properties[i].property == Uri_PROPERTY_FRAGMENT)
8052             prop = &(test->properties[i]);
8053     }
8054
8055     if(prop) {
8056         /* Use expected_value unless it's NULL, then use value. */
8057         LPCSTR expected = prop->expected_value ? prop->expected_value : prop->value;
8058         hr = IUriBuilder_GetFragment(builder, &len, &received);
8059         if(prop->todo) {
8060             todo_wine {
8061                 ok(hr == (expected ? S_OK : S_FALSE),
8062                     "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8063                     hr, (expected ? S_OK : S_FALSE), test_index);
8064             }
8065             if(SUCCEEDED(hr)) {
8066                 todo_wine {
8067                     ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
8068                         expected, wine_dbgstr_w(received), test_index);
8069                 }
8070                 todo_wine {
8071                     ok(lstrlen(expected) == len,
8072                         "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8073                         lstrlen(expected), len, test_index);
8074                 }
8075             }
8076         } else {
8077             ok(hr == (expected ? S_OK : S_FALSE),
8078                 "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8079                 hr, (expected ? S_OK : S_FALSE), test_index);
8080             ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
8081                 expected, wine_dbgstr_w(received), test_index);
8082             ok(lstrlen(expected) == len,
8083                 "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8084                 lstrlen(expected), len, test_index);
8085         }
8086     } else {
8087         /* The property wasn't set earlier, so it should return whatever
8088          * the base IUri contains (if anything).
8089          */
8090         IUri *uri = NULL;
8091         hr = IUriBuilder_GetIUri(builder, &uri);
8092         ok(hr == S_OK,
8093             "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8094             hr, S_OK, test_index);
8095         if(SUCCEEDED(hr)) {
8096             if(!uri) {
8097                 received = (void*) 0xdeadbeef;
8098                 len = -1;
8099
8100                 hr = IUriBuilder_GetFragment(builder, &len, &received);
8101                 ok(hr == S_FALSE,
8102                     "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8103                     hr, S_FALSE, test_index);
8104                 if(SUCCEEDED(hr)) {
8105                     ok(!len, "Error: Expected len to be 0, but was %d instead on uri_builder_tests[%d].\n",
8106                         len, test_index);
8107                     ok(!received, "Error: Expected received to be NULL, but was %p instead on uri_builder_tests[%d].\n",
8108                         received, test_index);
8109                 }
8110             } else {
8111                 BOOL has_prop = FALSE;
8112                 BSTR expected = NULL;
8113
8114                 hr = IUri_GetFragment(uri, &expected);
8115                 ok(SUCCEEDED(hr),
8116                     "Error: Expected IUri_GetFragment to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
8117                     hr, test_index);
8118                 has_prop = hr == S_OK;
8119
8120                 hr = IUriBuilder_GetFragment(builder, &len, &received);
8121                 if(has_prop) {
8122                     ok(hr == S_OK,
8123                         "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8124                         hr, S_OK, test_index);
8125                     if(SUCCEEDED(hr)) {
8126                         ok(!lstrcmpW(expected, received),
8127                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].\n",
8128                             wine_dbgstr_w(expected), wine_dbgstr_w(received), test_index);
8129                         ok(lstrlenW(expected) == len,
8130                             "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8131                             lstrlenW(expected), len, test_index);
8132                     }
8133                 } else {
8134                     ok(hr == S_FALSE,
8135                         "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8136                         hr, S_FALSE, test_index);
8137                     if(SUCCEEDED(hr)) {
8138                         ok(!received, "Error: Expected received to be NULL on uri_builder_tests[%d].\n", test_index);
8139                         ok(!len, "Error: Expected the length to be 0, but was %d instead on uri_builder_tests[%d].\n",
8140                             len, test_index);
8141                     }
8142                 }
8143                 SysFreeString(expected);
8144             }
8145         }
8146         if(uri) IUri_Release(uri);
8147     }
8148 }
8149
8150 static void test_IUriBuilder_GetHost(IUriBuilder *builder, const uri_builder_test *test,
8151                                      DWORD test_index) {
8152     HRESULT hr;
8153     DWORD i;
8154     LPCWSTR received = NULL;
8155     DWORD len = -1;
8156     const uri_builder_property *prop = NULL;
8157
8158     /* Check if the property was set earlier. */
8159     for(i = 0; i < sizeof(test->properties)/sizeof(test->properties[0]); ++i) {
8160         if(test->properties[i].change && test->properties[i].property == Uri_PROPERTY_HOST)
8161             prop = &(test->properties[i]);
8162     }
8163
8164     if(prop) {
8165         /* Use expected_value unless it's NULL, then use value. */
8166         LPCSTR expected = prop->expected_value ? prop->expected_value : prop->value;
8167         hr = IUriBuilder_GetHost(builder, &len, &received);
8168         if(prop->todo) {
8169             todo_wine {
8170                 ok(hr == (expected ? S_OK : S_FALSE),
8171                     "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8172                     hr, (expected ? S_OK : S_FALSE), test_index);
8173             }
8174             if(SUCCEEDED(hr)) {
8175                 todo_wine {
8176                     ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
8177                         expected, wine_dbgstr_w(received), test_index);
8178                 }
8179                 todo_wine {
8180                     ok(lstrlen(expected) == len,
8181                         "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8182                         lstrlen(expected), len, test_index);
8183                 }
8184             }
8185         } else {
8186             ok(hr == (expected ? S_OK : S_FALSE),
8187                 "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8188                 hr, (expected ? S_OK : S_FALSE), test_index);
8189             ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
8190                 expected, wine_dbgstr_w(received), test_index);
8191             ok(lstrlen(expected) == len,
8192                 "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8193                 lstrlen(expected), len, test_index);
8194         }
8195     } else {
8196         /* The property wasn't set earlier, so it should return whatever
8197          * the base IUri contains (if anything).
8198          */
8199         IUri *uri = NULL;
8200         hr = IUriBuilder_GetIUri(builder, &uri);
8201         ok(hr == S_OK,
8202             "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8203             hr, S_OK, test_index);
8204         if(SUCCEEDED(hr)) {
8205             if(!uri) {
8206                 received = (void*) 0xdeadbeef;
8207                 len = -1;
8208
8209                 hr = IUriBuilder_GetHost(builder, &len, &received);
8210                 ok(hr == S_FALSE,
8211                     "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8212                     hr, S_FALSE, test_index);
8213                 if(SUCCEEDED(hr)) {
8214                     ok(!len, "Error: Expected len to be 0, but was %d instead on uri_builder_tests[%d].\n",
8215                         len, test_index);
8216                     ok(!received, "Error: Expected received to be NULL, but was %p instead on uri_builder_tests[%d].\n",
8217                         received, test_index);
8218                 }
8219             } else {
8220                 BOOL has_prop = FALSE;
8221                 BSTR expected = NULL;
8222
8223                 hr = IUri_GetHost(uri, &expected);
8224                 ok(SUCCEEDED(hr),
8225                     "Error: Expected IUri_GetHost to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
8226                     hr, test_index);
8227                 has_prop = hr == S_OK;
8228
8229                 hr = IUriBuilder_GetHost(builder, &len, &received);
8230                 if(has_prop) {
8231                     ok(hr == S_OK,
8232                         "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8233                         hr, S_OK, test_index);
8234                     if(SUCCEEDED(hr)) {
8235                         ok(!lstrcmpW(expected, received),
8236                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].\n",
8237                             wine_dbgstr_w(expected), wine_dbgstr_w(received), test_index);
8238                         ok(lstrlenW(expected) == len,
8239                             "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8240                             lstrlenW(expected), len, test_index);
8241                     }
8242                 } else {
8243                     ok(hr == S_FALSE,
8244                         "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8245                         hr, S_FALSE, test_index);
8246                     if(SUCCEEDED(hr)) {
8247                         ok(!received, "Error: Expected received to be NULL on uri_builder_tests[%d].\n", test_index);
8248                         ok(!len, "Error: Expected the length to be 0, but was %d instead on uri_builder_tests[%d].\n",
8249                             len, test_index);
8250                     }
8251                 }
8252                 SysFreeString(expected);
8253             }
8254         }
8255         if(uri) IUri_Release(uri);
8256     }
8257 }
8258
8259 static void test_IUriBuilder_GetPassword(IUriBuilder *builder, const uri_builder_test *test,
8260                                          DWORD test_index) {
8261     HRESULT hr;
8262     DWORD i;
8263     LPCWSTR received = NULL;
8264     DWORD len = -1;
8265     const uri_builder_property *prop = NULL;
8266
8267     /* Check if the property was set earlier. */
8268     for(i = 0; i < sizeof(test->properties)/sizeof(test->properties[0]); ++i) {
8269         if(test->properties[i].change && test->properties[i].property == Uri_PROPERTY_PASSWORD)
8270             prop = &(test->properties[i]);
8271     }
8272
8273     if(prop) {
8274         /* Use expected_value unless it's NULL, then use value. */
8275         LPCSTR expected = prop->expected_value ? prop->expected_value : prop->value;
8276         hr = IUriBuilder_GetPassword(builder, &len, &received);
8277         if(prop->todo) {
8278             todo_wine {
8279                 ok(hr == (expected ? S_OK : S_FALSE),
8280                     "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8281                     hr, (expected ? S_OK : S_FALSE), test_index);
8282             }
8283             if(SUCCEEDED(hr)) {
8284                 todo_wine {
8285                     ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
8286                         expected, wine_dbgstr_w(received), test_index);
8287                 }
8288                 todo_wine {
8289                     ok(lstrlen(expected) == len,
8290                         "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8291                         lstrlen(expected), len, test_index);
8292                 }
8293             }
8294         } else {
8295             ok(hr == (expected ? S_OK : S_FALSE),
8296                 "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8297                 hr, (expected ? S_OK : S_FALSE), test_index);
8298             ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
8299                 expected, wine_dbgstr_w(received), test_index);
8300             ok(lstrlen(expected) == len,
8301                 "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8302                 lstrlen(expected), len, test_index);
8303         }
8304     } else {
8305         /* The property wasn't set earlier, so it should return whatever
8306          * the base IUri contains (if anything).
8307          */
8308         IUri *uri = NULL;
8309         hr = IUriBuilder_GetIUri(builder, &uri);
8310         ok(hr == S_OK,
8311             "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8312             hr, S_OK, test_index);
8313         if(SUCCEEDED(hr)) {
8314             if(!uri) {
8315                 received = (void*) 0xdeadbeef;
8316                 len = -1;
8317
8318                 hr = IUriBuilder_GetPassword(builder, &len, &received);
8319                 ok(hr == S_FALSE,
8320                     "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8321                     hr, S_FALSE, test_index);
8322                 if(SUCCEEDED(hr)) {
8323                     ok(!len, "Error: Expected len to be 0, but was %d instead on uri_builder_tests[%d].\n",
8324                         len, test_index);
8325                     ok(!received, "Error: Expected received to be NULL, but was %p instead on uri_builder_tests[%d].\n",
8326                         received, test_index);
8327                 }
8328             } else {
8329                 BOOL has_prop = FALSE;
8330                 BSTR expected = NULL;
8331
8332                 hr = IUri_GetPassword(uri, &expected);
8333                 ok(SUCCEEDED(hr),
8334                     "Error: Expected IUri_GetPassword to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
8335                     hr, test_index);
8336                 has_prop = hr == S_OK;
8337
8338                 hr = IUriBuilder_GetPassword(builder, &len, &received);
8339                 if(has_prop) {
8340                     ok(hr == S_OK,
8341                         "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8342                         hr, S_OK, test_index);
8343                     if(SUCCEEDED(hr)) {
8344                         ok(!lstrcmpW(expected, received),
8345                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].\n",
8346                             wine_dbgstr_w(expected), wine_dbgstr_w(received), test_index);
8347                         ok(lstrlenW(expected) == len,
8348                             "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8349                             lstrlenW(expected), len, test_index);
8350                     }
8351                 } else {
8352                     ok(hr == S_FALSE,
8353                         "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8354                         hr, S_FALSE, test_index);
8355                     if(SUCCEEDED(hr)) {
8356                         ok(!received, "Error: Expected received to be NULL on uri_builder_tests[%d].\n", test_index);
8357                         ok(!len, "Error: Expected the length to be 0, but was %d instead on uri_builder_tests[%d].\n",
8358                             len, test_index);
8359                     }
8360                 }
8361                 SysFreeString(expected);
8362             }
8363         }
8364         if(uri) IUri_Release(uri);
8365     }
8366 }
8367
8368 static void test_IUriBuilder_GetPath(IUriBuilder *builder, const uri_builder_test *test,
8369                                      DWORD test_index) {
8370     HRESULT hr;
8371     DWORD i;
8372     LPCWSTR received = NULL;
8373     DWORD len = -1;
8374     const uri_builder_property *prop = NULL;
8375
8376     /* Check if the property was set earlier. */
8377     for(i = 0; i < sizeof(test->properties)/sizeof(test->properties[0]); ++i) {
8378         if(test->properties[i].change && test->properties[i].property == Uri_PROPERTY_PATH)
8379             prop = &(test->properties[i]);
8380     }
8381
8382     if(prop) {
8383         /* Use expected_value unless it's NULL, then use value. */
8384         LPCSTR expected = prop->expected_value ? prop->expected_value : prop->value;
8385         hr = IUriBuilder_GetPath(builder, &len, &received);
8386         if(prop->todo) {
8387             todo_wine {
8388                 ok(hr == (expected ? S_OK : S_FALSE),
8389                     "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8390                     hr, (expected ? S_OK : S_FALSE), test_index);
8391             }
8392             if(SUCCEEDED(hr)) {
8393                 todo_wine {
8394                     ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
8395                         expected, wine_dbgstr_w(received), test_index);
8396                 }
8397                 todo_wine {
8398                     ok(lstrlen(expected) == len,
8399                         "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8400                         lstrlen(expected), len, test_index);
8401                 }
8402             }
8403         } else {
8404             ok(hr == (expected ? S_OK : S_FALSE),
8405                 "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8406                 hr, (expected ? S_OK : S_FALSE), test_index);
8407             ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
8408                 expected, wine_dbgstr_w(received), test_index);
8409             ok(lstrlen(expected) == len,
8410                 "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8411                 lstrlen(expected), len, test_index);
8412         }
8413     } else {
8414         /* The property wasn't set earlier, so it should return whatever
8415          * the base IUri contains (if anything).
8416          */
8417         IUri *uri = NULL;
8418         hr = IUriBuilder_GetIUri(builder, &uri);
8419         ok(hr == S_OK,
8420             "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8421             hr, S_OK, test_index);
8422         if(SUCCEEDED(hr)) {
8423             if(!uri) {
8424                 received = (void*) 0xdeadbeef;
8425                 len = -1;
8426
8427                 hr = IUriBuilder_GetPath(builder, &len, &received);
8428                 ok(hr == S_FALSE,
8429                     "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8430                     hr, S_FALSE, test_index);
8431                 if(SUCCEEDED(hr)) {
8432                     ok(!len, "Error: Expected len to be 0, but was %d instead on uri_builder_tests[%d].\n",
8433                         len, test_index);
8434                     ok(!received, "Error: Expected received to be NULL, but was %p instead on uri_builder_tests[%d].\n",
8435                         received, test_index);
8436                 }
8437             } else {
8438                 BOOL has_prop = FALSE;
8439                 BSTR expected = NULL;
8440
8441                 hr = IUri_GetPath(uri, &expected);
8442                 ok(SUCCEEDED(hr),
8443                     "Error: Expected IUri_GetPath to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
8444                     hr, test_index);
8445                 has_prop = hr == S_OK;
8446
8447                 hr = IUriBuilder_GetPath(builder, &len, &received);
8448                 if(has_prop) {
8449                     ok(hr == S_OK,
8450                         "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8451                         hr, S_OK, test_index);
8452                     if(SUCCEEDED(hr)) {
8453                         ok(!lstrcmpW(expected, received),
8454                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].\n",
8455                             wine_dbgstr_w(expected), wine_dbgstr_w(received), test_index);
8456                         ok(lstrlenW(expected) == len,
8457                             "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8458                             lstrlenW(expected), len, test_index);
8459                     }
8460                 } else {
8461                     ok(hr == S_FALSE,
8462                         "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8463                         hr, S_FALSE, test_index);
8464                     if(SUCCEEDED(hr)) {
8465                         ok(!received, "Error: Expected received to be NULL on uri_builder_tests[%d].\n", test_index);
8466                         ok(!len, "Error: Expected the length to be 0, but was %d instead on uri_builder_tests[%d].\n",
8467                             len, test_index);
8468                     }
8469                 }
8470                 SysFreeString(expected);
8471             }
8472         }
8473         if(uri) IUri_Release(uri);
8474     }
8475 }
8476
8477 static void test_IUriBuilder_GetPort(IUriBuilder *builder, const uri_builder_test *test,
8478                                      DWORD test_index) {
8479     HRESULT hr;
8480     BOOL has_port = FALSE;
8481     DWORD received = -1;
8482
8483     if(test->port_prop.change) {
8484         DWORD expected = test->port_prop.value;
8485
8486         hr = IUriBuilder_GetPort(builder, &has_port, &received);
8487         if(test->port_prop.todo) {
8488             todo_wine {
8489                 ok(hr == S_OK,
8490                     "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8491                     hr, S_OK, test_index);
8492             }
8493             if(SUCCEEDED(hr)) {
8494                 todo_wine {
8495                     ok(has_port == test->port_prop.set,
8496                         "Error: Expected has_port to be %d but was %d instead on uri_builder_tests[%d].\n",
8497                         test->port_prop.set, has_port, test_index);
8498                 }
8499                 todo_wine {
8500                     ok(received == expected,
8501                         "Error: Expected received to be %d, but was %d instead on uri_builder_tests[%d].\n",
8502                         expected, received, test_index);
8503                 }
8504             }
8505         } else {
8506             ok(hr == S_OK,
8507                 "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8508                 hr, S_OK, test_index);
8509             ok(has_port == test->port_prop.set,
8510                 "Error: Expected has_port to be %d, but was %d instead on uri_builder_tests[%d].\n",
8511                 test->port_prop.set, has_port, test_index);
8512             ok(received == test->port_prop.value,
8513                 "Error: Expected port to be %d, but was %d instead on uri_builder_tests[%d].\n",
8514                 test->port_prop.value, received, test_index);
8515         }
8516     } else {
8517         IUri *uri = NULL;
8518
8519         hr = IUriBuilder_GetIUri(builder, &uri);
8520         ok(hr == S_OK,
8521             "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8522             hr, S_OK, test_index);
8523         if(SUCCEEDED(hr)) {
8524             if(!uri) {
8525                 hr = IUriBuilder_GetPort(builder, &has_port, &received);
8526                 ok(hr == S_OK,
8527                     "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8528                     hr, S_OK, test_index);
8529                 if(SUCCEEDED(hr)) {
8530                     ok(has_port == FALSE,
8531                         "Error: Expected has_port to be FALSE, but was %d instead on uri_builder_tests[%d].\n",
8532                         has_port, test_index);
8533                     ok(!received, "Error: Expected received to be 0, but was %d instead on uri_builder_tests[%d].\n",
8534                         received, test_index);
8535                 }
8536             } else {
8537                 DWORD expected;
8538
8539                 hr = IUri_GetPort(uri, &expected);
8540                 ok(SUCCEEDED(hr),
8541                     "Error: Expected IUri_Port to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
8542                     hr, test_index);
8543
8544                 hr = IUriBuilder_GetPort(builder, &has_port, &received);
8545                 ok(hr == S_OK,
8546                     "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8547                     hr, S_OK, test_index);
8548                 if(SUCCEEDED(hr)) {
8549                     ok(!has_port,
8550                         "Error: Expected has_port to be FALSE but was TRUE instead on uri_builder_tests[%d].\n",
8551                         test_index);
8552                     ok(received == expected,
8553                         "Error: Expected received to be %d, but was %d instead on uri_builder_tests[%d].\n",
8554                         expected, received, test_index);
8555                 }
8556             }
8557         }
8558         if(uri) IUri_Release(uri);
8559     }
8560 }
8561
8562 static void test_IUriBuilder_GetQuery(IUriBuilder *builder, const uri_builder_test *test,
8563                                       DWORD test_index) {
8564     HRESULT hr;
8565     DWORD i;
8566     LPCWSTR received = NULL;
8567     DWORD len = -1;
8568     const uri_builder_property *prop = NULL;
8569
8570     /* Check if the property was set earlier. */
8571     for(i = 0; i < sizeof(test->properties)/sizeof(test->properties[0]); ++i) {
8572         if(test->properties[i].change && test->properties[i].property == Uri_PROPERTY_QUERY)
8573             prop = &(test->properties[i]);
8574     }
8575
8576     if(prop) {
8577         /* Use expected_value unless it's NULL, then use value. */
8578         LPCSTR expected = prop->expected_value ? prop->expected_value : prop->value;
8579         hr = IUriBuilder_GetQuery(builder, &len, &received);
8580         if(prop->todo) {
8581             todo_wine {
8582                 ok(hr == (expected ? S_OK : S_FALSE),
8583                     "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8584                     hr, (expected ? S_OK : S_FALSE), test_index);
8585             }
8586             if(SUCCEEDED(hr)) {
8587                 todo_wine {
8588                     ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
8589                         expected, wine_dbgstr_w(received), test_index);
8590                 }
8591                 todo_wine {
8592                     ok(lstrlen(expected) == len,
8593                         "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8594                         lstrlen(expected), len, test_index);
8595                 }
8596             }
8597         } else {
8598             ok(hr == (expected ? S_OK : S_FALSE),
8599                 "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8600                 hr, (expected ? S_OK : S_FALSE), test_index);
8601             ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
8602                 expected, wine_dbgstr_w(received), test_index);
8603             ok(lstrlen(expected) == len,
8604                 "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8605                 lstrlen(expected), len, test_index);
8606         }
8607     } else {
8608         /* The property wasn't set earlier, so it should return whatever
8609          * the base IUri contains (if anything).
8610          */
8611         IUri *uri = NULL;
8612         hr = IUriBuilder_GetIUri(builder, &uri);
8613         ok(hr == S_OK,
8614             "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8615             hr, S_OK, test_index);
8616         if(SUCCEEDED(hr)) {
8617             if(!uri) {
8618                 received = (void*) 0xdeadbeef;
8619                 len = -1;
8620
8621                 hr = IUriBuilder_GetQuery(builder, &len, &received);
8622                 ok(hr == S_FALSE,
8623                     "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8624                     hr, S_FALSE, test_index);
8625                 if(SUCCEEDED(hr)) {
8626                     ok(!len, "Error: Expected len to be 0, but was %d instead on uri_builder_tests[%d].\n",
8627                         len, test_index);
8628                     ok(!received, "Error: Expected received to be NULL, but was %p instead on uri_builder_tests[%d].\n",
8629                         received, test_index);
8630                 }
8631             } else {
8632                 BOOL has_prop = FALSE;
8633                 BSTR expected = NULL;
8634
8635                 hr = IUri_GetQuery(uri, &expected);
8636                 ok(SUCCEEDED(hr),
8637                     "Error: Expected IUri_GetQuery to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
8638                     hr, test_index);
8639                 has_prop = hr == S_OK;
8640
8641                 hr = IUriBuilder_GetQuery(builder, &len, &received);
8642                 if(has_prop) {
8643                     ok(hr == S_OK,
8644                         "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8645                         hr, S_OK, test_index);
8646                     if(SUCCEEDED(hr)) {
8647                         ok(!lstrcmpW(expected, received),
8648                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].\n",
8649                             wine_dbgstr_w(expected), wine_dbgstr_w(received), test_index);
8650                         ok(lstrlenW(expected) == len,
8651                             "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8652                             lstrlenW(expected), len, test_index);
8653                     }
8654                 } else {
8655                     ok(hr == S_FALSE,
8656                         "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8657                         hr, S_FALSE, test_index);
8658                     if(SUCCEEDED(hr)) {
8659                         ok(!received, "Error: Expected received to be NULL on uri_builder_tests[%d].\n", test_index);
8660                         ok(!len, "Error: Expected the length to be 0, but was %d instead on uri_builder_tests[%d].\n",
8661                             len, test_index);
8662                     }
8663                 }
8664                 SysFreeString(expected);
8665             }
8666         }
8667         if(uri) IUri_Release(uri);
8668     }
8669 }
8670
8671 static void test_IUriBuilder_GetSchemeName(IUriBuilder *builder, const uri_builder_test *test,
8672                                            DWORD test_index) {
8673     HRESULT hr;
8674     DWORD i;
8675     LPCWSTR received = NULL;
8676     DWORD len = -1;
8677     const uri_builder_property *prop = NULL;
8678
8679     /* Check if the property was set earlier. */
8680     for(i = 0; i < sizeof(test->properties)/sizeof(test->properties[0]); ++i) {
8681         if(test->properties[i].change && test->properties[i].property == Uri_PROPERTY_SCHEME_NAME)
8682             prop = &(test->properties[i]);
8683     }
8684
8685     if(prop) {
8686         /* Use expected_value unless it's NULL, then use value. */
8687         LPCSTR expected = prop->expected_value ? prop->expected_value : prop->value;
8688         hr = IUriBuilder_GetSchemeName(builder, &len, &received);
8689         if(prop->todo) {
8690             todo_wine {
8691                 ok(hr == (expected ? S_OK : S_FALSE),
8692                     "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8693                     hr, (expected ? S_OK : S_FALSE), test_index);
8694             }
8695             if(SUCCEEDED(hr)) {
8696                 todo_wine {
8697                     ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
8698                         expected, wine_dbgstr_w(received), test_index);
8699                 }
8700                 todo_wine {
8701                     ok(lstrlen(expected) == len,
8702                         "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8703                         lstrlen(expected), len, test_index);
8704                 }
8705             }
8706         } else {
8707             ok(hr == (expected ? S_OK : S_FALSE),
8708                 "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8709                 hr, (expected ? S_OK : S_FALSE), test_index);
8710             ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
8711                 expected, wine_dbgstr_w(received), test_index);
8712             ok(lstrlen(expected) == len,
8713                 "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8714                 lstrlen(expected), len, test_index);
8715         }
8716     } else {
8717         /* The property wasn't set earlier, so it should return whatever
8718          * the base IUri contains (if anything).
8719          */
8720         IUri *uri = NULL;
8721         hr = IUriBuilder_GetIUri(builder, &uri);
8722         ok(hr == S_OK,
8723             "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8724             hr, S_OK, test_index);
8725         if(SUCCEEDED(hr)) {
8726             if(!uri) {
8727                 received = (void*) 0xdeadbeef;
8728                 len = -1;
8729
8730                 hr = IUriBuilder_GetSchemeName(builder, &len, &received);
8731                 ok(hr == S_FALSE,
8732                     "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8733                     hr, S_FALSE, test_index);
8734                 if(SUCCEEDED(hr)) {
8735                     ok(!len, "Error: Expected len to be 0, but was %d instead on uri_builder_tests[%d].\n",
8736                         len, test_index);
8737                     ok(!received, "Error: Expected received to be NULL, but was %p instead on uri_builder_tests[%d].\n",
8738                         received, test_index);
8739                 }
8740             } else {
8741                 BOOL has_prop = FALSE;
8742                 BSTR expected = NULL;
8743
8744                 hr = IUri_GetSchemeName(uri, &expected);
8745                 ok(SUCCEEDED(hr),
8746                     "Error: Expected IUri_GetSchemeName to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
8747                     hr, test_index);
8748                 has_prop = hr == S_OK;
8749
8750                 hr = IUriBuilder_GetSchemeName(builder, &len, &received);
8751                 if(has_prop) {
8752                     ok(hr == S_OK,
8753                         "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8754                         hr, S_OK, test_index);
8755                     if(SUCCEEDED(hr)) {
8756                         ok(!lstrcmpW(expected, received),
8757                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].\n",
8758                             wine_dbgstr_w(expected), wine_dbgstr_w(received), test_index);
8759                         ok(lstrlenW(expected) == len,
8760                             "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8761                             lstrlenW(expected), len, test_index);
8762                     }
8763                 } else {
8764                     ok(hr == S_FALSE,
8765                         "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8766                         hr, S_FALSE, test_index);
8767                     if(SUCCEEDED(hr)) {
8768                         ok(!received, "Error: Expected received to be NULL on uri_builder_tests[%d].\n", test_index);
8769                         ok(!len, "Error: Expected the length to be 0, but was %d instead on uri_builder_tests[%d].\n",
8770                             len, test_index);
8771                     }
8772                 }
8773                 SysFreeString(expected);
8774             }
8775         }
8776         if(uri) IUri_Release(uri);
8777     }
8778 }
8779
8780 static void test_IUriBuilder_GetUserName(IUriBuilder *builder, const uri_builder_test *test,
8781                                          DWORD test_index) {
8782     HRESULT hr;
8783     DWORD i;
8784     LPCWSTR received = NULL;
8785     DWORD len = -1;
8786     const uri_builder_property *prop = NULL;
8787
8788     /* Check if the property was set earlier. */
8789     for(i = 0; i < sizeof(test->properties)/sizeof(test->properties[0]); ++i) {
8790         if(test->properties[i].change && test->properties[i].property == Uri_PROPERTY_USER_NAME)
8791             prop = &(test->properties[i]);
8792     }
8793
8794     if(prop && prop->value && *prop->value) {
8795         /* Use expected_value unless it's NULL, then use value. */
8796         LPCSTR expected = prop->expected_value ? prop->expected_value : prop->value;
8797         hr = IUriBuilder_GetUserName(builder, &len, &received);
8798         if(prop->todo) {
8799             todo_wine {
8800                 ok(hr == (expected ? S_OK : S_FALSE),
8801                     "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8802                     hr, (expected ? S_OK : S_FALSE), test_index);
8803             }
8804             if(SUCCEEDED(hr)) {
8805                 todo_wine {
8806                     ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
8807                         expected, wine_dbgstr_w(received), test_index);
8808                 }
8809                 todo_wine {
8810                     ok(lstrlen(expected) == len,
8811                         "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8812                         lstrlen(expected), len, test_index);
8813                 }
8814             }
8815         } else {
8816             ok(hr == (expected ? S_OK : S_FALSE),
8817                 "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8818                 hr, (expected ? S_OK : S_FALSE), test_index);
8819             ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
8820                 expected, wine_dbgstr_w(received), test_index);
8821             ok(lstrlen(expected) == len,
8822                 "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8823                 lstrlen(expected), len, test_index);
8824         }
8825     } else {
8826         /* The property wasn't set earlier, so it should return whatever
8827          * the base IUri contains (if anything).
8828          */
8829         IUri *uri = NULL;
8830         hr = IUriBuilder_GetIUri(builder, &uri);
8831         ok(hr == S_OK,
8832             "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8833             hr, S_OK, test_index);
8834         if(SUCCEEDED(hr)) {
8835             if(!uri) {
8836                 received = (void*) 0xdeadbeef;
8837                 len = -1;
8838
8839                 hr = IUriBuilder_GetUserName(builder, &len, &received);
8840                 ok(hr == S_FALSE,
8841                     "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8842                     hr, S_FALSE, test_index);
8843                 if(SUCCEEDED(hr)) {
8844                     ok(!len, "Error: Expected len to be 0, but was %d instead on uri_builder_tests[%d].\n",
8845                         len, test_index);
8846                     ok(!received, "Error: Expected received to be NULL, but was %p instead on uri_builder_tests[%d].\n",
8847                         received, test_index);
8848                 }
8849             } else {
8850                 BSTR expected = NULL;
8851                 BOOL has_prop = FALSE;
8852
8853                 hr = IUri_GetUserName(uri, &expected);
8854                 ok(SUCCEEDED(hr),
8855                     "Error: Expected IUri_GetUserName to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
8856                     hr, test_index);
8857                 has_prop = hr == S_OK;
8858
8859                 hr = IUriBuilder_GetUserName(builder, &len, &received);
8860                 if(has_prop) {
8861                     ok(hr == S_OK,
8862                         "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8863                         hr, S_OK, test_index);
8864                     if(SUCCEEDED(hr)) {
8865                         ok(!lstrcmpW(expected, received),
8866                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].\n",
8867                             wine_dbgstr_w(expected), wine_dbgstr_w(received), test_index);
8868                         ok(lstrlenW(expected) == len,
8869                             "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8870                             lstrlenW(expected), len, test_index);
8871                     }
8872                 } else {
8873                     ok(hr == S_FALSE,
8874                         "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8875                         hr, S_FALSE, test_index);
8876                     if(SUCCEEDED(hr)) {
8877                         ok(!received, "Error: Expected received to be NULL on uri_builder_tests[%d].\n", test_index);
8878                         ok(!len, "Error: Expected the length to be 0, but was %d instead on uri_builder_tests[%d].\n",
8879                             len, test_index);
8880                     }
8881                 }
8882                 SysFreeString(expected);
8883             }
8884         }
8885         if(uri) IUri_Release(uri);
8886     }
8887 }
8888
8889 /* Tests IUriBuilder functions. */
8890 static void test_IUriBuilder(void) {
8891     HRESULT hr;
8892     IUriBuilder *builder;
8893     DWORD i;
8894
8895     for(i = 0; i < sizeof(uri_builder_tests)/sizeof(uri_builder_tests[0]); ++i) {
8896         IUri *uri = NULL;
8897         uri_builder_test test = uri_builder_tests[i];
8898         LPWSTR uriW = NULL;
8899
8900         if(test.uri) {
8901             uriW = a2w(test.uri);
8902             hr = pCreateUri(uriW, test.create_flags, 0, &uri);
8903             ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8904                 hr, S_OK, i);
8905             if(FAILED(hr)) continue;
8906         }
8907         hr = pCreateIUriBuilder(uri, 0, 0, &builder);
8908         if(test.create_builder_todo) {
8909             todo_wine {
8910                 ok(hr == test.create_builder_expected,
8911                     "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8912                     hr, test.create_builder_expected, i);
8913             }
8914         } else {
8915             ok(hr == test.create_builder_expected,
8916                 "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8917                 hr, test.create_builder_expected, i);
8918         }
8919         if(SUCCEEDED(hr)) {
8920             DWORD j;
8921             BOOL modified = FALSE, received = FALSE;
8922
8923             /* Perform all the string property changes. */
8924             for(j = 0; j < URI_BUILDER_STR_PROPERTY_COUNT; ++j) {
8925                 uri_builder_property prop = test.properties[j];
8926                 if(prop.change) {
8927                     change_property(builder, &prop, i);
8928                     if(prop.property != Uri_PROPERTY_SCHEME_NAME &&
8929                        prop.property != Uri_PROPERTY_HOST)
8930                         modified = TRUE;
8931                     else if(prop.value && *prop.value)
8932                         modified = TRUE;
8933                     else if(prop.value && !*prop.value && prop.property == Uri_PROPERTY_HOST)
8934                         /* Host name property can't be NULL, but it can be empty. */
8935                         modified = TRUE;
8936                 }
8937             }
8938
8939             if(test.port_prop.change) {
8940                 hr = IUriBuilder_SetPort(builder, test.port_prop.set, test.port_prop.value);
8941                 modified = TRUE;
8942                 if(test.port_prop.todo) {
8943                     todo_wine {
8944                         ok(hr == test.port_prop.expected,
8945                             "Error: IUriBuilder_SetPort returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8946                             hr, test.port_prop.expected, i);
8947                     }
8948                 } else {
8949                     ok(hr == test.port_prop.expected,
8950                         "Error: IUriBuilder_SetPort returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8951                         hr, test.port_prop.expected, i);
8952                 }
8953             }
8954
8955             hr = IUriBuilder_HasBeenModified(builder, &received);
8956             ok(hr == S_OK,
8957                 "Error IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8958                 hr, S_OK, i);
8959             if(SUCCEEDED(hr))
8960                 ok(received == modified,
8961                     "Error: Expected received to be %d but was %d instead on uri_builder_tests[%d].\n",
8962                     modified, received, i);
8963
8964             /* Test the "Get*" functions. */
8965             test_IUriBuilder_GetFragment(builder, &test, i);
8966             test_IUriBuilder_GetHost(builder, &test, i);
8967             test_IUriBuilder_GetPassword(builder, &test, i);
8968             test_IUriBuilder_GetPath(builder, &test, i);
8969             test_IUriBuilder_GetPort(builder, &test, i);
8970             test_IUriBuilder_GetQuery(builder, &test, i);
8971             test_IUriBuilder_GetSchemeName(builder, &test, i);
8972             test_IUriBuilder_GetUserName(builder, &test, i);
8973
8974             test_IUriBuilder_CreateUri(builder, &test, i);
8975             test_IUriBuilder_CreateUriSimple(builder, &test, i);
8976             test_IUriBuilder_CreateUriWithFlags(builder, &test, i);
8977         }
8978         if(builder) IUriBuilder_Release(builder);
8979         if(uri) IUri_Release(uri);
8980         heap_free(uriW);
8981     }
8982 }
8983
8984 static void test_IUriBuilder_HasBeenModified(void) {
8985     HRESULT hr;
8986     IUriBuilder *builder = NULL;
8987
8988     hr = pCreateIUriBuilder(NULL, 0, 0, &builder);
8989     ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8990     if(SUCCEEDED(hr)) {
8991         static const WCHAR hostW[] = {'g','o','o','g','l','e','.','c','o','m',0};
8992         IUri *uri = NULL;
8993         BOOL received;
8994
8995         hr = IUriBuilder_HasBeenModified(builder, NULL);
8996         ok(hr == E_POINTER, "Error: IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x.\n",
8997             hr, E_POINTER);
8998
8999         hr = IUriBuilder_SetHost(builder, hostW);
9000         ok(hr == S_OK, "Error: IUriBuilder_SetHost returned 0x%08x, expected 0x%08x.\n",
9001             hr, S_OK);
9002
9003         hr = IUriBuilder_HasBeenModified(builder, &received);
9004         ok(hr == S_OK, "Error: IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x.\n",
9005             hr, S_OK);
9006         if(SUCCEEDED(hr))
9007             ok(received == TRUE, "Error: Expected received to be TRUE.\n");
9008
9009         hr = pCreateUri(http_urlW, 0, 0, &uri);
9010         ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9011         if(SUCCEEDED(hr)) {
9012             LPCWSTR prop;
9013             DWORD len = -1;
9014
9015             hr = IUriBuilder_SetIUri(builder, uri);
9016             ok(hr == S_OK, "Error: IUriBuilder_SetIUri returned 0x%08x, expected 0x%08x.\n",
9017                 hr, S_OK);
9018
9019             hr = IUriBuilder_HasBeenModified(builder, &received);
9020             ok(hr == S_OK, "Error: IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x.\n",
9021                 hr, S_OK);
9022             if(SUCCEEDED(hr))
9023                 ok(received == FALSE, "Error: Expected received to be FALSE.\n");
9024
9025             /* Test what happens with you call SetIUri with the same IUri again. */
9026             hr = IUriBuilder_SetHost(builder, hostW);
9027             ok(hr == S_OK, "Error: IUriBuilder_SetHost returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9028
9029             hr = IUriBuilder_HasBeenModified(builder, &received);
9030             ok(hr == S_OK, "Error: IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x.\n",
9031                 hr, S_OK);
9032             if(SUCCEEDED(hr))
9033                 ok(received == TRUE, "Error: Expected received to be TRUE.\n");
9034
9035             hr = IUriBuilder_SetIUri(builder, uri);
9036             ok(hr == S_OK, "Error: IUriBuilder_SetIUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9037
9038             /* IUriBuilder already had 'uri' as it's IUri property and so Windows doesn't
9039              * reset any of the changes that were made to the IUriBuilder.
9040              */
9041             hr = IUriBuilder_HasBeenModified(builder, &received);
9042             ok(hr == S_OK, "Error: IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9043             if(SUCCEEDED(hr))
9044                 ok(received == TRUE, "Error: Expected received to be TRUE.\n");
9045
9046             hr = IUriBuilder_GetHost(builder, &len, &prop);
9047             ok(hr == S_OK, "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9048             if(SUCCEEDED(hr)) {
9049                 ok(!lstrcmpW(prop, hostW), "Error: Expected %s but got %s instead.\n",
9050                     wine_dbgstr_w(hostW), wine_dbgstr_w(prop));
9051                 ok(len == lstrlenW(hostW), "Error: Expected len to be %d, but was %d instead.\n",
9052                     lstrlenW(hostW), len);
9053             }
9054
9055             hr = IUriBuilder_SetIUri(builder, NULL);
9056             ok(hr == S_OK, "Error: IUriBuilder_SetIUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9057
9058             hr = IUriBuilder_SetHost(builder, hostW);
9059             ok(hr == S_OK, "Error: IUriBuilder_SetHost returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9060             hr = IUriBuilder_HasBeenModified(builder, &received);
9061             ok(hr == S_OK, "Error: IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x.\n",
9062                 hr, S_OK);
9063             if(SUCCEEDED(hr))
9064                 ok(received == TRUE, "Error: Expected received to be TRUE.\n");
9065
9066             hr = IUriBuilder_SetIUri(builder, NULL);
9067             ok(hr == S_OK, "Error: IUriBuilder_SetIUri returned 0x%08x, expected 0x%09x.\n", hr, S_OK);
9068
9069             hr = IUriBuilder_HasBeenModified(builder, &received);
9070             ok(hr == S_OK, "Error: IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x.\n",
9071                 hr, S_OK);
9072             if(SUCCEEDED(hr))
9073                 ok(received == TRUE, "Error: Expected received to be TRUE.\n");
9074
9075             hr = IUriBuilder_GetHost(builder, &len, &prop);
9076             ok(hr == S_OK, "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9077             if(SUCCEEDED(hr)) {
9078                 ok(!lstrcmpW(prop, hostW), "Error: Expected %s but got %s instead.\n",
9079                     wine_dbgstr_w(hostW), wine_dbgstr_w(prop));
9080                 ok(len == lstrlenW(hostW), "Error: Expected len to %d, but was %d instead.\n",
9081                     lstrlenW(hostW), len);
9082             }
9083         }
9084         if(uri) IUri_Release(uri);
9085     }
9086     if(builder) IUriBuilder_Release(builder);
9087 }
9088
9089 /* Test IUriBuilder {Get,Set}IUri functions. */
9090 static void test_IUriBuilder_IUriProperty(void) {
9091     IUriBuilder *builder = NULL;
9092     HRESULT hr;
9093
9094     hr = pCreateIUriBuilder(NULL, 0, 0, &builder);
9095     ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9096     if(SUCCEEDED(hr)) {
9097         IUri *uri = NULL;
9098
9099         hr = IUriBuilder_GetIUri(builder, NULL);
9100         ok(hr == E_POINTER, "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x.\n",
9101             hr, E_POINTER);
9102
9103         hr = pCreateUri(http_urlW, 0, 0, &uri);
9104         if(SUCCEEDED(hr)) {
9105             IUri *test = NULL;
9106             ULONG cur_count, orig_count;
9107
9108             /* IUriBuilder doesn't clone the IUri, it use the same IUri. */
9109             orig_count = get_refcnt(uri);
9110             hr = IUriBuilder_SetIUri(builder, uri);
9111             cur_count = get_refcnt(uri);
9112             if(SUCCEEDED(hr))
9113                 ok(cur_count == orig_count+1, "Error: Expected uri ref count to be %d, but was %d instead.\n",
9114                     orig_count+1, cur_count);
9115
9116             hr = IUriBuilder_SetIUri(builder, NULL);
9117             cur_count = get_refcnt(uri);
9118             if(SUCCEEDED(hr))
9119                 ok(cur_count == orig_count, "Error: Expected uri ref count to be %d, but was %d instead.\n",
9120                     orig_count, cur_count);
9121
9122             /* CreateUri* functions will return back the same IUri if nothing has changed. */
9123             hr = IUriBuilder_SetIUri(builder, uri);
9124             ok(hr == S_OK, "Error: IUriBuilder_SetIUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9125             orig_count = get_refcnt(uri);
9126
9127             hr = IUriBuilder_CreateUri(builder, 0, 0, 0, &test);
9128             ok(hr == S_OK, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9129             if(SUCCEEDED(hr)) {
9130                 cur_count = get_refcnt(uri);
9131                 ok(cur_count == orig_count+1, "Error: Expected uri ref count to be %d, but was %d instead.\n",
9132                     orig_count+1, cur_count);
9133                 ok(test == uri, "Error: Expected test to be %p, but was %p instead.\n",
9134                     uri, test);
9135             }
9136             if(test) IUri_Release(test);
9137
9138             test = NULL;
9139             hr = IUriBuilder_CreateUri(builder, -1, 0, 0, &test);
9140             ok(hr == S_OK, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9141             if(SUCCEEDED(hr)) {
9142                 cur_count = get_refcnt(uri);
9143                 ok(cur_count == orig_count+1, "Error: Expected uri ref count to be %d, but was %d instead.\n",
9144                     orig_count+1, cur_count);
9145                 ok(test == uri, "Error: Expected test to be %p, but was %p instead.\n", uri, test);
9146             }
9147             if(test) IUri_Release(test);
9148
9149             /* Doesn't return the same IUri, if the flag combination is different then the one that created
9150              * the base IUri.
9151              */
9152             test = NULL;
9153             hr = IUriBuilder_CreateUri(builder, Uri_CREATE_ALLOW_RELATIVE, 0, 0, &test);
9154             ok(hr == S_OK, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9155             if(SUCCEEDED(hr))
9156                 ok(test != uri, "Error: Wasn't expecting 'test' to be 'uri'\n");
9157
9158             if(test) IUri_Release(test);
9159
9160             /* Still returns the same IUri, even though the base one wasn't created with CREATE_CANONICALIZE
9161              * explicitly set (because it's a default flags).
9162              */
9163             test = NULL;
9164             hr = IUriBuilder_CreateUri(builder, Uri_CREATE_CANONICALIZE, 0, 0, &test);
9165             ok(hr == S_OK, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9166             if(SUCCEEDED(hr)) {
9167                 cur_count = get_refcnt(uri);
9168                 ok(cur_count == orig_count+1, "Error: Expected uri ref count to be %d, but was %d instead.\n",
9169                     orig_count+1, cur_count);
9170                 ok(test == uri, "Error: Expected 'test' to be %p, but was %p instead.\n", uri, test);
9171             }
9172             if(test) IUri_Release(test);
9173
9174             test = NULL;
9175             hr = IUriBuilder_CreateUriSimple(builder, 0, 0, &test);
9176             ok(hr == S_OK, "Error: IUriBuilder_CreateUriSimple returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9177             if(SUCCEEDED(hr)) {
9178                 cur_count = get_refcnt(uri);
9179                 ok(cur_count == orig_count+1, "Error: Expected uri ref count to be %d, but was %d instead.\n",
9180                     orig_count+1, cur_count);
9181                 ok(test == uri, "Error: Expected test to be %p, but was %p instead.\n", uri, test);
9182             }
9183             if(test) IUri_Release(test);
9184
9185             test = NULL;
9186             hr = IUriBuilder_CreateUriWithFlags(builder, 0, 0, 0, 0, &test);
9187             ok(hr == S_OK, "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x.\n",
9188                 hr, S_OK);
9189             if(SUCCEEDED(hr)) {
9190                 cur_count = get_refcnt(uri);
9191                 ok(cur_count == orig_count+1, "Error: Expected uri ref count to be %d, but was %d instead.\n",
9192                     orig_count+1, cur_count);
9193                 ok(test == uri, "Error: Expected test to be %p, but was %p instead.\n", uri, test);
9194             }
9195             if(test) IUri_Release(test);
9196
9197             /* Doesn't return the same IUri, if the flag combination is different then the one that created
9198              * the base IUri.
9199              */
9200             test = NULL;
9201             hr = IUriBuilder_CreateUriWithFlags(builder, Uri_CREATE_ALLOW_RELATIVE, 0, 0, 0, &test);
9202             ok(hr == S_OK, "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9203             if(SUCCEEDED(hr))
9204                 ok(test != uri, "Error: Wasn't expecting 'test' to be 'uri'\n");
9205
9206             if(test) IUri_Release(test);
9207
9208             /* Still returns the same IUri, even though the base one wasn't created with CREATE_CANONICALIZE
9209              * explicitly set (because it's a default flags).
9210              */
9211             test = NULL;
9212             hr = IUriBuilder_CreateUriWithFlags(builder, Uri_CREATE_CANONICALIZE, 0, 0, 0, &test);
9213             ok(hr == S_OK, "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9214             if(SUCCEEDED(hr)) {
9215                 cur_count = get_refcnt(uri);
9216                 ok(cur_count == orig_count+1, "Error: Expected uri ref count to be %d, but was %d instead.\n",
9217                     orig_count+1, cur_count);
9218                 ok(test == uri, "Error: Expected 'test' to be %p, but was %p instead.\n", uri, test);
9219             }
9220             if(test) IUri_Release(test);
9221         }
9222         if(uri) IUri_Release(uri);
9223     }
9224     if(builder) IUriBuilder_Release(builder);
9225 }
9226
9227 static void test_IUriBuilder_RemoveProperties(void) {
9228     IUriBuilder *builder = NULL;
9229     HRESULT hr;
9230     DWORD i;
9231
9232     hr = pCreateIUriBuilder(NULL, 0, 0, &builder);
9233     ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9234     if(SUCCEEDED(hr)) {
9235         /* Properties that can't be removed. */
9236         const DWORD invalid = Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_RAW_URI|Uri_HAS_HOST_TYPE|
9237                               Uri_HAS_SCHEME|Uri_HAS_ZONE;
9238
9239         for(i = Uri_PROPERTY_STRING_START; i <= Uri_PROPERTY_DWORD_LAST; ++i) {
9240             hr = IUriBuilder_RemoveProperties(builder, i << 1);
9241             if((i << 1) & invalid) {
9242                 ok(hr == E_INVALIDARG,
9243                     "Error: IUriBuilder_RemoveProperties returned 0x%08x, expected 0x%08x with prop=%d.\n",
9244                     hr, E_INVALIDARG, i);
9245             } else {
9246                 ok(hr == S_OK,
9247                     "Error: IUriBuilder_RemoveProperties returned 0x%08x, expected 0x%08x with prop=%d.\n",
9248                     hr, S_OK, i);
9249             }
9250         }
9251
9252         /* Also doesn't accept anything that's outside the range of the
9253          * Uri_HAS flags.
9254          */
9255         hr = IUriBuilder_RemoveProperties(builder, (Uri_PROPERTY_DWORD_LAST+1) << 1);
9256         ok(hr == E_INVALIDARG, "Error: IUriBuilder_RemoveProperties returned 0x%08x, expected 0x%08x.\n",
9257             hr, E_INVALIDARG);
9258     }
9259     if(builder) IUriBuilder_Release(builder);
9260
9261     for(i = 0; i < sizeof(uri_builder_remove_tests)/sizeof(uri_builder_remove_tests[0]); ++i) {
9262         uri_builder_remove_test test = uri_builder_remove_tests[i];
9263         IUri *uri = NULL;
9264         LPWSTR uriW;
9265
9266         uriW = a2w(test.uri);
9267         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
9268         if(SUCCEEDED(hr)) {
9269             builder = NULL;
9270
9271             hr = pCreateIUriBuilder(uri, 0, 0, &builder);
9272             if(test.create_builder_todo) {
9273                 todo_wine {
9274                     ok(hr == test.create_builder_expected,
9275                         "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x on test %d.\n",
9276                         hr, test.create_builder_expected, i);
9277                 }
9278             } else {
9279                 ok(hr == test.create_builder_expected,
9280                     "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x on test %d.\n",
9281                     hr, test.create_builder_expected, i);
9282             }
9283             if(SUCCEEDED(hr)) {
9284                 hr = IUriBuilder_RemoveProperties(builder, test.remove_properties);
9285                 if(test.remove_todo) {
9286                     todo_wine {
9287                         ok(hr == test.remove_expected,
9288                             "Error: IUriBuilder_RemoveProperties returned 0x%08x, expected 0x%08x on test %d.\n",
9289                             hr, test.remove_expected, i);
9290                     }
9291                 } else {
9292                     ok(hr == test.remove_expected,
9293                         "Error: IUriBuilder returned 0x%08x, expected 0x%08x on test %d.\n",
9294                         hr, test.remove_expected, i);
9295                 }
9296                 if(SUCCEEDED(hr)) {
9297                     IUri *result = NULL;
9298
9299                     hr = IUriBuilder_CreateUri(builder, test.expected_flags, 0, 0, &result);
9300                     if(test.expected_todo) {
9301                         todo_wine {
9302                             ok(hr == test.expected_hres,
9303                                 "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x on test %d.\n",
9304                                 hr, test.expected_hres, i);
9305                         }
9306                     } else {
9307                         ok(hr == test.expected_hres,
9308                             "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x on test %d.\n",
9309                             hr, test.expected_hres, i);
9310                     }
9311                     if(SUCCEEDED(hr)) {
9312                         BSTR received = NULL;
9313
9314                         hr = IUri_GetAbsoluteUri(result, &received);
9315                         ok(!strcmp_aw(test.expected_uri, received),
9316                             "Error: Expected %s but got %s instead on test %d.\n",
9317                             test.expected_uri, wine_dbgstr_w(received), i);
9318                         SysFreeString(received);
9319                     }
9320                     if(result) IUri_Release(result);
9321                 }
9322             }
9323             if(builder) IUriBuilder_Release(builder);
9324         }
9325         if(uri) IUri_Release(uri);
9326         heap_free(uriW);
9327     }
9328 }
9329
9330 static void test_IUriBuilder_Misc(void) {
9331     HRESULT hr;
9332     IUri *uri;
9333
9334     hr = pCreateUri(http_urlW, 0, 0, &uri);
9335     if(SUCCEEDED(hr)) {
9336         IUriBuilder *builder;
9337
9338         hr = pCreateIUriBuilder(uri, 0, 0, &builder);
9339         ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9340         if(SUCCEEDED(hr)) {
9341             BOOL has = -1;
9342             DWORD port = -1;
9343
9344             hr = IUriBuilder_GetPort(builder, &has, &port);
9345             ok(hr == S_OK, "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9346             if(SUCCEEDED(hr)) {
9347                 /* 'has' will be set to FALSE, even though uri had a port. */
9348                 ok(has == FALSE, "Error: Expected 'has' to be FALSE, was %d instead.\n", has);
9349                 /* Still sets 'port' to 80. */
9350                 ok(port == 80, "Error: Expected the port to be 80, but, was %d instead.\n", port);
9351             }
9352         }
9353         if(builder) IUriBuilder_Release(builder);
9354     }
9355     if(uri) IUri_Release(uri);
9356 }
9357
9358 static void test_CoInternetCombineIUri(void) {
9359     HRESULT hr;
9360     IUri *base, *relative, *result;
9361     DWORD i;
9362
9363     base = NULL;
9364     hr = pCreateUri(http_urlW, 0, 0, &base);
9365     ok(SUCCEEDED(hr), "Error: Expected CreateUri to succeed, got 0x%08x.\n", hr);
9366     if(SUCCEEDED(hr)) {
9367         result = (void*) 0xdeadbeef;
9368         hr = pCoInternetCombineIUri(base, NULL, 0, &result, 0);
9369         ok(hr == E_INVALIDARG, "Error: CoInternetCombineIUri returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
9370         ok(!result, "Error: Expected 'result' to be NULL, was %p.\n", result);
9371     }
9372
9373     relative = NULL;
9374     hr = pCreateUri(http_urlW, 0, 0, &relative);
9375     ok(SUCCEEDED(hr), "Error: Expected CreateUri to succeed, got 0x%08x.\n", hr);
9376     if(SUCCEEDED(hr)) {
9377         result = (void*) 0xdeadbeef;
9378         hr = pCoInternetCombineIUri(NULL, relative, 0, &result, 0);
9379         ok(hr == E_INVALIDARG, "Error: CoInternetCombineIUri returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
9380         ok(!result, "Error: Expected 'result' to be NULL, was %p.\n", result);
9381     }
9382
9383     hr = pCoInternetCombineIUri(base, relative, 0, NULL, 0);
9384     ok(hr == E_INVALIDARG, "Error: CoInternetCombineIUri returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
9385
9386     if(base) IUri_Release(base);
9387     if(relative) IUri_Release(relative);
9388
9389     for(i = 0; i < sizeof(uri_combine_tests)/sizeof(uri_combine_tests[0]); ++i) {
9390         LPWSTR baseW = a2w(uri_combine_tests[i].base_uri);
9391
9392         hr = pCreateUri(baseW, uri_combine_tests[i].base_create_flags, 0, &base);
9393         ok(SUCCEEDED(hr), "Error: Expected CreateUri to succeed, got 0x%08x on uri_combine_tests[%d].\n", hr, i);
9394         if(SUCCEEDED(hr)) {
9395             LPWSTR relativeW = a2w(uri_combine_tests[i].relative_uri);
9396
9397             hr = pCreateUri(relativeW, uri_combine_tests[i].relative_create_flags, 0, &relative);
9398             ok(SUCCEEDED(hr), "Error: Expected CreateUri to succeed, got 0x%08x on uri_combine_tests[%d].\n", hr, i);
9399             if(SUCCEEDED(hr)) {
9400                 result = NULL;
9401
9402                 hr = pCoInternetCombineIUri(base, relative, uri_combine_tests[i].combine_flags, &result, 0);
9403                 if(uri_combine_tests[i].todo) {
9404                     todo_wine {
9405                         ok(hr == uri_combine_tests[i].expected,
9406                             "Error: CoInternetCombineIUri returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].\n",
9407                             hr, uri_combine_tests[i].expected, i);
9408                     }
9409                 } else {
9410                     ok(hr == uri_combine_tests[i].expected,
9411                         "Error: CoInternetCombineIUri returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].\n",
9412                         hr, uri_combine_tests[i]. expected, i);
9413                 }
9414                 if(SUCCEEDED(hr)) {
9415                     DWORD j;
9416
9417                     for(j = 0; j < sizeof(uri_combine_tests[i].str_props)/sizeof(uri_combine_tests[i].str_props[0]); ++j) {
9418                         uri_str_property prop = uri_combine_tests[i].str_props[j];
9419                         BSTR received;
9420
9421                         hr = IUri_GetPropertyBSTR(result, j, &received, 0);
9422                         if(prop.todo) {
9423                             todo_wine {
9424                                 ok(hr == prop.expected,
9425                                     "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].str_props[%d].\n",
9426                                     hr, prop.expected, i, j);
9427                             }
9428                             todo_wine {
9429                                 ok(!strcmp_aw(prop.value, received) ||
9430                                    broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
9431                                     "Error: Expected %s but got %s instead on uri_combine_tests[%d].str_props[%d].\n",
9432                                     prop.value, wine_dbgstr_w(received), i, j);
9433                             }
9434                         } else {
9435                             ok(hr == prop.expected,
9436                                 "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].str_props[%d].\n",
9437                                 hr, prop.expected, i, j);
9438                             ok(!strcmp_aw(prop.value, received) ||
9439                                broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
9440                                 "Error: Expected %s but got %s instead on uri_combine_tests[%d].str_props[%d].\n",
9441                                 prop.value, wine_dbgstr_w(received), i, j);
9442                         }
9443                         SysFreeString(received);
9444                     }
9445
9446                     for(j = 0; j < sizeof(uri_combine_tests[i].dword_props)/sizeof(uri_combine_tests[i].dword_props[0]); ++j) {
9447                         uri_dword_property prop = uri_combine_tests[i].dword_props[j];
9448                         DWORD received;
9449
9450                         hr = IUri_GetPropertyDWORD(result, j+Uri_PROPERTY_DWORD_START, &received, 0);
9451                         if(prop.todo) {
9452                             todo_wine {
9453                                 ok(hr == prop.expected,
9454                                     "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].dword_props[%d].\n",
9455                                     hr, prop.expected, i, j);
9456                             }
9457                             todo_wine {
9458                                 ok(prop.value == received, "Error: Expected %d, but got %d instead on uri_combine_tests[%d].dword_props[%d].\n",
9459                                     prop.value, received, i, j);
9460                             }
9461                         } else {
9462                             ok(hr == prop.expected,
9463                                 "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].dword_props[%d].\n",
9464                                 hr, prop.expected, i, j);
9465                             ok(prop.value == received, "Error: Expected %d, but got %d instead on uri_combine_tests[%d].dword_props[%d].\n",
9466                                 prop.value, received, i, j);
9467                         }
9468                     }
9469                 }
9470                 if(result) IUri_Release(result);
9471             }
9472             if(relative) IUri_Release(relative);
9473             heap_free(relativeW);
9474         }
9475         if(base) IUri_Release(base);
9476         heap_free(baseW);
9477     }
9478 }
9479
9480 START_TEST(uri) {
9481     HMODULE hurlmon;
9482
9483     hurlmon = GetModuleHandle("urlmon.dll");
9484     pCreateUri = (void*) GetProcAddress(hurlmon, "CreateUri");
9485     pCreateUriWithFragment = (void*) GetProcAddress(hurlmon, "CreateUriWithFragment");
9486     pCreateIUriBuilder = (void*) GetProcAddress(hurlmon, "CreateIUriBuilder");
9487     pCoInternetCombineIUri = (void*) GetProcAddress(hurlmon, "CoInternetCombineIUri");
9488
9489     if(!pCreateUri) {
9490         win_skip("CreateUri is not present, skipping tests.\n");
9491         return;
9492     }
9493
9494     trace("test CreateUri invalid flags...\n");
9495     test_CreateUri_InvalidFlags();
9496
9497     trace("test CreateUri invalid args...\n");
9498     test_CreateUri_InvalidArgs();
9499
9500     trace("test CreateUri invalid URIs...\n");
9501     test_CreateUri_InvalidUri();
9502
9503     trace("test IUri_GetPropertyBSTR...\n");
9504     test_IUri_GetPropertyBSTR();
9505
9506     trace("test IUri_GetPropertyDWORD...\n");
9507     test_IUri_GetPropertyDWORD();
9508
9509     trace("test IUri_GetStrProperties...\n");
9510     test_IUri_GetStrProperties();
9511
9512     trace("test IUri_GetDwordProperties...\n");
9513     test_IUri_GetDwordProperties();
9514
9515     trace("test IUri_GetPropertyLength...\n");
9516     test_IUri_GetPropertyLength();
9517
9518     trace("test IUri_GetProperties...\n");
9519     test_IUri_GetProperties();
9520
9521     trace("test IUri_HasProperty...\n");
9522     test_IUri_HasProperty();
9523
9524     trace("test IUri_IsEqual...\n");
9525     test_IUri_IsEqual();
9526
9527     trace("test CreateUriWithFragment invalid args...\n");
9528     test_CreateUriWithFragment_InvalidArgs();
9529
9530     trace("test CreateUriWithFragment invalid flags...\n");
9531     test_CreateUriWithFragment_InvalidFlags();
9532
9533     trace("test CreateUriWithFragment...\n");
9534     test_CreateUriWithFragment();
9535
9536     trace("test CreateIUriBuilder...\n");
9537     test_CreateIUriBuilder();
9538
9539     trace("test IUriBuilder_CreateInvalidArgs...\n");
9540     test_IUriBuilder_CreateInvalidArgs();
9541
9542     trace("test IUriBuilder...\n");
9543     test_IUriBuilder();
9544
9545     trace("test IUriBuilder_GetInvalidArgs...\n");
9546     test_IUriBuilder_GetInvalidArgs();
9547
9548     trace("test IUriBuilder_HasBeenModified...\n");
9549     test_IUriBuilder_HasBeenModified();
9550
9551     trace("test IUriBuilder_IUriProperty...\n");
9552     test_IUriBuilder_IUriProperty();
9553
9554     trace("test IUriBuilder_RemoveProperties...\n");
9555     test_IUriBuilder_RemoveProperties();
9556
9557     trace("test IUriBuilder miscellaneous...\n");
9558     test_IUriBuilder_Misc();
9559
9560     trace("test CoInternetCombineIUri...\n");
9561     test_CoInternetCombineIUri();
9562 }