urlmon: Improved url canonicalize when Uri_CREATE_FILE_USE_DOS_PATH is specified.
[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
40 static const WCHAR http_urlW[] = { 'h','t','t','p',':','/','/','w','w','w','.','w','i','n','e','h','q',
41         '.','o','r','g','/',0};
42 static const WCHAR http_url_fragW[] = { 'h','t','t','p',':','/','/','w','w','w','.','w','i','n','e','h','q',
43         '.','o','r','g','/','#','F','r','a','g',0};
44
45 typedef struct _uri_create_flag_test {
46     DWORD   flags;
47     HRESULT expected;
48 } uri_create_flag_test;
49
50 static const uri_create_flag_test invalid_flag_tests[] = {
51     /* Set of invalid flag combinations to test for. */
52     {Uri_CREATE_DECODE_EXTRA_INFO | Uri_CREATE_NO_DECODE_EXTRA_INFO, E_INVALIDARG},
53     {Uri_CREATE_CANONICALIZE | Uri_CREATE_NO_CANONICALIZE, E_INVALIDARG},
54     {Uri_CREATE_CRACK_UNKNOWN_SCHEMES | Uri_CREATE_NO_CRACK_UNKNOWN_SCHEMES, E_INVALIDARG},
55     {Uri_CREATE_PRE_PROCESS_HTML_URI | Uri_CREATE_NO_PRE_PROCESS_HTML_URI, E_INVALIDARG},
56     {Uri_CREATE_IE_SETTINGS | Uri_CREATE_NO_IE_SETTINGS, E_INVALIDARG}
57 };
58
59 typedef struct _uri_str_property {
60     const char* value;
61     HRESULT     expected;
62     BOOL        todo;
63     const char* broken_value;
64 } uri_str_property;
65
66 typedef struct _uri_dword_property {
67     DWORD   value;
68     HRESULT expected;
69     BOOL    todo;
70 } uri_dword_property;
71
72 typedef struct _uri_properties {
73     const char*         uri;
74     DWORD               create_flags;
75     HRESULT             create_expected;
76     BOOL                create_todo;
77     DWORD               props;
78     BOOL                props_todo;
79
80     uri_str_property    str_props[URI_STR_PROPERTY_COUNT];
81     uri_dword_property  dword_props[URI_DWORD_PROPERTY_COUNT];
82 } uri_properties;
83
84 static const uri_properties uri_tests[] = {
85     {   "http://www.winehq.org/tests/../tests/../..", 0, S_OK, FALSE,
86         /* A flag bitmap containing all the Uri_HAS_* flags that correspond to this uri. */
87         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_HOST|
88         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|
89         Uri_HAS_PORT|Uri_HAS_SCHEME,
90         FALSE,
91         {
92             {"http://www.winehq.org/",S_OK,FALSE},                      /* ABSOLUTE_URI */
93             {"www.winehq.org",S_OK,FALSE},                              /* AUTHORITY */
94             {"http://www.winehq.org/",S_OK,FALSE},                      /* DISPLAY_URI */
95             {"winehq.org",S_OK,FALSE},                                  /* DOMAIN */
96             {"",S_FALSE,FALSE},                                         /* EXTENSION */
97             {"",S_FALSE,FALSE},                                         /* FRAGMENT */
98             {"www.winehq.org",S_OK,FALSE},                              /* HOST */
99             {"",S_FALSE,FALSE},                                         /* PASSWORD */
100             {"/",S_OK,FALSE},                                           /* PATH */
101             {"/",S_OK,FALSE},                                           /* PATH_AND_QUERY */
102             {"",S_FALSE,FALSE},                                         /* QUERY */
103             {"http://www.winehq.org/tests/../tests/../..",S_OK,FALSE},  /* RAW_URI */
104             {"http",S_OK,FALSE},                                        /* SCHEME_NAME */
105             {"",S_FALSE,FALSE},                                         /* USER_INFO */
106             {"",S_FALSE,FALSE}                                          /* USER_NAME */
107         },
108         {
109             {Uri_HOST_DNS,S_OK,FALSE},                                  /* HOST_TYPE */
110             {80,S_OK,FALSE},                                            /* PORT */
111             {URL_SCHEME_HTTP,S_OK,FALSE},                               /* SCHEME */
112             {URLZONE_INVALID,E_NOTIMPL,FALSE}                           /* ZONE */
113         }
114     },
115     {   "http://winehq.org/tests/.././tests", 0, S_OK, FALSE,
116         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_HOST|
117         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|
118         Uri_HAS_PORT|Uri_HAS_SCHEME,
119         FALSE,
120         {
121             {"http://winehq.org/tests",S_OK,FALSE},
122             {"winehq.org",S_OK,FALSE},
123             {"http://winehq.org/tests",S_OK,FALSE},
124             {"winehq.org",S_OK,FALSE},
125             {"",S_FALSE,FALSE},
126             {"",S_FALSE,FALSE},
127             {"winehq.org",S_OK,FALSE},
128             {"",S_FALSE,FALSE},
129             {"/tests",S_OK,FALSE},
130             {"/tests",S_OK,FALSE},
131             {"",S_FALSE,FALSE},
132             {"http://winehq.org/tests/.././tests",S_OK,FALSE},
133             {"http",S_OK,FALSE},
134             {"",S_FALSE,FALSE},
135             {"",S_FALSE,FALSE}
136         },
137         {
138             {Uri_HOST_DNS,S_OK,FALSE},
139             {80,S_OK,FALSE},
140             {URL_SCHEME_HTTP,S_OK,FALSE},
141             {URLZONE_INVALID,E_NOTIMPL,FALSE}
142         }
143     },
144     {   "HtTp://www.winehq.org/tests/..?query=x&return=y", 0, S_OK, FALSE,
145         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_HOST|
146         Uri_HAS_DOMAIN|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_QUERY|Uri_HAS_RAW_URI|
147         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
148         FALSE,
149         {
150             {"http://www.winehq.org/?query=x&return=y",S_OK,FALSE},
151             {"www.winehq.org",S_OK,FALSE},
152             {"http://www.winehq.org/?query=x&return=y",S_OK,FALSE},
153             {"winehq.org",S_OK,FALSE},
154             {"",S_FALSE,FALSE},
155             {"",S_FALSE,FALSE},
156             {"www.winehq.org",S_OK,FALSE},
157             {"",S_FALSE,FALSE},
158             {"/",S_OK,FALSE},
159             {"/?query=x&return=y",S_OK,FALSE},
160             {"?query=x&return=y",S_OK,FALSE},
161             {"HtTp://www.winehq.org/tests/..?query=x&return=y",S_OK,FALSE},
162             {"http",S_OK,FALSE},
163             {"",S_FALSE,FALSE},
164             {"",S_FALSE,FALSE}
165         },
166         {
167             {Uri_HOST_DNS,S_OK,FALSE},
168             {80,S_OK,FALSE},
169             {URL_SCHEME_HTTP,S_OK,FALSE},
170             {URLZONE_INVALID,E_NOTIMPL,FALSE},
171         }
172     },
173     {   "hTTp://us%45r%3Ainfo@examp%4CE.com:80/path/a/b/./c/../%2E%2E/Forbidden'<|> Characters", 0, S_OK, FALSE,
174         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_HOST|Uri_HAS_PATH|
175         Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_USER_INFO|Uri_HAS_USER_NAME|
176         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
177         FALSE,
178         {
179             {"http://usEr%3Ainfo@example.com/path/a/Forbidden'%3C%7C%3E%20Characters",S_OK,FALSE},
180             {"usEr%3Ainfo@example.com",S_OK,FALSE},
181             {"http://example.com/path/a/Forbidden'%3C%7C%3E%20Characters",S_OK,FALSE},
182             {"example.com",S_OK,FALSE},
183             {"",S_FALSE,FALSE},
184             {"",S_FALSE,FALSE},
185             {"example.com",S_OK,FALSE},
186             {"",S_FALSE,FALSE},
187             {"/path/a/Forbidden'%3C%7C%3E%20Characters",S_OK,FALSE},
188             {"/path/a/Forbidden'%3C%7C%3E%20Characters",S_OK,FALSE},
189             {"",S_FALSE,FALSE},
190             {"hTTp://us%45r%3Ainfo@examp%4CE.com:80/path/a/b/./c/../%2E%2E/Forbidden'<|> Characters",S_OK,FALSE},
191             {"http",S_OK,FALSE},
192             {"usEr%3Ainfo",S_OK,FALSE},
193             {"usEr%3Ainfo",S_OK,FALSE}
194         },
195         {
196             {Uri_HOST_DNS,S_OK,FALSE},
197             {80,S_OK,FALSE},
198             {URL_SCHEME_HTTP,S_OK,FALSE},
199             {URLZONE_INVALID,E_NOTIMPL,FALSE},
200         }
201     },
202     {   "ftp://winepass:wine@ftp.winehq.org:9999/dir/foo bar.txt", 0, S_OK, FALSE,
203         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_EXTENSION|
204         Uri_HAS_HOST|Uri_HAS_PASSWORD|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
205         Uri_HAS_SCHEME_NAME|Uri_HAS_USER_INFO|Uri_HAS_USER_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|
206         Uri_HAS_SCHEME,
207         FALSE,
208         {
209             {"ftp://winepass:wine@ftp.winehq.org:9999/dir/foo%20bar.txt",S_OK,FALSE},
210             {"winepass:wine@ftp.winehq.org:9999",S_OK,FALSE},
211             {"ftp://ftp.winehq.org:9999/dir/foo%20bar.txt",S_OK,FALSE},
212             {"winehq.org",S_OK,FALSE},
213             {".txt",S_OK,FALSE},
214             {"",S_FALSE,FALSE},
215             {"ftp.winehq.org",S_OK,FALSE},
216             {"wine",S_OK,FALSE},
217             {"/dir/foo%20bar.txt",S_OK,FALSE},
218             {"/dir/foo%20bar.txt",S_OK,FALSE},
219             {"",S_FALSE,FALSE},
220             {"ftp://winepass:wine@ftp.winehq.org:9999/dir/foo bar.txt",S_OK,FALSE},
221             {"ftp",S_OK,FALSE},
222             {"winepass:wine",S_OK,FALSE},
223             {"winepass",S_OK,FALSE}
224         },
225         {
226             {Uri_HOST_DNS,S_OK,FALSE},
227             {9999,S_OK,FALSE},
228             {URL_SCHEME_FTP,S_OK,FALSE},
229             {URLZONE_INVALID,E_NOTIMPL,FALSE}
230         }
231     },
232     {   "file://c:\\tests\\../tests/foo%20bar.mp3", 0, S_OK, FALSE,
233         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH|
234         Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
235         FALSE,
236         {
237             {"file:///c:/tests/foo%2520bar.mp3",S_OK,FALSE},
238             {"",S_FALSE,FALSE},
239             {"file:///c:/tests/foo%2520bar.mp3",S_OK,FALSE},
240             {"",S_FALSE,FALSE},
241             {".mp3",S_OK,FALSE},
242             {"",S_FALSE,FALSE},
243             {"",S_FALSE,FALSE},
244             {"",S_FALSE,FALSE},
245             {"/c:/tests/foo%2520bar.mp3",S_OK,FALSE},
246             {"/c:/tests/foo%2520bar.mp3",S_OK,FALSE},
247             {"",S_FALSE,FALSE},
248             {"file://c:\\tests\\../tests/foo%20bar.mp3",S_OK,FALSE},
249             {"file",S_OK,FALSE},
250             {"",S_FALSE,FALSE},
251             {"",S_FALSE,FALSE}
252         },
253         {
254             {Uri_HOST_UNKNOWN,S_OK,FALSE},
255             {0,S_FALSE,FALSE},
256             {URL_SCHEME_FILE,S_OK,FALSE},
257             {URLZONE_INVALID,E_NOTIMPL,FALSE}
258         }
259     },
260     {   "FILE://localhost/test dir\\../tests/test%20file.README.txt", 0, S_OK, FALSE,
261         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH|
262         Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
263         FALSE,
264         {
265             {"file:///tests/test%20file.README.txt",S_OK,FALSE},
266             {"",S_FALSE,FALSE},
267             {"file:///tests/test%20file.README.txt",S_OK,FALSE},
268             {"",S_FALSE,FALSE},
269             {".txt",S_OK,FALSE},
270             {"",S_FALSE,FALSE},
271             {"",S_FALSE,FALSE},
272             {"",S_FALSE,FALSE},
273             {"/tests/test%20file.README.txt",S_OK,FALSE},
274             {"/tests/test%20file.README.txt",S_OK,FALSE},
275             {"",S_FALSE,FALSE},
276             {"FILE://localhost/test dir\\../tests/test%20file.README.txt",S_OK,FALSE},
277             {"file",S_OK,FALSE},
278             {"",S_FALSE,FALSE},
279             {"",S_FALSE,FALSE}
280         },
281         {
282             {Uri_HOST_UNKNOWN,S_OK,FALSE},
283             {0,S_FALSE,FALSE},
284             {URL_SCHEME_FILE,S_OK,FALSE},
285             {URLZONE_INVALID,E_NOTIMPL,FALSE}
286         }
287     },
288     {   "urn:nothing:should:happen here", 0, S_OK, FALSE,
289         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|
290         Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
291         FALSE,
292         {
293             {"urn:nothing:should:happen here",S_OK,FALSE},
294             {"",S_FALSE,FALSE},
295             {"urn:nothing:should:happen here",S_OK,FALSE},
296             {"",S_FALSE,FALSE},
297             {"",S_FALSE,FALSE},
298             {"",S_FALSE,FALSE},
299             {"",S_FALSE,FALSE},
300             {"",S_FALSE,FALSE},
301             {"nothing:should:happen here",S_OK,FALSE},
302             {"nothing:should:happen here",S_OK,FALSE},
303             {"",S_FALSE,FALSE},
304             {"urn:nothing:should:happen here",S_OK,FALSE},
305             {"urn",S_OK,FALSE},
306             {"",S_FALSE,FALSE},
307             {"",S_FALSE,FALSE}
308         },
309         {
310             {Uri_HOST_UNKNOWN,S_OK,FALSE},
311             {0,S_FALSE,FALSE},
312             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
313             {URLZONE_INVALID,E_NOTIMPL,FALSE}
314         }
315     },
316     {   "http://127.0.0.1/tests/../test dir/./test.txt", 0, S_OK, FALSE,
317         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|
318         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
319         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
320         FALSE,
321         {
322             {"http://127.0.0.1/test%20dir/test.txt",S_OK,FALSE},
323             {"127.0.0.1",S_OK,FALSE},
324             {"http://127.0.0.1/test%20dir/test.txt",S_OK,FALSE},
325             {"",S_FALSE,FALSE},
326             {".txt",S_OK,FALSE},
327             {"",S_FALSE,FALSE},
328             {"127.0.0.1",S_OK,FALSE},
329             {"",S_FALSE,FALSE},
330             {"/test%20dir/test.txt",S_OK,FALSE},
331             {"/test%20dir/test.txt",S_OK,FALSE},
332             {"",S_FALSE,FALSE},
333             {"http://127.0.0.1/tests/../test dir/./test.txt",S_OK,FALSE},
334             {"http",S_OK,FALSE},
335             {"",S_FALSE,FALSE},
336             {"",S_FALSE,FALSE}
337         },
338         {
339             {Uri_HOST_IPV4,S_OK,FALSE},
340             {80,S_OK,FALSE},
341             {URL_SCHEME_HTTP,S_OK,FALSE},
342             {URLZONE_INVALID,E_NOTIMPL,FALSE}
343         }
344     },
345     {   "http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]", 0, S_OK, FALSE,
346         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
347         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
348         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
349         FALSE,
350         {
351             {"http://[fedc:ba98:7654:3210:fedc:ba98:7654:3210]/",S_OK,FALSE},
352             {"[fedc:ba98:7654:3210:fedc:ba98:7654:3210]",S_OK,FALSE},
353             {"http://[fedc:ba98:7654:3210:fedc:ba98:7654:3210]/",S_OK,FALSE},
354             {"",S_FALSE,FALSE},
355             {"",S_FALSE,FALSE},
356             {"",S_FALSE,FALSE},
357             {"fedc:ba98:7654:3210:fedc:ba98:7654:3210",S_OK,FALSE},
358             {"",S_FALSE,FALSE},
359             {"/",S_OK,FALSE},
360             {"/",S_OK,FALSE},
361             {"",S_FALSE,FALSE},
362             {"http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]",S_OK,FALSE},
363             {"http",S_OK,FALSE},
364             {"",S_FALSE,FALSE},
365             {"",S_FALSE,FALSE}
366         },
367         {
368             {Uri_HOST_IPV6,S_OK,FALSE},
369             {80,S_OK,FALSE},
370             {URL_SCHEME_HTTP,S_OK,FALSE},
371             {URLZONE_INVALID,E_NOTIMPL,FALSE}
372         }
373     },
374     {   "ftp://[::13.1.68.3]", 0, S_OK, FALSE,
375         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
376         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
377         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
378         FALSE,
379         {
380             {"ftp://[::13.1.68.3]/",S_OK,FALSE},
381             {"[::13.1.68.3]",S_OK,FALSE},
382             {"ftp://[::13.1.68.3]/",S_OK,FALSE},
383             {"",S_FALSE,FALSE},
384             {"",S_FALSE,FALSE},
385             {"",S_FALSE,FALSE},
386             {"::13.1.68.3",S_OK,FALSE},
387             {"",S_FALSE,FALSE},
388             {"/",S_OK,FALSE},
389             {"/",S_OK,FALSE},
390             {"",S_FALSE,FALSE},
391             {"ftp://[::13.1.68.3]",S_OK,FALSE},
392             {"ftp",S_OK,FALSE},
393             {"",S_FALSE,FALSE},
394             {"",S_FALSE,FALSE}
395         },
396         {
397             {Uri_HOST_IPV6,S_OK,FALSE},
398             {21,S_OK,FALSE},
399             {URL_SCHEME_FTP,S_OK,FALSE},
400             {URLZONE_INVALID,E_NOTIMPL,FALSE}
401         }
402     },
403     {   "http://[FEDC:BA98:0:0:0:0:0:3210]", 0, S_OK, FALSE,
404         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
405         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
406         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
407         FALSE,
408         {
409             {"http://[fedc:ba98::3210]/",S_OK,FALSE},
410             {"[fedc:ba98::3210]",S_OK,FALSE},
411             {"http://[fedc:ba98::3210]/",S_OK,FALSE},
412             {"",S_FALSE,FALSE},
413             {"",S_FALSE,FALSE},
414             {"",S_FALSE,FALSE},
415             {"fedc:ba98::3210",S_OK,FALSE},
416             {"",S_FALSE,FALSE},
417             {"/",S_OK,FALSE},
418             {"/",S_OK,FALSE},
419             {"",S_FALSE,FALSE},
420             {"http://[FEDC:BA98:0:0:0:0:0:3210]",S_OK,FALSE},
421             {"http",S_OK,FALSE},
422             {"",S_FALSE,FALSE},
423             {"",S_FALSE,FALSE},
424         },
425         {
426             {Uri_HOST_IPV6,S_OK,FALSE},
427             {80,S_OK,FALSE},
428             {URL_SCHEME_HTTP,S_OK,FALSE},
429             {URLZONE_INVALID,E_NOTIMPL,FALSE}
430         }
431     },
432     {   "1234://www.winehq.org", 0, S_OK, FALSE,
433         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
434         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
435         Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
436         FALSE,
437         {
438             {"1234://www.winehq.org/",S_OK,FALSE},
439             {"www.winehq.org",S_OK,FALSE},
440             {"1234://www.winehq.org/",S_OK,FALSE},
441             {"winehq.org",S_OK,FALSE},
442             {"",S_FALSE,FALSE},
443             {"",S_FALSE,FALSE},
444             {"www.winehq.org",S_OK,FALSE},
445             {"",S_FALSE,FALSE},
446             {"/",S_OK,FALSE},
447             {"/",S_OK,FALSE},
448             {"",S_FALSE,FALSE},
449             {"1234://www.winehq.org",S_OK,FALSE},
450             {"1234",S_OK,FALSE},
451             {"",S_FALSE,FALSE},
452             {"",S_FALSE,FALSE}
453         },
454         {
455             {Uri_HOST_DNS,S_OK,FALSE},
456             {0,S_FALSE,FALSE},
457             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
458             {URLZONE_INVALID,E_NOTIMPL,FALSE}
459         }
460     },
461     /* Test's to make sure the parser/canonicalizer handles implicit file schemes correctly. */
462     {   "C:/test/test.mp3", Uri_CREATE_ALLOW_IMPLICIT_FILE_SCHEME, S_OK, FALSE,
463         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH|
464         Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
465         FALSE,
466         {
467             {"file:///C:/test/test.mp3",S_OK,FALSE},
468             {"",S_FALSE,FALSE},
469             {"file:///C:/test/test.mp3",S_OK,FALSE},
470             {"",S_FALSE,FALSE},
471             {".mp3",S_OK,FALSE},
472             {"",S_FALSE,FALSE},
473             {"",S_FALSE,FALSE},
474             {"",S_FALSE,FALSE},
475             {"/C:/test/test.mp3",S_OK,FALSE},
476             {"/C:/test/test.mp3",S_OK,FALSE},
477             {"",S_FALSE,FALSE},
478             {"C:/test/test.mp3",S_OK,FALSE},
479             {"file",S_OK,FALSE},
480             {"",S_FALSE,FALSE},
481             {"",S_FALSE,FALSE}
482         },
483         {
484             {Uri_HOST_UNKNOWN,S_OK,FALSE},
485             {0,S_FALSE,FALSE},
486             {URL_SCHEME_FILE,S_OK,FALSE},
487             {URLZONE_INVALID,E_NOTIMPL,FALSE}
488         }
489     },
490     /* Test's to make sure the parser/canonicalizer handles implicit file schemes correctly. */
491     {   "\\\\Server/test.mp3", Uri_CREATE_ALLOW_IMPLICIT_FILE_SCHEME, S_OK, FALSE,
492         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|
493         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_HOST|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
494         Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
495         FALSE,
496         {
497             {"file://server/test.mp3",S_OK,FALSE},
498             {"server",S_OK,FALSE},
499             {"file://server/test.mp3",S_OK,FALSE},
500             {"",S_FALSE,FALSE},
501             {".mp3",S_OK,FALSE},
502             {"",S_FALSE,FALSE},
503             {"server",S_OK,FALSE},
504             {"",S_FALSE,FALSE},
505             {"/test.mp3",S_OK,FALSE},
506             {"/test.mp3",S_OK,FALSE},
507             {"",S_FALSE,FALSE},
508             {"\\\\Server/test.mp3",S_OK,FALSE},
509             {"file",S_OK,FALSE},
510             {"",S_FALSE,FALSE},
511             {"",S_FALSE,FALSE}
512         },
513         {
514             {Uri_HOST_DNS,S_OK,FALSE},
515             {0,S_FALSE,FALSE},
516             {URL_SCHEME_FILE,S_OK,FALSE},
517             {URLZONE_INVALID,E_NOTIMPL,FALSE}
518         }
519     },
520     {   "www.winehq.org/test", Uri_CREATE_ALLOW_IMPLICIT_WILDCARD_SCHEME, S_OK, FALSE,
521         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_HOST|
522         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|
523         Uri_HAS_SCHEME,
524         FALSE,
525         {
526             {"*:www.winehq.org/test",S_OK,FALSE},
527             {"www.winehq.org",S_OK,FALSE},
528             {"*:www.winehq.org/test",S_OK,FALSE},
529             {"winehq.org",S_OK,FALSE},
530             {"",S_FALSE,FALSE},
531             {"",S_FALSE,FALSE},
532             {"www.winehq.org",S_OK,FALSE},
533             {"",S_FALSE,FALSE},
534             {"/test",S_OK,FALSE},
535             {"/test",S_OK,FALSE},
536             {"",S_FALSE,FALSE},
537             {"www.winehq.org/test",S_OK,FALSE},
538             {"*",S_OK,FALSE},
539             {"",S_FALSE,FALSE},
540             {"",S_FALSE,FALSE}
541         },
542         {
543             {Uri_HOST_DNS,S_OK,FALSE},
544             {0,S_FALSE,FALSE},
545             {URL_SCHEME_WILDCARD,S_OK,FALSE},
546             {URLZONE_INVALID,E_NOTIMPL,FALSE}
547         }
548     },
549     /* Valid since the '*' is the only character in the scheme name. */
550     {   "*:www.winehq.org/test", 0, S_OK, FALSE,
551         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_HOST|
552         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|
553         Uri_HAS_SCHEME,
554         FALSE,
555         {
556             {"*:www.winehq.org/test",S_OK,FALSE},
557             {"www.winehq.org",S_OK,FALSE},
558             {"*:www.winehq.org/test",S_OK,FALSE},
559             {"winehq.org",S_OK,FALSE},
560             {"",S_FALSE,FALSE},
561             {"",S_FALSE,FALSE},
562             {"www.winehq.org",S_OK,FALSE},
563             {"",S_FALSE,FALSE},
564             {"/test",S_OK,FALSE},
565             {"/test",S_OK,FALSE},
566             {"",S_FALSE,FALSE},
567             {"*:www.winehq.org/test",S_OK,FALSE},
568             {"*",S_OK,FALSE},
569             {"",S_FALSE,FALSE},
570             {"",S_FALSE,FALSE}
571         },
572         {
573             {Uri_HOST_DNS,S_OK,FALSE},
574             {0,S_FALSE,FALSE},
575             {URL_SCHEME_WILDCARD,S_OK,FALSE},
576             {URLZONE_INVALID,E_NOTIMPL,FALSE}
577         }
578     },
579     {   "/../some dir/test.ext", Uri_CREATE_ALLOW_RELATIVE, S_OK, FALSE,
580         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH|
581         Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
582         FALSE,
583         {
584             {"/../some dir/test.ext",S_OK,FALSE},
585             {"",S_FALSE,FALSE},
586             {"/../some dir/test.ext",S_OK,FALSE},
587             {"",S_FALSE,FALSE},
588             {".ext",S_OK,FALSE},
589             {"",S_FALSE,FALSE},
590             {"",S_FALSE,FALSE},
591             {"",S_FALSE,FALSE},
592             {"/../some dir/test.ext",S_OK,FALSE},
593             {"/../some dir/test.ext",S_OK,FALSE},
594             {"",S_FALSE,FALSE},
595             {"/../some dir/test.ext",S_OK,FALSE},
596             {"",S_FALSE,FALSE},
597             {"",S_FALSE,FALSE},
598             {"",S_FALSE,FALSE}
599         },
600         {
601             {Uri_HOST_UNKNOWN,S_OK,FALSE},
602             {0,S_FALSE,FALSE},
603             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
604             {URLZONE_INVALID,E_NOTIMPL,FALSE}
605         }
606     },
607     {   "//implicit/wildcard/uri scheme", Uri_CREATE_ALLOW_RELATIVE|Uri_CREATE_ALLOW_IMPLICIT_WILDCARD_SCHEME, S_OK, FALSE,
608         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|Uri_HAS_PATH|
609         Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
610         FALSE,
611         {
612             {"*://implicit/wildcard/uri%20scheme",S_OK,FALSE},
613             {"",S_OK,FALSE},
614             {"*://implicit/wildcard/uri%20scheme",S_OK,FALSE},
615             {"",S_FALSE,FALSE},
616             {"",S_FALSE,FALSE},
617             {"",S_FALSE,FALSE},
618             {"",S_OK,FALSE},
619             {"",S_FALSE,FALSE},
620             {"//implicit/wildcard/uri%20scheme",S_OK,FALSE},
621             {"//implicit/wildcard/uri%20scheme",S_OK,FALSE},
622             {"",S_FALSE,FALSE},
623             {"//implicit/wildcard/uri scheme",S_OK,FALSE},
624             {"*",S_OK,FALSE},
625             {"",S_FALSE,FALSE},
626             {"",S_FALSE,FALSE},
627         },
628         {
629             {Uri_HOST_UNKNOWN,S_OK,FALSE},
630             {0,S_FALSE,FALSE},
631             {URL_SCHEME_WILDCARD,S_OK,FALSE},
632             {URLZONE_INVALID,E_NOTIMPL,FALSE}
633         }
634     },
635     /* URI is considered opaque since CREATE_NO_CRACK_UNKNOWN_SCHEMES is set and its an unknown scheme. */
636     {   "zip://google.com", Uri_CREATE_NO_CRACK_UNKNOWN_SCHEMES, S_OK, FALSE,
637         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH|
638         Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME_NAME|
639         Uri_HAS_SCHEME,
640         FALSE,
641         {
642             {"zip:/.//google.com",S_OK,FALSE},
643             {"",S_FALSE,FALSE},
644             {"zip:/.//google.com",S_OK,FALSE},
645             {"",S_FALSE,FALSE},
646             {".com",S_OK,FALSE},
647             {"",S_FALSE,FALSE},
648             {"",S_FALSE,FALSE},
649             {"",S_FALSE,FALSE},
650             {"/.//google.com",S_OK,FALSE},
651             {"/.//google.com",S_OK,FALSE},
652             {"",S_FALSE,FALSE},
653             {"zip://google.com",S_OK,FALSE},
654             {"zip",S_OK,FALSE},
655             {"",S_FALSE,FALSE},
656             {"",S_FALSE,FALSE}
657         },
658         {
659             {Uri_HOST_UNKNOWN,S_OK,FALSE},
660             {0,S_FALSE,FALSE},
661             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
662             {URLZONE_INVALID,E_NOTIMPL,FALSE}
663         }
664     },
665     /* Windows uses the first occurrence of ':' to delimit the userinfo. */
666     {   "ftp://user:pass:word@winehq.org/", 0, S_OK, FALSE,
667         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
668         Uri_HAS_HOST|Uri_HAS_PASSWORD|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
669         Uri_HAS_SCHEME_NAME|Uri_HAS_USER_INFO|Uri_HAS_USER_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|
670         Uri_HAS_SCHEME,
671         FALSE,
672         {
673             {"ftp://user:pass:word@winehq.org/",S_OK,FALSE},
674             {"user:pass:word@winehq.org",S_OK,FALSE},
675             {"ftp://winehq.org/",S_OK,FALSE},
676             {"winehq.org",S_OK,FALSE},
677             {"",S_FALSE,FALSE},
678             {"",S_FALSE,FALSE},
679             {"winehq.org",S_OK,FALSE},
680             {"pass:word",S_OK,FALSE},
681             {"/",S_OK,FALSE},
682             {"/",S_OK,FALSE},
683             {"",S_FALSE,FALSE},
684             {"ftp://user:pass:word@winehq.org/",S_OK,FALSE},
685             {"ftp",S_OK,FALSE},
686             {"user:pass:word",S_OK,FALSE},
687             {"user",S_OK,FALSE}
688         },
689         {
690             {Uri_HOST_DNS,S_OK,FALSE},
691             {21,S_OK,FALSE},
692             {URL_SCHEME_FTP,S_OK,FALSE},
693             {URLZONE_INVALID,E_NOTIMPL,FALSE}
694         }
695     },
696     /* Make sure % encoded unreserved characters are decoded. */
697     {   "ftp://w%49%4Ee:PA%53%53@ftp.google.com/", 0, S_OK, FALSE,
698         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
699         Uri_HAS_HOST|Uri_HAS_PASSWORD|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
700         Uri_HAS_SCHEME_NAME|Uri_HAS_USER_INFO|Uri_HAS_USER_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|
701         Uri_HAS_SCHEME,
702         FALSE,
703         {
704             {"ftp://wINe:PASS@ftp.google.com/",S_OK,FALSE},
705             {"wINe:PASS@ftp.google.com",S_OK,FALSE},
706             {"ftp://ftp.google.com/",S_OK,FALSE},
707             {"google.com",S_OK,FALSE},
708             {"",S_FALSE,FALSE},
709             {"",S_FALSE,FALSE},
710             {"ftp.google.com",S_OK,FALSE},
711             {"PASS",S_OK,FALSE},
712             {"/",S_OK,FALSE},
713             {"/",S_OK,FALSE},
714             {"",S_FALSE,FALSE},
715             {"ftp://w%49%4Ee:PA%53%53@ftp.google.com/",S_OK,FALSE},
716             {"ftp",S_OK,FALSE},
717             {"wINe:PASS",S_OK,FALSE},
718             {"wINe",S_OK,FALSE}
719         },
720         {
721             {Uri_HOST_DNS,S_OK,FALSE},
722             {21,S_OK,FALSE},
723             {URL_SCHEME_FTP,S_OK,FALSE},
724             {URLZONE_INVALID,E_NOTIMPL,FALSE}
725         }
726     },
727     /* Make sure % encoded characters which are NOT unreserved are NOT decoded. */
728     {   "ftp://w%5D%5Be:PA%7B%7D@ftp.google.com/", 0, S_OK, FALSE,
729         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
730         Uri_HAS_HOST|Uri_HAS_PASSWORD|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
731         Uri_HAS_SCHEME_NAME|Uri_HAS_USER_INFO|Uri_HAS_USER_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|
732         Uri_HAS_SCHEME,
733         FALSE,
734         {
735             {"ftp://w%5D%5Be:PA%7B%7D@ftp.google.com/",S_OK,FALSE},
736             {"w%5D%5Be:PA%7B%7D@ftp.google.com",S_OK,FALSE},
737             {"ftp://ftp.google.com/",S_OK,FALSE},
738             {"google.com",S_OK,FALSE},
739             {"",S_FALSE,FALSE},
740             {"",S_FALSE,FALSE},
741             {"ftp.google.com",S_OK,FALSE},
742             {"PA%7B%7D",S_OK,FALSE},
743             {"/",S_OK,FALSE},
744             {"/",S_OK,FALSE},
745             {"",S_FALSE,FALSE},
746             {"ftp://w%5D%5Be:PA%7B%7D@ftp.google.com/",S_OK,FALSE},
747             {"ftp",S_OK,FALSE},
748             {"w%5D%5Be:PA%7B%7D",S_OK,FALSE},
749             {"w%5D%5Be",S_OK,FALSE}
750         },
751         {
752             {Uri_HOST_DNS,S_OK,FALSE},
753             {21,S_OK,FALSE},
754             {URL_SCHEME_FTP,S_OK,FALSE},
755             {URLZONE_INVALID,E_NOTIMPL,FALSE}
756         }
757     },
758     /* You're allowed to have an empty password portion in the userinfo section. */
759     {   "ftp://empty:@ftp.google.com/", 0, S_OK, FALSE,
760         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
761         Uri_HAS_HOST|Uri_HAS_PASSWORD|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
762         Uri_HAS_SCHEME_NAME|Uri_HAS_USER_INFO|Uri_HAS_USER_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|
763         Uri_HAS_SCHEME,
764         FALSE,
765         {
766             {"ftp://empty:@ftp.google.com/",S_OK,FALSE},
767             {"empty:@ftp.google.com",S_OK,FALSE},
768             {"ftp://ftp.google.com/",S_OK,FALSE},
769             {"google.com",S_OK,FALSE},
770             {"",S_FALSE,FALSE},
771             {"",S_FALSE,FALSE},
772             {"ftp.google.com",S_OK,FALSE},
773             {"",S_OK,FALSE},
774             {"/",S_OK,FALSE},
775             {"/",S_OK,FALSE},
776             {"",S_FALSE,FALSE},
777             {"ftp://empty:@ftp.google.com/",S_OK,FALSE},
778             {"ftp",S_OK,FALSE},
779             {"empty:",S_OK,FALSE},
780             {"empty",S_OK,FALSE}
781         },
782         {
783             {Uri_HOST_DNS,S_OK,FALSE},
784             {21,S_OK,FALSE},
785             {URL_SCHEME_FTP,S_OK,FALSE},
786             {URLZONE_INVALID,E_NOTIMPL,FALSE}
787         }
788     },
789     /* Make sure forbidden characters in "userinfo" get encoded. */
790     {   "ftp://\" \"weird@ftp.google.com/", 0, S_OK, FALSE,
791         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
792         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
793         Uri_HAS_SCHEME_NAME|Uri_HAS_USER_INFO|Uri_HAS_USER_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|
794         Uri_HAS_SCHEME,
795         FALSE,
796         {
797             {"ftp://%22%20%22weird@ftp.google.com/",S_OK,FALSE},
798             {"%22%20%22weird@ftp.google.com",S_OK,FALSE},
799             {"ftp://ftp.google.com/",S_OK,FALSE},
800             {"google.com",S_OK,FALSE},
801             {"",S_FALSE,FALSE},
802             {"",S_FALSE,FALSE},
803             {"ftp.google.com",S_OK,FALSE},
804             {"",S_FALSE,FALSE},
805             {"/",S_OK,FALSE},
806             {"/",S_OK,FALSE},
807             {"",S_FALSE,FALSE},
808             {"ftp://\" \"weird@ftp.google.com/",S_OK,FALSE},
809             {"ftp",S_OK,FALSE},
810             {"%22%20%22weird",S_OK,FALSE},
811             {"%22%20%22weird",S_OK,FALSE}
812         },
813         {
814             {Uri_HOST_DNS,S_OK,FALSE},
815             {21,S_OK,FALSE},
816             {URL_SCHEME_FTP,S_OK,FALSE},
817             {URLZONE_INVALID,E_NOTIMPL,FALSE}
818         }
819     },
820     /* Make sure the forbidden characters don't get percent encoded. */
821     {   "ftp://\" \"weird@ftp.google.com/", Uri_CREATE_NO_ENCODE_FORBIDDEN_CHARACTERS, S_OK, FALSE,
822         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
823         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
824         Uri_HAS_SCHEME_NAME|Uri_HAS_USER_INFO|Uri_HAS_USER_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|
825         Uri_HAS_SCHEME,
826         FALSE,
827         {
828             {"ftp://\" \"weird@ftp.google.com/",S_OK,FALSE},
829             {"\" \"weird@ftp.google.com",S_OK,FALSE},
830             {"ftp://ftp.google.com/",S_OK,FALSE},
831             {"google.com",S_OK,FALSE},
832             {"",S_FALSE,FALSE},
833             {"",S_FALSE,FALSE},
834             {"ftp.google.com",S_OK,FALSE},
835             {"",S_FALSE,FALSE},
836             {"/",S_OK,FALSE},
837             {"/",S_OK,FALSE},
838             {"",S_FALSE,FALSE},
839             {"ftp://\" \"weird@ftp.google.com/",S_OK,FALSE},
840             {"ftp",S_OK,FALSE},
841             {"\" \"weird",S_OK,FALSE},
842             {"\" \"weird",S_OK,FALSE}
843         },
844         {
845             {Uri_HOST_DNS,S_OK,FALSE},
846             {21,S_OK,FALSE},
847             {URL_SCHEME_FTP,S_OK,FALSE},
848             {URLZONE_INVALID,E_NOTIMPL,FALSE}
849         }
850     },
851     /* Allowed to have invalid % encoded because its an unknown scheme type. */
852     {   "zip://%xy:word@winehq.org/", 0, S_OK, FALSE,
853         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
854         Uri_HAS_HOST|Uri_HAS_PASSWORD|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
855         Uri_HAS_SCHEME_NAME|Uri_HAS_USER_INFO|Uri_HAS_USER_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
856         FALSE,
857         {
858             {"zip://%xy:word@winehq.org/",S_OK,FALSE},
859             {"%xy:word@winehq.org",S_OK,FALSE},
860             {"zip://%xy:word@winehq.org/",S_OK,FALSE},
861             {"winehq.org",S_OK,FALSE},
862             {"",S_FALSE,FALSE},
863             {"",S_FALSE,FALSE},
864             {"winehq.org",S_OK,FALSE},
865             {"word",S_OK,FALSE},
866             {"/",S_OK,FALSE},
867             {"/",S_OK,FALSE},
868             {"",S_FALSE,FALSE},
869             {"zip://%xy:word@winehq.org/",S_OK,FALSE},
870             {"zip",S_OK,FALSE},
871             {"%xy:word",S_OK,FALSE},
872             {"%xy",S_OK,FALSE}
873         },
874         {
875             {Uri_HOST_DNS,S_OK,FALSE},
876             {0,S_FALSE,FALSE},
877             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
878             {URLZONE_INVALID,E_NOTIMPL,FALSE}
879         }
880     },
881     /* Unreserved, percent encoded characters aren't decoded in the userinfo becuase the scheme
882      * isn't known.
883      */
884     {   "zip://%2E:%52%53ord@winehq.org/", 0, S_OK, FALSE,
885         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
886         Uri_HAS_HOST|Uri_HAS_PASSWORD|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
887         Uri_HAS_SCHEME_NAME|Uri_HAS_USER_INFO|Uri_HAS_USER_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
888         FALSE,
889         {
890             {"zip://%2E:%52%53ord@winehq.org/",S_OK,FALSE},
891             {"%2E:%52%53ord@winehq.org",S_OK,FALSE},
892             {"zip://%2E:%52%53ord@winehq.org/",S_OK,FALSE},
893             {"winehq.org",S_OK,FALSE},
894             {"",S_FALSE,FALSE},
895             {"",S_FALSE,FALSE},
896             {"winehq.org",S_OK,FALSE},
897             {"%52%53ord",S_OK,FALSE},
898             {"/",S_OK,FALSE},
899             {"/",S_OK,FALSE},
900             {"",S_FALSE,FALSE},
901             {"zip://%2E:%52%53ord@winehq.org/",S_OK,FALSE},
902             {"zip",S_OK,FALSE},
903             {"%2E:%52%53ord",S_OK,FALSE},
904             {"%2E",S_OK,FALSE}
905         },
906         {
907             {Uri_HOST_DNS,S_OK,FALSE},
908             {0,S_FALSE,FALSE},
909             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
910             {URLZONE_INVALID,E_NOTIMPL,FALSE}
911         }
912     },
913     {   "ftp://[](),'test':word@winehq.org/", 0, S_OK, FALSE,
914         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
915         Uri_HAS_HOST|Uri_HAS_PASSWORD|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
916         Uri_HAS_SCHEME_NAME|Uri_HAS_USER_INFO|Uri_HAS_USER_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|
917         Uri_HAS_SCHEME,
918         FALSE,
919         {
920             {"ftp://[](),'test':word@winehq.org/",S_OK,FALSE},
921             {"[](),'test':word@winehq.org",S_OK,FALSE},
922             {"ftp://winehq.org/",S_OK,FALSE},
923             {"winehq.org",S_OK,FALSE},
924             {"",S_FALSE,FALSE},
925             {"",S_FALSE,FALSE},
926             {"winehq.org",S_OK,FALSE},
927             {"word",S_OK,FALSE},
928             {"/",S_OK,FALSE},
929             {"/",S_OK,FALSE},
930             {"",S_FALSE,FALSE},
931             {"ftp://[](),'test':word@winehq.org/",S_OK,FALSE},
932             {"ftp",S_OK,FALSE},
933             {"[](),'test':word",S_OK,FALSE},
934             {"[](),'test'",S_OK,FALSE}
935         },
936         {
937             {Uri_HOST_DNS,S_OK,FALSE},
938             {21,S_OK,FALSE},
939             {URL_SCHEME_FTP,S_OK,FALSE},
940             {URLZONE_INVALID,E_NOTIMPL,FALSE}
941         }
942     },
943     {   "ftp://test?:word@winehq.org/", 0, S_OK, FALSE,
944         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
945         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
946         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
947         FALSE,
948         {
949             {"ftp://test/?:word@winehq.org/",S_OK,FALSE},
950             {"test",S_OK,FALSE},
951             {"ftp://test/?:word@winehq.org/",S_OK,FALSE},
952             {"",S_FALSE,FALSE},
953             {"",S_FALSE,FALSE},
954             {"",S_FALSE,FALSE},
955             {"test",S_OK,FALSE},
956             {"",S_FALSE,FALSE},
957             {"/",S_OK,FALSE},
958             {"/?:word@winehq.org/",S_OK,FALSE},
959             {"?:word@winehq.org/",S_OK,FALSE},
960             {"ftp://test?:word@winehq.org/",S_OK,FALSE},
961             {"ftp",S_OK,FALSE},
962             {"",S_FALSE,FALSE},
963             {"",S_FALSE,FALSE}
964         },
965         {
966             {Uri_HOST_DNS,S_OK,FALSE},
967             {21,S_OK,FALSE},
968             {URL_SCHEME_FTP,S_OK,FALSE},
969             {URLZONE_INVALID,E_NOTIMPL,FALSE}
970         }
971     },
972     {   "ftp://test#:word@winehq.org/", 0, S_OK, FALSE,
973         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_FRAGMENT|Uri_HAS_HOST|
974         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
975         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
976         FALSE,
977         {
978             {"ftp://test/#:word@winehq.org/",S_OK,FALSE},
979             {"test",S_OK,FALSE},
980             {"ftp://test/#:word@winehq.org/",S_OK,FALSE},
981             {"",S_FALSE,FALSE},
982             {"",S_FALSE,FALSE},
983             {"#:word@winehq.org/",S_OK,FALSE},
984             {"test",S_OK,FALSE},
985             {"",S_FALSE,FALSE},
986             {"/",S_OK,FALSE},
987             {"/",S_OK,FALSE},
988             {"",S_FALSE,FALSE},
989             {"ftp://test#:word@winehq.org/",S_OK,FALSE},
990             {"ftp",S_OK,FALSE},
991             {"",S_FALSE,FALSE},
992             {"",S_FALSE,FALSE}
993         },
994         {
995             {Uri_HOST_DNS,S_OK,FALSE},
996             {21,S_OK,FALSE},
997             {URL_SCHEME_FTP,S_OK,FALSE},
998             {URLZONE_INVALID,E_NOTIMPL,FALSE}
999         }
1000     },
1001     /* Allowed to have a backslash in the userinfo since it's an unknown scheme. */
1002     {   "zip://test\\:word@winehq.org/", 0, S_OK, FALSE,
1003         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_HOST|
1004         Uri_HAS_PASSWORD|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1005         Uri_HAS_USER_INFO|Uri_HAS_USER_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
1006         FALSE,
1007         {
1008             {"zip://test\\:word@winehq.org/",S_OK,FALSE},
1009             {"test\\:word@winehq.org",S_OK,FALSE},
1010             {"zip://test\\:word@winehq.org/",S_OK,FALSE},
1011             {"winehq.org",S_OK,FALSE},
1012             {"",S_FALSE,FALSE},
1013             {"",S_FALSE,FALSE},
1014             {"winehq.org",S_OK,FALSE},
1015             {"word",S_OK,FALSE},
1016             {"/",S_OK,FALSE},
1017             {"/",S_OK,FALSE},
1018             {"",S_FALSE,FALSE},
1019             {"zip://test\\:word@winehq.org/",S_OK,FALSE},
1020             {"zip",S_OK,FALSE},
1021             {"test\\:word",S_OK,FALSE},
1022             {"test\\",S_OK,FALSE}
1023         },
1024         {
1025             {Uri_HOST_DNS,S_OK,FALSE},
1026             {0,S_FALSE,FALSE},
1027             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1028             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1029         }
1030     },
1031     /* It normalizes IPv4 addresses correctly. */
1032     {   "http://127.000.000.100/", 0, S_OK, FALSE,
1033         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
1034         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1035         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1036         FALSE,
1037         {
1038             {"http://127.0.0.100/",S_OK,FALSE},
1039             {"127.0.0.100",S_OK,FALSE},
1040             {"http://127.0.0.100/",S_OK,FALSE},
1041             {"",S_FALSE,FALSE},
1042             {"",S_FALSE,FALSE},
1043             {"",S_FALSE,FALSE},
1044             {"127.0.0.100",S_OK,FALSE},
1045             {"",S_FALSE,FALSE},
1046             {"/",S_OK,FALSE},
1047             {"/",S_OK,FALSE},
1048             {"",S_FALSE,FALSE},
1049             {"http://127.000.000.100/",S_OK,FALSE},
1050             {"http",S_OK,FALSE},
1051             {"",S_FALSE,FALSE},
1052             {"",S_FALSE,FALSE}
1053         },
1054         {
1055             {Uri_HOST_IPV4,S_OK,FALSE},
1056             {80,S_OK,FALSE},
1057             {URL_SCHEME_HTTP,S_OK,FALSE},
1058             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1059         }
1060     },
1061     /* Make sure it normalizes partial IPv4 addresses correctly. */
1062     {   "http://127.0/", 0, S_OK, FALSE,
1063         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
1064         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1065         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1066         FALSE,
1067         {
1068             {"http://127.0.0.0/",S_OK,FALSE},
1069             {"127.0.0.0",S_OK,FALSE},
1070             {"http://127.0.0.0/",S_OK,FALSE},
1071             {"",S_FALSE,FALSE},
1072             {"",S_FALSE,FALSE},
1073             {"",S_FALSE,FALSE},
1074             {"127.0.0.0",S_OK,FALSE},
1075             {"",S_FALSE,FALSE},
1076             {"/",S_OK,FALSE},
1077             {"/",S_OK,FALSE},
1078             {"",S_FALSE,FALSE},
1079             {"http://127.0/",S_OK,FALSE},
1080             {"http",S_OK,FALSE},
1081             {"",S_FALSE,FALSE},
1082             {"",S_FALSE,FALSE}
1083         },
1084         {
1085             {Uri_HOST_IPV4,S_OK,FALSE},
1086             {80,S_OK,FALSE},
1087             {URL_SCHEME_HTTP,S_OK,FALSE},
1088             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1089         }
1090     },
1091     /* Make sure it converts implicit IPv4's correctly. */
1092     {   "http://123456/", 0, S_OK, FALSE,
1093         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
1094         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1095         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1096         FALSE,
1097         {
1098             {"http://0.1.226.64/",S_OK,FALSE},
1099             {"0.1.226.64",S_OK,FALSE},
1100             {"http://0.1.226.64/",S_OK,FALSE},
1101             {"",S_FALSE,FALSE},
1102             {"",S_FALSE,FALSE},
1103             {"",S_FALSE,FALSE},
1104             {"0.1.226.64",S_OK,FALSE},
1105             {"",S_FALSE,FALSE},
1106             {"/",S_OK,FALSE},
1107             {"/",S_OK,FALSE},
1108             {"",S_FALSE,FALSE},
1109             {"http://123456/",S_OK,FALSE},
1110             {"http",S_OK,FALSE},
1111             {"",S_FALSE,FALSE},
1112             {"",S_FALSE,FALSE}
1113         },
1114         {
1115             {Uri_HOST_IPV4,S_OK,FALSE},
1116             {80,S_OK,FALSE},
1117             {URL_SCHEME_HTTP,S_OK,FALSE},
1118             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1119         }
1120     },
1121     /* UINT_MAX */
1122     {   "http://4294967295/", 0, S_OK, FALSE,
1123         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
1124         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1125         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1126         FALSE,
1127         {
1128             {"http://255.255.255.255/",S_OK,FALSE},
1129             {"255.255.255.255",S_OK,FALSE},
1130             {"http://255.255.255.255/",S_OK,FALSE},
1131             {"",S_FALSE,FALSE},
1132             {"",S_FALSE,FALSE},
1133             {"",S_FALSE,FALSE},
1134             {"255.255.255.255",S_OK,FALSE},
1135             {"",S_FALSE,FALSE},
1136             {"/",S_OK,FALSE},
1137             {"/",S_OK,FALSE},
1138             {"",S_FALSE,FALSE},
1139             {"http://4294967295/",S_OK,FALSE},
1140             {"http",S_OK,FALSE},
1141             {"",S_FALSE,FALSE},
1142             {"",S_FALSE,FALSE}
1143         },
1144         {
1145             {Uri_HOST_IPV4,S_OK,FALSE},
1146             {80,S_OK,FALSE},
1147             {URL_SCHEME_HTTP,S_OK,FALSE},
1148             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1149         }
1150     },
1151     /* UINT_MAX+1 */
1152     {   "http://4294967296/", 0, S_OK, FALSE,
1153         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
1154         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1155         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1156         FALSE,
1157         {
1158             {"http://4294967296/",S_OK,FALSE},
1159             {"4294967296",S_OK,FALSE},
1160             {"http://4294967296/",S_OK,FALSE},
1161             {"",S_FALSE,FALSE},
1162             {"",S_FALSE,FALSE},
1163             {"",S_FALSE,FALSE},
1164             {"4294967296",S_OK,FALSE},
1165             {"",S_FALSE,FALSE},
1166             {"/",S_OK,FALSE},
1167             {"/",S_OK,FALSE},
1168             {"",S_FALSE,FALSE},
1169             {"http://4294967296/",S_OK,FALSE},
1170             {"http",S_OK,FALSE},
1171             {"",S_FALSE,FALSE},
1172             {"",S_FALSE,FALSE}
1173         },
1174         {
1175             {Uri_HOST_DNS,S_OK,FALSE},
1176             {80,S_OK,FALSE},
1177             {URL_SCHEME_HTTP,S_OK,FALSE},
1178             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1179         }
1180     },
1181     /* Window's doesn't normalize IP address for unknown schemes. */
1182     {   "1234://4294967295/", 0, S_OK, FALSE,
1183         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
1184         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1185         Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
1186         FALSE,
1187         {
1188             {"1234://4294967295/",S_OK,FALSE},
1189             {"4294967295",S_OK,FALSE},
1190             {"1234://4294967295/",S_OK,FALSE},
1191             {"",S_FALSE,FALSE},
1192             {"",S_FALSE,FALSE},
1193             {"",S_FALSE,FALSE},
1194             {"4294967295",S_OK,FALSE},
1195             {"",S_FALSE,FALSE},
1196             {"/",S_OK,FALSE},
1197             {"/",S_OK,FALSE},
1198             {"",S_FALSE,FALSE},
1199             {"1234://4294967295/",S_OK,FALSE},
1200             {"1234",S_OK,FALSE},
1201             {"",S_FALSE,FALSE},
1202             {"",S_FALSE,FALSE}
1203         },
1204         {
1205             {Uri_HOST_IPV4,S_OK,FALSE},
1206             {0,S_FALSE,FALSE},
1207             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1208             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1209         }
1210     },
1211     /* Window's doesn't normalize IP address for unknown schemes. */
1212     {   "1234://127.001/", 0, S_OK, FALSE,
1213         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
1214         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1215         Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
1216         FALSE,
1217         {
1218             {"1234://127.001/",S_OK,FALSE},
1219             {"127.001",S_OK,FALSE},
1220             {"1234://127.001/",S_OK,FALSE},
1221             {"",S_FALSE,FALSE},
1222             {"",S_FALSE,FALSE},
1223             {"",S_FALSE,FALSE},
1224             {"127.001",S_OK,FALSE},
1225             {"",S_FALSE,FALSE},
1226             {"/",S_OK,FALSE},
1227             {"/",S_OK,FALSE},
1228             {"",S_FALSE,FALSE},
1229             {"1234://127.001/",S_OK,FALSE},
1230             {"1234",S_OK,FALSE},
1231             {"",S_FALSE,FALSE},
1232             {"",S_FALSE,FALSE}
1233         },
1234         {
1235             {Uri_HOST_IPV4,S_OK,FALSE},
1236             {0,S_FALSE,FALSE},
1237             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1238             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1239         }
1240     },
1241     {   "http://[FEDC:BA98::3210]", 0, S_OK, FALSE,
1242         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
1243         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1244         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1245         FALSE,
1246         {
1247             {"http://[fedc:ba98::3210]/",S_OK,FALSE},
1248             {"[fedc:ba98::3210]",S_OK,FALSE},
1249             {"http://[fedc:ba98::3210]/",S_OK,FALSE},
1250             {"",S_FALSE,FALSE},
1251             {"",S_FALSE,FALSE},
1252             {"",S_FALSE,FALSE},
1253             {"fedc:ba98::3210",S_OK,FALSE},
1254             {"",S_FALSE,FALSE},
1255             {"/",S_OK,FALSE},
1256             {"/",S_OK,FALSE},
1257             {"",S_FALSE,FALSE},
1258             {"http://[FEDC:BA98::3210]",S_OK,FALSE},
1259             {"http",S_OK,FALSE},
1260             {"",S_FALSE,FALSE},
1261             {"",S_FALSE,FALSE},
1262         },
1263         {
1264             {Uri_HOST_IPV6,S_OK,FALSE},
1265             {80,S_OK,FALSE},
1266             {URL_SCHEME_HTTP,S_OK,FALSE},
1267             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1268         }
1269     },
1270     {   "http://[::]", 0, S_OK, FALSE,
1271         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
1272         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1273         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1274         FALSE,
1275         {
1276             {"http://[::]/",S_OK,FALSE},
1277             {"[::]",S_OK,FALSE},
1278             {"http://[::]/",S_OK,FALSE},
1279             {"",S_FALSE,FALSE},
1280             {"",S_FALSE,FALSE},
1281             {"",S_FALSE,FALSE},
1282             {"::",S_OK,FALSE},
1283             {"",S_FALSE,FALSE},
1284             {"/",S_OK,FALSE},
1285             {"/",S_OK,FALSE},
1286             {"",S_FALSE,FALSE},
1287             {"http://[::]",S_OK,FALSE},
1288             {"http",S_OK,FALSE},
1289             {"",S_FALSE,FALSE},
1290             {"",S_FALSE,FALSE},
1291         },
1292         {
1293             {Uri_HOST_IPV6,S_OK,FALSE},
1294             {80,S_OK,FALSE},
1295             {URL_SCHEME_HTTP,S_OK,FALSE},
1296             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1297         }
1298     },
1299     {   "http://[FEDC:BA98::]", 0, S_OK, FALSE,
1300         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
1301         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1302         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1303         FALSE,
1304         {
1305             {"http://[fedc:ba98::]/",S_OK,FALSE},
1306             {"[fedc:ba98::]",S_OK,FALSE},
1307             {"http://[fedc:ba98::]/",S_OK,FALSE},
1308             {"",S_FALSE,FALSE},
1309             {"",S_FALSE,FALSE},
1310             {"",S_FALSE,FALSE},
1311             {"fedc:ba98::",S_OK,FALSE},
1312             {"",S_FALSE,FALSE},
1313             {"/",S_OK,FALSE},
1314             {"/",S_OK,FALSE},
1315             {"",S_FALSE,FALSE},
1316             {"http://[FEDC:BA98::]",S_OK,FALSE},
1317             {"http",S_OK,FALSE},
1318             {"",S_FALSE,FALSE},
1319             {"",S_FALSE,FALSE},
1320         },
1321         {
1322             {Uri_HOST_IPV6,S_OK,FALSE},
1323             {80,S_OK,FALSE},
1324             {URL_SCHEME_HTTP,S_OK,FALSE},
1325             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1326         }
1327     },
1328     /* Valid even with 2 byte elision because it doesn't appear the beginning or end. */
1329     {   "http://[1::3:4:5:6:7:8]", 0, S_OK, FALSE,
1330         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
1331         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1332         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1333         FALSE,
1334         {
1335             {"http://[1:0:3:4:5:6:7:8]/",S_OK,FALSE},
1336             {"[1:0:3:4:5:6:7:8]",S_OK,FALSE},
1337             {"http://[1:0:3:4:5:6:7:8]/",S_OK,FALSE},
1338             {"",S_FALSE,FALSE},
1339             {"",S_FALSE,FALSE},
1340             {"",S_FALSE,FALSE},
1341             {"1:0:3:4:5:6:7:8",S_OK,FALSE},
1342             {"",S_FALSE,FALSE},
1343             {"/",S_OK,FALSE},
1344             {"/",S_OK,FALSE},
1345             {"",S_FALSE,FALSE},
1346             {"http://[1::3:4:5:6:7:8]",S_OK,FALSE},
1347             {"http",S_OK,FALSE},
1348             {"",S_FALSE,FALSE},
1349             {"",S_FALSE,FALSE},
1350         },
1351         {
1352             {Uri_HOST_IPV6,S_OK,FALSE},
1353             {80,S_OK,FALSE},
1354             {URL_SCHEME_HTTP,S_OK,FALSE},
1355             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1356         }
1357     },
1358     {   "http://[v2.34]/", 0, S_OK, FALSE,
1359         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
1360         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1361         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1362         FALSE,
1363         {
1364             {"http://[v2.34]/",S_OK,FALSE},
1365             {"[v2.34]",S_OK,FALSE},
1366             {"http://[v2.34]/",S_OK,FALSE},
1367             {"",S_FALSE,FALSE},
1368             {"",S_FALSE,FALSE},
1369             {"",S_FALSE,FALSE},
1370             {"[v2.34]",S_OK,FALSE},
1371             {"",S_FALSE,FALSE},
1372             {"/",S_OK,FALSE},
1373             {"/",S_OK,FALSE},
1374             {"",S_FALSE,FALSE},
1375             {"http://[v2.34]/",S_OK,FALSE},
1376             {"http",S_OK,FALSE},
1377             {"",S_FALSE,FALSE},
1378             {"",S_FALSE,FALSE}
1379         },
1380         {
1381             {Uri_HOST_UNKNOWN,S_OK,FALSE},
1382             {80,S_OK,FALSE},
1383             {URL_SCHEME_HTTP,S_OK,FALSE},
1384             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1385         }
1386     },
1387     /* Windows ignores ':' if they appear after a '[' on a non-IPLiteral host. */
1388     {   "http://[xyz:12345.com/test", 0, S_OK, FALSE,
1389         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
1390         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
1391         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1392         FALSE,
1393         {
1394             {"http://[xyz:12345.com/test",S_OK,FALSE},
1395             {"[xyz:12345.com",S_OK,FALSE},
1396             {"http://[xyz:12345.com/test",S_OK,FALSE},
1397             {"[xyz:12345.com",S_OK,FALSE},
1398             {"",S_FALSE,FALSE},
1399             {"",S_FALSE,FALSE},
1400             {"[xyz:12345.com",S_OK,FALSE},
1401             {"",S_FALSE,FALSE},
1402             {"/test",S_OK,FALSE},
1403             {"/test",S_OK,FALSE},
1404             {"",S_FALSE,FALSE},
1405             {"http://[xyz:12345.com/test",S_OK,FALSE},
1406             {"http",S_OK,FALSE},
1407             {"",S_FALSE,FALSE},
1408             {"",S_FALSE,FALSE}
1409         },
1410         {
1411             {Uri_HOST_DNS,S_OK,FALSE},
1412             {80,S_OK,FALSE},
1413             {URL_SCHEME_HTTP,S_OK,FALSE},
1414             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1415         }
1416     },
1417     /* Valid URI since the '[' and ']' don't appear at the beginning and end
1418      * of the host name (respectively).
1419      */
1420     {   "ftp://www.[works].com/", 0, S_OK, FALSE,
1421         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
1422         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
1423         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1424         FALSE,
1425         {
1426             {"ftp://www.[works].com/",S_OK,FALSE},
1427             {"www.[works].com",S_OK,FALSE},
1428             {"ftp://www.[works].com/",S_OK,FALSE},
1429             {"[works].com",S_OK,FALSE},
1430             {"",S_FALSE,FALSE},
1431             {"",S_FALSE,FALSE},
1432             {"www.[works].com",S_OK,FALSE},
1433             {"",S_FALSE,FALSE},
1434             {"/",S_OK,FALSE},
1435             {"/",S_OK,FALSE},
1436             {"",S_FALSE,FALSE},
1437             {"ftp://www.[works].com/",S_OK,FALSE},
1438             {"ftp",S_OK,FALSE},
1439             {"",S_FALSE,FALSE},
1440             {"",S_FALSE,FALSE}
1441         },
1442         {
1443             {Uri_HOST_DNS,S_OK,FALSE},
1444             {21,S_OK,FALSE},
1445             {URL_SCHEME_FTP,S_OK,FALSE},
1446             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1447         }
1448     },
1449     /* Considers ':' a delimiter since it appears after the ']'. */
1450     {   "http://www.google.com]:12345/", 0, S_OK, FALSE,
1451         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
1452         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
1453         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1454         FALSE,
1455         {
1456             {"http://www.google.com]:12345/",S_OK,FALSE},
1457             {"www.google.com]:12345",S_OK,FALSE},
1458             {"http://www.google.com]:12345/",S_OK,FALSE},
1459             {"google.com]",S_OK,FALSE},
1460             {"",S_FALSE,FALSE},
1461             {"",S_FALSE,FALSE},
1462             {"www.google.com]",S_OK,FALSE},
1463             {"",S_FALSE,FALSE},
1464             {"/",S_OK,FALSE},
1465             {"/",S_OK,FALSE},
1466             {"",S_FALSE,FALSE},
1467             {"http://www.google.com]:12345/",S_OK,FALSE},
1468             {"http",S_OK,FALSE},
1469             {"",S_FALSE,FALSE},
1470             {"",S_FALSE,FALSE}
1471         },
1472         {
1473             {Uri_HOST_DNS,S_OK,FALSE},
1474             {12345,S_OK,FALSE},
1475             {URL_SCHEME_HTTP,S_OK,FALSE},
1476             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1477         }
1478     },
1479     /* Unknown scheme types can have invalid % encoded data in the hostname. */
1480     {   "zip://w%XXw%GEw.google.com/", 0, S_OK, FALSE,
1481         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
1482         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
1483         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
1484         FALSE,
1485         {
1486             {"zip://w%XXw%GEw.google.com/",S_OK,FALSE},
1487             {"w%XXw%GEw.google.com",S_OK,FALSE},
1488             {"zip://w%XXw%GEw.google.com/",S_OK,FALSE},
1489             {"google.com",S_OK,FALSE},
1490             {"",S_FALSE,FALSE},
1491             {"",S_FALSE,FALSE},
1492             {"w%XXw%GEw.google.com",S_OK,FALSE},
1493             {"",S_FALSE,FALSE},
1494             {"/",S_OK,FALSE},
1495             {"/",S_OK,FALSE},
1496             {"",S_FALSE,FALSE},
1497             {"zip://w%XXw%GEw.google.com/",S_OK,FALSE},
1498             {"zip",S_OK,FALSE},
1499             {"",S_FALSE,FALSE},
1500             {"",S_FALSE,FALSE}
1501         },
1502         {
1503             {Uri_HOST_DNS,S_OK,FALSE},
1504             {0,S_FALSE,FALSE},
1505             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1506             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1507         }
1508     },
1509     /* Unknown scheme types hostname doesn't get lower cased. */
1510     {   "zip://GOOGLE.com/", 0, S_OK, FALSE,
1511         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
1512         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
1513         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
1514         FALSE,
1515         {
1516             {"zip://GOOGLE.com/",S_OK,FALSE},
1517             {"GOOGLE.com",S_OK,FALSE},
1518             {"zip://GOOGLE.com/",S_OK,FALSE},
1519             {"GOOGLE.com",S_OK,FALSE},
1520             {"",S_FALSE,FALSE},
1521             {"",S_FALSE,FALSE},
1522             {"GOOGLE.com",S_OK,FALSE},
1523             {"",S_FALSE,FALSE},
1524             {"/",S_OK,FALSE},
1525             {"/",S_OK,FALSE},
1526             {"",S_FALSE,FALSE},
1527             {"zip://GOOGLE.com/",S_OK,FALSE},
1528             {"zip",S_OK,FALSE},
1529             {"",S_FALSE,FALSE},
1530             {"",S_FALSE,FALSE}
1531         },
1532         {
1533             {Uri_HOST_DNS,S_OK,FALSE},
1534             {0,S_FALSE,FALSE},
1535             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1536             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1537         }
1538     },
1539     /* Hostname get's lower cased for known scheme types. */
1540     {   "http://WWW.GOOGLE.com/", 0, S_OK, FALSE,
1541         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
1542         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
1543         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1544         FALSE,
1545         {
1546             {"http://www.google.com/",S_OK,FALSE},
1547             {"www.google.com",S_OK,FALSE},
1548             {"http://www.google.com/",S_OK,FALSE},
1549             {"google.com",S_OK,FALSE},
1550             {"",S_FALSE,FALSE},
1551             {"",S_FALSE,FALSE},
1552             {"www.google.com",S_OK,FALSE},
1553             {"",S_FALSE,FALSE},
1554             {"/",S_OK,FALSE},
1555             {"/",S_OK,FALSE},
1556             {"",S_FALSE,FALSE},
1557             {"http://WWW.GOOGLE.com/",S_OK,FALSE},
1558             {"http",S_OK,FALSE},
1559             {"",S_FALSE,FALSE},
1560             {"",S_FALSE,FALSE}
1561         },
1562         {
1563             {Uri_HOST_DNS,S_OK,FALSE},
1564             {80,S_OK,FALSE},
1565             {URL_SCHEME_HTTP,S_OK,FALSE},
1566             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1567         }
1568     },
1569     /* Characters that get % encoded in the hostname also have their percent
1570      * encoded forms lower cased.
1571      */
1572     {   "http://www.%7Cgoogle|.com/", 0, S_OK, FALSE,
1573         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
1574         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
1575         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1576         FALSE,
1577         {
1578             {"http://www.%7cgoogle%7c.com/",S_OK,FALSE},
1579             {"www.%7cgoogle%7c.com",S_OK,FALSE},
1580             {"http://www.%7cgoogle%7c.com/",S_OK,FALSE},
1581             {"%7cgoogle%7c.com",S_OK,FALSE},
1582             {"",S_FALSE,FALSE},
1583             {"",S_FALSE,FALSE},
1584             {"www.%7cgoogle%7c.com",S_OK,FALSE},
1585             {"",S_FALSE,FALSE},
1586             {"/",S_OK,FALSE},
1587             {"/",S_OK,FALSE},
1588             {"",S_FALSE,FALSE},
1589             {"http://www.%7Cgoogle|.com/",S_OK,FALSE},
1590             {"http",S_OK,FALSE},
1591             {"",S_FALSE,FALSE},
1592             {"",S_FALSE,FALSE}
1593         },
1594         {
1595             {Uri_HOST_DNS,S_OK,FALSE},
1596             {80,S_OK,FALSE},
1597             {URL_SCHEME_HTTP,S_OK,FALSE},
1598             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1599         }
1600     },
1601     /* IPv4 addresses attached to IPv6 can be included in elisions. */
1602     {   "http://[1:2:3:4:5:6:0.0.0.0]", 0, S_OK, FALSE,
1603         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
1604         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1605         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1606         FALSE,
1607         {
1608             {"http://[1:2:3:4:5:6::]/",S_OK,FALSE},
1609             {"[1:2:3:4:5:6::]",S_OK,FALSE},
1610             {"http://[1:2:3:4:5:6::]/",S_OK,FALSE},
1611             {"",S_FALSE,FALSE},
1612             {"",S_FALSE,FALSE},
1613             {"",S_FALSE,FALSE},
1614             {"1:2:3:4:5:6::",S_OK,FALSE},
1615             {"",S_FALSE,FALSE},
1616             {"/",S_OK,FALSE},
1617             {"/",S_OK,FALSE},
1618             {"",S_FALSE,FALSE},
1619             {"http://[1:2:3:4:5:6:0.0.0.0]",S_OK,FALSE},
1620             {"http",S_OK,FALSE},
1621             {"",S_FALSE,FALSE},
1622             {"",S_FALSE,FALSE},
1623         },
1624         {
1625             {Uri_HOST_IPV6,S_OK,FALSE},
1626             {80,S_OK,FALSE},
1627             {URL_SCHEME_HTTP,S_OK,FALSE},
1628             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1629         }
1630     },
1631     /* IPv4 addresses get normalized. */
1632     {   "http://[::001.002.003.000]", 0, S_OK, FALSE,
1633         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
1634         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1635         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1636         FALSE,
1637         {
1638             {"http://[::1.2.3.0]/",S_OK,FALSE},
1639             {"[::1.2.3.0]",S_OK,FALSE},
1640             {"http://[::1.2.3.0]/",S_OK,FALSE},
1641             {"",S_FALSE,FALSE},
1642             {"",S_FALSE,FALSE},
1643             {"",S_FALSE,FALSE},
1644             {"::1.2.3.0",S_OK,FALSE},
1645             {"",S_FALSE,FALSE},
1646             {"/",S_OK,FALSE},
1647             {"/",S_OK,FALSE},
1648             {"",S_FALSE,FALSE},
1649             {"http://[::001.002.003.000]",S_OK,FALSE},
1650             {"http",S_OK,FALSE},
1651             {"",S_FALSE,FALSE},
1652             {"",S_FALSE,FALSE},
1653         },
1654         {
1655             {Uri_HOST_IPV6,S_OK,FALSE},
1656             {80,S_OK,FALSE},
1657             {URL_SCHEME_HTTP,S_OK,FALSE},
1658             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1659         }
1660     },
1661     /* Windows doesn't do anything to IPv6's in unknown schemes. */
1662     {   "zip://[0001:0:000:0004:0005:0006:001.002.003.000]", 0, S_OK, FALSE,
1663         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
1664         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1665         Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
1666         FALSE,
1667         {
1668             {"zip://[0001:0:000:0004:0005:0006:001.002.003.000]/",S_OK,FALSE},
1669             {"[0001:0:000:0004:0005:0006:001.002.003.000]",S_OK,FALSE},
1670             {"zip://[0001:0:000:0004:0005:0006:001.002.003.000]/",S_OK,FALSE},
1671             {"",S_FALSE,FALSE},
1672             {"",S_FALSE,FALSE},
1673             {"",S_FALSE,FALSE},
1674             {"0001:0:000:0004:0005:0006:001.002.003.000",S_OK,FALSE},
1675             {"",S_FALSE,FALSE},
1676             {"/",S_OK,FALSE},
1677             {"/",S_OK,FALSE},
1678             {"",S_FALSE,FALSE},
1679             {"zip://[0001:0:000:0004:0005:0006:001.002.003.000]",S_OK,FALSE},
1680             {"zip",S_OK,FALSE},
1681             {"",S_FALSE,FALSE},
1682             {"",S_FALSE,FALSE},
1683         },
1684         {
1685             {Uri_HOST_IPV6,S_OK,FALSE},
1686             {0,S_FALSE,FALSE},
1687             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1688             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1689         }
1690     },
1691     /* IPv4 address is converted into 2 h16 components. */
1692     {   "http://[ffff::192.222.111.32]", 0, S_OK, FALSE,
1693         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
1694         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1695         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1696         FALSE,
1697         {
1698             {"http://[ffff::c0de:6f20]/",S_OK,FALSE},
1699             {"[ffff::c0de:6f20]",S_OK,FALSE},
1700             {"http://[ffff::c0de:6f20]/",S_OK,FALSE},
1701             {"",S_FALSE,FALSE},
1702             {"",S_FALSE,FALSE},
1703             {"",S_FALSE,FALSE},
1704             {"ffff::c0de:6f20",S_OK,FALSE},
1705             {"",S_FALSE,FALSE},
1706             {"/",S_OK,FALSE},
1707             {"/",S_OK,FALSE},
1708             {"",S_FALSE,FALSE},
1709             {"http://[ffff::192.222.111.32]",S_OK,FALSE},
1710             {"http",S_OK,FALSE},
1711             {"",S_FALSE,FALSE},
1712             {"",S_FALSE,FALSE},
1713         },
1714         {
1715             {Uri_HOST_IPV6,S_OK,FALSE},
1716             {80,S_OK,FALSE},
1717             {URL_SCHEME_HTTP,S_OK,FALSE},
1718             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1719         }
1720     },
1721     /* Max value for a port. */
1722     {   "http://google.com:65535", 0, S_OK, FALSE,
1723         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
1724         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1725         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1726         FALSE,
1727         {
1728             {"http://google.com:65535/",S_OK,FALSE},
1729             {"google.com:65535",S_OK,FALSE},
1730             {"http://google.com:65535/",S_OK,FALSE},
1731             {"google.com",S_OK,FALSE},
1732             {"",S_FALSE,FALSE},
1733             {"",S_FALSE,FALSE},
1734             {"google.com",S_OK,FALSE},
1735             {"",S_FALSE,FALSE},
1736             {"/",S_OK,FALSE},
1737             {"/",S_OK,FALSE},
1738             {"",S_FALSE,FALSE},
1739             {"http://google.com:65535",S_OK,FALSE},
1740             {"http",S_OK,FALSE},
1741             {"",S_FALSE,FALSE},
1742             {"",S_FALSE,FALSE}
1743         },
1744         {
1745             {Uri_HOST_DNS,S_OK,FALSE},
1746             {65535,S_OK,FALSE},
1747             {URL_SCHEME_HTTP,S_OK,FALSE},
1748             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1749         }
1750     },
1751     {   "zip://google.com:65536", 0, S_OK, FALSE,
1752         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
1753         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1754         Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
1755         FALSE,
1756         {
1757             {"zip://google.com:65536/",S_OK,FALSE},
1758             {"google.com:65536",S_OK,FALSE},
1759             {"zip://google.com:65536/",S_OK,FALSE},
1760             {"google.com:65536",S_OK,FALSE},
1761             {"",S_FALSE,FALSE},
1762             {"",S_FALSE,FALSE},
1763             {"google.com:65536",S_OK,FALSE},
1764             {"",S_FALSE,FALSE},
1765             {"/",S_OK,FALSE},
1766             {"/",S_OK,FALSE},
1767             {"",S_FALSE,FALSE},
1768             {"zip://google.com:65536",S_OK,FALSE},
1769             {"zip",S_OK,FALSE},
1770             {"",S_FALSE,FALSE},
1771             {"",S_FALSE,FALSE}
1772         },
1773         {
1774             {Uri_HOST_DNS,S_OK,FALSE},
1775             {0,S_FALSE,FALSE},
1776             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1777             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1778         }
1779     },
1780     {   "zip://google.com:65536:25", 0, S_OK, FALSE,
1781         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
1782         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1783         Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
1784         FALSE,
1785         {
1786             {"zip://google.com:65536:25/",S_OK,FALSE},
1787             {"google.com:65536:25",S_OK,FALSE},
1788             {"zip://google.com:65536:25/",S_OK,FALSE},
1789             {"google.com:65536:25",S_OK,FALSE},
1790             {"",S_FALSE,FALSE},
1791             {"",S_FALSE,FALSE},
1792             {"google.com:65536:25",S_OK,FALSE},
1793             {"",S_FALSE,FALSE},
1794             {"/",S_OK,FALSE},
1795             {"/",S_OK,FALSE},
1796             {"",S_FALSE,FALSE},
1797             {"zip://google.com:65536:25",S_OK,FALSE},
1798             {"zip",S_OK,FALSE},
1799             {"",S_FALSE,FALSE},
1800             {"",S_FALSE,FALSE}
1801         },
1802         {
1803             {Uri_HOST_DNS,S_OK,FALSE},
1804             {0,S_FALSE,FALSE},
1805             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1806             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1807         }
1808     },
1809     {   "zip://[::ffff]:abcd", 0, S_OK, FALSE,
1810         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|
1811         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1812         Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
1813         FALSE,
1814         {
1815             {"zip://[::ffff]:abcd/",S_OK,FALSE},
1816             {"[::ffff]:abcd",S_OK,FALSE},
1817             {"zip://[::ffff]:abcd/",S_OK,FALSE},
1818             {"",S_FALSE,FALSE},
1819             {"",S_FALSE,FALSE},
1820             {"",S_FALSE,FALSE},
1821             {"[::ffff]:abcd",S_OK,FALSE},
1822             {"",S_FALSE,FALSE},
1823             {"/",S_OK,FALSE},
1824             {"/",S_OK,FALSE},
1825             {"",S_FALSE,FALSE},
1826             {"zip://[::ffff]:abcd",S_OK,FALSE},
1827             {"zip",S_OK,FALSE},
1828             {"",S_FALSE,FALSE},
1829             {"",S_FALSE,FALSE}
1830         },
1831         {
1832             {Uri_HOST_DNS,S_OK,FALSE},
1833             {0,S_FALSE,FALSE},
1834             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1835             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1836         }
1837     },
1838     {   "zip://127.0.0.1:abcd", 0, S_OK, FALSE,
1839         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
1840         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1841         Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
1842         FALSE,
1843         {
1844             {"zip://127.0.0.1:abcd/",S_OK,FALSE},
1845             {"127.0.0.1:abcd",S_OK,FALSE},
1846             {"zip://127.0.0.1:abcd/",S_OK,FALSE},
1847             {"0.1:abcd",S_OK,FALSE},
1848             {"",S_FALSE,FALSE},
1849             {"",S_FALSE,FALSE},
1850             {"127.0.0.1:abcd",S_OK,FALSE},
1851             {"",S_FALSE,FALSE},
1852             {"/",S_OK,FALSE},
1853             {"/",S_OK,FALSE},
1854             {"",S_FALSE,FALSE},
1855             {"zip://127.0.0.1:abcd",S_OK,FALSE},
1856             {"zip",S_OK,FALSE},
1857             {"",S_FALSE,FALSE},
1858             {"",S_FALSE,FALSE}
1859         },
1860         {
1861             {Uri_HOST_DNS,S_OK,FALSE},
1862             {0,S_FALSE,FALSE},
1863             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1864             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1865         }
1866     },
1867     /* Port is just copied over. */
1868     {   "http://google.com:00035", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
1869         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
1870         Uri_HAS_HOST|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1871         FALSE,
1872         {
1873             {"http://google.com:00035",S_OK,FALSE},
1874             {"google.com:00035",S_OK,FALSE},
1875             {"http://google.com:00035",S_OK,FALSE,"http://google.com:35"},
1876             {"google.com",S_OK,FALSE},
1877             {"",S_FALSE,FALSE},
1878             {"",S_FALSE,FALSE},
1879             {"google.com",S_OK,FALSE},
1880             {"",S_FALSE,FALSE},
1881             {"",S_FALSE,FALSE},
1882             {"",S_FALSE,FALSE},
1883             {"",S_FALSE,FALSE},
1884             {"http://google.com:00035",S_OK,FALSE},
1885             {"http",S_OK,FALSE},
1886             {"",S_FALSE,FALSE},
1887             {"",S_FALSE,FALSE}
1888         },
1889         {
1890             {Uri_HOST_DNS,S_OK,FALSE},
1891             {35,S_OK,FALSE},
1892             {URL_SCHEME_HTTP,S_OK,FALSE},
1893             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1894         }
1895     },
1896     /* Default port is copied over. */
1897     {   "http://google.com:80", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
1898         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
1899         Uri_HAS_HOST|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1900         FALSE,
1901         {
1902             {"http://google.com:80",S_OK,FALSE},
1903             {"google.com:80",S_OK,FALSE},
1904             {"http://google.com:80",S_OK,FALSE},
1905             {"google.com",S_OK,FALSE},
1906             {"",S_FALSE,FALSE},
1907             {"",S_FALSE,FALSE},
1908             {"google.com",S_OK,FALSE},
1909             {"",S_FALSE,FALSE},
1910             {"",S_FALSE,FALSE},
1911             {"",S_FALSE,FALSE},
1912             {"",S_FALSE,FALSE},
1913             {"http://google.com:80",S_OK,FALSE},
1914             {"http",S_OK,FALSE},
1915             {"",S_FALSE,FALSE},
1916             {"",S_FALSE,FALSE}
1917         },
1918         {
1919             {Uri_HOST_DNS,S_OK,FALSE},
1920             {80,S_OK,FALSE},
1921             {URL_SCHEME_HTTP,S_OK,FALSE},
1922             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1923         }
1924     },
1925     {   "http://google.com.uk", 0, S_OK, FALSE,
1926         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
1927         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1928         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1929         FALSE,
1930         {
1931             {"http://google.com.uk/",S_OK,FALSE},
1932             {"google.com.uk",S_OK,FALSE},
1933             {"http://google.com.uk/",S_OK,FALSE},
1934             {"google.com.uk",S_OK,FALSE},
1935             {"",S_FALSE,FALSE},
1936             {"",S_FALSE,FALSE},
1937             {"google.com.uk",S_OK,FALSE},
1938             {"",S_FALSE,FALSE},
1939             {"/",S_OK,FALSE},
1940             {"/",S_OK,FALSE},
1941             {"",S_FALSE,FALSE},
1942             {"http://google.com.uk",S_OK,FALSE},
1943             {"http",S_OK,FALSE},
1944             {"",S_FALSE,FALSE},
1945             {"",S_FALSE,FALSE}
1946         },
1947         {
1948             {Uri_HOST_DNS,S_OK,FALSE},
1949             {80,S_OK,FALSE},
1950             {URL_SCHEME_HTTP,S_OK,FALSE},
1951             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1952         }
1953     },
1954     {   "http://google.com.com", 0, S_OK, FALSE,
1955         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
1956         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1957         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1958         FALSE,
1959         {
1960             {"http://google.com.com/",S_OK,FALSE},
1961             {"google.com.com",S_OK,FALSE},
1962             {"http://google.com.com/",S_OK,FALSE},
1963             {"com.com",S_OK,FALSE},
1964             {"",S_FALSE,FALSE},
1965             {"",S_FALSE,FALSE},
1966             {"google.com.com",S_OK,FALSE},
1967             {"",S_FALSE,FALSE},
1968             {"/",S_OK,FALSE},
1969             {"/",S_OK,FALSE},
1970             {"",S_FALSE,FALSE},
1971             {"http://google.com.com",S_OK,FALSE},
1972             {"http",S_OK,FALSE},
1973             {"",S_FALSE,FALSE},
1974             {"",S_FALSE,FALSE}
1975         },
1976         {
1977             {Uri_HOST_DNS,S_OK,FALSE},
1978             {80,S_OK,FALSE},
1979             {URL_SCHEME_HTTP,S_OK,FALSE},
1980             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1981         }
1982     },
1983     {   "http://google.uk.1", 0, S_OK, FALSE,
1984         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
1985         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1986         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1987         FALSE,
1988         {
1989             {"http://google.uk.1/",S_OK,FALSE},
1990             {"google.uk.1",S_OK,FALSE},
1991             {"http://google.uk.1/",S_OK,FALSE},
1992             {"google.uk.1",S_OK,FALSE},
1993             {"",S_FALSE,FALSE},
1994             {"",S_FALSE,FALSE},
1995             {"google.uk.1",S_OK,FALSE},
1996             {"",S_FALSE,FALSE},
1997             {"/",S_OK,FALSE},
1998             {"/",S_OK,FALSE},
1999             {"",S_FALSE,FALSE},
2000             {"http://google.uk.1",S_OK,FALSE},
2001             {"http",S_OK,FALSE},
2002             {"",S_FALSE,FALSE},
2003             {"",S_FALSE,FALSE}
2004         },
2005         {
2006             {Uri_HOST_DNS,S_OK,FALSE},
2007             {80,S_OK,FALSE},
2008             {URL_SCHEME_HTTP,S_OK,FALSE},
2009             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2010         }
2011     },
2012     /* Since foo isn't a recognized 3 character TLD its considered the domain name. */
2013     {   "http://google.foo.uk", 0, S_OK, FALSE,
2014         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
2015         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
2016         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
2017         FALSE,
2018         {
2019             {"http://google.foo.uk/",S_OK,FALSE},
2020             {"google.foo.uk",S_OK,FALSE},
2021             {"http://google.foo.uk/",S_OK,FALSE},
2022             {"foo.uk",S_OK,FALSE},
2023             {"",S_FALSE,FALSE},
2024             {"",S_FALSE,FALSE},
2025             {"google.foo.uk",S_OK,FALSE},
2026             {"",S_FALSE,FALSE},
2027             {"/",S_OK,FALSE},
2028             {"/",S_OK,FALSE},
2029             {"",S_FALSE,FALSE},
2030             {"http://google.foo.uk",S_OK,FALSE},
2031             {"http",S_OK,FALSE},
2032             {"",S_FALSE,FALSE},
2033             {"",S_FALSE,FALSE}
2034         },
2035         {
2036             {Uri_HOST_DNS,S_OK,FALSE},
2037             {80,S_OK,FALSE},
2038             {URL_SCHEME_HTTP,S_OK,FALSE},
2039             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2040         }
2041     },
2042     {   "http://.com", 0, S_OK, FALSE,
2043         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
2044         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
2045         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
2046         FALSE,
2047         {
2048             {"http://.com/",S_OK,FALSE},
2049             {".com",S_OK,FALSE},
2050             {"http://.com/",S_OK,FALSE},
2051             {".com",S_OK,FALSE},
2052             {"",S_FALSE,FALSE},
2053             {"",S_FALSE,FALSE},
2054             {".com",S_OK,FALSE},
2055             {"",S_FALSE,FALSE},
2056             {"/",S_OK,FALSE},
2057             {"/",S_OK,FALSE},
2058             {"",S_FALSE,FALSE},
2059             {"http://.com",S_OK,FALSE},
2060             {"http",S_OK,FALSE},
2061             {"",S_FALSE,FALSE},
2062             {"",S_FALSE,FALSE}
2063         },
2064         {
2065             {Uri_HOST_DNS,S_OK,FALSE},
2066             {80,S_OK,FALSE},
2067             {URL_SCHEME_HTTP,S_OK,FALSE},
2068             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2069         }
2070     },
2071     {   "http://.uk", 0, S_OK, FALSE,
2072         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
2073         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
2074         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
2075         FALSE,
2076         {
2077             {"http://.uk/",S_OK,FALSE},
2078             {".uk",S_OK,FALSE},
2079             {"http://.uk/",S_OK,FALSE},
2080             {"",S_FALSE,FALSE},
2081             {"",S_FALSE,FALSE},
2082             {"",S_FALSE,FALSE},
2083             {".uk",S_OK,FALSE},
2084             {"",S_FALSE,FALSE},
2085             {"/",S_OK,FALSE},
2086             {"/",S_OK,FALSE},
2087             {"",S_FALSE,FALSE},
2088             {"http://.uk",S_OK,FALSE},
2089             {"http",S_OK,FALSE},
2090             {"",S_FALSE,FALSE},
2091             {"",S_FALSE,FALSE}
2092         },
2093         {
2094             {Uri_HOST_DNS,S_OK,FALSE},
2095             {80,S_OK,FALSE},
2096             {URL_SCHEME_HTTP,S_OK,FALSE},
2097             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2098         }
2099     },
2100     {   "http://www.co.google.com.[]", 0, S_OK, FALSE,
2101         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
2102         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
2103         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
2104         FALSE,
2105         {
2106             {"http://www.co.google.com.[]/",S_OK,FALSE},
2107             {"www.co.google.com.[]",S_OK,FALSE},
2108             {"http://www.co.google.com.[]/",S_OK,FALSE},
2109             {"google.com.[]",S_OK,FALSE},
2110             {"",S_FALSE,FALSE},
2111             {"",S_FALSE,FALSE},
2112             {"www.co.google.com.[]",S_OK,FALSE},
2113             {"",S_FALSE,FALSE},
2114             {"/",S_OK,FALSE},
2115             {"/",S_OK,FALSE},
2116             {"",S_FALSE,FALSE},
2117             {"http://www.co.google.com.[]",S_OK,FALSE},
2118             {"http",S_OK,FALSE},
2119             {"",S_FALSE,FALSE},
2120             {"",S_FALSE,FALSE}
2121         },
2122         {
2123             {Uri_HOST_DNS,S_OK,FALSE},
2124             {80,S_OK,FALSE},
2125             {URL_SCHEME_HTTP,S_OK,FALSE},
2126             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2127         }
2128     },
2129     {   "http://co.uk", 0, S_OK, FALSE,
2130         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
2131         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
2132         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
2133         FALSE,
2134         {
2135             {"http://co.uk/",S_OK,FALSE},
2136             {"co.uk",S_OK,FALSE},
2137             {"http://co.uk/",S_OK,FALSE},
2138             {"",S_FALSE,FALSE},
2139             {"",S_FALSE,FALSE},
2140             {"",S_FALSE,FALSE},
2141             {"co.uk",S_OK,FALSE},
2142             {"",S_FALSE,FALSE},
2143             {"/",S_OK,FALSE},
2144             {"/",S_OK,FALSE},
2145             {"",S_FALSE,FALSE},
2146             {"http://co.uk",S_OK,FALSE},
2147             {"http",S_OK,FALSE},
2148             {"",S_FALSE,FALSE},
2149             {"",S_FALSE,FALSE}
2150         },
2151         {
2152             {Uri_HOST_DNS,S_OK,FALSE},
2153             {80,S_OK,FALSE},
2154             {URL_SCHEME_HTTP,S_OK,FALSE},
2155             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2156         }
2157     },
2158     {   "http://www.co.google.us.test", 0, S_OK, FALSE,
2159         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
2160         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
2161         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
2162         FALSE,
2163         {
2164             {"http://www.co.google.us.test/",S_OK,FALSE},
2165             {"www.co.google.us.test",S_OK,FALSE},
2166             {"http://www.co.google.us.test/",S_OK,FALSE},
2167             {"us.test",S_OK,FALSE},
2168             {"",S_FALSE,FALSE},
2169             {"",S_FALSE,FALSE},
2170             {"www.co.google.us.test",S_OK,FALSE},
2171             {"",S_FALSE,FALSE},
2172             {"/",S_OK,FALSE},
2173             {"/",S_OK,FALSE},
2174             {"",S_FALSE,FALSE},
2175             {"http://www.co.google.us.test",S_OK,FALSE},
2176             {"http",S_OK,FALSE},
2177             {"",S_FALSE,FALSE},
2178             {"",S_FALSE,FALSE}
2179         },
2180         {
2181             {Uri_HOST_DNS,S_OK,FALSE},
2182             {80,S_OK,FALSE},
2183             {URL_SCHEME_HTTP,S_OK,FALSE},
2184             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2185         }
2186     },
2187     {   "http://gov.uk", 0, S_OK, FALSE,
2188         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
2189         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
2190         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
2191         FALSE,
2192         {
2193             {"http://gov.uk/",S_OK,FALSE},
2194             {"gov.uk",S_OK,FALSE},
2195             {"http://gov.uk/",S_OK,FALSE},
2196             {"",S_FALSE,FALSE},
2197             {"",S_FALSE,FALSE},
2198             {"",S_FALSE,FALSE},
2199             {"gov.uk",S_OK,FALSE},
2200             {"",S_FALSE,FALSE},
2201             {"/",S_OK,FALSE},
2202             {"/",S_OK,FALSE},
2203             {"",S_FALSE,FALSE},
2204             {"http://gov.uk",S_OK,FALSE},
2205             {"http",S_OK,FALSE},
2206             {"",S_FALSE,FALSE},
2207             {"",S_FALSE,FALSE}
2208         },
2209         {
2210             {Uri_HOST_DNS,S_OK,FALSE},
2211             {80,S_OK,FALSE},
2212             {URL_SCHEME_HTTP,S_OK,FALSE},
2213             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2214         }
2215     },
2216     {   "zip://www.google.com\\test", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
2217         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
2218         Uri_HAS_HOST|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
2219         FALSE,
2220         {
2221             {"zip://www.google.com\\test",S_OK,FALSE},
2222             {"www.google.com\\test",S_OK,FALSE},
2223             {"zip://www.google.com\\test",S_OK,FALSE},
2224             {"google.com\\test",S_OK,FALSE},
2225             {"",S_FALSE,FALSE},
2226             {"",S_FALSE,FALSE},
2227             {"www.google.com\\test",S_OK,FALSE},
2228             {"",S_FALSE,FALSE},
2229             {"",S_FALSE,FALSE},
2230             {"",S_FALSE,FALSE},
2231             {"",S_FALSE,FALSE},
2232             {"zip://www.google.com\\test",S_OK,FALSE},
2233             {"zip",S_OK,FALSE},
2234             {"",S_FALSE,FALSE},
2235             {"",S_FALSE,FALSE}
2236         },
2237         {
2238             {Uri_HOST_DNS,S_OK,FALSE},
2239             {0,S_FALSE,FALSE},
2240             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2241             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2242         }
2243     },
2244     {   "urn:excepts:bad:%XY:encoded", 0, S_OK, FALSE,
2245         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|
2246         Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
2247         FALSE,
2248         {
2249             {"urn:excepts:bad:%XY:encoded",S_OK,FALSE},
2250             {"",S_FALSE,FALSE},
2251             {"urn:excepts:bad:%XY:encoded",S_OK,FALSE},
2252             {"",S_FALSE,FALSE},
2253             {"",S_FALSE,FALSE},
2254             {"",S_FALSE,FALSE},
2255             {"",S_FALSE,FALSE},
2256             {"",S_FALSE,FALSE},
2257             {"excepts:bad:%XY:encoded",S_OK,FALSE},
2258             {"excepts:bad:%XY:encoded",S_OK,FALSE},
2259             {"",S_FALSE,FALSE},
2260             {"urn:excepts:bad:%XY:encoded",S_OK,FALSE},
2261             {"urn",S_OK,FALSE},
2262             {"",S_FALSE,FALSE},
2263             {"",S_FALSE,FALSE}
2264         },
2265         {
2266             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2267             {0,S_FALSE,FALSE},
2268             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2269             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2270         }
2271     },
2272     /* Since the original URI doesn't contain an extra '/' before the path no % encoded values
2273      * are decoded and all '%' are encoded.
2274      */
2275     {   "file://C:/te%3Es%2Et/tes%t.mp3", 0, S_OK, FALSE,
2276         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH|
2277         Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
2278         FALSE,
2279         {
2280             {"file:///C:/te%253Es%252Et/tes%25t.mp3",S_OK,FALSE},
2281             {"",S_FALSE,FALSE},
2282             {"file:///C:/te%253Es%252Et/tes%25t.mp3",S_OK,FALSE},
2283             {"",S_FALSE,FALSE},
2284             {".mp3",S_OK,FALSE},
2285             {"",S_FALSE,FALSE},
2286             {"",S_FALSE,FALSE},
2287             {"",S_FALSE,FALSE},
2288             {"/C:/te%253Es%252Et/tes%25t.mp3",S_OK,FALSE},
2289             {"/C:/te%253Es%252Et/tes%25t.mp3",S_OK,FALSE},
2290             {"",S_FALSE,FALSE},
2291             {"file://C:/te%3Es%2Et/tes%t.mp3",S_OK,FALSE},
2292             {"file",S_OK,FALSE},
2293             {"",S_FALSE,FALSE},
2294             {"",S_FALSE,FALSE}
2295         },
2296         {
2297             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2298             {0,S_FALSE,FALSE},
2299             {URL_SCHEME_FILE,S_OK,FALSE},
2300             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2301         }
2302     },
2303     /* Since there's a '/' in front of the drive letter, any percent encoded, non-forbidden character
2304      * is decoded and only %'s in front of invalid hex digits are encoded.
2305      */
2306     {   "file:///C:/te%3Es%2Et/t%23es%t.mp3", 0, S_OK, FALSE,
2307         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH|
2308         Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
2309         FALSE,
2310         {
2311             {"file:///C:/te%3Es.t/t#es%25t.mp3",S_OK,FALSE},
2312             {"",S_FALSE,FALSE},
2313             {"file:///C:/te%3Es.t/t#es%25t.mp3",S_OK,FALSE},
2314             {"",S_FALSE,FALSE},
2315             {".mp3",S_OK,FALSE},
2316             {"",S_FALSE,FALSE},
2317             {"",S_FALSE,FALSE},
2318             {"",S_FALSE,FALSE},
2319             {"/C:/te%3Es.t/t#es%25t.mp3",S_OK,FALSE},
2320             {"/C:/te%3Es.t/t#es%25t.mp3",S_OK,FALSE},
2321             {"",S_FALSE,FALSE},
2322             {"file:///C:/te%3Es%2Et/t%23es%t.mp3",S_OK,FALSE},
2323             {"file",S_OK,FALSE},
2324             {"",S_FALSE,FALSE},
2325             {"",S_FALSE,FALSE}
2326         },
2327         {
2328             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2329             {0,S_FALSE,FALSE},
2330             {URL_SCHEME_FILE,S_OK,FALSE},
2331             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2332         }
2333     },
2334     /* Only unreserved percent encoded characters are decoded for known schemes that aren't file. */
2335     {   "http://[::001.002.003.000]/%3F%23%2E%54/test", 0, S_OK, FALSE,
2336         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
2337         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
2338         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
2339         FALSE,
2340         {
2341             {"http://[::1.2.3.0]/%3F%23.T/test",S_OK,FALSE},
2342             {"[::1.2.3.0]",S_OK,FALSE},
2343             {"http://[::1.2.3.0]/%3F%23.T/test",S_OK,FALSE},
2344             {"",S_FALSE,FALSE},
2345             {"",S_FALSE,FALSE},
2346             {"",S_FALSE,FALSE},
2347             {"::1.2.3.0",S_OK,FALSE},
2348             {"",S_FALSE,FALSE},
2349             {"/%3F%23.T/test",S_OK,FALSE},
2350             {"/%3F%23.T/test",S_OK,FALSE},
2351             {"",S_FALSE,FALSE},
2352             {"http://[::001.002.003.000]/%3F%23%2E%54/test",S_OK,FALSE},
2353             {"http",S_OK,FALSE},
2354             {"",S_FALSE,FALSE},
2355             {"",S_FALSE,FALSE},
2356         },
2357         {
2358             {Uri_HOST_IPV6,S_OK,FALSE},
2359             {80,S_OK,FALSE},
2360             {URL_SCHEME_HTTP,S_OK,FALSE},
2361             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2362         }
2363     },
2364     /* Forbidden characters are always encoded for file URIs. */
2365     {   "file:///C:/\"test\"/test.mp3", Uri_CREATE_NO_ENCODE_FORBIDDEN_CHARACTERS, S_OK, FALSE,
2366         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH|
2367         Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
2368         FALSE,
2369         {
2370             {"file:///C:/%22test%22/test.mp3",S_OK,FALSE},
2371             {"",S_FALSE,FALSE},
2372             {"file:///C:/%22test%22/test.mp3",S_OK,FALSE},
2373             {"",S_FALSE,FALSE},
2374             {".mp3",S_OK,FALSE},
2375             {"",S_FALSE,FALSE},
2376             {"",S_FALSE,FALSE},
2377             {"",S_FALSE,FALSE},
2378             {"/C:/%22test%22/test.mp3",S_OK,FALSE},
2379             {"/C:/%22test%22/test.mp3",S_OK,FALSE},
2380             {"",S_FALSE,FALSE},
2381             {"file:///C:/\"test\"/test.mp3",S_OK,FALSE},
2382             {"file",S_OK,FALSE},
2383             {"",S_FALSE,FALSE},
2384             {"",S_FALSE,FALSE}
2385         },
2386         {
2387             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2388             {0,S_FALSE,FALSE},
2389             {URL_SCHEME_FILE,S_OK,FALSE},
2390             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2391         }
2392     },
2393     /* Forbidden characters are never encoded for unknown scheme types. */
2394     {   "1234://4294967295/<|>\" test<|>", 0, S_OK, FALSE,
2395         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
2396         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
2397         Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
2398         FALSE,
2399         {
2400             {"1234://4294967295/<|>\" test<|>",S_OK,FALSE},
2401             {"4294967295",S_OK,FALSE},
2402             {"1234://4294967295/<|>\" test<|>",S_OK,FALSE},
2403             {"",S_FALSE,FALSE},
2404             {"",S_FALSE,FALSE},
2405             {"",S_FALSE,FALSE},
2406             {"4294967295",S_OK,FALSE},
2407             {"",S_FALSE,FALSE},
2408             {"/<|>\" test<|>",S_OK,FALSE},
2409             {"/<|>\" test<|>",S_OK,FALSE},
2410             {"",S_FALSE,FALSE},
2411             {"1234://4294967295/<|>\" test<|>",S_OK,FALSE},
2412             {"1234",S_OK,FALSE},
2413             {"",S_FALSE,FALSE},
2414             {"",S_FALSE,FALSE}
2415         },
2416         {
2417             {Uri_HOST_IPV4,S_OK,FALSE},
2418             {0,S_FALSE,FALSE},
2419             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2420             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2421         }
2422     },
2423     /* Make sure forbidden characters are percent encoded. */
2424     {   "http://gov.uk/<|> test<|>", 0, S_OK, FALSE,
2425         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
2426         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
2427         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
2428         FALSE,
2429         {
2430             {"http://gov.uk/%3C%7C%3E%20test%3C%7C%3E",S_OK,FALSE},
2431             {"gov.uk",S_OK,FALSE},
2432             {"http://gov.uk/%3C%7C%3E%20test%3C%7C%3E",S_OK,FALSE},
2433             {"",S_FALSE,FALSE},
2434             {"",S_FALSE,FALSE},
2435             {"",S_FALSE,FALSE},
2436             {"gov.uk",S_OK,FALSE},
2437             {"",S_FALSE,FALSE},
2438             {"/%3C%7C%3E%20test%3C%7C%3E",S_OK,FALSE},
2439             {"/%3C%7C%3E%20test%3C%7C%3E",S_OK,FALSE},
2440             {"",S_FALSE,FALSE},
2441             {"http://gov.uk/<|> test<|>",S_OK,FALSE},
2442             {"http",S_OK,FALSE},
2443             {"",S_FALSE,FALSE},
2444             {"",S_FALSE,FALSE}
2445         },
2446         {
2447             {Uri_HOST_DNS,S_OK,FALSE},
2448             {80,S_OK,FALSE},
2449             {URL_SCHEME_HTTP,S_OK,FALSE},
2450             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2451         }
2452     },
2453     {   "http://gov.uk/test/../test2/././../test3/.././././", 0, S_OK, FALSE,
2454         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
2455         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
2456         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
2457         FALSE,
2458         {
2459             {"http://gov.uk/",S_OK,FALSE},
2460             {"gov.uk",S_OK,FALSE},
2461             {"http://gov.uk/",S_OK,FALSE},
2462             {"",S_FALSE,FALSE},
2463             {"",S_FALSE,FALSE},
2464             {"",S_FALSE,FALSE},
2465             {"gov.uk",S_OK,FALSE},
2466             {"",S_FALSE,FALSE},
2467             {"/",S_OK,FALSE},
2468             {"/",S_OK,FALSE},
2469             {"",S_FALSE,FALSE},
2470             {"http://gov.uk/test/../test2/././../test3/.././././",S_OK,FALSE},
2471             {"http",S_OK,FALSE},
2472             {"",S_FALSE,FALSE},
2473             {"",S_FALSE,FALSE}
2474         },
2475         {
2476             {Uri_HOST_DNS,S_OK,FALSE},
2477             {80,S_OK,FALSE},
2478             {URL_SCHEME_HTTP,S_OK,FALSE},
2479             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2480         }
2481     },
2482     {   "http://gov.uk/test/test2/../../..", 0, S_OK, FALSE,
2483         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
2484         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
2485         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
2486         FALSE,
2487         {
2488             {"http://gov.uk/",S_OK,FALSE},
2489             {"gov.uk",S_OK,FALSE},
2490             {"http://gov.uk/",S_OK,FALSE},
2491             {"",S_FALSE,FALSE},
2492             {"",S_FALSE,FALSE},
2493             {"",S_FALSE,FALSE},
2494             {"gov.uk",S_OK,FALSE},
2495             {"",S_FALSE,FALSE},
2496             {"/",S_OK,FALSE},
2497             {"/",S_OK,FALSE},
2498             {"",S_FALSE,FALSE},
2499             {"http://gov.uk/test/test2/../../..",S_OK,FALSE},
2500             {"http",S_OK,FALSE},
2501             {"",S_FALSE,FALSE},
2502             {"",S_FALSE,FALSE}
2503         },
2504         {
2505             {Uri_HOST_DNS,S_OK,FALSE},
2506             {80,S_OK,FALSE},
2507             {URL_SCHEME_HTTP,S_OK,FALSE},
2508             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2509         }
2510     },
2511     {   "http://gov.uk/test/test2/../../.", 0, S_OK, FALSE,
2512         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
2513         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
2514         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
2515         FALSE,
2516         {
2517             {"http://gov.uk/",S_OK,FALSE},
2518             {"gov.uk",S_OK,FALSE},
2519             {"http://gov.uk/",S_OK,FALSE},
2520             {"",S_FALSE,FALSE},
2521             {"",S_FALSE,FALSE},
2522             {"",S_FALSE,FALSE},
2523             {"gov.uk",S_OK,FALSE},
2524             {"",S_FALSE,FALSE},
2525             {"/",S_OK,FALSE},
2526             {"/",S_OK,FALSE},
2527             {"",S_FALSE,FALSE},
2528             {"http://gov.uk/test/test2/../../.",S_OK,FALSE},
2529             {"http",S_OK,FALSE},
2530             {"",S_FALSE,FALSE},
2531             {"",S_FALSE,FALSE}
2532         },
2533         {
2534             {Uri_HOST_DNS,S_OK,FALSE},
2535             {80,S_OK,FALSE},
2536             {URL_SCHEME_HTTP,S_OK,FALSE},
2537             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2538         }
2539     },
2540     {   "file://c:\\tests\\../tests\\./.\\..\\foo%20bar.mp3", 0, S_OK, FALSE,
2541         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH|
2542         Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
2543         FALSE,
2544         {
2545             {"file:///c:/foo%2520bar.mp3",S_OK,FALSE},
2546             {"",S_FALSE,FALSE},
2547             {"file:///c:/foo%2520bar.mp3",S_OK,FALSE},
2548             {"",S_FALSE,FALSE},
2549             {".mp3",S_OK,FALSE},
2550             {"",S_FALSE,FALSE},
2551             {"",S_FALSE,FALSE},
2552             {"",S_FALSE,FALSE},
2553             {"/c:/foo%2520bar.mp3",S_OK,FALSE},
2554             {"/c:/foo%2520bar.mp3",S_OK,FALSE},
2555             {"",S_FALSE,FALSE},
2556             {"file://c:\\tests\\../tests\\./.\\..\\foo%20bar.mp3",S_OK,FALSE},
2557             {"file",S_OK,FALSE},
2558             {"",S_FALSE,FALSE},
2559             {"",S_FALSE,FALSE}
2560         },
2561         {
2562             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2563             {0,S_FALSE,FALSE},
2564             {URL_SCHEME_FILE,S_OK,FALSE},
2565             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2566         }
2567     },
2568     /* Dot removal happens for unknown scheme types. */
2569     {   "zip://gov.uk/test/test2/../../.", 0, S_OK, FALSE,
2570         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
2571         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
2572         Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
2573         FALSE,
2574         {
2575             {"zip://gov.uk/",S_OK,FALSE},
2576             {"gov.uk",S_OK,FALSE},
2577             {"zip://gov.uk/",S_OK,FALSE},
2578             {"",S_FALSE,FALSE},
2579             {"",S_FALSE,FALSE},
2580             {"",S_FALSE,FALSE},
2581             {"gov.uk",S_OK,FALSE},
2582             {"",S_FALSE,FALSE},
2583             {"/",S_OK,FALSE},
2584             {"/",S_OK,FALSE},
2585             {"",S_FALSE,FALSE},
2586             {"zip://gov.uk/test/test2/../../.",S_OK,FALSE},
2587             {"zip",S_OK,FALSE},
2588             {"",S_FALSE,FALSE},
2589             {"",S_FALSE,FALSE}
2590         },
2591         {
2592             {Uri_HOST_DNS,S_OK,FALSE},
2593             {0,S_FALSE,FALSE},
2594             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2595             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2596         }
2597     },
2598     /* Dot removal doesn't happen if NO_CANONICALIZE is set. */
2599     {   "http://gov.uk/test/test2/../../.", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
2600         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|
2601         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
2602         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
2603         FALSE,
2604         {
2605             {"http://gov.uk/test/test2/../../.",S_OK,FALSE},
2606             {"gov.uk",S_OK,FALSE},
2607             {"http://gov.uk/test/test2/../../.",S_OK,FALSE},
2608             {"",S_FALSE,FALSE},
2609             {".",S_OK,FALSE},
2610             {"",S_FALSE,FALSE},
2611             {"gov.uk",S_OK,FALSE},
2612             {"",S_FALSE,FALSE},
2613             {"/test/test2/../../.",S_OK,FALSE},
2614             {"/test/test2/../../.",S_OK,FALSE},
2615             {"",S_FALSE,FALSE},
2616             {"http://gov.uk/test/test2/../../.",S_OK,FALSE},
2617             {"http",S_OK,FALSE},
2618             {"",S_FALSE,FALSE},
2619             {"",S_FALSE,FALSE}
2620         },
2621         {
2622             {Uri_HOST_DNS,S_OK,FALSE},
2623             {80,S_OK,FALSE},
2624             {URL_SCHEME_HTTP,S_OK,FALSE},
2625             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2626         }
2627     },
2628     /* Dot removal doesn't happen for wildcard scheme types. */
2629     {   "*:gov.uk/test/test2/../../.", 0, S_OK, FALSE,
2630         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|
2631         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
2632         Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
2633         FALSE,
2634         {
2635             {"*:gov.uk/test/test2/../../.",S_OK,FALSE},
2636             {"gov.uk",S_OK,FALSE},
2637             {"*:gov.uk/test/test2/../../.",S_OK,FALSE},
2638             {"",S_FALSE,FALSE},
2639             {".",S_OK,FALSE},
2640             {"",S_FALSE,FALSE},
2641             {"gov.uk",S_OK,FALSE},
2642             {"",S_FALSE,FALSE},
2643             {"/test/test2/../../.",S_OK,FALSE},
2644             {"/test/test2/../../.",S_OK,FALSE},
2645             {"",S_FALSE,FALSE},
2646             {"*:gov.uk/test/test2/../../.",S_OK,FALSE},
2647             {"*",S_OK,FALSE},
2648             {"",S_FALSE,FALSE},
2649             {"",S_FALSE,FALSE}
2650         },
2651         {
2652             {Uri_HOST_DNS,S_OK,FALSE},
2653             {0,S_FALSE,FALSE},
2654             {URL_SCHEME_WILDCARD,S_OK,FALSE},
2655             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2656         }
2657     },
2658     /* Forbidden characters are encoded for opaque known scheme types. */
2659     {   "mailto:\"acco<|>unt@example.com\"", 0, S_OK, FALSE,
2660         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|
2661         Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
2662         FALSE,
2663         {
2664             {"mailto:%22acco%3C%7C%3Eunt@example.com%22",S_OK,FALSE},
2665             {"",S_FALSE,FALSE},
2666             {"mailto:%22acco%3C%7C%3Eunt@example.com%22",S_OK,FALSE},
2667             {"",S_FALSE,FALSE},
2668             {".com%22",S_OK,FALSE},
2669             {"",S_FALSE,FALSE},
2670             {"",S_FALSE,FALSE},
2671             {"",S_FALSE,FALSE},
2672             {"%22acco%3C%7C%3Eunt@example.com%22",S_OK,FALSE},
2673             {"%22acco%3C%7C%3Eunt@example.com%22",S_OK,FALSE},
2674             {"",S_FALSE,FALSE},
2675             {"mailto:\"acco<|>unt@example.com\"",S_OK,FALSE},
2676             {"mailto",S_OK,FALSE},
2677             {"",S_FALSE,FALSE},
2678             {"",S_FALSE,FALSE}
2679         },
2680         {
2681             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2682             {0,S_FALSE,FALSE},
2683             {URL_SCHEME_MAILTO,S_OK,FALSE},
2684             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2685         }
2686     },
2687     {   "news:test.tes<|>t.com", 0, S_OK, FALSE,
2688         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|
2689         Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
2690         FALSE,
2691         {
2692             {"news:test.tes%3C%7C%3Et.com",S_OK,FALSE},
2693             {"",S_FALSE,FALSE},
2694             {"news:test.tes%3C%7C%3Et.com",S_OK,FALSE},
2695             {"",S_FALSE,FALSE},
2696             {".com",S_OK,FALSE},
2697             {"",S_FALSE,FALSE},
2698             {"",S_FALSE,FALSE},
2699             {"",S_FALSE,FALSE},
2700             {"test.tes%3C%7C%3Et.com",S_OK,FALSE},
2701             {"test.tes%3C%7C%3Et.com",S_OK,FALSE},
2702             {"",S_FALSE,FALSE},
2703             {"news:test.tes<|>t.com",S_OK,FALSE},
2704             {"news",S_OK,FALSE},
2705             {"",S_FALSE,FALSE},
2706             {"",S_FALSE,FALSE}
2707         },
2708         {
2709             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2710             {0,S_FALSE,FALSE},
2711             {URL_SCHEME_NEWS,S_OK,FALSE},
2712             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2713         }
2714     },
2715     /* Don't encode forbidden characters. */
2716     {   "news:test.tes<|>t.com", Uri_CREATE_NO_ENCODE_FORBIDDEN_CHARACTERS, S_OK, FALSE,
2717         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|
2718         Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
2719         FALSE,
2720         {
2721             {"news:test.tes<|>t.com",S_OK,FALSE},
2722             {"",S_FALSE,FALSE},
2723             {"news:test.tes<|>t.com",S_OK,FALSE},
2724             {"",S_FALSE,FALSE},
2725             {".com",S_OK,FALSE},
2726             {"",S_FALSE,FALSE},
2727             {"",S_FALSE,FALSE},
2728             {"",S_FALSE,FALSE},
2729             {"test.tes<|>t.com",S_OK,FALSE},
2730             {"test.tes<|>t.com",S_OK,FALSE},
2731             {"",S_FALSE,FALSE},
2732             {"news:test.tes<|>t.com",S_OK,FALSE},
2733             {"news",S_OK,FALSE},
2734             {"",S_FALSE,FALSE},
2735             {"",S_FALSE,FALSE}
2736         },
2737         {
2738             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2739             {0,S_FALSE,FALSE},
2740             {URL_SCHEME_NEWS,S_OK,FALSE},
2741             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2742         }
2743     },
2744     /* Forbidden characters aren't encoded for unknown, opaque URIs. */
2745     {   "urn:test.tes<|>t.com", 0, S_OK, FALSE,
2746         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|
2747         Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
2748         FALSE,
2749         {
2750             {"urn:test.tes<|>t.com",S_OK,FALSE},
2751             {"",S_FALSE,FALSE},
2752             {"urn:test.tes<|>t.com",S_OK,FALSE},
2753             {"",S_FALSE,FALSE},
2754             {".com",S_OK,FALSE},
2755             {"",S_FALSE,FALSE},
2756             {"",S_FALSE,FALSE},
2757             {"",S_FALSE,FALSE},
2758             {"test.tes<|>t.com",S_OK,FALSE},
2759             {"test.tes<|>t.com",S_OK,FALSE},
2760             {"",S_FALSE,FALSE},
2761             {"urn:test.tes<|>t.com",S_OK,FALSE},
2762             {"urn",S_OK,FALSE},
2763             {"",S_FALSE,FALSE},
2764             {"",S_FALSE,FALSE}
2765         },
2766         {
2767             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2768             {0,S_FALSE,FALSE},
2769             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2770             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2771         }
2772     },
2773     /* Percent encoded unreserved characters are decoded for known opaque URIs. */
2774     {   "news:test.%74%65%73%74.com", 0, S_OK, FALSE,
2775         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|
2776         Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
2777         FALSE,
2778         {
2779             {"news:test.test.com",S_OK,FALSE},
2780             {"",S_FALSE,FALSE},
2781             {"news:test.test.com",S_OK,FALSE},
2782             {"",S_FALSE,FALSE},
2783             {".com",S_OK,FALSE},
2784             {"",S_FALSE,FALSE},
2785             {"",S_FALSE,FALSE},
2786             {"",S_FALSE,FALSE},
2787             {"test.test.com",S_OK,FALSE},
2788             {"test.test.com",S_OK,FALSE},
2789             {"",S_FALSE,FALSE},
2790             {"news:test.%74%65%73%74.com",S_OK,FALSE},
2791             {"news",S_OK,FALSE},
2792             {"",S_FALSE,FALSE},
2793             {"",S_FALSE,FALSE}
2794         },
2795         {
2796             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2797             {0,S_FALSE,FALSE},
2798             {URL_SCHEME_NEWS,S_OK,FALSE},
2799             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2800         }
2801     },
2802     /* Percent encoded characters are still decoded for known scheme types. */
2803     {   "news:test.%74%65%73%74.com", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
2804         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|
2805         Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
2806         FALSE,
2807         {
2808             {"news:test.test.com",S_OK,FALSE},
2809             {"",S_FALSE,FALSE},
2810             {"news:test.test.com",S_OK,FALSE},
2811             {"",S_FALSE,FALSE},
2812             {".com",S_OK,FALSE},
2813             {"",S_FALSE,FALSE},
2814             {"",S_FALSE,FALSE},
2815             {"",S_FALSE,FALSE},
2816             {"test.test.com",S_OK,FALSE},
2817             {"test.test.com",S_OK,FALSE},
2818             {"",S_FALSE,FALSE},
2819             {"news:test.%74%65%73%74.com",S_OK,FALSE},
2820             {"news",S_OK,FALSE},
2821             {"",S_FALSE,FALSE},
2822             {"",S_FALSE,FALSE}
2823         },
2824         {
2825             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2826             {0,S_FALSE,FALSE},
2827             {URL_SCHEME_NEWS,S_OK,FALSE},
2828             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2829         }
2830     },
2831     /* Percent encoded characters aren't decoded for unknown scheme types. */
2832     {   "urn:test.%74%65%73%74.com", 0, S_OK, FALSE,
2833         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|
2834         Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
2835         FALSE,
2836         {
2837             {"urn:test.%74%65%73%74.com",S_OK,FALSE},
2838             {"",S_FALSE,FALSE},
2839             {"urn:test.%74%65%73%74.com",S_OK,FALSE},
2840             {"",S_FALSE,FALSE},
2841             {".com",S_OK,FALSE},
2842             {"",S_FALSE,FALSE},
2843             {"",S_FALSE,FALSE},
2844             {"",S_FALSE,FALSE},
2845             {"test.%74%65%73%74.com",S_OK,FALSE},
2846             {"test.%74%65%73%74.com",S_OK,FALSE},
2847             {"",S_FALSE,FALSE},
2848             {"urn:test.%74%65%73%74.com",S_OK,FALSE},
2849             {"urn",S_OK,FALSE},
2850             {"",S_FALSE,FALSE},
2851             {"",S_FALSE,FALSE}
2852         },
2853         {
2854             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2855             {0,S_FALSE,FALSE},
2856             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2857             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2858         }
2859     },
2860     /* Unknown scheme types can have invalid % encoded data in query string. */
2861     {   "zip://www.winehq.org/tests/..?query=%xx&return=y", 0, S_OK, FALSE,
2862         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_HOST|
2863         Uri_HAS_DOMAIN|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_QUERY|Uri_HAS_RAW_URI|
2864         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
2865         FALSE,
2866         {
2867             {"zip://www.winehq.org/?query=%xx&return=y",S_OK,FALSE},
2868             {"www.winehq.org",S_OK,FALSE},
2869             {"zip://www.winehq.org/?query=%xx&return=y",S_OK,FALSE},
2870             {"winehq.org",S_OK,FALSE},
2871             {"",S_FALSE,FALSE},
2872             {"",S_FALSE,FALSE},
2873             {"www.winehq.org",S_OK,FALSE},
2874             {"",S_FALSE,FALSE},
2875             {"/",S_OK,FALSE},
2876             {"/?query=%xx&return=y",S_OK,FALSE},
2877             {"?query=%xx&return=y",S_OK,FALSE},
2878             {"zip://www.winehq.org/tests/..?query=%xx&return=y",S_OK,FALSE},
2879             {"zip",S_OK,FALSE},
2880             {"",S_FALSE,FALSE},
2881             {"",S_FALSE,FALSE}
2882         },
2883         {
2884             {Uri_HOST_DNS,S_OK,FALSE},
2885             {0,S_FALSE,FALSE},
2886             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2887             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2888         }
2889     },
2890     /* Known scheme types can have invalid % encoded data with the right flags. */
2891     {   "http://www.winehq.org/tests/..?query=%xx&return=y", Uri_CREATE_NO_DECODE_EXTRA_INFO, S_OK, FALSE,
2892         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_HOST|
2893         Uri_HAS_DOMAIN|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_PORT|Uri_HAS_QUERY|Uri_HAS_RAW_URI|
2894         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
2895         FALSE,
2896         {
2897             {"http://www.winehq.org/?query=%xx&return=y",S_OK,FALSE},
2898             {"www.winehq.org",S_OK,FALSE},
2899             {"http://www.winehq.org/?query=%xx&return=y",S_OK,FALSE},
2900             {"winehq.org",S_OK,FALSE},
2901             {"",S_FALSE,FALSE},
2902             {"",S_FALSE,FALSE},
2903             {"www.winehq.org",S_OK,FALSE},
2904             {"",S_FALSE,FALSE},
2905             {"/",S_OK,FALSE},
2906             {"/?query=%xx&return=y",S_OK,FALSE},
2907             {"?query=%xx&return=y",S_OK,FALSE},
2908             {"http://www.winehq.org/tests/..?query=%xx&return=y",S_OK,FALSE},
2909             {"http",S_OK,FALSE},
2910             {"",S_FALSE,FALSE},
2911             {"",S_FALSE,FALSE}
2912         },
2913         {
2914             {Uri_HOST_DNS,S_OK,FALSE},
2915             {80,S_OK,FALSE},
2916             {URL_SCHEME_HTTP,S_OK,FALSE},
2917             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2918         }
2919     },
2920     /* Forbidden characters in query aren't percent encoded for known scheme types with this flag. */
2921     {   "http://www.winehq.org/tests/..?query=<|>&return=y", Uri_CREATE_NO_DECODE_EXTRA_INFO, S_OK, FALSE,
2922         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_HOST|
2923         Uri_HAS_DOMAIN|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_PORT|Uri_HAS_QUERY|Uri_HAS_RAW_URI|
2924         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
2925         FALSE,
2926         {
2927             {"http://www.winehq.org/?query=<|>&return=y",S_OK,FALSE},
2928             {"www.winehq.org",S_OK,FALSE},
2929             {"http://www.winehq.org/?query=<|>&return=y",S_OK,FALSE},
2930             {"winehq.org",S_OK,FALSE},
2931             {"",S_FALSE,FALSE},
2932             {"",S_FALSE,FALSE},
2933             {"www.winehq.org",S_OK,FALSE},
2934             {"",S_FALSE,FALSE},
2935             {"/",S_OK,FALSE},
2936             {"/?query=<|>&return=y",S_OK,FALSE},
2937             {"?query=<|>&return=y",S_OK,FALSE},
2938             {"http://www.winehq.org/tests/..?query=<|>&return=y",S_OK,FALSE},
2939             {"http",S_OK,FALSE},
2940             {"",S_FALSE,FALSE},
2941             {"",S_FALSE,FALSE}
2942         },
2943         {
2944             {Uri_HOST_DNS,S_OK,FALSE},
2945             {80,S_OK,FALSE},
2946             {URL_SCHEME_HTTP,S_OK,FALSE},
2947             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2948         }
2949     },
2950     /* Forbidden characters in query aren't percent encoded for known scheme types with this flag. */
2951     {   "http://www.winehq.org/tests/..?query=<|>&return=y", Uri_CREATE_NO_ENCODE_FORBIDDEN_CHARACTERS, S_OK, FALSE,
2952         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_HOST|
2953         Uri_HAS_DOMAIN|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_PORT|Uri_HAS_QUERY|Uri_HAS_RAW_URI|
2954         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
2955         FALSE,
2956         {
2957             {"http://www.winehq.org/?query=<|>&return=y",S_OK,FALSE},
2958             {"www.winehq.org",S_OK,FALSE},
2959             {"http://www.winehq.org/?query=<|>&return=y",S_OK,FALSE},
2960             {"winehq.org",S_OK,FALSE},
2961             {"",S_FALSE,FALSE},
2962             {"",S_FALSE,FALSE},
2963             {"www.winehq.org",S_OK,FALSE},
2964             {"",S_FALSE,FALSE},
2965             {"/",S_OK,FALSE},
2966             {"/?query=<|>&return=y",S_OK,FALSE},
2967             {"?query=<|>&return=y",S_OK,FALSE},
2968             {"http://www.winehq.org/tests/..?query=<|>&return=y",S_OK,FALSE},
2969             {"http",S_OK,FALSE},
2970             {"",S_FALSE,FALSE},
2971             {"",S_FALSE,FALSE}
2972         },
2973         {
2974             {Uri_HOST_DNS,S_OK,FALSE},
2975             {80,S_OK,FALSE},
2976             {URL_SCHEME_HTTP,S_OK,FALSE},
2977             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2978         }
2979     },
2980     /* Forbidden characters are encoded for known scheme types. */
2981     {   "http://www.winehq.org/tests/..?query=<|>&return=y", 0, S_OK, FALSE,
2982         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_HOST|
2983         Uri_HAS_DOMAIN|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_PORT|Uri_HAS_QUERY|Uri_HAS_RAW_URI|
2984         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
2985         FALSE,
2986         {
2987             {"http://www.winehq.org/?query=%3C%7C%3E&return=y",S_OK,FALSE},
2988             {"www.winehq.org",S_OK,FALSE},
2989             {"http://www.winehq.org/?query=%3C%7C%3E&return=y",S_OK,FALSE},
2990             {"winehq.org",S_OK,FALSE},
2991             {"",S_FALSE,FALSE},
2992             {"",S_FALSE,FALSE},
2993             {"www.winehq.org",S_OK,FALSE},
2994             {"",S_FALSE,FALSE},
2995             {"/",S_OK,FALSE},
2996             {"/?query=%3C%7C%3E&return=y",S_OK,FALSE},
2997             {"?query=%3C%7C%3E&return=y",S_OK,FALSE},
2998             {"http://www.winehq.org/tests/..?query=<|>&return=y",S_OK,FALSE},
2999             {"http",S_OK,FALSE},
3000             {"",S_FALSE,FALSE},
3001             {"",S_FALSE,FALSE}
3002         },
3003         {
3004             {Uri_HOST_DNS,S_OK,FALSE},
3005             {80,S_OK,FALSE},
3006             {URL_SCHEME_HTTP,S_OK,FALSE},
3007             {URLZONE_INVALID,E_NOTIMPL,FALSE},
3008         }
3009     },
3010     /* Forbidden characters are not encoded for unknown scheme types. */
3011     {   "zip://www.winehq.org/tests/..?query=<|>&return=y", 0, S_OK, FALSE,
3012         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_HOST|
3013         Uri_HAS_DOMAIN|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_QUERY|Uri_HAS_RAW_URI|
3014         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
3015         FALSE,
3016         {
3017             {"zip://www.winehq.org/?query=<|>&return=y",S_OK,FALSE},
3018             {"www.winehq.org",S_OK,FALSE},
3019             {"zip://www.winehq.org/?query=<|>&return=y",S_OK,FALSE},
3020             {"winehq.org",S_OK,FALSE},
3021             {"",S_FALSE,FALSE},
3022             {"",S_FALSE,FALSE},
3023             {"www.winehq.org",S_OK,FALSE},
3024             {"",S_FALSE,FALSE},
3025             {"/",S_OK,FALSE},
3026             {"/?query=<|>&return=y",S_OK,FALSE},
3027             {"?query=<|>&return=y",S_OK,FALSE},
3028             {"zip://www.winehq.org/tests/..?query=<|>&return=y",S_OK,FALSE},
3029             {"zip",S_OK,FALSE},
3030             {"",S_FALSE,FALSE},
3031             {"",S_FALSE,FALSE}
3032         },
3033         {
3034             {Uri_HOST_DNS,S_OK,FALSE},
3035             {0,S_FALSE,FALSE},
3036             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
3037             {URLZONE_INVALID,E_NOTIMPL,FALSE},
3038         }
3039     },
3040     /* Percent encoded, unreserved characters are decoded for known scheme types. */
3041     {   "http://www.winehq.org/tests/..?query=%30%31&return=y", 0, S_OK, FALSE,
3042         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_HOST|
3043         Uri_HAS_DOMAIN|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_PORT|Uri_HAS_QUERY|Uri_HAS_RAW_URI|
3044         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
3045         FALSE,
3046         {
3047             {"http://www.winehq.org/?query=01&return=y",S_OK,FALSE},
3048             {"www.winehq.org",S_OK,FALSE},
3049             {"http://www.winehq.org/?query=01&return=y",S_OK,FALSE},
3050             {"winehq.org",S_OK,FALSE},
3051             {"",S_FALSE,FALSE},
3052             {"",S_FALSE,FALSE},
3053             {"www.winehq.org",S_OK,FALSE},
3054             {"",S_FALSE,FALSE},
3055             {"/",S_OK,FALSE},
3056             {"/?query=01&return=y",S_OK,FALSE},
3057             {"?query=01&return=y",S_OK,FALSE},
3058             {"http://www.winehq.org/tests/..?query=%30%31&return=y",S_OK,FALSE},
3059             {"http",S_OK,FALSE},
3060             {"",S_FALSE,FALSE},
3061             {"",S_FALSE,FALSE}
3062         },
3063         {
3064             {Uri_HOST_DNS,S_OK,FALSE},
3065             {80,S_OK,FALSE},
3066             {URL_SCHEME_HTTP,S_OK,FALSE},
3067             {URLZONE_INVALID,E_NOTIMPL,FALSE},
3068         }
3069     },
3070     /* Percent encoded, unreserved characters aren't decoded for unknown scheme types. */
3071     {   "zip://www.winehq.org/tests/..?query=%30%31&return=y", 0, S_OK, FALSE,
3072         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_HOST|
3073         Uri_HAS_DOMAIN|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_QUERY|Uri_HAS_RAW_URI|
3074         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
3075         FALSE,
3076         {
3077             {"zip://www.winehq.org/?query=%30%31&return=y",S_OK,FALSE},
3078             {"www.winehq.org",S_OK,FALSE},
3079             {"zip://www.winehq.org/?query=%30%31&return=y",S_OK,FALSE},
3080             {"winehq.org",S_OK,FALSE},
3081             {"",S_FALSE,FALSE},
3082             {"",S_FALSE,FALSE},
3083             {"www.winehq.org",S_OK,FALSE},
3084             {"",S_FALSE,FALSE},
3085             {"/",S_OK,FALSE},
3086             {"/?query=%30%31&return=y",S_OK,FALSE},
3087             {"?query=%30%31&return=y",S_OK,FALSE},
3088             {"zip://www.winehq.org/tests/..?query=%30%31&return=y",S_OK,FALSE},
3089             {"zip",S_OK,FALSE},
3090             {"",S_FALSE,FALSE},
3091             {"",S_FALSE,FALSE}
3092         },
3093         {
3094             {Uri_HOST_DNS,S_OK,FALSE},
3095             {0,S_FALSE,FALSE},
3096             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
3097             {URLZONE_INVALID,E_NOTIMPL,FALSE},
3098         }
3099     },
3100     /* Percent encoded characters aren't decoded when NO_DECODE_EXTRA_INFO is set. */
3101     {   "http://www.winehq.org/tests/..?query=%30%31&return=y", Uri_CREATE_NO_DECODE_EXTRA_INFO, S_OK, FALSE,
3102         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_HOST|
3103         Uri_HAS_DOMAIN|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_PORT|Uri_HAS_QUERY|Uri_HAS_RAW_URI|
3104         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
3105         FALSE,
3106         {
3107             {"http://www.winehq.org/?query=%30%31&return=y",S_OK,FALSE},
3108             {"www.winehq.org",S_OK,FALSE},
3109             {"http://www.winehq.org/?query=%30%31&return=y",S_OK,FALSE},
3110             {"winehq.org",S_OK,FALSE},
3111             {"",S_FALSE,FALSE},
3112             {"",S_FALSE,FALSE},
3113             {"www.winehq.org",S_OK,FALSE},
3114             {"",S_FALSE,FALSE},
3115             {"/",S_OK,FALSE},
3116             {"/?query=%30%31&return=y",S_OK,FALSE},
3117             {"?query=%30%31&return=y",S_OK,FALSE},
3118             {"http://www.winehq.org/tests/..?query=%30%31&return=y",S_OK,FALSE},
3119             {"http",S_OK,FALSE},
3120             {"",S_FALSE,FALSE},
3121             {"",S_FALSE,FALSE}
3122         },
3123         {
3124             {Uri_HOST_DNS,S_OK,FALSE},
3125             {80,S_OK,FALSE},
3126             {URL_SCHEME_HTTP,S_OK,FALSE},
3127             {URLZONE_INVALID,E_NOTIMPL,FALSE},
3128         }
3129     },
3130     {   "http://www.winehq.org?query=12&return=y", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
3131         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_HOST|
3132         Uri_HAS_DOMAIN|Uri_HAS_PATH_AND_QUERY|Uri_HAS_PORT|Uri_HAS_QUERY|Uri_HAS_RAW_URI|
3133         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
3134         FALSE,
3135         {
3136             {"http://www.winehq.org?query=12&return=y",S_OK,FALSE},
3137             {"www.winehq.org",S_OK,FALSE},
3138             {"http://www.winehq.org?query=12&return=y",S_OK,FALSE},
3139             {"winehq.org",S_OK,FALSE},
3140             {"",S_FALSE,FALSE},
3141             {"",S_FALSE,FALSE},
3142             {"www.winehq.org",S_OK,FALSE},
3143             {"",S_FALSE,FALSE},
3144             {"",S_FALSE,FALSE},
3145             {"?query=12&return=y",S_OK,FALSE},
3146             {"?query=12&return=y",S_OK,FALSE},
3147             {"http://www.winehq.org?query=12&return=y",S_OK,FALSE},
3148             {"http",S_OK,FALSE},
3149             {"",S_FALSE,FALSE},
3150             {"",S_FALSE,FALSE}
3151         },
3152         {
3153             {Uri_HOST_DNS,S_OK,FALSE},
3154             {80,S_OK,FALSE},
3155             {URL_SCHEME_HTTP,S_OK,FALSE},
3156             {URLZONE_INVALID,E_NOTIMPL,FALSE},
3157         }
3158     },
3159     /* Unknown scheme types can have invalid % encoded data in fragments. */
3160     {   "zip://www.winehq.org/tests/#Te%xx", 0, S_OK, FALSE,
3161         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_FRAGMENT|
3162         Uri_HAS_HOST|Uri_HAS_DOMAIN|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
3163         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
3164         FALSE,
3165         {
3166             {"zip://www.winehq.org/tests/#Te%xx",S_OK,FALSE},
3167             {"www.winehq.org",S_OK,FALSE},
3168             {"zip://www.winehq.org/tests/#Te%xx",S_OK,FALSE},
3169             {"winehq.org",S_OK,FALSE},
3170             {"",S_FALSE,FALSE},
3171             {"#Te%xx",S_OK,FALSE},
3172             {"www.winehq.org",S_OK,FALSE},
3173             {"",S_FALSE,FALSE},
3174             {"/tests/",S_OK,FALSE},
3175             {"/tests/",S_OK,FALSE},
3176             {"",S_FALSE,FALSE},
3177             {"zip://www.winehq.org/tests/#Te%xx",S_OK,FALSE},
3178             {"zip",S_OK,FALSE},
3179             {"",S_FALSE,FALSE},
3180             {"",S_FALSE,FALSE}
3181         },
3182         {
3183             {Uri_HOST_DNS,S_OK,FALSE},
3184             {0,S_FALSE,FALSE},
3185             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
3186             {URLZONE_INVALID,E_NOTIMPL,FALSE},
3187         }
3188     },
3189     /* Forbidden characters in fragment aren't encoded for unknown schemes. */
3190     {   "zip://www.winehq.org/tests/#Te<|>", 0, S_OK, FALSE,
3191         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_FRAGMENT|
3192         Uri_HAS_HOST|Uri_HAS_DOMAIN|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
3193         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
3194         FALSE,
3195         {
3196             {"zip://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
3197             {"www.winehq.org",S_OK,FALSE},
3198             {"zip://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
3199             {"winehq.org",S_OK,FALSE},
3200             {"",S_FALSE,FALSE},
3201             {"#Te<|>",S_OK,FALSE},
3202             {"www.winehq.org",S_OK,FALSE},
3203             {"",S_FALSE,FALSE},
3204             {"/tests/",S_OK,FALSE},
3205             {"/tests/",S_OK,FALSE},
3206             {"",S_FALSE,FALSE},
3207             {"zip://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
3208             {"zip",S_OK,FALSE},
3209             {"",S_FALSE,FALSE},
3210             {"",S_FALSE,FALSE}
3211         },
3212         {
3213             {Uri_HOST_DNS,S_OK,FALSE},
3214             {0,S_FALSE,FALSE},
3215             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
3216             {URLZONE_INVALID,E_NOTIMPL,FALSE},
3217         }
3218     },
3219     /* Forbidden characters in the fragment are percent encoded for known schemes. */
3220     {   "http://www.winehq.org/tests/#Te<|>", 0, S_OK, FALSE,
3221         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_FRAGMENT|
3222         Uri_HAS_HOST|Uri_HAS_DOMAIN|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
3223         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
3224         FALSE,
3225         {
3226             {"http://www.winehq.org/tests/#Te%3C%7C%3E",S_OK,FALSE},
3227             {"www.winehq.org",S_OK,FALSE},
3228             {"http://www.winehq.org/tests/#Te%3C%7C%3E",S_OK,FALSE},
3229             {"winehq.org",S_OK,FALSE},
3230             {"",S_FALSE,FALSE},
3231             {"#Te%3C%7C%3E",S_OK,FALSE},
3232             {"www.winehq.org",S_OK,FALSE},
3233             {"",S_FALSE,FALSE},
3234             {"/tests/",S_OK,FALSE},
3235             {"/tests/",S_OK,FALSE},
3236             {"",S_FALSE,FALSE},
3237             {"http://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
3238             {"http",S_OK,FALSE},
3239             {"",S_FALSE,FALSE},
3240             {"",S_FALSE,FALSE}
3241         },
3242         {
3243             {Uri_HOST_DNS,S_OK,FALSE},
3244             {80,S_OK,FALSE},
3245             {URL_SCHEME_HTTP,S_OK,FALSE},
3246             {URLZONE_INVALID,E_NOTIMPL,FALSE},
3247         }
3248     },
3249     /* Forbidden characters aren't encoded in the fragment with this flag. */
3250     {   "http://www.winehq.org/tests/#Te<|>", Uri_CREATE_NO_DECODE_EXTRA_INFO, S_OK, FALSE,
3251         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_FRAGMENT|
3252         Uri_HAS_HOST|Uri_HAS_DOMAIN|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
3253         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
3254         FALSE,
3255         {
3256             {"http://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
3257             {"www.winehq.org",S_OK,FALSE},
3258             {"http://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
3259             {"winehq.org",S_OK,FALSE},
3260             {"",S_FALSE,FALSE},
3261             {"#Te<|>",S_OK,FALSE},
3262             {"www.winehq.org",S_OK,FALSE},
3263             {"",S_FALSE,FALSE},
3264             {"/tests/",S_OK,FALSE},
3265             {"/tests/",S_OK,FALSE},
3266             {"",S_FALSE,FALSE},
3267             {"http://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
3268             {"http",S_OK,FALSE},
3269             {"",S_FALSE,FALSE},
3270             {"",S_FALSE,FALSE}
3271         },
3272         {
3273             {Uri_HOST_DNS,S_OK,FALSE},
3274             {80,S_OK,FALSE},
3275             {URL_SCHEME_HTTP,S_OK,FALSE},
3276             {URLZONE_INVALID,E_NOTIMPL,FALSE},
3277         }
3278     },
3279     /* Forbidden characters aren't encoded in the fragment with this flag. */
3280     {   "http://www.winehq.org/tests/#Te<|>", Uri_CREATE_NO_ENCODE_FORBIDDEN_CHARACTERS, S_OK, FALSE,
3281         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_FRAGMENT|
3282         Uri_HAS_HOST|Uri_HAS_DOMAIN|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
3283         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
3284         FALSE,
3285         {
3286             {"http://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
3287             {"www.winehq.org",S_OK,FALSE},
3288             {"http://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
3289             {"winehq.org",S_OK,FALSE},
3290             {"",S_FALSE,FALSE},
3291             {"#Te<|>",S_OK,FALSE},
3292             {"www.winehq.org",S_OK,FALSE},
3293             {"",S_FALSE,FALSE},
3294             {"/tests/",S_OK,FALSE},
3295             {"/tests/",S_OK,FALSE},
3296             {"",S_FALSE,FALSE},
3297             {"http://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
3298             {"http",S_OK,FALSE},
3299             {"",S_FALSE,FALSE},
3300             {"",S_FALSE,FALSE}
3301         },
3302         {
3303             {Uri_HOST_DNS,S_OK,FALSE},
3304             {80,S_OK,FALSE},
3305             {URL_SCHEME_HTTP,S_OK,FALSE},
3306             {URLZONE_INVALID,E_NOTIMPL,FALSE},
3307         }
3308     },
3309     /* Percent encoded, unreserved characters aren't decoded for known scheme types. */
3310     {   "zip://www.winehq.org/tests/#Te%30%31%32", 0, S_OK, FALSE,
3311         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_FRAGMENT|
3312         Uri_HAS_HOST|Uri_HAS_DOMAIN|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
3313         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
3314         FALSE,
3315         {
3316             {"zip://www.winehq.org/tests/#Te%30%31%32",S_OK,FALSE},
3317             {"www.winehq.org",S_OK,FALSE},
3318             {"zip://www.winehq.org/tests/#Te%30%31%32",S_OK,FALSE},
3319             {"winehq.org",S_OK,FALSE},
3320             {"",S_FALSE,FALSE},
3321             {"#Te%30%31%32",S_OK,FALSE},
3322             {"www.winehq.org",S_OK,FALSE},
3323             {"",S_FALSE,FALSE},
3324             {"/tests/",S_OK,FALSE},
3325             {"/tests/",S_OK,FALSE},
3326             {"",S_FALSE,FALSE},
3327             {"zip://www.winehq.org/tests/#Te%30%31%32",S_OK,FALSE},
3328             {"zip",S_OK,FALSE},
3329             {"",S_FALSE,FALSE},
3330             {"",S_FALSE,FALSE}
3331         },
3332         {
3333             {Uri_HOST_DNS,S_OK,FALSE},
3334             {0,S_FALSE,FALSE},
3335             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
3336             {URLZONE_INVALID,E_NOTIMPL,FALSE},
3337         }
3338     },
3339     /* Percent encoded, unreserved characters are decoded for known schemes. */
3340     {   "http://www.winehq.org/tests/#Te%30%31%32", 0, S_OK, FALSE,
3341         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_FRAGMENT|
3342         Uri_HAS_HOST|Uri_HAS_DOMAIN|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
3343         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
3344         FALSE,
3345         {
3346             {"http://www.winehq.org/tests/#Te012",S_OK,FALSE},
3347             {"www.winehq.org",S_OK,FALSE},
3348             {"http://www.winehq.org/tests/#Te012",S_OK,FALSE},
3349             {"winehq.org",S_OK,FALSE},
3350             {"",S_FALSE,FALSE},
3351             {"#Te012",S_OK,FALSE},
3352             {"www.winehq.org",S_OK,FALSE},
3353             {"",S_FALSE,FALSE},
3354             {"/tests/",S_OK,FALSE},
3355             {"/tests/",S_OK,FALSE},
3356             {"",S_FALSE,FALSE},
3357             {"http://www.winehq.org/tests/#Te%30%31%32",S_OK,FALSE},
3358             {"http",S_OK,FALSE},
3359             {"",S_FALSE,FALSE},
3360             {"",S_FALSE,FALSE}
3361         },
3362         {
3363             {Uri_HOST_DNS,S_OK,FALSE},
3364             {80,S_OK,FALSE},
3365             {URL_SCHEME_HTTP,S_OK,FALSE},
3366             {URLZONE_INVALID,E_NOTIMPL,FALSE},
3367         }
3368     },
3369     /* Percent encoded, unreserved characters are decoded even if NO_CANONICALIZE is set. */
3370     {   "http://www.winehq.org/tests/#Te%30%31%32", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
3371         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_FRAGMENT|
3372         Uri_HAS_HOST|Uri_HAS_DOMAIN|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
3373         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
3374         FALSE,
3375         {
3376             {"http://www.winehq.org/tests/#Te012",S_OK,FALSE},
3377             {"www.winehq.org",S_OK,FALSE},
3378             {"http://www.winehq.org/tests/#Te012",S_OK,FALSE},
3379             {"winehq.org",S_OK,FALSE},
3380             {"",S_FALSE,FALSE},
3381             {"#Te012",S_OK,FALSE},
3382             {"www.winehq.org",S_OK,FALSE},
3383             {"",S_FALSE,FALSE},
3384             {"/tests/",S_OK,FALSE},
3385             {"/tests/",S_OK,FALSE},
3386             {"",S_FALSE,FALSE},
3387             {"http://www.winehq.org/tests/#Te%30%31%32",S_OK,FALSE},
3388             {"http",S_OK,FALSE},
3389             {"",S_FALSE,FALSE},
3390             {"",S_FALSE,FALSE}
3391         },
3392         {
3393             {Uri_HOST_DNS,S_OK,FALSE},
3394             {80,S_OK,FALSE},
3395             {URL_SCHEME_HTTP,S_OK,FALSE},
3396             {URLZONE_INVALID,E_NOTIMPL,FALSE},
3397         }
3398     },
3399     /* Percent encoded, unreserved characters aren't decoded when NO_DECODE_EXTRA is set. */
3400     {   "http://www.winehq.org/tests/#Te%30%31%32", Uri_CREATE_NO_DECODE_EXTRA_INFO, S_OK, FALSE,
3401         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_FRAGMENT|
3402         Uri_HAS_HOST|Uri_HAS_DOMAIN|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
3403         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
3404         FALSE,
3405         {
3406             {"http://www.winehq.org/tests/#Te%30%31%32",S_OK,FALSE},
3407             {"www.winehq.org",S_OK,FALSE},
3408             {"http://www.winehq.org/tests/#Te%30%31%32",S_OK,FALSE},
3409             {"winehq.org",S_OK,FALSE},
3410             {"",S_FALSE,FALSE},
3411             {"#Te%30%31%32",S_OK,FALSE},
3412             {"www.winehq.org",S_OK,FALSE},
3413             {"",S_FALSE,FALSE},
3414             {"/tests/",S_OK,FALSE},
3415             {"/tests/",S_OK,FALSE},
3416             {"",S_FALSE,FALSE},
3417             {"http://www.winehq.org/tests/#Te%30%31%32",S_OK,FALSE},
3418             {"http",S_OK,FALSE},
3419             {"",S_FALSE,FALSE},
3420             {"",S_FALSE,FALSE}
3421         },
3422         {
3423             {Uri_HOST_DNS,S_OK,FALSE},
3424             {80,S_OK,FALSE},
3425             {URL_SCHEME_HTTP,S_OK,FALSE},
3426             {URLZONE_INVALID,E_NOTIMPL,FALSE},
3427         }
3428     },
3429     /* Leading/Trailing whitespace is removed. */
3430     {   "    http://google.com/     ", 0, S_OK, FALSE,
3431         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
3432         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
3433         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
3434         FALSE,
3435         {
3436             {"http://google.com/",S_OK,FALSE},
3437             {"google.com",S_OK,FALSE},
3438             {"http://google.com/",S_OK,FALSE},
3439             {"google.com",S_OK,FALSE},
3440             {"",S_FALSE,FALSE},
3441             {"",S_FALSE,FALSE},
3442             {"google.com",S_OK,FALSE},
3443             {"",S_FALSE,FALSE},
3444             {"/",S_OK,FALSE},
3445             {"/",S_OK,FALSE},
3446             {"",S_FALSE,FALSE},
3447             {"http://google.com/",S_OK,FALSE},
3448             {"http",S_OK,FALSE},
3449             {"",S_FALSE,FALSE},
3450             {"",S_FALSE,FALSE}
3451         },
3452         {
3453             {Uri_HOST_DNS,S_OK,FALSE},
3454             {80,S_OK,FALSE},
3455             {URL_SCHEME_HTTP,S_OK,FALSE},
3456             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3457         }
3458     },
3459     {   "\t\t\r\nhttp\n://g\noogle.co\rm/\n\n\n", 0, S_OK, FALSE,
3460         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
3461         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
3462         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
3463         FALSE,
3464         {
3465             {"http://google.com/",S_OK,FALSE},
3466             {"google.com",S_OK,FALSE},
3467             {"http://google.com/",S_OK,FALSE},
3468             {"google.com",S_OK,FALSE},
3469             {"",S_FALSE,FALSE},
3470             {"",S_FALSE,FALSE},
3471             {"google.com",S_OK,FALSE},
3472             {"",S_FALSE,FALSE},
3473             {"/",S_OK,FALSE},
3474             {"/",S_OK,FALSE},
3475             {"",S_FALSE,FALSE},
3476             {"http://google.com/",S_OK,FALSE},
3477             {"http",S_OK,FALSE},
3478             {"",S_FALSE,FALSE},
3479             {"",S_FALSE,FALSE}
3480         },
3481         {
3482             {Uri_HOST_DNS,S_OK,FALSE},
3483             {80,S_OK,FALSE},
3484             {URL_SCHEME_HTTP,S_OK,FALSE},
3485             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3486         }
3487     },
3488     {   "http://g\noogle.co\rm/\n\n\n", Uri_CREATE_NO_PRE_PROCESS_HTML_URI, S_OK, FALSE,
3489         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
3490         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
3491         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
3492         FALSE,
3493         {
3494             {"http://g%0aoogle.co%0dm/%0A%0A%0A",S_OK,FALSE},
3495             {"g%0aoogle.co%0dm",S_OK,FALSE},
3496             {"http://g%0aoogle.co%0dm/%0A%0A%0A",S_OK,FALSE},
3497             {"g%0aoogle.co%0dm",S_OK,FALSE},
3498             {"",S_FALSE,FALSE},
3499             {"",S_FALSE,FALSE},
3500             {"g%0aoogle.co%0dm",S_OK,FALSE},
3501             {"",S_FALSE,FALSE},
3502             {"/%0A%0A%0A",S_OK,FALSE},
3503             {"/%0A%0A%0A",S_OK,FALSE},
3504             {"",S_FALSE,FALSE},
3505             {"http://g\noogle.co\rm/\n\n\n",S_OK,FALSE},
3506             {"http",S_OK,FALSE},
3507             {"",S_FALSE,FALSE},
3508             {"",S_FALSE,FALSE}
3509         },
3510         {
3511             {Uri_HOST_DNS,S_OK,FALSE},
3512             {80,S_OK,FALSE},
3513             {URL_SCHEME_HTTP,S_OK,FALSE},
3514             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3515         }
3516     },
3517     {   "zip://g\noogle.co\rm/\n\n\n", Uri_CREATE_NO_PRE_PROCESS_HTML_URI, S_OK, FALSE,
3518         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
3519         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
3520         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
3521         FALSE,
3522         {
3523             {"zip://g\noogle.co\rm/\n\n\n",S_OK,FALSE},
3524             {"g\noogle.co\rm",S_OK,FALSE},
3525             {"zip://g\noogle.co\rm/\n\n\n",S_OK,FALSE},
3526             {"g\noogle.co\rm",S_OK,FALSE},
3527             {"",S_FALSE,FALSE},
3528             {"",S_FALSE,FALSE},
3529             {"g\noogle.co\rm",S_OK,FALSE},
3530             {"",S_FALSE,FALSE},
3531             {"/\n\n\n",S_OK,FALSE},
3532             {"/\n\n\n",S_OK,FALSE},
3533             {"",S_FALSE,FALSE},
3534             {"zip://g\noogle.co\rm/\n\n\n",S_OK,FALSE},
3535             {"zip",S_OK,FALSE},
3536             {"",S_FALSE,FALSE},
3537             {"",S_FALSE,FALSE}
3538         },
3539         {
3540             {Uri_HOST_DNS,S_OK,FALSE},
3541             {0,S_FALSE,FALSE},
3542             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
3543             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3544         }
3545     },
3546     /* Since file URLs are usually hierarchical, it returns an empty string
3547      * for the absolute URI property since it was declared as an opaque URI.
3548      */
3549     {   "file:index.html", 0, S_OK, FALSE,
3550         Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY
3551         |Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME, FALSE,
3552         {
3553             {"",S_FALSE,FALSE},
3554             {"",S_FALSE,FALSE},
3555             {"file:index.html",S_OK,FALSE},
3556             {"",S_FALSE,FALSE},
3557             {".html",S_OK,FALSE},
3558             {"",S_FALSE,FALSE},
3559             {"",S_FALSE,FALSE},
3560             {"",S_FALSE,FALSE},
3561             {"index.html",S_OK,FALSE},
3562             {"index.html",S_OK,FALSE},
3563             {"",S_FALSE,FALSE},
3564             {"file:index.html",S_OK,FALSE},
3565             {"file",S_OK,FALSE},
3566             {"",S_FALSE,FALSE},
3567             {"",S_FALSE,FALSE}
3568         },
3569         {
3570             {0,S_OK,FALSE},
3571             {0,S_FALSE,FALSE},
3572             {URL_SCHEME_FILE,S_OK,FALSE},
3573             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3574         }
3575     },
3576     /* Doesn't have an absolute since it's opaque, but gets it port set. */
3577     {   "http:test.com/index.html", 0, S_OK, FALSE,
3578         Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY
3579         |Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME, FALSE,
3580         {
3581             {"",S_FALSE,FALSE},
3582             {"",S_FALSE,FALSE},
3583             {"http:test.com/index.html",S_OK,FALSE},
3584             {"",S_FALSE,FALSE},
3585             {".html",S_OK,FALSE},
3586             {"",S_FALSE,FALSE},
3587             {"",S_FALSE,FALSE},
3588             {"",S_FALSE,FALSE},
3589             {"test.com/index.html",S_OK,FALSE},
3590             {"test.com/index.html",S_OK,FALSE},
3591             {"",S_FALSE,FALSE},
3592             {"http:test.com/index.html",S_OK,FALSE},
3593             {"http",S_OK,FALSE},
3594             {"",S_FALSE,FALSE},
3595             {"",S_FALSE,FALSE}
3596         },
3597         {
3598             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3599             {80,S_OK,FALSE},
3600             {URL_SCHEME_HTTP,S_OK,FALSE},
3601             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3602         }
3603     },
3604     {   "ftp:test.com/index.html", 0, S_OK, FALSE,
3605         Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY
3606         |Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME, FALSE,
3607         {
3608             {"",S_FALSE,FALSE},
3609             {"",S_FALSE,FALSE},
3610             {"ftp:test.com/index.html",S_OK,FALSE},
3611             {"",S_FALSE,FALSE},
3612             {".html",S_OK,FALSE},
3613             {"",S_FALSE,FALSE},
3614             {"",S_FALSE,FALSE},
3615             {"",S_FALSE,FALSE},
3616             {"test.com/index.html",S_OK,FALSE},
3617             {"test.com/index.html",S_OK,FALSE},
3618             {"",S_FALSE,FALSE},
3619             {"ftp:test.com/index.html",S_OK,FALSE},
3620             {"ftp",S_OK,FALSE},
3621             {"",S_FALSE,FALSE},
3622             {"",S_FALSE,FALSE}
3623         },
3624         {
3625             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3626             {21,S_OK,FALSE},
3627             {URL_SCHEME_FTP,S_OK,FALSE},
3628             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3629         }
3630     },
3631     {   "file://C|/test.mp3", 0, S_OK, FALSE,
3632         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH|
3633         Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
3634         FALSE,
3635         {
3636             {"file:///C:/test.mp3",S_OK,FALSE},
3637             {"",S_FALSE,FALSE},
3638             {"file:///C:/test.mp3",S_OK,FALSE},
3639             {"",S_FALSE,FALSE},
3640             {".mp3",S_OK,FALSE},
3641             {"",S_FALSE,FALSE},
3642             {"",S_FALSE,FALSE},
3643             {"",S_FALSE,FALSE},
3644             {"/C:/test.mp3",S_OK,FALSE},
3645             {"/C:/test.mp3",S_OK,FALSE},
3646             {"",S_FALSE,FALSE},
3647             {"file://C|/test.mp3",S_OK,FALSE},
3648             {"file",S_OK,FALSE},
3649             {"",S_FALSE,FALSE},
3650             {"",S_FALSE,FALSE}
3651         },
3652         {
3653             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3654             {0,S_FALSE,FALSE},
3655             {URL_SCHEME_FILE,S_OK,FALSE},
3656             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3657         }
3658     },
3659     {   "file:///C|/test.mp3", 0, S_OK, FALSE,
3660         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH|
3661         Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
3662         FALSE,
3663         {
3664             {"file:///C:/test.mp3",S_OK,FALSE},
3665             {"",S_FALSE,FALSE},
3666             {"file:///C:/test.mp3",S_OK,FALSE},
3667             {"",S_FALSE,FALSE},
3668             {".mp3",S_OK,FALSE},
3669             {"",S_FALSE,FALSE},
3670             {"",S_FALSE,FALSE},
3671             {"",S_FALSE,FALSE},
3672             {"/C:/test.mp3",S_OK,FALSE},
3673             {"/C:/test.mp3",S_OK,FALSE},
3674             {"",S_FALSE,FALSE},
3675             {"file:///C|/test.mp3",S_OK,FALSE},
3676             {"file",S_OK,FALSE},
3677             {"",S_FALSE,FALSE},
3678             {"",S_FALSE,FALSE}
3679         },
3680         {
3681             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3682             {0,S_FALSE,FALSE},
3683             {URL_SCHEME_FILE,S_OK,FALSE},
3684             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3685         }
3686     },
3687     /* Extra '/' isn't added before "c:" since USE_DOS_PATH is set and '/' are converted
3688      * to '\\'.
3689      */
3690     {   "file://c:/dir/index.html", Uri_CREATE_FILE_USE_DOS_PATH, S_OK, FALSE,
3691         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH
3692         |Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE
3693         |Uri_HAS_SCHEME, FALSE,
3694         {
3695             {"file://c:\\dir\\index.html",S_OK,FALSE},
3696             {"",S_FALSE,FALSE},
3697             {"file://c:\\dir\\index.html",S_OK,FALSE},
3698             {"",S_FALSE,FALSE},
3699             {".html",S_OK,FALSE},
3700             {"",S_FALSE,FALSE},
3701             {"",S_FALSE,FALSE},
3702             {"",S_FALSE,FALSE},
3703             {"c:\\dir\\index.html",S_OK,FALSE},
3704             {"c:\\dir\\index.html",S_OK,FALSE},
3705             {"",S_FALSE,FALSE},
3706             {"file://c:/dir/index.html",S_OK,FALSE},
3707             {"file",S_OK,FALSE},
3708             {"",S_FALSE,FALSE},
3709             {"",S_FALSE,FALSE}
3710         },
3711         {
3712             {0,S_OK,FALSE},
3713             {0,S_FALSE,FALSE},
3714             {URL_SCHEME_FILE,S_OK,FALSE},
3715             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3716         }
3717     },
3718     /* Extra '/' after "file://" is removed. */
3719     {   "file:///c:/dir/index.html", Uri_CREATE_FILE_USE_DOS_PATH, S_OK, FALSE,
3720         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH
3721         |Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE
3722         |Uri_HAS_SCHEME, FALSE,
3723         {
3724             {"file://c:\\dir\\index.html",S_OK,FALSE},
3725             {"",S_FALSE,FALSE},
3726             {"file://c:\\dir\\index.html",S_OK,FALSE},
3727             {"",S_FALSE,FALSE},
3728             {".html",S_OK,FALSE},
3729             {"",S_FALSE,FALSE},
3730             {"",S_FALSE,FALSE},
3731             {"",S_FALSE,FALSE},
3732             {"c:\\dir\\index.html",S_OK,FALSE},
3733             {"c:\\dir\\index.html",S_OK,FALSE},
3734             {"",S_FALSE,FALSE},
3735             {"file:///c:/dir/index.html",S_OK,FALSE},
3736             {"file",S_OK,FALSE},
3737             {"",S_FALSE,FALSE},
3738             {"",S_FALSE,FALSE}
3739         },
3740         {
3741             {0,S_OK,FALSE},
3742             {0,S_FALSE,FALSE},
3743             {URL_SCHEME_FILE,S_OK,FALSE},
3744             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3745         }
3746     },
3747     /* Allow more characters when Uri_CREATE_FILE_USE_DOS_PATH is specified */
3748     {   "file:///c:/dir\%%61%20%5Fname/file%2A.html", Uri_CREATE_FILE_USE_DOS_PATH, S_OK, FALSE,
3749         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH
3750         |Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE
3751         |Uri_HAS_SCHEME, FALSE,
3752         {
3753             {"file://c:\\dir\%a _name\\file*.html",S_OK,FALSE},
3754             {"",S_FALSE,FALSE},
3755             {"file://c:\\dir\%a _name\\file*.html",S_OK,FALSE},
3756             {"",S_FALSE,FALSE},
3757             {".html",S_OK,FALSE},
3758             {"",S_FALSE,FALSE},
3759             {"",S_FALSE,FALSE},
3760             {"",S_FALSE,FALSE},
3761             {"c:\\dir\%a _name\\file*.html",S_OK,FALSE},
3762             {"c:\\dir\%a _name\\file*.html",S_OK,FALSE},
3763             {"",S_FALSE,FALSE},
3764             {"file:///c:/dir\%%61%20%5Fname/file%2A.html",S_OK,FALSE},
3765             {"file",S_OK,FALSE},
3766             {"",S_FALSE,FALSE},
3767             {"",S_FALSE,FALSE}
3768         },
3769         {
3770             {0,S_OK,FALSE},
3771             {0,S_FALSE,FALSE},
3772             {URL_SCHEME_FILE,S_OK,FALSE},
3773             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3774         }
3775     },
3776     {   "file://c|/dir\\index.html", Uri_CREATE_FILE_USE_DOS_PATH, S_OK, FALSE,
3777         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH
3778         |Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE
3779         |Uri_HAS_SCHEME, FALSE,
3780         {
3781             {"file://c:\\dir\\index.html",S_OK,FALSE},
3782             {"",S_FALSE,FALSE},
3783             {"file://c:\\dir\\index.html",S_OK,FALSE},
3784             {"",S_FALSE,FALSE},
3785             {".html",S_OK,FALSE},
3786             {"",S_FALSE,FALSE},
3787             {"",S_FALSE,FALSE},
3788             {"",S_FALSE,FALSE},
3789             {"c:\\dir\\index.html",S_OK,FALSE},
3790             {"c:\\dir\\index.html",S_OK,FALSE},
3791             {"",S_FALSE,FALSE},
3792             {"file://c|/dir\\index.html",S_OK,FALSE},
3793             {"file",S_OK,FALSE},
3794             {"",S_FALSE,FALSE},
3795             {"",S_FALSE,FALSE}
3796         },
3797         {
3798             {0,S_OK,FALSE},
3799             {0,S_FALSE,FALSE},
3800             {URL_SCHEME_FILE,S_OK,FALSE},
3801             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3802         }
3803     },
3804     /* The backslashes after the scheme name are converted to forward slashes. */
3805     {   "file:\\\\c:\\dir\\index.html", Uri_CREATE_FILE_USE_DOS_PATH, S_OK, FALSE,
3806         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH
3807         |Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE
3808         |Uri_HAS_SCHEME, FALSE,
3809         {
3810             {"file://c:\\dir\\index.html",S_OK,FALSE},
3811             {"",S_FALSE,FALSE},
3812             {"file://c:\\dir\\index.html",S_OK,FALSE},
3813             {"",S_FALSE,FALSE},
3814             {".html",S_OK,FALSE},
3815             {"",S_FALSE,FALSE},
3816             {"",S_FALSE,FALSE},
3817             {"",S_FALSE,FALSE},
3818             {"c:\\dir\\index.html",S_OK,FALSE},
3819             {"c:\\dir\\index.html",S_OK,FALSE},
3820             {"",S_FALSE,FALSE},
3821             {"file:\\\\c:\\dir\\index.html",S_OK,FALSE},
3822             {"file",S_OK,FALSE},
3823             {"",S_FALSE,FALSE},
3824             {"",S_FALSE,FALSE}
3825         },
3826         {
3827             {0,S_OK,FALSE},
3828             {0,S_FALSE,FALSE},
3829             {URL_SCHEME_FILE,S_OK,FALSE},
3830             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3831         }
3832     },
3833     {   "file:\\\\c:/dir/index.html", 0, S_OK, FALSE,
3834         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH
3835         |Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE
3836         |Uri_HAS_SCHEME, FALSE,
3837         {
3838             {"file:///c:/dir/index.html",S_OK,FALSE},
3839             {"",S_FALSE,FALSE},
3840             {"file:///c:/dir/index.html",S_OK,FALSE},
3841             {"",S_FALSE,FALSE},
3842             {".html",S_OK,FALSE},
3843             {"",S_FALSE,FALSE},
3844             {"",S_FALSE,FALSE},
3845             {"",S_FALSE,FALSE},
3846             {"/c:/dir/index.html",S_OK,FALSE},
3847             {"/c:/dir/index.html",S_OK,FALSE},
3848             {"",S_FALSE,FALSE},
3849             {"file:\\\\c:/dir/index.html",S_OK,FALSE},
3850             {"file",S_OK,FALSE},
3851             {"",S_FALSE,FALSE},
3852             {"",S_FALSE,FALSE}
3853         },
3854         {
3855             {0,S_OK,FALSE},
3856             {0,S_FALSE,FALSE},
3857             {URL_SCHEME_FILE,S_OK,FALSE},
3858             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3859         }
3860     },
3861     {   "http:\\\\google.com", 0, S_OK, FALSE,
3862         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
3863         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
3864         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
3865         FALSE,
3866         {
3867             {"http://google.com/",S_OK,FALSE},
3868             {"google.com",S_OK,FALSE},
3869             {"http://google.com/",S_OK,FALSE},
3870             {"google.com",S_OK,FALSE},
3871             {"",S_FALSE,FALSE},
3872             {"",S_FALSE,FALSE},
3873             {"google.com",S_OK,FALSE},
3874             {"",S_FALSE,FALSE},
3875             {"/",S_OK,FALSE},
3876             {"/",S_OK,FALSE},
3877             {"",S_FALSE,FALSE},
3878             {"http:\\\\google.com",S_OK,FALSE},
3879             {"http",S_OK,FALSE},
3880             {"",S_FALSE,FALSE},
3881             {"",S_FALSE,FALSE}
3882         },
3883         {
3884             {Uri_HOST_DNS,S_OK,FALSE},
3885             {80,S_OK,FALSE},
3886             {URL_SCHEME_HTTP,S_OK,FALSE},
3887             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3888         }
3889     },
3890     /* the "\\\\" aren't converted to "//" for unknown scheme types and it's considered opaque. */
3891     {   "zip:\\\\google.com", 0, S_OK, FALSE,
3892         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH|
3893         Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_SCHEME|
3894         Uri_HAS_HOST_TYPE,
3895         FALSE,
3896         {
3897             {"zip:\\\\google.com",S_OK,FALSE},
3898             {"",S_FALSE,FALSE},
3899             {"zip:\\\\google.com",S_OK,FALSE},
3900             {"",S_FALSE,FALSE},
3901             {".com",S_OK,FALSE},
3902             {"",S_FALSE,FALSE},
3903             {"",S_FALSE,FALSE},
3904             {"",S_FALSE,FALSE},
3905             {"\\\\google.com",S_OK,FALSE},
3906             {"\\\\google.com",S_OK,FALSE},
3907             {"",S_FALSE,FALSE},
3908             {"zip:\\\\google.com",S_OK,FALSE},
3909             {"zip",S_OK,FALSE},
3910             {"",S_FALSE,FALSE},
3911             {"",S_FALSE,FALSE}
3912         },
3913         {
3914             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3915             {0,S_FALSE,FALSE},
3916             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
3917             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3918         }
3919     },
3920     /* Dot segements aren't removed. */
3921     {   "file://c:\\dir\\../..\\./index.html", Uri_CREATE_FILE_USE_DOS_PATH, S_OK, FALSE,
3922         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH
3923         |Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE
3924         |Uri_HAS_SCHEME, FALSE,
3925         {
3926             {"file://c:\\dir\\..\\..\\.\\index.html",S_OK,FALSE},
3927             {"",S_FALSE,FALSE},
3928             {"file://c:\\dir\\..\\..\\.\\index.html",S_OK,FALSE},
3929             {"",S_FALSE,FALSE},
3930             {".html",S_OK,FALSE},
3931             {"",S_FALSE,FALSE},
3932             {"",S_FALSE,FALSE},
3933             {"",S_FALSE,FALSE},
3934             {"c:\\dir\\..\\..\\.\\index.html",S_OK,FALSE},
3935             {"c:\\dir\\..\\..\\.\\index.html",S_OK,FALSE},
3936             {"",S_FALSE,FALSE},
3937             {"file://c:\\dir\\../..\\./index.html",S_OK,FALSE},
3938             {"file",S_OK,FALSE},
3939             {"",S_FALSE,FALSE},
3940             {"",S_FALSE,FALSE}
3941         },
3942         {
3943             {0,S_OK,FALSE},
3944             {0,S_FALSE,FALSE},
3945             {URL_SCHEME_FILE,S_OK,FALSE},
3946             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3947         }
3948     },
3949     /* Forbidden characters aren't percent encoded. */
3950     {   "file://c:\\dir\\i^|ndex.html", Uri_CREATE_FILE_USE_DOS_PATH, S_OK, FALSE,
3951         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH
3952         |Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE
3953         |Uri_HAS_SCHEME, FALSE,
3954         {
3955             {"file://c:\\dir\\i^|ndex.html",S_OK,FALSE},
3956             {"",S_FALSE,FALSE},
3957             {"file://c:\\dir\\i^|ndex.html",S_OK,FALSE},
3958             {"",S_FALSE,FALSE},
3959             {".html",S_OK,FALSE},
3960             {"",S_FALSE,FALSE},
3961             {"",S_FALSE,FALSE},
3962             {"",S_FALSE,FALSE},
3963             {"c:\\dir\\i^|ndex.html",S_OK,FALSE},
3964             {"c:\\dir\\i^|ndex.html",S_OK,FALSE},
3965             {"",S_FALSE,FALSE},
3966             {"file://c:\\dir\\i^|ndex.html",S_OK,FALSE},
3967             {"file",S_OK,FALSE},
3968             {"",S_FALSE,FALSE},
3969             {"",S_FALSE,FALSE}
3970         },
3971         {
3972             {0,S_OK,FALSE},
3973             {0,S_FALSE,FALSE},
3974             {URL_SCHEME_FILE,S_OK,FALSE},
3975             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3976         }
3977     },
3978     /* The '\' are still converted to '/' even though it's an opaque file URI. */
3979     {   "file:c:\\dir\\../..\\index.html", 0, S_OK, FALSE,
3980         Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY
3981         |Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME, FALSE,
3982         {
3983             {"",S_FALSE,FALSE},
3984             {"",S_FALSE,FALSE},
3985             {"file:c:/dir/../../index.html",S_OK,FALSE},
3986             {"",S_FALSE,FALSE},
3987             {".html",S_OK,FALSE},
3988             {"",S_FALSE,FALSE},
3989             {"",S_FALSE,FALSE},
3990             {"",S_FALSE,FALSE},
3991             {"c:/dir/../../index.html",S_OK,FALSE},
3992             {"c:/dir/../../index.html",S_OK,FALSE},
3993             {"",S_FALSE,FALSE},
3994             {"file:c:\\dir\\../..\\index.html",S_OK,FALSE},
3995             {"file",S_OK,FALSE},
3996             {"",S_FALSE,FALSE},
3997             {"",S_FALSE,FALSE}
3998         },
3999         {
4000             {0,S_OK,FALSE},
4001             {0,S_FALSE,FALSE},
4002             {URL_SCHEME_FILE,S_OK,FALSE},
4003             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4004         }
4005     },
4006     /* '/' are still converted to '\' even though it's an opaque URI. */
4007     {   "file:c:/dir\\../..\\index.html", Uri_CREATE_FILE_USE_DOS_PATH, S_OK, FALSE,
4008         Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY
4009         |Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME, FALSE,
4010         {
4011             {"",S_FALSE,FALSE},
4012             {"",S_FALSE,FALSE},
4013             {"file:c:\\dir\\..\\..\\index.html",S_OK,FALSE},
4014             {"",S_FALSE,FALSE},
4015             {".html",S_OK,FALSE},
4016             {"",S_FALSE,FALSE},
4017             {"",S_FALSE,FALSE},
4018             {"",S_FALSE,FALSE},
4019             {"c:\\dir\\..\\..\\index.html",S_OK,FALSE},
4020             {"c:\\dir\\..\\..\\index.html",S_OK,FALSE},
4021             {"",S_FALSE,FALSE},
4022             {"file:c:/dir\\../..\\index.html",S_OK,FALSE},
4023             {"file",S_OK,FALSE},
4024             {"",S_FALSE,FALSE},
4025             {"",S_FALSE,FALSE}
4026         },
4027         {
4028             {0,S_OK,FALSE},
4029             {0,S_FALSE,FALSE},
4030             {URL_SCHEME_FILE,S_OK,FALSE},
4031             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4032         }
4033     },
4034     /* Forbidden characters aren't percent encoded. */
4035     {   "file:c:\\in^|dex.html", Uri_CREATE_FILE_USE_DOS_PATH, S_OK, FALSE,
4036         Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY
4037         |Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME, FALSE,
4038         {
4039             {"",S_FALSE,FALSE},
4040             {"",S_FALSE,FALSE},
4041             {"file:c:\\in^|dex.html",S_OK,FALSE},
4042             {"",S_FALSE,FALSE},
4043             {".html",S_OK,FALSE},
4044             {"",S_FALSE,FALSE},
4045             {"",S_FALSE,FALSE},
4046             {"",S_FALSE,FALSE},
4047             {"c:\\in^|dex.html",S_OK,FALSE},
4048             {"c:\\in^|dex.html",S_OK,FALSE},
4049             {"",S_FALSE,FALSE},
4050             {"file:c:\\in^|dex.html",S_OK,FALSE},
4051             {"file",S_OK,FALSE},
4052             {"",S_FALSE,FALSE},
4053             {"",S_FALSE,FALSE}
4054         },
4055         {
4056             {0,S_OK,FALSE},
4057             {0,S_FALSE,FALSE},
4058             {URL_SCHEME_FILE,S_OK,FALSE},
4059             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4060         }
4061     },
4062     /* Doesn't have a UserName since the ':' appears at the beginning of the
4063      * userinfo section.
4064      */
4065     {   "http://:password@gov.uk", 0, S_OK, FALSE,
4066         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
4067         Uri_HAS_PASSWORD|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
4068         Uri_HAS_USER_INFO|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
4069         FALSE,
4070         {
4071             {"http://:password@gov.uk/",S_OK,FALSE},
4072             {":password@gov.uk",S_OK,FALSE},
4073             {"http://gov.uk/",S_OK,FALSE},
4074             {"",S_FALSE,FALSE},
4075             {"",S_FALSE,FALSE},
4076             {"",S_FALSE,FALSE},
4077             {"gov.uk",S_OK,FALSE},
4078             {"password",S_OK,FALSE},
4079             {"/",S_OK,FALSE},
4080             {"/",S_OK,FALSE},
4081             {"",S_FALSE,FALSE},
4082             {"http://:password@gov.uk",S_OK,FALSE},
4083             {"http",S_OK,FALSE},
4084             {":password",S_OK,FALSE},
4085             {"",S_FALSE,FALSE}
4086         },
4087         {
4088             {Uri_HOST_DNS,S_OK,FALSE},
4089             {80,S_OK,FALSE},
4090             {URL_SCHEME_HTTP,S_OK,FALSE},
4091             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4092         }
4093     },
4094     /* Has a UserName since the userinfo section doesn't contain a password. */
4095     {   "http://@gov.uk", 0, S_OK, FALSE,
4096         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
4097         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
4098         Uri_HAS_USER_INFO|Uri_HAS_USER_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
4099         FALSE,
4100         {
4101             {"http://gov.uk/",S_OK,FALSE,"http://@gov.uk/"},
4102             {"@gov.uk",S_OK,FALSE},
4103             {"http://gov.uk/",S_OK,FALSE},
4104             {"",S_FALSE,FALSE},
4105             {"",S_FALSE,FALSE},
4106             {"",S_FALSE,FALSE},
4107             {"gov.uk",S_OK,FALSE},
4108             {"",S_FALSE,FALSE},
4109             {"/",S_OK,FALSE},
4110             {"/",S_OK,FALSE},
4111             {"",S_FALSE,FALSE},
4112             {"http://@gov.uk",S_OK,FALSE},
4113             {"http",S_OK,FALSE},
4114             {"",S_OK,FALSE},
4115             {"",S_OK,FALSE}
4116         },
4117         {
4118             {Uri_HOST_DNS,S_OK,FALSE},
4119             {80,S_OK,FALSE},
4120             {URL_SCHEME_HTTP,S_OK,FALSE},
4121             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4122         }
4123     },
4124     /* ":@" not included in the absolute URI. */
4125     {   "http://:@gov.uk", 0, S_OK, FALSE,
4126         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
4127         Uri_HAS_PASSWORD|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
4128         Uri_HAS_USER_INFO|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
4129         FALSE,
4130         {
4131             {"http://gov.uk/",S_OK,FALSE,"http://:@gov.uk/"},
4132             {":@gov.uk",S_OK,FALSE},
4133             {"http://gov.uk/",S_OK,FALSE},
4134             {"",S_FALSE,FALSE},
4135             {"",S_FALSE,FALSE},
4136             {"",S_FALSE,FALSE},
4137             {"gov.uk",S_OK,FALSE},
4138             {"",S_OK,FALSE},
4139             {"/",S_OK,FALSE},
4140             {"/",S_OK,FALSE},
4141             {"",S_FALSE,FALSE},
4142             {"http://:@gov.uk",S_OK,FALSE},
4143             {"http",S_OK,FALSE},
4144             {":",S_OK,FALSE},
4145             {"",S_FALSE,FALSE}
4146         },
4147         {
4148             {Uri_HOST_DNS,S_OK,FALSE},
4149             {80,S_OK,FALSE},
4150             {URL_SCHEME_HTTP,S_OK,FALSE},
4151             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4152         }
4153     },
4154     /* '@' is included because it's an unknown scheme type. */
4155     {   "zip://@gov.uk", 0, S_OK, FALSE,
4156         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
4157         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
4158         Uri_HAS_USER_INFO|Uri_HAS_USER_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
4159         FALSE,
4160         {
4161             {"zip://@gov.uk/",S_OK,FALSE},
4162             {"@gov.uk",S_OK,FALSE},
4163             {"zip://@gov.uk/",S_OK,FALSE},
4164             {"",S_FALSE,FALSE},
4165             {"",S_FALSE,FALSE},
4166             {"",S_FALSE,FALSE},
4167             {"gov.uk",S_OK,FALSE},
4168             {"",S_FALSE,FALSE},
4169             {"/",S_OK,FALSE},
4170             {"/",S_OK,FALSE},
4171             {"",S_FALSE,FALSE},
4172             {"zip://@gov.uk",S_OK,FALSE},
4173             {"zip",S_OK,FALSE},
4174             {"",S_OK,FALSE},
4175             {"",S_OK,FALSE}
4176         },
4177         {
4178             {Uri_HOST_DNS,S_OK,FALSE},
4179             {0,S_FALSE,FALSE},
4180             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
4181             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4182         }
4183     },
4184     /* ":@" are included because it's an unknown scheme type. */
4185     {   "zip://:@gov.uk", 0, S_OK, FALSE,
4186         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
4187         Uri_HAS_PASSWORD|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
4188         Uri_HAS_SCHEME_NAME|Uri_HAS_USER_INFO|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
4189         FALSE,
4190         {
4191             {"zip://:@gov.uk/",S_OK,FALSE},
4192             {":@gov.uk",S_OK,FALSE},
4193             {"zip://:@gov.uk/",S_OK,FALSE},
4194             {"",S_FALSE,FALSE},
4195             {"",S_FALSE,FALSE},
4196             {"",S_FALSE,FALSE},
4197             {"gov.uk",S_OK,FALSE},
4198             {"",S_OK,FALSE},
4199             {"/",S_OK,FALSE},
4200             {"/",S_OK,FALSE},
4201             {"",S_FALSE,FALSE},
4202             {"zip://:@gov.uk",S_OK,FALSE},
4203             {"zip",S_OK,FALSE},
4204             {":",S_OK,FALSE},
4205             {"",S_FALSE,FALSE}
4206         },
4207         {
4208             {Uri_HOST_DNS,S_OK,FALSE},
4209             {0,S_FALSE,FALSE},
4210             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
4211             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4212         }
4213     },
4214     {   "about:blank", 0, S_OK, FALSE,
4215         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
4216         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
4217         FALSE,
4218         {
4219             {"about:blank",S_OK,FALSE},
4220             {"",S_FALSE,FALSE},
4221             {"about:blank",S_OK,FALSE},
4222             {"",S_FALSE,FALSE},
4223             {"",S_FALSE,FALSE},
4224             {"",S_FALSE,FALSE},
4225             {"",S_FALSE,FALSE},
4226             {"",S_FALSE,FALSE},
4227             {"blank",S_OK,FALSE},
4228             {"blank",S_OK,FALSE},
4229             {"",S_FALSE,FALSE},
4230             {"about:blank",S_OK,FALSE},
4231             {"about",S_OK,FALSE},
4232             {"",S_FALSE,FALSE},
4233             {"",S_FALSE,FALSE}
4234         },
4235         {
4236             {0,S_OK,FALSE},
4237             {0,S_FALSE,FALSE},
4238             {URL_SCHEME_ABOUT,S_OK,FALSE},
4239             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4240         }
4241     },
4242     {   "mk:@MSITStore:C:\\Program Files/AutoCAD 2008\\Help/acad_acg.chm::/WSfacf1429558a55de1a7524c1004e616f8b-322b.htm",0,S_OK,FALSE,
4243         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|
4244         Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
4245         FALSE,
4246         {
4247             {"mk:@MSITStore:C:\\Program%20Files/AutoCAD%202008\\Help/acad_acg.chm::/WSfacf1429558a55de1a7524c1004e616f8b-322b.htm",S_OK,FALSE},
4248             {"",S_FALSE,FALSE},
4249             {"mk:@MSITStore:C:\\Program%20Files/AutoCAD%202008\\Help/acad_acg.chm::/WSfacf1429558a55de1a7524c1004e616f8b-322b.htm",S_OK,FALSE},
4250             {"",S_FALSE,FALSE},
4251             {".htm",S_OK,FALSE},
4252             {"",S_FALSE,FALSE},
4253             {"",S_FALSE,FALSE},
4254             {"",S_FALSE,FALSE},
4255             {"@MSITStore:C:\\Program%20Files/AutoCAD%202008\\Help/acad_acg.chm::/WSfacf1429558a55de1a7524c1004e616f8b-322b.htm",S_OK,FALSE},
4256             {"@MSITStore:C:\\Program%20Files/AutoCAD%202008\\Help/acad_acg.chm::/WSfacf1429558a55de1a7524c1004e616f8b-322b.htm",S_OK,FALSE},
4257             {"",S_FALSE,FALSE},
4258             {"mk:@MSITStore:C:\\Program Files/AutoCAD 2008\\Help/acad_acg.chm::/WSfacf1429558a55de1a7524c1004e616f8b-322b.htm",S_OK,FALSE},
4259             {"mk",S_OK,FALSE},
4260             {"",S_FALSE,FALSE},
4261             {"",S_FALSE,FALSE}
4262         },
4263         {
4264             {Uri_HOST_UNKNOWN,S_OK,FALSE},
4265             {0,S_FALSE,FALSE},
4266             {URL_SCHEME_MK,S_OK,FALSE},
4267             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4268         }
4269     },
4270     {   "mk:@MSITStore:Z:\\home\\test\\chm\\silqhelp.chm::/thesilqquickstartguide.htm",0,S_OK,FALSE,
4271         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|
4272         Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
4273         FALSE,
4274         {
4275             {"mk:@MSITStore:Z:\\home\\test\\chm\\silqhelp.chm::/thesilqquickstartguide.htm",S_OK,FALSE},
4276             {"",S_FALSE,FALSE},
4277             {"mk:@MSITStore:Z:\\home\\test\\chm\\silqhelp.chm::/thesilqquickstartguide.htm",S_OK,FALSE},
4278             {"",S_FALSE,FALSE},
4279             {".htm",S_OK,FALSE},
4280             {"",S_FALSE,FALSE},
4281             {"",S_FALSE,FALSE},
4282             {"",S_FALSE,FALSE},
4283             {"@MSITStore:Z:\\home\\test\\chm\\silqhelp.chm::/thesilqquickstartguide.htm",S_OK,FALSE},
4284             {"@MSITStore:Z:\\home\\test\\chm\\silqhelp.chm::/thesilqquickstartguide.htm",S_OK,FALSE},
4285             {"",S_FALSE,FALSE},
4286             {"mk:@MSITStore:Z:\\home\\test\\chm\\silqhelp.chm::/thesilqquickstartguide.htm",S_OK,FALSE},
4287             {"mk",S_OK,FALSE},
4288             {"",S_FALSE,FALSE},
4289             {"",S_FALSE,FALSE}
4290         },
4291         {
4292             {Uri_HOST_UNKNOWN,S_OK,FALSE},
4293             {0,S_FALSE,FALSE},
4294             {URL_SCHEME_MK,S_OK,FALSE},
4295             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4296         }
4297     }
4298 };
4299
4300 typedef struct _invalid_uri {
4301     const char* uri;
4302     DWORD       flags;
4303     BOOL        todo;
4304 } invalid_uri;
4305
4306 static const invalid_uri invalid_uri_tests[] = {
4307     /* Has to have a scheme name. */
4308     {"://www.winehq.org",0,FALSE},
4309     /* Window's doesn't like URI's which are implicitly file paths without the
4310      * ALLOW_IMPLICIT_FILE_SCHEME flag set.
4311      */
4312     {"C:/test/test.mp3",0,FALSE},
4313     {"\\\\Server/test/test.mp3",0,FALSE},
4314     {"C:/test/test.mp3",Uri_CREATE_ALLOW_IMPLICIT_WILDCARD_SCHEME,FALSE},
4315     {"\\\\Server/test/test.mp3",Uri_CREATE_ALLOW_RELATIVE,FALSE},
4316     /* Invalid schemes. */
4317     {"*abcd://not.valid.com",0,FALSE},
4318     {"*a*b*c*d://not.valid.com",0,FALSE},
4319     /* Not allowed to have invalid % encoded data. */
4320     {"ftp://google.co%XX/",0,FALSE},
4321     /* To many h16 components. */
4322     {"http://[1:2:3:4:5:6:7:8:9]",0,FALSE},
4323     /* Not enough room for IPv4 address. */
4324     {"http://[1:2:3:4:5:6:7:192.0.1.0]",0,FALSE},
4325     /* Not enough h16 components. */
4326     {"http://[1:2:3:4]",0,FALSE},
4327     /* Not enough components including IPv4. */
4328     {"http://[1:192.0.1.0]",0,FALSE},
4329     /* Not allowed to have partial IPv4 in IPv6. */
4330     {"http://[::192.0]",0,FALSE},
4331     /* Can't have elision of 1 h16 at beginning of address. */
4332     {"http://[::2:3:4:5:6:7:8]",0,FALSE},
4333     /* Can't have elision of 1 h16 at end of address. */
4334     {"http://[1:2:3:4:5:6:7::]",0,FALSE},
4335     /* Expects a valid IP Literal. */
4336     {"ftp://[not.valid.uri]/",0,FALSE},
4337     /* Expects valid port for a known scheme type. */
4338     {"ftp://www.winehq.org:123fgh",0,FALSE},
4339     /* Port exceeds USHORT_MAX for known scheme type. */
4340     {"ftp://www.winehq.org:65536",0,FALSE},
4341     /* Invalid port with IPv4 address. */
4342     {"http://www.winehq.org:1abcd",0,FALSE},
4343     /* Invalid port with IPv6 address. */
4344     {"http://[::ffff]:32xy",0,FALSE},
4345     /* Not allowed to have backslashes with NO_CANONICALIZE. */
4346     {"gopher://www.google.com\\test",Uri_CREATE_NO_CANONICALIZE,FALSE},
4347     /* Not allowed to have invalid % encoded data in opaque URI path. */
4348     {"news:test%XX",0,FALSE},
4349     {"mailto:wine@winehq%G8.com",0,FALSE},
4350     /* Known scheme types can't have invalid % encoded data in query string. */
4351     {"http://google.com/?query=te%xx",0,FALSE},
4352     /* Invalid % encoded data in fragment of know scheme type. */
4353     {"ftp://google.com/#Test%xx",0,FALSE},
4354     {"  http://google.com/",Uri_CREATE_NO_PRE_PROCESS_HTML_URI,FALSE},
4355     {"\n\nhttp://google.com/",Uri_CREATE_NO_PRE_PROCESS_HTML_URI,FALSE},
4356     {"file://c:\\test<test",Uri_CREATE_FILE_USE_DOS_PATH,FALSE},
4357     {"file://c:\\test>test",Uri_CREATE_FILE_USE_DOS_PATH,FALSE},
4358     {"file://c:\\test\"test",Uri_CREATE_FILE_USE_DOS_PATH,FALSE},
4359     {"file:c:\\test<test",Uri_CREATE_FILE_USE_DOS_PATH,FALSE},
4360     {"file:c:\\test>test",Uri_CREATE_FILE_USE_DOS_PATH,FALSE},
4361     {"file:c:\\test\"test",Uri_CREATE_FILE_USE_DOS_PATH,FALSE}
4362 };
4363
4364 typedef struct _uri_equality {
4365     const char* a;
4366     DWORD       create_flags_a;
4367     BOOL        create_todo_a;
4368     const char* b;
4369     DWORD       create_flags_b;
4370     BOOL        create_todo_b;
4371     BOOL        equal;
4372     BOOL        todo;
4373 } uri_equality;
4374
4375 static const uri_equality equality_tests[] = {
4376     {
4377         "HTTP://www.winehq.org/test dir/./",0,FALSE,
4378         "http://www.winehq.org/test dir/../test dir/",0,FALSE,
4379         TRUE, FALSE
4380     },
4381     {
4382         /* http://www.winehq.org/test%20dir */
4383         "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,
4384         "http://www.winehq.org/test dir",0,FALSE,
4385         TRUE, FALSE
4386     },
4387     {
4388         "c:\\test.mp3",Uri_CREATE_ALLOW_IMPLICIT_FILE_SCHEME,FALSE,
4389         "file:///c:/test.mp3",0,FALSE,
4390         TRUE, FALSE
4391     },
4392     {
4393         "ftp://ftp.winehq.org/",0,FALSE,
4394         "ftp://ftp.winehq.org",0,FALSE,
4395         TRUE, FALSE
4396     },
4397     {
4398         "ftp://ftp.winehq.org/test/test2/../../testB/",0,FALSE,
4399         "ftp://ftp.winehq.org/t%45stB/",0,FALSE,
4400         FALSE, FALSE
4401     },
4402     {
4403         "http://google.com/TEST",0,FALSE,
4404         "http://google.com/test",0,FALSE,
4405         FALSE, FALSE
4406     },
4407     {
4408         "http://GOOGLE.com/",0,FALSE,
4409         "http://google.com/",0,FALSE,
4410         TRUE, FALSE
4411     },
4412     /* Performs case insensitive compare of host names (for known scheme types). */
4413     {
4414         "ftp://GOOGLE.com/",Uri_CREATE_NO_CANONICALIZE,FALSE,
4415         "ftp://google.com/",0,FALSE,
4416         TRUE, FALSE
4417     },
4418     {
4419         "zip://GOOGLE.com/",0,FALSE,
4420         "zip://google.com/",0,FALSE,
4421         FALSE, FALSE
4422     },
4423     {
4424         "file:///c:/TEST/TeST/",0,FALSE,
4425         "file:///c:/test/test/",0,FALSE,
4426         TRUE, FALSE
4427     },
4428     {
4429         "file:///server/TEST",0,FALSE,
4430         "file:///SERVER/TEST",0,FALSE,
4431         TRUE, FALSE
4432     },
4433     {
4434         "http://google.com",Uri_CREATE_NO_CANONICALIZE,FALSE,
4435         "http://google.com/",0,FALSE,
4436         TRUE, FALSE
4437     },
4438     {
4439         "ftp://google.com:21/",0,FALSE,
4440         "ftp://google.com/",0,FALSE,
4441         TRUE, FALSE
4442     },
4443     {
4444         "http://google.com:80/",Uri_CREATE_NO_CANONICALIZE,FALSE,
4445         "http://google.com/",0,FALSE,
4446         TRUE, FALSE
4447     },
4448     {
4449         "http://google.com:70/",0,FALSE,
4450         "http://google.com:71/",0,FALSE,
4451         FALSE, FALSE
4452     }
4453 };
4454
4455 typedef struct _uri_with_fragment {
4456     const char* uri;
4457     const char* fragment;
4458     DWORD       create_flags;
4459     HRESULT     create_expected;
4460     BOOL        create_todo;
4461
4462     const char* expected_uri;
4463     BOOL        expected_todo;
4464 } uri_with_fragment;
4465
4466 static const uri_with_fragment uri_fragment_tests[] = {
4467     {
4468         "http://google.com/","#fragment",0,S_OK,FALSE,
4469         "http://google.com/#fragment",FALSE
4470     },
4471     {
4472         "http://google.com/","fragment",0,S_OK,FALSE,
4473         "http://google.com/#fragment",FALSE
4474     },
4475     {
4476         "zip://test.com/","?test",0,S_OK,FALSE,
4477         "zip://test.com/#?test",FALSE
4478     },
4479     /* The fragment can be empty. */
4480     {
4481         "ftp://ftp.google.com/","",0,S_OK,FALSE,
4482         "ftp://ftp.google.com/#",FALSE
4483     }
4484 };
4485
4486 typedef struct _uri_builder_property {
4487     BOOL            change;
4488     const char      *value;
4489     const char      *expected_value;
4490     Uri_PROPERTY    property;
4491     HRESULT         expected;
4492     BOOL            todo;
4493 } uri_builder_property;
4494
4495 typedef struct _uri_builder_port {
4496     BOOL    change;
4497     BOOL    set;
4498     DWORD   value;
4499     HRESULT expected;
4500     BOOL    todo;
4501 } uri_builder_port;
4502
4503 typedef struct _uri_builder_str_property {
4504     const char* expected;
4505     HRESULT     result;
4506     BOOL        todo;
4507 } uri_builder_str_property;
4508
4509 typedef struct _uri_builder_dword_property {
4510     DWORD   expected;
4511     HRESULT result;
4512     BOOL    todo;
4513 } uri_builder_dword_property;
4514
4515 typedef struct _uri_builder_test {
4516     const char                  *uri;
4517     DWORD                       create_flags;
4518     HRESULT                     create_builder_expected;
4519     BOOL                        create_builder_todo;
4520
4521     uri_builder_property        properties[URI_BUILDER_STR_PROPERTY_COUNT];
4522
4523     uri_builder_port            port_prop;
4524
4525     DWORD                       uri_flags;
4526     HRESULT                     uri_hres;
4527     BOOL                        uri_todo;
4528
4529     DWORD                       uri_simple_encode_flags;
4530     HRESULT                     uri_simple_hres;
4531     BOOL                        uri_simple_todo;
4532
4533     DWORD                       uri_with_flags;
4534     DWORD                       uri_with_builder_flags;
4535     DWORD                       uri_with_encode_flags;
4536     HRESULT                     uri_with_hres;
4537     BOOL                        uri_with_todo;
4538
4539     uri_builder_str_property    expected_str_props[URI_STR_PROPERTY_COUNT];
4540     uri_builder_dword_property  expected_dword_props[URI_DWORD_PROPERTY_COUNT];
4541 } uri_builder_test;
4542
4543 static const uri_builder_test uri_builder_tests[] = {
4544     {   "http://google.com/",0,S_OK,FALSE,
4545         {
4546             {TRUE,"#fragment",NULL,Uri_PROPERTY_FRAGMENT,S_OK,FALSE},
4547             {TRUE,"password",NULL,Uri_PROPERTY_PASSWORD,S_OK,FALSE},
4548             {TRUE,"?query=x",NULL,Uri_PROPERTY_QUERY,S_OK,FALSE},
4549             {TRUE,"username",NULL,Uri_PROPERTY_USER_NAME,S_OK,FALSE}
4550         },
4551         {FALSE},
4552         0,S_OK,FALSE,
4553         0,S_OK,FALSE,
4554         0,0,0,S_OK,FALSE,
4555         {
4556             {"http://username:password@google.com/?query=x#fragment",S_OK},
4557             {"username:password@google.com",S_OK},
4558             {"http://google.com/?query=x#fragment",S_OK},
4559             {"google.com",S_OK},
4560             {"",S_FALSE},
4561             {"#fragment",S_OK},
4562             {"google.com",S_OK},
4563             {"password",S_OK},
4564             {"/",S_OK},
4565             {"/?query=x",S_OK},
4566             {"?query=x",S_OK},
4567             {"http://username:password@google.com/?query=x#fragment",S_OK},
4568             {"http",S_OK},
4569             {"username:password",S_OK},
4570             {"username",S_OK}
4571         },
4572         {
4573             {Uri_HOST_DNS,S_OK},
4574             {80,S_OK},
4575             {URL_SCHEME_HTTP,S_OK},
4576             {URLZONE_INVALID,E_NOTIMPL}
4577         }
4578     },
4579     {   "http://google.com/",0,S_OK,FALSE,
4580         {
4581             {TRUE,"test",NULL,Uri_PROPERTY_SCHEME_NAME,S_OK,FALSE}
4582         },
4583         {TRUE,TRUE,120,S_OK,FALSE},
4584         0,S_OK,FALSE,
4585         0,S_OK,FALSE,
4586         0,0,0,S_OK,FALSE,
4587         {
4588             {"test://google.com:120/",S_OK},
4589             {"google.com:120",S_OK},
4590             {"test://google.com:120/",S_OK},
4591             {"google.com",S_OK},
4592             {"",S_FALSE},
4593             {"",S_FALSE},
4594             {"google.com",S_OK},
4595             {"",S_FALSE},
4596             {"/",S_OK},
4597             {"/",S_OK},
4598             {"",S_FALSE},
4599             {"test://google.com:120/",S_OK},
4600             {"test",S_OK},
4601             {"",S_FALSE},
4602             {"",S_FALSE}
4603         },
4604         {
4605             {Uri_HOST_DNS,S_OK},
4606             {120,S_OK},
4607             {URL_SCHEME_UNKNOWN,S_OK},
4608             {URLZONE_INVALID,E_NOTIMPL}
4609         }
4610     },
4611     {   "/Test/test dir",Uri_CREATE_ALLOW_RELATIVE,S_OK,FALSE,
4612         {
4613             {TRUE,"http",NULL,Uri_PROPERTY_SCHEME_NAME,S_OK,FALSE},
4614             {TRUE,"::192.2.3.4",NULL,Uri_PROPERTY_HOST,S_OK,FALSE},
4615             {TRUE,NULL,NULL,Uri_PROPERTY_PATH,S_OK,FALSE}
4616         },
4617         {FALSE},
4618         0,S_OK,FALSE,
4619         0,S_OK,FALSE,
4620         0,0,0,S_OK,FALSE,
4621         {
4622             {"http://[::192.2.3.4]/",S_OK},
4623             {"[::192.2.3.4]",S_OK},
4624             {"http://[::192.2.3.4]/",S_OK},
4625             {"",S_FALSE},
4626             {"",S_FALSE},
4627             {"",S_FALSE},
4628             {"::192.2.3.4",S_OK},
4629             {"",S_FALSE},
4630             {"/",S_OK},
4631             {"/",S_OK},
4632             {"",S_FALSE},
4633             {"http://[::192.2.3.4]/",S_OK},
4634             {"http",S_OK},
4635             {"",S_FALSE},
4636             {"",S_FALSE}
4637         },
4638         {
4639             {Uri_HOST_IPV6,S_OK},
4640             {80,S_OK},
4641             {URL_SCHEME_HTTP,S_OK},
4642             {URLZONE_INVALID,E_NOTIMPL}
4643         }
4644     },
4645     {   "http://google.com/",0,S_OK,FALSE,
4646         {
4647             {TRUE,"Frag","#Frag",Uri_PROPERTY_FRAGMENT,S_OK,FALSE}
4648         },
4649         {FALSE},
4650         0,S_OK,FALSE,
4651         0,S_OK,FALSE,
4652         0,0,0,S_OK,FALSE,
4653         {
4654             {"http://google.com/#Frag",S_OK},
4655             {"google.com",S_OK},
4656             {"http://google.com/#Frag",S_OK},
4657             {"google.com",S_OK},
4658             {"",S_FALSE},
4659             {"#Frag",S_OK},
4660             {"google.com",S_OK},
4661             {"",S_FALSE},
4662             {"/",S_OK},
4663             {"/",S_OK},
4664             {"",S_FALSE},
4665             {"http://google.com/#Frag",S_OK},
4666             {"http",S_OK},
4667             {"",S_FALSE},
4668             {"",S_FALSE}
4669         },
4670         {
4671             {Uri_HOST_DNS,S_OK},
4672             {80,S_OK},
4673             {URL_SCHEME_HTTP,S_OK},
4674             {URLZONE_INVALID,E_NOTIMPL}
4675         }
4676     },
4677     {   "http://google.com/",0,S_OK,FALSE,
4678         {
4679             {TRUE,"","#",Uri_PROPERTY_FRAGMENT,S_OK,FALSE},
4680         },
4681         {FALSE},
4682         0,S_OK,FALSE,
4683         0,S_OK,FALSE,
4684         0,0,0,S_OK,FALSE,
4685         {
4686             {"http://google.com/#",S_OK},
4687             {"google.com",S_OK},
4688             {"http://google.com/#",S_OK},
4689             {"google.com",S_OK},
4690             {"",S_FALSE},
4691             {"#",S_OK},
4692             {"google.com",S_OK},
4693             {"",S_FALSE},
4694             {"/",S_OK},
4695             {"/",S_OK},
4696             {"",S_FALSE},
4697             {"http://google.com/#",S_OK},
4698             {"http",S_OK},
4699             {"",S_FALSE},
4700             {"",S_FALSE}
4701         },
4702         {
4703             {Uri_HOST_DNS,S_OK},
4704             {80,S_OK},
4705             {URL_SCHEME_HTTP,S_OK},
4706             {URLZONE_INVALID,E_NOTIMPL}
4707         }
4708     },
4709     {   "http://google.com/",0,S_OK,FALSE,
4710         {
4711             {TRUE,":password",NULL,Uri_PROPERTY_PASSWORD,S_OK,FALSE}
4712         },
4713         {FALSE},
4714         0,S_OK,FALSE,
4715         0,S_OK,FALSE,
4716         0,0,0,S_OK,FALSE,
4717         {
4718             {"http://::password@google.com/",S_OK},
4719             {"::password@google.com",S_OK},
4720             {"http://google.com/",S_OK},
4721             {"google.com",S_OK},
4722             {"",S_FALSE},
4723             {"",S_FALSE},
4724             {"google.com",S_OK},
4725             {":password",S_OK},
4726             {"/",S_OK},
4727             {"/",S_OK},
4728             {"",S_FALSE},
4729             {"http://::password@google.com/",S_OK},
4730             {"http",S_OK},
4731             {"::password",S_OK},
4732             {"",S_FALSE}
4733         },
4734         {
4735             {Uri_HOST_DNS,S_OK},
4736             {80,S_OK},
4737             {URL_SCHEME_HTTP,S_OK},
4738             {URLZONE_INVALID,E_NOTIMPL}
4739         }
4740     },
4741     {   "test/test",Uri_CREATE_ALLOW_RELATIVE,S_OK,FALSE,
4742         {
4743             {TRUE,"password",NULL,Uri_PROPERTY_PASSWORD,S_OK,FALSE}
4744         },
4745         {FALSE},
4746         Uri_CREATE_ALLOW_RELATIVE,S_OK,FALSE,
4747         0,S_OK,FALSE,
4748         Uri_CREATE_ALLOW_RELATIVE,0,0,S_OK,FALSE,
4749         {
4750             {":password@test/test",S_OK},
4751             {":password@",S_OK},
4752             {":password@test/test",S_OK},
4753             {"",S_FALSE},
4754             {"",S_FALSE},
4755             {"",S_FALSE},
4756             {"",S_FALSE},
4757             {"password",S_OK},
4758             {"test/test",S_OK},
4759             {"test/test",S_OK},
4760             {"",S_FALSE},
4761             {":password@test/test",S_OK},
4762             {"",S_FALSE},
4763             {":password",S_OK},
4764             {"",S_FALSE}
4765         },
4766         {
4767             {Uri_HOST_UNKNOWN,S_OK},
4768             {0,S_FALSE},
4769             {URL_SCHEME_UNKNOWN,S_OK},
4770             {URLZONE_INVALID,E_NOTIMPL}
4771         }
4772     },
4773     {   "http://google.com/",0,S_OK,FALSE,
4774         {
4775             {TRUE,"test/test",NULL,Uri_PROPERTY_PATH,S_OK,FALSE},
4776         },
4777         {FALSE},
4778         0,S_OK,FALSE,
4779         0,S_OK,FALSE,
4780         0,0,0,S_OK,FALSE,
4781         {
4782             {"http://google.com/test/test",S_OK},
4783             {"google.com",S_OK},
4784             {"http://google.com/test/test",S_OK},
4785             {"google.com",S_OK},
4786             {"",S_FALSE},
4787             {"",S_FALSE},
4788             {"google.com",S_OK},
4789             {"",S_FALSE},
4790             {"/test/test",S_OK},
4791             {"/test/test",S_OK},
4792             {"",S_FALSE},
4793             {"http://google.com/test/test",S_OK},
4794             {"http",S_OK},
4795             {"",S_FALSE},
4796             {"",S_FALSE}
4797         },
4798         {
4799             {Uri_HOST_DNS,S_OK},
4800             {80,S_OK},
4801             {URL_SCHEME_HTTP,S_OK},
4802             {URLZONE_INVALID,E_NOTIMPL}
4803         }
4804     },
4805     {   "zip:testing/test",0,S_OK,FALSE,
4806         {
4807             {TRUE,"test",NULL,Uri_PROPERTY_PATH,S_OK,FALSE},
4808         },
4809         {FALSE},
4810         0,S_OK,FALSE,
4811         0,S_OK,FALSE,
4812         0,0,0,S_OK,FALSE,
4813         {
4814             {"zip:test",S_OK},
4815             {"",S_FALSE},
4816             {"zip:test",S_OK},
4817             {"",S_FALSE},
4818             {"",S_FALSE},
4819             {"",S_FALSE},
4820             {"",S_FALSE},
4821             {"",S_FALSE},
4822             {"test",S_OK},
4823             {"test",S_OK},
4824             {"",S_FALSE},
4825             {"zip:test",S_OK},
4826             {"zip",S_OK},
4827             {"",S_FALSE},
4828             {"",S_FALSE}
4829         },
4830         {
4831             {Uri_HOST_UNKNOWN,S_OK},
4832             {0,S_FALSE},
4833             {URL_SCHEME_UNKNOWN,S_OK},
4834             {URLZONE_INVALID,E_NOTIMPL}
4835         }
4836     },
4837     {   "http://google.com/",0,S_OK,FALSE,
4838         {
4839             {FALSE},
4840         },
4841         /* 555 will be returned from GetPort even though FALSE was passed as the hasPort parameter. */
4842         {TRUE,FALSE,555,S_OK,FALSE},
4843         0,S_OK,FALSE,
4844         0,S_OK,FALSE,
4845         0,0,0,S_OK,FALSE,
4846         {
4847             {"http://google.com/",S_OK},
4848             {"google.com",S_OK},
4849             {"http://google.com/",S_OK},
4850             {"google.com",S_OK},
4851             {"",S_FALSE},
4852             {"",S_FALSE},
4853             {"google.com",S_OK},
4854             {"",S_FALSE},
4855             {"/",S_OK},
4856             {"/",S_OK},
4857             {"",S_FALSE},
4858             {"http://google.com/",S_OK},
4859             {"http",S_OK},
4860             {"",S_FALSE},
4861             {"",S_FALSE}
4862         },
4863         {
4864             {Uri_HOST_DNS,S_OK},
4865             /* Still returns 80, even though earlier the port was disabled. */
4866             {80,S_OK},
4867             {URL_SCHEME_HTTP,S_OK},
4868             {URLZONE_INVALID,E_NOTIMPL}
4869         }
4870     },
4871     {   "http://google.com/",0,S_OK,FALSE,
4872         {
4873             {FALSE},
4874         },
4875         /* Instead of getting "TRUE" back as the "hasPort" parameter in GetPort,
4876          * you'll get 122345 instead.
4877          */
4878         {TRUE,122345,222,S_OK,FALSE},
4879         0,S_OK,FALSE,
4880         0,S_OK,FALSE,
4881         0,0,0,S_OK,FALSE,
4882         {
4883             {"http://google.com:222/",S_OK},
4884             {"google.com:222",S_OK},
4885             {"http://google.com:222/",S_OK},
4886             {"google.com",S_OK},
4887             {"",S_FALSE},
4888             {"",S_FALSE},
4889             {"google.com",S_OK},
4890             {"",S_FALSE},
4891             {"/",S_OK},
4892             {"/",S_OK},
4893             {"",S_FALSE},
4894             {"http://google.com:222/",S_OK},
4895             {"http",S_OK},
4896             {"",S_FALSE},
4897             {"",S_FALSE}
4898         },
4899         {
4900             {Uri_HOST_DNS,S_OK},
4901             {222,S_OK},
4902             {URL_SCHEME_HTTP,S_OK},
4903             {URLZONE_INVALID,E_NOTIMPL}
4904         }
4905     },
4906     /* IUri's created with the IUriBuilder can have ports that exceed USHORT_MAX. */
4907     {   "http://google.com/",0,S_OK,FALSE,
4908         {
4909             {FALSE},
4910         },
4911         {TRUE,TRUE,999999,S_OK,FALSE},
4912         0,S_OK,FALSE,
4913         0,S_OK,FALSE,
4914         0,0,0,S_OK,FALSE,
4915         {
4916             {"http://google.com:999999/",S_OK},
4917             {"google.com:999999",S_OK},
4918             {"http://google.com:999999/",S_OK},
4919             {"google.com",S_OK},
4920             {"",S_FALSE},
4921             {"",S_FALSE},
4922             {"google.com",S_OK},
4923             {"",S_FALSE},
4924             {"/",S_OK},
4925             {"/",S_OK},
4926             {"",S_FALSE},
4927             {"http://google.com:999999/",S_OK},
4928             {"http",S_OK},
4929             {"",S_FALSE},
4930             {"",S_FALSE}
4931         },
4932         {
4933             {Uri_HOST_DNS,S_OK},
4934             {999999,S_OK},
4935             {URL_SCHEME_HTTP,S_OK},
4936             {URLZONE_INVALID,E_NOTIMPL}
4937         }
4938     },
4939     {   "http://google.com/",0,S_OK,FALSE,
4940         {
4941             {TRUE,"test","?test",Uri_PROPERTY_QUERY,S_OK,FALSE},
4942         },
4943
4944         {FALSE},
4945         0,S_OK,FALSE,
4946         0,S_OK,FALSE,
4947         0,0,0,S_OK,FALSE,
4948         {
4949             {"http://google.com/?test",S_OK},
4950             {"google.com",S_OK},
4951             {"http://google.com/?test",S_OK},
4952             {"google.com",S_OK},
4953             {"",S_FALSE},
4954             {"",S_FALSE},
4955             {"google.com",S_OK},
4956             {"",S_FALSE},
4957             {"/",S_OK},
4958             {"/?test",S_OK},
4959             {"?test",S_OK},
4960             {"http://google.com/?test",S_OK},
4961             {"http",S_OK},
4962             {"",S_FALSE},
4963             {"",S_FALSE}
4964         },
4965         {
4966             {Uri_HOST_DNS,S_OK},
4967             {80,S_OK},
4968             {URL_SCHEME_HTTP,S_OK},
4969             {URLZONE_INVALID,E_NOTIMPL}
4970         }
4971     },
4972     {   "http://:password@google.com/",0,S_OK,FALSE,
4973         {
4974             {FALSE},
4975         },
4976         {FALSE},
4977         0,S_OK,FALSE,
4978         0,S_OK,FALSE,
4979         0,0,0,S_OK,FALSE,
4980         {
4981             {"http://:password@google.com/",S_OK},
4982             {":password@google.com",S_OK},
4983             {"http://google.com/",S_OK},
4984             {"google.com",S_OK},
4985             {"",S_FALSE},
4986             {"",S_FALSE},
4987             {"google.com",S_OK},
4988             {"password",S_OK},
4989             {"/",S_OK},
4990             {"/",S_OK},
4991             {"",S_FALSE},
4992             {"http://:password@google.com/",S_OK},
4993             {"http",S_OK},
4994             {":password",S_OK},
4995             {"",S_FALSE}
4996         },
4997         {
4998             {Uri_HOST_DNS,S_OK},
4999             {80,S_OK},
5000             {URL_SCHEME_HTTP,S_OK},
5001             {URLZONE_INVALID,E_NOTIMPL}
5002         }
5003     },
5004     /* IUriBuilder doesn't need a base IUri to build a IUri. */
5005     {   NULL,0,S_OK,FALSE,
5006         {
5007             {TRUE,"http",NULL,Uri_PROPERTY_SCHEME_NAME,S_OK,FALSE},
5008             {TRUE,"google.com",NULL,Uri_PROPERTY_HOST,S_OK,FALSE}
5009         },
5010         {FALSE},
5011         0,S_OK,FALSE,
5012         0,S_OK,FALSE,
5013         0,0,0,S_OK,FALSE,
5014         {
5015             {"http://google.com/",S_OK},
5016             {"google.com",S_OK},
5017             {"http://google.com/",S_OK},
5018             {"google.com",S_OK},
5019             {"",S_FALSE},
5020             {"",S_FALSE},
5021             {"google.com",S_OK},
5022             {"",S_FALSE},
5023             {"/",S_OK},
5024             {"/",S_OK},
5025             {"",S_FALSE},
5026             {"http://google.com/",S_OK},
5027             {"http",S_OK},
5028             {"",S_FALSE},
5029             {"",S_FALSE}
5030         },
5031         {
5032             {Uri_HOST_DNS,S_OK},
5033             {80,S_OK},
5034             {URL_SCHEME_HTTP,S_OK},
5035             {URLZONE_INVALID,E_NOTIMPL}
5036         }
5037     },
5038     /* Can't set the scheme name to NULL. */
5039     {   "zip://google.com/",0,S_OK,FALSE,
5040         {
5041             {TRUE,NULL,"zip",Uri_PROPERTY_SCHEME_NAME,E_INVALIDARG,FALSE}
5042         },
5043         {FALSE},
5044         0,S_OK,FALSE,
5045         0,S_OK,FALSE,
5046         0,0,0,S_OK,FALSE,
5047         {
5048             {"zip://google.com/",S_OK},
5049             {"google.com",S_OK},
5050             {"zip://google.com/",S_OK},
5051             {"google.com",S_OK},
5052             {"",S_FALSE},
5053             {"",S_FALSE},
5054             {"google.com",S_OK},
5055             {"",S_FALSE},
5056             {"/",S_OK},
5057             {"/",S_OK},
5058             {"",S_FALSE},
5059             {"zip://google.com/",S_OK},
5060             {"zip",S_OK},
5061             {"",S_FALSE},
5062             {"",S_FALSE}
5063         },
5064         {
5065             {Uri_HOST_DNS,S_OK},
5066             {0,S_FALSE},
5067             {URL_SCHEME_UNKNOWN,S_OK},
5068             {URLZONE_INVALID,E_NOTIMPL}
5069         }
5070     },
5071     /* Can't set the scheme name to an empty string. */
5072     {   "zip://google.com/",0,S_OK,FALSE,
5073         {
5074             {TRUE,"","zip",Uri_PROPERTY_SCHEME_NAME,E_INVALIDARG,FALSE}
5075         },
5076         {FALSE},
5077         0,S_OK,FALSE,
5078         0,S_OK,FALSE,
5079         0,0,0,S_OK,FALSE,
5080         {
5081             {"zip://google.com/",S_OK},
5082             {"google.com",S_OK},
5083             {"zip://google.com/",S_OK},
5084             {"google.com",S_OK},
5085             {"",S_FALSE},
5086             {"",S_FALSE},
5087             {"google.com",S_OK},
5088             {"",S_FALSE},
5089             {"/",S_OK},
5090             {"/",S_OK},
5091             {"",S_FALSE},
5092             {"zip://google.com/",S_OK},
5093             {"zip",S_OK},
5094             {"",S_FALSE},
5095             {"",S_FALSE}
5096         },
5097         {
5098             {Uri_HOST_DNS,S_OK},
5099             {0,S_FALSE},
5100             {URL_SCHEME_UNKNOWN,S_OK},
5101             {URLZONE_INVALID,E_NOTIMPL}
5102         }
5103     },
5104     /* -1 to CreateUri makes it use the same flags as the base IUri was created with.
5105      * CreateUriSimple always uses the flags the base IUri was created with (if any).
5106      */
5107     {   "http://google.com/../../",Uri_CREATE_NO_CANONICALIZE,S_OK,FALSE,
5108         {{FALSE}},
5109         {FALSE},
5110         -1,S_OK,FALSE,
5111         0,S_OK,FALSE,
5112         0,UriBuilder_USE_ORIGINAL_FLAGS,0,S_OK,FALSE,
5113         {
5114             {"http://google.com/../../",S_OK},
5115             {"google.com",S_OK},
5116             {"http://google.com/../../",S_OK},
5117             {"google.com",S_OK},
5118             {"",S_FALSE},
5119             {"",S_FALSE},
5120             {"google.com",S_OK},
5121             {"",S_FALSE},
5122             {"/../../",S_OK},
5123             {"/../../",S_OK},
5124             {"",S_FALSE},
5125             {"http://google.com/../../",S_OK},
5126             {"http",S_OK},
5127             {"",S_FALSE},
5128             {"",S_FALSE}
5129         },
5130         {
5131             {Uri_HOST_DNS,S_OK},
5132             {80,S_OK},
5133             {URL_SCHEME_HTTP,S_OK},
5134             {URLZONE_INVALID,E_NOTIMPL}
5135         }
5136     },
5137     {   "http://google.com/",0,S_OK,FALSE,
5138         {
5139             {TRUE,"#Fr<|>g",NULL,Uri_PROPERTY_FRAGMENT,S_OK,FALSE}
5140         },
5141         {FALSE},
5142         -1,S_OK,FALSE,
5143         0,S_OK,FALSE,
5144         Uri_CREATE_NO_DECODE_EXTRA_INFO,UriBuilder_USE_ORIGINAL_FLAGS,0,S_OK,FALSE,
5145         {
5146             {"http://google.com/#Fr%3C%7C%3Eg",S_OK},
5147             {"google.com",S_OK},
5148             {"http://google.com/#Fr%3C%7C%3Eg",S_OK},
5149             {"google.com",S_OK},
5150             {"",S_FALSE},
5151             {"#Fr%3C%7C%3Eg",S_OK},
5152             {"google.com",S_OK},
5153             {"",S_FALSE},
5154             {"/",S_OK},
5155             {"/",S_OK},
5156             {"",S_FALSE},
5157             {"http://google.com/#Fr<|>g",S_OK},
5158             {"http",S_OK},
5159             {"",S_FALSE},
5160             {"",S_FALSE}
5161         },
5162         {
5163             {Uri_HOST_DNS,S_OK},
5164             {80,S_OK},
5165             {URL_SCHEME_HTTP,S_OK},
5166             {URLZONE_INVALID,E_NOTIMPL}
5167         }
5168     },
5169     {   "http://google.com/",0,S_OK,FALSE,
5170         {
5171             {TRUE,"#Fr<|>g",NULL,Uri_PROPERTY_FRAGMENT,S_OK,FALSE}
5172         },
5173         {FALSE},
5174         Uri_CREATE_CANONICALIZE|Uri_CREATE_NO_CANONICALIZE,E_INVALIDARG,FALSE,
5175         0,S_OK,FALSE,
5176         Uri_CREATE_CANONICALIZE|Uri_CREATE_NO_CANONICALIZE,UriBuilder_USE_ORIGINAL_FLAGS,0,S_OK,FALSE,
5177         {
5178             {"http://google.com/#Fr%3C%7C%3Eg",S_OK},
5179             {"google.com",S_OK},
5180             {"http://google.com/#Fr%3C%7C%3Eg",S_OK},
5181             {"google.com",S_OK},
5182             {"",S_FALSE},
5183             {"#Fr%3C%7C%3Eg",S_OK},
5184             {"google.com",S_OK},
5185             {"",S_FALSE},
5186             {"/",S_OK},
5187             {"/",S_OK},
5188             {"",S_FALSE},
5189             {"http://google.com/#Fr<|>g",S_OK},
5190             {"http",S_OK},
5191             {"",S_FALSE},
5192             {"",S_FALSE}
5193         },
5194         {
5195             {Uri_HOST_DNS,S_OK},
5196             {80,S_OK},
5197             {URL_SCHEME_HTTP,S_OK},
5198             {URLZONE_INVALID,E_NOTIMPL}
5199         }
5200     },
5201     {   NULL,0,S_OK,FALSE,
5202         {
5203             {TRUE,"/test/test/",NULL,Uri_PROPERTY_PATH,S_OK,FALSE},
5204             {TRUE,"#Fr<|>g",NULL,Uri_PROPERTY_FRAGMENT,S_OK,FALSE}
5205         },
5206         {FALSE},
5207         0,INET_E_INVALID_URL,FALSE,
5208         0,INET_E_INVALID_URL,FALSE,
5209         0,0,0,INET_E_INVALID_URL,FALSE
5210     },
5211     {   "http://google.com/",0,S_OK,FALSE,
5212         {
5213             {TRUE,"ht%xxtp",NULL,Uri_PROPERTY_SCHEME_NAME,S_OK,FALSE}
5214         },
5215         {FALSE},
5216         0,INET_E_INVALID_URL,FALSE,
5217         0,INET_E_INVALID_URL,FALSE,
5218         0,0,0,INET_E_INVALID_URL,FALSE
5219     },
5220     /* File scheme's can't have a username set. */
5221     {   "file://google.com/",0,S_OK,FALSE,
5222         {
5223             {TRUE,"username",NULL,Uri_PROPERTY_USER_NAME,S_OK,FALSE}
5224         },
5225         {FALSE},
5226         0,INET_E_INVALID_URL,FALSE,
5227         0,INET_E_INVALID_URL,FALSE,
5228         0,0,0,INET_E_INVALID_URL,FALSE
5229     },
5230     /* File schemes can't have a password set. */
5231     {   "file://google.com/",0,S_OK,FALSE,
5232         {
5233             {TRUE,"password",NULL,Uri_PROPERTY_PASSWORD,S_OK,FALSE}
5234         },
5235         {FALSE},
5236         0,INET_E_INVALID_URL,FALSE,
5237         0,INET_E_INVALID_URL,FALSE,
5238         0,0,0,INET_E_INVALID_URL,FALSE
5239     },
5240     /* UserName can't contain any character that is a delimeter for another
5241      * component that appears after it in a normal URI.
5242      */
5243     {   "http://google.com/",0,S_OK,FALSE,
5244         {
5245             {TRUE,"user:pass",NULL,Uri_PROPERTY_USER_NAME,S_OK,FALSE}
5246         },
5247         {FALSE},
5248         0,INET_E_INVALID_URL,FALSE,
5249         0,INET_E_INVALID_URL,FALSE,
5250         0,0,0,INET_E_INVALID_URL,FALSE
5251     },
5252     {   "http://google.com/",0,S_OK,FALSE,
5253         {
5254             {TRUE,"user@google.com",NULL,Uri_PROPERTY_USER_NAME,S_OK,FALSE}
5255         },
5256         {FALSE},
5257         0,INET_E_INVALID_URL,FALSE,
5258         0,INET_E_INVALID_URL,FALSE,
5259         0,0,0,INET_E_INVALID_URL,FALSE
5260     },
5261     {   "http://google.com/",0,S_OK,FALSE,
5262         {
5263             {TRUE,"user/path",NULL,Uri_PROPERTY_USER_NAME,S_OK,FALSE}
5264         },
5265         {FALSE},
5266         0,INET_E_INVALID_URL,FALSE,
5267         0,INET_E_INVALID_URL,FALSE,
5268         0,0,0,INET_E_INVALID_URL,FALSE
5269     },
5270     {   "http://google.com/",0,S_OK,FALSE,
5271         {
5272             {TRUE,"user?Query",NULL,Uri_PROPERTY_USER_NAME,S_OK,FALSE}
5273         },
5274         {FALSE},
5275         0,INET_E_INVALID_URL,FALSE,
5276         0,INET_E_INVALID_URL,FALSE,
5277         0,0,0,INET_E_INVALID_URL,FALSE
5278     },
5279     {   "http://google.com/",0,S_OK,FALSE,
5280         {
5281             {TRUE,"user#Frag",NULL,Uri_PROPERTY_USER_NAME,S_OK,FALSE}
5282         },
5283         {FALSE},
5284         0,INET_E_INVALID_URL,FALSE,
5285         0,INET_E_INVALID_URL,FALSE,
5286         0,0,0,INET_E_INVALID_URL,FALSE
5287     },
5288     {   "http://google.com/",0,S_OK,FALSE,
5289         {
5290             {TRUE,"pass@google.com",NULL,Uri_PROPERTY_PASSWORD,S_OK,FALSE}
5291         },
5292         {FALSE},
5293         0,INET_E_INVALID_URL,FALSE,
5294         0,INET_E_INVALID_URL,FALSE,
5295         0,0,0,INET_E_INVALID_URL,FALSE
5296     },
5297     {   "http://google.com/",0,S_OK,FALSE,
5298         {
5299             {TRUE,"pass/path",NULL,Uri_PROPERTY_PASSWORD,S_OK,FALSE}
5300         },
5301         {FALSE},
5302         0,INET_E_INVALID_URL,FALSE,
5303         0,INET_E_INVALID_URL,FALSE,
5304         0,0,0,INET_E_INVALID_URL,FALSE
5305     },
5306     {   "http://google.com/",0,S_OK,FALSE,
5307         {
5308             {TRUE,"pass?query",NULL,Uri_PROPERTY_PASSWORD,S_OK,FALSE}
5309         },
5310         {FALSE},
5311         0,INET_E_INVALID_URL,FALSE,
5312         0,INET_E_INVALID_URL,FALSE,
5313        0,0,0,INET_E_INVALID_URL,FALSE
5314     },
5315     {   "http://google.com/",0,S_OK,FALSE,
5316         {
5317             {TRUE,"pass#frag",NULL,Uri_PROPERTY_PASSWORD,S_OK,FALSE}
5318         },
5319         {FALSE},
5320         0,INET_E_INVALID_URL,FALSE,
5321         0,INET_E_INVALID_URL,FALSE,
5322         0,0,0,INET_E_INVALID_URL,FALSE
5323     },
5324     {   "http://google.com/",0,S_OK,FALSE,
5325         {
5326             {TRUE,"winehq.org/test",NULL,Uri_PROPERTY_HOST,S_OK,FALSE}
5327         },
5328         {FALSE},
5329         0,INET_E_INVALID_URL,FALSE,
5330         0,INET_E_INVALID_URL,FALSE,
5331         0,0,0,INET_E_INVALID_URL,FALSE
5332     },
5333     {   "http://google.com/",0,S_OK,FALSE,
5334         {
5335             {TRUE,"winehq.org?test",NULL,Uri_PROPERTY_HOST,S_OK,FALSE}
5336         },
5337         {FALSE},
5338         0,INET_E_INVALID_URL,FALSE,
5339         0,INET_E_INVALID_URL,FALSE,
5340         0,0,0,INET_E_INVALID_URL,FALSE
5341     },
5342     {   "http://google.com/",0,S_OK,FALSE,
5343         {
5344             {TRUE,"winehq.org#test",NULL,Uri_PROPERTY_HOST,S_OK,FALSE}
5345         },
5346         {FALSE},
5347         0,INET_E_INVALID_URL,FALSE,
5348         0,INET_E_INVALID_URL,FALSE,
5349         0,0,0,INET_E_INVALID_URL,FALSE
5350     },
5351     /* Hostname is allowed to contain a ':' (even for known scheme types). */
5352     {   "http://google.com/",0,S_OK,FALSE,
5353         {
5354             {TRUE,"winehq.org:test",NULL,Uri_PROPERTY_HOST,S_OK,FALSE},
5355         },
5356         {FALSE},
5357         0,S_OK,FALSE,
5358         0,S_OK,FALSE,
5359         0,0,0,S_OK,FALSE,
5360         {
5361             {"http://winehq.org:test/",S_OK},
5362             {"winehq.org:test",S_OK},
5363             {"http://winehq.org:test/",S_OK},
5364             {"winehq.org:test",S_OK},
5365             {"",S_FALSE},
5366             {"",S_FALSE},
5367             {"winehq.org:test",S_OK},
5368             {"",S_FALSE},
5369             {"/",S_OK},
5370             {"/",S_OK},
5371             {"",S_FALSE},
5372             {"http://winehq.org:test/",S_OK},
5373             {"http",S_OK},
5374             {"",S_FALSE},
5375             {"",S_FALSE}
5376         },
5377         {
5378             {Uri_HOST_DNS,S_OK},
5379             {80,S_OK},
5380             {URL_SCHEME_HTTP,S_OK},
5381             {URLZONE_INVALID,E_NOTIMPL}
5382         }
5383     },
5384     /* Can't set the host name to NULL. */
5385     {   "http://google.com/",0,S_OK,FALSE,
5386         {
5387             {TRUE,NULL,"google.com",Uri_PROPERTY_HOST,E_INVALIDARG,FALSE}
5388         },
5389         {FALSE},
5390         0,S_OK,FALSE,
5391         0,S_OK,FALSE,
5392         0,0,0,S_OK,FALSE,
5393         {
5394             {"http://google.com/",S_OK},
5395             {"google.com",S_OK},
5396             {"http://google.com/",S_OK},
5397             {"google.com",S_OK},
5398             {"",S_FALSE},
5399             {"",S_FALSE},
5400             {"google.com",S_OK},
5401             {"",S_FALSE},
5402             {"/",S_OK},
5403             {"/",S_OK},
5404             {"",S_FALSE},
5405             {"http://google.com/",S_OK},
5406             {"http",S_OK},
5407             {"",S_FALSE},
5408             {"",S_FALSE}
5409         },
5410         {
5411             {Uri_HOST_DNS,S_OK},
5412             {80,S_OK},
5413             {URL_SCHEME_HTTP,S_OK},
5414             {URLZONE_INVALID,E_NOTIMPL}
5415         }
5416     },
5417     /* Can set the host name to an empty string. */
5418     {   "http://google.com/",0,S_OK,FALSE,
5419         {
5420             {TRUE,"",NULL,Uri_PROPERTY_HOST,S_OK,FALSE}
5421         },
5422         {FALSE},
5423         0,S_OK,FALSE,
5424         0,S_OK,FALSE,
5425         0,0,0,S_OK,FALSE,
5426         {
5427             {"http:///",S_OK},
5428             {"",S_OK},
5429             {"http:///",S_OK},
5430             {"",S_FALSE},
5431             {"",S_FALSE},
5432             {"",S_FALSE},
5433             {"",S_OK},
5434             {"",S_FALSE},
5435             {"/",S_OK},
5436             {"/",S_OK},
5437             {"",S_FALSE},
5438             {"http:///",S_OK},
5439             {"http",S_OK},
5440             {"",S_FALSE},
5441             {"",S_FALSE}
5442         },
5443         {
5444             {Uri_HOST_UNKNOWN,S_OK},
5445             {80,S_OK},
5446             {URL_SCHEME_HTTP,S_OK},
5447             {URLZONE_INVALID,E_NOTIMPL}
5448         }
5449     },
5450     {   "http://google.com/",0,S_OK,FALSE,
5451         {
5452             {TRUE,"/path?query",NULL,Uri_PROPERTY_PATH,S_OK,FALSE}
5453         },
5454         {FALSE},
5455         0,INET_E_INVALID_URL,FALSE,
5456         0,INET_E_INVALID_URL,FALSE,
5457         0,0,0,INET_E_INVALID_URL,FALSE
5458     },
5459     {   "http://google.com/",0,S_OK,FALSE,
5460         {
5461             {TRUE,"/path#test",NULL,Uri_PROPERTY_PATH,S_OK,FALSE}
5462         },
5463         {FALSE},
5464         0,INET_E_INVALID_URL,FALSE,
5465         0,INET_E_INVALID_URL,FALSE,
5466         0,0,0,INET_E_INVALID_URL,FALSE
5467     },
5468     {   "http://google.com/",0,S_OK,FALSE,
5469         {
5470             {TRUE,"?path#test",NULL,Uri_PROPERTY_QUERY,S_OK,FALSE}
5471         },
5472         {FALSE},
5473         0,INET_E_INVALID_URL,FALSE,
5474         0,INET_E_INVALID_URL,FALSE,
5475         0,0,0,INET_E_INVALID_URL,FALSE
5476     }
5477 };
5478
5479 typedef struct _uri_builder_remove_test {
5480     const char  *uri;
5481     DWORD       create_flags;
5482     HRESULT     create_builder_expected;
5483     BOOL        create_builder_todo;
5484
5485     DWORD       remove_properties;
5486     HRESULT     remove_expected;
5487     BOOL        remove_todo;
5488
5489     const char  *expected_uri;
5490     DWORD       expected_flags;
5491     HRESULT     expected_hres;
5492     BOOL        expected_todo;
5493 } uri_builder_remove_test;
5494
5495 static const uri_builder_remove_test uri_builder_remove_tests[] = {
5496     {   "http://google.com/test?test=y#Frag",0,S_OK,FALSE,
5497         Uri_HAS_FRAGMENT|Uri_HAS_PATH|Uri_HAS_QUERY,S_OK,FALSE,
5498         "http://google.com/",0,S_OK,FALSE
5499     },
5500     {   "http://user:pass@winehq.org/",0,S_OK,FALSE,
5501         Uri_HAS_USER_NAME|Uri_HAS_PASSWORD,S_OK,FALSE,
5502         "http://winehq.org/",0,S_OK,FALSE
5503     },
5504     {   "zip://google.com?Test=x",0,S_OK,FALSE,
5505         Uri_HAS_HOST,S_OK,FALSE,
5506         "zip:/?Test=x",0,S_OK,FALSE
5507     },
5508     /* Doesn't remove the whole userinfo component. */
5509     {   "http://username:pass@google.com/",0,S_OK,FALSE,
5510         Uri_HAS_USER_INFO,S_OK,FALSE,
5511         "http://username:pass@google.com/",0,S_OK,FALSE
5512     },
5513     /* Doesn't remove the domain. */
5514     {   "http://google.com/",0,S_OK,FALSE,
5515         Uri_HAS_DOMAIN,S_OK,FALSE,
5516         "http://google.com/",0,S_OK,FALSE
5517     },
5518     {   "http://google.com:120/",0,S_OK,FALSE,
5519         Uri_HAS_AUTHORITY,S_OK,FALSE,
5520         "http://google.com:120/",0,S_OK,FALSE
5521     },
5522     {   "http://google.com/test.com/",0,S_OK,FALSE,
5523         Uri_HAS_EXTENSION,S_OK,FALSE,
5524         "http://google.com/test.com/",0,S_OK,FALSE
5525     },
5526     {   "http://google.com/?test=x",0,S_OK,FALSE,
5527         Uri_HAS_PATH_AND_QUERY,S_OK,FALSE,
5528         "http://google.com/?test=x",0,S_OK,FALSE
5529     },
5530     /* Can't remove the scheme name. */
5531     {   "http://google.com/?test=x",0,S_OK,FALSE,
5532         Uri_HAS_SCHEME_NAME|Uri_HAS_QUERY,E_INVALIDARG,FALSE,
5533         "http://google.com/?test=x",0,S_OK,FALSE
5534     }
5535 };
5536
5537 static inline LPWSTR a2w(LPCSTR str) {
5538     LPWSTR ret = NULL;
5539
5540     if(str) {
5541         DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
5542         ret = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
5543         MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len);
5544     }
5545
5546     return ret;
5547 }
5548
5549 static inline BOOL heap_free(void* mem) {
5550     return HeapFree(GetProcessHeap(), 0, mem);
5551 }
5552
5553 static inline DWORD strcmp_aw(LPCSTR strA, LPCWSTR strB) {
5554     LPWSTR strAW = a2w(strA);
5555     DWORD ret = lstrcmpW(strAW, strB);
5556     heap_free(strAW);
5557     return ret;
5558 }
5559
5560 static inline ULONG get_refcnt(IUri *uri) {
5561     IUri_AddRef(uri);
5562     return IUri_Release(uri);
5563 }
5564
5565 static void change_property(IUriBuilder *builder, const uri_builder_property *prop,
5566                             DWORD test_index) {
5567     HRESULT hr;
5568     LPWSTR valueW;
5569
5570     valueW = a2w(prop->value);
5571     switch(prop->property) {
5572     case Uri_PROPERTY_FRAGMENT:
5573         hr = IUriBuilder_SetFragment(builder, valueW);
5574         if(prop->todo) {
5575             todo_wine {
5576                 ok(hr == prop->expected,
5577                     "Error: IUriBuilder_SetFragment returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
5578                     hr, prop->expected, test_index);
5579             }
5580         } else {
5581             ok(hr == prop->expected,
5582                 "Error: IUriBuilder_SetFragment returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
5583                 hr, prop->expected, test_index);
5584         }
5585         break;
5586     case Uri_PROPERTY_HOST:
5587         hr = IUriBuilder_SetHost(builder, valueW);
5588         if(prop->todo) {
5589             todo_wine {
5590                 ok(hr == prop->expected,
5591                     "Error: IUriBuilder_SetHost returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
5592                     hr, prop->expected, test_index);
5593             }
5594         } else {
5595             ok(hr == prop->expected,
5596                 "Error: IUriBuilder_SetHost returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
5597                 hr, prop->expected, test_index);
5598         }
5599         break;
5600     case Uri_PROPERTY_PASSWORD:
5601         hr = IUriBuilder_SetPassword(builder, valueW);
5602         if(prop->todo) {
5603             todo_wine {
5604                 ok(hr == prop->expected,
5605                     "Error: IUriBuilder_SetPassword returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
5606                     hr, prop->expected, test_index);
5607             }
5608         } else {
5609             ok(hr == prop->expected,
5610                 "Error: IUriBuilder_SetPassword returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
5611                 hr, prop->expected, test_index);
5612         }
5613         break;
5614     case Uri_PROPERTY_PATH:
5615         hr = IUriBuilder_SetPath(builder, valueW);
5616         if(prop->todo) {
5617             todo_wine {
5618                 ok(hr == prop->expected,
5619                     "Error: IUriBuilder_SetPath returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
5620                     hr, prop->expected, test_index);
5621             }
5622         } else {
5623             ok(hr == prop->expected,
5624                 "Error: IUriBuilder_SetPath returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
5625                 hr, prop->expected, test_index);
5626         }
5627         break;
5628     case Uri_PROPERTY_QUERY:
5629         hr = IUriBuilder_SetQuery(builder, valueW);
5630         if(prop->todo) {
5631             todo_wine {
5632                 ok(hr == prop->expected,
5633                     "Error: IUriBuilder_SetQuery returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
5634                     hr, prop->expected, test_index);
5635             }
5636         } else {
5637             ok(hr == prop->expected,
5638                 "Error: IUriBuilder_SetQuery returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
5639                 hr, prop->expected, test_index);
5640         }
5641         break;
5642     case Uri_PROPERTY_SCHEME_NAME:
5643         hr = IUriBuilder_SetSchemeName(builder, valueW);
5644         if(prop->todo) {
5645             todo_wine {
5646                 ok(hr == prop->expected,
5647                     "Error: IUriBuilder_SetSchemeName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
5648                     hr, prop->expected, test_index);
5649             }
5650         } else {
5651             ok(hr == prop->expected,
5652                 "Error: IUriBuilder_SetSchemeName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
5653                 hr, prop->expected, test_index);
5654         }
5655         break;
5656     case Uri_PROPERTY_USER_NAME:
5657         hr = IUriBuilder_SetUserName(builder, valueW);
5658         if(prop->todo) {
5659             todo_wine {
5660                 ok(hr == prop->expected,
5661                     "Error: IUriBuilder_SetUserName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
5662                     hr, prop->expected, test_index);
5663             }
5664         } else {
5665             ok(hr == prop->expected,
5666                 "Error: IUriBuilder_SetUserName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
5667                 hr, prop->expected, test_index);
5668         }
5669         break;
5670     default:
5671         trace("Unsupported operation for %d on uri_builder_tests[%d].\n", prop->property, test_index);
5672     }
5673
5674     heap_free(valueW);
5675 }
5676
5677 /*
5678  * Simple tests to make sure the CreateUri function handles invalid flag combinations
5679  * correctly.
5680  */
5681 static void test_CreateUri_InvalidFlags(void) {
5682     DWORD i;
5683
5684     for(i = 0; i < sizeof(invalid_flag_tests)/sizeof(invalid_flag_tests[0]); ++i) {
5685         HRESULT hr;
5686         IUri *uri = (void*) 0xdeadbeef;
5687
5688         hr = pCreateUri(http_urlW, invalid_flag_tests[i].flags, 0, &uri);
5689         ok(hr == invalid_flag_tests[i].expected, "Error: CreateUri returned 0x%08x, expected 0x%08x, flags=0x%08x\n",
5690                 hr, invalid_flag_tests[i].expected, invalid_flag_tests[i].flags);
5691         ok(uri == NULL, "Error: expected the IUri to be NULL, but it was %p instead\n", uri);
5692     }
5693 }
5694
5695 static void test_CreateUri_InvalidArgs(void) {
5696     HRESULT hr;
5697     IUri *uri = (void*) 0xdeadbeef;
5698
5699     const WCHAR invalidW[] = {'i','n','v','a','l','i','d',0};
5700     static const WCHAR emptyW[] = {0};
5701
5702     hr = pCreateUri(http_urlW, 0, 0, NULL);
5703     ok(hr == E_INVALIDARG, "Error: CreateUri returned 0x%08x, expected 0x%08x\n", hr, E_INVALIDARG);
5704
5705     hr = pCreateUri(NULL, 0, 0, &uri);
5706     ok(hr == E_INVALIDARG, "Error: CreateUri returned 0x%08x, expected 0x%08x\n", hr, E_INVALIDARG);
5707     ok(uri == NULL, "Error: Expected the IUri to be NULL, but it was %p instead\n", uri);
5708
5709     uri = (void*) 0xdeadbeef;
5710     hr = pCreateUri(invalidW, 0, 0, &uri);
5711     ok(hr == E_INVALIDARG, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
5712     ok(uri == NULL, "Error: Expected the IUri to be NULL, but it was %p instead\n", uri);
5713
5714     uri = (void*) 0xdeadbeef;
5715     hr = pCreateUri(emptyW, 0, 0, &uri);
5716     ok(hr == E_INVALIDARG, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
5717     ok(uri == NULL, "Error: Expected the IUri to be NULL, but it was %p instead\n", uri);
5718 }
5719
5720 static void test_CreateUri_InvalidUri(void) {
5721     DWORD i;
5722
5723     for(i = 0; i < sizeof(invalid_uri_tests)/sizeof(invalid_uri_tests[0]); ++i) {
5724         invalid_uri test = invalid_uri_tests[i];
5725         IUri *uri = NULL;
5726         LPWSTR uriW;
5727         HRESULT hr;
5728
5729         uriW = a2w(test.uri);
5730         hr = pCreateUri(uriW, test.flags, 0, &uri);
5731         if(test.todo) {
5732             todo_wine {
5733                 ok(hr == E_INVALIDARG, "Error: CreateUri returned 0x%08x, expected 0x%08x on invalid_uri_tests[%d].\n",
5734                     hr, E_INVALIDARG, i);
5735             }
5736         } else {
5737             ok(hr == E_INVALIDARG, "Error: CreateUri returned 0x%08x, expected 0x%08x on invalid_uri_tests[%d].\n",
5738                 hr, E_INVALIDARG, i);
5739         }
5740         if(uri) IUri_Release(uri);
5741
5742         heap_free(uriW);
5743     }
5744 }
5745
5746 static void test_IUri_GetPropertyBSTR(void) {
5747     IUri *uri = NULL;
5748     HRESULT hr;
5749     DWORD i;
5750
5751     /* Make sure GetPropertyBSTR handles invalid args correctly. */
5752     hr = pCreateUri(http_urlW, 0, 0, &uri);
5753     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
5754     if(SUCCEEDED(hr)) {
5755         BSTR received = NULL;
5756
5757         hr = IUri_GetPropertyBSTR(uri, Uri_PROPERTY_RAW_URI, NULL, 0);
5758         ok(hr == E_POINTER, "Error: GetPropertyBSTR returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
5759
5760         /* Make sure it handles a invalid Uri_PROPERTY's correctly. */
5761         hr = IUri_GetPropertyBSTR(uri, Uri_PROPERTY_PORT, &received, 0);
5762         ok(hr == S_OK, "Error: GetPropertyBSTR returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
5763         ok(received != NULL, "Error: Expected the string not to be NULL.\n");
5764         ok(!SysStringLen(received), "Error: Expected the string to be of len=0 but it was %d instead.\n", SysStringLen(received));
5765         SysFreeString(received);
5766
5767         /* Make sure it handles the ZONE property correctly. */
5768         received = NULL;
5769         hr = IUri_GetPropertyBSTR(uri, Uri_PROPERTY_ZONE, &received, 0);
5770         ok(hr == S_FALSE, "Error: GetPropertyBSTR returned 0x%08x, expected 0x%08x.\n", hr, S_FALSE);
5771         ok(received != NULL, "Error: Expected the string not to be NULL.\n");
5772         ok(!SysStringLen(received), "Error: Expected the string to be of len=0 but it was %d instead.\n", SysStringLen(received));
5773         SysFreeString(received);
5774     }
5775     if(uri) IUri_Release(uri);
5776
5777     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
5778         uri_properties test = uri_tests[i];
5779         LPWSTR uriW;
5780         uri = NULL;
5781
5782         uriW = a2w(test.uri);
5783         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
5784         if(test.create_todo) {
5785             todo_wine {
5786                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x. Failed on uri_tests[%d].\n",
5787                         hr, test.create_expected, i);
5788             }
5789         } else {
5790             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x. Failed on uri_tests[%d].\n",
5791                     hr, test.create_expected, i);
5792         }
5793
5794         if(SUCCEEDED(hr)) {
5795             DWORD j;
5796
5797             /* Checks all the string properties of the uri. */
5798             for(j = Uri_PROPERTY_STRING_START; j <= Uri_PROPERTY_STRING_LAST; ++j) {
5799                 BSTR received = NULL;
5800                 uri_str_property prop = test.str_props[j];
5801
5802                 hr = IUri_GetPropertyBSTR(uri, j, &received, 0);
5803                 if(prop.todo) {
5804                     todo_wine {
5805                         ok(hr == prop.expected, "GetPropertyBSTR returned 0x%08x, expected 0x%08x. On uri_tests[%d].str_props[%d].\n",
5806                                 hr, prop.expected, i, j);
5807                     }
5808                     todo_wine {
5809                         ok(!strcmp_aw(prop.value, received) || broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
5810                                 "Expected %s but got %s on uri_tests[%d].str_props[%d].\n",
5811                                 prop.value, wine_dbgstr_w(received), i, j);
5812                     }
5813                 } else {
5814                     ok(hr == prop.expected, "GetPropertyBSTR returned 0x%08x, expected 0x%08x. On uri_tests[%d].str_props[%d].\n",
5815                             hr, prop.expected, i, j);
5816                     ok(!strcmp_aw(prop.value, received) || broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
5817                             "Expected %s but got %s on uri_tests[%d].str_props[%d].\n",
5818                             prop.value, wine_dbgstr_w(received), i, j);
5819                 }
5820
5821                 SysFreeString(received);
5822             }
5823         }
5824
5825         if(uri) IUri_Release(uri);
5826
5827         heap_free(uriW);
5828     }
5829 }
5830
5831 static void test_IUri_GetPropertyDWORD(void) {
5832     IUri *uri = NULL;
5833     HRESULT hr;
5834     DWORD i;
5835
5836     hr = pCreateUri(http_urlW, 0, 0, &uri);
5837     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
5838     if(SUCCEEDED(hr)) {
5839         DWORD received = 0xdeadbeef;
5840
5841         hr = IUri_GetPropertyDWORD(uri, Uri_PROPERTY_DWORD_START, NULL, 0);
5842         ok(hr == E_INVALIDARG, "Error: GetPropertyDWORD returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
5843
5844         hr = IUri_GetPropertyDWORD(uri, Uri_PROPERTY_ABSOLUTE_URI, &received, 0);
5845         ok(hr == E_INVALIDARG, "Error: GetPropertyDWORD returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
5846         ok(received == 0, "Error: Expected received=%d but instead received=%d.\n", 0, received);
5847     }
5848     if(uri) IUri_Release(uri);
5849
5850     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
5851         uri_properties test = uri_tests[i];
5852         LPWSTR uriW;
5853         uri = NULL;
5854
5855         uriW = a2w(test.uri);
5856         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
5857         if(test.create_todo) {
5858             todo_wine {
5859                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x. Failed on uri_tests[%d].\n",
5860                         hr, test.create_expected, i);
5861             }
5862         } else {
5863             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x. Failed on uri_tests[%d].\n",
5864                     hr, test.create_expected, i);
5865         }
5866
5867         if(SUCCEEDED(hr)) {
5868             DWORD j;
5869
5870             /* Checks all the DWORD properties of the uri. */
5871             for(j = 0; j < sizeof(test.dword_props)/sizeof(test.dword_props[0]); ++j) {
5872                 DWORD received;
5873                 uri_dword_property prop = test.dword_props[j];
5874
5875                 hr = IUri_GetPropertyDWORD(uri, j+Uri_PROPERTY_DWORD_START, &received, 0);
5876                 if(prop.todo) {
5877                     todo_wine {
5878                         ok(hr == prop.expected, "GetPropertyDWORD returned 0x%08x, expected 0x%08x. On uri_tests[%d].dword_props[%d].\n",
5879                                 hr, prop.expected, i, j);
5880                     }
5881                     todo_wine {
5882                         ok(prop.value == received, "Expected %d but got %d on uri_tests[%d].dword_props[%d].\n",
5883                                 prop.value, received, i, j);
5884                     }
5885                 } else {
5886                     ok(hr == prop.expected, "GetPropertyDWORD returned 0x%08x, expected 0x%08x. On uri_tests[%d].dword_props[%d].\n",
5887                             hr, prop.expected, i, j);
5888                     ok(prop.value == received, "Expected %d but got %d on uri_tests[%d].dword_props[%d].\n",
5889                             prop.value, received, i, j);
5890                 }
5891             }
5892         }
5893
5894         if(uri) IUri_Release(uri);
5895
5896         heap_free(uriW);
5897     }
5898 }
5899
5900 /* Tests all the 'Get*' property functions which deal with strings. */
5901 static void test_IUri_GetStrProperties(void) {
5902     IUri *uri = NULL;
5903     HRESULT hr;
5904     DWORD i;
5905
5906     /* Make sure all the 'Get*' string property functions handle invalid args correctly. */
5907     hr = pCreateUri(http_urlW, 0, 0, &uri);
5908     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
5909     if(SUCCEEDED(hr)) {
5910         hr = IUri_GetAbsoluteUri(uri, NULL);
5911         ok(hr == E_POINTER, "Error: GetAbsoluteUri returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
5912
5913         hr = IUri_GetAuthority(uri, NULL);
5914         ok(hr == E_POINTER, "Error: GetAuthority returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
5915
5916         hr = IUri_GetDisplayUri(uri, NULL);
5917         ok(hr == E_POINTER, "Error: GetDisplayUri returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
5918
5919         hr = IUri_GetDomain(uri, NULL);
5920         ok(hr == E_POINTER, "Error: GetDomain returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
5921
5922         hr = IUri_GetExtension(uri, NULL);
5923         ok(hr == E_POINTER, "Error: GetExtension returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
5924
5925         hr = IUri_GetFragment(uri, NULL);
5926         ok(hr == E_POINTER, "Error: GetFragment returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
5927
5928         hr = IUri_GetHost(uri, NULL);
5929         ok(hr == E_POINTER, "Error: GetHost returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
5930
5931         hr = IUri_GetPassword(uri, NULL);
5932         ok(hr == E_POINTER, "Error: GetPassword returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
5933
5934         hr = IUri_GetPath(uri, NULL);
5935         ok(hr == E_POINTER, "Error: GetPath returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
5936
5937         hr = IUri_GetPathAndQuery(uri, NULL);
5938         ok(hr == E_POINTER, "Error: GetPathAndQuery returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
5939
5940         hr = IUri_GetQuery(uri, NULL);
5941         ok(hr == E_POINTER, "Error: GetQuery returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
5942
5943         hr = IUri_GetRawUri(uri, NULL);
5944         ok(hr == E_POINTER, "Error: GetRawUri returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
5945
5946         hr = IUri_GetSchemeName(uri, NULL);
5947         ok(hr == E_POINTER, "Error: GetSchemeName returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
5948
5949         hr = IUri_GetUserInfo(uri, NULL);
5950         ok(hr == E_POINTER, "Error: GetUserInfo returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
5951
5952         hr = IUri_GetUserName(uri, NULL);
5953         ok(hr == E_POINTER, "Error: GetUserName returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
5954     }
5955     if(uri) IUri_Release(uri);
5956
5957     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
5958         uri_properties test = uri_tests[i];
5959         LPWSTR uriW;
5960         uri = NULL;
5961
5962         uriW = a2w(test.uri);
5963         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
5964         if(test.create_todo) {
5965             todo_wine {
5966                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
5967                         hr, test.create_expected, i);
5968             }
5969         } else {
5970             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
5971                     hr, test.create_expected, i);
5972         }
5973
5974         if(SUCCEEDED(hr)) {
5975             uri_str_property prop;
5976             BSTR received = NULL;
5977
5978             /* GetAbsoluteUri() tests. */
5979             prop = test.str_props[Uri_PROPERTY_ABSOLUTE_URI];
5980             hr = IUri_GetAbsoluteUri(uri, &received);
5981             if(prop.todo) {
5982                 todo_wine {
5983                     ok(hr == prop.expected, "Error: GetAbsoluteUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
5984                             hr, prop.expected, i);
5985                 }
5986                 todo_wine {
5987                     ok(!strcmp_aw(prop.value, received) || broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
5988                             "Error: Expected %s but got %s on uri_tests[%d].\n",
5989                             prop.value, wine_dbgstr_w(received), i);
5990                 }
5991             } else {
5992                 ok(hr == prop.expected, "Error: GetAbsoluteUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
5993                         hr, prop.expected, i);
5994                 ok(!strcmp_aw(prop.value, received) || broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
5995                         "Error: Expected %s but got %s on uri_tests[%d].\n",
5996                         prop.value, wine_dbgstr_w(received), i);
5997             }
5998             SysFreeString(received);
5999             received = NULL;
6000
6001             /* GetAuthority() tests. */
6002             prop = test.str_props[Uri_PROPERTY_AUTHORITY];
6003             hr = IUri_GetAuthority(uri, &received);
6004             if(prop.todo) {
6005                 todo_wine {
6006                     ok(hr == prop.expected, "Error: GetAuthority returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6007                             hr, prop.expected, i);
6008                 }
6009                 todo_wine {
6010                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6011                             prop.value, wine_dbgstr_w(received), i);
6012                 }
6013             } else {
6014                 ok(hr == prop.expected, "Error: GetAuthority returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6015                         hr, prop.expected, i);
6016                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6017                         prop.value, wine_dbgstr_w(received), i);
6018             }
6019             SysFreeString(received);
6020             received = NULL;
6021
6022             /* GetDisplayUri() tests. */
6023             prop = test.str_props[Uri_PROPERTY_DISPLAY_URI];
6024             hr = IUri_GetDisplayUri(uri, &received);
6025             if(prop.todo) {
6026                 todo_wine {
6027                     ok(hr == prop.expected, "Error: GetDisplayUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6028                             hr, prop.expected, i);
6029                 }
6030                 todo_wine {
6031                     ok(!strcmp_aw(prop.value, received) || broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
6032                             "Error: Expected %s but got %s on uri_test[%d].\n",
6033                             prop.value, wine_dbgstr_w(received), i);
6034                 }
6035             } else {
6036                 ok(hr == prop.expected, "Error: GetDisplayUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6037                         hr, prop.expected, i);
6038                 ok(!strcmp_aw(prop.value, received) || broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
6039                         "Error: Expected %s but got %s on uri_tests[%d].\n",
6040                         prop.value, wine_dbgstr_w(received), i);
6041             }
6042             SysFreeString(received);
6043             received = NULL;
6044
6045             /* GetDomain() tests. */
6046             prop = test.str_props[Uri_PROPERTY_DOMAIN];
6047             hr = IUri_GetDomain(uri, &received);
6048             if(prop.todo) {
6049                 todo_wine {
6050                     ok(hr == prop.expected, "Error: GetDomain returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6051                             hr, prop.expected, i);
6052                 }
6053                 todo_wine {
6054                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6055                             prop.value, wine_dbgstr_w(received), i);
6056                 }
6057             } else {
6058                 ok(hr == prop.expected, "Error: GetDomain returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6059                         hr, prop.expected, i);
6060                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6061                         prop.value, wine_dbgstr_w(received), i);
6062             }
6063             SysFreeString(received);
6064             received = NULL;
6065
6066             /* GetExtension() tests. */
6067             prop = test.str_props[Uri_PROPERTY_EXTENSION];
6068             hr = IUri_GetExtension(uri, &received);
6069             if(prop.todo) {
6070                 todo_wine {
6071                     ok(hr == prop.expected, "Error: GetExtension returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6072                             hr, prop.expected, i);
6073                 }
6074                 todo_wine {
6075                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6076                             prop.value, wine_dbgstr_w(received), i);
6077                 }
6078             } else {
6079                 ok(hr == prop.expected, "Error: GetExtension returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6080                         hr, prop.expected, i);
6081                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6082                         prop.value, wine_dbgstr_w(received), i);
6083             }
6084             SysFreeString(received);
6085             received = NULL;
6086
6087             /* GetFragment() tests. */
6088             prop = test.str_props[Uri_PROPERTY_FRAGMENT];
6089             hr = IUri_GetFragment(uri, &received);
6090             if(prop.todo) {
6091                 todo_wine {
6092                     ok(hr == prop.expected, "Error: GetFragment returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6093                             hr, prop.expected, i);
6094                 }
6095                 todo_wine {
6096                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6097                             prop.value, wine_dbgstr_w(received), i);
6098                 }
6099             } else {
6100                 ok(hr == prop.expected, "Error: GetFragment returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6101                         hr, prop.expected, i);
6102                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6103                         prop.value, wine_dbgstr_w(received), i);
6104             }
6105             SysFreeString(received);
6106             received = NULL;
6107
6108             /* GetHost() tests. */
6109             prop = test.str_props[Uri_PROPERTY_HOST];
6110             hr = IUri_GetHost(uri, &received);
6111             if(prop.todo) {
6112                 todo_wine {
6113                     ok(hr == prop.expected, "Error: GetHost returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6114                             hr, prop.expected, i);
6115                 }
6116                 todo_wine {
6117                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6118                             prop.value, wine_dbgstr_w(received), i);
6119                 }
6120             } else {
6121                 ok(hr == prop.expected, "Error: GetHost returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6122                         hr, prop.expected, i);
6123                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6124                         prop.value, wine_dbgstr_w(received), i);
6125             }
6126             SysFreeString(received);
6127             received = NULL;
6128
6129             /* GetPassword() tests. */
6130             prop = test.str_props[Uri_PROPERTY_PASSWORD];
6131             hr = IUri_GetPassword(uri, &received);
6132             if(prop.todo) {
6133                 todo_wine {
6134                     ok(hr == prop.expected, "Error: GetPassword returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6135                             hr, prop.expected, i);
6136                 }
6137                 todo_wine {
6138                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6139                             prop.value, wine_dbgstr_w(received), i);
6140                 }
6141             } else {
6142                 ok(hr == prop.expected, "Error: GetPassword returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6143                         hr, prop.expected, i);
6144                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6145                         prop.value, wine_dbgstr_w(received), i);
6146             }
6147             SysFreeString(received);
6148             received = NULL;
6149
6150             /* GetPath() tests. */
6151             prop = test.str_props[Uri_PROPERTY_PATH];
6152             hr = IUri_GetPath(uri, &received);
6153             if(prop.todo) {
6154                 todo_wine {
6155                     ok(hr == prop.expected, "Error: GetPath returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6156                             hr, prop.expected, i);
6157                 }
6158                 todo_wine {
6159                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6160                             prop.value, wine_dbgstr_w(received), i);
6161                 }
6162             } else {
6163                 ok(hr == prop.expected, "Error: GetPath returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6164                         hr, prop.expected, i);
6165                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6166                         prop.value, wine_dbgstr_w(received), i);
6167             }
6168             SysFreeString(received);
6169             received = NULL;
6170
6171             /* GetPathAndQuery() tests. */
6172             prop = test.str_props[Uri_PROPERTY_PATH_AND_QUERY];
6173             hr = IUri_GetPathAndQuery(uri, &received);
6174             if(prop.todo) {
6175                 todo_wine {
6176                     ok(hr == prop.expected, "Error: GetPathAndQuery returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6177                             hr, prop.expected, i);
6178                 }
6179                 todo_wine {
6180                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6181                             prop.value, wine_dbgstr_w(received), i);
6182                 }
6183             } else {
6184                 ok(hr == prop.expected, "Error: GetPathAndQuery returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6185                         hr, prop.expected, i);
6186                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6187                         prop.value, wine_dbgstr_w(received), i);
6188             }
6189             SysFreeString(received);
6190             received = NULL;
6191
6192             /* GetQuery() tests. */
6193             prop = test.str_props[Uri_PROPERTY_QUERY];
6194             hr = IUri_GetQuery(uri, &received);
6195             if(prop.todo) {
6196                 todo_wine {
6197                     ok(hr == prop.expected, "Error: GetQuery returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6198                             hr, prop.expected, i);
6199                 }
6200                 todo_wine {
6201                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6202                             prop.value, wine_dbgstr_w(received), i);
6203                 }
6204             } else {
6205                 ok(hr == prop.expected, "Error: GetQuery returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6206                         hr, prop.expected, i);
6207                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6208                         prop.value, wine_dbgstr_w(received), i);
6209             }
6210             SysFreeString(received);
6211             received = NULL;
6212
6213             /* GetRawUri() tests. */
6214             prop = test.str_props[Uri_PROPERTY_RAW_URI];
6215             hr = IUri_GetRawUri(uri, &received);
6216             if(prop.todo) {
6217                 todo_wine {
6218                     ok(hr == prop.expected, "Error: GetRawUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6219                             hr, prop.expected, i);
6220                 }
6221                 todo_wine {
6222                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6223                             prop.value, wine_dbgstr_w(received), i);
6224                 }
6225             } else {
6226                 ok(hr == prop.expected, "Error: GetRawUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6227                         hr, prop.expected, i);
6228                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6229                         prop.value, wine_dbgstr_w(received), i);
6230             }
6231             SysFreeString(received);
6232             received = NULL;
6233
6234             /* GetSchemeName() tests. */
6235             prop = test.str_props[Uri_PROPERTY_SCHEME_NAME];
6236             hr = IUri_GetSchemeName(uri, &received);
6237             if(prop.todo) {
6238                 todo_wine {
6239                     ok(hr == prop.expected, "Error: GetSchemeName returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6240                             hr, prop.expected, i);
6241                 }
6242                 todo_wine {
6243                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6244                             prop.value, wine_dbgstr_w(received), i);
6245                 }
6246             } else {
6247                 ok(hr == prop.expected, "Error: GetSchemeName returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6248                         hr, prop.expected, i);
6249                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6250                         prop.value, wine_dbgstr_w(received), i);
6251             }
6252             SysFreeString(received);
6253             received = NULL;
6254
6255             /* GetUserInfo() tests. */
6256             prop = test.str_props[Uri_PROPERTY_USER_INFO];
6257             hr = IUri_GetUserInfo(uri, &received);
6258             if(prop.todo) {
6259                 todo_wine {
6260                     ok(hr == prop.expected, "Error: GetUserInfo returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6261                             hr, prop.expected, i);
6262                 }
6263                 todo_wine {
6264                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6265                             prop.value, wine_dbgstr_w(received), i);
6266                 }
6267             } else {
6268                 ok(hr == prop.expected, "Error: GetUserInfo returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6269                         hr, prop.expected, i);
6270                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6271                         prop.value, wine_dbgstr_w(received), i);
6272             }
6273             SysFreeString(received);
6274             received = NULL;
6275
6276             /* GetUserName() tests. */
6277             prop = test.str_props[Uri_PROPERTY_USER_NAME];
6278             hr = IUri_GetUserName(uri, &received);
6279             if(prop.todo) {
6280                 todo_wine {
6281                     ok(hr == prop.expected, "Error: GetUserName returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6282                             hr, prop.expected, i);
6283                 }
6284                 todo_wine {
6285                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6286                             prop.value, wine_dbgstr_w(received), i);
6287                 }
6288             } else {
6289                 ok(hr == prop.expected, "Error: GetUserName returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6290                         hr, prop.expected, i);
6291                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6292                         prop.value, wine_dbgstr_w(received), i);
6293             }
6294             SysFreeString(received);
6295         }
6296
6297         if(uri) IUri_Release(uri);
6298
6299         heap_free(uriW);
6300     }
6301 }
6302
6303 static void test_IUri_GetDwordProperties(void) {
6304     IUri *uri = NULL;
6305     HRESULT hr;
6306     DWORD i;
6307
6308     /* Make sure all the 'Get*' dword property functions handle invalid args correctly. */
6309     hr = pCreateUri(http_urlW, 0, 0, &uri);
6310     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
6311     if(SUCCEEDED(hr)) {
6312         hr = IUri_GetHostType(uri, NULL);
6313         ok(hr == E_INVALIDARG, "Error: GetHostType returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
6314
6315         hr = IUri_GetPort(uri, NULL);
6316         ok(hr == E_INVALIDARG, "Error: GetPort returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
6317
6318         hr = IUri_GetScheme(uri, NULL);
6319         ok(hr == E_INVALIDARG, "Error: GetScheme returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
6320
6321         hr = IUri_GetZone(uri, NULL);
6322         ok(hr == E_INVALIDARG, "Error: GetZone returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
6323     }
6324     if(uri) IUri_Release(uri);
6325
6326     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
6327         uri_properties test = uri_tests[i];
6328         LPWSTR uriW;
6329         uri = NULL;
6330
6331         uriW = a2w(test.uri);
6332         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
6333         if(test.create_todo) {
6334             todo_wine {
6335                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6336                         hr, test.create_expected, i);
6337             }
6338         } else {
6339             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6340                     hr, test.create_expected, i);
6341         }
6342
6343         if(SUCCEEDED(hr)) {
6344             uri_dword_property prop;
6345             DWORD received;
6346
6347             /* Assign an insane value so tests don't accidentally pass when
6348              * they shouldn't!
6349              */
6350             received = -9999999;
6351
6352             /* GetHostType() tests. */
6353             prop = test.dword_props[Uri_PROPERTY_HOST_TYPE-Uri_PROPERTY_DWORD_START];
6354             hr = IUri_GetHostType(uri, &received);
6355             if(prop.todo) {
6356                 todo_wine {
6357                     ok(hr == prop.expected, "Error: GetHostType returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6358                             hr, prop.expected, i);
6359                 }
6360                 todo_wine {
6361                     ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
6362                 }
6363             } else {
6364                 ok(hr == prop.expected, "Error: GetHostType returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6365                         hr, prop.expected, i);
6366                 ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
6367             }
6368             received = -9999999;
6369
6370             /* GetPort() tests. */
6371             prop = test.dword_props[Uri_PROPERTY_PORT-Uri_PROPERTY_DWORD_START];
6372             hr = IUri_GetPort(uri, &received);
6373             if(prop.todo) {
6374                 todo_wine {
6375                     ok(hr == prop.expected, "Error: GetPort returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6376                             hr, prop.expected, i);
6377                 }
6378                 todo_wine {
6379                     ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
6380                 }
6381             } else {
6382                 ok(hr == prop.expected, "Error: GetPort returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6383                         hr, prop.expected, i);
6384                 ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
6385             }
6386             received = -9999999;
6387
6388             /* GetScheme() tests. */
6389             prop = test.dword_props[Uri_PROPERTY_SCHEME-Uri_PROPERTY_DWORD_START];
6390             hr = IUri_GetScheme(uri, &received);
6391             if(prop.todo) {
6392                 todo_wine {
6393                     ok(hr == prop.expected, "Error: GetScheme returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6394                             hr, prop.expected, i);
6395                 }
6396                 todo_wine {
6397                     ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
6398                 }
6399             } else {
6400                 ok(hr == prop.expected, "Error: GetScheme returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6401                         hr, prop.expected, i);
6402                 ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
6403             }
6404             received = -9999999;
6405
6406             /* GetZone() tests. */
6407             prop = test.dword_props[Uri_PROPERTY_ZONE-Uri_PROPERTY_DWORD_START];
6408             hr = IUri_GetZone(uri, &received);
6409             if(prop.todo) {
6410                 todo_wine {
6411                     ok(hr == prop.expected, "Error: GetZone returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6412                             hr, prop.expected, i);
6413                 }
6414                 todo_wine {
6415                     ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
6416                 }
6417             } else {
6418                 ok(hr == prop.expected, "Error: GetZone returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6419                         hr, prop.expected, i);
6420                 ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
6421             }
6422         }
6423
6424         if(uri) IUri_Release(uri);
6425
6426         heap_free(uriW);
6427     }
6428 }
6429
6430 static void test_IUri_GetPropertyLength(void) {
6431     IUri *uri = NULL;
6432     HRESULT hr;
6433     DWORD i;
6434
6435     /* Make sure it handles invalid args correctly. */
6436     hr = pCreateUri(http_urlW, 0, 0, &uri);
6437     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
6438     if(SUCCEEDED(hr)) {
6439         DWORD received = 0xdeadbeef;
6440
6441         hr = IUri_GetPropertyLength(uri, Uri_PROPERTY_STRING_START, NULL, 0);
6442         ok(hr == E_INVALIDARG, "Error: GetPropertyLength returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
6443
6444         hr = IUri_GetPropertyLength(uri, Uri_PROPERTY_DWORD_START, &received, 0);
6445         ok(hr == E_INVALIDARG, "Error: GetPropertyLength return 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
6446         ok(received == 0xdeadbeef, "Error: Expected 0xdeadbeef but got 0x%08x.\n", received);
6447     }
6448     if(uri) IUri_Release(uri);
6449
6450     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
6451         uri_properties test = uri_tests[i];
6452         LPWSTR uriW;
6453         uri = NULL;
6454
6455         uriW = a2w(test.uri);
6456         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
6457         if(test.create_todo) {
6458             todo_wine {
6459                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6460                         hr, test.create_expected, i);
6461             }
6462         } else {
6463             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_test[%d].\n",
6464                     hr, test.create_expected, i);
6465         }
6466
6467         if(SUCCEEDED(hr)) {
6468             DWORD j;
6469
6470             for(j = Uri_PROPERTY_STRING_START; j <= Uri_PROPERTY_STRING_LAST; ++j) {
6471                 DWORD expectedLen, brokenLen, receivedLen;
6472                 uri_str_property prop = test.str_props[j];
6473
6474                 expectedLen = lstrlen(prop.value);
6475                 brokenLen = lstrlen(prop.broken_value);
6476
6477                 /* This won't be necessary once GetPropertyLength is implemented. */
6478                 receivedLen = -1;
6479
6480                 hr = IUri_GetPropertyLength(uri, j, &receivedLen, 0);
6481                 if(prop.todo) {
6482                     todo_wine {
6483                         ok(hr == prop.expected, "Error: GetPropertyLength returned 0x%08x, expected 0x%08x on uri_tests[%d].str_props[%d].\n",
6484                                 hr, prop.expected, i, j);
6485                     }
6486                     todo_wine {
6487                         ok(receivedLen == expectedLen || broken(receivedLen == brokenLen),
6488                                 "Error: Expected a length of %d but got %d on uri_tests[%d].str_props[%d].\n",
6489                                 expectedLen, receivedLen, i, j);
6490                     }
6491                 } else {
6492                     ok(hr == prop.expected, "Error: GetPropertyLength returned 0x%08x, expected 0x%08x on uri_tests[%d].str_props[%d].\n",
6493                             hr, prop.expected, i, j);
6494                     ok(receivedLen == expectedLen || broken(receivedLen == brokenLen),
6495                             "Error: Expected a length of %d but got %d on uri_tests[%d].str_props[%d].\n",
6496                             expectedLen, receivedLen, i, j);
6497                 }
6498             }
6499         }
6500
6501         if(uri) IUri_Release(uri);
6502
6503         heap_free(uriW);
6504     }
6505 }
6506
6507 static void test_IUri_GetProperties(void) {
6508     IUri *uri = NULL;
6509     HRESULT hr;
6510     DWORD i;
6511
6512     hr = pCreateUri(http_urlW, 0, 0, &uri);
6513     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
6514     if(SUCCEEDED(hr)) {
6515         hr = IUri_GetProperties(uri, NULL);
6516         ok(hr == E_INVALIDARG, "Error: GetProperties returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
6517     }
6518     if(uri) IUri_Release(uri);
6519
6520     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
6521         uri_properties test = uri_tests[i];
6522         LPWSTR uriW;
6523         uri = NULL;
6524
6525         uriW = a2w(test.uri);
6526         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
6527         if(test.create_todo) {
6528             todo_wine {
6529                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, test.create_expected);
6530             }
6531         } else {
6532             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, test.create_expected);
6533         }
6534
6535         if(SUCCEEDED(hr)) {
6536             DWORD received = 0;
6537             DWORD j;
6538
6539             hr = IUri_GetProperties(uri, &received);
6540             if(test.props_todo) {
6541                 todo_wine {
6542                     ok(hr == S_OK, "Error: GetProperties returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
6543                 }
6544             } else {
6545                 ok(hr == S_OK, "Error: GetProperties returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
6546             }
6547
6548             for(j = 0; j <= Uri_PROPERTY_DWORD_LAST; ++j) {
6549                 /* (1 << j) converts a Uri_PROPERTY to its corresponding Uri_HAS_* flag mask. */
6550                 if(test.props & (1 << j)) {
6551                     if(test.props_todo) {
6552                         todo_wine {
6553                             ok(received & (1 << j), "Error: Expected flag for property %d on uri_tests[%d].\n", j, i);
6554                         }
6555                     } else {
6556                         ok(received & (1 << j), "Error: Expected flag for property %d on uri_tests[%d].\n", j, i);
6557                     }
6558                 } else {
6559                     /* NOTE: Since received is initialized to 0, this test will always pass while
6560                      * GetProperties is unimplemented.
6561                      */
6562                     ok(!(received & (1 << j)), "Error: Received flag for property %d when not expected on uri_tests[%d].\n", j, i);
6563                 }
6564             }
6565         }
6566
6567         if(uri) IUri_Release(uri);
6568
6569         heap_free(uriW);
6570     }
6571 }
6572
6573 static void test_IUri_HasProperty(void) {
6574     IUri *uri = NULL;
6575     HRESULT hr;
6576     DWORD i;
6577
6578     hr = pCreateUri(http_urlW, 0, 0, &uri);
6579     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
6580     if(SUCCEEDED(hr)) {
6581         hr = IUri_HasProperty(uri, Uri_PROPERTY_RAW_URI, NULL);
6582         ok(hr == E_INVALIDARG, "Error: HasProperty returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
6583     }
6584     if(uri) IUri_Release(uri);
6585
6586     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
6587         uri_properties test = uri_tests[i];
6588         LPWSTR uriW;
6589         uri = NULL;
6590
6591         uriW = a2w(test.uri);
6592
6593         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
6594         if(test.create_todo) {
6595             todo_wine {
6596                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, test.create_expected);
6597             }
6598         } else {
6599             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, test.create_expected);
6600         }
6601
6602         if(SUCCEEDED(hr)) {
6603             DWORD j;
6604
6605             for(j = 0; j <= Uri_PROPERTY_DWORD_LAST; ++j) {
6606                 /* Assign -1, then explicitly test for TRUE or FALSE later. */
6607                 BOOL received = -1;
6608
6609                 hr = IUri_HasProperty(uri, j, &received);
6610                 if(test.props_todo) {
6611                     todo_wine {
6612                         ok(hr == S_OK, "Error: HasProperty returned 0x%08x, expected 0x%08x for property %d on uri_tests[%d].\n",
6613                                 hr, S_OK, j, i);
6614                     }
6615
6616                     /* Check if the property should be true. */
6617                     if(test.props & (1 << j)) {
6618                         todo_wine {
6619                             ok(received == TRUE, "Error: Expected to have property %d on uri_tests[%d].\n", j, i);
6620                         }
6621                     } else {
6622                         todo_wine {
6623                             ok(received == FALSE, "Error: Wasn't expecting to have property %d on uri_tests[%d].\n", j, i);
6624                         }
6625                     }
6626                 } else {
6627                     ok(hr == S_OK, "Error: HasProperty returned 0x%08x, expected 0x%08x for property %d on uri_tests[%d].\n",
6628                             hr, S_OK, j, i);
6629
6630                     if(test.props & (1 << j)) {
6631                         ok(received == TRUE, "Error: Expected to have property %d on uri_tests[%d].\n", j, i);
6632                     } else {
6633                         ok(received == FALSE, "Error: Wasn't expecting to have property %d on uri_tests[%d].\n", j, i);
6634                     }
6635                 }
6636             }
6637         }
6638
6639         if(uri) IUri_Release(uri);
6640
6641         heap_free(uriW);
6642     }
6643 }
6644
6645 static void test_IUri_IsEqual(void) {
6646     IUri *uriA, *uriB;
6647     HRESULT hrA, hrB;
6648     DWORD i;
6649
6650     uriA = uriB = NULL;
6651
6652     /* Make sure IsEqual handles invalid args correctly. */
6653     hrA = pCreateUri(http_urlW, 0, 0, &uriA);
6654     hrB = pCreateUri(http_urlW, 0, 0, &uriB);
6655     ok(hrA == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hrA, S_OK);
6656     ok(hrB == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hrB, S_OK);
6657     if(SUCCEEDED(hrA) && SUCCEEDED(hrB)) {
6658         BOOL equal = -1;
6659         hrA = IUri_IsEqual(uriA, NULL, &equal);
6660         ok(hrA == S_OK, "Error: IsEqual returned 0x%08x, expected 0x%08x.\n", hrA, S_OK);
6661         ok(equal == FALSE, "Error: Expected equal to be FALSE, but was %d instead.\n", equal);
6662
6663         hrA = IUri_IsEqual(uriA, uriB, NULL);
6664         ok(hrA == E_POINTER, "Error: IsEqual returned 0x%08x, expected 0x%08x.\n", hrA, E_POINTER);
6665     }
6666     if(uriA) IUri_Release(uriA);
6667     if(uriB) IUri_Release(uriB);
6668
6669     for(i = 0; i < sizeof(equality_tests)/sizeof(equality_tests[0]); ++i) {
6670         uri_equality test = equality_tests[i];
6671         LPWSTR uriA_W, uriB_W;
6672
6673         uriA = uriB = NULL;
6674
6675         uriA_W = a2w(test.a);
6676         uriB_W = a2w(test.b);
6677
6678         hrA = pCreateUri(uriA_W, test.create_flags_a, 0, &uriA);
6679         if(test.create_todo_a) {
6680             todo_wine {
6681                 ok(hrA == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x on equality_tests[%d].a\n",
6682                         hrA, S_OK, i);
6683             }
6684         } else {
6685             ok(hrA == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x on equality_tests[%d].a\n",
6686                     hrA, S_OK, i);
6687         }
6688
6689         hrB = pCreateUri(uriB_W, test.create_flags_b, 0, &uriB);
6690         if(test.create_todo_b) {
6691             todo_wine {
6692                 ok(hrB == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x on equality_tests[%d].b\n",
6693                         hrB, S_OK, i);
6694             }
6695         } else {
6696             ok(hrB == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x on equality_tests[%d].b\n",
6697                     hrB, S_OK, i);
6698         }
6699
6700         if(SUCCEEDED(hrA) && SUCCEEDED(hrB)) {
6701             BOOL equal = -1;
6702
6703             hrA = IUri_IsEqual(uriA, uriB, &equal);
6704             if(test.todo) {
6705                 todo_wine {
6706                     ok(hrA == S_OK, "Error: IsEqual returned 0x%08x, expected 0x%08x on equality_tests[%d].\n",
6707                             hrA, S_OK, i);
6708                 }
6709                 todo_wine {
6710                     ok(equal == test.equal, "Error: Expected the comparison to be %d on equality_tests[%d].\n", test.equal, i);
6711                 }
6712             } else {
6713                 ok(hrA == S_OK, "Error: IsEqual returned 0x%08x, expected 0x%08x on equality_tests[%d].\n", hrA, S_OK, i);
6714                 ok(equal == test.equal, "Error: Expected the comparison to be %d on equality_tests[%d].\n", test.equal, i);
6715             }
6716         }
6717         if(uriA) IUri_Release(uriA);
6718         if(uriB) IUri_Release(uriB);
6719
6720         heap_free(uriA_W);
6721         heap_free(uriB_W);
6722     }
6723 }
6724
6725 static void test_CreateUriWithFragment_InvalidArgs(void) {
6726     HRESULT hr;
6727     IUri *uri = (void*) 0xdeadbeef;
6728     const WCHAR fragmentW[] = {'#','f','r','a','g','m','e','n','t',0};
6729
6730     hr = pCreateUriWithFragment(NULL, fragmentW, 0, 0, &uri);
6731     ok(hr == E_INVALIDARG, "Error: CreateUriWithFragment returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
6732     ok(uri == NULL, "Error: Expected uri to be NULL, but was %p instead.\n", uri);
6733
6734     hr = pCreateUriWithFragment(http_urlW, fragmentW, 0, 0, NULL);
6735     ok(hr == E_INVALIDARG, "Error: CreateUriWithFragment returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
6736
6737     /* Original URI can't already contain a fragment component. */
6738     uri = (void*) 0xdeadbeef;
6739     hr = pCreateUriWithFragment(http_url_fragW, fragmentW, 0, 0, &uri);
6740     ok(hr == E_INVALIDARG, "Error: CreateUriWithFragment returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
6741     ok(uri == NULL, "Error: Expected uri to be NULL, but was %p instead.\n", uri);
6742 }
6743
6744 /* CreateUriWithFragment has the same invalid flag combinations as CreateUri. */
6745 static void test_CreateUriWithFragment_InvalidFlags(void) {
6746     DWORD i;
6747
6748     for(i = 0; i < sizeof(invalid_flag_tests)/sizeof(invalid_flag_tests[0]); ++i) {
6749         HRESULT hr;
6750         IUri *uri = (void*) 0xdeadbeef;
6751
6752         hr = pCreateUriWithFragment(http_urlW, NULL, invalid_flag_tests[i].flags, 0, &uri);
6753         ok(hr == invalid_flag_tests[i].expected, "Error: CreateUriWithFragment returned 0x%08x, expected 0x%08x. flags=0x%08x.\n",
6754             hr, invalid_flag_tests[i].expected, invalid_flag_tests[i].flags);
6755         ok(uri == NULL, "Error: Expected uri to be NULL, but was %p instead.\n", uri);
6756     }
6757 }
6758
6759 static void test_CreateUriWithFragment(void) {
6760     DWORD i;
6761
6762     for(i = 0; i < sizeof(uri_fragment_tests)/sizeof(uri_fragment_tests[0]); ++i) {
6763         HRESULT hr;
6764         IUri *uri = NULL;
6765         LPWSTR uriW, fragW;
6766         uri_with_fragment test = uri_fragment_tests[i];
6767
6768         uriW = a2w(test.uri);
6769         fragW = a2w(test.fragment);
6770
6771         hr = pCreateUriWithFragment(uriW, fragW, test.create_flags, 0, &uri);
6772         if(test.expected_todo) {
6773             todo_wine {
6774                 ok(hr == test.create_expected,
6775                     "Error: CreateUriWithFragment returned 0x%08x, expected 0x%08x on uri_fragment_tests[%d].\n",
6776                     hr, test.create_expected, i);
6777             }
6778         } else
6779             ok(hr == test.create_expected,
6780                 "Error: CreateUriWithFragment returned 0x%08x, expected 0x%08x on uri_fragment_tests[%d].\n",
6781                 hr, test.create_expected, i);
6782
6783         if(SUCCEEDED(hr)) {
6784             BSTR received = NULL;
6785
6786             hr = IUri_GetAbsoluteUri(uri, &received);
6787             if(test.expected_todo) {
6788                 todo_wine {
6789                     ok(hr == S_OK,
6790                         "Error: GetAbsoluteUri returned 0x%08x, expected 0x%08x on uri_fragment_tests[%d].\n",
6791                         hr, S_OK, i);
6792                 }
6793                 todo_wine {
6794                     ok(!strcmp_aw(test.expected_uri, received),
6795                         "Error: Expected %s but got %s on uri_fragment_tests[%d].\n",
6796                         test.expected_uri, wine_dbgstr_w(received), i);
6797                 }
6798             } else {
6799                 ok(hr == S_OK, "Error: GetAbsoluteUri returned 0x%08x, expected 0x%08x on uri_fragment_tests[%d].\n",
6800                     hr, S_OK, i);
6801                 ok(!strcmp_aw(test.expected_uri, received), "Error: Expected %s but got %s on uri_fragment_tests[%d].\n",
6802                     test.expected_uri, wine_dbgstr_w(received), i);
6803             }
6804
6805             SysFreeString(received);
6806         }
6807
6808         if(uri) IUri_Release(uri);
6809         heap_free(uriW);
6810     }
6811 }
6812
6813 static void test_CreateIUriBuilder(void) {
6814     HRESULT hr;
6815     IUriBuilder *builder = NULL;
6816     IUri *uri;
6817
6818     hr = pCreateIUriBuilder(NULL, 0, 0, NULL);
6819     ok(hr == E_POINTER, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x\n",
6820         hr, E_POINTER);
6821
6822     /* CreateIUriBuilder increases the ref count of the IUri it receives. */
6823     hr = pCreateUri(http_urlW, 0, 0, &uri);
6824     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
6825     if(SUCCEEDED(hr)) {
6826         ULONG cur_count, orig_count;
6827
6828         orig_count = get_refcnt(uri);
6829         hr = pCreateIUriBuilder(uri, 0, 0, &builder);
6830         ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
6831         ok(builder != NULL, "Error: Expecting builder not to be NULL\n");
6832
6833         cur_count = get_refcnt(uri);
6834         ok(cur_count == orig_count+1, "Error: Expected the ref count to be %u, but was %u instead.\n", orig_count+1, cur_count);
6835
6836         if(builder) IUriBuilder_Release(builder);
6837         cur_count = get_refcnt(uri);
6838         ok(cur_count == orig_count, "Error: Expected the ref count to be %u, but was %u instead.\n", orig_count, cur_count);
6839     }
6840     if(uri) IUri_Release(uri);
6841 }
6842
6843 static void test_IUriBuilder_CreateUri(IUriBuilder *builder, const uri_builder_test *test,
6844                                        DWORD test_index) {
6845     HRESULT hr;
6846     IUri *uri = NULL;
6847
6848     hr = IUriBuilder_CreateUri(builder, test->uri_flags, 0, 0, &uri);
6849     if(test->uri_todo) {
6850         todo_wine {
6851             ok(hr == test->uri_hres,
6852                 "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6853                 hr, test->uri_hres, test_index);
6854         }
6855     } else {
6856         ok(hr == test->uri_hres,
6857             "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6858             hr, test->uri_hres, test_index);
6859     }
6860
6861     if(SUCCEEDED(hr)) {
6862         DWORD i;
6863
6864         for(i = 0; i < sizeof(test->expected_str_props)/sizeof(test->expected_str_props[0]); ++i) {
6865             uri_builder_str_property prop = test->expected_str_props[i];
6866             BSTR received = NULL;
6867
6868             hr = IUri_GetPropertyBSTR(uri, i, &received, 0);
6869             if(prop.todo) {
6870                 todo_wine {
6871                     ok(hr == prop.result,
6872                         "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_str_props[%d].\n",
6873                         hr, prop.result, test_index, i);
6874                 }
6875             } else {
6876                 ok(hr == prop.result,
6877                     "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_str_props[%d].\n",
6878                     hr, prop.result, test_index, i);
6879             }
6880             if(SUCCEEDED(hr)) {
6881                 if(prop.todo) {
6882                     todo_wine {
6883                         ok(!strcmp_aw(prop.expected, received),
6884                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].expected_str_props[%d].\n",
6885                             prop.expected, wine_dbgstr_w(received), test_index, i);
6886                     }
6887                 } else {
6888                     ok(!strcmp_aw(prop.expected, received),
6889                         "Error: Expected %s but got %s instead on uri_builder_tests[%d].expected_str_props[%d].\n",
6890                         prop.expected, wine_dbgstr_w(received), test_index, i);
6891                 }
6892             }
6893             SysFreeString(received);
6894         }
6895
6896         for(i = 0; i < sizeof(test->expected_dword_props)/sizeof(test->expected_dword_props[0]); ++i) {
6897             uri_builder_dword_property prop = test->expected_dword_props[i];
6898             DWORD received = -2;
6899
6900             hr = IUri_GetPropertyDWORD(uri, i+Uri_PROPERTY_DWORD_START, &received, 0);
6901             if(prop.todo) {
6902                 todo_wine {
6903                     ok(hr == prop.result,
6904                         "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_dword_props[%d].\n",
6905                         hr, prop.result, test_index, i);
6906                 }
6907             } else {
6908                 ok(hr == prop.result,
6909                     "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_dword_props[%d].\n",
6910                     hr, prop.result, test_index, i);
6911             }
6912             if(SUCCEEDED(hr)) {
6913                 if(prop.todo) {
6914                     todo_wine {
6915                         ok(received == prop.expected,
6916                             "Error: Expected %d but got %d instead on uri_builder_tests[%d].expected_dword_props[%d].\n",
6917                             prop.expected, received, test_index, i);
6918                     }
6919                 } else {
6920                     ok(received == prop.expected,
6921                         "Error: Expected %d but got %d instead on uri_builder_tests[%d].expected_dword_props[%d].\n",
6922                         prop.expected, received, test_index, i);
6923                 }
6924             }
6925         }
6926     }
6927     if(uri) IUri_Release(uri);
6928 }
6929
6930 static void test_IUriBuilder_CreateUriSimple(IUriBuilder *builder, const uri_builder_test *test,
6931                                        DWORD test_index) {
6932     HRESULT hr;
6933     IUri *uri = NULL;
6934
6935     hr = IUriBuilder_CreateUriSimple(builder, test->uri_simple_encode_flags, 0, &uri);
6936     if(test->uri_simple_todo) {
6937         todo_wine {
6938             ok(hr == test->uri_simple_hres,
6939                 "Error: IUriBuilder_CreateUriSimple returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6940                 hr, test->uri_simple_hres, test_index);
6941         }
6942     } else {
6943         ok(hr == test->uri_simple_hres,
6944             "Error: IUriBuilder_CreateUriSimple returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6945             hr, test->uri_simple_hres, test_index);
6946     }
6947
6948     if(SUCCEEDED(hr)) {
6949         DWORD i;
6950
6951         for(i = 0; i < sizeof(test->expected_str_props)/sizeof(test->expected_str_props[0]); ++i) {
6952             uri_builder_str_property prop = test->expected_str_props[i];
6953             BSTR received = NULL;
6954
6955             hr = IUri_GetPropertyBSTR(uri, i, &received, 0);
6956             if(prop.todo) {
6957                 todo_wine {
6958                     ok(hr == prop.result,
6959                         "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_str_props[%d].\n",
6960                         hr, prop.result, test_index, i);
6961                 }
6962             } else {
6963                 ok(hr == prop.result,
6964                     "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_str_props[%d].\n",
6965                     hr, prop.result, test_index, i);
6966             }
6967             if(SUCCEEDED(hr)) {
6968                 if(prop.todo) {
6969                     todo_wine {
6970                         ok(!strcmp_aw(prop.expected, received),
6971                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].expected_str_props[%d].\n",
6972                             prop.expected, wine_dbgstr_w(received), test_index, i);
6973                     }
6974                 } else {
6975                     ok(!strcmp_aw(prop.expected, received),
6976                         "Error: Expected %s but got %s instead on uri_builder_tests[%d].expected_str_props[%d].\n",
6977                         prop.expected, wine_dbgstr_w(received), test_index, i);
6978                 }
6979             }
6980             SysFreeString(received);
6981         }
6982
6983         for(i = 0; i < sizeof(test->expected_dword_props)/sizeof(test->expected_dword_props[0]); ++i) {
6984             uri_builder_dword_property prop = test->expected_dword_props[i];
6985             DWORD received = -2;
6986
6987             hr = IUri_GetPropertyDWORD(uri, i+Uri_PROPERTY_DWORD_START, &received, 0);
6988             if(prop.todo) {
6989                 todo_wine {
6990                     ok(hr == prop.result,
6991                         "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_dword_props[%d].\n",
6992                         hr, prop.result, test_index, i);
6993                 }
6994             } else {
6995                 ok(hr == prop.result,
6996                     "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_dword_props[%d].\n",
6997                     hr, prop.result, test_index, i);
6998             }
6999             if(SUCCEEDED(hr)) {
7000                 if(prop.todo) {
7001                     todo_wine {
7002                         ok(received == prop.expected,
7003                             "Error: Expected %d but got %d instead on uri_builder_tests[%d].expected_dword_props[%d].\n",
7004                             prop.expected, received, test_index, i);
7005                     }
7006                 } else {
7007                     ok(received == prop.expected,
7008                         "Error: Expected %d but got %d instead on uri_builder_tests[%d].expected_dword_props[%d].\n",
7009                         prop.expected, received, test_index, i);
7010                 }
7011             }
7012         }
7013     }
7014     if(uri) IUri_Release(uri);
7015 }
7016
7017 static void test_IUriBuilder_CreateUriWithFlags(IUriBuilder *builder, const uri_builder_test *test,
7018                                                 DWORD test_index) {
7019     HRESULT hr;
7020     IUri *uri = NULL;
7021
7022     hr = IUriBuilder_CreateUriWithFlags(builder, test->uri_with_flags, test->uri_with_builder_flags,
7023                                         test->uri_with_encode_flags, 0, &uri);
7024     if(test->uri_with_todo) {
7025         todo_wine {
7026             ok(hr == test->uri_with_hres,
7027                 "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7028                 hr, test->uri_with_hres, test_index);
7029         }
7030     } else {
7031         ok(hr == test->uri_with_hres,
7032             "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7033             hr, test->uri_with_hres, test_index);
7034     }
7035
7036     if(SUCCEEDED(hr)) {
7037         DWORD i;
7038
7039         for(i = 0; i < sizeof(test->expected_str_props)/sizeof(test->expected_str_props[0]); ++i) {
7040             uri_builder_str_property prop = test->expected_str_props[i];
7041             BSTR received = NULL;
7042
7043             hr = IUri_GetPropertyBSTR(uri, i, &received, 0);
7044             if(prop.todo) {
7045                 todo_wine {
7046                     ok(hr == prop.result,
7047                         "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_str_props[%d].\n",
7048                         hr, prop.result, test_index, i);
7049                 }
7050             } else {
7051                 ok(hr == prop.result,
7052                     "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_str_props[%d].\n",
7053                     hr, prop.result, test_index, i);
7054             }
7055             if(SUCCEEDED(hr)) {
7056                 if(prop.todo) {
7057                     todo_wine {
7058                         ok(!strcmp_aw(prop.expected, received),
7059                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].expected_str_props[%d].\n",
7060                             prop.expected, wine_dbgstr_w(received), test_index, i);
7061                     }
7062                 } else {
7063                     ok(!strcmp_aw(prop.expected, received),
7064                         "Error: Expected %s but got %s instead on uri_builder_tests[%d].expected_str_props[%d].\n",
7065                         prop.expected, wine_dbgstr_w(received), test_index, i);
7066                 }
7067             }
7068             SysFreeString(received);
7069         }
7070
7071         for(i = 0; i < sizeof(test->expected_dword_props)/sizeof(test->expected_dword_props[0]); ++i) {
7072             uri_builder_dword_property prop = test->expected_dword_props[i];
7073             DWORD received = -2;
7074
7075             hr = IUri_GetPropertyDWORD(uri, i+Uri_PROPERTY_DWORD_START, &received, 0);
7076             if(prop.todo) {
7077                 todo_wine {
7078                     ok(hr == prop.result,
7079                         "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_dword_props[%d].\n",
7080                         hr, prop.result, test_index, i);
7081                 }
7082             } else {
7083                 ok(hr == prop.result,
7084                     "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_dword_props[%d].\n",
7085                     hr, prop.result, test_index, i);
7086             }
7087             if(SUCCEEDED(hr)) {
7088                 if(prop.todo) {
7089                     todo_wine {
7090                         ok(received == prop.expected,
7091                             "Error: Expected %d but got %d instead on uri_builder_tests[%d].expected_dword_props[%d].\n",
7092                             prop.expected, received, test_index, i);
7093                     }
7094                 } else {
7095                     ok(received == prop.expected,
7096                         "Error: Expected %d but got %d instead on uri_builder_tests[%d].expected_dword_props[%d].\n",
7097                         prop.expected, received, test_index, i);
7098                 }
7099             }
7100         }
7101     }
7102     if(uri) IUri_Release(uri);
7103 }
7104
7105 static void test_IUriBuilder_CreateInvalidArgs(void) {
7106     IUriBuilder *builder;
7107     HRESULT hr;
7108
7109     hr = pCreateIUriBuilder(NULL, 0, 0, &builder);
7110     ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7111     if(SUCCEEDED(hr)) {
7112         IUri *test = NULL, *uri = (void*) 0xdeadbeef;
7113
7114         /* Test what happens if the IUriBuilder doesn't have a IUri set. */
7115         hr = IUriBuilder_CreateUri(builder, 0, 0, 0, NULL);
7116         ok(hr == E_POINTER, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
7117
7118         uri = (void*) 0xdeadbeef;
7119         hr = IUriBuilder_CreateUri(builder, 0, Uri_HAS_USER_NAME, 0, &uri);
7120         ok(hr == E_NOTIMPL, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, E_NOTIMPL);
7121         ok(uri == NULL, "Error: expected uri to be NULL, but was %p instead.\n", uri);
7122
7123         hr = IUriBuilder_CreateUriSimple(builder, 0, 0, NULL);
7124         ok(hr == E_POINTER, "Error: IUriBuilder_CreateUriSimple returned 0x%08x, expected 0x%08x.\n",
7125             hr, E_POINTER);
7126
7127         uri = (void*) 0xdeadbeef;
7128         hr = IUriBuilder_CreateUriSimple(builder, Uri_HAS_USER_NAME, 0, &uri);
7129         ok(hr == E_NOTIMPL, "Error: IUriBuilder_CreateUriSimple returned 0x%08x, expected 0x%08x.\n",
7130             hr, E_NOTIMPL);
7131         ok(!uri, "Error: Expected uri to NULL, but was %p instead.\n", uri);
7132
7133         hr = IUriBuilder_CreateUriWithFlags(builder, 0, 0, 0, 0, NULL);
7134         ok(hr == E_POINTER, "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x.\n",
7135             hr, E_POINTER);
7136
7137         uri = (void*) 0xdeadbeef;
7138         hr = IUriBuilder_CreateUriWithFlags(builder, 0, 0, Uri_HAS_USER_NAME, 0, &uri);
7139         ok(hr == E_NOTIMPL, "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x.\n",
7140             hr, E_NOTIMPL);
7141         ok(!uri, "Error: Expected uri to be NULL, but was %p instead.\n", uri);
7142
7143         hr = pCreateUri(http_urlW, 0, 0, &test);
7144         ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7145         if(SUCCEEDED(hr)) {
7146             hr = IUriBuilder_SetIUri(builder, test);
7147             ok(hr == S_OK, "Error: IUriBuilder_SetIUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7148
7149             /* No longer returns E_NOTIMPL, since a IUri has been set and hasn't been modified. */
7150             uri = NULL;
7151             hr = IUriBuilder_CreateUri(builder, 0, Uri_HAS_USER_NAME, 0, &uri);
7152             ok(hr == S_OK, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7153             ok(uri != NULL, "Error: The uri was NULL.\n");
7154             if(uri) IUri_Release(uri);
7155
7156             uri = NULL;
7157             hr = IUriBuilder_CreateUriSimple(builder, Uri_HAS_USER_NAME, 0, &uri);
7158             ok(hr == S_OK, "Error: IUriBuilder_CreateUriSimple returned 0x%08x, expected 0x%08x.\n",
7159                 hr, S_OK);
7160             ok(uri != NULL, "Error: uri was NULL.\n");
7161             if(uri) IUri_Release(uri);
7162
7163             uri = NULL;
7164             hr = IUriBuilder_CreateUriWithFlags(builder, 0, 0, 0, 0, &uri);
7165             ok(hr == S_OK, "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x.\n",
7166                 hr, S_OK);
7167             ok(uri != NULL, "Error: uri was NULL.\n");
7168             if(uri) IUri_Release(uri);
7169
7170             hr = IUriBuilder_SetFragment(builder, NULL);
7171             ok(hr == S_OK, "Error: IUriBuilder_SetFragment returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7172
7173             /* The IUriBuilder is changed, so it returns E_NOTIMPL again. */
7174             uri = (void*) 0xdeadbeef;
7175             hr = IUriBuilder_CreateUri(builder, 0, Uri_HAS_USER_NAME, 0, &uri);
7176             ok(hr == E_NOTIMPL, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7177             ok(!uri, "Error: Expected uri to be NULL but was %p instead.\n", uri);
7178
7179             uri = (void*) 0xdeadbeef;
7180             hr = IUriBuilder_CreateUriSimple(builder, Uri_HAS_USER_NAME, 0, &uri);
7181             ok(hr == E_NOTIMPL, "Error: IUriBuilder_CreateUriSimple returned 0x%08x, expected 0x%08x.\n",
7182                 hr, S_OK);
7183             ok(!uri, "Error: Expected uri to be NULL, but was %p instead.\n", uri);
7184
7185             uri = (void*) 0xdeadbeef;
7186             hr = IUriBuilder_CreateUriWithFlags(builder, 0, 0, Uri_HAS_USER_NAME, 0, &uri);
7187             ok(hr == E_NOTIMPL, "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x.\n",
7188                 hr, E_NOTIMPL);
7189             ok(!uri, "Error: Expected uri to be NULL, but was %p instead.\n", uri);
7190         }
7191         if(test) IUri_Release(test);
7192     }
7193     if(builder) IUriBuilder_Release(builder);
7194 }
7195
7196 /* Tests invalid args to the "Get*" functions. */
7197 static void test_IUriBuilder_GetInvalidArgs(void) {
7198     IUriBuilder *builder = NULL;
7199     HRESULT hr;
7200
7201     hr = pCreateIUriBuilder(NULL, 0, 0, &builder);
7202     ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7203     if(SUCCEEDED(hr)) {
7204         LPCWSTR received = (void*) 0xdeadbeef;
7205         DWORD len = -1, port = -1;
7206         BOOL set = -1;
7207
7208         hr = IUriBuilder_GetFragment(builder, NULL, NULL);
7209         ok(hr == E_POINTER, "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x.\n",
7210             hr, E_POINTER);
7211         hr = IUriBuilder_GetFragment(builder, NULL, &received);
7212         ok(hr == E_POINTER, "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x.\n",
7213             hr, E_POINTER);
7214         ok(!received, "Error: Expected received to be NULL, but was %p instead.\n", received);
7215         hr = IUriBuilder_GetFragment(builder, &len, NULL);
7216         ok(hr == E_POINTER, "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x.\n",
7217             hr, E_POINTER);
7218         ok(!len, "Error: Expected len to be 0, but was %d instead.\n", len);
7219
7220         hr = IUriBuilder_GetHost(builder, NULL, NULL);
7221         ok(hr == E_POINTER, "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x.\n",
7222             hr, E_POINTER);
7223         received = (void*) 0xdeadbeef;
7224         hr = IUriBuilder_GetHost(builder, NULL, &received);
7225         ok(hr == E_POINTER, "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x.\n",
7226             hr, E_POINTER);
7227         ok(!received, "Error: Expected received to be NULL, but was %p instead.\n", received);
7228         len = -1;
7229         hr = IUriBuilder_GetHost(builder, &len, NULL);
7230         ok(hr == E_POINTER, "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x.\n",
7231             hr, E_POINTER);
7232         ok(!len, "Error: Expected len to be 0, but was %d instead.\n", len);
7233
7234         hr = IUriBuilder_GetPassword(builder, NULL, NULL);
7235         ok(hr == E_POINTER, "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x.\n",
7236             hr, E_POINTER);
7237         received = (void*) 0xdeadbeef;
7238         hr = IUriBuilder_GetPassword(builder, NULL, &received);
7239         ok(hr == E_POINTER, "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x.\n",
7240             hr, E_POINTER);
7241         ok(!received, "Error: Expected received to be NULL, but was %p instead.\n", received);
7242         len = -1;
7243         hr = IUriBuilder_GetPassword(builder, &len, NULL);
7244         ok(hr == E_POINTER, "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x.\n",
7245             hr, E_POINTER);
7246         ok(!len, "Error: Expected len to be 0, but was %d instead.\n", len);
7247
7248         hr = IUriBuilder_GetPath(builder, NULL, NULL);
7249         ok(hr == E_POINTER, "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x.\n",
7250             hr, E_POINTER);
7251         received = (void*) 0xdeadbeef;
7252         hr = IUriBuilder_GetPath(builder, NULL, &received);
7253         ok(hr == E_POINTER, "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x.\n",
7254             hr, E_POINTER);
7255         ok(!received, "Error: Expected received to be NULL, but was %p instead.\n", received);
7256         len = -1;
7257         hr = IUriBuilder_GetPath(builder, &len, NULL);
7258         ok(hr == E_POINTER, "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x.\n",
7259             hr, E_POINTER);
7260         ok(!len, "Error: Expected len to be 0, but was %d instead.\n", len);
7261
7262         hr = IUriBuilder_GetPort(builder, NULL, NULL);
7263         ok(hr == E_POINTER, "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x.\n",
7264             hr, E_POINTER);
7265         hr = IUriBuilder_GetPort(builder, NULL, &port);
7266         ok(hr == E_POINTER, "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x.\n",
7267             hr, E_POINTER);
7268         ok(!port, "Error: Expected port to be 0, but was %d instead.\n", port);
7269         hr = IUriBuilder_GetPort(builder, &set, NULL);
7270         ok(hr == E_POINTER, "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x.\n",
7271             hr, E_POINTER);
7272         ok(!set, "Error: Expected set to be FALSE, but was %d instead.\n", set);
7273
7274         hr = IUriBuilder_GetQuery(builder, NULL, NULL);
7275         ok(hr == E_POINTER, "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x.\n",
7276             hr, E_POINTER);
7277         received = (void*) 0xdeadbeef;
7278         hr = IUriBuilder_GetQuery(builder, NULL, &received);
7279         ok(hr == E_POINTER, "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x.\n",
7280             hr, E_POINTER);
7281         ok(!received, "Error: Expected received to be NULL, but was %p instead.\n", received);
7282         len = -1;
7283         hr = IUriBuilder_GetQuery(builder, &len, NULL);
7284         ok(hr == E_POINTER, "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x.\n",
7285             hr, E_POINTER);
7286         ok(!len, "Error: Expected len to be 0, but was %d instead.\n", len);
7287
7288         hr = IUriBuilder_GetSchemeName(builder, NULL, NULL);
7289         ok(hr == E_POINTER, "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x.\n",
7290             hr, E_POINTER);
7291         received = (void*) 0xdeadbeef;
7292         hr = IUriBuilder_GetSchemeName(builder, NULL, &received);
7293         ok(hr == E_POINTER, "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x.\n",
7294             hr, E_POINTER);
7295         ok(!received, "Error: Expected received to be NULL, but was %p instead.\n", received);
7296         len = -1;
7297         hr = IUriBuilder_GetSchemeName(builder, &len, NULL);
7298         ok(hr == E_POINTER, "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x.\n",
7299             hr, E_POINTER);
7300         ok(!len, "Error: Expected len to be 0, but was %d instead.\n", len);
7301
7302         hr = IUriBuilder_GetUserName(builder, NULL, NULL);
7303         ok(hr == E_POINTER, "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x.\n",
7304             hr, E_POINTER);
7305         received = (void*) 0xdeadbeef;
7306         hr = IUriBuilder_GetUserName(builder, NULL, &received);
7307         ok(hr == E_POINTER, "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x.\n",
7308             hr, E_POINTER);
7309         ok(!received, "Error: Expected received to be NULL, but was %p instead.\n", received);
7310         len = -1;
7311         hr = IUriBuilder_GetUserName(builder, &len, NULL);
7312         ok(hr == E_POINTER, "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x.\n",
7313             hr, E_POINTER);
7314         ok(!len, "Error: Expected len to be 0, but was %d instead.\n", len);
7315     }
7316     if(builder) IUriBuilder_Release(builder);
7317 }
7318
7319 static void test_IUriBuilder_GetFragment(IUriBuilder *builder, const uri_builder_test *test,
7320                                          DWORD test_index) {
7321     HRESULT hr;
7322     DWORD i;
7323     LPCWSTR received = NULL;
7324     DWORD len = -1;
7325     const uri_builder_property *prop = NULL;
7326
7327     /* Check if the property was set earlier. */
7328     for(i = 0; i < sizeof(test->properties)/sizeof(test->properties[0]); ++i) {
7329         if(test->properties[i].change && test->properties[i].property == Uri_PROPERTY_FRAGMENT)
7330             prop = &(test->properties[i]);
7331     }
7332
7333     if(prop) {
7334         /* Use expected_value unless it's NULL, then use value. */
7335         LPCSTR expected = prop->expected_value ? prop->expected_value : prop->value;
7336         hr = IUriBuilder_GetFragment(builder, &len, &received);
7337         if(prop->todo) {
7338             todo_wine {
7339                 ok(hr == (expected ? S_OK : S_FALSE),
7340                     "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7341                     hr, (expected ? S_OK : S_FALSE), test_index);
7342             }
7343             if(SUCCEEDED(hr)) {
7344                 todo_wine {
7345                     ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
7346                         expected, wine_dbgstr_w(received), test_index);
7347                 }
7348                 todo_wine {
7349                     ok(lstrlen(expected) == len,
7350                         "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
7351                         lstrlen(expected), len, test_index);
7352                 }
7353             }
7354         } else {
7355             ok(hr == (expected ? S_OK : S_FALSE),
7356                 "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7357                 hr, (expected ? S_OK : S_FALSE), test_index);
7358             ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
7359                 expected, wine_dbgstr_w(received), test_index);
7360             ok(lstrlen(expected) == len,
7361                 "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
7362                 lstrlen(expected), len, test_index);
7363         }
7364     } else {
7365         /* The property wasn't set earlier, so it should return whatever
7366          * the base IUri contains (if anything).
7367          */
7368         IUri *uri = NULL;
7369         hr = IUriBuilder_GetIUri(builder, &uri);
7370         ok(hr == S_OK,
7371             "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7372             hr, S_OK, test_index);
7373         if(SUCCEEDED(hr)) {
7374             if(!uri) {
7375                 received = (void*) 0xdeadbeef;
7376                 len = -1;
7377
7378                 hr = IUriBuilder_GetFragment(builder, &len, &received);
7379                 ok(hr == S_FALSE,
7380                     "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7381                     hr, S_FALSE, test_index);
7382                 if(SUCCEEDED(hr)) {
7383                     ok(!len, "Error: Expected len to be 0, but was %d instead on uri_builder_tests[%d].\n",
7384                         len, test_index);
7385                     ok(!received, "Error: Expected received to be NULL, but was %p instead on uri_builder_tests[%d].\n",
7386                         received, test_index);
7387                 }
7388             } else {
7389                 BOOL has_prop = FALSE;
7390                 BSTR expected = NULL;
7391
7392                 hr = IUri_GetFragment(uri, &expected);
7393                 ok(SUCCEEDED(hr),
7394                     "Error: Expected IUri_GetFragment to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
7395                     hr, test_index);
7396                 has_prop = hr == S_OK;
7397
7398                 hr = IUriBuilder_GetFragment(builder, &len, &received);
7399                 if(has_prop) {
7400                     ok(hr == S_OK,
7401                         "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7402                         hr, S_OK, test_index);
7403                     if(SUCCEEDED(hr)) {
7404                         ok(!lstrcmpW(expected, received),
7405                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].\n",
7406                             wine_dbgstr_w(expected), wine_dbgstr_w(received), test_index);
7407                         ok(lstrlenW(expected) == len,
7408                             "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
7409                             lstrlenW(expected), len, test_index);
7410                     }
7411                 } else {
7412                     ok(hr == S_FALSE,
7413                         "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7414                         hr, S_FALSE, test_index);
7415                     if(SUCCEEDED(hr)) {
7416                         ok(!received, "Error: Expected received to be NULL on uri_builder_tests[%d].\n", test_index);
7417                         ok(!len, "Error: Expected the length to be 0, but was %d instead on uri_builder_tests[%d].\n",
7418                             len, test_index);
7419                     }
7420                 }
7421                 SysFreeString(expected);
7422             }
7423         }
7424         if(uri) IUri_Release(uri);
7425     }
7426 }
7427
7428 static void test_IUriBuilder_GetHost(IUriBuilder *builder, const uri_builder_test *test,
7429                                      DWORD test_index) {
7430     HRESULT hr;
7431     DWORD i;
7432     LPCWSTR received = NULL;
7433     DWORD len = -1;
7434     const uri_builder_property *prop = NULL;
7435
7436     /* Check if the property was set earlier. */
7437     for(i = 0; i < sizeof(test->properties)/sizeof(test->properties[0]); ++i) {
7438         if(test->properties[i].change && test->properties[i].property == Uri_PROPERTY_HOST)
7439             prop = &(test->properties[i]);
7440     }
7441
7442     if(prop) {
7443         /* Use expected_value unless it's NULL, then use value. */
7444         LPCSTR expected = prop->expected_value ? prop->expected_value : prop->value;
7445         hr = IUriBuilder_GetHost(builder, &len, &received);
7446         if(prop->todo) {
7447             todo_wine {
7448                 ok(hr == (expected ? S_OK : S_FALSE),
7449                     "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7450                     hr, (expected ? S_OK : S_FALSE), test_index);
7451             }
7452             if(SUCCEEDED(hr)) {
7453                 todo_wine {
7454                     ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
7455                         expected, wine_dbgstr_w(received), test_index);
7456                 }
7457                 todo_wine {
7458                     ok(lstrlen(expected) == len,
7459                         "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
7460                         lstrlen(expected), len, test_index);
7461                 }
7462             }
7463         } else {
7464             ok(hr == (expected ? S_OK : S_FALSE),
7465                 "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7466                 hr, (expected ? S_OK : S_FALSE), test_index);
7467             ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
7468                 expected, wine_dbgstr_w(received), test_index);
7469             ok(lstrlen(expected) == len,
7470                 "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
7471                 lstrlen(expected), len, test_index);
7472         }
7473     } else {
7474         /* The property wasn't set earlier, so it should return whatever
7475          * the base IUri contains (if anything).
7476          */
7477         IUri *uri = NULL;
7478         hr = IUriBuilder_GetIUri(builder, &uri);
7479         ok(hr == S_OK,
7480             "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7481             hr, S_OK, test_index);
7482         if(SUCCEEDED(hr)) {
7483             if(!uri) {
7484                 received = (void*) 0xdeadbeef;
7485                 len = -1;
7486
7487                 hr = IUriBuilder_GetHost(builder, &len, &received);
7488                 ok(hr == S_FALSE,
7489                     "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7490                     hr, S_FALSE, test_index);
7491                 if(SUCCEEDED(hr)) {
7492                     ok(!len, "Error: Expected len to be 0, but was %d instead on uri_builder_tests[%d].\n",
7493                         len, test_index);
7494                     ok(!received, "Error: Expected received to be NULL, but was %p instead on uri_builder_tests[%d].\n",
7495                         received, test_index);
7496                 }
7497             } else {
7498                 BOOL has_prop = FALSE;
7499                 BSTR expected = NULL;
7500
7501                 hr = IUri_GetHost(uri, &expected);
7502                 ok(SUCCEEDED(hr),
7503                     "Error: Expected IUri_GetHost to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
7504                     hr, test_index);
7505                 has_prop = hr == S_OK;
7506
7507                 hr = IUriBuilder_GetHost(builder, &len, &received);
7508                 if(has_prop) {
7509                     ok(hr == S_OK,
7510                         "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7511                         hr, S_OK, test_index);
7512                     if(SUCCEEDED(hr)) {
7513                         ok(!lstrcmpW(expected, received),
7514                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].\n",
7515                             wine_dbgstr_w(expected), wine_dbgstr_w(received), test_index);
7516                         ok(lstrlenW(expected) == len,
7517                             "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
7518                             lstrlenW(expected), len, test_index);
7519                     }
7520                 } else {
7521                     ok(hr == S_FALSE,
7522                         "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7523                         hr, S_FALSE, test_index);
7524                     if(SUCCEEDED(hr)) {
7525                         ok(!received, "Error: Expected received to be NULL on uri_builder_tests[%d].\n", test_index);
7526                         ok(!len, "Error: Expected the length to be 0, but was %d instead on uri_builder_tests[%d].\n",
7527                             len, test_index);
7528                     }
7529                 }
7530                 SysFreeString(expected);
7531             }
7532         }
7533         if(uri) IUri_Release(uri);
7534     }
7535 }
7536
7537 static void test_IUriBuilder_GetPassword(IUriBuilder *builder, const uri_builder_test *test,
7538                                          DWORD test_index) {
7539     HRESULT hr;
7540     DWORD i;
7541     LPCWSTR received = NULL;
7542     DWORD len = -1;
7543     const uri_builder_property *prop = NULL;
7544
7545     /* Check if the property was set earlier. */
7546     for(i = 0; i < sizeof(test->properties)/sizeof(test->properties[0]); ++i) {
7547         if(test->properties[i].change && test->properties[i].property == Uri_PROPERTY_PASSWORD)
7548             prop = &(test->properties[i]);
7549     }
7550
7551     if(prop) {
7552         /* Use expected_value unless it's NULL, then use value. */
7553         LPCSTR expected = prop->expected_value ? prop->expected_value : prop->value;
7554         hr = IUriBuilder_GetPassword(builder, &len, &received);
7555         if(prop->todo) {
7556             todo_wine {
7557                 ok(hr == (expected ? S_OK : S_FALSE),
7558                     "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7559                     hr, (expected ? S_OK : S_FALSE), test_index);
7560             }
7561             if(SUCCEEDED(hr)) {
7562                 todo_wine {
7563                     ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
7564                         expected, wine_dbgstr_w(received), test_index);
7565                 }
7566                 todo_wine {
7567                     ok(lstrlen(expected) == len,
7568                         "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
7569                         lstrlen(expected), len, test_index);
7570                 }
7571             }
7572         } else {
7573             ok(hr == (expected ? S_OK : S_FALSE),
7574                 "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7575                 hr, (expected ? S_OK : S_FALSE), test_index);
7576             ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
7577                 expected, wine_dbgstr_w(received), test_index);
7578             ok(lstrlen(expected) == len,
7579                 "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
7580                 lstrlen(expected), len, test_index);
7581         }
7582     } else {
7583         /* The property wasn't set earlier, so it should return whatever
7584          * the base IUri contains (if anything).
7585          */
7586         IUri *uri = NULL;
7587         hr = IUriBuilder_GetIUri(builder, &uri);
7588         ok(hr == S_OK,
7589             "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7590             hr, S_OK, test_index);
7591         if(SUCCEEDED(hr)) {
7592             if(!uri) {
7593                 received = (void*) 0xdeadbeef;
7594                 len = -1;
7595
7596                 hr = IUriBuilder_GetPassword(builder, &len, &received);
7597                 ok(hr == S_FALSE,
7598                     "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7599                     hr, S_FALSE, test_index);
7600                 if(SUCCEEDED(hr)) {
7601                     ok(!len, "Error: Expected len to be 0, but was %d instead on uri_builder_tests[%d].\n",
7602                         len, test_index);
7603                     ok(!received, "Error: Expected received to be NULL, but was %p instead on uri_builder_tests[%d].\n",
7604                         received, test_index);
7605                 }
7606             } else {
7607                 BOOL has_prop = FALSE;
7608                 BSTR expected = NULL;
7609
7610                 hr = IUri_GetPassword(uri, &expected);
7611                 ok(SUCCEEDED(hr),
7612                     "Error: Expected IUri_GetPassword to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
7613                     hr, test_index);
7614                 has_prop = hr == S_OK;
7615
7616                 hr = IUriBuilder_GetPassword(builder, &len, &received);
7617                 if(has_prop) {
7618                     ok(hr == S_OK,
7619                         "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7620                         hr, S_OK, test_index);
7621                     if(SUCCEEDED(hr)) {
7622                         ok(!lstrcmpW(expected, received),
7623                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].\n",
7624                             wine_dbgstr_w(expected), wine_dbgstr_w(received), test_index);
7625                         ok(lstrlenW(expected) == len,
7626                             "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
7627                             lstrlenW(expected), len, test_index);
7628                     }
7629                 } else {
7630                     ok(hr == S_FALSE,
7631                         "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7632                         hr, S_FALSE, test_index);
7633                     if(SUCCEEDED(hr)) {
7634                         ok(!received, "Error: Expected received to be NULL on uri_builder_tests[%d].\n", test_index);
7635                         ok(!len, "Error: Expected the length to be 0, but was %d instead on uri_builder_tests[%d].\n",
7636                             len, test_index);
7637                     }
7638                 }
7639                 SysFreeString(expected);
7640             }
7641         }
7642         if(uri) IUri_Release(uri);
7643     }
7644 }
7645
7646 static void test_IUriBuilder_GetPath(IUriBuilder *builder, const uri_builder_test *test,
7647                                      DWORD test_index) {
7648     HRESULT hr;
7649     DWORD i;
7650     LPCWSTR received = NULL;
7651     DWORD len = -1;
7652     const uri_builder_property *prop = NULL;
7653
7654     /* Check if the property was set earlier. */
7655     for(i = 0; i < sizeof(test->properties)/sizeof(test->properties[0]); ++i) {
7656         if(test->properties[i].change && test->properties[i].property == Uri_PROPERTY_PATH)
7657             prop = &(test->properties[i]);
7658     }
7659
7660     if(prop) {
7661         /* Use expected_value unless it's NULL, then use value. */
7662         LPCSTR expected = prop->expected_value ? prop->expected_value : prop->value;
7663         hr = IUriBuilder_GetPath(builder, &len, &received);
7664         if(prop->todo) {
7665             todo_wine {
7666                 ok(hr == (expected ? S_OK : S_FALSE),
7667                     "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7668                     hr, (expected ? S_OK : S_FALSE), test_index);
7669             }
7670             if(SUCCEEDED(hr)) {
7671                 todo_wine {
7672                     ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
7673                         expected, wine_dbgstr_w(received), test_index);
7674                 }
7675                 todo_wine {
7676                     ok(lstrlen(expected) == len,
7677                         "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
7678                         lstrlen(expected), len, test_index);
7679                 }
7680             }
7681         } else {
7682             ok(hr == (expected ? S_OK : S_FALSE),
7683                 "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7684                 hr, (expected ? S_OK : S_FALSE), test_index);
7685             ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
7686                 expected, wine_dbgstr_w(received), test_index);
7687             ok(lstrlen(expected) == len,
7688                 "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
7689                 lstrlen(expected), len, test_index);
7690         }
7691     } else {
7692         /* The property wasn't set earlier, so it should return whatever
7693          * the base IUri contains (if anything).
7694          */
7695         IUri *uri = NULL;
7696         hr = IUriBuilder_GetIUri(builder, &uri);
7697         ok(hr == S_OK,
7698             "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7699             hr, S_OK, test_index);
7700         if(SUCCEEDED(hr)) {
7701             if(!uri) {
7702                 received = (void*) 0xdeadbeef;
7703                 len = -1;
7704
7705                 hr = IUriBuilder_GetPath(builder, &len, &received);
7706                 ok(hr == S_FALSE,
7707                     "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7708                     hr, S_FALSE, test_index);
7709                 if(SUCCEEDED(hr)) {
7710                     ok(!len, "Error: Expected len to be 0, but was %d instead on uri_builder_tests[%d].\n",
7711                         len, test_index);
7712                     ok(!received, "Error: Expected received to be NULL, but was %p instead on uri_builder_tests[%d].\n",
7713                         received, test_index);
7714                 }
7715             } else {
7716                 BOOL has_prop = FALSE;
7717                 BSTR expected = NULL;
7718
7719                 hr = IUri_GetPath(uri, &expected);
7720                 ok(SUCCEEDED(hr),
7721                     "Error: Expected IUri_GetPath to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
7722                     hr, test_index);
7723                 has_prop = hr == S_OK;
7724
7725                 hr = IUriBuilder_GetPath(builder, &len, &received);
7726                 if(has_prop) {
7727                     ok(hr == S_OK,
7728                         "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7729                         hr, S_OK, test_index);
7730                     if(SUCCEEDED(hr)) {
7731                         ok(!lstrcmpW(expected, received),
7732                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].\n",
7733                             wine_dbgstr_w(expected), wine_dbgstr_w(received), test_index);
7734                         ok(lstrlenW(expected) == len,
7735                             "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
7736                             lstrlenW(expected), len, test_index);
7737                     }
7738                 } else {
7739                     ok(hr == S_FALSE,
7740                         "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7741                         hr, S_FALSE, test_index);
7742                     if(SUCCEEDED(hr)) {
7743                         ok(!received, "Error: Expected received to be NULL on uri_builder_tests[%d].\n", test_index);
7744                         ok(!len, "Error: Expected the length to be 0, but was %d instead on uri_builder_tests[%d].\n",
7745                             len, test_index);
7746                     }
7747                 }
7748                 SysFreeString(expected);
7749             }
7750         }
7751         if(uri) IUri_Release(uri);
7752     }
7753 }
7754
7755 static void test_IUriBuilder_GetPort(IUriBuilder *builder, const uri_builder_test *test,
7756                                      DWORD test_index) {
7757     HRESULT hr;
7758     BOOL has_port = FALSE;
7759     DWORD received = -1;
7760
7761     if(test->port_prop.change) {
7762         DWORD expected = test->port_prop.value;
7763
7764         hr = IUriBuilder_GetPort(builder, &has_port, &received);
7765         if(test->port_prop.todo) {
7766             todo_wine {
7767                 ok(hr == S_OK,
7768                     "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7769                     hr, S_OK, test_index);
7770             }
7771             if(SUCCEEDED(hr)) {
7772                 todo_wine {
7773                     ok(has_port == test->port_prop.set,
7774                         "Error: Expected has_port to be %d but was %d instead on uri_builder_tests[%d].\n",
7775                         test->port_prop.set, has_port, test_index);
7776                 }
7777                 todo_wine {
7778                     ok(received == expected,
7779                         "Error: Expected received to be %d, but was %d instead on uri_builder_tests[%d].\n",
7780                         expected, received, test_index);
7781                 }
7782             }
7783         } else {
7784             ok(hr == S_OK,
7785                 "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7786                 hr, S_OK, test_index);
7787             ok(has_port == test->port_prop.set,
7788                 "Error: Expected has_port to be %d, but was %d instead on uri_builder_tests[%d].\n",
7789                 test->port_prop.set, has_port, test_index);
7790             ok(received == test->port_prop.value,
7791                 "Error: Expected port to be %d, but was %d instead on uri_builder_tests[%d].\n",
7792                 test->port_prop.value, received, test_index);
7793         }
7794     } else {
7795         IUri *uri = NULL;
7796
7797         hr = IUriBuilder_GetIUri(builder, &uri);
7798         ok(hr == S_OK,
7799             "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7800             hr, S_OK, test_index);
7801         if(SUCCEEDED(hr)) {
7802             if(!uri) {
7803                 hr = IUriBuilder_GetPort(builder, &has_port, &received);
7804                 ok(hr == S_OK,
7805                     "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7806                     hr, S_OK, test_index);
7807                 if(SUCCEEDED(hr)) {
7808                     ok(has_port == FALSE,
7809                         "Error: Expected has_port to be FALSE, but was %d instead on uri_builder_tests[%d].\n",
7810                         has_port, test_index);
7811                     ok(!received, "Error: Expected received to be 0, but was %d instead on uri_builder_tests[%d].\n",
7812                         received, test_index);
7813                 }
7814             } else {
7815                 DWORD expected;
7816
7817                 hr = IUri_GetPort(uri, &expected);
7818                 ok(SUCCEEDED(hr),
7819                     "Error: Expected IUri_Port to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
7820                     hr, test_index);
7821
7822                 hr = IUriBuilder_GetPort(builder, &has_port, &received);
7823                 ok(hr == S_OK,
7824                     "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7825                     hr, S_OK, test_index);
7826                 if(SUCCEEDED(hr)) {
7827                     ok(!has_port,
7828                         "Error: Expected has_port to be FALSE but was TRUE instead on uri_builder_tests[%d].\n",
7829                         test_index);
7830                     ok(received == expected,
7831                         "Error: Expected received to be %d, but was %d instead on uri_builder_tests[%d].\n",
7832                         expected, received, test_index);
7833                 }
7834             }
7835         }
7836         if(uri) IUri_Release(uri);
7837     }
7838 }
7839
7840 static void test_IUriBuilder_GetQuery(IUriBuilder *builder, const uri_builder_test *test,
7841                                       DWORD test_index) {
7842     HRESULT hr;
7843     DWORD i;
7844     LPCWSTR received = NULL;
7845     DWORD len = -1;
7846     const uri_builder_property *prop = NULL;
7847
7848     /* Check if the property was set earlier. */
7849     for(i = 0; i < sizeof(test->properties)/sizeof(test->properties[0]); ++i) {
7850         if(test->properties[i].change && test->properties[i].property == Uri_PROPERTY_QUERY)
7851             prop = &(test->properties[i]);
7852     }
7853
7854     if(prop) {
7855         /* Use expected_value unless it's NULL, then use value. */
7856         LPCSTR expected = prop->expected_value ? prop->expected_value : prop->value;
7857         hr = IUriBuilder_GetQuery(builder, &len, &received);
7858         if(prop->todo) {
7859             todo_wine {
7860                 ok(hr == (expected ? S_OK : S_FALSE),
7861                     "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7862                     hr, (expected ? S_OK : S_FALSE), test_index);
7863             }
7864             if(SUCCEEDED(hr)) {
7865                 todo_wine {
7866                     ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
7867                         expected, wine_dbgstr_w(received), test_index);
7868                 }
7869                 todo_wine {
7870                     ok(lstrlen(expected) == len,
7871                         "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
7872                         lstrlen(expected), len, test_index);
7873                 }
7874             }
7875         } else {
7876             ok(hr == (expected ? S_OK : S_FALSE),
7877                 "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7878                 hr, (expected ? S_OK : S_FALSE), test_index);
7879             ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
7880                 expected, wine_dbgstr_w(received), test_index);
7881             ok(lstrlen(expected) == len,
7882                 "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
7883                 lstrlen(expected), len, test_index);
7884         }
7885     } else {
7886         /* The property wasn't set earlier, so it should return whatever
7887          * the base IUri contains (if anything).
7888          */
7889         IUri *uri = NULL;
7890         hr = IUriBuilder_GetIUri(builder, &uri);
7891         ok(hr == S_OK,
7892             "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7893             hr, S_OK, test_index);
7894         if(SUCCEEDED(hr)) {
7895             if(!uri) {
7896                 received = (void*) 0xdeadbeef;
7897                 len = -1;
7898
7899                 hr = IUriBuilder_GetQuery(builder, &len, &received);
7900                 ok(hr == S_FALSE,
7901                     "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7902                     hr, S_FALSE, test_index);
7903                 if(SUCCEEDED(hr)) {
7904                     ok(!len, "Error: Expected len to be 0, but was %d instead on uri_builder_tests[%d].\n",
7905                         len, test_index);
7906                     ok(!received, "Error: Expected received to be NULL, but was %p instead on uri_builder_tests[%d].\n",
7907                         received, test_index);
7908                 }
7909             } else {
7910                 BOOL has_prop = FALSE;
7911                 BSTR expected = NULL;
7912
7913                 hr = IUri_GetQuery(uri, &expected);
7914                 ok(SUCCEEDED(hr),
7915                     "Error: Expected IUri_GetQuery to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
7916                     hr, test_index);
7917                 has_prop = hr == S_OK;
7918
7919                 hr = IUriBuilder_GetQuery(builder, &len, &received);
7920                 if(has_prop) {
7921                     ok(hr == S_OK,
7922                         "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7923                         hr, S_OK, test_index);
7924                     if(SUCCEEDED(hr)) {
7925                         ok(!lstrcmpW(expected, received),
7926                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].\n",
7927                             wine_dbgstr_w(expected), wine_dbgstr_w(received), test_index);
7928                         ok(lstrlenW(expected) == len,
7929                             "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
7930                             lstrlenW(expected), len, test_index);
7931                     }
7932                 } else {
7933                     ok(hr == S_FALSE,
7934                         "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7935                         hr, S_FALSE, test_index);
7936                     if(SUCCEEDED(hr)) {
7937                         ok(!received, "Error: Expected received to be NULL on uri_builder_tests[%d].\n", test_index);
7938                         ok(!len, "Error: Expected the length to be 0, but was %d instead on uri_builder_tests[%d].\n",
7939                             len, test_index);
7940                     }
7941                 }
7942                 SysFreeString(expected);
7943             }
7944         }
7945         if(uri) IUri_Release(uri);
7946     }
7947 }
7948
7949 static void test_IUriBuilder_GetSchemeName(IUriBuilder *builder, const uri_builder_test *test,
7950                                            DWORD test_index) {
7951     HRESULT hr;
7952     DWORD i;
7953     LPCWSTR received = NULL;
7954     DWORD len = -1;
7955     const uri_builder_property *prop = NULL;
7956
7957     /* Check if the property was set earlier. */
7958     for(i = 0; i < sizeof(test->properties)/sizeof(test->properties[0]); ++i) {
7959         if(test->properties[i].change && test->properties[i].property == Uri_PROPERTY_SCHEME_NAME)
7960             prop = &(test->properties[i]);
7961     }
7962
7963     if(prop) {
7964         /* Use expected_value unless it's NULL, then use value. */
7965         LPCSTR expected = prop->expected_value ? prop->expected_value : prop->value;
7966         hr = IUriBuilder_GetSchemeName(builder, &len, &received);
7967         if(prop->todo) {
7968             todo_wine {
7969                 ok(hr == (expected ? S_OK : S_FALSE),
7970                     "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7971                     hr, (expected ? S_OK : S_FALSE), test_index);
7972             }
7973             if(SUCCEEDED(hr)) {
7974                 todo_wine {
7975                     ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
7976                         expected, wine_dbgstr_w(received), test_index);
7977                 }
7978                 todo_wine {
7979                     ok(lstrlen(expected) == len,
7980                         "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
7981                         lstrlen(expected), len, test_index);
7982                 }
7983             }
7984         } else {
7985             ok(hr == (expected ? S_OK : S_FALSE),
7986                 "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7987                 hr, (expected ? S_OK : S_FALSE), test_index);
7988             ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
7989                 expected, wine_dbgstr_w(received), test_index);
7990             ok(lstrlen(expected) == len,
7991                 "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
7992                 lstrlen(expected), len, test_index);
7993         }
7994     } else {
7995         /* The property wasn't set earlier, so it should return whatever
7996          * the base IUri contains (if anything).
7997          */
7998         IUri *uri = NULL;
7999         hr = IUriBuilder_GetIUri(builder, &uri);
8000         ok(hr == S_OK,
8001             "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8002             hr, S_OK, test_index);
8003         if(SUCCEEDED(hr)) {
8004             if(!uri) {
8005                 received = (void*) 0xdeadbeef;
8006                 len = -1;
8007
8008                 hr = IUriBuilder_GetSchemeName(builder, &len, &received);
8009                 ok(hr == S_FALSE,
8010                     "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8011                     hr, S_FALSE, test_index);
8012                 if(SUCCEEDED(hr)) {
8013                     ok(!len, "Error: Expected len to be 0, but was %d instead on uri_builder_tests[%d].\n",
8014                         len, test_index);
8015                     ok(!received, "Error: Expected received to be NULL, but was %p instead on uri_builder_tests[%d].\n",
8016                         received, test_index);
8017                 }
8018             } else {
8019                 BOOL has_prop = FALSE;
8020                 BSTR expected = NULL;
8021
8022                 hr = IUri_GetSchemeName(uri, &expected);
8023                 ok(SUCCEEDED(hr),
8024                     "Error: Expected IUri_GetSchemeName to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
8025                     hr, test_index);
8026                 has_prop = hr == S_OK;
8027
8028                 hr = IUriBuilder_GetSchemeName(builder, &len, &received);
8029                 if(has_prop) {
8030                     ok(hr == S_OK,
8031                         "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8032                         hr, S_OK, test_index);
8033                     if(SUCCEEDED(hr)) {
8034                         ok(!lstrcmpW(expected, received),
8035                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].\n",
8036                             wine_dbgstr_w(expected), wine_dbgstr_w(received), test_index);
8037                         ok(lstrlenW(expected) == len,
8038                             "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8039                             lstrlenW(expected), len, test_index);
8040                     }
8041                 } else {
8042                     ok(hr == S_FALSE,
8043                         "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8044                         hr, S_FALSE, test_index);
8045                     if(SUCCEEDED(hr)) {
8046                         ok(!received, "Error: Expected received to be NULL on uri_builder_tests[%d].\n", test_index);
8047                         ok(!len, "Error: Expected the length to be 0, but was %d instead on uri_builder_tests[%d].\n",
8048                             len, test_index);
8049                     }
8050                 }
8051                 SysFreeString(expected);
8052             }
8053         }
8054         if(uri) IUri_Release(uri);
8055     }
8056 }
8057
8058 static void test_IUriBuilder_GetUserName(IUriBuilder *builder, const uri_builder_test *test,
8059                                          DWORD test_index) {
8060     HRESULT hr;
8061     DWORD i;
8062     LPCWSTR received = NULL;
8063     DWORD len = -1;
8064     const uri_builder_property *prop = NULL;
8065
8066     /* Check if the property was set earlier. */
8067     for(i = 0; i < sizeof(test->properties)/sizeof(test->properties[0]); ++i) {
8068         if(test->properties[i].change && test->properties[i].property == Uri_PROPERTY_USER_NAME)
8069             prop = &(test->properties[i]);
8070     }
8071
8072     if(prop && prop->value && *prop->value) {
8073         /* Use expected_value unless it's NULL, then use value. */
8074         LPCSTR expected = prop->expected_value ? prop->expected_value : prop->value;
8075         hr = IUriBuilder_GetUserName(builder, &len, &received);
8076         if(prop->todo) {
8077             todo_wine {
8078                 ok(hr == (expected ? S_OK : S_FALSE),
8079                     "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8080                     hr, (expected ? S_OK : S_FALSE), test_index);
8081             }
8082             if(SUCCEEDED(hr)) {
8083                 todo_wine {
8084                     ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
8085                         expected, wine_dbgstr_w(received), test_index);
8086                 }
8087                 todo_wine {
8088                     ok(lstrlen(expected) == len,
8089                         "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8090                         lstrlen(expected), len, test_index);
8091                 }
8092             }
8093         } else {
8094             ok(hr == (expected ? S_OK : S_FALSE),
8095                 "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8096                 hr, (expected ? S_OK : S_FALSE), test_index);
8097             ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
8098                 expected, wine_dbgstr_w(received), test_index);
8099             ok(lstrlen(expected) == len,
8100                 "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8101                 lstrlen(expected), len, test_index);
8102         }
8103     } else {
8104         /* The property wasn't set earlier, so it should return whatever
8105          * the base IUri contains (if anything).
8106          */
8107         IUri *uri = NULL;
8108         hr = IUriBuilder_GetIUri(builder, &uri);
8109         ok(hr == S_OK,
8110             "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8111             hr, S_OK, test_index);
8112         if(SUCCEEDED(hr)) {
8113             if(!uri) {
8114                 received = (void*) 0xdeadbeef;
8115                 len = -1;
8116
8117                 hr = IUriBuilder_GetUserName(builder, &len, &received);
8118                 ok(hr == S_FALSE,
8119                     "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8120                     hr, S_FALSE, test_index);
8121                 if(SUCCEEDED(hr)) {
8122                     ok(!len, "Error: Expected len to be 0, but was %d instead on uri_builder_tests[%d].\n",
8123                         len, test_index);
8124                     ok(!received, "Error: Expected received to be NULL, but was %p instead on uri_builder_tests[%d].\n",
8125                         received, test_index);
8126                 }
8127             } else {
8128                 BSTR expected = NULL;
8129                 BOOL has_prop = FALSE;
8130
8131                 hr = IUri_GetUserName(uri, &expected);
8132                 ok(SUCCEEDED(hr),
8133                     "Error: Expected IUri_GetUserName to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
8134                     hr, test_index);
8135                 has_prop = hr == S_OK;
8136
8137                 hr = IUriBuilder_GetUserName(builder, &len, &received);
8138                 if(has_prop) {
8139                     ok(hr == S_OK,
8140                         "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8141                         hr, S_OK, test_index);
8142                     if(SUCCEEDED(hr)) {
8143                         ok(!lstrcmpW(expected, received),
8144                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].\n",
8145                             wine_dbgstr_w(expected), wine_dbgstr_w(received), test_index);
8146                         ok(lstrlenW(expected) == len,
8147                             "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8148                             lstrlenW(expected), len, test_index);
8149                     }
8150                 } else {
8151                     ok(hr == S_FALSE,
8152                         "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8153                         hr, S_FALSE, test_index);
8154                     if(SUCCEEDED(hr)) {
8155                         ok(!received, "Error: Expected received to be NULL on uri_builder_tests[%d].\n", test_index);
8156                         ok(!len, "Error: Expected the length to be 0, but was %d instead on uri_builder_tests[%d].\n",
8157                             len, test_index);
8158                     }
8159                 }
8160                 SysFreeString(expected);
8161             }
8162         }
8163         if(uri) IUri_Release(uri);
8164     }
8165 }
8166
8167 /* Tests IUriBuilder functions. */
8168 static void test_IUriBuilder(void) {
8169     HRESULT hr;
8170     IUriBuilder *builder;
8171     DWORD i;
8172
8173     for(i = 0; i < sizeof(uri_builder_tests)/sizeof(uri_builder_tests[0]); ++i) {
8174         IUri *uri = NULL;
8175         uri_builder_test test = uri_builder_tests[i];
8176         LPWSTR uriW = NULL;
8177
8178         if(test.uri) {
8179             uriW = a2w(test.uri);
8180             hr = pCreateUri(uriW, test.create_flags, 0, &uri);
8181             ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8182                 hr, S_OK, i);
8183             if(FAILED(hr)) continue;
8184         }
8185         hr = pCreateIUriBuilder(uri, 0, 0, &builder);
8186         if(test.create_builder_todo) {
8187             todo_wine {
8188                 ok(hr == test.create_builder_expected,
8189                     "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8190                     hr, test.create_builder_expected, i);
8191             }
8192         } else {
8193             ok(hr == test.create_builder_expected,
8194                 "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8195                 hr, test.create_builder_expected, i);
8196         }
8197         if(SUCCEEDED(hr)) {
8198             DWORD j;
8199             BOOL modified = FALSE, received = FALSE;
8200
8201             /* Perform all the string property changes. */
8202             for(j = 0; j < URI_BUILDER_STR_PROPERTY_COUNT; ++j) {
8203                 uri_builder_property prop = test.properties[j];
8204                 if(prop.change) {
8205                     change_property(builder, &prop, i);
8206                     if(prop.property != Uri_PROPERTY_SCHEME_NAME &&
8207                        prop.property != Uri_PROPERTY_HOST)
8208                         modified = TRUE;
8209                     else if(prop.value && *prop.value)
8210                         modified = TRUE;
8211                     else if(prop.value && !*prop.value && prop.property == Uri_PROPERTY_HOST)
8212                         /* Host name property can't be NULL, but it can be empty. */
8213                         modified = TRUE;
8214                 }
8215             }
8216
8217             if(test.port_prop.change) {
8218                 hr = IUriBuilder_SetPort(builder, test.port_prop.set, test.port_prop.value);
8219                 modified = TRUE;
8220                 if(test.port_prop.todo) {
8221                     todo_wine {
8222                         ok(hr == test.port_prop.expected,
8223                             "Error: IUriBuilder_SetPort returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8224                             hr, test.port_prop.expected, i);
8225                     }
8226                 } else {
8227                     ok(hr == test.port_prop.expected,
8228                         "Error: IUriBuilder_SetPort returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8229                         hr, test.port_prop.expected, i);
8230                 }
8231             }
8232
8233             hr = IUriBuilder_HasBeenModified(builder, &received);
8234             ok(hr == S_OK,
8235                 "Error IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8236                 hr, S_OK, i);
8237             if(SUCCEEDED(hr))
8238                 ok(received == modified,
8239                     "Error: Expected received to be %d but was %d instead on uri_builder_tests[%d].\n",
8240                     modified, received, i);
8241
8242             /* Test the "Get*" functions. */
8243             test_IUriBuilder_GetFragment(builder, &test, i);
8244             test_IUriBuilder_GetHost(builder, &test, i);
8245             test_IUriBuilder_GetPassword(builder, &test, i);
8246             test_IUriBuilder_GetPath(builder, &test, i);
8247             test_IUriBuilder_GetPort(builder, &test, i);
8248             test_IUriBuilder_GetQuery(builder, &test, i);
8249             test_IUriBuilder_GetSchemeName(builder, &test, i);
8250             test_IUriBuilder_GetUserName(builder, &test, i);
8251
8252             test_IUriBuilder_CreateUri(builder, &test, i);
8253             test_IUriBuilder_CreateUriSimple(builder, &test, i);
8254             test_IUriBuilder_CreateUriWithFlags(builder, &test, i);
8255         }
8256         if(builder) IUriBuilder_Release(builder);
8257         if(uri) IUri_Release(uri);
8258         heap_free(uriW);
8259     }
8260 }
8261
8262 static void test_IUriBuilder_HasBeenModified(void) {
8263     HRESULT hr;
8264     IUriBuilder *builder = NULL;
8265
8266     hr = pCreateIUriBuilder(NULL, 0, 0, &builder);
8267     ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8268     if(SUCCEEDED(hr)) {
8269         static const WCHAR hostW[] = {'g','o','o','g','l','e','.','c','o','m',0};
8270         IUri *uri = NULL;
8271         BOOL received;
8272
8273         hr = IUriBuilder_HasBeenModified(builder, NULL);
8274         ok(hr == E_POINTER, "Error: IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x.\n",
8275             hr, E_POINTER);
8276
8277         hr = IUriBuilder_SetHost(builder, hostW);
8278         ok(hr == S_OK, "Error: IUriBuilder_SetHost returned 0x%08x, expected 0x%08x.\n",
8279             hr, S_OK);
8280
8281         hr = IUriBuilder_HasBeenModified(builder, &received);
8282         ok(hr == S_OK, "Error: IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x.\n",
8283             hr, S_OK);
8284         if(SUCCEEDED(hr))
8285             ok(received == TRUE, "Error: Expected received to be TRUE.\n");
8286
8287         hr = pCreateUri(http_urlW, 0, 0, &uri);
8288         ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8289         if(SUCCEEDED(hr)) {
8290             LPCWSTR prop;
8291             DWORD len = -1;
8292
8293             hr = IUriBuilder_SetIUri(builder, uri);
8294             ok(hr == S_OK, "Error: IUriBuilder_SetIUri returned 0x%08x, expected 0x%08x.\n",
8295                 hr, S_OK);
8296
8297             hr = IUriBuilder_HasBeenModified(builder, &received);
8298             ok(hr == S_OK, "Error: IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x.\n",
8299                 hr, S_OK);
8300             if(SUCCEEDED(hr))
8301                 ok(received == FALSE, "Error: Expected received to be FALSE.\n");
8302
8303             /* Test what happens with you call SetIUri with the same IUri again. */
8304             hr = IUriBuilder_SetHost(builder, hostW);
8305             ok(hr == S_OK, "Error: IUriBuilder_SetHost returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8306
8307             hr = IUriBuilder_HasBeenModified(builder, &received);
8308             ok(hr == S_OK, "Error: IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x.\n",
8309                 hr, S_OK);
8310             if(SUCCEEDED(hr))
8311                 ok(received == TRUE, "Error: Expected received to be TRUE.\n");
8312
8313             hr = IUriBuilder_SetIUri(builder, uri);
8314             ok(hr == S_OK, "Error: IUriBuilder_SetIUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8315
8316             /* IUriBuilder already had 'uri' as it's IUri property and so Windows doesn't
8317              * reset any of the changes that were made to the IUriBuilder.
8318              */
8319             hr = IUriBuilder_HasBeenModified(builder, &received);
8320             ok(hr == S_OK, "Error: IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8321             if(SUCCEEDED(hr))
8322                 ok(received == TRUE, "Error: Expected received to be TRUE.\n");
8323
8324             hr = IUriBuilder_GetHost(builder, &len, &prop);
8325             ok(hr == S_OK, "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8326             if(SUCCEEDED(hr)) {
8327                 ok(!lstrcmpW(prop, hostW), "Error: Expected %s but got %s instead.\n",
8328                     wine_dbgstr_w(hostW), wine_dbgstr_w(prop));
8329                 ok(len == lstrlenW(hostW), "Error: Expected len to be %d, but was %d instead.\n",
8330                     lstrlenW(hostW), len);
8331             }
8332
8333             hr = IUriBuilder_SetIUri(builder, NULL);
8334             ok(hr == S_OK, "Error: IUriBuilder_SetIUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8335
8336             hr = IUriBuilder_SetHost(builder, hostW);
8337             ok(hr == S_OK, "Error: IUriBuilder_SetHost returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8338             hr = IUriBuilder_HasBeenModified(builder, &received);
8339             ok(hr == S_OK, "Error: IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x.\n",
8340                 hr, S_OK);
8341             if(SUCCEEDED(hr))
8342                 ok(received == TRUE, "Error: Expected received to be TRUE.\n");
8343
8344             hr = IUriBuilder_SetIUri(builder, NULL);
8345             ok(hr == S_OK, "Error: IUriBuilder_SetIUri returned 0x%08x, expected 0x%09x.\n", hr, S_OK);
8346
8347             hr = IUriBuilder_HasBeenModified(builder, &received);
8348             ok(hr == S_OK, "Error: IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x.\n",
8349                 hr, S_OK);
8350             if(SUCCEEDED(hr))
8351                 ok(received == TRUE, "Error: Expected received to be TRUE.\n");
8352
8353             hr = IUriBuilder_GetHost(builder, &len, &prop);
8354             ok(hr == S_OK, "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8355             if(SUCCEEDED(hr)) {
8356                 ok(!lstrcmpW(prop, hostW), "Error: Expected %s but got %s instead.\n",
8357                     wine_dbgstr_w(hostW), wine_dbgstr_w(prop));
8358                 ok(len == lstrlenW(hostW), "Error: Expected len to %d, but was %d instead.\n",
8359                     lstrlenW(hostW), len);
8360             }
8361         }
8362         if(uri) IUri_Release(uri);
8363     }
8364     if(builder) IUriBuilder_Release(builder);
8365 }
8366
8367 /* Test IUriBuilder {Get,Set}IUri functions. */
8368 static void test_IUriBuilder_IUriProperty(void) {
8369     IUriBuilder *builder = NULL;
8370     HRESULT hr;
8371
8372     hr = pCreateIUriBuilder(NULL, 0, 0, &builder);
8373     ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8374     if(SUCCEEDED(hr)) {
8375         IUri *uri = NULL;
8376
8377         hr = IUriBuilder_GetIUri(builder, NULL);
8378         ok(hr == E_POINTER, "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x.\n",
8379             hr, E_POINTER);
8380
8381         hr = pCreateUri(http_urlW, 0, 0, &uri);
8382         if(SUCCEEDED(hr)) {
8383             IUri *test = NULL;
8384             ULONG cur_count, orig_count;
8385
8386             /* IUriBuilder doesn't clone the IUri, it use the same IUri. */
8387             orig_count = get_refcnt(uri);
8388             hr = IUriBuilder_SetIUri(builder, uri);
8389             cur_count = get_refcnt(uri);
8390             if(SUCCEEDED(hr))
8391                 ok(cur_count == orig_count+1, "Error: Expected uri ref count to be %d, but was %d instead.\n",
8392                     orig_count+1, cur_count);
8393
8394             hr = IUriBuilder_SetIUri(builder, NULL);
8395             cur_count = get_refcnt(uri);
8396             if(SUCCEEDED(hr))
8397                 ok(cur_count == orig_count, "Error: Expected uri ref count to be %d, but was %d instead.\n",
8398                     orig_count, cur_count);
8399
8400             /* CreateUri* functions will return back the same IUri if nothing has changed. */
8401             hr = IUriBuilder_SetIUri(builder, uri);
8402             ok(hr == S_OK, "Error: IUriBuilder_SetIUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8403             orig_count = get_refcnt(uri);
8404
8405             hr = IUriBuilder_CreateUri(builder, 0, 0, 0, &test);
8406             ok(hr == S_OK, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8407             if(SUCCEEDED(hr)) {
8408                 cur_count = get_refcnt(uri);
8409                 ok(cur_count == orig_count+1, "Error: Expected uri ref count to be %d, but was %d instead.\n",
8410                     orig_count+1, cur_count);
8411                 ok(test == uri, "Error: Expected test to be %p, but was %p instead.\n",
8412                     uri, test);
8413             }
8414             if(test) IUri_Release(test);
8415
8416             test = NULL;
8417             hr = IUriBuilder_CreateUri(builder, -1, 0, 0, &test);
8418             ok(hr == S_OK, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8419             if(SUCCEEDED(hr)) {
8420                 cur_count = get_refcnt(uri);
8421                 ok(cur_count == orig_count+1, "Error: Expected uri ref count to be %d, but was %d instead.\n",
8422                     orig_count+1, cur_count);
8423                 ok(test == uri, "Error: Expected test to be %p, but was %p instead.\n", uri, test);
8424             }
8425             if(test) IUri_Release(test);
8426
8427             /* Doesn't return the same IUri, if the flag combination is different then the one that created
8428              * the base IUri.
8429              */
8430             test = NULL;
8431             hr = IUriBuilder_CreateUri(builder, Uri_CREATE_ALLOW_RELATIVE, 0, 0, &test);
8432             ok(hr == S_OK, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8433             if(SUCCEEDED(hr))
8434                 ok(test != uri, "Error: Wasn't expecting 'test' to be 'uri'\n");
8435
8436             if(test) IUri_Release(test);
8437
8438             /* Still returns the same IUri, even though the base one wasn't created with CREATE_CANONICALIZE
8439              * explicitly set (because it's a default flags).
8440              */
8441             test = NULL;
8442             hr = IUriBuilder_CreateUri(builder, Uri_CREATE_CANONICALIZE, 0, 0, &test);
8443             ok(hr == S_OK, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8444             if(SUCCEEDED(hr)) {
8445                 cur_count = get_refcnt(uri);
8446                 ok(cur_count == orig_count+1, "Error: Expected uri ref count to be %d, but was %d instead.\n",
8447                     orig_count+1, cur_count);
8448                 ok(test == uri, "Error: Expected 'test' to be %p, but was %p instead.\n", uri, test);
8449             }
8450             if(test) IUri_Release(test);
8451
8452             test = NULL;
8453             hr = IUriBuilder_CreateUriSimple(builder, 0, 0, &test);
8454             ok(hr == S_OK, "Error: IUriBuilder_CreateUriSimple returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8455             if(SUCCEEDED(hr)) {
8456                 cur_count = get_refcnt(uri);
8457                 ok(cur_count == orig_count+1, "Error: Expected uri ref count to be %d, but was %d instead.\n",
8458                     orig_count+1, cur_count);
8459                 ok(test == uri, "Error: Expected test to be %p, but was %p instead.\n", uri, test);
8460             }
8461             if(test) IUri_Release(test);
8462
8463             test = NULL;
8464             hr = IUriBuilder_CreateUriWithFlags(builder, 0, 0, 0, 0, &test);
8465             ok(hr == S_OK, "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x.\n",
8466                 hr, S_OK);
8467             if(SUCCEEDED(hr)) {
8468                 cur_count = get_refcnt(uri);
8469                 ok(cur_count == orig_count+1, "Error: Expected uri ref count to be %d, but was %d instead.\n",
8470                     orig_count+1, cur_count);
8471                 ok(test == uri, "Error: Expected test to be %p, but was %p instead.\n", uri, test);
8472             }
8473             if(test) IUri_Release(test);
8474
8475             /* Doesn't return the same IUri, if the flag combination is different then the one that created
8476              * the base IUri.
8477              */
8478             test = NULL;
8479             hr = IUriBuilder_CreateUriWithFlags(builder, Uri_CREATE_ALLOW_RELATIVE, 0, 0, 0, &test);
8480             ok(hr == S_OK, "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8481             if(SUCCEEDED(hr))
8482                 ok(test != uri, "Error: Wasn't expecting 'test' to be 'uri'\n");
8483
8484             if(test) IUri_Release(test);
8485
8486             /* Still returns the same IUri, even though the base one wasn't created with CREATE_CANONICALIZE
8487              * explicitly set (because it's a default flags).
8488              */
8489             test = NULL;
8490             hr = IUriBuilder_CreateUriWithFlags(builder, Uri_CREATE_CANONICALIZE, 0, 0, 0, &test);
8491             ok(hr == S_OK, "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8492             if(SUCCEEDED(hr)) {
8493                 cur_count = get_refcnt(uri);
8494                 ok(cur_count == orig_count+1, "Error: Expected uri ref count to be %d, but was %d instead.\n",
8495                     orig_count+1, cur_count);
8496                 ok(test == uri, "Error: Expected 'test' to be %p, but was %p instead.\n", uri, test);
8497             }
8498             if(test) IUri_Release(test);
8499         }
8500         if(uri) IUri_Release(uri);
8501     }
8502     if(builder) IUriBuilder_Release(builder);
8503 }
8504
8505 static void test_IUriBuilder_RemoveProperties(void) {
8506     IUriBuilder *builder = NULL;
8507     HRESULT hr;
8508     DWORD i;
8509
8510     hr = pCreateIUriBuilder(NULL, 0, 0, &builder);
8511     ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8512     if(SUCCEEDED(hr)) {
8513         /* Properties that can't be removed. */
8514         const DWORD invalid = Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_RAW_URI|Uri_HAS_HOST_TYPE|
8515                               Uri_HAS_SCHEME|Uri_HAS_ZONE;
8516
8517         for(i = Uri_PROPERTY_STRING_START; i <= Uri_PROPERTY_DWORD_LAST; ++i) {
8518             hr = IUriBuilder_RemoveProperties(builder, i << 1);
8519             if((i << 1) & invalid) {
8520                 ok(hr == E_INVALIDARG,
8521                     "Error: IUriBuilder_RemoveProperties returned 0x%08x, expected 0x%08x with prop=%d.\n",
8522                     hr, E_INVALIDARG, i);
8523             } else {
8524                 ok(hr == S_OK,
8525                     "Error: IUriBuilder_RemoveProperties returned 0x%08x, expected 0x%08x with prop=%d.\n",
8526                     hr, S_OK, i);
8527             }
8528         }
8529
8530         /* Also doesn't accept anything that's outside the range of the
8531          * Uri_HAS flags.
8532          */
8533         hr = IUriBuilder_RemoveProperties(builder, (Uri_PROPERTY_DWORD_LAST+1) << 1);
8534         ok(hr == E_INVALIDARG, "Error: IUriBuilder_RemoveProperties returned 0x%08x, expected 0x%08x.\n",
8535             hr, E_INVALIDARG);
8536     }
8537     if(builder) IUriBuilder_Release(builder);
8538
8539     for(i = 0; i < sizeof(uri_builder_remove_tests)/sizeof(uri_builder_remove_tests[0]); ++i) {
8540         uri_builder_remove_test test = uri_builder_remove_tests[i];
8541         IUri *uri = NULL;
8542         LPWSTR uriW;
8543
8544         uriW = a2w(test.uri);
8545         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
8546         if(SUCCEEDED(hr)) {
8547             builder = NULL;
8548
8549             hr = pCreateIUriBuilder(uri, 0, 0, &builder);
8550             if(test.create_builder_todo) {
8551                 todo_wine {
8552                     ok(hr == test.create_builder_expected,
8553                         "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x on test %d.\n",
8554                         hr, test.create_builder_expected, i);
8555                 }
8556             } else {
8557                 ok(hr == test.create_builder_expected,
8558                     "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x on test %d.\n",
8559                     hr, test.create_builder_expected, i);
8560             }
8561             if(SUCCEEDED(hr)) {
8562                 hr = IUriBuilder_RemoveProperties(builder, test.remove_properties);
8563                 if(test.remove_todo) {
8564                     todo_wine {
8565                         ok(hr == test.remove_expected,
8566                             "Error: IUriBuilder_RemoveProperties returned 0x%08x, expected 0x%08x on test %d.\n",
8567                             hr, test.remove_expected, i);
8568                     }
8569                 } else {
8570                     ok(hr == test.remove_expected,
8571                         "Error: IUriBuilder returned 0x%08x, expected 0x%08x on test %d.\n",
8572                         hr, test.remove_expected, i);
8573                 }
8574                 if(SUCCEEDED(hr)) {
8575                     IUri *result = NULL;
8576
8577                     hr = IUriBuilder_CreateUri(builder, test.expected_flags, 0, 0, &result);
8578                     if(test.expected_todo) {
8579                         todo_wine {
8580                             ok(hr == test.expected_hres,
8581                                 "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x on test %d.\n",
8582                                 hr, test.expected_hres, i);
8583                         }
8584                     } else {
8585                         ok(hr == test.expected_hres,
8586                             "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x on test %d.\n",
8587                             hr, test.expected_hres, i);
8588                     }
8589                     if(SUCCEEDED(hr)) {
8590                         BSTR received = NULL;
8591
8592                         hr = IUri_GetAbsoluteUri(result, &received);
8593                         ok(!strcmp_aw(test.expected_uri, received),
8594                             "Error: Expected %s but got %s instead on test %d.\n",
8595                             test.expected_uri, wine_dbgstr_w(received), i);
8596                         SysFreeString(received);
8597                     }
8598                     if(result) IUri_Release(result);
8599                 }
8600             }
8601             if(builder) IUriBuilder_Release(builder);
8602         }
8603         if(uri) IUri_Release(uri);
8604         heap_free(uriW);
8605     }
8606 }
8607
8608 static void test_IUriBuilder_Misc(void) {
8609     HRESULT hr;
8610     IUri *uri;
8611
8612     hr = pCreateUri(http_urlW, 0, 0, &uri);
8613     if(SUCCEEDED(hr)) {
8614         IUriBuilder *builder;
8615
8616         hr = pCreateIUriBuilder(uri, 0, 0, &builder);
8617         ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8618         if(SUCCEEDED(hr)) {
8619             BOOL has = -1;
8620             DWORD port = -1;
8621
8622             hr = IUriBuilder_GetPort(builder, &has, &port);
8623             ok(hr == S_OK, "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8624             if(SUCCEEDED(hr)) {
8625                 /* 'has' will be set to FALSE, even though uri had a port. */
8626                 ok(has == FALSE, "Error: Expected 'has' to be FALSE, was %d instead.\n", has);
8627                 /* Still sets 'port' to 80. */
8628                 ok(port == 80, "Error: Expected the port to be 80, but, was %d instead.\n", port);
8629             }
8630         }
8631         if(builder) IUriBuilder_Release(builder);
8632     }
8633     if(uri) IUri_Release(uri);
8634 }
8635
8636 START_TEST(uri) {
8637     HMODULE hurlmon;
8638
8639     hurlmon = GetModuleHandle("urlmon.dll");
8640     pCreateUri = (void*) GetProcAddress(hurlmon, "CreateUri");
8641     pCreateUriWithFragment = (void*) GetProcAddress(hurlmon, "CreateUriWithFragment");
8642     pCreateIUriBuilder = (void*) GetProcAddress(hurlmon, "CreateIUriBuilder");
8643
8644     if(!pCreateUri) {
8645         win_skip("CreateUri is not present, skipping tests.\n");
8646         return;
8647     }
8648
8649     trace("test CreateUri invalid flags...\n");
8650     test_CreateUri_InvalidFlags();
8651
8652     trace("test CreateUri invalid args...\n");
8653     test_CreateUri_InvalidArgs();
8654
8655     trace("test CreateUri invalid URIs...\n");
8656     test_CreateUri_InvalidUri();
8657
8658     trace("test IUri_GetPropertyBSTR...\n");
8659     test_IUri_GetPropertyBSTR();
8660
8661     trace("test IUri_GetPropertyDWORD...\n");
8662     test_IUri_GetPropertyDWORD();
8663
8664     trace("test IUri_GetStrProperties...\n");
8665     test_IUri_GetStrProperties();
8666
8667     trace("test IUri_GetDwordProperties...\n");
8668     test_IUri_GetDwordProperties();
8669
8670     trace("test IUri_GetPropertyLength...\n");
8671     test_IUri_GetPropertyLength();
8672
8673     trace("test IUri_GetProperties...\n");
8674     test_IUri_GetProperties();
8675
8676     trace("test IUri_HasProperty...\n");
8677     test_IUri_HasProperty();
8678
8679     trace("test IUri_IsEqual...\n");
8680     test_IUri_IsEqual();
8681
8682     trace("test CreateUriWithFragment invalid args...\n");
8683     test_CreateUriWithFragment_InvalidArgs();
8684
8685     trace("test CreateUriWithFragment invalid flags...\n");
8686     test_CreateUriWithFragment_InvalidFlags();
8687
8688     trace("test CreateUriWithFragment...\n");
8689     test_CreateUriWithFragment();
8690
8691     trace("test CreateIUriBuilder...\n");
8692     test_CreateIUriBuilder();
8693
8694     trace("test IUriBuilder_CreateInvalidArgs...\n");
8695     test_IUriBuilder_CreateInvalidArgs();
8696
8697     trace("test IUriBuilder...\n");
8698     test_IUriBuilder();
8699
8700     trace("test IUriBuilder_GetInvalidArgs...\n");
8701     test_IUriBuilder_GetInvalidArgs();
8702
8703     trace("test IUriBuilder_HasBeenModified...\n");
8704     test_IUriBuilder_HasBeenModified();
8705
8706     trace("test IUriBuilder_IUriProperty...\n");
8707     test_IUriBuilder_IUriProperty();
8708
8709     trace("test IUriBuilder_RemoveProperties...\n");
8710     test_IUriBuilder_RemoveProperties();
8711
8712     trace("test IUriBuilder miscellaneous...\n");
8713     test_IUriBuilder_Misc();
8714 }