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