urlmon: Implemented a path parser for hierarchical URIs.
[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 /*
22  * IUri testing framework goals:
23  *  - Test invalid args
24  *      - invalid flags
25  *      - invalid args (IUri, uri string)
26  *  - Test parsing for components when no canonicalization occurs
27  *  - Test parsing for components when canonicalization occurs.
28  *  - More tests...
29  */
30
31 #include <wine/test.h>
32 #include <stdarg.h>
33 #include <stddef.h>
34
35 #define COBJMACROS
36
37 #include "windef.h"
38 #include "winbase.h"
39 #include "urlmon.h"
40 #include "shlwapi.h"
41
42 #define URI_STR_PROPERTY_COUNT Uri_PROPERTY_STRING_LAST+1
43 #define URI_DWORD_PROPERTY_COUNT (Uri_PROPERTY_DWORD_LAST - Uri_PROPERTY_DWORD_START)+1
44
45 static HRESULT (WINAPI *pCreateUri)(LPCWSTR, DWORD, DWORD_PTR, IUri**);
46
47 static const WCHAR http_urlW[] = { 'h','t','t','p',':','/','/','w','w','w','.','w','i','n','e','h','q',
48         '.','o','r','g','/',0};
49
50 typedef struct _uri_create_flag_test {
51     DWORD   flags;
52     HRESULT expected;
53 } uri_create_flag_test;
54
55 static const uri_create_flag_test invalid_flag_tests[] = {
56     /* Set of invalid flag combinations to test for. */
57     {Uri_CREATE_DECODE_EXTRA_INFO | Uri_CREATE_NO_DECODE_EXTRA_INFO, E_INVALIDARG},
58     {Uri_CREATE_CANONICALIZE | Uri_CREATE_NO_CANONICALIZE, E_INVALIDARG},
59     {Uri_CREATE_CRACK_UNKNOWN_SCHEMES | Uri_CREATE_NO_CRACK_UNKNOWN_SCHEMES, E_INVALIDARG},
60     {Uri_CREATE_PRE_PROCESS_HTML_URI | Uri_CREATE_NO_PRE_PROCESS_HTML_URI, E_INVALIDARG},
61     {Uri_CREATE_IE_SETTINGS | Uri_CREATE_NO_IE_SETTINGS, E_INVALIDARG}
62 };
63
64 typedef struct _uri_str_property {
65     const char* value;
66     HRESULT     expected;
67     BOOL        todo;
68     const char* broken_value;
69 } uri_str_property;
70
71 typedef struct _uri_dword_property {
72     DWORD   value;
73     HRESULT expected;
74     BOOL    todo;
75 } uri_dword_property;
76
77 typedef struct _uri_properties {
78     const char*         uri;
79     DWORD               create_flags;
80     HRESULT             create_expected;
81     BOOL                create_todo;
82     DWORD               props;
83     BOOL                props_todo;
84
85     uri_str_property    str_props[URI_STR_PROPERTY_COUNT];
86     uri_dword_property  dword_props[URI_DWORD_PROPERTY_COUNT];
87 } uri_properties;
88
89 static const uri_properties uri_tests[] = {
90     {   "http://www.winehq.org/tests/../tests/../..", 0, S_OK, FALSE,
91         /* A flag bitmap containing all the Uri_HAS_* flags that correspond to this uri. */
92         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_HOST|
93         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|
94         Uri_HAS_PORT|Uri_HAS_SCHEME,
95         TRUE,
96         {
97             {"http://www.winehq.org/",S_OK,TRUE},                       /* ABSOLUTE_URI */
98             {"www.winehq.org",S_OK,FALSE},                              /* AUTHORITY */
99             {"http://www.winehq.org/",S_OK,TRUE},                       /* DISPLAY_URI */
100             {"winehq.org",S_OK,FALSE},                                  /* DOMAIN */
101             {"",S_FALSE,TRUE},                                          /* EXTENSION */
102             {"",S_FALSE,TRUE},                                          /* FRAGMENT */
103             {"www.winehq.org",S_OK,FALSE},                              /* HOST */
104             {"",S_FALSE,FALSE},                                         /* PASSWORD */
105             {"/",S_OK,TRUE},                                            /* PATH */
106             {"/",S_OK,TRUE},                                            /* PATH_AND_QUERY */
107             {"",S_FALSE,TRUE},                                          /* QUERY */
108             {"http://www.winehq.org/tests/../tests/../..",S_OK,FALSE},  /* RAW_URI */
109             {"http",S_OK,FALSE},                                        /* SCHEME_NAME */
110             {"",S_FALSE,FALSE},                                         /* USER_INFO */
111             {"",S_FALSE,FALSE}                                          /* USER_NAME */
112         },
113         {
114             {Uri_HOST_DNS,S_OK,FALSE},                                  /* HOST_TYPE */
115             {80,S_OK,FALSE},                                            /* PORT */
116             {URL_SCHEME_HTTP,S_OK,FALSE},                               /* SCHEME */
117             {URLZONE_INVALID,E_NOTIMPL,FALSE}                           /* ZONE */
118         }
119     },
120     {   "http://winehq.org/tests/.././tests", 0, S_OK, FALSE,
121         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_HOST|
122         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|
123         Uri_HAS_PORT|Uri_HAS_SCHEME,
124         TRUE,
125         {
126             {"http://winehq.org/tests",S_OK,TRUE},
127             {"winehq.org",S_OK,FALSE},
128             {"http://winehq.org/tests",S_OK,TRUE},
129             {"winehq.org",S_OK,FALSE},
130             {"",S_FALSE,TRUE},
131             {"",S_FALSE,TRUE},
132             {"winehq.org",S_OK,FALSE},
133             {"",S_FALSE,FALSE},
134             {"/tests",S_OK,TRUE},
135             {"/tests",S_OK,TRUE},
136             {"",S_FALSE,TRUE},
137             {"http://winehq.org/tests/.././tests",S_OK,FALSE},
138             {"http",S_OK,FALSE},
139             {"",S_FALSE,FALSE},
140             {"",S_FALSE,FALSE}
141         },
142         {
143             {Uri_HOST_DNS,S_OK,FALSE},
144             {80,S_OK,FALSE},
145             {URL_SCHEME_HTTP,S_OK,FALSE},
146             {URLZONE_INVALID,E_NOTIMPL,FALSE}
147         }
148     },
149     {   "HtTp://www.winehq.org/tests/..?query=x&return=y", 0, S_OK, FALSE,
150         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_HOST|
151         Uri_HAS_DOMAIN|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_QUERY|Uri_HAS_RAW_URI|
152         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
153         TRUE,
154         {
155             {"http://www.winehq.org/?query=x&return=y",S_OK,TRUE},
156             {"www.winehq.org",S_OK,FALSE},
157             {"http://www.winehq.org/?query=x&return=y",S_OK,TRUE},
158             {"winehq.org",S_OK,FALSE},
159             {"",S_FALSE,TRUE},
160             {"",S_FALSE,TRUE},
161             {"www.winehq.org",S_OK,FALSE},
162             {"",S_FALSE,FALSE},
163             {"/",S_OK,TRUE},
164             {"/?query=x&return=y",S_OK,TRUE},
165             {"?query=x&return=y",S_OK,TRUE},
166             {"HtTp://www.winehq.org/tests/..?query=x&return=y",S_OK,FALSE},
167             {"http",S_OK,FALSE},
168             {"",S_FALSE,FALSE},
169             {"",S_FALSE,FALSE}
170         },
171         {
172             {Uri_HOST_DNS,S_OK,FALSE},
173             {80,S_OK,FALSE},
174             {URL_SCHEME_HTTP,S_OK,FALSE},
175             {URLZONE_INVALID,E_NOTIMPL,FALSE},
176         }
177     },
178     {   "hTTp://us%45r%3Ainfo@examp%4CE.com:80/path/a/b/./c/../%2E%2E/Forbidden'<|> Characters", 0, S_OK, FALSE,
179         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_HOST|Uri_HAS_PATH|
180         Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_USER_INFO|Uri_HAS_USER_NAME|
181         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
182         TRUE,
183         {
184             {"http://usEr%3Ainfo@example.com/path/a/Forbidden'%3C%7C%3E%20Characters",S_OK,TRUE},
185             {"usEr%3Ainfo@example.com",S_OK,FALSE},
186             {"http://example.com/path/a/Forbidden'%3C%7C%3E%20Characters",S_OK,TRUE},
187             {"example.com",S_OK,FALSE},
188             {"",S_FALSE,TRUE},
189             {"",S_FALSE,TRUE},
190             {"example.com",S_OK,FALSE},
191             {"",S_FALSE,FALSE},
192             {"/path/a/Forbidden'%3C%7C%3E%20Characters",S_OK,TRUE},
193             {"/path/a/Forbidden'%3C%7C%3E%20Characters",S_OK,TRUE},
194             {"",S_FALSE,TRUE},
195             {"hTTp://us%45r%3Ainfo@examp%4CE.com:80/path/a/b/./c/../%2E%2E/Forbidden'<|> Characters",S_OK,FALSE},
196             {"http",S_OK,FALSE},
197             {"usEr%3Ainfo",S_OK,FALSE},
198             {"usEr%3Ainfo",S_OK,FALSE}
199         },
200         {
201             {Uri_HOST_DNS,S_OK,FALSE},
202             {80,S_OK,FALSE},
203             {URL_SCHEME_HTTP,S_OK,FALSE},
204             {URLZONE_INVALID,E_NOTIMPL,FALSE},
205         }
206     },
207     {   "ftp://winepass:wine@ftp.winehq.org:9999/dir/foo bar.txt", 0, S_OK, FALSE,
208         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_EXTENSION|
209         Uri_HAS_HOST|Uri_HAS_PASSWORD|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
210         Uri_HAS_SCHEME_NAME|Uri_HAS_USER_INFO|Uri_HAS_USER_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|
211         Uri_HAS_SCHEME,
212         TRUE,
213         {
214             {"ftp://winepass:wine@ftp.winehq.org:9999/dir/foo%20bar.txt",S_OK,TRUE},
215             {"winepass:wine@ftp.winehq.org:9999",S_OK,FALSE},
216             {"ftp://ftp.winehq.org:9999/dir/foo%20bar.txt",S_OK,TRUE},
217             {"winehq.org",S_OK,FALSE},
218             {".txt",S_OK,TRUE},
219             {"",S_FALSE,TRUE},
220             {"ftp.winehq.org",S_OK,FALSE},
221             {"wine",S_OK,FALSE},
222             {"/dir/foo%20bar.txt",S_OK,TRUE},
223             {"/dir/foo%20bar.txt",S_OK,TRUE},
224             {"",S_FALSE,TRUE},
225             {"ftp://winepass:wine@ftp.winehq.org:9999/dir/foo bar.txt",S_OK,FALSE},
226             {"ftp",S_OK,FALSE},
227             {"winepass:wine",S_OK,FALSE},
228             {"winepass",S_OK,FALSE}
229         },
230         {
231             {Uri_HOST_DNS,S_OK,FALSE},
232             {9999,S_OK,FALSE},
233             {URL_SCHEME_FTP,S_OK,FALSE},
234             {URLZONE_INVALID,E_NOTIMPL,FALSE}
235         }
236     },
237     {   "file://c:\\tests\\../tests/foo%20bar.mp3", 0, S_OK, FALSE,
238         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH|
239         Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
240         TRUE,
241         {
242             {"file:///c:/tests/foo%2520bar.mp3",S_OK,TRUE},
243             {"",S_FALSE,FALSE},
244             {"file:///c:/tests/foo%2520bar.mp3",S_OK,TRUE},
245             {"",S_FALSE,FALSE},
246             {".mp3",S_OK,TRUE},
247             {"",S_FALSE,TRUE},
248             {"",S_FALSE,FALSE},
249             {"",S_FALSE,FALSE},
250             {"/c:/tests/foo%2520bar.mp3",S_OK,TRUE},
251             {"/c:/tests/foo%2520bar.mp3",S_OK,TRUE},
252             {"",S_FALSE,TRUE},
253             {"file://c:\\tests\\../tests/foo%20bar.mp3",S_OK,FALSE},
254             {"file",S_OK,FALSE},
255             {"",S_FALSE,FALSE},
256             {"",S_FALSE,FALSE}
257         },
258         {
259             {Uri_HOST_UNKNOWN,S_OK,FALSE},
260             {0,S_FALSE,FALSE},
261             {URL_SCHEME_FILE,S_OK,FALSE},
262             {URLZONE_INVALID,E_NOTIMPL,FALSE}
263         }
264     },
265     {   "FILE://localhost/test dir\\../tests/test%20file.README.txt", 0, S_OK, FALSE,
266         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH|
267         Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
268         TRUE,
269         {
270             {"file:///tests/test%20file.README.txt",S_OK,TRUE},
271             {"",S_FALSE,FALSE},
272             {"file:///tests/test%20file.README.txt",S_OK,TRUE},
273             {"",S_FALSE,FALSE},
274             {".txt",S_OK,TRUE},
275             {"",S_FALSE,TRUE},
276             {"",S_FALSE,FALSE},
277             {"",S_FALSE,FALSE},
278             {"/tests/test%20file.README.txt",S_OK,TRUE},
279             {"/tests/test%20file.README.txt",S_OK,TRUE},
280             {"",S_FALSE,TRUE},
281             {"FILE://localhost/test dir\\../tests/test%20file.README.txt",S_OK,FALSE},
282             {"file",S_OK,FALSE},
283             {"",S_FALSE,FALSE},
284             {"",S_FALSE,FALSE}
285         },
286         {
287             {Uri_HOST_UNKNOWN,S_OK,FALSE},
288             {0,S_FALSE,FALSE},
289             {URL_SCHEME_FILE,S_OK,FALSE},
290             {URLZONE_INVALID,E_NOTIMPL,FALSE}
291         }
292     },
293     {   "urn:nothing:should:happen here", 0, S_OK, FALSE,
294         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|
295         Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
296         TRUE,
297         {
298             {"urn:nothing:should:happen here",S_OK,TRUE},
299             {"",S_FALSE,FALSE},
300             {"urn:nothing:should:happen here",S_OK,TRUE},
301             {"",S_FALSE,FALSE},
302             {"",S_FALSE,TRUE},
303             {"",S_FALSE,TRUE},
304             {"",S_FALSE,FALSE},
305             {"",S_FALSE,FALSE},
306             {"nothing:should:happen here",S_OK,TRUE},
307             {"nothing:should:happen here",S_OK,TRUE},
308             {"",S_FALSE,TRUE},
309             {"urn:nothing:should:happen here",S_OK,FALSE},
310             {"urn",S_OK,FALSE},
311             {"",S_FALSE,FALSE},
312             {"",S_FALSE,FALSE}
313         },
314         {
315             {Uri_HOST_UNKNOWN,S_OK,FALSE},
316             {0,S_FALSE,FALSE},
317             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
318             {URLZONE_INVALID,E_NOTIMPL,FALSE}
319         }
320     },
321     {   "http://127.0.0.1/tests/../test dir/./test.txt", 0, S_OK, FALSE,
322         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|
323         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
324         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
325         TRUE,
326         {
327             {"http://127.0.0.1/test%20dir/test.txt",S_OK,TRUE},
328             {"127.0.0.1",S_OK,FALSE},
329             {"http://127.0.0.1/test%20dir/test.txt",S_OK,TRUE},
330             {"",S_FALSE,FALSE},
331             {".txt",S_OK,TRUE},
332             {"",S_FALSE,TRUE},
333             {"127.0.0.1",S_OK,FALSE},
334             {"",S_FALSE,FALSE},
335             {"/test%20dir/test.txt",S_OK,TRUE},
336             {"/test%20dir/test.txt",S_OK,TRUE},
337             {"",S_FALSE,TRUE},
338             {"http://127.0.0.1/tests/../test dir/./test.txt",S_OK,FALSE},
339             {"http",S_OK,FALSE},
340             {"",S_FALSE,FALSE},
341             {"",S_FALSE,FALSE}
342         },
343         {
344             {Uri_HOST_IPV4,S_OK,FALSE},
345             {80,S_OK,FALSE},
346             {URL_SCHEME_HTTP,S_OK,FALSE},
347             {URLZONE_INVALID,E_NOTIMPL,FALSE}
348         }
349     },
350     {   "http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]", 0, S_OK, FALSE,
351         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
352         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
353         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
354         TRUE,
355         {
356             {"http://[fedc:ba98:7654:3210:fedc:ba98:7654:3210]/",S_OK,TRUE},
357             {"[fedc:ba98:7654:3210:fedc:ba98:7654:3210]",S_OK,FALSE},
358             {"http://[fedc:ba98:7654:3210:fedc:ba98:7654:3210]/",S_OK,TRUE},
359             {"",S_FALSE,FALSE},
360             {"",S_FALSE,TRUE},
361             {"",S_FALSE,TRUE},
362             {"fedc:ba98:7654:3210:fedc:ba98:7654:3210",S_OK,FALSE},
363             {"",S_FALSE,FALSE},
364             {"/",S_OK,TRUE},
365             {"/",S_OK,TRUE},
366             {"",S_FALSE,TRUE},
367             {"http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]",S_OK,FALSE},
368             {"http",S_OK,FALSE},
369             {"",S_FALSE,FALSE},
370             {"",S_FALSE,FALSE}
371         },
372         {
373             {Uri_HOST_IPV6,S_OK,FALSE},
374             {80,S_OK,FALSE},
375             {URL_SCHEME_HTTP,S_OK,FALSE},
376             {URLZONE_INVALID,E_NOTIMPL,FALSE}
377         }
378     },
379     {   "ftp://[::13.1.68.3]", 0, S_OK, FALSE,
380         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
381         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
382         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
383         TRUE,
384         {
385             {"ftp://[::13.1.68.3]/",S_OK,TRUE},
386             {"[::13.1.68.3]",S_OK,FALSE},
387             {"ftp://[::13.1.68.3]/",S_OK,TRUE},
388             {"",S_FALSE,FALSE},
389             {"",S_FALSE,TRUE},
390             {"",S_FALSE,TRUE},
391             {"::13.1.68.3",S_OK,FALSE},
392             {"",S_FALSE,FALSE},
393             {"/",S_OK,TRUE},
394             {"/",S_OK,TRUE},
395             {"",S_FALSE,TRUE},
396             {"ftp://[::13.1.68.3]",S_OK,FALSE},
397             {"ftp",S_OK,FALSE},
398             {"",S_FALSE,FALSE},
399             {"",S_FALSE,FALSE}
400         },
401         {
402             {Uri_HOST_IPV6,S_OK,FALSE},
403             {21,S_OK,FALSE},
404             {URL_SCHEME_FTP,S_OK,FALSE},
405             {URLZONE_INVALID,E_NOTIMPL,FALSE}
406         }
407     },
408     {   "http://[FEDC:BA98:0:0:0:0:0:3210]", 0, S_OK, FALSE,
409         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
410         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
411         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
412         TRUE,
413         {
414             {"http://[fedc:ba98::3210]/",S_OK,TRUE},
415             {"[fedc:ba98::3210]",S_OK,FALSE},
416             {"http://[fedc:ba98::3210]/",S_OK,TRUE},
417             {"",S_FALSE,FALSE},
418             {"",S_FALSE,TRUE},
419             {"",S_FALSE,TRUE},
420             {"fedc:ba98::3210",S_OK,FALSE},
421             {"",S_FALSE,FALSE},
422             {"/",S_OK,TRUE},
423             {"/",S_OK,TRUE},
424             {"",S_FALSE,TRUE},
425             {"http://[FEDC:BA98:0:0:0:0:0:3210]",S_OK,FALSE},
426             {"http",S_OK,FALSE},
427             {"",S_FALSE,FALSE},
428             {"",S_FALSE,FALSE},
429         },
430         {
431             {Uri_HOST_IPV6,S_OK,FALSE},
432             {80,S_OK,FALSE},
433             {URL_SCHEME_HTTP,S_OK,FALSE},
434             {URLZONE_INVALID,E_NOTIMPL,FALSE}
435         }
436     },
437     {   "1234://www.winehq.org", 0, S_OK, FALSE,
438         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
439         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
440         Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
441         TRUE,
442         {
443             {"1234://www.winehq.org/",S_OK,TRUE},
444             {"www.winehq.org",S_OK,FALSE},
445             {"1234://www.winehq.org/",S_OK,TRUE},
446             {"winehq.org",S_OK,FALSE},
447             {"",S_FALSE,TRUE},
448             {"",S_FALSE,TRUE},
449             {"www.winehq.org",S_OK,FALSE},
450             {"",S_FALSE,FALSE},
451             {"/",S_OK,TRUE},
452             {"/",S_OK,TRUE},
453             {"",S_FALSE,TRUE},
454             {"1234://www.winehq.org",S_OK,FALSE},
455             {"1234",S_OK,FALSE},
456             {"",S_FALSE,FALSE},
457             {"",S_FALSE,FALSE}
458         },
459         {
460             {Uri_HOST_DNS,S_OK,FALSE},
461             {0,S_FALSE,FALSE},
462             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
463             {URLZONE_INVALID,E_NOTIMPL,FALSE}
464         }
465     },
466     /* Test's to make sure the parser/canonicalizer handles implicit file schemes correctly. */
467     {   "C:/test/test.mp3", Uri_CREATE_ALLOW_IMPLICIT_FILE_SCHEME, S_OK, FALSE,
468         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH|
469         Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
470         TRUE,
471         {
472             {"file:///C:/test/test.mp3",S_OK,TRUE},
473             {"",S_FALSE,FALSE},
474             {"file:///C:/test/test.mp3",S_OK,TRUE},
475             {"",S_FALSE,FALSE},
476             {".mp3",S_OK,TRUE},
477             {"",S_FALSE,TRUE},
478             {"",S_FALSE,FALSE},
479             {"",S_FALSE,FALSE},
480             {"/C:/test/test.mp3",S_OK,TRUE},
481             {"/C:/test/test.mp3",S_OK,TRUE},
482             {"",S_FALSE,TRUE},
483             {"C:/test/test.mp3",S_OK,FALSE},
484             {"file",S_OK,FALSE},
485             {"",S_FALSE,FALSE},
486             {"",S_FALSE,FALSE}
487         },
488         {
489             {Uri_HOST_UNKNOWN,S_OK,FALSE},
490             {0,S_FALSE,FALSE},
491             {URL_SCHEME_FILE,S_OK,FALSE},
492             {URLZONE_INVALID,E_NOTIMPL,FALSE}
493         }
494     },
495     /* Test's to make sure the parser/canonicalizer handles implicit file schemes correctly. */
496     {   "\\\\Server/test.mp3", Uri_CREATE_ALLOW_IMPLICIT_FILE_SCHEME, S_OK, FALSE,
497         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|
498         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_HOST|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
499         Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
500         TRUE,
501         {
502             {"file://server/test.mp3",S_OK,TRUE},
503             {"server",S_OK,FALSE},
504             {"file://server/test.mp3",S_OK,TRUE},
505             {"",S_FALSE,FALSE},
506             {".mp3",S_OK,TRUE},
507             {"",S_FALSE,TRUE},
508             {"server",S_OK,FALSE},
509             {"",S_FALSE,FALSE},
510             {"/test.mp3",S_OK,TRUE},
511             {"/test.mp3",S_OK,TRUE},
512             {"",S_FALSE,TRUE},
513             {"\\\\Server/test.mp3",S_OK,FALSE},
514             {"file",S_OK,FALSE},
515             {"",S_FALSE,FALSE},
516             {"",S_FALSE,FALSE}
517         },
518         {
519             {Uri_HOST_DNS,S_OK,FALSE},
520             {0,S_FALSE,FALSE},
521             {URL_SCHEME_FILE,S_OK,FALSE},
522             {URLZONE_INVALID,E_NOTIMPL,FALSE}
523         }
524     },
525     {   "www.winehq.org/test", Uri_CREATE_ALLOW_IMPLICIT_WILDCARD_SCHEME, S_OK, FALSE,
526         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_HOST|
527         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|
528         Uri_HAS_SCHEME,
529         TRUE,
530         {
531             {"*:www.winehq.org/test",S_OK,TRUE},
532             {"www.winehq.org",S_OK,FALSE},
533             {"*:www.winehq.org/test",S_OK,TRUE},
534             {"winehq.org",S_OK,FALSE},
535             {"",S_FALSE,TRUE},
536             {"",S_FALSE,TRUE},
537             {"www.winehq.org",S_OK,FALSE},
538             {"",S_FALSE,FALSE},
539             {"/test",S_OK,TRUE},
540             {"/test",S_OK,TRUE},
541             {"",S_FALSE,TRUE},
542             {"www.winehq.org/test",S_OK,FALSE},
543             {"*",S_OK,FALSE},
544             {"",S_FALSE,FALSE},
545             {"",S_FALSE,FALSE}
546         },
547         {
548             {Uri_HOST_DNS,S_OK,FALSE},
549             {0,S_FALSE,FALSE},
550             {URL_SCHEME_WILDCARD,S_OK,FALSE},
551             {URLZONE_INVALID,E_NOTIMPL,FALSE}
552         }
553     },
554     /* Valid since the '*' is the only character in the scheme name. */
555     {   "*:www.winehq.org/test", 0, S_OK, FALSE,
556         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_HOST|
557         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|
558         Uri_HAS_SCHEME,
559         TRUE,
560         {
561             {"*:www.winehq.org/test",S_OK,TRUE},
562             {"www.winehq.org",S_OK,FALSE},
563             {"*:www.winehq.org/test",S_OK,TRUE},
564             {"winehq.org",S_OK,FALSE},
565             {"",S_FALSE,TRUE},
566             {"",S_FALSE,TRUE},
567             {"www.winehq.org",S_OK,FALSE},
568             {"",S_FALSE,FALSE},
569             {"/test",S_OK,TRUE},
570             {"/test",S_OK,TRUE},
571             {"",S_FALSE,TRUE},
572             {"*:www.winehq.org/test",S_OK,FALSE},
573             {"*",S_OK,FALSE},
574             {"",S_FALSE,FALSE},
575             {"",S_FALSE,FALSE}
576         },
577         {
578             {Uri_HOST_DNS,S_OK,FALSE},
579             {0,S_FALSE,FALSE},
580             {URL_SCHEME_WILDCARD,S_OK,FALSE},
581             {URLZONE_INVALID,E_NOTIMPL,FALSE}
582         }
583     },
584     {   "/../some dir/test.ext", Uri_CREATE_ALLOW_RELATIVE, S_OK, FALSE,
585         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH|
586         Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
587         TRUE,
588         {
589             {"/../some dir/test.ext",S_OK,TRUE},
590             {"",S_FALSE,FALSE},
591             {"/../some dir/test.ext",S_OK,TRUE},
592             {"",S_FALSE,FALSE},
593             {".ext",S_OK,TRUE},
594             {"",S_FALSE,TRUE},
595             {"",S_FALSE,FALSE},
596             {"",S_FALSE,FALSE},
597             {"/../some dir/test.ext",S_OK,TRUE},
598             {"/../some dir/test.ext",S_OK,TRUE},
599             {"",S_FALSE,TRUE},
600             {"/../some dir/test.ext",S_OK,FALSE},
601             {"",S_FALSE,FALSE},
602             {"",S_FALSE,FALSE},
603             {"",S_FALSE,FALSE}
604         },
605         {
606             {Uri_HOST_UNKNOWN,S_OK,FALSE},
607             {0,S_FALSE,FALSE},
608             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
609             {URLZONE_INVALID,E_NOTIMPL,FALSE}
610         }
611     },
612     {   "//implicit/wildcard/uri scheme", Uri_CREATE_ALLOW_RELATIVE|Uri_CREATE_ALLOW_IMPLICIT_WILDCARD_SCHEME, S_OK, FALSE,
613         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|Uri_HAS_PATH|
614         Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
615         TRUE,
616         {
617             {"*://implicit/wildcard/uri%20scheme",S_OK,TRUE},
618             {"",S_OK,FALSE},
619             {"*://implicit/wildcard/uri%20scheme",S_OK,TRUE},
620             {"",S_FALSE,FALSE},
621             {"",S_FALSE,TRUE},
622             {"",S_FALSE,TRUE},
623             {"",S_OK,FALSE},
624             {"",S_FALSE,FALSE},
625             {"//implicit/wildcard/uri%20scheme",S_OK,TRUE},
626             {"//implicit/wildcard/uri%20scheme",S_OK,TRUE},
627             {"",S_FALSE,TRUE},
628             {"//implicit/wildcard/uri scheme",S_OK,FALSE},
629             {"*",S_OK,FALSE},
630             {"",S_FALSE,FALSE},
631             {"",S_FALSE,FALSE},
632         },
633         {
634             {Uri_HOST_UNKNOWN,S_OK,FALSE},
635             {0,S_FALSE,FALSE},
636             {URL_SCHEME_WILDCARD,S_OK,FALSE},
637             {URLZONE_INVALID,E_NOTIMPL,FALSE}
638         }
639     },
640     /* URI is considered opaque since CREATE_NO_CRACK_UNKNOWN_SCHEMES is set and its an unknown scheme. */
641     {   "zip://google.com", Uri_CREATE_NO_CRACK_UNKNOWN_SCHEMES, S_OK, FALSE,
642         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH|
643         Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME_NAME|
644         Uri_HAS_SCHEME,
645         TRUE,
646         {
647             {"zip:/.//google.com",S_OK,TRUE},
648             {"",S_FALSE,FALSE},
649             {"zip:/.//google.com",S_OK,TRUE},
650             {"",S_FALSE,FALSE},
651             {".com",S_OK,TRUE},
652             {"",S_FALSE,TRUE},
653             {"",S_FALSE,FALSE},
654             {"",S_FALSE,FALSE},
655             {"/.//google.com",S_OK,TRUE},
656             {"/.//google.com",S_OK,TRUE},
657             {"",S_FALSE,TRUE},
658             {"zip://google.com",S_OK,FALSE},
659             {"zip",S_OK,FALSE},
660             {"",S_FALSE,FALSE},
661             {"",S_FALSE,FALSE}
662         },
663         {
664             {Uri_HOST_UNKNOWN,S_OK,FALSE},
665             {0,S_FALSE,FALSE},
666             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
667             {URLZONE_INVALID,E_NOTIMPL,FALSE}
668         }
669     },
670     /* Windows uses the first occurence of ':' to delimit the userinfo. */
671     {   "ftp://user:pass:word@winehq.org/", 0, S_OK, FALSE,
672         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
673         Uri_HAS_HOST|Uri_HAS_PASSWORD|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
674         Uri_HAS_SCHEME_NAME|Uri_HAS_USER_INFO|Uri_HAS_USER_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|
675         Uri_HAS_SCHEME,
676         TRUE,
677         {
678             {"ftp://user:pass:word@winehq.org/",S_OK,TRUE},
679             {"user:pass:word@winehq.org",S_OK,FALSE},
680             {"ftp://winehq.org/",S_OK,TRUE},
681             {"winehq.org",S_OK,FALSE},
682             {"",S_FALSE,TRUE},
683             {"",S_FALSE,TRUE},
684             {"winehq.org",S_OK,FALSE},
685             {"pass:word",S_OK,FALSE},
686             {"/",S_OK,TRUE},
687             {"/",S_OK,TRUE},
688             {"",S_FALSE,TRUE},
689             {"ftp://user:pass:word@winehq.org/",S_OK,FALSE},
690             {"ftp",S_OK,FALSE},
691             {"user:pass:word",S_OK,FALSE},
692             {"user",S_OK,FALSE}
693         },
694         {
695             {Uri_HOST_DNS,S_OK,FALSE},
696             {21,S_OK,FALSE},
697             {URL_SCHEME_FTP,S_OK,FALSE},
698             {URLZONE_INVALID,E_NOTIMPL,FALSE}
699         }
700     },
701     /* Make sure % encoded unreserved characters are decoded. */
702     {   "ftp://w%49%4Ee:PA%53%53@ftp.google.com/", 0, S_OK, FALSE,
703         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
704         Uri_HAS_HOST|Uri_HAS_PASSWORD|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
705         Uri_HAS_SCHEME_NAME|Uri_HAS_USER_INFO|Uri_HAS_USER_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|
706         Uri_HAS_SCHEME,
707         TRUE,
708         {
709             {"ftp://wINe:PASS@ftp.google.com/",S_OK,TRUE},
710             {"wINe:PASS@ftp.google.com",S_OK,FALSE},
711             {"ftp://ftp.google.com/",S_OK,TRUE},
712             {"google.com",S_OK,FALSE},
713             {"",S_FALSE,TRUE},
714             {"",S_FALSE,TRUE},
715             {"ftp.google.com",S_OK,FALSE},
716             {"PASS",S_OK,FALSE},
717             {"/",S_OK,TRUE},
718             {"/",S_OK,TRUE},
719             {"",S_FALSE,TRUE},
720             {"ftp://w%49%4Ee:PA%53%53@ftp.google.com/",S_OK,FALSE},
721             {"ftp",S_OK,FALSE},
722             {"wINe:PASS",S_OK,FALSE},
723             {"wINe",S_OK,FALSE}
724         },
725         {
726             {Uri_HOST_DNS,S_OK,FALSE},
727             {21,S_OK,FALSE},
728             {URL_SCHEME_FTP,S_OK,FALSE},
729             {URLZONE_INVALID,E_NOTIMPL,FALSE}
730         }
731     },
732     /* Make sure % encoded characters which are NOT unreserved are NOT decoded. */
733     {   "ftp://w%5D%5Be:PA%7B%7D@ftp.google.com/", 0, S_OK, FALSE,
734         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
735         Uri_HAS_HOST|Uri_HAS_PASSWORD|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
736         Uri_HAS_SCHEME_NAME|Uri_HAS_USER_INFO|Uri_HAS_USER_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|
737         Uri_HAS_SCHEME,
738         TRUE,
739         {
740             {"ftp://w%5D%5Be:PA%7B%7D@ftp.google.com/",S_OK,TRUE},
741             {"w%5D%5Be:PA%7B%7D@ftp.google.com",S_OK,FALSE},
742             {"ftp://ftp.google.com/",S_OK,TRUE},
743             {"google.com",S_OK,FALSE},
744             {"",S_FALSE,TRUE},
745             {"",S_FALSE,TRUE},
746             {"ftp.google.com",S_OK,FALSE},
747             {"PA%7B%7D",S_OK,FALSE},
748             {"/",S_OK,TRUE},
749             {"/",S_OK,TRUE},
750             {"",S_FALSE,TRUE},
751             {"ftp://w%5D%5Be:PA%7B%7D@ftp.google.com/",S_OK,FALSE},
752             {"ftp",S_OK,FALSE},
753             {"w%5D%5Be:PA%7B%7D",S_OK,FALSE},
754             {"w%5D%5Be",S_OK,FALSE}
755         },
756         {
757             {Uri_HOST_DNS,S_OK,FALSE},
758             {21,S_OK,FALSE},
759             {URL_SCHEME_FTP,S_OK,FALSE},
760             {URLZONE_INVALID,E_NOTIMPL,FALSE}
761         }
762     },
763     /* You're allowed to have an empty password portion in the userinfo section. */
764     {   "ftp://empty:@ftp.google.com/", 0, S_OK, FALSE,
765         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
766         Uri_HAS_HOST|Uri_HAS_PASSWORD|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
767         Uri_HAS_SCHEME_NAME|Uri_HAS_USER_INFO|Uri_HAS_USER_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|
768         Uri_HAS_SCHEME,
769         TRUE,
770         {
771             {"ftp://empty:@ftp.google.com/",S_OK,TRUE},
772             {"empty:@ftp.google.com",S_OK,FALSE},
773             {"ftp://ftp.google.com/",S_OK,TRUE},
774             {"google.com",S_OK,FALSE},
775             {"",S_FALSE,TRUE},
776             {"",S_FALSE,TRUE},
777             {"ftp.google.com",S_OK,FALSE},
778             {"",S_OK,FALSE},
779             {"/",S_OK,TRUE},
780             {"/",S_OK,TRUE},
781             {"",S_FALSE,TRUE},
782             {"ftp://empty:@ftp.google.com/",S_OK,FALSE},
783             {"ftp",S_OK,FALSE},
784             {"empty:",S_OK,FALSE},
785             {"empty",S_OK,FALSE}
786         },
787         {
788             {Uri_HOST_DNS,S_OK,FALSE},
789             {21,S_OK,FALSE},
790             {URL_SCHEME_FTP,S_OK,FALSE},
791             {URLZONE_INVALID,E_NOTIMPL,FALSE}
792         }
793     },
794     /* Make sure forbidden characters in "userinfo" get encoded. */
795     {   "ftp://\" \"weird@ftp.google.com/", 0, S_OK, FALSE,
796         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
797         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
798         Uri_HAS_SCHEME_NAME|Uri_HAS_USER_INFO|Uri_HAS_USER_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|
799         Uri_HAS_SCHEME,
800         TRUE,
801         {
802             {"ftp://%22%20%22weird@ftp.google.com/",S_OK,TRUE},
803             {"%22%20%22weird@ftp.google.com",S_OK,FALSE},
804             {"ftp://ftp.google.com/",S_OK,TRUE},
805             {"google.com",S_OK,FALSE},
806             {"",S_FALSE,TRUE},
807             {"",S_FALSE,TRUE},
808             {"ftp.google.com",S_OK,FALSE},
809             {"",S_FALSE,FALSE},
810             {"/",S_OK,TRUE},
811             {"/",S_OK,TRUE},
812             {"",S_FALSE,TRUE},
813             {"ftp://\" \"weird@ftp.google.com/",S_OK,FALSE},
814             {"ftp",S_OK,FALSE},
815             {"%22%20%22weird",S_OK,FALSE},
816             {"%22%20%22weird",S_OK,FALSE}
817         },
818         {
819             {Uri_HOST_DNS,S_OK,FALSE},
820             {21,S_OK,FALSE},
821             {URL_SCHEME_FTP,S_OK,FALSE},
822             {URLZONE_INVALID,E_NOTIMPL,FALSE}
823         }
824     },
825     /* Make sure the forbidden characters don't get percent encoded. */
826     {   "ftp://\" \"weird@ftp.google.com/", Uri_CREATE_NO_ENCODE_FORBIDDEN_CHARACTERS, S_OK, FALSE,
827         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
828         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
829         Uri_HAS_SCHEME_NAME|Uri_HAS_USER_INFO|Uri_HAS_USER_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|
830         Uri_HAS_SCHEME,
831         TRUE,
832         {
833             {"ftp://\" \"weird@ftp.google.com/",S_OK,TRUE},
834             {"\" \"weird@ftp.google.com",S_OK,FALSE},
835             {"ftp://ftp.google.com/",S_OK,TRUE},
836             {"google.com",S_OK,FALSE},
837             {"",S_FALSE,TRUE},
838             {"",S_FALSE,TRUE},
839             {"ftp.google.com",S_OK,FALSE},
840             {"",S_FALSE,FALSE},
841             {"/",S_OK,TRUE},
842             {"/",S_OK,TRUE},
843             {"",S_FALSE,TRUE},
844             {"ftp://\" \"weird@ftp.google.com/",S_OK,FALSE},
845             {"ftp",S_OK,FALSE},
846             {"\" \"weird",S_OK,FALSE},
847             {"\" \"weird",S_OK,FALSE}
848         },
849         {
850             {Uri_HOST_DNS,S_OK,FALSE},
851             {21,S_OK,FALSE},
852             {URL_SCHEME_FTP,S_OK,FALSE},
853             {URLZONE_INVALID,E_NOTIMPL,FALSE}
854         }
855     },
856     /* Allowed to have invalid % encoded because its an unknown scheme type. */
857     {   "zip://%xy:word@winehq.org/", 0, S_OK, FALSE,
858         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
859         Uri_HAS_HOST|Uri_HAS_PASSWORD|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
860         Uri_HAS_SCHEME_NAME|Uri_HAS_USER_INFO|Uri_HAS_USER_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
861         TRUE,
862         {
863             {"zip://%xy:word@winehq.org/",S_OK,TRUE},
864             {"%xy:word@winehq.org",S_OK,FALSE},
865             {"zip://%xy:word@winehq.org/",S_OK,TRUE},
866             {"winehq.org",S_OK,FALSE},
867             {"",S_FALSE,TRUE},
868             {"",S_FALSE,TRUE},
869             {"winehq.org",S_OK,FALSE},
870             {"word",S_OK,FALSE},
871             {"/",S_OK,TRUE},
872             {"/",S_OK,TRUE},
873             {"",S_FALSE,TRUE},
874             {"zip://%xy:word@winehq.org/",S_OK,FALSE},
875             {"zip",S_OK,FALSE},
876             {"%xy:word",S_OK,FALSE},
877             {"%xy",S_OK,FALSE}
878         },
879         {
880             {Uri_HOST_DNS,S_OK,FALSE},
881             {0,S_FALSE,FALSE},
882             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
883             {URLZONE_INVALID,E_NOTIMPL,FALSE}
884         }
885     },
886     /* Unreserved, percent encoded characters aren't decoded in the userinfo becuase the scheme
887      * isn't known.
888      */
889     {   "zip://%2E:%52%53ord@winehq.org/", 0, S_OK, FALSE,
890         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
891         Uri_HAS_HOST|Uri_HAS_PASSWORD|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
892         Uri_HAS_SCHEME_NAME|Uri_HAS_USER_INFO|Uri_HAS_USER_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
893         TRUE,
894         {
895             {"zip://%2E:%52%53ord@winehq.org/",S_OK,TRUE},
896             {"%2E:%52%53ord@winehq.org",S_OK,FALSE},
897             {"zip://%2E:%52%53ord@winehq.org/",S_OK,TRUE},
898             {"winehq.org",S_OK,FALSE},
899             {"",S_FALSE,TRUE},
900             {"",S_FALSE,TRUE},
901             {"winehq.org",S_OK,FALSE},
902             {"%52%53ord",S_OK,FALSE},
903             {"/",S_OK,TRUE},
904             {"/",S_OK,TRUE},
905             {"",S_FALSE,TRUE},
906             {"zip://%2E:%52%53ord@winehq.org/",S_OK,FALSE},
907             {"zip",S_OK,FALSE},
908             {"%2E:%52%53ord",S_OK,FALSE},
909             {"%2E",S_OK,FALSE}
910         },
911         {
912             {Uri_HOST_DNS,S_OK,FALSE},
913             {0,S_FALSE,FALSE},
914             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
915             {URLZONE_INVALID,E_NOTIMPL,FALSE}
916         }
917     },
918     {   "ftp://[](),'test':word@winehq.org/", 0, S_OK, FALSE,
919         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
920         Uri_HAS_HOST|Uri_HAS_PASSWORD|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
921         Uri_HAS_SCHEME_NAME|Uri_HAS_USER_INFO|Uri_HAS_USER_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|
922         Uri_HAS_SCHEME,
923         TRUE,
924         {
925             {"ftp://[](),'test':word@winehq.org/",S_OK,TRUE},
926             {"[](),'test':word@winehq.org",S_OK,FALSE},
927             {"ftp://winehq.org/",S_OK,TRUE},
928             {"winehq.org",S_OK,FALSE},
929             {"",S_FALSE,TRUE},
930             {"",S_FALSE,TRUE},
931             {"winehq.org",S_OK,FALSE},
932             {"word",S_OK,FALSE},
933             {"/",S_OK,TRUE},
934             {"/",S_OK,TRUE},
935             {"",S_FALSE,TRUE},
936             {"ftp://[](),'test':word@winehq.org/",S_OK,FALSE},
937             {"ftp",S_OK,FALSE},
938             {"[](),'test':word",S_OK,FALSE},
939             {"[](),'test'",S_OK,FALSE}
940         },
941         {
942             {Uri_HOST_DNS,S_OK,FALSE},
943             {21,S_OK,FALSE},
944             {URL_SCHEME_FTP,S_OK,FALSE},
945             {URLZONE_INVALID,E_NOTIMPL,FALSE}
946         }
947     },
948     {   "ftp://test?:word@winehq.org/", 0, S_OK, FALSE,
949         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
950         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
951         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
952         TRUE,
953         {
954             {"ftp://test/?:word@winehq.org/",S_OK,TRUE},
955             {"test",S_OK,FALSE},
956             {"ftp://test/?:word@winehq.org/",S_OK,TRUE},
957             {"",S_FALSE,FALSE},
958             {"",S_FALSE,TRUE},
959             {"",S_FALSE,TRUE},
960             {"test",S_OK,FALSE},
961             {"",S_FALSE,FALSE},
962             {"/",S_OK,TRUE},
963             {"/?:word@winehq.org/",S_OK,TRUE},
964             {"?:word@winehq.org/",S_OK,TRUE},
965             {"ftp://test?:word@winehq.org/",S_OK,FALSE},
966             {"ftp",S_OK,FALSE},
967             {"",S_FALSE,FALSE},
968             {"",S_FALSE,FALSE}
969         },
970         {
971             {Uri_HOST_DNS,S_OK,FALSE},
972             {21,S_OK,FALSE},
973             {URL_SCHEME_FTP,S_OK,FALSE},
974             {URLZONE_INVALID,E_NOTIMPL,FALSE}
975         }
976     },
977     {   "ftp://test#:word@winehq.org/", 0, S_OK, FALSE,
978         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_FRAGMENT|Uri_HAS_HOST|
979         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
980         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
981         TRUE,
982         {
983             {"ftp://test/#:word@winehq.org/",S_OK,TRUE},
984             {"test",S_OK,FALSE},
985             {"ftp://test/#:word@winehq.org/",S_OK,TRUE},
986             {"",S_FALSE,FALSE},
987             {"",S_FALSE,TRUE},
988             {"#:word@winehq.org/",S_OK,TRUE},
989             {"test",S_OK,FALSE},
990             {"",S_FALSE,FALSE},
991             {"/",S_OK,TRUE},
992             {"/",S_OK,TRUE},
993             {"",S_FALSE,TRUE},
994             {"ftp://test#:word@winehq.org/",S_OK,FALSE},
995             {"ftp",S_OK,FALSE},
996             {"",S_FALSE,FALSE},
997             {"",S_FALSE,FALSE}
998         },
999         {
1000             {Uri_HOST_DNS,S_OK,FALSE},
1001             {21,S_OK,FALSE},
1002             {URL_SCHEME_FTP,S_OK,FALSE},
1003             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1004         }
1005     },
1006     /* Allowed to have a backslash in the userinfo since it's an unknown scheme. */
1007     {   "zip://test\\:word@winehq.org/", 0, S_OK, FALSE,
1008         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_HOST|
1009         Uri_HAS_PASSWORD|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1010         Uri_HAS_USER_INFO|Uri_HAS_USER_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
1011         TRUE,
1012         {
1013             {"zip://test\\:word@winehq.org/",S_OK,TRUE},
1014             {"test\\:word@winehq.org",S_OK,FALSE},
1015             {"zip://test\\:word@winehq.org/",S_OK,TRUE},
1016             {"winehq.org",S_OK,FALSE},
1017             {"",S_FALSE,TRUE},
1018             {"",S_FALSE,TRUE},
1019             {"winehq.org",S_OK,FALSE},
1020             {"word",S_OK,FALSE},
1021             {"/",S_OK,TRUE},
1022             {"/",S_OK,TRUE},
1023             {"",S_FALSE,TRUE},
1024             {"zip://test\\:word@winehq.org/",S_OK,FALSE},
1025             {"zip",S_OK,FALSE},
1026             {"test\\:word",S_OK,FALSE},
1027             {"test\\",S_OK,FALSE}
1028         },
1029         {
1030             {Uri_HOST_DNS,S_OK,FALSE},
1031             {0,S_FALSE,FALSE},
1032             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1033             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1034         }
1035     },
1036     /* It normalizes IPv4 addresses correctly. */
1037     {   "http://127.000.000.100/", 0, S_OK, FALSE,
1038         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
1039         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1040         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1041         TRUE,
1042         {
1043             {"http://127.0.0.100/",S_OK,TRUE},
1044             {"127.0.0.100",S_OK,FALSE},
1045             {"http://127.0.0.100/",S_OK,TRUE},
1046             {"",S_FALSE,FALSE},
1047             {"",S_FALSE,TRUE},
1048             {"",S_FALSE,TRUE},
1049             {"127.0.0.100",S_OK,FALSE},
1050             {"",S_FALSE,FALSE},
1051             {"/",S_OK,TRUE},
1052             {"/",S_OK,TRUE},
1053             {"",S_FALSE,TRUE},
1054             {"http://127.000.000.100/",S_OK,FALSE},
1055             {"http",S_OK,FALSE},
1056             {"",S_FALSE,FALSE},
1057             {"",S_FALSE,FALSE}
1058         },
1059         {
1060             {Uri_HOST_IPV4,S_OK,FALSE},
1061             {80,S_OK,FALSE},
1062             {URL_SCHEME_HTTP,S_OK,FALSE},
1063             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1064         }
1065     },
1066     /* Make sure it normalizes partial IPv4 addresses correctly. */
1067     {   "http://127.0/", 0, S_OK, FALSE,
1068         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
1069         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1070         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1071         TRUE,
1072         {
1073             {"http://127.0.0.0/",S_OK,TRUE},
1074             {"127.0.0.0",S_OK,FALSE},
1075             {"http://127.0.0.0/",S_OK,TRUE},
1076             {"",S_FALSE,FALSE},
1077             {"",S_FALSE,TRUE},
1078             {"",S_FALSE,TRUE},
1079             {"127.0.0.0",S_OK,FALSE},
1080             {"",S_FALSE,FALSE},
1081             {"/",S_OK,TRUE},
1082             {"/",S_OK,TRUE},
1083             {"",S_FALSE,TRUE},
1084             {"http://127.0/",S_OK,FALSE},
1085             {"http",S_OK,FALSE},
1086             {"",S_FALSE,FALSE},
1087             {"",S_FALSE,FALSE}
1088         },
1089         {
1090             {Uri_HOST_IPV4,S_OK,FALSE},
1091             {80,S_OK,FALSE},
1092             {URL_SCHEME_HTTP,S_OK,FALSE},
1093             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1094         }
1095     },
1096     /* Make sure it converts implicit IPv4's correctly. */
1097     {   "http://123456/", 0, S_OK, FALSE,
1098         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
1099         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1100         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1101         TRUE,
1102         {
1103             {"http://0.1.226.64/",S_OK,TRUE},
1104             {"0.1.226.64",S_OK,FALSE},
1105             {"http://0.1.226.64/",S_OK,TRUE},
1106             {"",S_FALSE,FALSE},
1107             {"",S_FALSE,TRUE},
1108             {"",S_FALSE,TRUE},
1109             {"0.1.226.64",S_OK,FALSE},
1110             {"",S_FALSE,FALSE},
1111             {"/",S_OK,TRUE},
1112             {"/",S_OK,TRUE},
1113             {"",S_FALSE,TRUE},
1114             {"http://123456/",S_OK,FALSE},
1115             {"http",S_OK,FALSE},
1116             {"",S_FALSE,FALSE},
1117             {"",S_FALSE,FALSE}
1118         },
1119         {
1120             {Uri_HOST_IPV4,S_OK,FALSE},
1121             {80,S_OK,FALSE},
1122             {URL_SCHEME_HTTP,S_OK,FALSE},
1123             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1124         }
1125     },
1126     /* UINT_MAX */
1127     {   "http://4294967295/", 0, S_OK, FALSE,
1128         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
1129         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1130         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1131         TRUE,
1132         {
1133             {"http://255.255.255.255/",S_OK,TRUE},
1134             {"255.255.255.255",S_OK,FALSE},
1135             {"http://255.255.255.255/",S_OK,TRUE},
1136             {"",S_FALSE,FALSE},
1137             {"",S_FALSE,TRUE},
1138             {"",S_FALSE,TRUE},
1139             {"255.255.255.255",S_OK,FALSE},
1140             {"",S_FALSE,FALSE},
1141             {"/",S_OK,TRUE},
1142             {"/",S_OK,TRUE},
1143             {"",S_FALSE,TRUE},
1144             {"http://4294967295/",S_OK,FALSE},
1145             {"http",S_OK,FALSE},
1146             {"",S_FALSE,FALSE},
1147             {"",S_FALSE,FALSE}
1148         },
1149         {
1150             {Uri_HOST_IPV4,S_OK,FALSE},
1151             {80,S_OK,FALSE},
1152             {URL_SCHEME_HTTP,S_OK,FALSE},
1153             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1154         }
1155     },
1156     /* UINT_MAX+1 */
1157     {   "http://4294967296/", 0, S_OK, FALSE,
1158         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
1159         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1160         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1161         TRUE,
1162         {
1163             {"http://4294967296/",S_OK,TRUE},
1164             {"4294967296",S_OK,FALSE},
1165             {"http://4294967296/",S_OK,TRUE},
1166             {"",S_FALSE,FALSE},
1167             {"",S_FALSE,TRUE},
1168             {"",S_FALSE,TRUE},
1169             {"4294967296",S_OK,FALSE},
1170             {"",S_FALSE,FALSE},
1171             {"/",S_OK,TRUE},
1172             {"/",S_OK,TRUE},
1173             {"",S_FALSE,TRUE},
1174             {"http://4294967296/",S_OK,FALSE},
1175             {"http",S_OK,FALSE},
1176             {"",S_FALSE,FALSE},
1177             {"",S_FALSE,FALSE}
1178         },
1179         {
1180             {Uri_HOST_DNS,S_OK,FALSE},
1181             {80,S_OK,FALSE},
1182             {URL_SCHEME_HTTP,S_OK,FALSE},
1183             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1184         }
1185     },
1186     /* Window's doesn't normalize IP address for unknown schemes. */
1187     {   "1234://4294967295/", 0, S_OK, FALSE,
1188         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
1189         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1190         Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
1191         TRUE,
1192         {
1193             {"1234://4294967295/",S_OK,TRUE},
1194             {"4294967295",S_OK,FALSE},
1195             {"1234://4294967295/",S_OK,TRUE},
1196             {"",S_FALSE,FALSE},
1197             {"",S_FALSE,TRUE},
1198             {"",S_FALSE,TRUE},
1199             {"4294967295",S_OK,FALSE},
1200             {"",S_FALSE,FALSE},
1201             {"/",S_OK,TRUE},
1202             {"/",S_OK,TRUE},
1203             {"",S_FALSE,TRUE},
1204             {"1234://4294967295/",S_OK,FALSE},
1205             {"1234",S_OK,FALSE},
1206             {"",S_FALSE,FALSE},
1207             {"",S_FALSE,FALSE}
1208         },
1209         {
1210             {Uri_HOST_IPV4,S_OK,FALSE},
1211             {0,S_FALSE,FALSE},
1212             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1213             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1214         }
1215     },
1216     /* Window's doesn't normalize IP address for unknown schemes. */
1217     {   "1234://127.001/", 0, S_OK, FALSE,
1218         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
1219         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1220         Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
1221         TRUE,
1222         {
1223             {"1234://127.001/",S_OK,TRUE},
1224             {"127.001",S_OK,FALSE},
1225             {"1234://127.001/",S_OK,TRUE},
1226             {"",S_FALSE,FALSE},
1227             {"",S_FALSE,TRUE},
1228             {"",S_FALSE,TRUE},
1229             {"127.001",S_OK,FALSE},
1230             {"",S_FALSE,FALSE},
1231             {"/",S_OK,TRUE},
1232             {"/",S_OK,TRUE},
1233             {"",S_FALSE,TRUE},
1234             {"1234://127.001/",S_OK,FALSE},
1235             {"1234",S_OK,FALSE},
1236             {"",S_FALSE,FALSE},
1237             {"",S_FALSE,FALSE}
1238         },
1239         {
1240             {Uri_HOST_IPV4,S_OK,FALSE},
1241             {0,S_FALSE,FALSE},
1242             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1243             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1244         }
1245     },
1246     {   "http://[FEDC:BA98::3210]", 0, S_OK, FALSE,
1247         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
1248         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1249         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1250         TRUE,
1251         {
1252             {"http://[fedc:ba98::3210]/",S_OK,TRUE},
1253             {"[fedc:ba98::3210]",S_OK,FALSE},
1254             {"http://[fedc:ba98::3210]/",S_OK,TRUE},
1255             {"",S_FALSE,FALSE},
1256             {"",S_FALSE,TRUE},
1257             {"",S_FALSE,TRUE},
1258             {"fedc:ba98::3210",S_OK,FALSE},
1259             {"",S_FALSE,FALSE},
1260             {"/",S_OK,TRUE},
1261             {"/",S_OK,TRUE},
1262             {"",S_FALSE,TRUE},
1263             {"http://[FEDC:BA98::3210]",S_OK,FALSE},
1264             {"http",S_OK,FALSE},
1265             {"",S_FALSE,FALSE},
1266             {"",S_FALSE,FALSE},
1267         },
1268         {
1269             {Uri_HOST_IPV6,S_OK,FALSE},
1270             {80,S_OK,FALSE},
1271             {URL_SCHEME_HTTP,S_OK,FALSE},
1272             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1273         }
1274     },
1275     {   "http://[::]", 0, S_OK, FALSE,
1276         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
1277         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1278         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1279         TRUE,
1280         {
1281             {"http://[::]/",S_OK,TRUE},
1282             {"[::]",S_OK,FALSE},
1283             {"http://[::]/",S_OK,TRUE},
1284             {"",S_FALSE,FALSE},
1285             {"",S_FALSE,TRUE},
1286             {"",S_FALSE,TRUE},
1287             {"::",S_OK,FALSE},
1288             {"",S_FALSE,FALSE},
1289             {"/",S_OK,TRUE},
1290             {"/",S_OK,TRUE},
1291             {"",S_FALSE,TRUE},
1292             {"http://[::]",S_OK,FALSE},
1293             {"http",S_OK,FALSE},
1294             {"",S_FALSE,FALSE},
1295             {"",S_FALSE,FALSE},
1296         },
1297         {
1298             {Uri_HOST_IPV6,S_OK,FALSE},
1299             {80,S_OK,FALSE},
1300             {URL_SCHEME_HTTP,S_OK,FALSE},
1301             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1302         }
1303     },
1304     {   "http://[FEDC:BA98::]", 0, S_OK, FALSE,
1305         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
1306         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1307         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1308         TRUE,
1309         {
1310             {"http://[fedc:ba98::]/",S_OK,TRUE},
1311             {"[fedc:ba98::]",S_OK,FALSE},
1312             {"http://[fedc:ba98::]/",S_OK,TRUE},
1313             {"",S_FALSE,FALSE},
1314             {"",S_FALSE,TRUE},
1315             {"",S_FALSE,TRUE},
1316             {"fedc:ba98::",S_OK,FALSE},
1317             {"",S_FALSE,FALSE},
1318             {"/",S_OK,TRUE},
1319             {"/",S_OK,TRUE},
1320             {"",S_FALSE,TRUE},
1321             {"http://[FEDC:BA98::]",S_OK,FALSE},
1322             {"http",S_OK,FALSE},
1323             {"",S_FALSE,FALSE},
1324             {"",S_FALSE,FALSE},
1325         },
1326         {
1327             {Uri_HOST_IPV6,S_OK,FALSE},
1328             {80,S_OK,FALSE},
1329             {URL_SCHEME_HTTP,S_OK,FALSE},
1330             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1331         }
1332     },
1333     /* Valid even with 2 byte elision because it doesn't appear the beginning or end. */
1334     {   "http://[1::3:4:5:6:7:8]", 0, S_OK, FALSE,
1335         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
1336         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1337         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1338         TRUE,
1339         {
1340             {"http://[1:0:3:4:5:6:7:8]/",S_OK,TRUE},
1341             {"[1:0:3:4:5:6:7:8]",S_OK,FALSE},
1342             {"http://[1:0:3:4:5:6:7:8]/",S_OK,TRUE},
1343             {"",S_FALSE,FALSE},
1344             {"",S_FALSE,TRUE},
1345             {"",S_FALSE,TRUE},
1346             {"1:0:3:4:5:6:7:8",S_OK,FALSE},
1347             {"",S_FALSE,FALSE},
1348             {"/",S_OK,TRUE},
1349             {"/",S_OK,TRUE},
1350             {"",S_FALSE,TRUE},
1351             {"http://[1::3:4:5:6:7:8]",S_OK,FALSE},
1352             {"http",S_OK,FALSE},
1353             {"",S_FALSE,FALSE},
1354             {"",S_FALSE,FALSE},
1355         },
1356         {
1357             {Uri_HOST_IPV6,S_OK,FALSE},
1358             {80,S_OK,FALSE},
1359             {URL_SCHEME_HTTP,S_OK,FALSE},
1360             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1361         }
1362     },
1363     {   "http://[v2.34]/", 0, S_OK, FALSE,
1364         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
1365         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1366         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1367         TRUE,
1368         {
1369             {"http://[v2.34]/",S_OK,TRUE},
1370             {"[v2.34]",S_OK,FALSE},
1371             {"http://[v2.34]/",S_OK,TRUE},
1372             {"",S_FALSE,FALSE},
1373             {"",S_FALSE,TRUE},
1374             {"",S_FALSE,TRUE},
1375             {"[v2.34]",S_OK,FALSE},
1376             {"",S_FALSE,FALSE},
1377             {"/",S_OK,TRUE},
1378             {"/",S_OK,TRUE},
1379             {"",S_FALSE,TRUE},
1380             {"http://[v2.34]/",S_OK,FALSE},
1381             {"http",S_OK,FALSE},
1382             {"",S_FALSE,FALSE},
1383             {"",S_FALSE,FALSE}
1384         },
1385         {
1386             {Uri_HOST_UNKNOWN,S_OK,FALSE},
1387             {80,S_OK,FALSE},
1388             {URL_SCHEME_HTTP,S_OK,FALSE},
1389             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1390         }
1391     },
1392     /* Windows ignores ':' if they appear after a '[' on a non-IPLiteral host. */
1393     {   "http://[xyz:12345.com/test", 0, S_OK, FALSE,
1394         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
1395         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
1396         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1397         TRUE,
1398         {
1399             {"http://[xyz:12345.com/test",S_OK,TRUE},
1400             {"[xyz:12345.com",S_OK,FALSE},
1401             {"http://[xyz:12345.com/test",S_OK,TRUE},
1402             {"[xyz:12345.com",S_OK,FALSE},
1403             {"",S_FALSE,TRUE},
1404             {"",S_FALSE,TRUE},
1405             {"[xyz:12345.com",S_OK,FALSE},
1406             {"",S_FALSE,FALSE},
1407             {"/test",S_OK,TRUE},
1408             {"/test",S_OK,TRUE},
1409             {"",S_FALSE,TRUE},
1410             {"http://[xyz:12345.com/test",S_OK,FALSE},
1411             {"http",S_OK,FALSE},
1412             {"",S_FALSE,FALSE},
1413             {"",S_FALSE,FALSE}
1414         },
1415         {
1416             {Uri_HOST_DNS,S_OK,FALSE},
1417             {80,S_OK,FALSE},
1418             {URL_SCHEME_HTTP,S_OK,FALSE},
1419             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1420         }
1421     },
1422     /* Valid URI since the '[' and ']' don't appear at the begining and end
1423      * of the host name (respectively).
1424      */
1425     {   "ftp://www.[works].com/", 0, S_OK, FALSE,
1426         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
1427         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
1428         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1429         TRUE,
1430         {
1431             {"ftp://www.[works].com/",S_OK,TRUE},
1432             {"www.[works].com",S_OK,FALSE},
1433             {"ftp://www.[works].com/",S_OK,TRUE},
1434             {"[works].com",S_OK,FALSE},
1435             {"",S_FALSE,TRUE},
1436             {"",S_FALSE,TRUE},
1437             {"www.[works].com",S_OK,FALSE},
1438             {"",S_FALSE,FALSE},
1439             {"/",S_OK,TRUE},
1440             {"/",S_OK,TRUE},
1441             {"",S_FALSE,TRUE},
1442             {"ftp://www.[works].com/",S_OK,FALSE},
1443             {"ftp",S_OK,FALSE},
1444             {"",S_FALSE,FALSE},
1445             {"",S_FALSE,FALSE}
1446         },
1447         {
1448             {Uri_HOST_DNS,S_OK,FALSE},
1449             {21,S_OK,FALSE},
1450             {URL_SCHEME_FTP,S_OK,FALSE},
1451             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1452         }
1453     },
1454     /* Considers ':' a delimiter since it appears after the ']'. */
1455     {   "http://www.google.com]:12345/", 0, S_OK, FALSE,
1456         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
1457         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
1458         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1459         TRUE,
1460         {
1461             {"http://www.google.com]:12345/",S_OK,TRUE},
1462             {"www.google.com]:12345",S_OK,FALSE},
1463             {"http://www.google.com]:12345/",S_OK,TRUE},
1464             {"google.com]",S_OK,FALSE},
1465             {"",S_FALSE,TRUE},
1466             {"",S_FALSE,TRUE},
1467             {"www.google.com]",S_OK,FALSE},
1468             {"",S_FALSE,FALSE},
1469             {"/",S_OK,TRUE},
1470             {"/",S_OK,TRUE},
1471             {"",S_FALSE,TRUE},
1472             {"http://www.google.com]:12345/",S_OK,FALSE},
1473             {"http",S_OK,FALSE},
1474             {"",S_FALSE,FALSE},
1475             {"",S_FALSE,FALSE}
1476         },
1477         {
1478             {Uri_HOST_DNS,S_OK,FALSE},
1479             {12345,S_OK,FALSE},
1480             {URL_SCHEME_HTTP,S_OK,FALSE},
1481             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1482         }
1483     },
1484     /* Unknown scheme types can have invalid % encoded data in the hostname. */
1485     {   "zip://w%XXw%GEw.google.com/", 0, S_OK, FALSE,
1486         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
1487         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
1488         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
1489         TRUE,
1490         {
1491             {"zip://w%XXw%GEw.google.com/",S_OK,TRUE},
1492             {"w%XXw%GEw.google.com",S_OK,FALSE},
1493             {"zip://w%XXw%GEw.google.com/",S_OK,TRUE},
1494             {"google.com",S_OK,FALSE},
1495             {"",S_FALSE,TRUE},
1496             {"",S_FALSE,TRUE},
1497             {"w%XXw%GEw.google.com",S_OK,FALSE},
1498             {"",S_FALSE,FALSE},
1499             {"/",S_OK,TRUE},
1500             {"/",S_OK,TRUE},
1501             {"",S_FALSE,TRUE},
1502             {"zip://w%XXw%GEw.google.com/",S_OK,FALSE},
1503             {"zip",S_OK,FALSE},
1504             {"",S_FALSE,FALSE},
1505             {"",S_FALSE,FALSE}
1506         },
1507         {
1508             {Uri_HOST_DNS,S_OK,FALSE},
1509             {0,S_FALSE,FALSE},
1510             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1511             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1512         }
1513     },
1514     /* Unknown scheme types hostname doesn't get lower cased. */
1515     {   "zip://GOOGLE.com/", 0, S_OK, FALSE,
1516         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
1517         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
1518         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
1519         TRUE,
1520         {
1521             {"zip://GOOGLE.com/",S_OK,TRUE},
1522             {"GOOGLE.com",S_OK,FALSE},
1523             {"zip://GOOGLE.com/",S_OK,TRUE},
1524             {"GOOGLE.com",S_OK,FALSE},
1525             {"",S_FALSE,TRUE},
1526             {"",S_FALSE,TRUE},
1527             {"GOOGLE.com",S_OK,FALSE},
1528             {"",S_FALSE,FALSE},
1529             {"/",S_OK,TRUE},
1530             {"/",S_OK,TRUE},
1531             {"",S_FALSE,TRUE},
1532             {"zip://GOOGLE.com/",S_OK,FALSE},
1533             {"zip",S_OK,FALSE},
1534             {"",S_FALSE,FALSE},
1535             {"",S_FALSE,FALSE}
1536         },
1537         {
1538             {Uri_HOST_DNS,S_OK,FALSE},
1539             {0,S_FALSE,FALSE},
1540             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1541             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1542         }
1543     },
1544     /* Hostname get's lower cased for known scheme types. */
1545     {   "http://WWW.GOOGLE.com/", 0, S_OK, FALSE,
1546         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
1547         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
1548         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1549         TRUE,
1550         {
1551             {"http://www.google.com/",S_OK,TRUE},
1552             {"www.google.com",S_OK,FALSE},
1553             {"http://www.google.com/",S_OK,TRUE},
1554             {"google.com",S_OK,FALSE},
1555             {"",S_FALSE,TRUE},
1556             {"",S_FALSE,TRUE},
1557             {"www.google.com",S_OK,FALSE},
1558             {"",S_FALSE,FALSE},
1559             {"/",S_OK,TRUE},
1560             {"/",S_OK,TRUE},
1561             {"",S_FALSE,TRUE},
1562             {"http://WWW.GOOGLE.com/",S_OK,FALSE},
1563             {"http",S_OK,FALSE},
1564             {"",S_FALSE,FALSE},
1565             {"",S_FALSE,FALSE}
1566         },
1567         {
1568             {Uri_HOST_DNS,S_OK,FALSE},
1569             {80,S_OK,FALSE},
1570             {URL_SCHEME_HTTP,S_OK,FALSE},
1571             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1572         }
1573     },
1574     /* Characters that get % encoded in the hostname also have their percent
1575      * encoded forms lower cased.
1576      */
1577     {   "http://www.%7Cgoogle|.com/", 0, S_OK, FALSE,
1578         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
1579         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
1580         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1581         TRUE,
1582         {
1583             {"http://www.%7cgoogle%7c.com/",S_OK,TRUE},
1584             {"www.%7cgoogle%7c.com",S_OK,FALSE},
1585             {"http://www.%7cgoogle%7c.com/",S_OK,TRUE},
1586             {"%7cgoogle%7c.com",S_OK,FALSE},
1587             {"",S_FALSE,TRUE},
1588             {"",S_FALSE,TRUE},
1589             {"www.%7cgoogle%7c.com",S_OK,FALSE},
1590             {"",S_FALSE,FALSE},
1591             {"/",S_OK,TRUE},
1592             {"/",S_OK,TRUE},
1593             {"",S_FALSE,TRUE},
1594             {"http://www.%7Cgoogle|.com/",S_OK,FALSE},
1595             {"http",S_OK,FALSE},
1596             {"",S_FALSE,FALSE},
1597             {"",S_FALSE,FALSE}
1598         },
1599         {
1600             {Uri_HOST_DNS,S_OK,FALSE},
1601             {80,S_OK,FALSE},
1602             {URL_SCHEME_HTTP,S_OK,FALSE},
1603             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1604         }
1605     },
1606     /* IPv4 addresses attached to IPv6 can be included in elisions. */
1607     {   "http://[1:2:3:4:5:6:0.0.0.0]", 0, S_OK, FALSE,
1608         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
1609         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1610         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1611         TRUE,
1612         {
1613             {"http://[1:2:3:4:5:6::]/",S_OK,TRUE},
1614             {"[1:2:3:4:5:6::]",S_OK,FALSE},
1615             {"http://[1:2:3:4:5:6::]/",S_OK,TRUE},
1616             {"",S_FALSE,FALSE},
1617             {"",S_FALSE,TRUE},
1618             {"",S_FALSE,TRUE},
1619             {"1:2:3:4:5:6::",S_OK,FALSE},
1620             {"",S_FALSE,FALSE},
1621             {"/",S_OK,TRUE},
1622             {"/",S_OK,TRUE},
1623             {"",S_FALSE,TRUE},
1624             {"http://[1:2:3:4:5:6:0.0.0.0]",S_OK,FALSE},
1625             {"http",S_OK,FALSE},
1626             {"",S_FALSE,FALSE},
1627             {"",S_FALSE,FALSE},
1628         },
1629         {
1630             {Uri_HOST_IPV6,S_OK,FALSE},
1631             {80,S_OK,FALSE},
1632             {URL_SCHEME_HTTP,S_OK,FALSE},
1633             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1634         }
1635     },
1636     /* IPv4 addresses get normalized. */
1637     {   "http://[::001.002.003.000]", 0, S_OK, FALSE,
1638         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
1639         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1640         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1641         TRUE,
1642         {
1643             {"http://[::1.2.3.0]/",S_OK,TRUE},
1644             {"[::1.2.3.0]",S_OK,FALSE},
1645             {"http://[::1.2.3.0]/",S_OK,TRUE},
1646             {"",S_FALSE,FALSE},
1647             {"",S_FALSE,TRUE},
1648             {"",S_FALSE,TRUE},
1649             {"::1.2.3.0",S_OK,FALSE},
1650             {"",S_FALSE,FALSE},
1651             {"/",S_OK,TRUE},
1652             {"/",S_OK,TRUE},
1653             {"",S_FALSE,TRUE},
1654             {"http://[::001.002.003.000]",S_OK,FALSE},
1655             {"http",S_OK,FALSE},
1656             {"",S_FALSE,FALSE},
1657             {"",S_FALSE,FALSE},
1658         },
1659         {
1660             {Uri_HOST_IPV6,S_OK,FALSE},
1661             {80,S_OK,FALSE},
1662             {URL_SCHEME_HTTP,S_OK,FALSE},
1663             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1664         }
1665     },
1666     /* Windows doesn't do anything to IPv6's in unknown schemes. */
1667     {   "zip://[0001:0:000:0004:0005:0006:001.002.003.000]", 0, S_OK, FALSE,
1668         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
1669         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1670         Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
1671         TRUE,
1672         {
1673             {"zip://[0001:0:000:0004:0005:0006:001.002.003.000]/",S_OK,TRUE},
1674             {"[0001:0:000:0004:0005:0006:001.002.003.000]",S_OK,FALSE},
1675             {"zip://[0001:0:000:0004:0005:0006:001.002.003.000]/",S_OK,TRUE},
1676             {"",S_FALSE,FALSE},
1677             {"",S_FALSE,TRUE},
1678             {"",S_FALSE,TRUE},
1679             {"0001:0:000:0004:0005:0006:001.002.003.000",S_OK,FALSE},
1680             {"",S_FALSE,FALSE},
1681             {"/",S_OK,TRUE},
1682             {"/",S_OK,TRUE},
1683             {"",S_FALSE,TRUE},
1684             {"zip://[0001:0:000:0004:0005:0006:001.002.003.000]",S_OK,FALSE},
1685             {"zip",S_OK,FALSE},
1686             {"",S_FALSE,FALSE},
1687             {"",S_FALSE,FALSE},
1688         },
1689         {
1690             {Uri_HOST_IPV6,S_OK,FALSE},
1691             {0,S_FALSE,FALSE},
1692             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1693             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1694         }
1695     },
1696     /* IPv4 address is converted into 2 h16 components. */
1697     {   "http://[ffff::192.222.111.32]", 0, S_OK, FALSE,
1698         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
1699         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1700         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1701         TRUE,
1702         {
1703             {"http://[ffff::c0de:6f20]/",S_OK,TRUE},
1704             {"[ffff::c0de:6f20]",S_OK,FALSE},
1705             {"http://[ffff::c0de:6f20]/",S_OK,TRUE},
1706             {"",S_FALSE,FALSE},
1707             {"",S_FALSE,TRUE},
1708             {"",S_FALSE,TRUE},
1709             {"ffff::c0de:6f20",S_OK,FALSE},
1710             {"",S_FALSE,FALSE},
1711             {"/",S_OK,TRUE},
1712             {"/",S_OK,TRUE},
1713             {"",S_FALSE,TRUE},
1714             {"http://[ffff::192.222.111.32]",S_OK,FALSE},
1715             {"http",S_OK,FALSE},
1716             {"",S_FALSE,FALSE},
1717             {"",S_FALSE,FALSE},
1718         },
1719         {
1720             {Uri_HOST_IPV6,S_OK,FALSE},
1721             {80,S_OK,FALSE},
1722             {URL_SCHEME_HTTP,S_OK,FALSE},
1723             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1724         }
1725     },
1726     /* Max value for a port. */
1727     {   "http://google.com:65535", 0, S_OK, FALSE,
1728         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
1729         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1730         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1731         TRUE,
1732         {
1733             {"http://google.com:65535/",S_OK,TRUE},
1734             {"google.com:65535",S_OK,FALSE},
1735             {"http://google.com:65535/",S_OK,TRUE},
1736             {"google.com",S_OK,FALSE},
1737             {"",S_FALSE,TRUE},
1738             {"",S_FALSE,TRUE},
1739             {"google.com",S_OK,FALSE},
1740             {"",S_FALSE,FALSE},
1741             {"/",S_OK,TRUE},
1742             {"/",S_OK,TRUE},
1743             {"",S_FALSE,TRUE},
1744             {"http://google.com:65535",S_OK,FALSE},
1745             {"http",S_OK,FALSE},
1746             {"",S_FALSE,FALSE},
1747             {"",S_FALSE,FALSE}
1748         },
1749         {
1750             {Uri_HOST_DNS,S_OK,FALSE},
1751             {65535,S_OK,FALSE},
1752             {URL_SCHEME_HTTP,S_OK,FALSE},
1753             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1754         }
1755     },
1756     {   "zip://google.com:65536", 0, S_OK, FALSE,
1757         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
1758         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1759         Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
1760         TRUE,
1761         {
1762             {"zip://google.com:65536/",S_OK,TRUE},
1763             {"google.com:65536",S_OK,FALSE},
1764             {"zip://google.com:65536/",S_OK,TRUE},
1765             {"google.com:65536",S_OK,FALSE},
1766             {"",S_FALSE,TRUE},
1767             {"",S_FALSE,TRUE},
1768             {"google.com:65536",S_OK,FALSE},
1769             {"",S_FALSE,FALSE},
1770             {"/",S_OK,TRUE},
1771             {"/",S_OK,TRUE},
1772             {"",S_FALSE,TRUE},
1773             {"zip://google.com:65536",S_OK,FALSE},
1774             {"zip",S_OK,FALSE},
1775             {"",S_FALSE,FALSE},
1776             {"",S_FALSE,FALSE}
1777         },
1778         {
1779             {Uri_HOST_DNS,S_OK,FALSE},
1780             {0,S_FALSE,FALSE},
1781             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1782             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1783         }
1784     },
1785     {   "zip://google.com:65536:25", 0, S_OK, FALSE,
1786         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
1787         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1788         Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
1789         TRUE,
1790         {
1791             {"zip://google.com:65536:25/",S_OK,TRUE},
1792             {"google.com:65536:25",S_OK,FALSE},
1793             {"zip://google.com:65536:25/",S_OK,TRUE},
1794             {"google.com:65536:25",S_OK,FALSE},
1795             {"",S_FALSE,TRUE},
1796             {"",S_FALSE,TRUE},
1797             {"google.com:65536:25",S_OK,FALSE},
1798             {"",S_FALSE,FALSE},
1799             {"/",S_OK,TRUE},
1800             {"/",S_OK,TRUE},
1801             {"",S_FALSE,TRUE},
1802             {"zip://google.com:65536:25",S_OK,FALSE},
1803             {"zip",S_OK,FALSE},
1804             {"",S_FALSE,FALSE},
1805             {"",S_FALSE,FALSE}
1806         },
1807         {
1808             {Uri_HOST_DNS,S_OK,FALSE},
1809             {0,S_FALSE,FALSE},
1810             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1811             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1812         }
1813     },
1814     {   "zip://[::ffff]:abcd", 0, S_OK, FALSE,
1815         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|
1816         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1817         Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
1818         TRUE,
1819         {
1820             {"zip://[::ffff]:abcd/",S_OK,TRUE},
1821             {"[::ffff]:abcd",S_OK,FALSE},
1822             {"zip://[::ffff]:abcd/",S_OK,TRUE},
1823             {"",S_FALSE,FALSE},
1824             {"",S_FALSE,TRUE},
1825             {"",S_FALSE,TRUE},
1826             {"[::ffff]:abcd",S_OK,FALSE},
1827             {"",S_FALSE,FALSE},
1828             {"/",S_OK,TRUE},
1829             {"/",S_OK,TRUE},
1830             {"",S_FALSE,TRUE},
1831             {"zip://[::ffff]:abcd",S_OK,FALSE},
1832             {"zip",S_OK,FALSE},
1833             {"",S_FALSE,FALSE},
1834             {"",S_FALSE,FALSE}
1835         },
1836         {
1837             {Uri_HOST_DNS,S_OK,FALSE},
1838             {0,S_FALSE,FALSE},
1839             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1840             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1841         }
1842     },
1843     {   "zip://127.0.0.1:abcd", 0, S_OK, FALSE,
1844         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
1845         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1846         Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
1847         TRUE,
1848         {
1849             {"zip://127.0.0.1:abcd/",S_OK,TRUE},
1850             {"127.0.0.1:abcd",S_OK,FALSE},
1851             {"zip://127.0.0.1:abcd/",S_OK,TRUE},
1852             {"0.1:abcd",S_OK,FALSE},
1853             {"",S_FALSE,TRUE},
1854             {"",S_FALSE,TRUE},
1855             {"127.0.0.1:abcd",S_OK,FALSE},
1856             {"",S_FALSE,FALSE},
1857             {"/",S_OK,TRUE},
1858             {"/",S_OK,TRUE},
1859             {"",S_FALSE,TRUE},
1860             {"zip://127.0.0.1:abcd",S_OK,FALSE},
1861             {"zip",S_OK,FALSE},
1862             {"",S_FALSE,FALSE},
1863             {"",S_FALSE,FALSE}
1864         },
1865         {
1866             {Uri_HOST_DNS,S_OK,FALSE},
1867             {0,S_FALSE,FALSE},
1868             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1869             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1870         }
1871     },
1872     /* Port is just copied over. */
1873     {   "http://google.com:00035", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
1874         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
1875         Uri_HAS_HOST|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1876         TRUE,
1877         {
1878             {"http://google.com:00035",S_OK,TRUE},
1879             {"google.com:00035",S_OK,FALSE},
1880             {"http://google.com:00035",S_OK,TRUE,"http://google.com:35"},
1881             {"google.com",S_OK,FALSE},
1882             {"",S_FALSE,TRUE},
1883             {"",S_FALSE,TRUE},
1884             {"google.com",S_OK,FALSE},
1885             {"",S_FALSE,FALSE},
1886             {"",S_FALSE,TRUE},
1887             {"",S_FALSE,TRUE},
1888             {"",S_FALSE,TRUE},
1889             {"http://google.com:00035",S_OK,FALSE},
1890             {"http",S_OK,FALSE},
1891             {"",S_FALSE,FALSE},
1892             {"",S_FALSE,FALSE}
1893         },
1894         {
1895             {Uri_HOST_DNS,S_OK,FALSE},
1896             {35,S_OK,FALSE},
1897             {URL_SCHEME_HTTP,S_OK,FALSE},
1898             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1899         }
1900     },
1901     /* Default port is copied over. */
1902     {   "http://google.com:80", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
1903         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
1904         Uri_HAS_HOST|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1905         TRUE,
1906         {
1907             {"http://google.com:80",S_OK,TRUE},
1908             {"google.com:80",S_OK,FALSE},
1909             {"http://google.com:80",S_OK,TRUE},
1910             {"google.com",S_OK,FALSE},
1911             {"",S_FALSE,TRUE},
1912             {"",S_FALSE,TRUE},
1913             {"google.com",S_OK,FALSE},
1914             {"",S_FALSE,FALSE},
1915             {"",S_FALSE,TRUE},
1916             {"",S_FALSE,TRUE},
1917             {"",S_FALSE,TRUE},
1918             {"http://google.com:80",S_OK,FALSE},
1919             {"http",S_OK,FALSE},
1920             {"",S_FALSE,FALSE},
1921             {"",S_FALSE,FALSE}
1922         },
1923         {
1924             {Uri_HOST_DNS,S_OK,FALSE},
1925             {80,S_OK,FALSE},
1926             {URL_SCHEME_HTTP,S_OK,FALSE},
1927             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1928         }
1929     },
1930     {   "http://google.com.uk", 0, S_OK, FALSE,
1931         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
1932         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1933         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1934         TRUE,
1935         {
1936             {"http://google.com.uk/",S_OK,TRUE},
1937             {"google.com.uk",S_OK,FALSE},
1938             {"http://google.com.uk/",S_OK,TRUE},
1939             {"google.com.uk",S_OK,FALSE},
1940             {"",S_FALSE,TRUE},
1941             {"",S_FALSE,TRUE},
1942             {"google.com.uk",S_OK,FALSE},
1943             {"",S_FALSE,FALSE},
1944             {"/",S_OK,TRUE},
1945             {"/",S_OK,TRUE},
1946             {"",S_FALSE,TRUE},
1947             {"http://google.com.uk",S_OK,FALSE},
1948             {"http",S_OK,FALSE},
1949             {"",S_FALSE,FALSE},
1950             {"",S_FALSE,FALSE}
1951         },
1952         {
1953             {Uri_HOST_DNS,S_OK,FALSE},
1954             {80,S_OK,FALSE},
1955             {URL_SCHEME_HTTP,S_OK,FALSE},
1956             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1957         }
1958     },
1959     {   "http://google.com.com", 0, S_OK, FALSE,
1960         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
1961         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1962         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1963         TRUE,
1964         {
1965             {"http://google.com.com/",S_OK,TRUE},
1966             {"google.com.com",S_OK,FALSE},
1967             {"http://google.com.com/",S_OK,TRUE},
1968             {"com.com",S_OK,FALSE},
1969             {"",S_FALSE,TRUE},
1970             {"",S_FALSE,TRUE},
1971             {"google.com.com",S_OK,FALSE},
1972             {"",S_FALSE,FALSE},
1973             {"/",S_OK,TRUE},
1974             {"/",S_OK,TRUE},
1975             {"",S_FALSE,TRUE},
1976             {"http://google.com.com",S_OK,FALSE},
1977             {"http",S_OK,FALSE},
1978             {"",S_FALSE,FALSE},
1979             {"",S_FALSE,FALSE}
1980         },
1981         {
1982             {Uri_HOST_DNS,S_OK,FALSE},
1983             {80,S_OK,FALSE},
1984             {URL_SCHEME_HTTP,S_OK,FALSE},
1985             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1986         }
1987     },
1988     {   "http://google.uk.1", 0, S_OK, FALSE,
1989         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
1990         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1991         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1992         TRUE,
1993         {
1994             {"http://google.uk.1/",S_OK,TRUE},
1995             {"google.uk.1",S_OK,FALSE},
1996             {"http://google.uk.1/",S_OK,TRUE},
1997             {"google.uk.1",S_OK,FALSE},
1998             {"",S_FALSE,TRUE},
1999             {"",S_FALSE,TRUE},
2000             {"google.uk.1",S_OK,FALSE},
2001             {"",S_FALSE,FALSE},
2002             {"/",S_OK,TRUE},
2003             {"/",S_OK,TRUE},
2004             {"",S_FALSE,TRUE},
2005             {"http://google.uk.1",S_OK,FALSE},
2006             {"http",S_OK,FALSE},
2007             {"",S_FALSE,FALSE},
2008             {"",S_FALSE,FALSE}
2009         },
2010         {
2011             {Uri_HOST_DNS,S_OK,FALSE},
2012             {80,S_OK,FALSE},
2013             {URL_SCHEME_HTTP,S_OK,FALSE},
2014             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2015         }
2016     },
2017     /* Since foo isn't a recognized 3 character TLD its considered the domain name. */
2018     {   "http://google.foo.uk", 0, S_OK, FALSE,
2019         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
2020         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
2021         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
2022         TRUE,
2023         {
2024             {"http://google.foo.uk/",S_OK,TRUE},
2025             {"google.foo.uk",S_OK,FALSE},
2026             {"http://google.foo.uk/",S_OK,TRUE},
2027             {"foo.uk",S_OK,FALSE},
2028             {"",S_FALSE,TRUE},
2029             {"",S_FALSE,TRUE},
2030             {"google.foo.uk",S_OK,FALSE},
2031             {"",S_FALSE,FALSE},
2032             {"/",S_OK,TRUE},
2033             {"/",S_OK,TRUE},
2034             {"",S_FALSE,TRUE},
2035             {"http://google.foo.uk",S_OK,FALSE},
2036             {"http",S_OK,FALSE},
2037             {"",S_FALSE,FALSE},
2038             {"",S_FALSE,FALSE}
2039         },
2040         {
2041             {Uri_HOST_DNS,S_OK,FALSE},
2042             {80,S_OK,FALSE},
2043             {URL_SCHEME_HTTP,S_OK,FALSE},
2044             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2045         }
2046     },
2047     {   "http://.com", 0, S_OK, FALSE,
2048         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
2049         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
2050         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
2051         TRUE,
2052         {
2053             {"http://.com/",S_OK,TRUE},
2054             {".com",S_OK,FALSE},
2055             {"http://.com/",S_OK,TRUE},
2056             {".com",S_OK,FALSE},
2057             {"",S_FALSE,TRUE},
2058             {"",S_FALSE,TRUE},
2059             {".com",S_OK,FALSE},
2060             {"",S_FALSE,FALSE},
2061             {"/",S_OK,TRUE},
2062             {"/",S_OK,TRUE},
2063             {"",S_FALSE,TRUE},
2064             {"http://.com",S_OK,FALSE},
2065             {"http",S_OK,FALSE},
2066             {"",S_FALSE,FALSE},
2067             {"",S_FALSE,FALSE}
2068         },
2069         {
2070             {Uri_HOST_DNS,S_OK,FALSE},
2071             {80,S_OK,FALSE},
2072             {URL_SCHEME_HTTP,S_OK,FALSE},
2073             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2074         }
2075     },
2076     {   "http://.uk", 0, S_OK, FALSE,
2077         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
2078         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
2079         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
2080         TRUE,
2081         {
2082             {"http://.uk/",S_OK,TRUE},
2083             {".uk",S_OK,FALSE},
2084             {"http://.uk/",S_OK,TRUE},
2085             {"",S_FALSE,FALSE},
2086             {"",S_FALSE,TRUE},
2087             {"",S_FALSE,TRUE},
2088             {".uk",S_OK,FALSE},
2089             {"",S_FALSE,FALSE},
2090             {"/",S_OK,TRUE},
2091             {"/",S_OK,TRUE},
2092             {"",S_FALSE,TRUE},
2093             {"http://.uk",S_OK,FALSE},
2094             {"http",S_OK,FALSE},
2095             {"",S_FALSE,FALSE},
2096             {"",S_FALSE,FALSE}
2097         },
2098         {
2099             {Uri_HOST_DNS,S_OK,FALSE},
2100             {80,S_OK,FALSE},
2101             {URL_SCHEME_HTTP,S_OK,FALSE},
2102             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2103         }
2104     },
2105     {   "http://www.co.google.com.[]", 0, S_OK, FALSE,
2106         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
2107         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
2108         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
2109         TRUE,
2110         {
2111             {"http://www.co.google.com.[]/",S_OK,TRUE},
2112             {"www.co.google.com.[]",S_OK,FALSE},
2113             {"http://www.co.google.com.[]/",S_OK,TRUE},
2114             {"google.com.[]",S_OK,FALSE},
2115             {"",S_FALSE,TRUE},
2116             {"",S_FALSE,TRUE},
2117             {"www.co.google.com.[]",S_OK,FALSE},
2118             {"",S_FALSE,FALSE},
2119             {"/",S_OK,TRUE},
2120             {"/",S_OK,TRUE},
2121             {"",S_FALSE,TRUE},
2122             {"http://www.co.google.com.[]",S_OK,FALSE},
2123             {"http",S_OK,FALSE},
2124             {"",S_FALSE,FALSE},
2125             {"",S_FALSE,FALSE}
2126         },
2127         {
2128             {Uri_HOST_DNS,S_OK,FALSE},
2129             {80,S_OK,FALSE},
2130             {URL_SCHEME_HTTP,S_OK,FALSE},
2131             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2132         }
2133     },
2134     {   "http://co.uk", 0, S_OK, FALSE,
2135         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
2136         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
2137         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
2138         TRUE,
2139         {
2140             {"http://co.uk/",S_OK,TRUE},
2141             {"co.uk",S_OK,FALSE},
2142             {"http://co.uk/",S_OK,TRUE},
2143             {"",S_FALSE,FALSE},
2144             {"",S_FALSE,TRUE},
2145             {"",S_FALSE,TRUE},
2146             {"co.uk",S_OK,FALSE},
2147             {"",S_FALSE,FALSE},
2148             {"/",S_OK,TRUE},
2149             {"/",S_OK,TRUE},
2150             {"",S_FALSE,TRUE},
2151             {"http://co.uk",S_OK,FALSE},
2152             {"http",S_OK,FALSE},
2153             {"",S_FALSE,FALSE},
2154             {"",S_FALSE,FALSE}
2155         },
2156         {
2157             {Uri_HOST_DNS,S_OK,FALSE},
2158             {80,S_OK,FALSE},
2159             {URL_SCHEME_HTTP,S_OK,FALSE},
2160             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2161         }
2162     },
2163     {   "http://www.co.google.us.test", 0, S_OK, FALSE,
2164         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
2165         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
2166         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
2167         TRUE,
2168         {
2169             {"http://www.co.google.us.test/",S_OK,TRUE},
2170             {"www.co.google.us.test",S_OK,FALSE},
2171             {"http://www.co.google.us.test/",S_OK,TRUE},
2172             {"us.test",S_OK,FALSE},
2173             {"",S_FALSE,TRUE},
2174             {"",S_FALSE,TRUE},
2175             {"www.co.google.us.test",S_OK,FALSE},
2176             {"",S_FALSE,FALSE},
2177             {"/",S_OK,TRUE},
2178             {"/",S_OK,TRUE},
2179             {"",S_FALSE,TRUE},
2180             {"http://www.co.google.us.test",S_OK,FALSE},
2181             {"http",S_OK,FALSE},
2182             {"",S_FALSE,FALSE},
2183             {"",S_FALSE,FALSE}
2184         },
2185         {
2186             {Uri_HOST_DNS,S_OK,FALSE},
2187             {80,S_OK,FALSE},
2188             {URL_SCHEME_HTTP,S_OK,FALSE},
2189             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2190         }
2191     },
2192     {   "http://gov.uk", 0, S_OK, FALSE,
2193         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
2194         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
2195         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
2196         TRUE,
2197         {
2198             {"http://gov.uk/",S_OK,TRUE},
2199             {"gov.uk",S_OK,FALSE},
2200             {"http://gov.uk/",S_OK,TRUE},
2201             {"",S_FALSE,FALSE},
2202             {"",S_FALSE,TRUE},
2203             {"",S_FALSE,TRUE},
2204             {"gov.uk",S_OK,FALSE},
2205             {"",S_FALSE,FALSE},
2206             {"/",S_OK,TRUE},
2207             {"/",S_OK,TRUE},
2208             {"",S_FALSE,TRUE},
2209             {"http://gov.uk",S_OK,FALSE},
2210             {"http",S_OK,FALSE},
2211             {"",S_FALSE,FALSE},
2212             {"",S_FALSE,FALSE}
2213         },
2214         {
2215             {Uri_HOST_DNS,S_OK,FALSE},
2216             {80,S_OK,FALSE},
2217             {URL_SCHEME_HTTP,S_OK,FALSE},
2218             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2219         }
2220     },
2221     {   "zip://www.google.com\\test", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
2222         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
2223         Uri_HAS_HOST|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
2224         TRUE,
2225         {
2226             {"zip://www.google.com\\test",S_OK,TRUE},
2227             {"www.google.com\\test",S_OK,FALSE},
2228             {"zip://www.google.com\\test",S_OK,TRUE},
2229             {"google.com\\test",S_OK,FALSE},
2230             {"",S_FALSE,TRUE},
2231             {"",S_FALSE,TRUE},
2232             {"www.google.com\\test",S_OK,FALSE},
2233             {"",S_FALSE,FALSE},
2234             {"",S_FALSE,TRUE},
2235             {"",S_FALSE,TRUE},
2236             {"",S_FALSE,TRUE},
2237             {"zip://www.google.com\\test",S_OK,FALSE},
2238             {"zip",S_OK,FALSE},
2239             {"",S_FALSE,FALSE},
2240             {"",S_FALSE,FALSE}
2241         },
2242         {
2243             {Uri_HOST_DNS,S_OK,FALSE},
2244             {0,S_FALSE,FALSE},
2245             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2246             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2247         }
2248     }
2249 };
2250
2251 typedef struct _invalid_uri {
2252     const char* uri;
2253     DWORD       flags;
2254     BOOL        todo;
2255 } invalid_uri;
2256
2257 static const invalid_uri invalid_uri_tests[] = {
2258     /* Has to have a scheme name. */
2259     {"://www.winehq.org",0,FALSE},
2260     /* Window's doesn't like URI's which are implicitly file paths without the
2261      * ALLOW_IMPLICIT_FILE_SCHEME flag set.
2262      */
2263     {"C:/test/test.mp3",0,FALSE},
2264     {"\\\\Server/test/test.mp3",0,FALSE},
2265     {"C:/test/test.mp3",Uri_CREATE_ALLOW_IMPLICIT_WILDCARD_SCHEME,FALSE},
2266     {"\\\\Server/test/test.mp3",Uri_CREATE_ALLOW_RELATIVE,FALSE},
2267     /* Invalid schemes. */
2268     {"*abcd://not.valid.com",0,FALSE},
2269     {"*a*b*c*d://not.valid.com",0,FALSE},
2270     /* Not allowed to have invalid % encoded data. */
2271     {"ftp://google.co%XX/",0,FALSE},
2272     /* To many h16 components. */
2273     {"http://[1:2:3:4:5:6:7:8:9]",0,FALSE},
2274     /* Not enough room for IPv4 address. */
2275     {"http://[1:2:3:4:5:6:7:192.0.1.0]",0,FALSE},
2276     /* Not enough h16 components. */
2277     {"http://[1:2:3:4]",0,FALSE},
2278     /* Not enough components including IPv4. */
2279     {"http://[1:192.0.1.0]",0,FALSE},
2280     /* Not allowed to have partial IPv4 in IPv6. */
2281     {"http://[::192.0]",0,FALSE},
2282     /* Can't have elision of 1 h16 at beginning of address. */
2283     {"http://[::2:3:4:5:6:7:8]",0,FALSE},
2284     /* Can't have elision of 1 h16 at end of address. */
2285     {"http://[1:2:3:4:5:6:7::]",0,FALSE},
2286     /* Expects a valid IP Literal. */
2287     {"ftp://[not.valid.uri]/",0,FALSE},
2288     /* Expects valid port for a known scheme type. */
2289     {"ftp://www.winehq.org:123fgh",0,FALSE},
2290     /* Port exceeds USHORT_MAX for known scheme type. */
2291     {"ftp://www.winehq.org:65536",0,FALSE},
2292     /* Invalid port with IPv4 address. */
2293     {"http://www.winehq.org:1abcd",0,FALSE},
2294     /* Invalid port with IPv6 address. */
2295     {"http://[::ffff]:32xy",0,FALSE},
2296     /* Not allowed to have backslashes with NO_CANONICALIZE. */
2297     {"gopher://www.google.com\\test",Uri_CREATE_NO_CANONICALIZE,FALSE}
2298 };
2299
2300 typedef struct _uri_equality {
2301     const char* a;
2302     DWORD       create_flags_a;
2303     BOOL        create_todo_a;
2304     const char* b;
2305     DWORD       create_flags_b;
2306     BOOL        create_todo_b;
2307     BOOL        equal;
2308     BOOL        todo;
2309 } uri_equality;
2310
2311 static const uri_equality equality_tests[] = {
2312     {
2313         "HTTP://www.winehq.org/test dir/./",0,FALSE,
2314         "http://www.winehq.org/test dir/../test dir/",0,FALSE,
2315         TRUE, TRUE
2316     },
2317     {
2318         /* http://www.winehq.org/test%20dir */
2319         "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,
2320         "http://www.winehq.org/test dir",0,FALSE,
2321         TRUE, TRUE,
2322     },
2323     {
2324         "c:\\test.mp3",Uri_CREATE_ALLOW_IMPLICIT_FILE_SCHEME,FALSE,
2325         "file:///c:/test.mp3",0,FALSE,
2326         TRUE,TRUE
2327     },
2328     {
2329         "ftp://ftp.winehq.org/",0,FALSE,
2330         "ftp://ftp.winehq.org",0,FALSE,
2331         TRUE, TRUE
2332     },
2333     {
2334         "ftp://ftp.winehq.org/test/test2/../../testB/",0,FALSE,
2335         "ftp://ftp.winehq.org/t%45stB/",0,FALSE,
2336         FALSE, TRUE
2337     }
2338 };
2339
2340 static inline LPWSTR a2w(LPCSTR str) {
2341     LPWSTR ret = NULL;
2342
2343     if(str) {
2344         DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
2345         ret = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
2346         MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len);
2347     }
2348
2349     return ret;
2350 }
2351
2352 static inline BOOL heap_free(void* mem) {
2353     return HeapFree(GetProcessHeap(), 0, mem);
2354 }
2355
2356 static inline DWORD strcmp_aw(LPCSTR strA, LPCWSTR strB) {
2357     LPWSTR strAW = a2w(strA);
2358     DWORD ret = lstrcmpW(strAW, strB);
2359     heap_free(strAW);
2360     return ret;
2361 }
2362
2363 /*
2364  * Simple tests to make sure the CreateUri function handles invalid flag combinations
2365  * correctly.
2366  */
2367 static void test_CreateUri_InvalidFlags(void) {
2368     DWORD i;
2369
2370     for(i = 0; i < sizeof(invalid_flag_tests)/sizeof(invalid_flag_tests[0]); ++i) {
2371         HRESULT hr;
2372         IUri *uri = (void*) 0xdeadbeef;
2373
2374         hr = pCreateUri(http_urlW, invalid_flag_tests[i].flags, 0, &uri);
2375         todo_wine {
2376             ok(hr == invalid_flag_tests[i].expected, "Error: CreateUri returned 0x%08x, expected 0x%08x, flags=0x%08x\n",
2377                     hr, invalid_flag_tests[i].expected, invalid_flag_tests[i].flags);
2378         }
2379         todo_wine { ok(uri == NULL, "Error: expected the IUri to be NULL, but it was %p instead\n", uri); }
2380     }
2381 }
2382
2383 static void test_CreateUri_InvalidArgs(void) {
2384     HRESULT hr;
2385     IUri *uri = (void*) 0xdeadbeef;
2386
2387     const WCHAR invalidW[] = {'i','n','v','a','l','i','d',0};
2388
2389     hr = pCreateUri(http_urlW, 0, 0, NULL);
2390     ok(hr == E_INVALIDARG, "Error: CreateUri returned 0x%08x, expected 0x%08x\n", hr, E_INVALIDARG);
2391
2392     hr = pCreateUri(NULL, 0, 0, &uri);
2393     ok(hr == E_INVALIDARG, "Error: CreateUri returned 0x%08x, expected 0x%08x\n", hr, E_INVALIDARG);
2394     ok(uri == NULL, "Error: Expected the IUri to be NULL, but it was %p instead\n", uri);
2395
2396     uri = (void*) 0xdeadbeef;
2397     hr = pCreateUri(invalidW, 0, 0, &uri);
2398     ok(hr == E_INVALIDARG, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
2399     ok(uri == NULL, "Error: Expected the IUri to be NULL, but it was %p instead\n", uri);
2400 }
2401
2402 static void test_CreateUri_InvalidUri(void) {
2403     DWORD i;
2404
2405     for(i = 0; i < sizeof(invalid_uri_tests)/sizeof(invalid_uri_tests[0]); ++i) {
2406         invalid_uri test = invalid_uri_tests[i];
2407         IUri *uri = NULL;
2408         LPWSTR uriW;
2409         HRESULT hr;
2410
2411         uriW = a2w(test.uri);
2412         hr = pCreateUri(uriW, test.flags, 0, &uri);
2413         if(test.todo) {
2414             todo_wine {
2415                 ok(hr == E_INVALIDARG, "Error: CreateUri returned 0x%08x, expected 0x%08x on invalid_uri_tests[%d].\n",
2416                     hr, E_INVALIDARG, i);
2417             }
2418         } else {
2419             ok(hr == E_INVALIDARG, "Error: CreateUri returned 0x%08x, expected 0x%08x on invalid_uri_tests[%d].\n",
2420                 hr, E_INVALIDARG, i);
2421         }
2422         if(uri) IUri_Release(uri);
2423
2424         heap_free(uriW);
2425     }
2426 }
2427
2428 static void test_IUri_GetPropertyBSTR(void) {
2429     IUri *uri = NULL;
2430     HRESULT hr;
2431     DWORD i;
2432
2433     /* Make sure GetPropertyBSTR handles invalid args correctly. */
2434     hr = pCreateUri(http_urlW, 0, 0, &uri);
2435     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
2436     if(SUCCEEDED(hr)) {
2437         BSTR received = NULL;
2438
2439         hr = IUri_GetPropertyBSTR(uri, Uri_PROPERTY_RAW_URI, NULL, 0);
2440         ok(hr == E_POINTER, "Error: GetPropertyBSTR returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
2441
2442         /* Make sure it handles a invalid Uri_PROPERTY's correctly. */
2443         hr = IUri_GetPropertyBSTR(uri, Uri_PROPERTY_PORT, &received, 0);
2444         ok(hr == S_OK, "Error: GetPropertyBSTR returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
2445         ok(received != NULL, "Error: Expected the string not to be NULL.\n");
2446         ok(!SysStringLen(received), "Error: Expected the string to be of len=0 but it was %d instead.\n", SysStringLen(received));
2447         SysFreeString(received);
2448
2449         /* Make sure it handles the ZONE property correctly. */
2450         received = NULL;
2451         hr = IUri_GetPropertyBSTR(uri, Uri_PROPERTY_ZONE, &received, 0);
2452         ok(hr == S_FALSE, "Error: GetPropertyBSTR returned 0x%08x, expected 0x%08x.\n", hr, S_FALSE);
2453         ok(received != NULL, "Error: Expected the string not to be NULL.\n");
2454         ok(!SysStringLen(received), "Error: Expected the string to be of len=0 but it was %d instead.\n", SysStringLen(received));
2455         SysFreeString(received);
2456     }
2457     if(uri) IUri_Release(uri);
2458
2459     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
2460         uri_properties test = uri_tests[i];
2461         LPWSTR uriW;
2462         uri = NULL;
2463
2464         uriW = a2w(test.uri);
2465         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
2466         if(test.create_todo) {
2467             todo_wine {
2468                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x. Failed on uri_tests[%d].\n",
2469                         hr, test.create_expected, i);
2470             }
2471         } else {
2472             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x. Failed on uri_tests[%d].\n",
2473                     hr, test.create_expected, i);
2474         }
2475
2476         if(SUCCEEDED(hr)) {
2477             DWORD j;
2478
2479             /* Checks all the string properties of the uri. */
2480             for(j = Uri_PROPERTY_STRING_START; j <= Uri_PROPERTY_STRING_LAST; ++j) {
2481                 BSTR received = NULL;
2482                 uri_str_property prop = test.str_props[j];
2483
2484                 hr = IUri_GetPropertyBSTR(uri, j, &received, 0);
2485                 if(prop.todo) {
2486                     todo_wine {
2487                         ok(hr == prop.expected, "GetPropertyBSTR returned 0x%08x, expected 0x%08x. On uri_tests[%d].str_props[%d].\n",
2488                                 hr, prop.expected, i, j);
2489                     }
2490                     todo_wine {
2491                         ok(!strcmp_aw(prop.value, received) || broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
2492                                 "Expected %s but got %s on uri_tests[%d].str_props[%d].\n",
2493                                 prop.value, wine_dbgstr_w(received), i, j);
2494                     }
2495                     if (hr == E_NOTIMPL)  /* no point in continuing */
2496                     {
2497                         if(uri) IUri_Release(uri);
2498                         heap_free(uriW);
2499                         return;
2500                     }
2501                 } else {
2502                     ok(hr == prop.expected, "GetPropertyBSTR returned 0x%08x, expected 0x%08x. On uri_tests[%d].str_props[%d].\n",
2503                             hr, prop.expected, i, j);
2504                     ok(!strcmp_aw(prop.value, received) || broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
2505                             "Expected %s but got %s on uri_tests[%d].str_props[%d].\n",
2506                             prop.value, wine_dbgstr_w(received), i, j);
2507                 }
2508
2509                 SysFreeString(received);
2510             }
2511         }
2512
2513         if(uri) IUri_Release(uri);
2514
2515         heap_free(uriW);
2516     }
2517 }
2518
2519 static void test_IUri_GetPropertyDWORD(void) {
2520     IUri *uri = NULL;
2521     HRESULT hr;
2522     DWORD i;
2523
2524     hr = pCreateUri(http_urlW, 0, 0, &uri);
2525     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
2526     if(SUCCEEDED(hr)) {
2527         DWORD received = 0xdeadbeef;
2528
2529         hr = IUri_GetPropertyDWORD(uri, Uri_PROPERTY_DWORD_START, NULL, 0);
2530         ok(hr == E_INVALIDARG, "Error: GetPropertyDWORD returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
2531
2532         hr = IUri_GetPropertyDWORD(uri, Uri_PROPERTY_ABSOLUTE_URI, &received, 0);
2533         ok(hr == E_INVALIDARG, "Error: GetPropertyDWORD returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
2534         ok(received == 0, "Error: Expected received=%d but instead received=%d.\n", 0, received);
2535     }
2536     if(uri) IUri_Release(uri);
2537
2538     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
2539         uri_properties test = uri_tests[i];
2540         LPWSTR uriW;
2541         uri = NULL;
2542
2543         uriW = a2w(test.uri);
2544         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
2545         if(test.create_todo) {
2546             todo_wine {
2547                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x. Failed on uri_tests[%d].\n",
2548                         hr, test.create_expected, i);
2549             }
2550         } else {
2551             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x. Failed on uri_tests[%d].\n",
2552                     hr, test.create_expected, i);
2553         }
2554
2555         if(SUCCEEDED(hr)) {
2556             DWORD j;
2557
2558             /* Checks all the DWORD properties of the uri. */
2559             for(j = 0; j < sizeof(test.dword_props)/sizeof(test.dword_props[0]); ++j) {
2560                 DWORD received;
2561                 uri_dword_property prop = test.dword_props[j];
2562
2563                 hr = IUri_GetPropertyDWORD(uri, j+Uri_PROPERTY_DWORD_START, &received, 0);
2564                 if(prop.todo) {
2565                     todo_wine {
2566                         ok(hr == prop.expected, "GetPropertyDWORD returned 0x%08x, expected 0x%08x. On uri_tests[%d].dword_props[%d].\n",
2567                                 hr, prop.expected, i, j);
2568                     }
2569                     todo_wine {
2570                         ok(prop.value == received, "Expected %d but got %d on uri_tests[%d].dword_props[%d].\n",
2571                                 prop.value, received, i, j);
2572                     }
2573                 } else {
2574                     ok(hr == prop.expected, "GetPropertyDWORD returned 0x%08x, expected 0x%08x. On uri_tests[%d].dword_props[%d].\n",
2575                             hr, prop.expected, i, j);
2576                     ok(prop.value == received, "Expected %d but got %d on uri_tests[%d].dword_props[%d].\n",
2577                             prop.value, received, i, j);
2578                 }
2579             }
2580         }
2581
2582         if(uri) IUri_Release(uri);
2583
2584         heap_free(uriW);
2585     }
2586 }
2587
2588 /* Tests all the 'Get*' property functions which deal with strings. */
2589 static void test_IUri_GetStrProperties(void) {
2590     IUri *uri = NULL;
2591     HRESULT hr;
2592     DWORD i;
2593
2594     /* Make sure all the 'Get*' string property functions handle invalid args correctly. */
2595     hr = pCreateUri(http_urlW, 0, 0, &uri);
2596     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
2597     if(SUCCEEDED(hr)) {
2598         hr = IUri_GetAbsoluteUri(uri, NULL);
2599         ok(hr == E_POINTER, "Error: GetAbsoluteUri returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
2600
2601         hr = IUri_GetAuthority(uri, NULL);
2602         ok(hr == E_POINTER, "Error: GetAuthority returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
2603
2604         hr = IUri_GetDisplayUri(uri, NULL);
2605         ok(hr == E_POINTER, "Error: GetDisplayUri returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
2606
2607         hr = IUri_GetDomain(uri, NULL);
2608         ok(hr == E_POINTER, "Error: GetDomain returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
2609
2610         hr = IUri_GetExtension(uri, NULL);
2611         ok(hr == E_POINTER, "Error: GetExtension returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
2612
2613         hr = IUri_GetFragment(uri, NULL);
2614         ok(hr == E_POINTER, "Error: GetFragment returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
2615
2616         hr = IUri_GetHost(uri, NULL);
2617         ok(hr == E_POINTER, "Error: GetHost returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
2618
2619         hr = IUri_GetPassword(uri, NULL);
2620         ok(hr == E_POINTER, "Error: GetPassword returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
2621
2622         hr = IUri_GetPath(uri, NULL);
2623         ok(hr == E_POINTER, "Error: GetPath returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
2624
2625         hr = IUri_GetPathAndQuery(uri, NULL);
2626         ok(hr == E_POINTER, "Error: GetPathAndQuery returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
2627
2628         hr = IUri_GetQuery(uri, NULL);
2629         ok(hr == E_POINTER, "Error: GetQuery returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
2630
2631         hr = IUri_GetRawUri(uri, NULL);
2632         ok(hr == E_POINTER, "Error: GetRawUri returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
2633
2634         hr = IUri_GetSchemeName(uri, NULL);
2635         ok(hr == E_POINTER, "Error: GetSchemeName returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
2636
2637         hr = IUri_GetUserInfo(uri, NULL);
2638         ok(hr == E_POINTER, "Error: GetUserInfo returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
2639
2640         hr = IUri_GetUserName(uri, NULL);
2641         ok(hr == E_POINTER, "Error: GetUserName returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
2642     }
2643     if(uri) IUri_Release(uri);
2644
2645     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
2646         uri_properties test = uri_tests[i];
2647         LPWSTR uriW;
2648         uri = NULL;
2649
2650         uriW = a2w(test.uri);
2651         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
2652         if(test.create_todo) {
2653             todo_wine {
2654                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
2655                         hr, test.create_expected, i);
2656             }
2657         } else {
2658             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
2659                     hr, test.create_expected, i);
2660         }
2661
2662         if(SUCCEEDED(hr)) {
2663             uri_str_property prop;
2664             BSTR received = NULL;
2665
2666             /* GetAbsoluteUri() tests. */
2667             prop = test.str_props[Uri_PROPERTY_ABSOLUTE_URI];
2668             hr = IUri_GetAbsoluteUri(uri, &received);
2669             if (hr == E_NOTIMPL) goto skip_unimplemented;
2670             if(prop.todo) {
2671                 todo_wine {
2672                     ok(hr == prop.expected, "Error: GetAbsoluteUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
2673                             hr, prop.expected, i);
2674                 }
2675                 todo_wine {
2676                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
2677                             prop.value, wine_dbgstr_w(received), i);
2678                 }
2679             } else {
2680                 ok(hr == prop.expected, "Error: GetAbsoluteUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
2681                         hr, prop.expected, i);
2682                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
2683                         prop.value, wine_dbgstr_w(received), i);
2684             }
2685             SysFreeString(received);
2686             received = NULL;
2687
2688             /* GetDisplayUri() tests. */
2689             prop = test.str_props[Uri_PROPERTY_DISPLAY_URI];
2690             hr = IUri_GetDisplayUri(uri, &received);
2691             if(prop.todo) {
2692                 todo_wine {
2693                     ok(hr == prop.expected, "Error: GetDisplayUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
2694                             hr, prop.expected, i);
2695                 }
2696                 todo_wine {
2697                     ok(!strcmp_aw(prop.value, received) || broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
2698                             "Error: Expected %s but got %s on uri_test[%d].\n",
2699                             prop.value, wine_dbgstr_w(received), i);
2700                 }
2701             } else {
2702                 ok(hr == prop.expected, "Error: GetDisplayUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
2703                         hr, prop.expected, i);
2704                 ok(!strcmp_aw(prop.value, received) || broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
2705                         "Error: Expected %s but got %s on uri_tests[%d].\n",
2706                         prop.value, wine_dbgstr_w(received), i);
2707             }
2708             SysFreeString(received);
2709             received = NULL;
2710
2711             /* GetExtension() tests. */
2712             prop = test.str_props[Uri_PROPERTY_EXTENSION];
2713             hr = IUri_GetExtension(uri, &received);
2714             if(prop.todo) {
2715                 todo_wine {
2716                     ok(hr == prop.expected, "Error: GetExtension returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
2717                             hr, prop.expected, i);
2718                 }
2719                 todo_wine {
2720                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
2721                             prop.value, wine_dbgstr_w(received), i);
2722                 }
2723             } else {
2724                 ok(hr == prop.expected, "Error: GetExtension returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
2725                         hr, prop.expected, i);
2726                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
2727                         prop.value, wine_dbgstr_w(received), i);
2728             }
2729             SysFreeString(received);
2730             received = NULL;
2731
2732             /* GetFragment() tests. */
2733             prop = test.str_props[Uri_PROPERTY_FRAGMENT];
2734             hr = IUri_GetFragment(uri, &received);
2735             if(prop.todo) {
2736                 todo_wine {
2737                     ok(hr == prop.expected, "Error: GetFragment returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
2738                             hr, prop.expected, i);
2739                 }
2740                 todo_wine {
2741                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
2742                             prop.value, wine_dbgstr_w(received), i);
2743                 }
2744             } else {
2745                 ok(hr == prop.expected, "Error: GetFragment returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
2746                         hr, prop.expected, i);
2747                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
2748                         prop.value, wine_dbgstr_w(received), i);
2749             }
2750             SysFreeString(received);
2751             received = NULL;
2752
2753             /* GetPassword() tests. */
2754             prop = test.str_props[Uri_PROPERTY_PASSWORD];
2755             hr = IUri_GetPassword(uri, &received);
2756             if(prop.todo) {
2757                 todo_wine {
2758                     ok(hr == prop.expected, "Error: GetPassword returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
2759                             hr, prop.expected, i);
2760                 }
2761                 todo_wine {
2762                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
2763                             prop.value, wine_dbgstr_w(received), i);
2764                 }
2765             } else {
2766                 ok(hr == prop.expected, "Error: GetPassword returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
2767                         hr, prop.expected, i);
2768                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
2769                         prop.value, wine_dbgstr_w(received), i);
2770             }
2771             SysFreeString(received);
2772             received = NULL;
2773
2774         skip_unimplemented:
2775             /* GetAuthority() tests. */
2776             prop = test.str_props[Uri_PROPERTY_AUTHORITY];
2777             hr = IUri_GetAuthority(uri, &received);
2778             if(prop.todo) {
2779                 todo_wine {
2780                     ok(hr == prop.expected, "Error: GetAuthority returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
2781                             hr, prop.expected, i);
2782                 }
2783                 todo_wine {
2784                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
2785                             prop.value, wine_dbgstr_w(received), i);
2786                 }
2787             } else {
2788                 ok(hr == prop.expected, "Error: GetAuthority returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
2789                         hr, prop.expected, i);
2790                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
2791                         prop.value, wine_dbgstr_w(received), i);
2792             }
2793             SysFreeString(received);
2794             received = NULL;
2795
2796             /* GetDomain() tests. */
2797             prop = test.str_props[Uri_PROPERTY_DOMAIN];
2798             hr = IUri_GetDomain(uri, &received);
2799             if(prop.todo) {
2800                 todo_wine {
2801                     ok(hr == prop.expected, "Error: GetDomain returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
2802                             hr, prop.expected, i);
2803                 }
2804                 todo_wine {
2805                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
2806                             prop.value, wine_dbgstr_w(received), i);
2807                 }
2808             } else {
2809                 ok(hr == prop.expected, "Error: GetDomain returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
2810                         hr, prop.expected, i);
2811                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
2812                         prop.value, wine_dbgstr_w(received), i);
2813             }
2814             SysFreeString(received);
2815             received = NULL;
2816
2817             /* GetHost() tests. */
2818             prop = test.str_props[Uri_PROPERTY_HOST];
2819             hr = IUri_GetHost(uri, &received);
2820             if(prop.todo) {
2821                 todo_wine {
2822                     ok(hr == prop.expected, "Error: GetHost returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
2823                             hr, prop.expected, i);
2824                 }
2825                 todo_wine {
2826                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
2827                             prop.value, wine_dbgstr_w(received), i);
2828                 }
2829             } else {
2830                 ok(hr == prop.expected, "Error: GetHost returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
2831                         hr, prop.expected, i);
2832                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
2833                         prop.value, wine_dbgstr_w(received), i);
2834             }
2835             SysFreeString(received);
2836             received = NULL;
2837
2838             /* GetPath() tests. */
2839             prop = test.str_props[Uri_PROPERTY_PATH];
2840             hr = IUri_GetPath(uri, &received);
2841             if(prop.todo) {
2842                 todo_wine {
2843                     ok(hr == prop.expected, "Error: GetPath returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
2844                             hr, prop.expected, i);
2845                 }
2846                 todo_wine {
2847                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
2848                             prop.value, wine_dbgstr_w(received), i);
2849                 }
2850             } else {
2851                 ok(hr == prop.expected, "Error: GetPath returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
2852                         hr, prop.expected, i);
2853                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
2854                         prop.value, wine_dbgstr_w(received), i);
2855             }
2856             SysFreeString(received);
2857             received = NULL;
2858
2859             /* GetPathAndQuery() tests. */
2860             prop = test.str_props[Uri_PROPERTY_PATH_AND_QUERY];
2861             hr = IUri_GetPathAndQuery(uri, &received);
2862             if(prop.todo) {
2863                 todo_wine {
2864                     ok(hr == prop.expected, "Error: GetPathAndQuery returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
2865                             hr, prop.expected, i);
2866                 }
2867                 todo_wine {
2868                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
2869                             prop.value, wine_dbgstr_w(received), i);
2870                 }
2871             } else {
2872                 ok(hr == prop.expected, "Error: GetPathAndQuery returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
2873                         hr, prop.expected, i);
2874                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
2875                         prop.value, wine_dbgstr_w(received), i);
2876             }
2877             SysFreeString(received);
2878             received = NULL;
2879
2880             /* GetQuery() tests. */
2881             prop = test.str_props[Uri_PROPERTY_QUERY];
2882             hr = IUri_GetQuery(uri, &received);
2883             if(prop.todo) {
2884                 todo_wine {
2885                     ok(hr == prop.expected, "Error: GetQuery returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
2886                             hr, prop.expected, i);
2887                 }
2888                 todo_wine {
2889                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
2890                             prop.value, wine_dbgstr_w(received), i);
2891                 }
2892             } else {
2893                 ok(hr == prop.expected, "Error: GetQuery returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
2894                         hr, prop.expected, i);
2895                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
2896                         prop.value, wine_dbgstr_w(received), i);
2897             }
2898             SysFreeString(received);
2899             received = NULL;
2900
2901             /* GetRawUri() tests. */
2902             prop = test.str_props[Uri_PROPERTY_RAW_URI];
2903             hr = IUri_GetRawUri(uri, &received);
2904             if(prop.todo) {
2905                 todo_wine {
2906                     ok(hr == prop.expected, "Error: GetRawUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
2907                             hr, prop.expected, i);
2908                 }
2909                 todo_wine {
2910                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
2911                             prop.value, wine_dbgstr_w(received), i);
2912                 }
2913             } else {
2914                 ok(hr == prop.expected, "Error: GetRawUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
2915                         hr, prop.expected, i);
2916                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
2917                         prop.value, wine_dbgstr_w(received), i);
2918             }
2919             SysFreeString(received);
2920             received = NULL;
2921
2922             /* GetSchemeName() tests. */
2923             prop = test.str_props[Uri_PROPERTY_SCHEME_NAME];
2924             hr = IUri_GetSchemeName(uri, &received);
2925             if(prop.todo) {
2926                 todo_wine {
2927                     ok(hr == prop.expected, "Error: GetSchemeName returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
2928                             hr, prop.expected, i);
2929                 }
2930                 todo_wine {
2931                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
2932                             prop.value, wine_dbgstr_w(received), i);
2933                 }
2934             } else {
2935                 ok(hr == prop.expected, "Error: GetSchemeName returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
2936                         hr, prop.expected, i);
2937                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
2938                         prop.value, wine_dbgstr_w(received), i);
2939             }
2940             SysFreeString(received);
2941             received = NULL;
2942
2943             /* GetUserInfo() tests. */
2944             prop = test.str_props[Uri_PROPERTY_USER_INFO];
2945             hr = IUri_GetUserInfo(uri, &received);
2946             if(prop.todo) {
2947                 todo_wine {
2948                     ok(hr == prop.expected, "Error: GetUserInfo returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
2949                             hr, prop.expected, i);
2950                 }
2951                 todo_wine {
2952                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
2953                             prop.value, wine_dbgstr_w(received), i);
2954                 }
2955             } else {
2956                 ok(hr == prop.expected, "Error: GetUserInfo returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
2957                         hr, prop.expected, i);
2958                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
2959                         prop.value, wine_dbgstr_w(received), i);
2960             }
2961             SysFreeString(received);
2962             received = NULL;
2963
2964             /* GetUserName() tests. */
2965             prop = test.str_props[Uri_PROPERTY_USER_NAME];
2966             hr = IUri_GetUserName(uri, &received);
2967             if(prop.todo) {
2968                 todo_wine {
2969                     ok(hr == prop.expected, "Error: GetUserName returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
2970                             hr, prop.expected, i);
2971                 }
2972                 todo_wine {
2973                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
2974                             prop.value, wine_dbgstr_w(received), i);
2975                 }
2976             } else {
2977                 ok(hr == prop.expected, "Error: GetUserName returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
2978                         hr, prop.expected, i);
2979                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
2980                         prop.value, wine_dbgstr_w(received), i);
2981             }
2982             SysFreeString(received);
2983         }
2984
2985         if(uri) IUri_Release(uri);
2986
2987         heap_free(uriW);
2988     }
2989 }
2990
2991 static void test_IUri_GetDwordProperties(void) {
2992     IUri *uri = NULL;
2993     HRESULT hr;
2994     DWORD i;
2995
2996     /* Make sure all the 'Get*' dword property functions handle invalid args correctly. */
2997     hr = pCreateUri(http_urlW, 0, 0, &uri);
2998     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
2999     if(SUCCEEDED(hr)) {
3000         hr = IUri_GetHostType(uri, NULL);
3001         ok(hr == E_INVALIDARG, "Error: GetHostType returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
3002
3003         hr = IUri_GetPort(uri, NULL);
3004         ok(hr == E_INVALIDARG, "Error: GetPort returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
3005
3006         hr = IUri_GetScheme(uri, NULL);
3007         ok(hr == E_INVALIDARG, "Error: GetScheme returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
3008
3009         hr = IUri_GetZone(uri, NULL);
3010         ok(hr == E_INVALIDARG, "Error: GetZone returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
3011     }
3012     if(uri) IUri_Release(uri);
3013
3014     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
3015         uri_properties test = uri_tests[i];
3016         LPWSTR uriW;
3017         uri = NULL;
3018
3019         uriW = a2w(test.uri);
3020         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
3021         if(test.create_todo) {
3022             todo_wine {
3023                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
3024                         hr, test.create_expected, i);
3025             }
3026         } else {
3027             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
3028                     hr, test.create_expected, i);
3029         }
3030
3031         if(SUCCEEDED(hr)) {
3032             uri_dword_property prop;
3033             DWORD received;
3034
3035             /* Assign an insane value so tests don't accidentally pass when
3036              * they shouldn't!
3037              */
3038             received = -9999999;
3039
3040             /* GetHostType() tests. */
3041             prop = test.dword_props[Uri_PROPERTY_HOST_TYPE-Uri_PROPERTY_DWORD_START];
3042             hr = IUri_GetHostType(uri, &received);
3043             if(prop.todo) {
3044                 todo_wine {
3045                     ok(hr == prop.expected, "Error: GetHostType returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
3046                             hr, prop.expected, i);
3047                 }
3048                 todo_wine {
3049                     ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
3050                 }
3051             } else {
3052                 ok(hr == prop.expected, "Error: GetHostType returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
3053                         hr, prop.expected, i);
3054                 ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
3055             }
3056             received = -9999999;
3057
3058             /* GetPort() tests. */
3059             prop = test.dword_props[Uri_PROPERTY_PORT-Uri_PROPERTY_DWORD_START];
3060             hr = IUri_GetPort(uri, &received);
3061             if(prop.todo) {
3062                 todo_wine {
3063                     ok(hr == prop.expected, "Error: GetPort returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
3064                             hr, prop.expected, i);
3065                 }
3066                 todo_wine {
3067                     ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
3068                 }
3069             } else {
3070                 ok(hr == prop.expected, "Error: GetPort returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
3071                         hr, prop.expected, i);
3072                 ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
3073             }
3074             received = -9999999;
3075
3076             /* GetScheme() tests. */
3077             prop = test.dword_props[Uri_PROPERTY_SCHEME-Uri_PROPERTY_DWORD_START];
3078             hr = IUri_GetScheme(uri, &received);
3079             if(prop.todo) {
3080                 todo_wine {
3081                     ok(hr == prop.expected, "Error: GetScheme returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
3082                             hr, prop.expected, i);
3083                 }
3084                 todo_wine {
3085                     ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
3086                 }
3087             } else {
3088                 ok(hr == prop.expected, "Error: GetScheme returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
3089                         hr, prop.expected, i);
3090                 ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
3091             }
3092             received = -9999999;
3093
3094             /* GetZone() tests. */
3095             prop = test.dword_props[Uri_PROPERTY_ZONE-Uri_PROPERTY_DWORD_START];
3096             hr = IUri_GetZone(uri, &received);
3097             if(prop.todo) {
3098                 todo_wine {
3099                     ok(hr == prop.expected, "Error: GetZone returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
3100                             hr, prop.expected, i);
3101                 }
3102                 todo_wine {
3103                     ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
3104                 }
3105             } else {
3106                 ok(hr == prop.expected, "Error: GetZone returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
3107                         hr, prop.expected, i);
3108                 ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
3109             }
3110         }
3111
3112         if(uri) IUri_Release(uri);
3113
3114         heap_free(uriW);
3115     }
3116 }
3117
3118 static void test_IUri_GetPropertyLength(void) {
3119     IUri *uri = NULL;
3120     HRESULT hr;
3121     DWORD i;
3122
3123     /* Make sure it handles invalid args correctly. */
3124     hr = pCreateUri(http_urlW, 0, 0, &uri);
3125     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
3126     if(SUCCEEDED(hr)) {
3127         DWORD received = 0xdeadbeef;
3128
3129         hr = IUri_GetPropertyLength(uri, Uri_PROPERTY_STRING_START, NULL, 0);
3130         ok(hr == E_INVALIDARG, "Error: GetPropertyLength returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
3131
3132         hr = IUri_GetPropertyLength(uri, Uri_PROPERTY_DWORD_START, &received, 0);
3133         ok(hr == E_INVALIDARG, "Error: GetPropertyLength return 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
3134         ok(received == 0xdeadbeef, "Error: Expected 0xdeadbeef but got 0x%08x.\n", received);
3135     }
3136     if(uri) IUri_Release(uri);
3137
3138     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
3139         uri_properties test = uri_tests[i];
3140         LPWSTR uriW;
3141         uri = NULL;
3142
3143         uriW = a2w(test.uri);
3144         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
3145         if(test.create_todo) {
3146             todo_wine {
3147                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
3148                         hr, test.create_expected, i);
3149             }
3150         } else {
3151             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_test[%d].\n",
3152                     hr, test.create_expected, i);
3153         }
3154
3155         if(SUCCEEDED(hr)) {
3156             DWORD j;
3157
3158             for(j = Uri_PROPERTY_STRING_START; j <= Uri_PROPERTY_STRING_LAST; ++j) {
3159                 DWORD expectedLen, brokenLen, receivedLen;
3160                 uri_str_property prop = test.str_props[j];
3161
3162                 expectedLen = lstrlen(prop.value);
3163                 brokenLen = lstrlen(prop.broken_value);
3164
3165                 /* This won't be necessary once GetPropertyLength is implemented. */
3166                 receivedLen = -1;
3167
3168                 hr = IUri_GetPropertyLength(uri, j, &receivedLen, 0);
3169                 if(prop.todo) {
3170                     todo_wine {
3171                         ok(hr == prop.expected, "Error: GetPropertyLength returned 0x%08x, expected 0x%08x on uri_tests[%d].str_props[%d].\n",
3172                                 hr, prop.expected, i, j);
3173                     }
3174                     todo_wine {
3175                         ok(receivedLen == expectedLen || broken(receivedLen == brokenLen),
3176                                 "Error: Expected a length of %d but got %d on uri_tests[%d].str_props[%d].\n",
3177                                 expectedLen, receivedLen, i, j);
3178                     }
3179                     if (hr == E_NOTIMPL)  /* no point in continuing */
3180                     {
3181                         if(uri) IUri_Release(uri);
3182                         heap_free(uriW);
3183                         return;
3184                     }
3185                 } else {
3186                     ok(hr == prop.expected, "Error: GetPropertyLength returned 0x%08x, expected 0x%08x on uri_tests[%d].str_props[%d].\n",
3187                             hr, prop.expected, i, j);
3188                     ok(receivedLen == expectedLen || broken(receivedLen == brokenLen),
3189                             "Error: Expected a length of %d but got %d on uri_tests[%d].str_props[%d].\n",
3190                             expectedLen, receivedLen, i, j);
3191                 }
3192             }
3193         }
3194
3195         if(uri) IUri_Release(uri);
3196
3197         heap_free(uriW);
3198     }
3199 }
3200
3201 static void test_IUri_GetProperties(void) {
3202     IUri *uri = NULL;
3203     HRESULT hr;
3204     DWORD i;
3205
3206     hr = pCreateUri(http_urlW, 0, 0, &uri);
3207     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
3208     if(SUCCEEDED(hr)) {
3209         hr = IUri_GetProperties(uri, NULL);
3210         ok(hr == E_INVALIDARG, "Error: GetProperties returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
3211     }
3212     if(uri) IUri_Release(uri);
3213
3214     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
3215         uri_properties test = uri_tests[i];
3216         LPWSTR uriW;
3217         uri = NULL;
3218
3219         uriW = a2w(test.uri);
3220         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
3221         if(test.create_todo) {
3222             todo_wine {
3223                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, test.create_expected);
3224             }
3225         } else {
3226             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, test.create_expected);
3227         }
3228
3229         if(SUCCEEDED(hr)) {
3230             DWORD received = 0;
3231             DWORD j;
3232
3233             hr = IUri_GetProperties(uri, &received);
3234             if(test.props_todo) {
3235                 todo_wine {
3236                     ok(hr == S_OK, "Error: GetProperties returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
3237                 }
3238                 if (hr == E_NOTIMPL)  /* no point in continuing */
3239                 {
3240                     if(uri) IUri_Release(uri);
3241                     heap_free(uriW);
3242                     return;
3243                 }
3244             } else {
3245                 ok(hr == S_OK, "Error: GetProperties returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
3246             }
3247
3248             for(j = 0; j <= Uri_PROPERTY_DWORD_LAST; ++j) {
3249                 /* (1 << j) converts a Uri_PROPERTY to its corresponding Uri_HAS_* flag mask. */
3250                 if(test.props & (1 << j)) {
3251                     if(test.props_todo) {
3252                         todo_wine {
3253                             ok(received & (1 << j), "Error: Expected flag for property %d on uri_tests[%d].\n", j, i);
3254                         }
3255                     } else {
3256                         ok(received & (1 << j), "Error: Expected flag for property %d on uri_tests[%d].\n", j, i);
3257                     }
3258                 } else {
3259                     /* NOTE: Since received is initialized to 0, this test will always pass while
3260                      * GetProperties is unimplemented.
3261                      */
3262                     ok(!(received & (1 << j)), "Error: Received flag for property %d when not expected on uri_tests[%d].\n", j, i);
3263                 }
3264             }
3265         }
3266
3267         if(uri) IUri_Release(uri);
3268
3269         heap_free(uriW);
3270     }
3271 }
3272
3273 static void test_IUri_HasProperty(void) {
3274     IUri *uri = NULL;
3275     HRESULT hr;
3276     DWORD i;
3277
3278     hr = pCreateUri(http_urlW, 0, 0, &uri);
3279     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
3280     if(SUCCEEDED(hr)) {
3281         hr = IUri_HasProperty(uri, Uri_PROPERTY_RAW_URI, NULL);
3282         ok(hr == E_INVALIDARG, "Error: HasProperty returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
3283     }
3284     if(uri) IUri_Release(uri);
3285
3286     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
3287         uri_properties test = uri_tests[i];
3288         LPWSTR uriW;
3289         uri = NULL;
3290
3291         uriW = a2w(test.uri);
3292
3293         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
3294         if(test.create_todo) {
3295             todo_wine {
3296                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, test.create_expected);
3297             }
3298         } else {
3299             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, test.create_expected);
3300         }
3301
3302         if(SUCCEEDED(hr)) {
3303             DWORD j;
3304
3305             for(j = 0; j <= Uri_PROPERTY_DWORD_LAST; ++j) {
3306                 /* Assign -1, then explicitly test for TRUE or FALSE later. */
3307                 BOOL received = -1;
3308
3309                 hr = IUri_HasProperty(uri, j, &received);
3310                 if(test.props_todo) {
3311                     todo_wine {
3312                         ok(hr == S_OK, "Error: HasProperty returned 0x%08x, expected 0x%08x for property %d on uri_tests[%d].\n",
3313                                 hr, S_OK, j, i);
3314                     }
3315                     if (hr == E_NOTIMPL)  /* no point in continuing */
3316                     {
3317                         if(uri) IUri_Release(uri);
3318                         heap_free(uriW);
3319                         return;
3320                     }
3321
3322                     /* Check if the property should be true. */
3323                     if(test.props & (1 << j)) {
3324                         todo_wine {
3325                             ok(received == TRUE, "Error: Expected to have property %d on uri_tests[%d].\n", j, i);
3326                         }
3327                     } else {
3328                         todo_wine {
3329                             ok(received == FALSE, "Error: Wasn't expecting to have property %d on uri_tests[%d].\n", j, i);
3330                         }
3331                     }
3332                 } else {
3333                     ok(hr == S_OK, "Error: HasProperty returned 0x%08x, expected 0x%08x for property %d on uri_tests[%d].\n",
3334                             hr, S_OK, j, i);
3335
3336                     if(test.props & (1 << j)) {
3337                         ok(received == TRUE, "Error: Expected to have property %d on uri_tests[%d].\n", j, i);
3338                     } else {
3339                         ok(received == FALSE, "Error: Wasn't expecting to have property %d on uri_tests[%d].\n", j, i);
3340                     }
3341                 }
3342             }
3343         }
3344
3345         if(uri) IUri_Release(uri);
3346
3347         heap_free(uriW);
3348     }
3349 }
3350
3351 static void test_IUri_IsEqual(void) {
3352     IUri *uriA, *uriB;
3353     HRESULT hrA, hrB;
3354     DWORD i;
3355
3356     uriA = uriB = NULL;
3357
3358     /* Make sure IsEqual handles invalid args correctly. */
3359     hrA = pCreateUri(http_urlW, 0, 0, &uriA);
3360     hrB = pCreateUri(http_urlW, 0, 0, &uriB);
3361     ok(hrA == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hrA, S_OK);
3362     ok(hrB == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hrB, S_OK);
3363     if(SUCCEEDED(hrA) && SUCCEEDED(hrB)) {
3364         BOOL equal = -1;
3365         hrA = IUri_IsEqual(uriA, NULL, &equal);
3366         ok(hrA == S_OK, "Error: IsEqual returned 0x%08x, expected 0x%08x.\n", hrA, S_OK);
3367         ok(equal == FALSE, "Error: Expected equal to be FALSE, but was %d instead.\n", equal);
3368
3369         hrA = IUri_IsEqual(uriA, uriB, NULL);
3370         ok(hrA == E_POINTER, "Error: IsEqual returned 0x%08x, expected 0x%08x.\n", hrA, E_POINTER);
3371     }
3372     if(uriA) IUri_Release(uriA);
3373     if(uriB) IUri_Release(uriB);
3374
3375     for(i = 0; i < sizeof(equality_tests)/sizeof(equality_tests[0]); ++i) {
3376         uri_equality test = equality_tests[i];
3377         LPWSTR uriA_W, uriB_W;
3378
3379         uriA = uriB = NULL;
3380
3381         uriA_W = a2w(test.a);
3382         uriB_W = a2w(test.b);
3383
3384         hrA = pCreateUri(uriA_W, test.create_flags_a, 0, &uriA);
3385         if(test.create_todo_a) {
3386             todo_wine {
3387                 ok(hrA == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x on equality_tests[%d].a\n",
3388                         hrA, S_OK, i);
3389             }
3390         } else {
3391             ok(hrA == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x on equality_tests[%d].a\n",
3392                     hrA, S_OK, i);
3393         }
3394
3395         hrB = pCreateUri(uriB_W, test.create_flags_b, 0, &uriB);
3396         if(test.create_todo_b) {
3397             todo_wine {
3398                 ok(hrB == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x on equality_tests[%d].b\n",
3399                         hrB, S_OK, i);
3400             }
3401         } else {
3402             ok(hrB == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x on equality_tests[%d].b\n",
3403                     hrB, S_OK, i);
3404         }
3405
3406         if(SUCCEEDED(hrA) && SUCCEEDED(hrB)) {
3407             BOOL equal = -1;
3408
3409             hrA = IUri_IsEqual(uriA, uriB, &equal);
3410             if(test.todo) {
3411                 todo_wine {
3412                     ok(hrA == S_OK, "Error: IsEqual returned 0x%08x, expected 0x%08x on equality_tests[%d].\n",
3413                             hrA, S_OK, i);
3414                 }
3415                 todo_wine {
3416                     ok(equal == test.equal, "Error: Expected the comparison to be %d on equality_tests[%d].\n", test.equal, i);
3417                 }
3418             } else {
3419                 ok(hrA == S_OK, "Error: IsEqual returned 0x%08x, expected 0x%08x on equality_tests[%d].\n", hrA, S_OK, i);
3420                 ok(equal == test.equal, "Error: Expected the comparison to be %d on equality_tests[%d].\n", test.equal, i);
3421             }
3422         }
3423         if(uriA) IUri_Release(uriA);
3424         if(uriB) IUri_Release(uriB);
3425
3426         heap_free(uriA_W);
3427         heap_free(uriB_W);
3428     }
3429 }
3430
3431 START_TEST(uri) {
3432     HMODULE hurlmon;
3433
3434     hurlmon = GetModuleHandle("urlmon.dll");
3435     pCreateUri = (void*) GetProcAddress(hurlmon, "CreateUri");
3436
3437     if(!pCreateUri) {
3438         win_skip("CreateUri is not present, skipping tests.\n");
3439         return;
3440     }
3441
3442     trace("test CreateUri invalid flags...\n");
3443     test_CreateUri_InvalidFlags();
3444
3445     trace("test CreateUri invalid args...\n");
3446     test_CreateUri_InvalidArgs();
3447
3448     trace("test CreateUri invalid URIs...\n");
3449     test_CreateUri_InvalidUri();
3450
3451     trace("test IUri_GetPropertyBSTR...\n");
3452     test_IUri_GetPropertyBSTR();
3453
3454     trace("test IUri_GetPropertyDWORD...\n");
3455     test_IUri_GetPropertyDWORD();
3456
3457     trace("test IUri_GetStrProperties...\n");
3458     test_IUri_GetStrProperties();
3459
3460     trace("test IUri_GetDwordProperties...\n");
3461     test_IUri_GetDwordProperties();
3462
3463     trace("test IUri_GetPropertyLength...\n");
3464     test_IUri_GetPropertyLength();
3465
3466     trace("test IUri_GetProperties...\n");
3467     test_IUri_GetProperties();
3468
3469     trace("test IUri_HasProperty...\n");
3470     test_IUri_HasProperty();
3471
3472     trace("test IUri_IsEqual...\n");
3473     test_IUri_IsEqual();
3474 }