windowscodecs: Handle TIFF's with RowsPerStrip greater than Height.
[wine] / dlls / urlmon / tests / uri.c
1 /*
2  * UrlMon IUri tests
3  *
4  * Copyright 2010 Thomas Mullaly
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #include <wine/test.h>
22 #include <stdarg.h>
23 #include <stddef.h>
24
25 #define COBJMACROS
26
27 #include "windef.h"
28 #include "winbase.h"
29 #include "urlmon.h"
30 #include "shlwapi.h"
31
32 #define URI_STR_PROPERTY_COUNT Uri_PROPERTY_STRING_LAST+1
33 #define URI_DWORD_PROPERTY_COUNT (Uri_PROPERTY_DWORD_LAST - Uri_PROPERTY_DWORD_START)+1
34 #define URI_BUILDER_STR_PROPERTY_COUNT 7
35
36 static HRESULT (WINAPI *pCreateUri)(LPCWSTR, DWORD, DWORD_PTR, IUri**);
37 static HRESULT (WINAPI *pCreateUriWithFragment)(LPCWSTR, LPCWSTR, DWORD, DWORD_PTR, IUri**);
38 static HRESULT (WINAPI *pCreateIUriBuilder)(IUri*, DWORD, DWORD_PTR, IUriBuilder**);
39
40 static const WCHAR http_urlW[] = { 'h','t','t','p',':','/','/','w','w','w','.','w','i','n','e','h','q',
41         '.','o','r','g','/',0};
42 static const WCHAR http_url_fragW[] = { 'h','t','t','p',':','/','/','w','w','w','.','w','i','n','e','h','q',
43         '.','o','r','g','/','#','F','r','a','g',0};
44
45 typedef struct _uri_create_flag_test {
46     DWORD   flags;
47     HRESULT expected;
48 } uri_create_flag_test;
49
50 static const uri_create_flag_test invalid_flag_tests[] = {
51     /* Set of invalid flag combinations to test for. */
52     {Uri_CREATE_DECODE_EXTRA_INFO | Uri_CREATE_NO_DECODE_EXTRA_INFO, E_INVALIDARG},
53     {Uri_CREATE_CANONICALIZE | Uri_CREATE_NO_CANONICALIZE, E_INVALIDARG},
54     {Uri_CREATE_CRACK_UNKNOWN_SCHEMES | Uri_CREATE_NO_CRACK_UNKNOWN_SCHEMES, E_INVALIDARG},
55     {Uri_CREATE_PRE_PROCESS_HTML_URI | Uri_CREATE_NO_PRE_PROCESS_HTML_URI, E_INVALIDARG},
56     {Uri_CREATE_IE_SETTINGS | Uri_CREATE_NO_IE_SETTINGS, E_INVALIDARG}
57 };
58
59 typedef struct _uri_str_property {
60     const char* value;
61     HRESULT     expected;
62     BOOL        todo;
63     const char* broken_value;
64 } uri_str_property;
65
66 typedef struct _uri_dword_property {
67     DWORD   value;
68     HRESULT expected;
69     BOOL    todo;
70 } uri_dword_property;
71
72 typedef struct _uri_properties {
73     const char*         uri;
74     DWORD               create_flags;
75     HRESULT             create_expected;
76     BOOL                create_todo;
77     DWORD               props;
78     BOOL                props_todo;
79
80     uri_str_property    str_props[URI_STR_PROPERTY_COUNT];
81     uri_dword_property  dword_props[URI_DWORD_PROPERTY_COUNT];
82 } uri_properties;
83
84 static const uri_properties uri_tests[] = {
85     {   "http://www.winehq.org/tests/../tests/../..", 0, S_OK, FALSE,
86         /* A flag bitmap containing all the Uri_HAS_* flags that correspond to this uri. */
87         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_HOST|
88         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|
89         Uri_HAS_PORT|Uri_HAS_SCHEME,
90         FALSE,
91         {
92             {"http://www.winehq.org/",S_OK,FALSE},                      /* ABSOLUTE_URI */
93             {"www.winehq.org",S_OK,FALSE},                              /* AUTHORITY */
94             {"http://www.winehq.org/",S_OK,FALSE},                      /* DISPLAY_URI */
95             {"winehq.org",S_OK,FALSE},                                  /* DOMAIN */
96             {"",S_FALSE,FALSE},                                         /* EXTENSION */
97             {"",S_FALSE,FALSE},                                         /* FRAGMENT */
98             {"www.winehq.org",S_OK,FALSE},                              /* HOST */
99             {"",S_FALSE,FALSE},                                         /* PASSWORD */
100             {"/",S_OK,FALSE},                                           /* PATH */
101             {"/",S_OK,FALSE},                                           /* PATH_AND_QUERY */
102             {"",S_FALSE,FALSE},                                         /* QUERY */
103             {"http://www.winehq.org/tests/../tests/../..",S_OK,FALSE},  /* RAW_URI */
104             {"http",S_OK,FALSE},                                        /* SCHEME_NAME */
105             {"",S_FALSE,FALSE},                                         /* USER_INFO */
106             {"",S_FALSE,FALSE}                                          /* USER_NAME */
107         },
108         {
109             {Uri_HOST_DNS,S_OK,FALSE},                                  /* HOST_TYPE */
110             {80,S_OK,FALSE},                                            /* PORT */
111             {URL_SCHEME_HTTP,S_OK,FALSE},                               /* SCHEME */
112             {URLZONE_INVALID,E_NOTIMPL,FALSE}                           /* ZONE */
113         }
114     },
115     {   "http://winehq.org/tests/.././tests", 0, S_OK, FALSE,
116         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_HOST|
117         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|
118         Uri_HAS_PORT|Uri_HAS_SCHEME,
119         FALSE,
120         {
121             {"http://winehq.org/tests",S_OK,FALSE},
122             {"winehq.org",S_OK,FALSE},
123             {"http://winehq.org/tests",S_OK,FALSE},
124             {"winehq.org",S_OK,FALSE},
125             {"",S_FALSE,FALSE},
126             {"",S_FALSE,FALSE},
127             {"winehq.org",S_OK,FALSE},
128             {"",S_FALSE,FALSE},
129             {"/tests",S_OK,FALSE},
130             {"/tests",S_OK,FALSE},
131             {"",S_FALSE,FALSE},
132             {"http://winehq.org/tests/.././tests",S_OK,FALSE},
133             {"http",S_OK,FALSE},
134             {"",S_FALSE,FALSE},
135             {"",S_FALSE,FALSE}
136         },
137         {
138             {Uri_HOST_DNS,S_OK,FALSE},
139             {80,S_OK,FALSE},
140             {URL_SCHEME_HTTP,S_OK,FALSE},
141             {URLZONE_INVALID,E_NOTIMPL,FALSE}
142         }
143     },
144     {   "HtTp://www.winehq.org/tests/..?query=x&return=y", 0, S_OK, FALSE,
145         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_HOST|
146         Uri_HAS_DOMAIN|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_QUERY|Uri_HAS_RAW_URI|
147         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
148         FALSE,
149         {
150             {"http://www.winehq.org/?query=x&return=y",S_OK,FALSE},
151             {"www.winehq.org",S_OK,FALSE},
152             {"http://www.winehq.org/?query=x&return=y",S_OK,FALSE},
153             {"winehq.org",S_OK,FALSE},
154             {"",S_FALSE,FALSE},
155             {"",S_FALSE,FALSE},
156             {"www.winehq.org",S_OK,FALSE},
157             {"",S_FALSE,FALSE},
158             {"/",S_OK,FALSE},
159             {"/?query=x&return=y",S_OK,FALSE},
160             {"?query=x&return=y",S_OK,FALSE},
161             {"HtTp://www.winehq.org/tests/..?query=x&return=y",S_OK,FALSE},
162             {"http",S_OK,FALSE},
163             {"",S_FALSE,FALSE},
164             {"",S_FALSE,FALSE}
165         },
166         {
167             {Uri_HOST_DNS,S_OK,FALSE},
168             {80,S_OK,FALSE},
169             {URL_SCHEME_HTTP,S_OK,FALSE},
170             {URLZONE_INVALID,E_NOTIMPL,FALSE},
171         }
172     },
173     {   "hTTp://us%45r%3Ainfo@examp%4CE.com:80/path/a/b/./c/../%2E%2E/Forbidden'<|> Characters", 0, S_OK, FALSE,
174         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_HOST|Uri_HAS_PATH|
175         Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_USER_INFO|Uri_HAS_USER_NAME|
176         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
177         FALSE,
178         {
179             {"http://usEr%3Ainfo@example.com/path/a/Forbidden'%3C%7C%3E%20Characters",S_OK,FALSE},
180             {"usEr%3Ainfo@example.com",S_OK,FALSE},
181             {"http://example.com/path/a/Forbidden'%3C%7C%3E%20Characters",S_OK,FALSE},
182             {"example.com",S_OK,FALSE},
183             {"",S_FALSE,FALSE},
184             {"",S_FALSE,FALSE},
185             {"example.com",S_OK,FALSE},
186             {"",S_FALSE,FALSE},
187             {"/path/a/Forbidden'%3C%7C%3E%20Characters",S_OK,FALSE},
188             {"/path/a/Forbidden'%3C%7C%3E%20Characters",S_OK,FALSE},
189             {"",S_FALSE,FALSE},
190             {"hTTp://us%45r%3Ainfo@examp%4CE.com:80/path/a/b/./c/../%2E%2E/Forbidden'<|> Characters",S_OK,FALSE},
191             {"http",S_OK,FALSE},
192             {"usEr%3Ainfo",S_OK,FALSE},
193             {"usEr%3Ainfo",S_OK,FALSE}
194         },
195         {
196             {Uri_HOST_DNS,S_OK,FALSE},
197             {80,S_OK,FALSE},
198             {URL_SCHEME_HTTP,S_OK,FALSE},
199             {URLZONE_INVALID,E_NOTIMPL,FALSE},
200         }
201     },
202     {   "ftp://winepass:wine@ftp.winehq.org:9999/dir/foo bar.txt", 0, S_OK, FALSE,
203         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_EXTENSION|
204         Uri_HAS_HOST|Uri_HAS_PASSWORD|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
205         Uri_HAS_SCHEME_NAME|Uri_HAS_USER_INFO|Uri_HAS_USER_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|
206         Uri_HAS_SCHEME,
207         FALSE,
208         {
209             {"ftp://winepass:wine@ftp.winehq.org:9999/dir/foo%20bar.txt",S_OK,FALSE},
210             {"winepass:wine@ftp.winehq.org:9999",S_OK,FALSE},
211             {"ftp://ftp.winehq.org:9999/dir/foo%20bar.txt",S_OK,FALSE},
212             {"winehq.org",S_OK,FALSE},
213             {".txt",S_OK,FALSE},
214             {"",S_FALSE,FALSE},
215             {"ftp.winehq.org",S_OK,FALSE},
216             {"wine",S_OK,FALSE},
217             {"/dir/foo%20bar.txt",S_OK,FALSE},
218             {"/dir/foo%20bar.txt",S_OK,FALSE},
219             {"",S_FALSE,FALSE},
220             {"ftp://winepass:wine@ftp.winehq.org:9999/dir/foo bar.txt",S_OK,FALSE},
221             {"ftp",S_OK,FALSE},
222             {"winepass:wine",S_OK,FALSE},
223             {"winepass",S_OK,FALSE}
224         },
225         {
226             {Uri_HOST_DNS,S_OK,FALSE},
227             {9999,S_OK,FALSE},
228             {URL_SCHEME_FTP,S_OK,FALSE},
229             {URLZONE_INVALID,E_NOTIMPL,FALSE}
230         }
231     },
232     {   "file://c:\\tests\\../tests/foo%20bar.mp3", 0, S_OK, FALSE,
233         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH|
234         Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
235         FALSE,
236         {
237             {"file:///c:/tests/foo%2520bar.mp3",S_OK,FALSE},
238             {"",S_FALSE,FALSE},
239             {"file:///c:/tests/foo%2520bar.mp3",S_OK,FALSE},
240             {"",S_FALSE,FALSE},
241             {".mp3",S_OK,FALSE},
242             {"",S_FALSE,FALSE},
243             {"",S_FALSE,FALSE},
244             {"",S_FALSE,FALSE},
245             {"/c:/tests/foo%2520bar.mp3",S_OK,FALSE},
246             {"/c:/tests/foo%2520bar.mp3",S_OK,FALSE},
247             {"",S_FALSE,FALSE},
248             {"file://c:\\tests\\../tests/foo%20bar.mp3",S_OK,FALSE},
249             {"file",S_OK,FALSE},
250             {"",S_FALSE,FALSE},
251             {"",S_FALSE,FALSE}
252         },
253         {
254             {Uri_HOST_UNKNOWN,S_OK,FALSE},
255             {0,S_FALSE,FALSE},
256             {URL_SCHEME_FILE,S_OK,FALSE},
257             {URLZONE_INVALID,E_NOTIMPL,FALSE}
258         }
259     },
260     {   "FILE://localhost/test dir\\../tests/test%20file.README.txt", 0, S_OK, FALSE,
261         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH|
262         Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
263         FALSE,
264         {
265             {"file:///tests/test%20file.README.txt",S_OK,FALSE},
266             {"",S_FALSE,FALSE},
267             {"file:///tests/test%20file.README.txt",S_OK,FALSE},
268             {"",S_FALSE,FALSE},
269             {".txt",S_OK,FALSE},
270             {"",S_FALSE,FALSE},
271             {"",S_FALSE,FALSE},
272             {"",S_FALSE,FALSE},
273             {"/tests/test%20file.README.txt",S_OK,FALSE},
274             {"/tests/test%20file.README.txt",S_OK,FALSE},
275             {"",S_FALSE,FALSE},
276             {"FILE://localhost/test dir\\../tests/test%20file.README.txt",S_OK,FALSE},
277             {"file",S_OK,FALSE},
278             {"",S_FALSE,FALSE},
279             {"",S_FALSE,FALSE}
280         },
281         {
282             {Uri_HOST_UNKNOWN,S_OK,FALSE},
283             {0,S_FALSE,FALSE},
284             {URL_SCHEME_FILE,S_OK,FALSE},
285             {URLZONE_INVALID,E_NOTIMPL,FALSE}
286         }
287     },
288     {   "urn:nothing:should:happen here", 0, S_OK, FALSE,
289         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|
290         Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
291         FALSE,
292         {
293             {"urn:nothing:should:happen here",S_OK,FALSE},
294             {"",S_FALSE,FALSE},
295             {"urn:nothing:should:happen here",S_OK,FALSE},
296             {"",S_FALSE,FALSE},
297             {"",S_FALSE,FALSE},
298             {"",S_FALSE,FALSE},
299             {"",S_FALSE,FALSE},
300             {"",S_FALSE,FALSE},
301             {"nothing:should:happen here",S_OK,FALSE},
302             {"nothing:should:happen here",S_OK,FALSE},
303             {"",S_FALSE,FALSE},
304             {"urn:nothing:should:happen here",S_OK,FALSE},
305             {"urn",S_OK,FALSE},
306             {"",S_FALSE,FALSE},
307             {"",S_FALSE,FALSE}
308         },
309         {
310             {Uri_HOST_UNKNOWN,S_OK,FALSE},
311             {0,S_FALSE,FALSE},
312             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
313             {URLZONE_INVALID,E_NOTIMPL,FALSE}
314         }
315     },
316     {   "http://127.0.0.1/tests/../test dir/./test.txt", 0, S_OK, FALSE,
317         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|
318         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
319         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
320         FALSE,
321         {
322             {"http://127.0.0.1/test%20dir/test.txt",S_OK,FALSE},
323             {"127.0.0.1",S_OK,FALSE},
324             {"http://127.0.0.1/test%20dir/test.txt",S_OK,FALSE},
325             {"",S_FALSE,FALSE},
326             {".txt",S_OK,FALSE},
327             {"",S_FALSE,FALSE},
328             {"127.0.0.1",S_OK,FALSE},
329             {"",S_FALSE,FALSE},
330             {"/test%20dir/test.txt",S_OK,FALSE},
331             {"/test%20dir/test.txt",S_OK,FALSE},
332             {"",S_FALSE,FALSE},
333             {"http://127.0.0.1/tests/../test dir/./test.txt",S_OK,FALSE},
334             {"http",S_OK,FALSE},
335             {"",S_FALSE,FALSE},
336             {"",S_FALSE,FALSE}
337         },
338         {
339             {Uri_HOST_IPV4,S_OK,FALSE},
340             {80,S_OK,FALSE},
341             {URL_SCHEME_HTTP,S_OK,FALSE},
342             {URLZONE_INVALID,E_NOTIMPL,FALSE}
343         }
344     },
345     {   "http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]", 0, S_OK, FALSE,
346         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
347         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
348         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
349         FALSE,
350         {
351             {"http://[fedc:ba98:7654:3210:fedc:ba98:7654:3210]/",S_OK,FALSE},
352             {"[fedc:ba98:7654:3210:fedc:ba98:7654:3210]",S_OK,FALSE},
353             {"http://[fedc:ba98:7654:3210:fedc:ba98:7654:3210]/",S_OK,FALSE},
354             {"",S_FALSE,FALSE},
355             {"",S_FALSE,FALSE},
356             {"",S_FALSE,FALSE},
357             {"fedc:ba98:7654:3210:fedc:ba98:7654:3210",S_OK,FALSE},
358             {"",S_FALSE,FALSE},
359             {"/",S_OK,FALSE},
360             {"/",S_OK,FALSE},
361             {"",S_FALSE,FALSE},
362             {"http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]",S_OK,FALSE},
363             {"http",S_OK,FALSE},
364             {"",S_FALSE,FALSE},
365             {"",S_FALSE,FALSE}
366         },
367         {
368             {Uri_HOST_IPV6,S_OK,FALSE},
369             {80,S_OK,FALSE},
370             {URL_SCHEME_HTTP,S_OK,FALSE},
371             {URLZONE_INVALID,E_NOTIMPL,FALSE}
372         }
373     },
374     {   "ftp://[::13.1.68.3]", 0, S_OK, FALSE,
375         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
376         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
377         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
378         FALSE,
379         {
380             {"ftp://[::13.1.68.3]/",S_OK,FALSE},
381             {"[::13.1.68.3]",S_OK,FALSE},
382             {"ftp://[::13.1.68.3]/",S_OK,FALSE},
383             {"",S_FALSE,FALSE},
384             {"",S_FALSE,FALSE},
385             {"",S_FALSE,FALSE},
386             {"::13.1.68.3",S_OK,FALSE},
387             {"",S_FALSE,FALSE},
388             {"/",S_OK,FALSE},
389             {"/",S_OK,FALSE},
390             {"",S_FALSE,FALSE},
391             {"ftp://[::13.1.68.3]",S_OK,FALSE},
392             {"ftp",S_OK,FALSE},
393             {"",S_FALSE,FALSE},
394             {"",S_FALSE,FALSE}
395         },
396         {
397             {Uri_HOST_IPV6,S_OK,FALSE},
398             {21,S_OK,FALSE},
399             {URL_SCHEME_FTP,S_OK,FALSE},
400             {URLZONE_INVALID,E_NOTIMPL,FALSE}
401         }
402     },
403     {   "http://[FEDC:BA98:0:0:0:0:0:3210]", 0, S_OK, FALSE,
404         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
405         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
406         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
407         FALSE,
408         {
409             {"http://[fedc:ba98::3210]/",S_OK,FALSE},
410             {"[fedc:ba98::3210]",S_OK,FALSE},
411             {"http://[fedc:ba98::3210]/",S_OK,FALSE},
412             {"",S_FALSE,FALSE},
413             {"",S_FALSE,FALSE},
414             {"",S_FALSE,FALSE},
415             {"fedc:ba98::3210",S_OK,FALSE},
416             {"",S_FALSE,FALSE},
417             {"/",S_OK,FALSE},
418             {"/",S_OK,FALSE},
419             {"",S_FALSE,FALSE},
420             {"http://[FEDC:BA98:0:0:0:0:0:3210]",S_OK,FALSE},
421             {"http",S_OK,FALSE},
422             {"",S_FALSE,FALSE},
423             {"",S_FALSE,FALSE},
424         },
425         {
426             {Uri_HOST_IPV6,S_OK,FALSE},
427             {80,S_OK,FALSE},
428             {URL_SCHEME_HTTP,S_OK,FALSE},
429             {URLZONE_INVALID,E_NOTIMPL,FALSE}
430         }
431     },
432     {   "1234://www.winehq.org", 0, S_OK, FALSE,
433         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
434         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
435         Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
436         FALSE,
437         {
438             {"1234://www.winehq.org/",S_OK,FALSE},
439             {"www.winehq.org",S_OK,FALSE},
440             {"1234://www.winehq.org/",S_OK,FALSE},
441             {"winehq.org",S_OK,FALSE},
442             {"",S_FALSE,FALSE},
443             {"",S_FALSE,FALSE},
444             {"www.winehq.org",S_OK,FALSE},
445             {"",S_FALSE,FALSE},
446             {"/",S_OK,FALSE},
447             {"/",S_OK,FALSE},
448             {"",S_FALSE,FALSE},
449             {"1234://www.winehq.org",S_OK,FALSE},
450             {"1234",S_OK,FALSE},
451             {"",S_FALSE,FALSE},
452             {"",S_FALSE,FALSE}
453         },
454         {
455             {Uri_HOST_DNS,S_OK,FALSE},
456             {0,S_FALSE,FALSE},
457             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
458             {URLZONE_INVALID,E_NOTIMPL,FALSE}
459         }
460     },
461     /* Test's to make sure the parser/canonicalizer handles implicit file schemes correctly. */
462     {   "C:/test/test.mp3", Uri_CREATE_ALLOW_IMPLICIT_FILE_SCHEME, S_OK, FALSE,
463         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH|
464         Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
465         FALSE,
466         {
467             {"file:///C:/test/test.mp3",S_OK,FALSE},
468             {"",S_FALSE,FALSE},
469             {"file:///C:/test/test.mp3",S_OK,FALSE},
470             {"",S_FALSE,FALSE},
471             {".mp3",S_OK,FALSE},
472             {"",S_FALSE,FALSE},
473             {"",S_FALSE,FALSE},
474             {"",S_FALSE,FALSE},
475             {"/C:/test/test.mp3",S_OK,FALSE},
476             {"/C:/test/test.mp3",S_OK,FALSE},
477             {"",S_FALSE,FALSE},
478             {"C:/test/test.mp3",S_OK,FALSE},
479             {"file",S_OK,FALSE},
480             {"",S_FALSE,FALSE},
481             {"",S_FALSE,FALSE}
482         },
483         {
484             {Uri_HOST_UNKNOWN,S_OK,FALSE},
485             {0,S_FALSE,FALSE},
486             {URL_SCHEME_FILE,S_OK,FALSE},
487             {URLZONE_INVALID,E_NOTIMPL,FALSE}
488         }
489     },
490     /* Test's to make sure the parser/canonicalizer handles implicit file schemes correctly. */
491     {   "\\\\Server/test.mp3", Uri_CREATE_ALLOW_IMPLICIT_FILE_SCHEME, S_OK, FALSE,
492         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|
493         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_HOST|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
494         Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
495         FALSE,
496         {
497             {"file://server/test.mp3",S_OK,FALSE},
498             {"server",S_OK,FALSE},
499             {"file://server/test.mp3",S_OK,FALSE},
500             {"",S_FALSE,FALSE},
501             {".mp3",S_OK,FALSE},
502             {"",S_FALSE,FALSE},
503             {"server",S_OK,FALSE},
504             {"",S_FALSE,FALSE},
505             {"/test.mp3",S_OK,FALSE},
506             {"/test.mp3",S_OK,FALSE},
507             {"",S_FALSE,FALSE},
508             {"\\\\Server/test.mp3",S_OK,FALSE},
509             {"file",S_OK,FALSE},
510             {"",S_FALSE,FALSE},
511             {"",S_FALSE,FALSE}
512         },
513         {
514             {Uri_HOST_DNS,S_OK,FALSE},
515             {0,S_FALSE,FALSE},
516             {URL_SCHEME_FILE,S_OK,FALSE},
517             {URLZONE_INVALID,E_NOTIMPL,FALSE}
518         }
519     },
520     {   "www.winehq.org/test", Uri_CREATE_ALLOW_IMPLICIT_WILDCARD_SCHEME, S_OK, FALSE,
521         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_HOST|
522         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|
523         Uri_HAS_SCHEME,
524         FALSE,
525         {
526             {"*:www.winehq.org/test",S_OK,FALSE},
527             {"www.winehq.org",S_OK,FALSE},
528             {"*:www.winehq.org/test",S_OK,FALSE},
529             {"winehq.org",S_OK,FALSE},
530             {"",S_FALSE,FALSE},
531             {"",S_FALSE,FALSE},
532             {"www.winehq.org",S_OK,FALSE},
533             {"",S_FALSE,FALSE},
534             {"/test",S_OK,FALSE},
535             {"/test",S_OK,FALSE},
536             {"",S_FALSE,FALSE},
537             {"www.winehq.org/test",S_OK,FALSE},
538             {"*",S_OK,FALSE},
539             {"",S_FALSE,FALSE},
540             {"",S_FALSE,FALSE}
541         },
542         {
543             {Uri_HOST_DNS,S_OK,FALSE},
544             {0,S_FALSE,FALSE},
545             {URL_SCHEME_WILDCARD,S_OK,FALSE},
546             {URLZONE_INVALID,E_NOTIMPL,FALSE}
547         }
548     },
549     /* Valid since the '*' is the only character in the scheme name. */
550     {   "*:www.winehq.org/test", 0, S_OK, FALSE,
551         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_HOST|
552         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|
553         Uri_HAS_SCHEME,
554         FALSE,
555         {
556             {"*:www.winehq.org/test",S_OK,FALSE},
557             {"www.winehq.org",S_OK,FALSE},
558             {"*:www.winehq.org/test",S_OK,FALSE},
559             {"winehq.org",S_OK,FALSE},
560             {"",S_FALSE,FALSE},
561             {"",S_FALSE,FALSE},
562             {"www.winehq.org",S_OK,FALSE},
563             {"",S_FALSE,FALSE},
564             {"/test",S_OK,FALSE},
565             {"/test",S_OK,FALSE},
566             {"",S_FALSE,FALSE},
567             {"*:www.winehq.org/test",S_OK,FALSE},
568             {"*",S_OK,FALSE},
569             {"",S_FALSE,FALSE},
570             {"",S_FALSE,FALSE}
571         },
572         {
573             {Uri_HOST_DNS,S_OK,FALSE},
574             {0,S_FALSE,FALSE},
575             {URL_SCHEME_WILDCARD,S_OK,FALSE},
576             {URLZONE_INVALID,E_NOTIMPL,FALSE}
577         }
578     },
579     {   "/../some dir/test.ext", Uri_CREATE_ALLOW_RELATIVE, S_OK, FALSE,
580         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH|
581         Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
582         FALSE,
583         {
584             {"/../some dir/test.ext",S_OK,FALSE},
585             {"",S_FALSE,FALSE},
586             {"/../some dir/test.ext",S_OK,FALSE},
587             {"",S_FALSE,FALSE},
588             {".ext",S_OK,FALSE},
589             {"",S_FALSE,FALSE},
590             {"",S_FALSE,FALSE},
591             {"",S_FALSE,FALSE},
592             {"/../some dir/test.ext",S_OK,FALSE},
593             {"/../some dir/test.ext",S_OK,FALSE},
594             {"",S_FALSE,FALSE},
595             {"/../some dir/test.ext",S_OK,FALSE},
596             {"",S_FALSE,FALSE},
597             {"",S_FALSE,FALSE},
598             {"",S_FALSE,FALSE}
599         },
600         {
601             {Uri_HOST_UNKNOWN,S_OK,FALSE},
602             {0,S_FALSE,FALSE},
603             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
604             {URLZONE_INVALID,E_NOTIMPL,FALSE}
605         }
606     },
607     {   "//implicit/wildcard/uri scheme", Uri_CREATE_ALLOW_RELATIVE|Uri_CREATE_ALLOW_IMPLICIT_WILDCARD_SCHEME, S_OK, FALSE,
608         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|Uri_HAS_PATH|
609         Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
610         FALSE,
611         {
612             {"*://implicit/wildcard/uri%20scheme",S_OK,FALSE},
613             {"",S_OK,FALSE},
614             {"*://implicit/wildcard/uri%20scheme",S_OK,FALSE},
615             {"",S_FALSE,FALSE},
616             {"",S_FALSE,FALSE},
617             {"",S_FALSE,FALSE},
618             {"",S_OK,FALSE},
619             {"",S_FALSE,FALSE},
620             {"//implicit/wildcard/uri%20scheme",S_OK,FALSE},
621             {"//implicit/wildcard/uri%20scheme",S_OK,FALSE},
622             {"",S_FALSE,FALSE},
623             {"//implicit/wildcard/uri scheme",S_OK,FALSE},
624             {"*",S_OK,FALSE},
625             {"",S_FALSE,FALSE},
626             {"",S_FALSE,FALSE},
627         },
628         {
629             {Uri_HOST_UNKNOWN,S_OK,FALSE},
630             {0,S_FALSE,FALSE},
631             {URL_SCHEME_WILDCARD,S_OK,FALSE},
632             {URLZONE_INVALID,E_NOTIMPL,FALSE}
633         }
634     },
635     /* URI is considered opaque since CREATE_NO_CRACK_UNKNOWN_SCHEMES is set and its an unknown scheme. */
636     {   "zip://google.com", Uri_CREATE_NO_CRACK_UNKNOWN_SCHEMES, S_OK, FALSE,
637         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH|
638         Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME_NAME|
639         Uri_HAS_SCHEME,
640         FALSE,
641         {
642             {"zip:/.//google.com",S_OK,FALSE},
643             {"",S_FALSE,FALSE},
644             {"zip:/.//google.com",S_OK,FALSE},
645             {"",S_FALSE,FALSE},
646             {".com",S_OK,FALSE},
647             {"",S_FALSE,FALSE},
648             {"",S_FALSE,FALSE},
649             {"",S_FALSE,FALSE},
650             {"/.//google.com",S_OK,FALSE},
651             {"/.//google.com",S_OK,FALSE},
652             {"",S_FALSE,FALSE},
653             {"zip://google.com",S_OK,FALSE},
654             {"zip",S_OK,FALSE},
655             {"",S_FALSE,FALSE},
656             {"",S_FALSE,FALSE}
657         },
658         {
659             {Uri_HOST_UNKNOWN,S_OK,FALSE},
660             {0,S_FALSE,FALSE},
661             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
662             {URLZONE_INVALID,E_NOTIMPL,FALSE}
663         }
664     },
665     /* Windows uses the first occurrence of ':' to delimit the userinfo. */
666     {   "ftp://user:pass:word@winehq.org/", 0, S_OK, FALSE,
667         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
668         Uri_HAS_HOST|Uri_HAS_PASSWORD|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
669         Uri_HAS_SCHEME_NAME|Uri_HAS_USER_INFO|Uri_HAS_USER_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|
670         Uri_HAS_SCHEME,
671         FALSE,
672         {
673             {"ftp://user:pass:word@winehq.org/",S_OK,FALSE},
674             {"user:pass:word@winehq.org",S_OK,FALSE},
675             {"ftp://winehq.org/",S_OK,FALSE},
676             {"winehq.org",S_OK,FALSE},
677             {"",S_FALSE,FALSE},
678             {"",S_FALSE,FALSE},
679             {"winehq.org",S_OK,FALSE},
680             {"pass:word",S_OK,FALSE},
681             {"/",S_OK,FALSE},
682             {"/",S_OK,FALSE},
683             {"",S_FALSE,FALSE},
684             {"ftp://user:pass:word@winehq.org/",S_OK,FALSE},
685             {"ftp",S_OK,FALSE},
686             {"user:pass:word",S_OK,FALSE},
687             {"user",S_OK,FALSE}
688         },
689         {
690             {Uri_HOST_DNS,S_OK,FALSE},
691             {21,S_OK,FALSE},
692             {URL_SCHEME_FTP,S_OK,FALSE},
693             {URLZONE_INVALID,E_NOTIMPL,FALSE}
694         }
695     },
696     /* Make sure % encoded unreserved characters are decoded. */
697     {   "ftp://w%49%4Ee:PA%53%53@ftp.google.com/", 0, S_OK, FALSE,
698         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
699         Uri_HAS_HOST|Uri_HAS_PASSWORD|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
700         Uri_HAS_SCHEME_NAME|Uri_HAS_USER_INFO|Uri_HAS_USER_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|
701         Uri_HAS_SCHEME,
702         FALSE,
703         {
704             {"ftp://wINe:PASS@ftp.google.com/",S_OK,FALSE},
705             {"wINe:PASS@ftp.google.com",S_OK,FALSE},
706             {"ftp://ftp.google.com/",S_OK,FALSE},
707             {"google.com",S_OK,FALSE},
708             {"",S_FALSE,FALSE},
709             {"",S_FALSE,FALSE},
710             {"ftp.google.com",S_OK,FALSE},
711             {"PASS",S_OK,FALSE},
712             {"/",S_OK,FALSE},
713             {"/",S_OK,FALSE},
714             {"",S_FALSE,FALSE},
715             {"ftp://w%49%4Ee:PA%53%53@ftp.google.com/",S_OK,FALSE},
716             {"ftp",S_OK,FALSE},
717             {"wINe:PASS",S_OK,FALSE},
718             {"wINe",S_OK,FALSE}
719         },
720         {
721             {Uri_HOST_DNS,S_OK,FALSE},
722             {21,S_OK,FALSE},
723             {URL_SCHEME_FTP,S_OK,FALSE},
724             {URLZONE_INVALID,E_NOTIMPL,FALSE}
725         }
726     },
727     /* Make sure % encoded characters which are NOT unreserved are NOT decoded. */
728     {   "ftp://w%5D%5Be:PA%7B%7D@ftp.google.com/", 0, S_OK, FALSE,
729         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
730         Uri_HAS_HOST|Uri_HAS_PASSWORD|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
731         Uri_HAS_SCHEME_NAME|Uri_HAS_USER_INFO|Uri_HAS_USER_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|
732         Uri_HAS_SCHEME,
733         FALSE,
734         {
735             {"ftp://w%5D%5Be:PA%7B%7D@ftp.google.com/",S_OK,FALSE},
736             {"w%5D%5Be:PA%7B%7D@ftp.google.com",S_OK,FALSE},
737             {"ftp://ftp.google.com/",S_OK,FALSE},
738             {"google.com",S_OK,FALSE},
739             {"",S_FALSE,FALSE},
740             {"",S_FALSE,FALSE},
741             {"ftp.google.com",S_OK,FALSE},
742             {"PA%7B%7D",S_OK,FALSE},
743             {"/",S_OK,FALSE},
744             {"/",S_OK,FALSE},
745             {"",S_FALSE,FALSE},
746             {"ftp://w%5D%5Be:PA%7B%7D@ftp.google.com/",S_OK,FALSE},
747             {"ftp",S_OK,FALSE},
748             {"w%5D%5Be:PA%7B%7D",S_OK,FALSE},
749             {"w%5D%5Be",S_OK,FALSE}
750         },
751         {
752             {Uri_HOST_DNS,S_OK,FALSE},
753             {21,S_OK,FALSE},
754             {URL_SCHEME_FTP,S_OK,FALSE},
755             {URLZONE_INVALID,E_NOTIMPL,FALSE}
756         }
757     },
758     /* You're allowed to have an empty password portion in the userinfo section. */
759     {   "ftp://empty:@ftp.google.com/", 0, S_OK, FALSE,
760         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
761         Uri_HAS_HOST|Uri_HAS_PASSWORD|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
762         Uri_HAS_SCHEME_NAME|Uri_HAS_USER_INFO|Uri_HAS_USER_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|
763         Uri_HAS_SCHEME,
764         FALSE,
765         {
766             {"ftp://empty:@ftp.google.com/",S_OK,FALSE},
767             {"empty:@ftp.google.com",S_OK,FALSE},
768             {"ftp://ftp.google.com/",S_OK,FALSE},
769             {"google.com",S_OK,FALSE},
770             {"",S_FALSE,FALSE},
771             {"",S_FALSE,FALSE},
772             {"ftp.google.com",S_OK,FALSE},
773             {"",S_OK,FALSE},
774             {"/",S_OK,FALSE},
775             {"/",S_OK,FALSE},
776             {"",S_FALSE,FALSE},
777             {"ftp://empty:@ftp.google.com/",S_OK,FALSE},
778             {"ftp",S_OK,FALSE},
779             {"empty:",S_OK,FALSE},
780             {"empty",S_OK,FALSE}
781         },
782         {
783             {Uri_HOST_DNS,S_OK,FALSE},
784             {21,S_OK,FALSE},
785             {URL_SCHEME_FTP,S_OK,FALSE},
786             {URLZONE_INVALID,E_NOTIMPL,FALSE}
787         }
788     },
789     /* Make sure forbidden characters in "userinfo" get encoded. */
790     {   "ftp://\" \"weird@ftp.google.com/", 0, S_OK, FALSE,
791         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
792         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
793         Uri_HAS_SCHEME_NAME|Uri_HAS_USER_INFO|Uri_HAS_USER_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|
794         Uri_HAS_SCHEME,
795         FALSE,
796         {
797             {"ftp://%22%20%22weird@ftp.google.com/",S_OK,FALSE},
798             {"%22%20%22weird@ftp.google.com",S_OK,FALSE},
799             {"ftp://ftp.google.com/",S_OK,FALSE},
800             {"google.com",S_OK,FALSE},
801             {"",S_FALSE,FALSE},
802             {"",S_FALSE,FALSE},
803             {"ftp.google.com",S_OK,FALSE},
804             {"",S_FALSE,FALSE},
805             {"/",S_OK,FALSE},
806             {"/",S_OK,FALSE},
807             {"",S_FALSE,FALSE},
808             {"ftp://\" \"weird@ftp.google.com/",S_OK,FALSE},
809             {"ftp",S_OK,FALSE},
810             {"%22%20%22weird",S_OK,FALSE},
811             {"%22%20%22weird",S_OK,FALSE}
812         },
813         {
814             {Uri_HOST_DNS,S_OK,FALSE},
815             {21,S_OK,FALSE},
816             {URL_SCHEME_FTP,S_OK,FALSE},
817             {URLZONE_INVALID,E_NOTIMPL,FALSE}
818         }
819     },
820     /* Make sure the forbidden characters don't get percent encoded. */
821     {   "ftp://\" \"weird@ftp.google.com/", Uri_CREATE_NO_ENCODE_FORBIDDEN_CHARACTERS, S_OK, FALSE,
822         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
823         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
824         Uri_HAS_SCHEME_NAME|Uri_HAS_USER_INFO|Uri_HAS_USER_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|
825         Uri_HAS_SCHEME,
826         FALSE,
827         {
828             {"ftp://\" \"weird@ftp.google.com/",S_OK,FALSE},
829             {"\" \"weird@ftp.google.com",S_OK,FALSE},
830             {"ftp://ftp.google.com/",S_OK,FALSE},
831             {"google.com",S_OK,FALSE},
832             {"",S_FALSE,FALSE},
833             {"",S_FALSE,FALSE},
834             {"ftp.google.com",S_OK,FALSE},
835             {"",S_FALSE,FALSE},
836             {"/",S_OK,FALSE},
837             {"/",S_OK,FALSE},
838             {"",S_FALSE,FALSE},
839             {"ftp://\" \"weird@ftp.google.com/",S_OK,FALSE},
840             {"ftp",S_OK,FALSE},
841             {"\" \"weird",S_OK,FALSE},
842             {"\" \"weird",S_OK,FALSE}
843         },
844         {
845             {Uri_HOST_DNS,S_OK,FALSE},
846             {21,S_OK,FALSE},
847             {URL_SCHEME_FTP,S_OK,FALSE},
848             {URLZONE_INVALID,E_NOTIMPL,FALSE}
849         }
850     },
851     /* Allowed to have invalid % encoded because its an unknown scheme type. */
852     {   "zip://%xy:word@winehq.org/", 0, S_OK, FALSE,
853         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
854         Uri_HAS_HOST|Uri_HAS_PASSWORD|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
855         Uri_HAS_SCHEME_NAME|Uri_HAS_USER_INFO|Uri_HAS_USER_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
856         FALSE,
857         {
858             {"zip://%xy:word@winehq.org/",S_OK,FALSE},
859             {"%xy:word@winehq.org",S_OK,FALSE},
860             {"zip://%xy:word@winehq.org/",S_OK,FALSE},
861             {"winehq.org",S_OK,FALSE},
862             {"",S_FALSE,FALSE},
863             {"",S_FALSE,FALSE},
864             {"winehq.org",S_OK,FALSE},
865             {"word",S_OK,FALSE},
866             {"/",S_OK,FALSE},
867             {"/",S_OK,FALSE},
868             {"",S_FALSE,FALSE},
869             {"zip://%xy:word@winehq.org/",S_OK,FALSE},
870             {"zip",S_OK,FALSE},
871             {"%xy:word",S_OK,FALSE},
872             {"%xy",S_OK,FALSE}
873         },
874         {
875             {Uri_HOST_DNS,S_OK,FALSE},
876             {0,S_FALSE,FALSE},
877             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
878             {URLZONE_INVALID,E_NOTIMPL,FALSE}
879         }
880     },
881     /* Unreserved, percent encoded characters aren't decoded in the userinfo becuase the scheme
882      * isn't known.
883      */
884     {   "zip://%2E:%52%53ord@winehq.org/", 0, S_OK, FALSE,
885         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
886         Uri_HAS_HOST|Uri_HAS_PASSWORD|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
887         Uri_HAS_SCHEME_NAME|Uri_HAS_USER_INFO|Uri_HAS_USER_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
888         FALSE,
889         {
890             {"zip://%2E:%52%53ord@winehq.org/",S_OK,FALSE},
891             {"%2E:%52%53ord@winehq.org",S_OK,FALSE},
892             {"zip://%2E:%52%53ord@winehq.org/",S_OK,FALSE},
893             {"winehq.org",S_OK,FALSE},
894             {"",S_FALSE,FALSE},
895             {"",S_FALSE,FALSE},
896             {"winehq.org",S_OK,FALSE},
897             {"%52%53ord",S_OK,FALSE},
898             {"/",S_OK,FALSE},
899             {"/",S_OK,FALSE},
900             {"",S_FALSE,FALSE},
901             {"zip://%2E:%52%53ord@winehq.org/",S_OK,FALSE},
902             {"zip",S_OK,FALSE},
903             {"%2E:%52%53ord",S_OK,FALSE},
904             {"%2E",S_OK,FALSE}
905         },
906         {
907             {Uri_HOST_DNS,S_OK,FALSE},
908             {0,S_FALSE,FALSE},
909             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
910             {URLZONE_INVALID,E_NOTIMPL,FALSE}
911         }
912     },
913     {   "ftp://[](),'test':word@winehq.org/", 0, S_OK, FALSE,
914         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
915         Uri_HAS_HOST|Uri_HAS_PASSWORD|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
916         Uri_HAS_SCHEME_NAME|Uri_HAS_USER_INFO|Uri_HAS_USER_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|
917         Uri_HAS_SCHEME,
918         FALSE,
919         {
920             {"ftp://[](),'test':word@winehq.org/",S_OK,FALSE},
921             {"[](),'test':word@winehq.org",S_OK,FALSE},
922             {"ftp://winehq.org/",S_OK,FALSE},
923             {"winehq.org",S_OK,FALSE},
924             {"",S_FALSE,FALSE},
925             {"",S_FALSE,FALSE},
926             {"winehq.org",S_OK,FALSE},
927             {"word",S_OK,FALSE},
928             {"/",S_OK,FALSE},
929             {"/",S_OK,FALSE},
930             {"",S_FALSE,FALSE},
931             {"ftp://[](),'test':word@winehq.org/",S_OK,FALSE},
932             {"ftp",S_OK,FALSE},
933             {"[](),'test':word",S_OK,FALSE},
934             {"[](),'test'",S_OK,FALSE}
935         },
936         {
937             {Uri_HOST_DNS,S_OK,FALSE},
938             {21,S_OK,FALSE},
939             {URL_SCHEME_FTP,S_OK,FALSE},
940             {URLZONE_INVALID,E_NOTIMPL,FALSE}
941         }
942     },
943     {   "ftp://test?:word@winehq.org/", 0, S_OK, FALSE,
944         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
945         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
946         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
947         FALSE,
948         {
949             {"ftp://test/?:word@winehq.org/",S_OK,FALSE},
950             {"test",S_OK,FALSE},
951             {"ftp://test/?:word@winehq.org/",S_OK,FALSE},
952             {"",S_FALSE,FALSE},
953             {"",S_FALSE,FALSE},
954             {"",S_FALSE,FALSE},
955             {"test",S_OK,FALSE},
956             {"",S_FALSE,FALSE},
957             {"/",S_OK,FALSE},
958             {"/?:word@winehq.org/",S_OK,FALSE},
959             {"?:word@winehq.org/",S_OK,FALSE},
960             {"ftp://test?:word@winehq.org/",S_OK,FALSE},
961             {"ftp",S_OK,FALSE},
962             {"",S_FALSE,FALSE},
963             {"",S_FALSE,FALSE}
964         },
965         {
966             {Uri_HOST_DNS,S_OK,FALSE},
967             {21,S_OK,FALSE},
968             {URL_SCHEME_FTP,S_OK,FALSE},
969             {URLZONE_INVALID,E_NOTIMPL,FALSE}
970         }
971     },
972     {   "ftp://test#:word@winehq.org/", 0, S_OK, FALSE,
973         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_FRAGMENT|Uri_HAS_HOST|
974         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
975         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
976         FALSE,
977         {
978             {"ftp://test/#:word@winehq.org/",S_OK,FALSE},
979             {"test",S_OK,FALSE},
980             {"ftp://test/#:word@winehq.org/",S_OK,FALSE},
981             {"",S_FALSE,FALSE},
982             {"",S_FALSE,FALSE},
983             {"#:word@winehq.org/",S_OK,FALSE},
984             {"test",S_OK,FALSE},
985             {"",S_FALSE,FALSE},
986             {"/",S_OK,FALSE},
987             {"/",S_OK,FALSE},
988             {"",S_FALSE,FALSE},
989             {"ftp://test#:word@winehq.org/",S_OK,FALSE},
990             {"ftp",S_OK,FALSE},
991             {"",S_FALSE,FALSE},
992             {"",S_FALSE,FALSE}
993         },
994         {
995             {Uri_HOST_DNS,S_OK,FALSE},
996             {21,S_OK,FALSE},
997             {URL_SCHEME_FTP,S_OK,FALSE},
998             {URLZONE_INVALID,E_NOTIMPL,FALSE}
999         }
1000     },
1001     /* Allowed to have a backslash in the userinfo since it's an unknown scheme. */
1002     {   "zip://test\\:word@winehq.org/", 0, S_OK, FALSE,
1003         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_HOST|
1004         Uri_HAS_PASSWORD|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1005         Uri_HAS_USER_INFO|Uri_HAS_USER_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
1006         FALSE,
1007         {
1008             {"zip://test\\:word@winehq.org/",S_OK,FALSE},
1009             {"test\\:word@winehq.org",S_OK,FALSE},
1010             {"zip://test\\:word@winehq.org/",S_OK,FALSE},
1011             {"winehq.org",S_OK,FALSE},
1012             {"",S_FALSE,FALSE},
1013             {"",S_FALSE,FALSE},
1014             {"winehq.org",S_OK,FALSE},
1015             {"word",S_OK,FALSE},
1016             {"/",S_OK,FALSE},
1017             {"/",S_OK,FALSE},
1018             {"",S_FALSE,FALSE},
1019             {"zip://test\\:word@winehq.org/",S_OK,FALSE},
1020             {"zip",S_OK,FALSE},
1021             {"test\\:word",S_OK,FALSE},
1022             {"test\\",S_OK,FALSE}
1023         },
1024         {
1025             {Uri_HOST_DNS,S_OK,FALSE},
1026             {0,S_FALSE,FALSE},
1027             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1028             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1029         }
1030     },
1031     /* It normalizes IPv4 addresses correctly. */
1032     {   "http://127.000.000.100/", 0, S_OK, FALSE,
1033         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
1034         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1035         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1036         FALSE,
1037         {
1038             {"http://127.0.0.100/",S_OK,FALSE},
1039             {"127.0.0.100",S_OK,FALSE},
1040             {"http://127.0.0.100/",S_OK,FALSE},
1041             {"",S_FALSE,FALSE},
1042             {"",S_FALSE,FALSE},
1043             {"",S_FALSE,FALSE},
1044             {"127.0.0.100",S_OK,FALSE},
1045             {"",S_FALSE,FALSE},
1046             {"/",S_OK,FALSE},
1047             {"/",S_OK,FALSE},
1048             {"",S_FALSE,FALSE},
1049             {"http://127.000.000.100/",S_OK,FALSE},
1050             {"http",S_OK,FALSE},
1051             {"",S_FALSE,FALSE},
1052             {"",S_FALSE,FALSE}
1053         },
1054         {
1055             {Uri_HOST_IPV4,S_OK,FALSE},
1056             {80,S_OK,FALSE},
1057             {URL_SCHEME_HTTP,S_OK,FALSE},
1058             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1059         }
1060     },
1061     /* Make sure it normalizes partial IPv4 addresses correctly. */
1062     {   "http://127.0/", 0, S_OK, FALSE,
1063         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
1064         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1065         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1066         FALSE,
1067         {
1068             {"http://127.0.0.0/",S_OK,FALSE},
1069             {"127.0.0.0",S_OK,FALSE},
1070             {"http://127.0.0.0/",S_OK,FALSE},
1071             {"",S_FALSE,FALSE},
1072             {"",S_FALSE,FALSE},
1073             {"",S_FALSE,FALSE},
1074             {"127.0.0.0",S_OK,FALSE},
1075             {"",S_FALSE,FALSE},
1076             {"/",S_OK,FALSE},
1077             {"/",S_OK,FALSE},
1078             {"",S_FALSE,FALSE},
1079             {"http://127.0/",S_OK,FALSE},
1080             {"http",S_OK,FALSE},
1081             {"",S_FALSE,FALSE},
1082             {"",S_FALSE,FALSE}
1083         },
1084         {
1085             {Uri_HOST_IPV4,S_OK,FALSE},
1086             {80,S_OK,FALSE},
1087             {URL_SCHEME_HTTP,S_OK,FALSE},
1088             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1089         }
1090     },
1091     /* Make sure it converts implicit IPv4's correctly. */
1092     {   "http://123456/", 0, S_OK, FALSE,
1093         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
1094         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1095         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1096         FALSE,
1097         {
1098             {"http://0.1.226.64/",S_OK,FALSE},
1099             {"0.1.226.64",S_OK,FALSE},
1100             {"http://0.1.226.64/",S_OK,FALSE},
1101             {"",S_FALSE,FALSE},
1102             {"",S_FALSE,FALSE},
1103             {"",S_FALSE,FALSE},
1104             {"0.1.226.64",S_OK,FALSE},
1105             {"",S_FALSE,FALSE},
1106             {"/",S_OK,FALSE},
1107             {"/",S_OK,FALSE},
1108             {"",S_FALSE,FALSE},
1109             {"http://123456/",S_OK,FALSE},
1110             {"http",S_OK,FALSE},
1111             {"",S_FALSE,FALSE},
1112             {"",S_FALSE,FALSE}
1113         },
1114         {
1115             {Uri_HOST_IPV4,S_OK,FALSE},
1116             {80,S_OK,FALSE},
1117             {URL_SCHEME_HTTP,S_OK,FALSE},
1118             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1119         }
1120     },
1121     /* UINT_MAX */
1122     {   "http://4294967295/", 0, S_OK, FALSE,
1123         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
1124         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1125         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1126         FALSE,
1127         {
1128             {"http://255.255.255.255/",S_OK,FALSE},
1129             {"255.255.255.255",S_OK,FALSE},
1130             {"http://255.255.255.255/",S_OK,FALSE},
1131             {"",S_FALSE,FALSE},
1132             {"",S_FALSE,FALSE},
1133             {"",S_FALSE,FALSE},
1134             {"255.255.255.255",S_OK,FALSE},
1135             {"",S_FALSE,FALSE},
1136             {"/",S_OK,FALSE},
1137             {"/",S_OK,FALSE},
1138             {"",S_FALSE,FALSE},
1139             {"http://4294967295/",S_OK,FALSE},
1140             {"http",S_OK,FALSE},
1141             {"",S_FALSE,FALSE},
1142             {"",S_FALSE,FALSE}
1143         },
1144         {
1145             {Uri_HOST_IPV4,S_OK,FALSE},
1146             {80,S_OK,FALSE},
1147             {URL_SCHEME_HTTP,S_OK,FALSE},
1148             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1149         }
1150     },
1151     /* UINT_MAX+1 */
1152     {   "http://4294967296/", 0, S_OK, FALSE,
1153         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
1154         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1155         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1156         FALSE,
1157         {
1158             {"http://4294967296/",S_OK,FALSE},
1159             {"4294967296",S_OK,FALSE},
1160             {"http://4294967296/",S_OK,FALSE},
1161             {"",S_FALSE,FALSE},
1162             {"",S_FALSE,FALSE},
1163             {"",S_FALSE,FALSE},
1164             {"4294967296",S_OK,FALSE},
1165             {"",S_FALSE,FALSE},
1166             {"/",S_OK,FALSE},
1167             {"/",S_OK,FALSE},
1168             {"",S_FALSE,FALSE},
1169             {"http://4294967296/",S_OK,FALSE},
1170             {"http",S_OK,FALSE},
1171             {"",S_FALSE,FALSE},
1172             {"",S_FALSE,FALSE}
1173         },
1174         {
1175             {Uri_HOST_DNS,S_OK,FALSE},
1176             {80,S_OK,FALSE},
1177             {URL_SCHEME_HTTP,S_OK,FALSE},
1178             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1179         }
1180     },
1181     /* Window's doesn't normalize IP address for unknown schemes. */
1182     {   "1234://4294967295/", 0, S_OK, FALSE,
1183         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
1184         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1185         Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
1186         FALSE,
1187         {
1188             {"1234://4294967295/",S_OK,FALSE},
1189             {"4294967295",S_OK,FALSE},
1190             {"1234://4294967295/",S_OK,FALSE},
1191             {"",S_FALSE,FALSE},
1192             {"",S_FALSE,FALSE},
1193             {"",S_FALSE,FALSE},
1194             {"4294967295",S_OK,FALSE},
1195             {"",S_FALSE,FALSE},
1196             {"/",S_OK,FALSE},
1197             {"/",S_OK,FALSE},
1198             {"",S_FALSE,FALSE},
1199             {"1234://4294967295/",S_OK,FALSE},
1200             {"1234",S_OK,FALSE},
1201             {"",S_FALSE,FALSE},
1202             {"",S_FALSE,FALSE}
1203         },
1204         {
1205             {Uri_HOST_IPV4,S_OK,FALSE},
1206             {0,S_FALSE,FALSE},
1207             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1208             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1209         }
1210     },
1211     /* Window's doesn't normalize IP address for unknown schemes. */
1212     {   "1234://127.001/", 0, S_OK, FALSE,
1213         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
1214         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1215         Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
1216         FALSE,
1217         {
1218             {"1234://127.001/",S_OK,FALSE},
1219             {"127.001",S_OK,FALSE},
1220             {"1234://127.001/",S_OK,FALSE},
1221             {"",S_FALSE,FALSE},
1222             {"",S_FALSE,FALSE},
1223             {"",S_FALSE,FALSE},
1224             {"127.001",S_OK,FALSE},
1225             {"",S_FALSE,FALSE},
1226             {"/",S_OK,FALSE},
1227             {"/",S_OK,FALSE},
1228             {"",S_FALSE,FALSE},
1229             {"1234://127.001/",S_OK,FALSE},
1230             {"1234",S_OK,FALSE},
1231             {"",S_FALSE,FALSE},
1232             {"",S_FALSE,FALSE}
1233         },
1234         {
1235             {Uri_HOST_IPV4,S_OK,FALSE},
1236             {0,S_FALSE,FALSE},
1237             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1238             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1239         }
1240     },
1241     {   "http://[FEDC:BA98::3210]", 0, S_OK, FALSE,
1242         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
1243         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1244         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1245         FALSE,
1246         {
1247             {"http://[fedc:ba98::3210]/",S_OK,FALSE},
1248             {"[fedc:ba98::3210]",S_OK,FALSE},
1249             {"http://[fedc:ba98::3210]/",S_OK,FALSE},
1250             {"",S_FALSE,FALSE},
1251             {"",S_FALSE,FALSE},
1252             {"",S_FALSE,FALSE},
1253             {"fedc:ba98::3210",S_OK,FALSE},
1254             {"",S_FALSE,FALSE},
1255             {"/",S_OK,FALSE},
1256             {"/",S_OK,FALSE},
1257             {"",S_FALSE,FALSE},
1258             {"http://[FEDC:BA98::3210]",S_OK,FALSE},
1259             {"http",S_OK,FALSE},
1260             {"",S_FALSE,FALSE},
1261             {"",S_FALSE,FALSE},
1262         },
1263         {
1264             {Uri_HOST_IPV6,S_OK,FALSE},
1265             {80,S_OK,FALSE},
1266             {URL_SCHEME_HTTP,S_OK,FALSE},
1267             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1268         }
1269     },
1270     {   "http://[::]", 0, S_OK, FALSE,
1271         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
1272         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1273         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1274         FALSE,
1275         {
1276             {"http://[::]/",S_OK,FALSE},
1277             {"[::]",S_OK,FALSE},
1278             {"http://[::]/",S_OK,FALSE},
1279             {"",S_FALSE,FALSE},
1280             {"",S_FALSE,FALSE},
1281             {"",S_FALSE,FALSE},
1282             {"::",S_OK,FALSE},
1283             {"",S_FALSE,FALSE},
1284             {"/",S_OK,FALSE},
1285             {"/",S_OK,FALSE},
1286             {"",S_FALSE,FALSE},
1287             {"http://[::]",S_OK,FALSE},
1288             {"http",S_OK,FALSE},
1289             {"",S_FALSE,FALSE},
1290             {"",S_FALSE,FALSE},
1291         },
1292         {
1293             {Uri_HOST_IPV6,S_OK,FALSE},
1294             {80,S_OK,FALSE},
1295             {URL_SCHEME_HTTP,S_OK,FALSE},
1296             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1297         }
1298     },
1299     {   "http://[FEDC:BA98::]", 0, S_OK, FALSE,
1300         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
1301         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1302         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1303         FALSE,
1304         {
1305             {"http://[fedc:ba98::]/",S_OK,FALSE},
1306             {"[fedc:ba98::]",S_OK,FALSE},
1307             {"http://[fedc:ba98::]/",S_OK,FALSE},
1308             {"",S_FALSE,FALSE},
1309             {"",S_FALSE,FALSE},
1310             {"",S_FALSE,FALSE},
1311             {"fedc:ba98::",S_OK,FALSE},
1312             {"",S_FALSE,FALSE},
1313             {"/",S_OK,FALSE},
1314             {"/",S_OK,FALSE},
1315             {"",S_FALSE,FALSE},
1316             {"http://[FEDC:BA98::]",S_OK,FALSE},
1317             {"http",S_OK,FALSE},
1318             {"",S_FALSE,FALSE},
1319             {"",S_FALSE,FALSE},
1320         },
1321         {
1322             {Uri_HOST_IPV6,S_OK,FALSE},
1323             {80,S_OK,FALSE},
1324             {URL_SCHEME_HTTP,S_OK,FALSE},
1325             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1326         }
1327     },
1328     /* Valid even with 2 byte elision because it doesn't appear the beginning or end. */
1329     {   "http://[1::3:4:5:6:7:8]", 0, S_OK, FALSE,
1330         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
1331         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1332         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1333         FALSE,
1334         {
1335             {"http://[1:0:3:4:5:6:7:8]/",S_OK,FALSE},
1336             {"[1:0:3:4:5:6:7:8]",S_OK,FALSE},
1337             {"http://[1:0:3:4:5:6:7:8]/",S_OK,FALSE},
1338             {"",S_FALSE,FALSE},
1339             {"",S_FALSE,FALSE},
1340             {"",S_FALSE,FALSE},
1341             {"1:0:3:4:5:6:7:8",S_OK,FALSE},
1342             {"",S_FALSE,FALSE},
1343             {"/",S_OK,FALSE},
1344             {"/",S_OK,FALSE},
1345             {"",S_FALSE,FALSE},
1346             {"http://[1::3:4:5:6:7:8]",S_OK,FALSE},
1347             {"http",S_OK,FALSE},
1348             {"",S_FALSE,FALSE},
1349             {"",S_FALSE,FALSE},
1350         },
1351         {
1352             {Uri_HOST_IPV6,S_OK,FALSE},
1353             {80,S_OK,FALSE},
1354             {URL_SCHEME_HTTP,S_OK,FALSE},
1355             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1356         }
1357     },
1358     {   "http://[v2.34]/", 0, S_OK, FALSE,
1359         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
1360         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1361         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1362         FALSE,
1363         {
1364             {"http://[v2.34]/",S_OK,FALSE},
1365             {"[v2.34]",S_OK,FALSE},
1366             {"http://[v2.34]/",S_OK,FALSE},
1367             {"",S_FALSE,FALSE},
1368             {"",S_FALSE,FALSE},
1369             {"",S_FALSE,FALSE},
1370             {"[v2.34]",S_OK,FALSE},
1371             {"",S_FALSE,FALSE},
1372             {"/",S_OK,FALSE},
1373             {"/",S_OK,FALSE},
1374             {"",S_FALSE,FALSE},
1375             {"http://[v2.34]/",S_OK,FALSE},
1376             {"http",S_OK,FALSE},
1377             {"",S_FALSE,FALSE},
1378             {"",S_FALSE,FALSE}
1379         },
1380         {
1381             {Uri_HOST_UNKNOWN,S_OK,FALSE},
1382             {80,S_OK,FALSE},
1383             {URL_SCHEME_HTTP,S_OK,FALSE},
1384             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1385         }
1386     },
1387     /* Windows ignores ':' if they appear after a '[' on a non-IPLiteral host. */
1388     {   "http://[xyz:12345.com/test", 0, S_OK, FALSE,
1389         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
1390         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
1391         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1392         FALSE,
1393         {
1394             {"http://[xyz:12345.com/test",S_OK,FALSE},
1395             {"[xyz:12345.com",S_OK,FALSE},
1396             {"http://[xyz:12345.com/test",S_OK,FALSE},
1397             {"[xyz:12345.com",S_OK,FALSE},
1398             {"",S_FALSE,FALSE},
1399             {"",S_FALSE,FALSE},
1400             {"[xyz:12345.com",S_OK,FALSE},
1401             {"",S_FALSE,FALSE},
1402             {"/test",S_OK,FALSE},
1403             {"/test",S_OK,FALSE},
1404             {"",S_FALSE,FALSE},
1405             {"http://[xyz:12345.com/test",S_OK,FALSE},
1406             {"http",S_OK,FALSE},
1407             {"",S_FALSE,FALSE},
1408             {"",S_FALSE,FALSE}
1409         },
1410         {
1411             {Uri_HOST_DNS,S_OK,FALSE},
1412             {80,S_OK,FALSE},
1413             {URL_SCHEME_HTTP,S_OK,FALSE},
1414             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1415         }
1416     },
1417     /* Valid URI since the '[' and ']' don't appear at the beginning and end
1418      * of the host name (respectively).
1419      */
1420     {   "ftp://www.[works].com/", 0, S_OK, FALSE,
1421         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
1422         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
1423         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1424         FALSE,
1425         {
1426             {"ftp://www.[works].com/",S_OK,FALSE},
1427             {"www.[works].com",S_OK,FALSE},
1428             {"ftp://www.[works].com/",S_OK,FALSE},
1429             {"[works].com",S_OK,FALSE},
1430             {"",S_FALSE,FALSE},
1431             {"",S_FALSE,FALSE},
1432             {"www.[works].com",S_OK,FALSE},
1433             {"",S_FALSE,FALSE},
1434             {"/",S_OK,FALSE},
1435             {"/",S_OK,FALSE},
1436             {"",S_FALSE,FALSE},
1437             {"ftp://www.[works].com/",S_OK,FALSE},
1438             {"ftp",S_OK,FALSE},
1439             {"",S_FALSE,FALSE},
1440             {"",S_FALSE,FALSE}
1441         },
1442         {
1443             {Uri_HOST_DNS,S_OK,FALSE},
1444             {21,S_OK,FALSE},
1445             {URL_SCHEME_FTP,S_OK,FALSE},
1446             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1447         }
1448     },
1449     /* Considers ':' a delimiter since it appears after the ']'. */
1450     {   "http://www.google.com]:12345/", 0, S_OK, FALSE,
1451         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
1452         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
1453         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1454         FALSE,
1455         {
1456             {"http://www.google.com]:12345/",S_OK,FALSE},
1457             {"www.google.com]:12345",S_OK,FALSE},
1458             {"http://www.google.com]:12345/",S_OK,FALSE},
1459             {"google.com]",S_OK,FALSE},
1460             {"",S_FALSE,FALSE},
1461             {"",S_FALSE,FALSE},
1462             {"www.google.com]",S_OK,FALSE},
1463             {"",S_FALSE,FALSE},
1464             {"/",S_OK,FALSE},
1465             {"/",S_OK,FALSE},
1466             {"",S_FALSE,FALSE},
1467             {"http://www.google.com]:12345/",S_OK,FALSE},
1468             {"http",S_OK,FALSE},
1469             {"",S_FALSE,FALSE},
1470             {"",S_FALSE,FALSE}
1471         },
1472         {
1473             {Uri_HOST_DNS,S_OK,FALSE},
1474             {12345,S_OK,FALSE},
1475             {URL_SCHEME_HTTP,S_OK,FALSE},
1476             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1477         }
1478     },
1479     /* Unknown scheme types can have invalid % encoded data in the hostname. */
1480     {   "zip://w%XXw%GEw.google.com/", 0, S_OK, FALSE,
1481         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
1482         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
1483         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
1484         FALSE,
1485         {
1486             {"zip://w%XXw%GEw.google.com/",S_OK,FALSE},
1487             {"w%XXw%GEw.google.com",S_OK,FALSE},
1488             {"zip://w%XXw%GEw.google.com/",S_OK,FALSE},
1489             {"google.com",S_OK,FALSE},
1490             {"",S_FALSE,FALSE},
1491             {"",S_FALSE,FALSE},
1492             {"w%XXw%GEw.google.com",S_OK,FALSE},
1493             {"",S_FALSE,FALSE},
1494             {"/",S_OK,FALSE},
1495             {"/",S_OK,FALSE},
1496             {"",S_FALSE,FALSE},
1497             {"zip://w%XXw%GEw.google.com/",S_OK,FALSE},
1498             {"zip",S_OK,FALSE},
1499             {"",S_FALSE,FALSE},
1500             {"",S_FALSE,FALSE}
1501         },
1502         {
1503             {Uri_HOST_DNS,S_OK,FALSE},
1504             {0,S_FALSE,FALSE},
1505             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1506             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1507         }
1508     },
1509     /* Unknown scheme types hostname doesn't get lower cased. */
1510     {   "zip://GOOGLE.com/", 0, S_OK, FALSE,
1511         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
1512         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
1513         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
1514         FALSE,
1515         {
1516             {"zip://GOOGLE.com/",S_OK,FALSE},
1517             {"GOOGLE.com",S_OK,FALSE},
1518             {"zip://GOOGLE.com/",S_OK,FALSE},
1519             {"GOOGLE.com",S_OK,FALSE},
1520             {"",S_FALSE,FALSE},
1521             {"",S_FALSE,FALSE},
1522             {"GOOGLE.com",S_OK,FALSE},
1523             {"",S_FALSE,FALSE},
1524             {"/",S_OK,FALSE},
1525             {"/",S_OK,FALSE},
1526             {"",S_FALSE,FALSE},
1527             {"zip://GOOGLE.com/",S_OK,FALSE},
1528             {"zip",S_OK,FALSE},
1529             {"",S_FALSE,FALSE},
1530             {"",S_FALSE,FALSE}
1531         },
1532         {
1533             {Uri_HOST_DNS,S_OK,FALSE},
1534             {0,S_FALSE,FALSE},
1535             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1536             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1537         }
1538     },
1539     /* Hostname get's lower cased for known scheme types. */
1540     {   "http://WWW.GOOGLE.com/", 0, S_OK, FALSE,
1541         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
1542         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
1543         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1544         FALSE,
1545         {
1546             {"http://www.google.com/",S_OK,FALSE},
1547             {"www.google.com",S_OK,FALSE},
1548             {"http://www.google.com/",S_OK,FALSE},
1549             {"google.com",S_OK,FALSE},
1550             {"",S_FALSE,FALSE},
1551             {"",S_FALSE,FALSE},
1552             {"www.google.com",S_OK,FALSE},
1553             {"",S_FALSE,FALSE},
1554             {"/",S_OK,FALSE},
1555             {"/",S_OK,FALSE},
1556             {"",S_FALSE,FALSE},
1557             {"http://WWW.GOOGLE.com/",S_OK,FALSE},
1558             {"http",S_OK,FALSE},
1559             {"",S_FALSE,FALSE},
1560             {"",S_FALSE,FALSE}
1561         },
1562         {
1563             {Uri_HOST_DNS,S_OK,FALSE},
1564             {80,S_OK,FALSE},
1565             {URL_SCHEME_HTTP,S_OK,FALSE},
1566             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1567         }
1568     },
1569     /* Characters that get % encoded in the hostname also have their percent
1570      * encoded forms lower cased.
1571      */
1572     {   "http://www.%7Cgoogle|.com/", 0, S_OK, FALSE,
1573         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
1574         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
1575         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1576         FALSE,
1577         {
1578             {"http://www.%7cgoogle%7c.com/",S_OK,FALSE},
1579             {"www.%7cgoogle%7c.com",S_OK,FALSE},
1580             {"http://www.%7cgoogle%7c.com/",S_OK,FALSE},
1581             {"%7cgoogle%7c.com",S_OK,FALSE},
1582             {"",S_FALSE,FALSE},
1583             {"",S_FALSE,FALSE},
1584             {"www.%7cgoogle%7c.com",S_OK,FALSE},
1585             {"",S_FALSE,FALSE},
1586             {"/",S_OK,FALSE},
1587             {"/",S_OK,FALSE},
1588             {"",S_FALSE,FALSE},
1589             {"http://www.%7Cgoogle|.com/",S_OK,FALSE},
1590             {"http",S_OK,FALSE},
1591             {"",S_FALSE,FALSE},
1592             {"",S_FALSE,FALSE}
1593         },
1594         {
1595             {Uri_HOST_DNS,S_OK,FALSE},
1596             {80,S_OK,FALSE},
1597             {URL_SCHEME_HTTP,S_OK,FALSE},
1598             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1599         }
1600     },
1601     /* IPv4 addresses attached to IPv6 can be included in elisions. */
1602     {   "http://[1:2:3:4:5:6:0.0.0.0]", 0, S_OK, FALSE,
1603         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
1604         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1605         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1606         FALSE,
1607         {
1608             {"http://[1:2:3:4:5:6::]/",S_OK,FALSE},
1609             {"[1:2:3:4:5:6::]",S_OK,FALSE},
1610             {"http://[1:2:3:4:5:6::]/",S_OK,FALSE},
1611             {"",S_FALSE,FALSE},
1612             {"",S_FALSE,FALSE},
1613             {"",S_FALSE,FALSE},
1614             {"1:2:3:4:5:6::",S_OK,FALSE},
1615             {"",S_FALSE,FALSE},
1616             {"/",S_OK,FALSE},
1617             {"/",S_OK,FALSE},
1618             {"",S_FALSE,FALSE},
1619             {"http://[1:2:3:4:5:6:0.0.0.0]",S_OK,FALSE},
1620             {"http",S_OK,FALSE},
1621             {"",S_FALSE,FALSE},
1622             {"",S_FALSE,FALSE},
1623         },
1624         {
1625             {Uri_HOST_IPV6,S_OK,FALSE},
1626             {80,S_OK,FALSE},
1627             {URL_SCHEME_HTTP,S_OK,FALSE},
1628             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1629         }
1630     },
1631     /* IPv4 addresses get normalized. */
1632     {   "http://[::001.002.003.000]", 0, S_OK, FALSE,
1633         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
1634         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1635         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1636         FALSE,
1637         {
1638             {"http://[::1.2.3.0]/",S_OK,FALSE},
1639             {"[::1.2.3.0]",S_OK,FALSE},
1640             {"http://[::1.2.3.0]/",S_OK,FALSE},
1641             {"",S_FALSE,FALSE},
1642             {"",S_FALSE,FALSE},
1643             {"",S_FALSE,FALSE},
1644             {"::1.2.3.0",S_OK,FALSE},
1645             {"",S_FALSE,FALSE},
1646             {"/",S_OK,FALSE},
1647             {"/",S_OK,FALSE},
1648             {"",S_FALSE,FALSE},
1649             {"http://[::001.002.003.000]",S_OK,FALSE},
1650             {"http",S_OK,FALSE},
1651             {"",S_FALSE,FALSE},
1652             {"",S_FALSE,FALSE},
1653         },
1654         {
1655             {Uri_HOST_IPV6,S_OK,FALSE},
1656             {80,S_OK,FALSE},
1657             {URL_SCHEME_HTTP,S_OK,FALSE},
1658             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1659         }
1660     },
1661     /* Windows doesn't do anything to IPv6's in unknown schemes. */
1662     {   "zip://[0001:0:000:0004:0005:0006:001.002.003.000]", 0, S_OK, FALSE,
1663         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
1664         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1665         Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
1666         FALSE,
1667         {
1668             {"zip://[0001:0:000:0004:0005:0006:001.002.003.000]/",S_OK,FALSE},
1669             {"[0001:0:000:0004:0005:0006:001.002.003.000]",S_OK,FALSE},
1670             {"zip://[0001:0:000:0004:0005:0006:001.002.003.000]/",S_OK,FALSE},
1671             {"",S_FALSE,FALSE},
1672             {"",S_FALSE,FALSE},
1673             {"",S_FALSE,FALSE},
1674             {"0001:0:000:0004:0005:0006:001.002.003.000",S_OK,FALSE},
1675             {"",S_FALSE,FALSE},
1676             {"/",S_OK,FALSE},
1677             {"/",S_OK,FALSE},
1678             {"",S_FALSE,FALSE},
1679             {"zip://[0001:0:000:0004:0005:0006:001.002.003.000]",S_OK,FALSE},
1680             {"zip",S_OK,FALSE},
1681             {"",S_FALSE,FALSE},
1682             {"",S_FALSE,FALSE},
1683         },
1684         {
1685             {Uri_HOST_IPV6,S_OK,FALSE},
1686             {0,S_FALSE,FALSE},
1687             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1688             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1689         }
1690     },
1691     /* IPv4 address is converted into 2 h16 components. */
1692     {   "http://[ffff::192.222.111.32]", 0, S_OK, FALSE,
1693         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
1694         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1695         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1696         FALSE,
1697         {
1698             {"http://[ffff::c0de:6f20]/",S_OK,FALSE},
1699             {"[ffff::c0de:6f20]",S_OK,FALSE},
1700             {"http://[ffff::c0de:6f20]/",S_OK,FALSE},
1701             {"",S_FALSE,FALSE},
1702             {"",S_FALSE,FALSE},
1703             {"",S_FALSE,FALSE},
1704             {"ffff::c0de:6f20",S_OK,FALSE},
1705             {"",S_FALSE,FALSE},
1706             {"/",S_OK,FALSE},
1707             {"/",S_OK,FALSE},
1708             {"",S_FALSE,FALSE},
1709             {"http://[ffff::192.222.111.32]",S_OK,FALSE},
1710             {"http",S_OK,FALSE},
1711             {"",S_FALSE,FALSE},
1712             {"",S_FALSE,FALSE},
1713         },
1714         {
1715             {Uri_HOST_IPV6,S_OK,FALSE},
1716             {80,S_OK,FALSE},
1717             {URL_SCHEME_HTTP,S_OK,FALSE},
1718             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1719         }
1720     },
1721     /* Max value for a port. */
1722     {   "http://google.com:65535", 0, S_OK, FALSE,
1723         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
1724         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1725         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1726         FALSE,
1727         {
1728             {"http://google.com:65535/",S_OK,FALSE},
1729             {"google.com:65535",S_OK,FALSE},
1730             {"http://google.com:65535/",S_OK,FALSE},
1731             {"google.com",S_OK,FALSE},
1732             {"",S_FALSE,FALSE},
1733             {"",S_FALSE,FALSE},
1734             {"google.com",S_OK,FALSE},
1735             {"",S_FALSE,FALSE},
1736             {"/",S_OK,FALSE},
1737             {"/",S_OK,FALSE},
1738             {"",S_FALSE,FALSE},
1739             {"http://google.com:65535",S_OK,FALSE},
1740             {"http",S_OK,FALSE},
1741             {"",S_FALSE,FALSE},
1742             {"",S_FALSE,FALSE}
1743         },
1744         {
1745             {Uri_HOST_DNS,S_OK,FALSE},
1746             {65535,S_OK,FALSE},
1747             {URL_SCHEME_HTTP,S_OK,FALSE},
1748             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1749         }
1750     },
1751     {   "zip://google.com:65536", 0, S_OK, FALSE,
1752         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
1753         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1754         Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
1755         FALSE,
1756         {
1757             {"zip://google.com:65536/",S_OK,FALSE},
1758             {"google.com:65536",S_OK,FALSE},
1759             {"zip://google.com:65536/",S_OK,FALSE},
1760             {"google.com:65536",S_OK,FALSE},
1761             {"",S_FALSE,FALSE},
1762             {"",S_FALSE,FALSE},
1763             {"google.com:65536",S_OK,FALSE},
1764             {"",S_FALSE,FALSE},
1765             {"/",S_OK,FALSE},
1766             {"/",S_OK,FALSE},
1767             {"",S_FALSE,FALSE},
1768             {"zip://google.com:65536",S_OK,FALSE},
1769             {"zip",S_OK,FALSE},
1770             {"",S_FALSE,FALSE},
1771             {"",S_FALSE,FALSE}
1772         },
1773         {
1774             {Uri_HOST_DNS,S_OK,FALSE},
1775             {0,S_FALSE,FALSE},
1776             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1777             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1778         }
1779     },
1780     {   "zip://google.com:65536:25", 0, S_OK, FALSE,
1781         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
1782         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1783         Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
1784         FALSE,
1785         {
1786             {"zip://google.com:65536:25/",S_OK,FALSE},
1787             {"google.com:65536:25",S_OK,FALSE},
1788             {"zip://google.com:65536:25/",S_OK,FALSE},
1789             {"google.com:65536:25",S_OK,FALSE},
1790             {"",S_FALSE,FALSE},
1791             {"",S_FALSE,FALSE},
1792             {"google.com:65536:25",S_OK,FALSE},
1793             {"",S_FALSE,FALSE},
1794             {"/",S_OK,FALSE},
1795             {"/",S_OK,FALSE},
1796             {"",S_FALSE,FALSE},
1797             {"zip://google.com:65536:25",S_OK,FALSE},
1798             {"zip",S_OK,FALSE},
1799             {"",S_FALSE,FALSE},
1800             {"",S_FALSE,FALSE}
1801         },
1802         {
1803             {Uri_HOST_DNS,S_OK,FALSE},
1804             {0,S_FALSE,FALSE},
1805             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1806             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1807         }
1808     },
1809     {   "zip://[::ffff]:abcd", 0, S_OK, FALSE,
1810         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|
1811         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1812         Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
1813         FALSE,
1814         {
1815             {"zip://[::ffff]:abcd/",S_OK,FALSE},
1816             {"[::ffff]:abcd",S_OK,FALSE},
1817             {"zip://[::ffff]:abcd/",S_OK,FALSE},
1818             {"",S_FALSE,FALSE},
1819             {"",S_FALSE,FALSE},
1820             {"",S_FALSE,FALSE},
1821             {"[::ffff]:abcd",S_OK,FALSE},
1822             {"",S_FALSE,FALSE},
1823             {"/",S_OK,FALSE},
1824             {"/",S_OK,FALSE},
1825             {"",S_FALSE,FALSE},
1826             {"zip://[::ffff]:abcd",S_OK,FALSE},
1827             {"zip",S_OK,FALSE},
1828             {"",S_FALSE,FALSE},
1829             {"",S_FALSE,FALSE}
1830         },
1831         {
1832             {Uri_HOST_DNS,S_OK,FALSE},
1833             {0,S_FALSE,FALSE},
1834             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1835             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1836         }
1837     },
1838     {   "zip://127.0.0.1:abcd", 0, S_OK, FALSE,
1839         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
1840         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1841         Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
1842         FALSE,
1843         {
1844             {"zip://127.0.0.1:abcd/",S_OK,FALSE},
1845             {"127.0.0.1:abcd",S_OK,FALSE},
1846             {"zip://127.0.0.1:abcd/",S_OK,FALSE},
1847             {"0.1:abcd",S_OK,FALSE},
1848             {"",S_FALSE,FALSE},
1849             {"",S_FALSE,FALSE},
1850             {"127.0.0.1:abcd",S_OK,FALSE},
1851             {"",S_FALSE,FALSE},
1852             {"/",S_OK,FALSE},
1853             {"/",S_OK,FALSE},
1854             {"",S_FALSE,FALSE},
1855             {"zip://127.0.0.1:abcd",S_OK,FALSE},
1856             {"zip",S_OK,FALSE},
1857             {"",S_FALSE,FALSE},
1858             {"",S_FALSE,FALSE}
1859         },
1860         {
1861             {Uri_HOST_DNS,S_OK,FALSE},
1862             {0,S_FALSE,FALSE},
1863             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1864             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1865         }
1866     },
1867     /* Port is just copied over. */
1868     {   "http://google.com:00035", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
1869         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
1870         Uri_HAS_HOST|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1871         FALSE,
1872         {
1873             {"http://google.com:00035",S_OK,FALSE},
1874             {"google.com:00035",S_OK,FALSE},
1875             {"http://google.com:00035",S_OK,FALSE,"http://google.com:35"},
1876             {"google.com",S_OK,FALSE},
1877             {"",S_FALSE,FALSE},
1878             {"",S_FALSE,FALSE},
1879             {"google.com",S_OK,FALSE},
1880             {"",S_FALSE,FALSE},
1881             {"",S_FALSE,FALSE},
1882             {"",S_FALSE,FALSE},
1883             {"",S_FALSE,FALSE},
1884             {"http://google.com:00035",S_OK,FALSE},
1885             {"http",S_OK,FALSE},
1886             {"",S_FALSE,FALSE},
1887             {"",S_FALSE,FALSE}
1888         },
1889         {
1890             {Uri_HOST_DNS,S_OK,FALSE},
1891             {35,S_OK,FALSE},
1892             {URL_SCHEME_HTTP,S_OK,FALSE},
1893             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1894         }
1895     },
1896     /* Default port is copied over. */
1897     {   "http://google.com:80", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
1898         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
1899         Uri_HAS_HOST|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1900         FALSE,
1901         {
1902             {"http://google.com:80",S_OK,FALSE},
1903             {"google.com:80",S_OK,FALSE},
1904             {"http://google.com:80",S_OK,FALSE},
1905             {"google.com",S_OK,FALSE},
1906             {"",S_FALSE,FALSE},
1907             {"",S_FALSE,FALSE},
1908             {"google.com",S_OK,FALSE},
1909             {"",S_FALSE,FALSE},
1910             {"",S_FALSE,FALSE},
1911             {"",S_FALSE,FALSE},
1912             {"",S_FALSE,FALSE},
1913             {"http://google.com:80",S_OK,FALSE},
1914             {"http",S_OK,FALSE},
1915             {"",S_FALSE,FALSE},
1916             {"",S_FALSE,FALSE}
1917         },
1918         {
1919             {Uri_HOST_DNS,S_OK,FALSE},
1920             {80,S_OK,FALSE},
1921             {URL_SCHEME_HTTP,S_OK,FALSE},
1922             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1923         }
1924     },
1925     {   "http://google.com.uk", 0, S_OK, FALSE,
1926         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
1927         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1928         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1929         FALSE,
1930         {
1931             {"http://google.com.uk/",S_OK,FALSE},
1932             {"google.com.uk",S_OK,FALSE},
1933             {"http://google.com.uk/",S_OK,FALSE},
1934             {"google.com.uk",S_OK,FALSE},
1935             {"",S_FALSE,FALSE},
1936             {"",S_FALSE,FALSE},
1937             {"google.com.uk",S_OK,FALSE},
1938             {"",S_FALSE,FALSE},
1939             {"/",S_OK,FALSE},
1940             {"/",S_OK,FALSE},
1941             {"",S_FALSE,FALSE},
1942             {"http://google.com.uk",S_OK,FALSE},
1943             {"http",S_OK,FALSE},
1944             {"",S_FALSE,FALSE},
1945             {"",S_FALSE,FALSE}
1946         },
1947         {
1948             {Uri_HOST_DNS,S_OK,FALSE},
1949             {80,S_OK,FALSE},
1950             {URL_SCHEME_HTTP,S_OK,FALSE},
1951             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1952         }
1953     },
1954     {   "http://google.com.com", 0, S_OK, FALSE,
1955         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
1956         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1957         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1958         FALSE,
1959         {
1960             {"http://google.com.com/",S_OK,FALSE},
1961             {"google.com.com",S_OK,FALSE},
1962             {"http://google.com.com/",S_OK,FALSE},
1963             {"com.com",S_OK,FALSE},
1964             {"",S_FALSE,FALSE},
1965             {"",S_FALSE,FALSE},
1966             {"google.com.com",S_OK,FALSE},
1967             {"",S_FALSE,FALSE},
1968             {"/",S_OK,FALSE},
1969             {"/",S_OK,FALSE},
1970             {"",S_FALSE,FALSE},
1971             {"http://google.com.com",S_OK,FALSE},
1972             {"http",S_OK,FALSE},
1973             {"",S_FALSE,FALSE},
1974             {"",S_FALSE,FALSE}
1975         },
1976         {
1977             {Uri_HOST_DNS,S_OK,FALSE},
1978             {80,S_OK,FALSE},
1979             {URL_SCHEME_HTTP,S_OK,FALSE},
1980             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1981         }
1982     },
1983     {   "http://google.uk.1", 0, S_OK, FALSE,
1984         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
1985         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1986         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1987         FALSE,
1988         {
1989             {"http://google.uk.1/",S_OK,FALSE},
1990             {"google.uk.1",S_OK,FALSE},
1991             {"http://google.uk.1/",S_OK,FALSE},
1992             {"google.uk.1",S_OK,FALSE},
1993             {"",S_FALSE,FALSE},
1994             {"",S_FALSE,FALSE},
1995             {"google.uk.1",S_OK,FALSE},
1996             {"",S_FALSE,FALSE},
1997             {"/",S_OK,FALSE},
1998             {"/",S_OK,FALSE},
1999             {"",S_FALSE,FALSE},
2000             {"http://google.uk.1",S_OK,FALSE},
2001             {"http",S_OK,FALSE},
2002             {"",S_FALSE,FALSE},
2003             {"",S_FALSE,FALSE}
2004         },
2005         {
2006             {Uri_HOST_DNS,S_OK,FALSE},
2007             {80,S_OK,FALSE},
2008             {URL_SCHEME_HTTP,S_OK,FALSE},
2009             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2010         }
2011     },
2012     /* Since foo isn't a recognized 3 character TLD its considered the domain name. */
2013     {   "http://google.foo.uk", 0, S_OK, FALSE,
2014         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
2015         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
2016         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
2017         FALSE,
2018         {
2019             {"http://google.foo.uk/",S_OK,FALSE},
2020             {"google.foo.uk",S_OK,FALSE},
2021             {"http://google.foo.uk/",S_OK,FALSE},
2022             {"foo.uk",S_OK,FALSE},
2023             {"",S_FALSE,FALSE},
2024             {"",S_FALSE,FALSE},
2025             {"google.foo.uk",S_OK,FALSE},
2026             {"",S_FALSE,FALSE},
2027             {"/",S_OK,FALSE},
2028             {"/",S_OK,FALSE},
2029             {"",S_FALSE,FALSE},
2030             {"http://google.foo.uk",S_OK,FALSE},
2031             {"http",S_OK,FALSE},
2032             {"",S_FALSE,FALSE},
2033             {"",S_FALSE,FALSE}
2034         },
2035         {
2036             {Uri_HOST_DNS,S_OK,FALSE},
2037             {80,S_OK,FALSE},
2038             {URL_SCHEME_HTTP,S_OK,FALSE},
2039             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2040         }
2041     },
2042     {   "http://.com", 0, S_OK, FALSE,
2043         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
2044         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
2045         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
2046         FALSE,
2047         {
2048             {"http://.com/",S_OK,FALSE},
2049             {".com",S_OK,FALSE},
2050             {"http://.com/",S_OK,FALSE},
2051             {".com",S_OK,FALSE},
2052             {"",S_FALSE,FALSE},
2053             {"",S_FALSE,FALSE},
2054             {".com",S_OK,FALSE},
2055             {"",S_FALSE,FALSE},
2056             {"/",S_OK,FALSE},
2057             {"/",S_OK,FALSE},
2058             {"",S_FALSE,FALSE},
2059             {"http://.com",S_OK,FALSE},
2060             {"http",S_OK,FALSE},
2061             {"",S_FALSE,FALSE},
2062             {"",S_FALSE,FALSE}
2063         },
2064         {
2065             {Uri_HOST_DNS,S_OK,FALSE},
2066             {80,S_OK,FALSE},
2067             {URL_SCHEME_HTTP,S_OK,FALSE},
2068             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2069         }
2070     },
2071     {   "http://.uk", 0, S_OK, FALSE,
2072         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
2073         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
2074         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
2075         FALSE,
2076         {
2077             {"http://.uk/",S_OK,FALSE},
2078             {".uk",S_OK,FALSE},
2079             {"http://.uk/",S_OK,FALSE},
2080             {"",S_FALSE,FALSE},
2081             {"",S_FALSE,FALSE},
2082             {"",S_FALSE,FALSE},
2083             {".uk",S_OK,FALSE},
2084             {"",S_FALSE,FALSE},
2085             {"/",S_OK,FALSE},
2086             {"/",S_OK,FALSE},
2087             {"",S_FALSE,FALSE},
2088             {"http://.uk",S_OK,FALSE},
2089             {"http",S_OK,FALSE},
2090             {"",S_FALSE,FALSE},
2091             {"",S_FALSE,FALSE}
2092         },
2093         {
2094             {Uri_HOST_DNS,S_OK,FALSE},
2095             {80,S_OK,FALSE},
2096             {URL_SCHEME_HTTP,S_OK,FALSE},
2097             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2098         }
2099     },
2100     {   "http://www.co.google.com.[]", 0, S_OK, FALSE,
2101         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
2102         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
2103         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
2104         FALSE,
2105         {
2106             {"http://www.co.google.com.[]/",S_OK,FALSE},
2107             {"www.co.google.com.[]",S_OK,FALSE},
2108             {"http://www.co.google.com.[]/",S_OK,FALSE},
2109             {"google.com.[]",S_OK,FALSE},
2110             {"",S_FALSE,FALSE},
2111             {"",S_FALSE,FALSE},
2112             {"www.co.google.com.[]",S_OK,FALSE},
2113             {"",S_FALSE,FALSE},
2114             {"/",S_OK,FALSE},
2115             {"/",S_OK,FALSE},
2116             {"",S_FALSE,FALSE},
2117             {"http://www.co.google.com.[]",S_OK,FALSE},
2118             {"http",S_OK,FALSE},
2119             {"",S_FALSE,FALSE},
2120             {"",S_FALSE,FALSE}
2121         },
2122         {
2123             {Uri_HOST_DNS,S_OK,FALSE},
2124             {80,S_OK,FALSE},
2125             {URL_SCHEME_HTTP,S_OK,FALSE},
2126             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2127         }
2128     },
2129     {   "http://co.uk", 0, S_OK, FALSE,
2130         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
2131         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
2132         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
2133         FALSE,
2134         {
2135             {"http://co.uk/",S_OK,FALSE},
2136             {"co.uk",S_OK,FALSE},
2137             {"http://co.uk/",S_OK,FALSE},
2138             {"",S_FALSE,FALSE},
2139             {"",S_FALSE,FALSE},
2140             {"",S_FALSE,FALSE},
2141             {"co.uk",S_OK,FALSE},
2142             {"",S_FALSE,FALSE},
2143             {"/",S_OK,FALSE},
2144             {"/",S_OK,FALSE},
2145             {"",S_FALSE,FALSE},
2146             {"http://co.uk",S_OK,FALSE},
2147             {"http",S_OK,FALSE},
2148             {"",S_FALSE,FALSE},
2149             {"",S_FALSE,FALSE}
2150         },
2151         {
2152             {Uri_HOST_DNS,S_OK,FALSE},
2153             {80,S_OK,FALSE},
2154             {URL_SCHEME_HTTP,S_OK,FALSE},
2155             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2156         }
2157     },
2158     {   "http://www.co.google.us.test", 0, S_OK, FALSE,
2159         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
2160         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
2161         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
2162         FALSE,
2163         {
2164             {"http://www.co.google.us.test/",S_OK,FALSE},
2165             {"www.co.google.us.test",S_OK,FALSE},
2166             {"http://www.co.google.us.test/",S_OK,FALSE},
2167             {"us.test",S_OK,FALSE},
2168             {"",S_FALSE,FALSE},
2169             {"",S_FALSE,FALSE},
2170             {"www.co.google.us.test",S_OK,FALSE},
2171             {"",S_FALSE,FALSE},
2172             {"/",S_OK,FALSE},
2173             {"/",S_OK,FALSE},
2174             {"",S_FALSE,FALSE},
2175             {"http://www.co.google.us.test",S_OK,FALSE},
2176             {"http",S_OK,FALSE},
2177             {"",S_FALSE,FALSE},
2178             {"",S_FALSE,FALSE}
2179         },
2180         {
2181             {Uri_HOST_DNS,S_OK,FALSE},
2182             {80,S_OK,FALSE},
2183             {URL_SCHEME_HTTP,S_OK,FALSE},
2184             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2185         }
2186     },
2187     {   "http://gov.uk", 0, S_OK, FALSE,
2188         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
2189         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
2190         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
2191         FALSE,
2192         {
2193             {"http://gov.uk/",S_OK,FALSE},
2194             {"gov.uk",S_OK,FALSE},
2195             {"http://gov.uk/",S_OK,FALSE},
2196             {"",S_FALSE,FALSE},
2197             {"",S_FALSE,FALSE},
2198             {"",S_FALSE,FALSE},
2199             {"gov.uk",S_OK,FALSE},
2200             {"",S_FALSE,FALSE},
2201             {"/",S_OK,FALSE},
2202             {"/",S_OK,FALSE},
2203             {"",S_FALSE,FALSE},
2204             {"http://gov.uk",S_OK,FALSE},
2205             {"http",S_OK,FALSE},
2206             {"",S_FALSE,FALSE},
2207             {"",S_FALSE,FALSE}
2208         },
2209         {
2210             {Uri_HOST_DNS,S_OK,FALSE},
2211             {80,S_OK,FALSE},
2212             {URL_SCHEME_HTTP,S_OK,FALSE},
2213             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2214         }
2215     },
2216     {   "zip://www.google.com\\test", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
2217         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
2218         Uri_HAS_HOST|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
2219         FALSE,
2220         {
2221             {"zip://www.google.com\\test",S_OK,FALSE},
2222             {"www.google.com\\test",S_OK,FALSE},
2223             {"zip://www.google.com\\test",S_OK,FALSE},
2224             {"google.com\\test",S_OK,FALSE},
2225             {"",S_FALSE,FALSE},
2226             {"",S_FALSE,FALSE},
2227             {"www.google.com\\test",S_OK,FALSE},
2228             {"",S_FALSE,FALSE},
2229             {"",S_FALSE,FALSE},
2230             {"",S_FALSE,FALSE},
2231             {"",S_FALSE,FALSE},
2232             {"zip://www.google.com\\test",S_OK,FALSE},
2233             {"zip",S_OK,FALSE},
2234             {"",S_FALSE,FALSE},
2235             {"",S_FALSE,FALSE}
2236         },
2237         {
2238             {Uri_HOST_DNS,S_OK,FALSE},
2239             {0,S_FALSE,FALSE},
2240             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2241             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2242         }
2243     },
2244     {   "urn:excepts:bad:%XY:encoded", 0, S_OK, FALSE,
2245         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|
2246         Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
2247         FALSE,
2248         {
2249             {"urn:excepts:bad:%XY:encoded",S_OK,FALSE},
2250             {"",S_FALSE,FALSE},
2251             {"urn:excepts:bad:%XY:encoded",S_OK,FALSE},
2252             {"",S_FALSE,FALSE},
2253             {"",S_FALSE,FALSE},
2254             {"",S_FALSE,FALSE},
2255             {"",S_FALSE,FALSE},
2256             {"",S_FALSE,FALSE},
2257             {"excepts:bad:%XY:encoded",S_OK,FALSE},
2258             {"excepts:bad:%XY:encoded",S_OK,FALSE},
2259             {"",S_FALSE,FALSE},
2260             {"urn:excepts:bad:%XY:encoded",S_OK,FALSE},
2261             {"urn",S_OK,FALSE},
2262             {"",S_FALSE,FALSE},
2263             {"",S_FALSE,FALSE}
2264         },
2265         {
2266             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2267             {0,S_FALSE,FALSE},
2268             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2269             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2270         }
2271     },
2272     /* Since the original URI doesn't contain an extra '/' before the path no % encoded values
2273      * are decoded and all '%' are encoded.
2274      */
2275     {   "file://C:/te%3Es%2Et/tes%t.mp3", 0, S_OK, FALSE,
2276         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH|
2277         Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
2278         FALSE,
2279         {
2280             {"file:///C:/te%253Es%252Et/tes%25t.mp3",S_OK,FALSE},
2281             {"",S_FALSE,FALSE},
2282             {"file:///C:/te%253Es%252Et/tes%25t.mp3",S_OK,FALSE},
2283             {"",S_FALSE,FALSE},
2284             {".mp3",S_OK,FALSE},
2285             {"",S_FALSE,FALSE},
2286             {"",S_FALSE,FALSE},
2287             {"",S_FALSE,FALSE},
2288             {"/C:/te%253Es%252Et/tes%25t.mp3",S_OK,FALSE},
2289             {"/C:/te%253Es%252Et/tes%25t.mp3",S_OK,FALSE},
2290             {"",S_FALSE,FALSE},
2291             {"file://C:/te%3Es%2Et/tes%t.mp3",S_OK,FALSE},
2292             {"file",S_OK,FALSE},
2293             {"",S_FALSE,FALSE},
2294             {"",S_FALSE,FALSE}
2295         },
2296         {
2297             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2298             {0,S_FALSE,FALSE},
2299             {URL_SCHEME_FILE,S_OK,FALSE},
2300             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2301         }
2302     },
2303     /* Since there's a '/' in front of the drive letter, any percent encoded, non-forbidden character
2304      * is decoded and only %'s in front of invalid hex digits are encoded.
2305      */
2306     {   "file:///C:/te%3Es%2Et/t%23es%t.mp3", 0, S_OK, FALSE,
2307         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH|
2308         Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
2309         FALSE,
2310         {
2311             {"file:///C:/te%3Es.t/t#es%25t.mp3",S_OK,FALSE},
2312             {"",S_FALSE,FALSE},
2313             {"file:///C:/te%3Es.t/t#es%25t.mp3",S_OK,FALSE},
2314             {"",S_FALSE,FALSE},
2315             {".mp3",S_OK,FALSE},
2316             {"",S_FALSE,FALSE},
2317             {"",S_FALSE,FALSE},
2318             {"",S_FALSE,FALSE},
2319             {"/C:/te%3Es.t/t#es%25t.mp3",S_OK,FALSE},
2320             {"/C:/te%3Es.t/t#es%25t.mp3",S_OK,FALSE},
2321             {"",S_FALSE,FALSE},
2322             {"file:///C:/te%3Es%2Et/t%23es%t.mp3",S_OK,FALSE},
2323             {"file",S_OK,FALSE},
2324             {"",S_FALSE,FALSE},
2325             {"",S_FALSE,FALSE}
2326         },
2327         {
2328             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2329             {0,S_FALSE,FALSE},
2330             {URL_SCHEME_FILE,S_OK,FALSE},
2331             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2332         }
2333     },
2334     /* Only unreserved percent encoded characters are decoded for known schemes that aren't file. */
2335     {   "http://[::001.002.003.000]/%3F%23%2E%54/test", 0, S_OK, FALSE,
2336         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
2337         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
2338         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
2339         FALSE,
2340         {
2341             {"http://[::1.2.3.0]/%3F%23.T/test",S_OK,FALSE},
2342             {"[::1.2.3.0]",S_OK,FALSE},
2343             {"http://[::1.2.3.0]/%3F%23.T/test",S_OK,FALSE},
2344             {"",S_FALSE,FALSE},
2345             {"",S_FALSE,FALSE},
2346             {"",S_FALSE,FALSE},
2347             {"::1.2.3.0",S_OK,FALSE},
2348             {"",S_FALSE,FALSE},
2349             {"/%3F%23.T/test",S_OK,FALSE},
2350             {"/%3F%23.T/test",S_OK,FALSE},
2351             {"",S_FALSE,FALSE},
2352             {"http://[::001.002.003.000]/%3F%23%2E%54/test",S_OK,FALSE},
2353             {"http",S_OK,FALSE},
2354             {"",S_FALSE,FALSE},
2355             {"",S_FALSE,FALSE},
2356         },
2357         {
2358             {Uri_HOST_IPV6,S_OK,FALSE},
2359             {80,S_OK,FALSE},
2360             {URL_SCHEME_HTTP,S_OK,FALSE},
2361             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2362         }
2363     },
2364     /* Forbidden characters are always encoded for file URIs. */
2365     {   "file:///C:/\"test\"/test.mp3", Uri_CREATE_NO_ENCODE_FORBIDDEN_CHARACTERS, S_OK, FALSE,
2366         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH|
2367         Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
2368         FALSE,
2369         {
2370             {"file:///C:/%22test%22/test.mp3",S_OK,FALSE},
2371             {"",S_FALSE,FALSE},
2372             {"file:///C:/%22test%22/test.mp3",S_OK,FALSE},
2373             {"",S_FALSE,FALSE},
2374             {".mp3",S_OK,FALSE},
2375             {"",S_FALSE,FALSE},
2376             {"",S_FALSE,FALSE},
2377             {"",S_FALSE,FALSE},
2378             {"/C:/%22test%22/test.mp3",S_OK,FALSE},
2379             {"/C:/%22test%22/test.mp3",S_OK,FALSE},
2380             {"",S_FALSE,FALSE},
2381             {"file:///C:/\"test\"/test.mp3",S_OK,FALSE},
2382             {"file",S_OK,FALSE},
2383             {"",S_FALSE,FALSE},
2384             {"",S_FALSE,FALSE}
2385         },
2386         {
2387             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2388             {0,S_FALSE,FALSE},
2389             {URL_SCHEME_FILE,S_OK,FALSE},
2390             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2391         }
2392     },
2393     /* Forbidden characters are never encoded for unknown scheme types. */
2394     {   "1234://4294967295/<|>\" test<|>", 0, S_OK, FALSE,
2395         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
2396         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
2397         Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
2398         FALSE,
2399         {
2400             {"1234://4294967295/<|>\" test<|>",S_OK,FALSE},
2401             {"4294967295",S_OK,FALSE},
2402             {"1234://4294967295/<|>\" test<|>",S_OK,FALSE},
2403             {"",S_FALSE,FALSE},
2404             {"",S_FALSE,FALSE},
2405             {"",S_FALSE,FALSE},
2406             {"4294967295",S_OK,FALSE},
2407             {"",S_FALSE,FALSE},
2408             {"/<|>\" test<|>",S_OK,FALSE},
2409             {"/<|>\" test<|>",S_OK,FALSE},
2410             {"",S_FALSE,FALSE},
2411             {"1234://4294967295/<|>\" test<|>",S_OK,FALSE},
2412             {"1234",S_OK,FALSE},
2413             {"",S_FALSE,FALSE},
2414             {"",S_FALSE,FALSE}
2415         },
2416         {
2417             {Uri_HOST_IPV4,S_OK,FALSE},
2418             {0,S_FALSE,FALSE},
2419             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2420             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2421         }
2422     },
2423     /* Make sure forbidden characters are percent encoded. */
2424     {   "http://gov.uk/<|> test<|>", 0, S_OK, FALSE,
2425         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
2426         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
2427         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
2428         FALSE,
2429         {
2430             {"http://gov.uk/%3C%7C%3E%20test%3C%7C%3E",S_OK,FALSE},
2431             {"gov.uk",S_OK,FALSE},
2432             {"http://gov.uk/%3C%7C%3E%20test%3C%7C%3E",S_OK,FALSE},
2433             {"",S_FALSE,FALSE},
2434             {"",S_FALSE,FALSE},
2435             {"",S_FALSE,FALSE},
2436             {"gov.uk",S_OK,FALSE},
2437             {"",S_FALSE,FALSE},
2438             {"/%3C%7C%3E%20test%3C%7C%3E",S_OK,FALSE},
2439             {"/%3C%7C%3E%20test%3C%7C%3E",S_OK,FALSE},
2440             {"",S_FALSE,FALSE},
2441             {"http://gov.uk/<|> test<|>",S_OK,FALSE},
2442             {"http",S_OK,FALSE},
2443             {"",S_FALSE,FALSE},
2444             {"",S_FALSE,FALSE}
2445         },
2446         {
2447             {Uri_HOST_DNS,S_OK,FALSE},
2448             {80,S_OK,FALSE},
2449             {URL_SCHEME_HTTP,S_OK,FALSE},
2450             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2451         }
2452     },
2453     {   "http://gov.uk/test/../test2/././../test3/.././././", 0, S_OK, FALSE,
2454         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
2455         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
2456         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
2457         FALSE,
2458         {
2459             {"http://gov.uk/",S_OK,FALSE},
2460             {"gov.uk",S_OK,FALSE},
2461             {"http://gov.uk/",S_OK,FALSE},
2462             {"",S_FALSE,FALSE},
2463             {"",S_FALSE,FALSE},
2464             {"",S_FALSE,FALSE},
2465             {"gov.uk",S_OK,FALSE},
2466             {"",S_FALSE,FALSE},
2467             {"/",S_OK,FALSE},
2468             {"/",S_OK,FALSE},
2469             {"",S_FALSE,FALSE},
2470             {"http://gov.uk/test/../test2/././../test3/.././././",S_OK,FALSE},
2471             {"http",S_OK,FALSE},
2472             {"",S_FALSE,FALSE},
2473             {"",S_FALSE,FALSE}
2474         },
2475         {
2476             {Uri_HOST_DNS,S_OK,FALSE},
2477             {80,S_OK,FALSE},
2478             {URL_SCHEME_HTTP,S_OK,FALSE},
2479             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2480         }
2481     },
2482     {   "http://gov.uk/test/test2/../../..", 0, S_OK, FALSE,
2483         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
2484         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
2485         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
2486         FALSE,
2487         {
2488             {"http://gov.uk/",S_OK,FALSE},
2489             {"gov.uk",S_OK,FALSE},
2490             {"http://gov.uk/",S_OK,FALSE},
2491             {"",S_FALSE,FALSE},
2492             {"",S_FALSE,FALSE},
2493             {"",S_FALSE,FALSE},
2494             {"gov.uk",S_OK,FALSE},
2495             {"",S_FALSE,FALSE},
2496             {"/",S_OK,FALSE},
2497             {"/",S_OK,FALSE},
2498             {"",S_FALSE,FALSE},
2499             {"http://gov.uk/test/test2/../../..",S_OK,FALSE},
2500             {"http",S_OK,FALSE},
2501             {"",S_FALSE,FALSE},
2502             {"",S_FALSE,FALSE}
2503         },
2504         {
2505             {Uri_HOST_DNS,S_OK,FALSE},
2506             {80,S_OK,FALSE},
2507             {URL_SCHEME_HTTP,S_OK,FALSE},
2508             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2509         }
2510     },
2511     {   "http://gov.uk/test/test2/../../.", 0, S_OK, FALSE,
2512         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
2513         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
2514         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
2515         FALSE,
2516         {
2517             {"http://gov.uk/",S_OK,FALSE},
2518             {"gov.uk",S_OK,FALSE},
2519             {"http://gov.uk/",S_OK,FALSE},
2520             {"",S_FALSE,FALSE},
2521             {"",S_FALSE,FALSE},
2522             {"",S_FALSE,FALSE},
2523             {"gov.uk",S_OK,FALSE},
2524             {"",S_FALSE,FALSE},
2525             {"/",S_OK,FALSE},
2526             {"/",S_OK,FALSE},
2527             {"",S_FALSE,FALSE},
2528             {"http://gov.uk/test/test2/../../.",S_OK,FALSE},
2529             {"http",S_OK,FALSE},
2530             {"",S_FALSE,FALSE},
2531             {"",S_FALSE,FALSE}
2532         },
2533         {
2534             {Uri_HOST_DNS,S_OK,FALSE},
2535             {80,S_OK,FALSE},
2536             {URL_SCHEME_HTTP,S_OK,FALSE},
2537             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2538         }
2539     },
2540     {   "file://c:\\tests\\../tests\\./.\\..\\foo%20bar.mp3", 0, S_OK, FALSE,
2541         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH|
2542         Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
2543         FALSE,
2544         {
2545             {"file:///c:/foo%2520bar.mp3",S_OK,FALSE},
2546             {"",S_FALSE,FALSE},
2547             {"file:///c:/foo%2520bar.mp3",S_OK,FALSE},
2548             {"",S_FALSE,FALSE},
2549             {".mp3",S_OK,FALSE},
2550             {"",S_FALSE,FALSE},
2551             {"",S_FALSE,FALSE},
2552             {"",S_FALSE,FALSE},
2553             {"/c:/foo%2520bar.mp3",S_OK,FALSE},
2554             {"/c:/foo%2520bar.mp3",S_OK,FALSE},
2555             {"",S_FALSE,FALSE},
2556             {"file://c:\\tests\\../tests\\./.\\..\\foo%20bar.mp3",S_OK,FALSE},
2557             {"file",S_OK,FALSE},
2558             {"",S_FALSE,FALSE},
2559             {"",S_FALSE,FALSE}
2560         },
2561         {
2562             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2563             {0,S_FALSE,FALSE},
2564             {URL_SCHEME_FILE,S_OK,FALSE},
2565             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2566         }
2567     },
2568     /* Dot removal happens for unknown scheme types. */
2569     {   "zip://gov.uk/test/test2/../../.", 0, S_OK, FALSE,
2570         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
2571         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
2572         Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
2573         FALSE,
2574         {
2575             {"zip://gov.uk/",S_OK,FALSE},
2576             {"gov.uk",S_OK,FALSE},
2577             {"zip://gov.uk/",S_OK,FALSE},
2578             {"",S_FALSE,FALSE},
2579             {"",S_FALSE,FALSE},
2580             {"",S_FALSE,FALSE},
2581             {"gov.uk",S_OK,FALSE},
2582             {"",S_FALSE,FALSE},
2583             {"/",S_OK,FALSE},
2584             {"/",S_OK,FALSE},
2585             {"",S_FALSE,FALSE},
2586             {"zip://gov.uk/test/test2/../../.",S_OK,FALSE},
2587             {"zip",S_OK,FALSE},
2588             {"",S_FALSE,FALSE},
2589             {"",S_FALSE,FALSE}
2590         },
2591         {
2592             {Uri_HOST_DNS,S_OK,FALSE},
2593             {0,S_FALSE,FALSE},
2594             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2595             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2596         }
2597     },
2598     /* Dot removal doesn't happen if NO_CANONICALIZE is set. */
2599     {   "http://gov.uk/test/test2/../../.", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
2600         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|
2601         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
2602         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
2603         FALSE,
2604         {
2605             {"http://gov.uk/test/test2/../../.",S_OK,FALSE},
2606             {"gov.uk",S_OK,FALSE},
2607             {"http://gov.uk/test/test2/../../.",S_OK,FALSE},
2608             {"",S_FALSE,FALSE},
2609             {".",S_OK,FALSE},
2610             {"",S_FALSE,FALSE},
2611             {"gov.uk",S_OK,FALSE},
2612             {"",S_FALSE,FALSE},
2613             {"/test/test2/../../.",S_OK,FALSE},
2614             {"/test/test2/../../.",S_OK,FALSE},
2615             {"",S_FALSE,FALSE},
2616             {"http://gov.uk/test/test2/../../.",S_OK,FALSE},
2617             {"http",S_OK,FALSE},
2618             {"",S_FALSE,FALSE},
2619             {"",S_FALSE,FALSE}
2620         },
2621         {
2622             {Uri_HOST_DNS,S_OK,FALSE},
2623             {80,S_OK,FALSE},
2624             {URL_SCHEME_HTTP,S_OK,FALSE},
2625             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2626         }
2627     },
2628     /* Dot removal doesn't happen for wildcard scheme types. */
2629     {   "*:gov.uk/test/test2/../../.", 0, S_OK, FALSE,
2630         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|
2631         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
2632         Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
2633         FALSE,
2634         {
2635             {"*:gov.uk/test/test2/../../.",S_OK,FALSE},
2636             {"gov.uk",S_OK,FALSE},
2637             {"*:gov.uk/test/test2/../../.",S_OK,FALSE},
2638             {"",S_FALSE,FALSE},
2639             {".",S_OK,FALSE},
2640             {"",S_FALSE,FALSE},
2641             {"gov.uk",S_OK,FALSE},
2642             {"",S_FALSE,FALSE},
2643             {"/test/test2/../../.",S_OK,FALSE},
2644             {"/test/test2/../../.",S_OK,FALSE},
2645             {"",S_FALSE,FALSE},
2646             {"*:gov.uk/test/test2/../../.",S_OK,FALSE},
2647             {"*",S_OK,FALSE},
2648             {"",S_FALSE,FALSE},
2649             {"",S_FALSE,FALSE}
2650         },
2651         {
2652             {Uri_HOST_DNS,S_OK,FALSE},
2653             {0,S_FALSE,FALSE},
2654             {URL_SCHEME_WILDCARD,S_OK,FALSE},
2655             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2656         }
2657     },
2658     /* Forbidden characters are encoded for opaque known scheme types. */
2659     {   "mailto:\"acco<|>unt@example.com\"", 0, S_OK, FALSE,
2660         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|
2661         Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
2662         FALSE,
2663         {
2664             {"mailto:%22acco%3C%7C%3Eunt@example.com%22",S_OK,FALSE},
2665             {"",S_FALSE,FALSE},
2666             {"mailto:%22acco%3C%7C%3Eunt@example.com%22",S_OK,FALSE},
2667             {"",S_FALSE,FALSE},
2668             {".com%22",S_OK,FALSE},
2669             {"",S_FALSE,FALSE},
2670             {"",S_FALSE,FALSE},
2671             {"",S_FALSE,FALSE},
2672             {"%22acco%3C%7C%3Eunt@example.com%22",S_OK,FALSE},
2673             {"%22acco%3C%7C%3Eunt@example.com%22",S_OK,FALSE},
2674             {"",S_FALSE,FALSE},
2675             {"mailto:\"acco<|>unt@example.com\"",S_OK,FALSE},
2676             {"mailto",S_OK,FALSE},
2677             {"",S_FALSE,FALSE},
2678             {"",S_FALSE,FALSE}
2679         },
2680         {
2681             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2682             {0,S_FALSE,FALSE},
2683             {URL_SCHEME_MAILTO,S_OK,FALSE},
2684             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2685         }
2686     },
2687     {   "news:test.tes<|>t.com", 0, S_OK, FALSE,
2688         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|
2689         Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
2690         FALSE,
2691         {
2692             {"news:test.tes%3C%7C%3Et.com",S_OK,FALSE},
2693             {"",S_FALSE,FALSE},
2694             {"news:test.tes%3C%7C%3Et.com",S_OK,FALSE},
2695             {"",S_FALSE,FALSE},
2696             {".com",S_OK,FALSE},
2697             {"",S_FALSE,FALSE},
2698             {"",S_FALSE,FALSE},
2699             {"",S_FALSE,FALSE},
2700             {"test.tes%3C%7C%3Et.com",S_OK,FALSE},
2701             {"test.tes%3C%7C%3Et.com",S_OK,FALSE},
2702             {"",S_FALSE,FALSE},
2703             {"news:test.tes<|>t.com",S_OK,FALSE},
2704             {"news",S_OK,FALSE},
2705             {"",S_FALSE,FALSE},
2706             {"",S_FALSE,FALSE}
2707         },
2708         {
2709             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2710             {0,S_FALSE,FALSE},
2711             {URL_SCHEME_NEWS,S_OK,FALSE},
2712             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2713         }
2714     },
2715     /* Don't encode forbidden characters. */
2716     {   "news:test.tes<|>t.com", Uri_CREATE_NO_ENCODE_FORBIDDEN_CHARACTERS, S_OK, FALSE,
2717         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|
2718         Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
2719         FALSE,
2720         {
2721             {"news:test.tes<|>t.com",S_OK,FALSE},
2722             {"",S_FALSE,FALSE},
2723             {"news:test.tes<|>t.com",S_OK,FALSE},
2724             {"",S_FALSE,FALSE},
2725             {".com",S_OK,FALSE},
2726             {"",S_FALSE,FALSE},
2727             {"",S_FALSE,FALSE},
2728             {"",S_FALSE,FALSE},
2729             {"test.tes<|>t.com",S_OK,FALSE},
2730             {"test.tes<|>t.com",S_OK,FALSE},
2731             {"",S_FALSE,FALSE},
2732             {"news:test.tes<|>t.com",S_OK,FALSE},
2733             {"news",S_OK,FALSE},
2734             {"",S_FALSE,FALSE},
2735             {"",S_FALSE,FALSE}
2736         },
2737         {
2738             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2739             {0,S_FALSE,FALSE},
2740             {URL_SCHEME_NEWS,S_OK,FALSE},
2741             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2742         }
2743     },
2744     /* Forbidden characters aren't encoded for unknown, opaque URIs. */
2745     {   "urn:test.tes<|>t.com", 0, S_OK, FALSE,
2746         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|
2747         Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
2748         FALSE,
2749         {
2750             {"urn:test.tes<|>t.com",S_OK,FALSE},
2751             {"",S_FALSE,FALSE},
2752             {"urn:test.tes<|>t.com",S_OK,FALSE},
2753             {"",S_FALSE,FALSE},
2754             {".com",S_OK,FALSE},
2755             {"",S_FALSE,FALSE},
2756             {"",S_FALSE,FALSE},
2757             {"",S_FALSE,FALSE},
2758             {"test.tes<|>t.com",S_OK,FALSE},
2759             {"test.tes<|>t.com",S_OK,FALSE},
2760             {"",S_FALSE,FALSE},
2761             {"urn:test.tes<|>t.com",S_OK,FALSE},
2762             {"urn",S_OK,FALSE},
2763             {"",S_FALSE,FALSE},
2764             {"",S_FALSE,FALSE}
2765         },
2766         {
2767             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2768             {0,S_FALSE,FALSE},
2769             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2770             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2771         }
2772     },
2773     /* Percent encoded unreserved characters are decoded for known opaque URIs. */
2774     {   "news:test.%74%65%73%74.com", 0, S_OK, FALSE,
2775         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|
2776         Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
2777         FALSE,
2778         {
2779             {"news:test.test.com",S_OK,FALSE},
2780             {"",S_FALSE,FALSE},
2781             {"news:test.test.com",S_OK,FALSE},
2782             {"",S_FALSE,FALSE},
2783             {".com",S_OK,FALSE},
2784             {"",S_FALSE,FALSE},
2785             {"",S_FALSE,FALSE},
2786             {"",S_FALSE,FALSE},
2787             {"test.test.com",S_OK,FALSE},
2788             {"test.test.com",S_OK,FALSE},
2789             {"",S_FALSE,FALSE},
2790             {"news:test.%74%65%73%74.com",S_OK,FALSE},
2791             {"news",S_OK,FALSE},
2792             {"",S_FALSE,FALSE},
2793             {"",S_FALSE,FALSE}
2794         },
2795         {
2796             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2797             {0,S_FALSE,FALSE},
2798             {URL_SCHEME_NEWS,S_OK,FALSE},
2799             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2800         }
2801     },
2802     /* Percent encoded characters are still decoded for known scheme types. */
2803     {   "news:test.%74%65%73%74.com", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
2804         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|
2805         Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
2806         FALSE,
2807         {
2808             {"news:test.test.com",S_OK,FALSE},
2809             {"",S_FALSE,FALSE},
2810             {"news:test.test.com",S_OK,FALSE},
2811             {"",S_FALSE,FALSE},
2812             {".com",S_OK,FALSE},
2813             {"",S_FALSE,FALSE},
2814             {"",S_FALSE,FALSE},
2815             {"",S_FALSE,FALSE},
2816             {"test.test.com",S_OK,FALSE},
2817             {"test.test.com",S_OK,FALSE},
2818             {"",S_FALSE,FALSE},
2819             {"news:test.%74%65%73%74.com",S_OK,FALSE},
2820             {"news",S_OK,FALSE},
2821             {"",S_FALSE,FALSE},
2822             {"",S_FALSE,FALSE}
2823         },
2824         {
2825             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2826             {0,S_FALSE,FALSE},
2827             {URL_SCHEME_NEWS,S_OK,FALSE},
2828             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2829         }
2830     },
2831     /* Percent encoded characters aren't decoded for unknown scheme types. */
2832     {   "urn:test.%74%65%73%74.com", 0, S_OK, FALSE,
2833         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|
2834         Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
2835         FALSE,
2836         {
2837             {"urn:test.%74%65%73%74.com",S_OK,FALSE},
2838             {"",S_FALSE,FALSE},
2839             {"urn:test.%74%65%73%74.com",S_OK,FALSE},
2840             {"",S_FALSE,FALSE},
2841             {".com",S_OK,FALSE},
2842             {"",S_FALSE,FALSE},
2843             {"",S_FALSE,FALSE},
2844             {"",S_FALSE,FALSE},
2845             {"test.%74%65%73%74.com",S_OK,FALSE},
2846             {"test.%74%65%73%74.com",S_OK,FALSE},
2847             {"",S_FALSE,FALSE},
2848             {"urn:test.%74%65%73%74.com",S_OK,FALSE},
2849             {"urn",S_OK,FALSE},
2850             {"",S_FALSE,FALSE},
2851             {"",S_FALSE,FALSE}
2852         },
2853         {
2854             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2855             {0,S_FALSE,FALSE},
2856             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2857             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2858         }
2859     },
2860     /* Unknown scheme types can have invalid % encoded data in query string. */
2861     {   "zip://www.winehq.org/tests/..?query=%xx&return=y", 0, S_OK, FALSE,
2862         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_HOST|
2863         Uri_HAS_DOMAIN|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_QUERY|Uri_HAS_RAW_URI|
2864         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
2865         FALSE,
2866         {
2867             {"zip://www.winehq.org/?query=%xx&return=y",S_OK,FALSE},
2868             {"www.winehq.org",S_OK,FALSE},
2869             {"zip://www.winehq.org/?query=%xx&return=y",S_OK,FALSE},
2870             {"winehq.org",S_OK,FALSE},
2871             {"",S_FALSE,FALSE},
2872             {"",S_FALSE,FALSE},
2873             {"www.winehq.org",S_OK,FALSE},
2874             {"",S_FALSE,FALSE},
2875             {"/",S_OK,FALSE},
2876             {"/?query=%xx&return=y",S_OK,FALSE},
2877             {"?query=%xx&return=y",S_OK,FALSE},
2878             {"zip://www.winehq.org/tests/..?query=%xx&return=y",S_OK,FALSE},
2879             {"zip",S_OK,FALSE},
2880             {"",S_FALSE,FALSE},
2881             {"",S_FALSE,FALSE}
2882         },
2883         {
2884             {Uri_HOST_DNS,S_OK,FALSE},
2885             {0,S_FALSE,FALSE},
2886             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2887             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2888         }
2889     },
2890     /* Known scheme types can have invalid % encoded data with the right flags. */
2891     {   "http://www.winehq.org/tests/..?query=%xx&return=y", Uri_CREATE_NO_DECODE_EXTRA_INFO, S_OK, FALSE,
2892         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_HOST|
2893         Uri_HAS_DOMAIN|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_PORT|Uri_HAS_QUERY|Uri_HAS_RAW_URI|
2894         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
2895         FALSE,
2896         {
2897             {"http://www.winehq.org/?query=%xx&return=y",S_OK,FALSE},
2898             {"www.winehq.org",S_OK,FALSE},
2899             {"http://www.winehq.org/?query=%xx&return=y",S_OK,FALSE},
2900             {"winehq.org",S_OK,FALSE},
2901             {"",S_FALSE,FALSE},
2902             {"",S_FALSE,FALSE},
2903             {"www.winehq.org",S_OK,FALSE},
2904             {"",S_FALSE,FALSE},
2905             {"/",S_OK,FALSE},
2906             {"/?query=%xx&return=y",S_OK,FALSE},
2907             {"?query=%xx&return=y",S_OK,FALSE},
2908             {"http://www.winehq.org/tests/..?query=%xx&return=y",S_OK,FALSE},
2909             {"http",S_OK,FALSE},
2910             {"",S_FALSE,FALSE},
2911             {"",S_FALSE,FALSE}
2912         },
2913         {
2914             {Uri_HOST_DNS,S_OK,FALSE},
2915             {80,S_OK,FALSE},
2916             {URL_SCHEME_HTTP,S_OK,FALSE},
2917             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2918         }
2919     },
2920     /* Forbidden characters in query aren't percent encoded for known scheme types with this flag. */
2921     {   "http://www.winehq.org/tests/..?query=<|>&return=y", Uri_CREATE_NO_DECODE_EXTRA_INFO, S_OK, FALSE,
2922         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_HOST|
2923         Uri_HAS_DOMAIN|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_PORT|Uri_HAS_QUERY|Uri_HAS_RAW_URI|
2924         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
2925         FALSE,
2926         {
2927             {"http://www.winehq.org/?query=<|>&return=y",S_OK,FALSE},
2928             {"www.winehq.org",S_OK,FALSE},
2929             {"http://www.winehq.org/?query=<|>&return=y",S_OK,FALSE},
2930             {"winehq.org",S_OK,FALSE},
2931             {"",S_FALSE,FALSE},
2932             {"",S_FALSE,FALSE},
2933             {"www.winehq.org",S_OK,FALSE},
2934             {"",S_FALSE,FALSE},
2935             {"/",S_OK,FALSE},
2936             {"/?query=<|>&return=y",S_OK,FALSE},
2937             {"?query=<|>&return=y",S_OK,FALSE},
2938             {"http://www.winehq.org/tests/..?query=<|>&return=y",S_OK,FALSE},
2939             {"http",S_OK,FALSE},
2940             {"",S_FALSE,FALSE},
2941             {"",S_FALSE,FALSE}
2942         },
2943         {
2944             {Uri_HOST_DNS,S_OK,FALSE},
2945             {80,S_OK,FALSE},
2946             {URL_SCHEME_HTTP,S_OK,FALSE},
2947             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2948         }
2949     },
2950     /* Forbidden characters in query aren't percent encoded for known scheme types with this flag. */
2951     {   "http://www.winehq.org/tests/..?query=<|>&return=y", Uri_CREATE_NO_ENCODE_FORBIDDEN_CHARACTERS, S_OK, FALSE,
2952         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_HOST|
2953         Uri_HAS_DOMAIN|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_PORT|Uri_HAS_QUERY|Uri_HAS_RAW_URI|
2954         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
2955         FALSE,
2956         {
2957             {"http://www.winehq.org/?query=<|>&return=y",S_OK,FALSE},
2958             {"www.winehq.org",S_OK,FALSE},
2959             {"http://www.winehq.org/?query=<|>&return=y",S_OK,FALSE},
2960             {"winehq.org",S_OK,FALSE},
2961             {"",S_FALSE,FALSE},
2962             {"",S_FALSE,FALSE},
2963             {"www.winehq.org",S_OK,FALSE},
2964             {"",S_FALSE,FALSE},
2965             {"/",S_OK,FALSE},
2966             {"/?query=<|>&return=y",S_OK,FALSE},
2967             {"?query=<|>&return=y",S_OK,FALSE},
2968             {"http://www.winehq.org/tests/..?query=<|>&return=y",S_OK,FALSE},
2969             {"http",S_OK,FALSE},
2970             {"",S_FALSE,FALSE},
2971             {"",S_FALSE,FALSE}
2972         },
2973         {
2974             {Uri_HOST_DNS,S_OK,FALSE},
2975             {80,S_OK,FALSE},
2976             {URL_SCHEME_HTTP,S_OK,FALSE},
2977             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2978         }
2979     },
2980     /* Forbidden characters are encoded for known scheme types. */
2981     {   "http://www.winehq.org/tests/..?query=<|>&return=y", 0, S_OK, FALSE,
2982         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_HOST|
2983         Uri_HAS_DOMAIN|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_PORT|Uri_HAS_QUERY|Uri_HAS_RAW_URI|
2984         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
2985         FALSE,
2986         {
2987             {"http://www.winehq.org/?query=%3C%7C%3E&return=y",S_OK,FALSE},
2988             {"www.winehq.org",S_OK,FALSE},
2989             {"http://www.winehq.org/?query=%3C%7C%3E&return=y",S_OK,FALSE},
2990             {"winehq.org",S_OK,FALSE},
2991             {"",S_FALSE,FALSE},
2992             {"",S_FALSE,FALSE},
2993             {"www.winehq.org",S_OK,FALSE},
2994             {"",S_FALSE,FALSE},
2995             {"/",S_OK,FALSE},
2996             {"/?query=%3C%7C%3E&return=y",S_OK,FALSE},
2997             {"?query=%3C%7C%3E&return=y",S_OK,FALSE},
2998             {"http://www.winehq.org/tests/..?query=<|>&return=y",S_OK,FALSE},
2999             {"http",S_OK,FALSE},
3000             {"",S_FALSE,FALSE},
3001             {"",S_FALSE,FALSE}
3002         },
3003         {
3004             {Uri_HOST_DNS,S_OK,FALSE},
3005             {80,S_OK,FALSE},
3006             {URL_SCHEME_HTTP,S_OK,FALSE},
3007             {URLZONE_INVALID,E_NOTIMPL,FALSE},
3008         }
3009     },
3010     /* Forbidden characters are not encoded for unknown scheme types. */
3011     {   "zip://www.winehq.org/tests/..?query=<|>&return=y", 0, S_OK, FALSE,
3012         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_HOST|
3013         Uri_HAS_DOMAIN|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_QUERY|Uri_HAS_RAW_URI|
3014         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
3015         FALSE,
3016         {
3017             {"zip://www.winehq.org/?query=<|>&return=y",S_OK,FALSE},
3018             {"www.winehq.org",S_OK,FALSE},
3019             {"zip://www.winehq.org/?query=<|>&return=y",S_OK,FALSE},
3020             {"winehq.org",S_OK,FALSE},
3021             {"",S_FALSE,FALSE},
3022             {"",S_FALSE,FALSE},
3023             {"www.winehq.org",S_OK,FALSE},
3024             {"",S_FALSE,FALSE},
3025             {"/",S_OK,FALSE},
3026             {"/?query=<|>&return=y",S_OK,FALSE},
3027             {"?query=<|>&return=y",S_OK,FALSE},
3028             {"zip://www.winehq.org/tests/..?query=<|>&return=y",S_OK,FALSE},
3029             {"zip",S_OK,FALSE},
3030             {"",S_FALSE,FALSE},
3031             {"",S_FALSE,FALSE}
3032         },
3033         {
3034             {Uri_HOST_DNS,S_OK,FALSE},
3035             {0,S_FALSE,FALSE},
3036             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
3037             {URLZONE_INVALID,E_NOTIMPL,FALSE},
3038         }
3039     },
3040     /* Percent encoded, unreserved characters are decoded for known scheme types. */
3041     {   "http://www.winehq.org/tests/..?query=%30%31&return=y", 0, S_OK, FALSE,
3042         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_HOST|
3043         Uri_HAS_DOMAIN|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_PORT|Uri_HAS_QUERY|Uri_HAS_RAW_URI|
3044         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
3045         FALSE,
3046         {
3047             {"http://www.winehq.org/?query=01&return=y",S_OK,FALSE},
3048             {"www.winehq.org",S_OK,FALSE},
3049             {"http://www.winehq.org/?query=01&return=y",S_OK,FALSE},
3050             {"winehq.org",S_OK,FALSE},
3051             {"",S_FALSE,FALSE},
3052             {"",S_FALSE,FALSE},
3053             {"www.winehq.org",S_OK,FALSE},
3054             {"",S_FALSE,FALSE},
3055             {"/",S_OK,FALSE},
3056             {"/?query=01&return=y",S_OK,FALSE},
3057             {"?query=01&return=y",S_OK,FALSE},
3058             {"http://www.winehq.org/tests/..?query=%30%31&return=y",S_OK,FALSE},
3059             {"http",S_OK,FALSE},
3060             {"",S_FALSE,FALSE},
3061             {"",S_FALSE,FALSE}
3062         },
3063         {
3064             {Uri_HOST_DNS,S_OK,FALSE},
3065             {80,S_OK,FALSE},
3066             {URL_SCHEME_HTTP,S_OK,FALSE},
3067             {URLZONE_INVALID,E_NOTIMPL,FALSE},
3068         }
3069     },
3070     /* Percent encoded, unreserved characters aren't decoded for unknown scheme types. */
3071     {   "zip://www.winehq.org/tests/..?query=%30%31&return=y", 0, S_OK, FALSE,
3072         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_HOST|
3073         Uri_HAS_DOMAIN|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_QUERY|Uri_HAS_RAW_URI|
3074         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
3075         FALSE,
3076         {
3077             {"zip://www.winehq.org/?query=%30%31&return=y",S_OK,FALSE},
3078             {"www.winehq.org",S_OK,FALSE},
3079             {"zip://www.winehq.org/?query=%30%31&return=y",S_OK,FALSE},
3080             {"winehq.org",S_OK,FALSE},
3081             {"",S_FALSE,FALSE},
3082             {"",S_FALSE,FALSE},
3083             {"www.winehq.org",S_OK,FALSE},
3084             {"",S_FALSE,FALSE},
3085             {"/",S_OK,FALSE},
3086             {"/?query=%30%31&return=y",S_OK,FALSE},
3087             {"?query=%30%31&return=y",S_OK,FALSE},
3088             {"zip://www.winehq.org/tests/..?query=%30%31&return=y",S_OK,FALSE},
3089             {"zip",S_OK,FALSE},
3090             {"",S_FALSE,FALSE},
3091             {"",S_FALSE,FALSE}
3092         },
3093         {
3094             {Uri_HOST_DNS,S_OK,FALSE},
3095             {0,S_FALSE,FALSE},
3096             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
3097             {URLZONE_INVALID,E_NOTIMPL,FALSE},
3098         }
3099     },
3100     /* Percent encoded characters aren't decoded when NO_DECODE_EXTRA_INFO is set. */
3101     {   "http://www.winehq.org/tests/..?query=%30%31&return=y", Uri_CREATE_NO_DECODE_EXTRA_INFO, S_OK, FALSE,
3102         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_HOST|
3103         Uri_HAS_DOMAIN|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_PORT|Uri_HAS_QUERY|Uri_HAS_RAW_URI|
3104         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
3105         FALSE,
3106         {
3107             {"http://www.winehq.org/?query=%30%31&return=y",S_OK,FALSE},
3108             {"www.winehq.org",S_OK,FALSE},
3109             {"http://www.winehq.org/?query=%30%31&return=y",S_OK,FALSE},
3110             {"winehq.org",S_OK,FALSE},
3111             {"",S_FALSE,FALSE},
3112             {"",S_FALSE,FALSE},
3113             {"www.winehq.org",S_OK,FALSE},
3114             {"",S_FALSE,FALSE},
3115             {"/",S_OK,FALSE},
3116             {"/?query=%30%31&return=y",S_OK,FALSE},
3117             {"?query=%30%31&return=y",S_OK,FALSE},
3118             {"http://www.winehq.org/tests/..?query=%30%31&return=y",S_OK,FALSE},
3119             {"http",S_OK,FALSE},
3120             {"",S_FALSE,FALSE},
3121             {"",S_FALSE,FALSE}
3122         },
3123         {
3124             {Uri_HOST_DNS,S_OK,FALSE},
3125             {80,S_OK,FALSE},
3126             {URL_SCHEME_HTTP,S_OK,FALSE},
3127             {URLZONE_INVALID,E_NOTIMPL,FALSE},
3128         }
3129     },
3130     {   "http://www.winehq.org?query=12&return=y", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
3131         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_HOST|
3132         Uri_HAS_DOMAIN|Uri_HAS_PATH_AND_QUERY|Uri_HAS_PORT|Uri_HAS_QUERY|Uri_HAS_RAW_URI|
3133         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
3134         FALSE,
3135         {
3136             {"http://www.winehq.org?query=12&return=y",S_OK,FALSE},
3137             {"www.winehq.org",S_OK,FALSE},
3138             {"http://www.winehq.org?query=12&return=y",S_OK,FALSE},
3139             {"winehq.org",S_OK,FALSE},
3140             {"",S_FALSE,FALSE},
3141             {"",S_FALSE,FALSE},
3142             {"www.winehq.org",S_OK,FALSE},
3143             {"",S_FALSE,FALSE},
3144             {"",S_FALSE,FALSE},
3145             {"?query=12&return=y",S_OK,FALSE},
3146             {"?query=12&return=y",S_OK,FALSE},
3147             {"http://www.winehq.org?query=12&return=y",S_OK,FALSE},
3148             {"http",S_OK,FALSE},
3149             {"",S_FALSE,FALSE},
3150             {"",S_FALSE,FALSE}
3151         },
3152         {
3153             {Uri_HOST_DNS,S_OK,FALSE},
3154             {80,S_OK,FALSE},
3155             {URL_SCHEME_HTTP,S_OK,FALSE},
3156             {URLZONE_INVALID,E_NOTIMPL,FALSE},
3157         }
3158     },
3159     /* Unknown scheme types can have invalid % encoded data in fragments. */
3160     {   "zip://www.winehq.org/tests/#Te%xx", 0, S_OK, FALSE,
3161         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_FRAGMENT|
3162         Uri_HAS_HOST|Uri_HAS_DOMAIN|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
3163         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
3164         FALSE,
3165         {
3166             {"zip://www.winehq.org/tests/#Te%xx",S_OK,FALSE},
3167             {"www.winehq.org",S_OK,FALSE},
3168             {"zip://www.winehq.org/tests/#Te%xx",S_OK,FALSE},
3169             {"winehq.org",S_OK,FALSE},
3170             {"",S_FALSE,FALSE},
3171             {"#Te%xx",S_OK,FALSE},
3172             {"www.winehq.org",S_OK,FALSE},
3173             {"",S_FALSE,FALSE},
3174             {"/tests/",S_OK,FALSE},
3175             {"/tests/",S_OK,FALSE},
3176             {"",S_FALSE,FALSE},
3177             {"zip://www.winehq.org/tests/#Te%xx",S_OK,FALSE},
3178             {"zip",S_OK,FALSE},
3179             {"",S_FALSE,FALSE},
3180             {"",S_FALSE,FALSE}
3181         },
3182         {
3183             {Uri_HOST_DNS,S_OK,FALSE},
3184             {0,S_FALSE,FALSE},
3185             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
3186             {URLZONE_INVALID,E_NOTIMPL,FALSE},
3187         }
3188     },
3189     /* Forbidden characters in fragment aren't encoded for unknown schemes. */
3190     {   "zip://www.winehq.org/tests/#Te<|>", 0, S_OK, FALSE,
3191         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_FRAGMENT|
3192         Uri_HAS_HOST|Uri_HAS_DOMAIN|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
3193         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
3194         FALSE,
3195         {
3196             {"zip://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
3197             {"www.winehq.org",S_OK,FALSE},
3198             {"zip://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
3199             {"winehq.org",S_OK,FALSE},
3200             {"",S_FALSE,FALSE},
3201             {"#Te<|>",S_OK,FALSE},
3202             {"www.winehq.org",S_OK,FALSE},
3203             {"",S_FALSE,FALSE},
3204             {"/tests/",S_OK,FALSE},
3205             {"/tests/",S_OK,FALSE},
3206             {"",S_FALSE,FALSE},
3207             {"zip://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
3208             {"zip",S_OK,FALSE},
3209             {"",S_FALSE,FALSE},
3210             {"",S_FALSE,FALSE}
3211         },
3212         {
3213             {Uri_HOST_DNS,S_OK,FALSE},
3214             {0,S_FALSE,FALSE},
3215             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
3216             {URLZONE_INVALID,E_NOTIMPL,FALSE},
3217         }
3218     },
3219     /* Forbidden characters in the fragment are percent encoded for known schemes. */
3220     {   "http://www.winehq.org/tests/#Te<|>", 0, S_OK, FALSE,
3221         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_FRAGMENT|
3222         Uri_HAS_HOST|Uri_HAS_DOMAIN|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
3223         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
3224         FALSE,
3225         {
3226             {"http://www.winehq.org/tests/#Te%3C%7C%3E",S_OK,FALSE},
3227             {"www.winehq.org",S_OK,FALSE},
3228             {"http://www.winehq.org/tests/#Te%3C%7C%3E",S_OK,FALSE},
3229             {"winehq.org",S_OK,FALSE},
3230             {"",S_FALSE,FALSE},
3231             {"#Te%3C%7C%3E",S_OK,FALSE},
3232             {"www.winehq.org",S_OK,FALSE},
3233             {"",S_FALSE,FALSE},
3234             {"/tests/",S_OK,FALSE},
3235             {"/tests/",S_OK,FALSE},
3236             {"",S_FALSE,FALSE},
3237             {"http://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
3238             {"http",S_OK,FALSE},
3239             {"",S_FALSE,FALSE},
3240             {"",S_FALSE,FALSE}
3241         },
3242         {
3243             {Uri_HOST_DNS,S_OK,FALSE},
3244             {80,S_OK,FALSE},
3245             {URL_SCHEME_HTTP,S_OK,FALSE},
3246             {URLZONE_INVALID,E_NOTIMPL,FALSE},
3247         }
3248     },
3249     /* Forbidden characters aren't encoded in the fragment with this flag. */
3250     {   "http://www.winehq.org/tests/#Te<|>", Uri_CREATE_NO_DECODE_EXTRA_INFO, S_OK, FALSE,
3251         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_FRAGMENT|
3252         Uri_HAS_HOST|Uri_HAS_DOMAIN|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
3253         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
3254         FALSE,
3255         {
3256             {"http://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
3257             {"www.winehq.org",S_OK,FALSE},
3258             {"http://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
3259             {"winehq.org",S_OK,FALSE},
3260             {"",S_FALSE,FALSE},
3261             {"#Te<|>",S_OK,FALSE},
3262             {"www.winehq.org",S_OK,FALSE},
3263             {"",S_FALSE,FALSE},
3264             {"/tests/",S_OK,FALSE},
3265             {"/tests/",S_OK,FALSE},
3266             {"",S_FALSE,FALSE},
3267             {"http://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
3268             {"http",S_OK,FALSE},
3269             {"",S_FALSE,FALSE},
3270             {"",S_FALSE,FALSE}
3271         },
3272         {
3273             {Uri_HOST_DNS,S_OK,FALSE},
3274             {80,S_OK,FALSE},
3275             {URL_SCHEME_HTTP,S_OK,FALSE},
3276             {URLZONE_INVALID,E_NOTIMPL,FALSE},
3277         }
3278     },
3279     /* Forbidden characters aren't encoded in the fragment with this flag. */
3280     {   "http://www.winehq.org/tests/#Te<|>", Uri_CREATE_NO_ENCODE_FORBIDDEN_CHARACTERS, S_OK, FALSE,
3281         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_FRAGMENT|
3282         Uri_HAS_HOST|Uri_HAS_DOMAIN|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
3283         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
3284         FALSE,
3285         {
3286             {"http://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
3287             {"www.winehq.org",S_OK,FALSE},
3288             {"http://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
3289             {"winehq.org",S_OK,FALSE},
3290             {"",S_FALSE,FALSE},
3291             {"#Te<|>",S_OK,FALSE},
3292             {"www.winehq.org",S_OK,FALSE},
3293             {"",S_FALSE,FALSE},
3294             {"/tests/",S_OK,FALSE},
3295             {"/tests/",S_OK,FALSE},
3296             {"",S_FALSE,FALSE},
3297             {"http://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
3298             {"http",S_OK,FALSE},
3299             {"",S_FALSE,FALSE},
3300             {"",S_FALSE,FALSE}
3301         },
3302         {
3303             {Uri_HOST_DNS,S_OK,FALSE},
3304             {80,S_OK,FALSE},
3305             {URL_SCHEME_HTTP,S_OK,FALSE},
3306             {URLZONE_INVALID,E_NOTIMPL,FALSE},
3307         }
3308     },
3309     /* Percent encoded, unreserved characters aren't decoded for known scheme types. */
3310     {   "zip://www.winehq.org/tests/#Te%30%31%32", 0, S_OK, FALSE,
3311         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_FRAGMENT|
3312         Uri_HAS_HOST|Uri_HAS_DOMAIN|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
3313         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
3314         FALSE,
3315         {
3316             {"zip://www.winehq.org/tests/#Te%30%31%32",S_OK,FALSE},
3317             {"www.winehq.org",S_OK,FALSE},
3318             {"zip://www.winehq.org/tests/#Te%30%31%32",S_OK,FALSE},
3319             {"winehq.org",S_OK,FALSE},
3320             {"",S_FALSE,FALSE},
3321             {"#Te%30%31%32",S_OK,FALSE},
3322             {"www.winehq.org",S_OK,FALSE},
3323             {"",S_FALSE,FALSE},
3324             {"/tests/",S_OK,FALSE},
3325             {"/tests/",S_OK,FALSE},
3326             {"",S_FALSE,FALSE},
3327             {"zip://www.winehq.org/tests/#Te%30%31%32",S_OK,FALSE},
3328             {"zip",S_OK,FALSE},
3329             {"",S_FALSE,FALSE},
3330             {"",S_FALSE,FALSE}
3331         },
3332         {
3333             {Uri_HOST_DNS,S_OK,FALSE},
3334             {0,S_FALSE,FALSE},
3335             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
3336             {URLZONE_INVALID,E_NOTIMPL,FALSE},
3337         }
3338     },
3339     /* Percent encoded, unreserved characters are decoded for known schemes. */
3340     {   "http://www.winehq.org/tests/#Te%30%31%32", 0, S_OK, FALSE,
3341         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_FRAGMENT|
3342         Uri_HAS_HOST|Uri_HAS_DOMAIN|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
3343         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
3344         FALSE,
3345         {
3346             {"http://www.winehq.org/tests/#Te012",S_OK,FALSE},
3347             {"www.winehq.org",S_OK,FALSE},
3348             {"http://www.winehq.org/tests/#Te012",S_OK,FALSE},
3349             {"winehq.org",S_OK,FALSE},
3350             {"",S_FALSE,FALSE},
3351             {"#Te012",S_OK,FALSE},
3352             {"www.winehq.org",S_OK,FALSE},
3353             {"",S_FALSE,FALSE},
3354             {"/tests/",S_OK,FALSE},
3355             {"/tests/",S_OK,FALSE},
3356             {"",S_FALSE,FALSE},
3357             {"http://www.winehq.org/tests/#Te%30%31%32",S_OK,FALSE},
3358             {"http",S_OK,FALSE},
3359             {"",S_FALSE,FALSE},
3360             {"",S_FALSE,FALSE}
3361         },
3362         {
3363             {Uri_HOST_DNS,S_OK,FALSE},
3364             {80,S_OK,FALSE},
3365             {URL_SCHEME_HTTP,S_OK,FALSE},
3366             {URLZONE_INVALID,E_NOTIMPL,FALSE},
3367         }
3368     },
3369     /* Percent encoded, unreserved characters are decoded even if NO_CANONICALIZE is set. */
3370     {   "http://www.winehq.org/tests/#Te%30%31%32", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
3371         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_FRAGMENT|
3372         Uri_HAS_HOST|Uri_HAS_DOMAIN|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
3373         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
3374         FALSE,
3375         {
3376             {"http://www.winehq.org/tests/#Te012",S_OK,FALSE},
3377             {"www.winehq.org",S_OK,FALSE},
3378             {"http://www.winehq.org/tests/#Te012",S_OK,FALSE},
3379             {"winehq.org",S_OK,FALSE},
3380             {"",S_FALSE,FALSE},
3381             {"#Te012",S_OK,FALSE},
3382             {"www.winehq.org",S_OK,FALSE},
3383             {"",S_FALSE,FALSE},
3384             {"/tests/",S_OK,FALSE},
3385             {"/tests/",S_OK,FALSE},
3386             {"",S_FALSE,FALSE},
3387             {"http://www.winehq.org/tests/#Te%30%31%32",S_OK,FALSE},
3388             {"http",S_OK,FALSE},
3389             {"",S_FALSE,FALSE},
3390             {"",S_FALSE,FALSE}
3391         },
3392         {
3393             {Uri_HOST_DNS,S_OK,FALSE},
3394             {80,S_OK,FALSE},
3395             {URL_SCHEME_HTTP,S_OK,FALSE},
3396             {URLZONE_INVALID,E_NOTIMPL,FALSE},
3397         }
3398     },
3399     /* Percent encoded, unreserved characters aren't decoded when NO_DECODE_EXTRA is set. */
3400     {   "http://www.winehq.org/tests/#Te%30%31%32", Uri_CREATE_NO_DECODE_EXTRA_INFO, S_OK, FALSE,
3401         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_FRAGMENT|
3402         Uri_HAS_HOST|Uri_HAS_DOMAIN|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
3403         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
3404         FALSE,
3405         {
3406             {"http://www.winehq.org/tests/#Te%30%31%32",S_OK,FALSE},
3407             {"www.winehq.org",S_OK,FALSE},
3408             {"http://www.winehq.org/tests/#Te%30%31%32",S_OK,FALSE},
3409             {"winehq.org",S_OK,FALSE},
3410             {"",S_FALSE,FALSE},
3411             {"#Te%30%31%32",S_OK,FALSE},
3412             {"www.winehq.org",S_OK,FALSE},
3413             {"",S_FALSE,FALSE},
3414             {"/tests/",S_OK,FALSE},
3415             {"/tests/",S_OK,FALSE},
3416             {"",S_FALSE,FALSE},
3417             {"http://www.winehq.org/tests/#Te%30%31%32",S_OK,FALSE},
3418             {"http",S_OK,FALSE},
3419             {"",S_FALSE,FALSE},
3420             {"",S_FALSE,FALSE}
3421         },
3422         {
3423             {Uri_HOST_DNS,S_OK,FALSE},
3424             {80,S_OK,FALSE},
3425             {URL_SCHEME_HTTP,S_OK,FALSE},
3426             {URLZONE_INVALID,E_NOTIMPL,FALSE},
3427         }
3428     },
3429     /* Leading/Trailing whitespace is removed. */
3430     {   "    http://google.com/     ", 0, S_OK, FALSE,
3431         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
3432         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
3433         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
3434         FALSE,
3435         {
3436             {"http://google.com/",S_OK,FALSE},
3437             {"google.com",S_OK,FALSE},
3438             {"http://google.com/",S_OK,FALSE},
3439             {"google.com",S_OK,FALSE},
3440             {"",S_FALSE,FALSE},
3441             {"",S_FALSE,FALSE},
3442             {"google.com",S_OK,FALSE},
3443             {"",S_FALSE,FALSE},
3444             {"/",S_OK,FALSE},
3445             {"/",S_OK,FALSE},
3446             {"",S_FALSE,FALSE},
3447             {"http://google.com/",S_OK,FALSE},
3448             {"http",S_OK,FALSE},
3449             {"",S_FALSE,FALSE},
3450             {"",S_FALSE,FALSE}
3451         },
3452         {
3453             {Uri_HOST_DNS,S_OK,FALSE},
3454             {80,S_OK,FALSE},
3455             {URL_SCHEME_HTTP,S_OK,FALSE},
3456             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3457         }
3458     },
3459     {   "\t\t\r\nhttp\n://g\noogle.co\rm/\n\n\n", 0, S_OK, FALSE,
3460         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
3461         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
3462         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
3463         FALSE,
3464         {
3465             {"http://google.com/",S_OK,FALSE},
3466             {"google.com",S_OK,FALSE},
3467             {"http://google.com/",S_OK,FALSE},
3468             {"google.com",S_OK,FALSE},
3469             {"",S_FALSE,FALSE},
3470             {"",S_FALSE,FALSE},
3471             {"google.com",S_OK,FALSE},
3472             {"",S_FALSE,FALSE},
3473             {"/",S_OK,FALSE},
3474             {"/",S_OK,FALSE},
3475             {"",S_FALSE,FALSE},
3476             {"http://google.com/",S_OK,FALSE},
3477             {"http",S_OK,FALSE},
3478             {"",S_FALSE,FALSE},
3479             {"",S_FALSE,FALSE}
3480         },
3481         {
3482             {Uri_HOST_DNS,S_OK,FALSE},
3483             {80,S_OK,FALSE},
3484             {URL_SCHEME_HTTP,S_OK,FALSE},
3485             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3486         }
3487     },
3488     {   "http://g\noogle.co\rm/\n\n\n", Uri_CREATE_NO_PRE_PROCESS_HTML_URI, S_OK, FALSE,
3489         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
3490         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
3491         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
3492         FALSE,
3493         {
3494             {"http://g%0aoogle.co%0dm/%0A%0A%0A",S_OK,FALSE},
3495             {"g%0aoogle.co%0dm",S_OK,FALSE},
3496             {"http://g%0aoogle.co%0dm/%0A%0A%0A",S_OK,FALSE},
3497             {"g%0aoogle.co%0dm",S_OK,FALSE},
3498             {"",S_FALSE,FALSE},
3499             {"",S_FALSE,FALSE},
3500             {"g%0aoogle.co%0dm",S_OK,FALSE},
3501             {"",S_FALSE,FALSE},
3502             {"/%0A%0A%0A",S_OK,FALSE},
3503             {"/%0A%0A%0A",S_OK,FALSE},
3504             {"",S_FALSE,FALSE},
3505             {"http://g\noogle.co\rm/\n\n\n",S_OK,FALSE},
3506             {"http",S_OK,FALSE},
3507             {"",S_FALSE,FALSE},
3508             {"",S_FALSE,FALSE}
3509         },
3510         {
3511             {Uri_HOST_DNS,S_OK,FALSE},
3512             {80,S_OK,FALSE},
3513             {URL_SCHEME_HTTP,S_OK,FALSE},
3514             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3515         }
3516     },
3517     {   "zip://g\noogle.co\rm/\n\n\n", Uri_CREATE_NO_PRE_PROCESS_HTML_URI, S_OK, FALSE,
3518         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
3519         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
3520         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
3521         FALSE,
3522         {
3523             {"zip://g\noogle.co\rm/\n\n\n",S_OK,FALSE},
3524             {"g\noogle.co\rm",S_OK,FALSE},
3525             {"zip://g\noogle.co\rm/\n\n\n",S_OK,FALSE},
3526             {"g\noogle.co\rm",S_OK,FALSE},
3527             {"",S_FALSE,FALSE},
3528             {"",S_FALSE,FALSE},
3529             {"g\noogle.co\rm",S_OK,FALSE},
3530             {"",S_FALSE,FALSE},
3531             {"/\n\n\n",S_OK,FALSE},
3532             {"/\n\n\n",S_OK,FALSE},
3533             {"",S_FALSE,FALSE},
3534             {"zip://g\noogle.co\rm/\n\n\n",S_OK,FALSE},
3535             {"zip",S_OK,FALSE},
3536             {"",S_FALSE,FALSE},
3537             {"",S_FALSE,FALSE}
3538         },
3539         {
3540             {Uri_HOST_DNS,S_OK,FALSE},
3541             {0,S_FALSE,FALSE},
3542             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
3543             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3544         }
3545     }
3546 };
3547
3548 typedef struct _invalid_uri {
3549     const char* uri;
3550     DWORD       flags;
3551     BOOL        todo;
3552 } invalid_uri;
3553
3554 static const invalid_uri invalid_uri_tests[] = {
3555     /* Has to have a scheme name. */
3556     {"://www.winehq.org",0,FALSE},
3557     /* Window's doesn't like URI's which are implicitly file paths without the
3558      * ALLOW_IMPLICIT_FILE_SCHEME flag set.
3559      */
3560     {"C:/test/test.mp3",0,FALSE},
3561     {"\\\\Server/test/test.mp3",0,FALSE},
3562     {"C:/test/test.mp3",Uri_CREATE_ALLOW_IMPLICIT_WILDCARD_SCHEME,FALSE},
3563     {"\\\\Server/test/test.mp3",Uri_CREATE_ALLOW_RELATIVE,FALSE},
3564     /* Invalid schemes. */
3565     {"*abcd://not.valid.com",0,FALSE},
3566     {"*a*b*c*d://not.valid.com",0,FALSE},
3567     /* Not allowed to have invalid % encoded data. */
3568     {"ftp://google.co%XX/",0,FALSE},
3569     /* To many h16 components. */
3570     {"http://[1:2:3:4:5:6:7:8:9]",0,FALSE},
3571     /* Not enough room for IPv4 address. */
3572     {"http://[1:2:3:4:5:6:7:192.0.1.0]",0,FALSE},
3573     /* Not enough h16 components. */
3574     {"http://[1:2:3:4]",0,FALSE},
3575     /* Not enough components including IPv4. */
3576     {"http://[1:192.0.1.0]",0,FALSE},
3577     /* Not allowed to have partial IPv4 in IPv6. */
3578     {"http://[::192.0]",0,FALSE},
3579     /* Can't have elision of 1 h16 at beginning of address. */
3580     {"http://[::2:3:4:5:6:7:8]",0,FALSE},
3581     /* Can't have elision of 1 h16 at end of address. */
3582     {"http://[1:2:3:4:5:6:7::]",0,FALSE},
3583     /* Expects a valid IP Literal. */
3584     {"ftp://[not.valid.uri]/",0,FALSE},
3585     /* Expects valid port for a known scheme type. */
3586     {"ftp://www.winehq.org:123fgh",0,FALSE},
3587     /* Port exceeds USHORT_MAX for known scheme type. */
3588     {"ftp://www.winehq.org:65536",0,FALSE},
3589     /* Invalid port with IPv4 address. */
3590     {"http://www.winehq.org:1abcd",0,FALSE},
3591     /* Invalid port with IPv6 address. */
3592     {"http://[::ffff]:32xy",0,FALSE},
3593     /* Not allowed to have backslashes with NO_CANONICALIZE. */
3594     {"gopher://www.google.com\\test",Uri_CREATE_NO_CANONICALIZE,FALSE},
3595     /* Not allowed to have invalid % encoded data in opaque URI path. */
3596     {"news:test%XX",0,FALSE},
3597     {"mailto:wine@winehq%G8.com",0,FALSE},
3598     /* Known scheme types can't have invalid % encoded data in query string. */
3599     {"http://google.com/?query=te%xx",0,FALSE},
3600     /* Invalid % encoded data in fragment of know scheme type. */
3601     {"ftp://google.com/#Test%xx",0,FALSE},
3602     {"  http://google.com/",Uri_CREATE_NO_PRE_PROCESS_HTML_URI,FALSE},
3603     {"\n\nhttp://google.com/",Uri_CREATE_NO_PRE_PROCESS_HTML_URI,FALSE}
3604 };
3605
3606 typedef struct _uri_equality {
3607     const char* a;
3608     DWORD       create_flags_a;
3609     BOOL        create_todo_a;
3610     const char* b;
3611     DWORD       create_flags_b;
3612     BOOL        create_todo_b;
3613     BOOL        equal;
3614     BOOL        todo;
3615 } uri_equality;
3616
3617 static const uri_equality equality_tests[] = {
3618     {
3619         "HTTP://www.winehq.org/test dir/./",0,FALSE,
3620         "http://www.winehq.org/test dir/../test dir/",0,FALSE,
3621         TRUE, FALSE
3622     },
3623     {
3624         /* http://www.winehq.org/test%20dir */
3625         "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,
3626         "http://www.winehq.org/test dir",0,FALSE,
3627         TRUE, FALSE
3628     },
3629     {
3630         "c:\\test.mp3",Uri_CREATE_ALLOW_IMPLICIT_FILE_SCHEME,FALSE,
3631         "file:///c:/test.mp3",0,FALSE,
3632         TRUE, FALSE
3633     },
3634     {
3635         "ftp://ftp.winehq.org/",0,FALSE,
3636         "ftp://ftp.winehq.org",0,FALSE,
3637         TRUE, FALSE
3638     },
3639     {
3640         "ftp://ftp.winehq.org/test/test2/../../testB/",0,FALSE,
3641         "ftp://ftp.winehq.org/t%45stB/",0,FALSE,
3642         FALSE, FALSE
3643     },
3644     {
3645         "http://google.com/TEST",0,FALSE,
3646         "http://google.com/test",0,FALSE,
3647         FALSE, FALSE
3648     },
3649     {
3650         "http://GOOGLE.com/",0,FALSE,
3651         "http://google.com/",0,FALSE,
3652         TRUE, FALSE
3653     },
3654     /* Performs case insensitive compare of host names (for known scheme types). */
3655     {
3656         "ftp://GOOGLE.com/",Uri_CREATE_NO_CANONICALIZE,FALSE,
3657         "ftp://google.com/",0,FALSE,
3658         TRUE, FALSE
3659     },
3660     {
3661         "zip://GOOGLE.com/",0,FALSE,
3662         "zip://google.com/",0,FALSE,
3663         FALSE, FALSE
3664     },
3665     {
3666         "file:///c:/TEST/TeST/",0,FALSE,
3667         "file:///c:/test/test/",0,FALSE,
3668         TRUE, FALSE
3669     },
3670     {
3671         "file:///server/TEST",0,FALSE,
3672         "file:///SERVER/TEST",0,FALSE,
3673         TRUE, FALSE
3674     },
3675     {
3676         "http://google.com",Uri_CREATE_NO_CANONICALIZE,FALSE,
3677         "http://google.com/",0,FALSE,
3678         TRUE, FALSE
3679     },
3680     {
3681         "ftp://google.com:21/",0,FALSE,
3682         "ftp://google.com/",0,FALSE,
3683         TRUE, FALSE
3684     },
3685     {
3686         "http://google.com:80/",Uri_CREATE_NO_CANONICALIZE,FALSE,
3687         "http://google.com/",0,FALSE,
3688         TRUE, FALSE
3689     },
3690     {
3691         "http://google.com:70/",0,FALSE,
3692         "http://google.com:71/",0,FALSE,
3693         FALSE, FALSE
3694     }
3695 };
3696
3697 typedef struct _uri_with_fragment {
3698     const char* uri;
3699     const char* fragment;
3700     DWORD       create_flags;
3701     HRESULT     create_expected;
3702     BOOL        create_todo;
3703
3704     const char* expected_uri;
3705     BOOL        expected_todo;
3706 } uri_with_fragment;
3707
3708 static const uri_with_fragment uri_fragment_tests[] = {
3709     {
3710         "http://google.com/","#fragment",0,S_OK,FALSE,
3711         "http://google.com/#fragment",FALSE
3712     },
3713     {
3714         "http://google.com/","fragment",0,S_OK,FALSE,
3715         "http://google.com/#fragment",FALSE
3716     },
3717     {
3718         "zip://test.com/","?test",0,S_OK,FALSE,
3719         "zip://test.com/#?test",FALSE
3720     },
3721     /* The fragment can be empty. */
3722     {
3723         "ftp://ftp.google.com/","",0,S_OK,FALSE,
3724         "ftp://ftp.google.com/#",FALSE
3725     }
3726 };
3727
3728 typedef struct _uri_builder_property {
3729     BOOL            change;
3730     const char      *value;
3731     const char      *expected_value;
3732     Uri_PROPERTY    property;
3733     HRESULT         expected;
3734     BOOL            todo;
3735 } uri_builder_property;
3736
3737 typedef struct _uri_builder_port {
3738     BOOL    change;
3739     BOOL    set;
3740     DWORD   value;
3741     HRESULT expected;
3742     BOOL    todo;
3743 } uri_builder_port;
3744
3745 typedef struct _uri_builder_test {
3746     const char              *uri;
3747     DWORD                   create_flags;
3748     HRESULT                 create_builder_expected;
3749     BOOL                    create_builder_todo;
3750
3751     uri_builder_property    properties[URI_BUILDER_STR_PROPERTY_COUNT];
3752
3753     uri_builder_port        port_prop;
3754
3755     const char              *uri_expected;
3756     DWORD                   uri_flags;
3757     HRESULT                 uri_hres;
3758     BOOL                    uri_todo;
3759
3760     const char              *uri_simple_expected;
3761     DWORD                   uri_simple_encode_flags;
3762     HRESULT                 uri_simple_hres;
3763     BOOL                    uri_simple_todo;
3764
3765     const char              *uri_with_expected;
3766     DWORD                   uri_with_flags;
3767     DWORD                   uri_with_builder_flags;
3768     DWORD                   uri_with_encode_flags;
3769     HRESULT                 uri_with_hres;
3770     BOOL                    uri_with_todo;
3771 } uri_builder_test;
3772
3773 static const uri_builder_test uri_builder_tests[] = {
3774     {   "http://google.com/",0,S_OK,FALSE,
3775         {
3776             {TRUE,"#fragment",NULL,Uri_PROPERTY_FRAGMENT,S_OK,TRUE},
3777             {TRUE,"password",NULL,Uri_PROPERTY_PASSWORD,S_OK,TRUE},
3778             {TRUE,"?query=x",NULL,Uri_PROPERTY_QUERY,S_OK,TRUE},
3779             {TRUE,"username",NULL,Uri_PROPERTY_USER_NAME,S_OK,TRUE}
3780         },
3781         {FALSE},
3782         "http://username:password@google.com/?query=x#fragment",0,S_OK,TRUE,
3783         "http://username:password@google.com/?query=x#fragment",0,S_OK,TRUE,
3784         "http://username:password@google.com/?query=x#fragment",0,0,0,S_OK,TRUE
3785     },
3786     {   "http://google.com/",0,S_OK,FALSE,
3787         {
3788             {TRUE,"test",NULL,Uri_PROPERTY_SCHEME_NAME,S_OK,TRUE}
3789         },
3790         {TRUE,TRUE,120,S_OK,TRUE},
3791         "test://google.com:120/",0,S_OK,TRUE,
3792         "test://google.com:120/",0,S_OK,TRUE,
3793         "test://google.com:120/",0,0,0,S_OK,TRUE
3794     },
3795     {   "/Test/test dir",Uri_CREATE_ALLOW_RELATIVE,S_OK,FALSE,
3796         {
3797             {TRUE,"http",NULL,Uri_PROPERTY_SCHEME_NAME,S_OK,TRUE},
3798             {TRUE,"::192.2.3.4",NULL,Uri_PROPERTY_HOST,S_OK,TRUE},
3799             {TRUE,NULL,NULL,Uri_PROPERTY_PATH,S_OK,TRUE}
3800         },
3801         {FALSE},
3802         "http://[::192.2.3.4]/",0,S_OK,TRUE,
3803         "http://[::192.2.3.4]/",0,S_OK,TRUE,
3804         "http://[::192.2.3.4]/",0,0,0,S_OK,TRUE
3805     }
3806 };
3807
3808 typedef struct _uri_builder_remove_test {
3809     const char  *uri;
3810     DWORD       create_flags;
3811     HRESULT     create_builder_expected;
3812     BOOL        create_builder_todo;
3813
3814     DWORD       remove_properties;
3815     HRESULT     remove_expected;
3816     BOOL        remove_todo;
3817
3818     const char  *expected_uri;
3819     DWORD       expected_flags;
3820     HRESULT     expected_hres;
3821     BOOL        expected_todo;
3822 } uri_builder_remove_test;
3823
3824 static const uri_builder_remove_test uri_builder_remove_tests[] = {
3825     {   "http://google.com/test?test=y#Frag",0,S_OK,FALSE,
3826         Uri_HAS_FRAGMENT|Uri_HAS_PATH|Uri_HAS_QUERY,S_OK,TRUE,
3827         "http://google.com/",0,S_OK,TRUE
3828     },
3829     {   "http://user:pass@winehq.org/",0,S_OK,FALSE,
3830         Uri_HAS_USER_NAME|Uri_HAS_PASSWORD,S_OK,TRUE,
3831         "http://winehq.org/",0,S_OK,TRUE
3832     },
3833     {   "zip://google.com?Test=x",0,S_OK,FALSE,
3834         Uri_HAS_HOST,S_OK,TRUE,
3835         "zip:/?Test=x",0,S_OK,TRUE
3836     }
3837 };
3838
3839 static inline LPWSTR a2w(LPCSTR str) {
3840     LPWSTR ret = NULL;
3841
3842     if(str) {
3843         DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3844         ret = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
3845         MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len);
3846     }
3847
3848     return ret;
3849 }
3850
3851 static inline BOOL heap_free(void* mem) {
3852     return HeapFree(GetProcessHeap(), 0, mem);
3853 }
3854
3855 static inline DWORD strcmp_aw(LPCSTR strA, LPCWSTR strB) {
3856     LPWSTR strAW = a2w(strA);
3857     DWORD ret = lstrcmpW(strAW, strB);
3858     heap_free(strAW);
3859     return ret;
3860 }
3861
3862 static inline ULONG get_refcnt(IUri *uri) {
3863     IUri_AddRef(uri);
3864     return IUri_Release(uri);
3865 }
3866
3867 static void change_property(IUriBuilder *builder, const uri_builder_property *prop,
3868                             DWORD test_index) {
3869     HRESULT hr;
3870     LPWSTR valueW;
3871
3872     valueW = a2w(prop->value);
3873     switch(prop->property) {
3874     case Uri_PROPERTY_FRAGMENT:
3875         hr = IUriBuilder_SetFragment(builder, valueW);
3876         if(prop->todo) {
3877             todo_wine {
3878                 ok(hr == prop->expected,
3879                     "Error: IUriBuilder_SetFragment returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
3880                     hr, prop->expected, test_index);
3881             }
3882         } else {
3883             ok(hr == prop->expected,
3884                 "Error: IUriBuilder_SetFragment returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
3885                 hr, prop->expected, test_index);
3886         }
3887         break;
3888     case Uri_PROPERTY_HOST:
3889         hr = IUriBuilder_SetHost(builder, valueW);
3890         if(prop->todo) {
3891             todo_wine {
3892                 ok(hr == prop->expected,
3893                     "Error: IUriBuilder_SetHost returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
3894                     hr, prop->expected, test_index);
3895             }
3896         } else {
3897             ok(hr == prop->expected,
3898                 "Error: IUriBuilder_SetHost returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
3899                 hr, prop->expected, test_index);
3900         }
3901         break;
3902     case Uri_PROPERTY_PASSWORD:
3903         hr = IUriBuilder_SetPassword(builder, valueW);
3904         if(prop->todo) {
3905             todo_wine {
3906                 ok(hr == prop->expected,
3907                     "Error: IUriBuilder_SetPassword returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
3908                     hr, prop->expected, test_index);
3909             }
3910         } else {
3911             ok(hr == prop->expected,
3912                 "Error: IUriBuilder_SetPassword returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
3913                 hr, prop->expected, test_index);
3914         }
3915         break;
3916     case Uri_PROPERTY_PATH:
3917         hr = IUriBuilder_SetPath(builder, valueW);
3918         if(prop->todo) {
3919             todo_wine {
3920                 ok(hr == prop->expected,
3921                     "Error: IUriBuilder_SetPath returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
3922                     hr, prop->expected, test_index);
3923             }
3924         } else {
3925             ok(hr == prop->expected,
3926                 "Error: IUriBuilder_SetPath returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
3927                 hr, prop->expected, test_index);
3928         }
3929         break;
3930     case Uri_PROPERTY_QUERY:
3931         hr = IUriBuilder_SetQuery(builder, valueW);
3932         if(prop->todo) {
3933             todo_wine {
3934                 ok(hr == prop->expected,
3935                     "Error: IUriBuilder_SetQuery returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
3936                     hr, prop->expected, test_index);
3937             }
3938         } else {
3939             ok(hr == prop->expected,
3940                 "Error: IUriBuilder_SetQuery returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
3941                 hr, prop->expected, test_index);
3942         }
3943         break;
3944     case Uri_PROPERTY_SCHEME_NAME:
3945         hr = IUriBuilder_SetSchemeName(builder, valueW);
3946         if(prop->todo) {
3947             todo_wine {
3948                 ok(hr == prop->expected,
3949                     "Error: IUriBuilder_SetSchemeName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
3950                     hr, prop->expected, test_index);
3951             }
3952         } else {
3953             ok(hr == prop->expected,
3954                 "Error: IUriBuilder_SetSchemeName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
3955                 hr, prop->expected, test_index);
3956         }
3957         break;
3958     case Uri_PROPERTY_USER_NAME:
3959         hr = IUriBuilder_SetUserName(builder, valueW);
3960         if(prop->todo) {
3961             todo_wine {
3962                 ok(hr == prop->expected,
3963                     "Error: IUriBuilder_SetUserName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
3964                     hr, prop->expected, test_index);
3965             }
3966         } else {
3967             ok(hr == prop->expected,
3968                 "Error: IUriBuilder_SetUserName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
3969                 hr, prop->expected, test_index);
3970         }
3971         break;
3972     default:
3973         trace("Unsupported operation for %d on uri_builder_tests[%d].\n", prop->property, test_index);
3974     }
3975
3976     heap_free(valueW);
3977 }
3978
3979 /*
3980  * Simple tests to make sure the CreateUri function handles invalid flag combinations
3981  * correctly.
3982  */
3983 static void test_CreateUri_InvalidFlags(void) {
3984     DWORD i;
3985
3986     for(i = 0; i < sizeof(invalid_flag_tests)/sizeof(invalid_flag_tests[0]); ++i) {
3987         HRESULT hr;
3988         IUri *uri = (void*) 0xdeadbeef;
3989
3990         hr = pCreateUri(http_urlW, invalid_flag_tests[i].flags, 0, &uri);
3991         ok(hr == invalid_flag_tests[i].expected, "Error: CreateUri returned 0x%08x, expected 0x%08x, flags=0x%08x\n",
3992                 hr, invalid_flag_tests[i].expected, invalid_flag_tests[i].flags);
3993         ok(uri == NULL, "Error: expected the IUri to be NULL, but it was %p instead\n", uri);
3994     }
3995 }
3996
3997 static void test_CreateUri_InvalidArgs(void) {
3998     HRESULT hr;
3999     IUri *uri = (void*) 0xdeadbeef;
4000
4001     const WCHAR invalidW[] = {'i','n','v','a','l','i','d',0};
4002
4003     hr = pCreateUri(http_urlW, 0, 0, NULL);
4004     ok(hr == E_INVALIDARG, "Error: CreateUri returned 0x%08x, expected 0x%08x\n", hr, E_INVALIDARG);
4005
4006     hr = pCreateUri(NULL, 0, 0, &uri);
4007     ok(hr == E_INVALIDARG, "Error: CreateUri returned 0x%08x, expected 0x%08x\n", hr, E_INVALIDARG);
4008     ok(uri == NULL, "Error: Expected the IUri to be NULL, but it was %p instead\n", uri);
4009
4010     uri = (void*) 0xdeadbeef;
4011     hr = pCreateUri(invalidW, 0, 0, &uri);
4012     ok(hr == E_INVALIDARG, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
4013     ok(uri == NULL, "Error: Expected the IUri to be NULL, but it was %p instead\n", uri);
4014 }
4015
4016 static void test_CreateUri_InvalidUri(void) {
4017     DWORD i;
4018
4019     for(i = 0; i < sizeof(invalid_uri_tests)/sizeof(invalid_uri_tests[0]); ++i) {
4020         invalid_uri test = invalid_uri_tests[i];
4021         IUri *uri = NULL;
4022         LPWSTR uriW;
4023         HRESULT hr;
4024
4025         uriW = a2w(test.uri);
4026         hr = pCreateUri(uriW, test.flags, 0, &uri);
4027         if(test.todo) {
4028             todo_wine {
4029                 ok(hr == E_INVALIDARG, "Error: CreateUri returned 0x%08x, expected 0x%08x on invalid_uri_tests[%d].\n",
4030                     hr, E_INVALIDARG, i);
4031             }
4032         } else {
4033             ok(hr == E_INVALIDARG, "Error: CreateUri returned 0x%08x, expected 0x%08x on invalid_uri_tests[%d].\n",
4034                 hr, E_INVALIDARG, i);
4035         }
4036         if(uri) IUri_Release(uri);
4037
4038         heap_free(uriW);
4039     }
4040 }
4041
4042 static void test_IUri_GetPropertyBSTR(void) {
4043     IUri *uri = NULL;
4044     HRESULT hr;
4045     DWORD i;
4046
4047     /* Make sure GetPropertyBSTR handles invalid args correctly. */
4048     hr = pCreateUri(http_urlW, 0, 0, &uri);
4049     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
4050     if(SUCCEEDED(hr)) {
4051         BSTR received = NULL;
4052
4053         hr = IUri_GetPropertyBSTR(uri, Uri_PROPERTY_RAW_URI, NULL, 0);
4054         ok(hr == E_POINTER, "Error: GetPropertyBSTR returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
4055
4056         /* Make sure it handles a invalid Uri_PROPERTY's correctly. */
4057         hr = IUri_GetPropertyBSTR(uri, Uri_PROPERTY_PORT, &received, 0);
4058         ok(hr == S_OK, "Error: GetPropertyBSTR returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
4059         ok(received != NULL, "Error: Expected the string not to be NULL.\n");
4060         ok(!SysStringLen(received), "Error: Expected the string to be of len=0 but it was %d instead.\n", SysStringLen(received));
4061         SysFreeString(received);
4062
4063         /* Make sure it handles the ZONE property correctly. */
4064         received = NULL;
4065         hr = IUri_GetPropertyBSTR(uri, Uri_PROPERTY_ZONE, &received, 0);
4066         ok(hr == S_FALSE, "Error: GetPropertyBSTR returned 0x%08x, expected 0x%08x.\n", hr, S_FALSE);
4067         ok(received != NULL, "Error: Expected the string not to be NULL.\n");
4068         ok(!SysStringLen(received), "Error: Expected the string to be of len=0 but it was %d instead.\n", SysStringLen(received));
4069         SysFreeString(received);
4070     }
4071     if(uri) IUri_Release(uri);
4072
4073     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
4074         uri_properties test = uri_tests[i];
4075         LPWSTR uriW;
4076         uri = NULL;
4077
4078         uriW = a2w(test.uri);
4079         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
4080         if(test.create_todo) {
4081             todo_wine {
4082                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x. Failed on uri_tests[%d].\n",
4083                         hr, test.create_expected, i);
4084             }
4085         } else {
4086             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x. Failed on uri_tests[%d].\n",
4087                     hr, test.create_expected, i);
4088         }
4089
4090         if(SUCCEEDED(hr)) {
4091             DWORD j;
4092
4093             /* Checks all the string properties of the uri. */
4094             for(j = Uri_PROPERTY_STRING_START; j <= Uri_PROPERTY_STRING_LAST; ++j) {
4095                 BSTR received = NULL;
4096                 uri_str_property prop = test.str_props[j];
4097
4098                 hr = IUri_GetPropertyBSTR(uri, j, &received, 0);
4099                 if(prop.todo) {
4100                     todo_wine {
4101                         ok(hr == prop.expected, "GetPropertyBSTR returned 0x%08x, expected 0x%08x. On uri_tests[%d].str_props[%d].\n",
4102                                 hr, prop.expected, i, j);
4103                     }
4104                     todo_wine {
4105                         ok(!strcmp_aw(prop.value, received) || broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
4106                                 "Expected %s but got %s on uri_tests[%d].str_props[%d].\n",
4107                                 prop.value, wine_dbgstr_w(received), i, j);
4108                     }
4109                 } else {
4110                     ok(hr == prop.expected, "GetPropertyBSTR returned 0x%08x, expected 0x%08x. On uri_tests[%d].str_props[%d].\n",
4111                             hr, prop.expected, i, j);
4112                     ok(!strcmp_aw(prop.value, received) || broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
4113                             "Expected %s but got %s on uri_tests[%d].str_props[%d].\n",
4114                             prop.value, wine_dbgstr_w(received), i, j);
4115                 }
4116
4117                 SysFreeString(received);
4118             }
4119         }
4120
4121         if(uri) IUri_Release(uri);
4122
4123         heap_free(uriW);
4124     }
4125 }
4126
4127 static void test_IUri_GetPropertyDWORD(void) {
4128     IUri *uri = NULL;
4129     HRESULT hr;
4130     DWORD i;
4131
4132     hr = pCreateUri(http_urlW, 0, 0, &uri);
4133     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
4134     if(SUCCEEDED(hr)) {
4135         DWORD received = 0xdeadbeef;
4136
4137         hr = IUri_GetPropertyDWORD(uri, Uri_PROPERTY_DWORD_START, NULL, 0);
4138         ok(hr == E_INVALIDARG, "Error: GetPropertyDWORD returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
4139
4140         hr = IUri_GetPropertyDWORD(uri, Uri_PROPERTY_ABSOLUTE_URI, &received, 0);
4141         ok(hr == E_INVALIDARG, "Error: GetPropertyDWORD returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
4142         ok(received == 0, "Error: Expected received=%d but instead received=%d.\n", 0, received);
4143     }
4144     if(uri) IUri_Release(uri);
4145
4146     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
4147         uri_properties test = uri_tests[i];
4148         LPWSTR uriW;
4149         uri = NULL;
4150
4151         uriW = a2w(test.uri);
4152         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
4153         if(test.create_todo) {
4154             todo_wine {
4155                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x. Failed on uri_tests[%d].\n",
4156                         hr, test.create_expected, i);
4157             }
4158         } else {
4159             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x. Failed on uri_tests[%d].\n",
4160                     hr, test.create_expected, i);
4161         }
4162
4163         if(SUCCEEDED(hr)) {
4164             DWORD j;
4165
4166             /* Checks all the DWORD properties of the uri. */
4167             for(j = 0; j < sizeof(test.dword_props)/sizeof(test.dword_props[0]); ++j) {
4168                 DWORD received;
4169                 uri_dword_property prop = test.dword_props[j];
4170
4171                 hr = IUri_GetPropertyDWORD(uri, j+Uri_PROPERTY_DWORD_START, &received, 0);
4172                 if(prop.todo) {
4173                     todo_wine {
4174                         ok(hr == prop.expected, "GetPropertyDWORD returned 0x%08x, expected 0x%08x. On uri_tests[%d].dword_props[%d].\n",
4175                                 hr, prop.expected, i, j);
4176                     }
4177                     todo_wine {
4178                         ok(prop.value == received, "Expected %d but got %d on uri_tests[%d].dword_props[%d].\n",
4179                                 prop.value, received, i, j);
4180                     }
4181                 } else {
4182                     ok(hr == prop.expected, "GetPropertyDWORD returned 0x%08x, expected 0x%08x. On uri_tests[%d].dword_props[%d].\n",
4183                             hr, prop.expected, i, j);
4184                     ok(prop.value == received, "Expected %d but got %d on uri_tests[%d].dword_props[%d].\n",
4185                             prop.value, received, i, j);
4186                 }
4187             }
4188         }
4189
4190         if(uri) IUri_Release(uri);
4191
4192         heap_free(uriW);
4193     }
4194 }
4195
4196 /* Tests all the 'Get*' property functions which deal with strings. */
4197 static void test_IUri_GetStrProperties(void) {
4198     IUri *uri = NULL;
4199     HRESULT hr;
4200     DWORD i;
4201
4202     /* Make sure all the 'Get*' string property functions handle invalid args correctly. */
4203     hr = pCreateUri(http_urlW, 0, 0, &uri);
4204     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
4205     if(SUCCEEDED(hr)) {
4206         hr = IUri_GetAbsoluteUri(uri, NULL);
4207         ok(hr == E_POINTER, "Error: GetAbsoluteUri returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
4208
4209         hr = IUri_GetAuthority(uri, NULL);
4210         ok(hr == E_POINTER, "Error: GetAuthority returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
4211
4212         hr = IUri_GetDisplayUri(uri, NULL);
4213         ok(hr == E_POINTER, "Error: GetDisplayUri returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
4214
4215         hr = IUri_GetDomain(uri, NULL);
4216         ok(hr == E_POINTER, "Error: GetDomain returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
4217
4218         hr = IUri_GetExtension(uri, NULL);
4219         ok(hr == E_POINTER, "Error: GetExtension returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
4220
4221         hr = IUri_GetFragment(uri, NULL);
4222         ok(hr == E_POINTER, "Error: GetFragment returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
4223
4224         hr = IUri_GetHost(uri, NULL);
4225         ok(hr == E_POINTER, "Error: GetHost returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
4226
4227         hr = IUri_GetPassword(uri, NULL);
4228         ok(hr == E_POINTER, "Error: GetPassword returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
4229
4230         hr = IUri_GetPath(uri, NULL);
4231         ok(hr == E_POINTER, "Error: GetPath returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
4232
4233         hr = IUri_GetPathAndQuery(uri, NULL);
4234         ok(hr == E_POINTER, "Error: GetPathAndQuery returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
4235
4236         hr = IUri_GetQuery(uri, NULL);
4237         ok(hr == E_POINTER, "Error: GetQuery returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
4238
4239         hr = IUri_GetRawUri(uri, NULL);
4240         ok(hr == E_POINTER, "Error: GetRawUri returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
4241
4242         hr = IUri_GetSchemeName(uri, NULL);
4243         ok(hr == E_POINTER, "Error: GetSchemeName returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
4244
4245         hr = IUri_GetUserInfo(uri, NULL);
4246         ok(hr == E_POINTER, "Error: GetUserInfo returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
4247
4248         hr = IUri_GetUserName(uri, NULL);
4249         ok(hr == E_POINTER, "Error: GetUserName returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
4250     }
4251     if(uri) IUri_Release(uri);
4252
4253     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
4254         uri_properties test = uri_tests[i];
4255         LPWSTR uriW;
4256         uri = NULL;
4257
4258         uriW = a2w(test.uri);
4259         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
4260         if(test.create_todo) {
4261             todo_wine {
4262                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
4263                         hr, test.create_expected, i);
4264             }
4265         } else {
4266             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
4267                     hr, test.create_expected, i);
4268         }
4269
4270         if(SUCCEEDED(hr)) {
4271             uri_str_property prop;
4272             BSTR received = NULL;
4273
4274             /* GetAbsoluteUri() tests. */
4275             prop = test.str_props[Uri_PROPERTY_ABSOLUTE_URI];
4276             hr = IUri_GetAbsoluteUri(uri, &received);
4277             if(prop.todo) {
4278                 todo_wine {
4279                     ok(hr == prop.expected, "Error: GetAbsoluteUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
4280                             hr, prop.expected, i);
4281                 }
4282                 todo_wine {
4283                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
4284                             prop.value, wine_dbgstr_w(received), i);
4285                 }
4286             } else {
4287                 ok(hr == prop.expected, "Error: GetAbsoluteUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
4288                         hr, prop.expected, i);
4289                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
4290                         prop.value, wine_dbgstr_w(received), i);
4291             }
4292             SysFreeString(received);
4293             received = NULL;
4294
4295             /* GetAuthority() tests. */
4296             prop = test.str_props[Uri_PROPERTY_AUTHORITY];
4297             hr = IUri_GetAuthority(uri, &received);
4298             if(prop.todo) {
4299                 todo_wine {
4300                     ok(hr == prop.expected, "Error: GetAuthority returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
4301                             hr, prop.expected, i);
4302                 }
4303                 todo_wine {
4304                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
4305                             prop.value, wine_dbgstr_w(received), i);
4306                 }
4307             } else {
4308                 ok(hr == prop.expected, "Error: GetAuthority returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
4309                         hr, prop.expected, i);
4310                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
4311                         prop.value, wine_dbgstr_w(received), i);
4312             }
4313             SysFreeString(received);
4314             received = NULL;
4315
4316             /* GetDisplayUri() tests. */
4317             prop = test.str_props[Uri_PROPERTY_DISPLAY_URI];
4318             hr = IUri_GetDisplayUri(uri, &received);
4319             if(prop.todo) {
4320                 todo_wine {
4321                     ok(hr == prop.expected, "Error: GetDisplayUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
4322                             hr, prop.expected, i);
4323                 }
4324                 todo_wine {
4325                     ok(!strcmp_aw(prop.value, received) || broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
4326                             "Error: Expected %s but got %s on uri_test[%d].\n",
4327                             prop.value, wine_dbgstr_w(received), i);
4328                 }
4329             } else {
4330                 ok(hr == prop.expected, "Error: GetDisplayUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
4331                         hr, prop.expected, i);
4332                 ok(!strcmp_aw(prop.value, received) || broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
4333                         "Error: Expected %s but got %s on uri_tests[%d].\n",
4334                         prop.value, wine_dbgstr_w(received), i);
4335             }
4336             SysFreeString(received);
4337             received = NULL;
4338
4339             /* GetDomain() tests. */
4340             prop = test.str_props[Uri_PROPERTY_DOMAIN];
4341             hr = IUri_GetDomain(uri, &received);
4342             if(prop.todo) {
4343                 todo_wine {
4344                     ok(hr == prop.expected, "Error: GetDomain returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
4345                             hr, prop.expected, i);
4346                 }
4347                 todo_wine {
4348                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
4349                             prop.value, wine_dbgstr_w(received), i);
4350                 }
4351             } else {
4352                 ok(hr == prop.expected, "Error: GetDomain returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
4353                         hr, prop.expected, i);
4354                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
4355                         prop.value, wine_dbgstr_w(received), i);
4356             }
4357             SysFreeString(received);
4358             received = NULL;
4359
4360             /* GetExtension() tests. */
4361             prop = test.str_props[Uri_PROPERTY_EXTENSION];
4362             hr = IUri_GetExtension(uri, &received);
4363             if(prop.todo) {
4364                 todo_wine {
4365                     ok(hr == prop.expected, "Error: GetExtension returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
4366                             hr, prop.expected, i);
4367                 }
4368                 todo_wine {
4369                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
4370                             prop.value, wine_dbgstr_w(received), i);
4371                 }
4372             } else {
4373                 ok(hr == prop.expected, "Error: GetExtension returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
4374                         hr, prop.expected, i);
4375                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
4376                         prop.value, wine_dbgstr_w(received), i);
4377             }
4378             SysFreeString(received);
4379             received = NULL;
4380
4381             /* GetFragment() tests. */
4382             prop = test.str_props[Uri_PROPERTY_FRAGMENT];
4383             hr = IUri_GetFragment(uri, &received);
4384             if(prop.todo) {
4385                 todo_wine {
4386                     ok(hr == prop.expected, "Error: GetFragment returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
4387                             hr, prop.expected, i);
4388                 }
4389                 todo_wine {
4390                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
4391                             prop.value, wine_dbgstr_w(received), i);
4392                 }
4393             } else {
4394                 ok(hr == prop.expected, "Error: GetFragment returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
4395                         hr, prop.expected, i);
4396                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
4397                         prop.value, wine_dbgstr_w(received), i);
4398             }
4399             SysFreeString(received);
4400             received = NULL;
4401
4402             /* GetHost() tests. */
4403             prop = test.str_props[Uri_PROPERTY_HOST];
4404             hr = IUri_GetHost(uri, &received);
4405             if(prop.todo) {
4406                 todo_wine {
4407                     ok(hr == prop.expected, "Error: GetHost returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
4408                             hr, prop.expected, i);
4409                 }
4410                 todo_wine {
4411                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
4412                             prop.value, wine_dbgstr_w(received), i);
4413                 }
4414             } else {
4415                 ok(hr == prop.expected, "Error: GetHost returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
4416                         hr, prop.expected, i);
4417                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
4418                         prop.value, wine_dbgstr_w(received), i);
4419             }
4420             SysFreeString(received);
4421             received = NULL;
4422
4423             /* GetPassword() tests. */
4424             prop = test.str_props[Uri_PROPERTY_PASSWORD];
4425             hr = IUri_GetPassword(uri, &received);
4426             if(prop.todo) {
4427                 todo_wine {
4428                     ok(hr == prop.expected, "Error: GetPassword returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
4429                             hr, prop.expected, i);
4430                 }
4431                 todo_wine {
4432                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
4433                             prop.value, wine_dbgstr_w(received), i);
4434                 }
4435             } else {
4436                 ok(hr == prop.expected, "Error: GetPassword returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
4437                         hr, prop.expected, i);
4438                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
4439                         prop.value, wine_dbgstr_w(received), i);
4440             }
4441             SysFreeString(received);
4442             received = NULL;
4443
4444             /* GetPath() tests. */
4445             prop = test.str_props[Uri_PROPERTY_PATH];
4446             hr = IUri_GetPath(uri, &received);
4447             if(prop.todo) {
4448                 todo_wine {
4449                     ok(hr == prop.expected, "Error: GetPath returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
4450                             hr, prop.expected, i);
4451                 }
4452                 todo_wine {
4453                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
4454                             prop.value, wine_dbgstr_w(received), i);
4455                 }
4456             } else {
4457                 ok(hr == prop.expected, "Error: GetPath returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
4458                         hr, prop.expected, i);
4459                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
4460                         prop.value, wine_dbgstr_w(received), i);
4461             }
4462             SysFreeString(received);
4463             received = NULL;
4464
4465             /* GetPathAndQuery() tests. */
4466             prop = test.str_props[Uri_PROPERTY_PATH_AND_QUERY];
4467             hr = IUri_GetPathAndQuery(uri, &received);
4468             if(prop.todo) {
4469                 todo_wine {
4470                     ok(hr == prop.expected, "Error: GetPathAndQuery returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
4471                             hr, prop.expected, i);
4472                 }
4473                 todo_wine {
4474                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
4475                             prop.value, wine_dbgstr_w(received), i);
4476                 }
4477             } else {
4478                 ok(hr == prop.expected, "Error: GetPathAndQuery returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
4479                         hr, prop.expected, i);
4480                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
4481                         prop.value, wine_dbgstr_w(received), i);
4482             }
4483             SysFreeString(received);
4484             received = NULL;
4485
4486             /* GetQuery() tests. */
4487             prop = test.str_props[Uri_PROPERTY_QUERY];
4488             hr = IUri_GetQuery(uri, &received);
4489             if(prop.todo) {
4490                 todo_wine {
4491                     ok(hr == prop.expected, "Error: GetQuery returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
4492                             hr, prop.expected, i);
4493                 }
4494                 todo_wine {
4495                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
4496                             prop.value, wine_dbgstr_w(received), i);
4497                 }
4498             } else {
4499                 ok(hr == prop.expected, "Error: GetQuery returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
4500                         hr, prop.expected, i);
4501                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
4502                         prop.value, wine_dbgstr_w(received), i);
4503             }
4504             SysFreeString(received);
4505             received = NULL;
4506
4507             /* GetRawUri() tests. */
4508             prop = test.str_props[Uri_PROPERTY_RAW_URI];
4509             hr = IUri_GetRawUri(uri, &received);
4510             if(prop.todo) {
4511                 todo_wine {
4512                     ok(hr == prop.expected, "Error: GetRawUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
4513                             hr, prop.expected, i);
4514                 }
4515                 todo_wine {
4516                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
4517                             prop.value, wine_dbgstr_w(received), i);
4518                 }
4519             } else {
4520                 ok(hr == prop.expected, "Error: GetRawUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
4521                         hr, prop.expected, i);
4522                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
4523                         prop.value, wine_dbgstr_w(received), i);
4524             }
4525             SysFreeString(received);
4526             received = NULL;
4527
4528             /* GetSchemeName() tests. */
4529             prop = test.str_props[Uri_PROPERTY_SCHEME_NAME];
4530             hr = IUri_GetSchemeName(uri, &received);
4531             if(prop.todo) {
4532                 todo_wine {
4533                     ok(hr == prop.expected, "Error: GetSchemeName returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
4534                             hr, prop.expected, i);
4535                 }
4536                 todo_wine {
4537                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
4538                             prop.value, wine_dbgstr_w(received), i);
4539                 }
4540             } else {
4541                 ok(hr == prop.expected, "Error: GetSchemeName returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
4542                         hr, prop.expected, i);
4543                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
4544                         prop.value, wine_dbgstr_w(received), i);
4545             }
4546             SysFreeString(received);
4547             received = NULL;
4548
4549             /* GetUserInfo() tests. */
4550             prop = test.str_props[Uri_PROPERTY_USER_INFO];
4551             hr = IUri_GetUserInfo(uri, &received);
4552             if(prop.todo) {
4553                 todo_wine {
4554                     ok(hr == prop.expected, "Error: GetUserInfo returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
4555                             hr, prop.expected, i);
4556                 }
4557                 todo_wine {
4558                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
4559                             prop.value, wine_dbgstr_w(received), i);
4560                 }
4561             } else {
4562                 ok(hr == prop.expected, "Error: GetUserInfo returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
4563                         hr, prop.expected, i);
4564                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
4565                         prop.value, wine_dbgstr_w(received), i);
4566             }
4567             SysFreeString(received);
4568             received = NULL;
4569
4570             /* GetUserName() tests. */
4571             prop = test.str_props[Uri_PROPERTY_USER_NAME];
4572             hr = IUri_GetUserName(uri, &received);
4573             if(prop.todo) {
4574                 todo_wine {
4575                     ok(hr == prop.expected, "Error: GetUserName returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
4576                             hr, prop.expected, i);
4577                 }
4578                 todo_wine {
4579                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
4580                             prop.value, wine_dbgstr_w(received), i);
4581                 }
4582             } else {
4583                 ok(hr == prop.expected, "Error: GetUserName returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
4584                         hr, prop.expected, i);
4585                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
4586                         prop.value, wine_dbgstr_w(received), i);
4587             }
4588             SysFreeString(received);
4589         }
4590
4591         if(uri) IUri_Release(uri);
4592
4593         heap_free(uriW);
4594     }
4595 }
4596
4597 static void test_IUri_GetDwordProperties(void) {
4598     IUri *uri = NULL;
4599     HRESULT hr;
4600     DWORD i;
4601
4602     /* Make sure all the 'Get*' dword property functions handle invalid args correctly. */
4603     hr = pCreateUri(http_urlW, 0, 0, &uri);
4604     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
4605     if(SUCCEEDED(hr)) {
4606         hr = IUri_GetHostType(uri, NULL);
4607         ok(hr == E_INVALIDARG, "Error: GetHostType returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
4608
4609         hr = IUri_GetPort(uri, NULL);
4610         ok(hr == E_INVALIDARG, "Error: GetPort returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
4611
4612         hr = IUri_GetScheme(uri, NULL);
4613         ok(hr == E_INVALIDARG, "Error: GetScheme returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
4614
4615         hr = IUri_GetZone(uri, NULL);
4616         ok(hr == E_INVALIDARG, "Error: GetZone returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
4617     }
4618     if(uri) IUri_Release(uri);
4619
4620     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
4621         uri_properties test = uri_tests[i];
4622         LPWSTR uriW;
4623         uri = NULL;
4624
4625         uriW = a2w(test.uri);
4626         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
4627         if(test.create_todo) {
4628             todo_wine {
4629                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
4630                         hr, test.create_expected, i);
4631             }
4632         } else {
4633             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
4634                     hr, test.create_expected, i);
4635         }
4636
4637         if(SUCCEEDED(hr)) {
4638             uri_dword_property prop;
4639             DWORD received;
4640
4641             /* Assign an insane value so tests don't accidentally pass when
4642              * they shouldn't!
4643              */
4644             received = -9999999;
4645
4646             /* GetHostType() tests. */
4647             prop = test.dword_props[Uri_PROPERTY_HOST_TYPE-Uri_PROPERTY_DWORD_START];
4648             hr = IUri_GetHostType(uri, &received);
4649             if(prop.todo) {
4650                 todo_wine {
4651                     ok(hr == prop.expected, "Error: GetHostType returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
4652                             hr, prop.expected, i);
4653                 }
4654                 todo_wine {
4655                     ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
4656                 }
4657             } else {
4658                 ok(hr == prop.expected, "Error: GetHostType returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
4659                         hr, prop.expected, i);
4660                 ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
4661             }
4662             received = -9999999;
4663
4664             /* GetPort() tests. */
4665             prop = test.dword_props[Uri_PROPERTY_PORT-Uri_PROPERTY_DWORD_START];
4666             hr = IUri_GetPort(uri, &received);
4667             if(prop.todo) {
4668                 todo_wine {
4669                     ok(hr == prop.expected, "Error: GetPort returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
4670                             hr, prop.expected, i);
4671                 }
4672                 todo_wine {
4673                     ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
4674                 }
4675             } else {
4676                 ok(hr == prop.expected, "Error: GetPort returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
4677                         hr, prop.expected, i);
4678                 ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
4679             }
4680             received = -9999999;
4681
4682             /* GetScheme() tests. */
4683             prop = test.dword_props[Uri_PROPERTY_SCHEME-Uri_PROPERTY_DWORD_START];
4684             hr = IUri_GetScheme(uri, &received);
4685             if(prop.todo) {
4686                 todo_wine {
4687                     ok(hr == prop.expected, "Error: GetScheme returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
4688                             hr, prop.expected, i);
4689                 }
4690                 todo_wine {
4691                     ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
4692                 }
4693             } else {
4694                 ok(hr == prop.expected, "Error: GetScheme returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
4695                         hr, prop.expected, i);
4696                 ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
4697             }
4698             received = -9999999;
4699
4700             /* GetZone() tests. */
4701             prop = test.dword_props[Uri_PROPERTY_ZONE-Uri_PROPERTY_DWORD_START];
4702             hr = IUri_GetZone(uri, &received);
4703             if(prop.todo) {
4704                 todo_wine {
4705                     ok(hr == prop.expected, "Error: GetZone returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
4706                             hr, prop.expected, i);
4707                 }
4708                 todo_wine {
4709                     ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
4710                 }
4711             } else {
4712                 ok(hr == prop.expected, "Error: GetZone returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
4713                         hr, prop.expected, i);
4714                 ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
4715             }
4716         }
4717
4718         if(uri) IUri_Release(uri);
4719
4720         heap_free(uriW);
4721     }
4722 }
4723
4724 static void test_IUri_GetPropertyLength(void) {
4725     IUri *uri = NULL;
4726     HRESULT hr;
4727     DWORD i;
4728
4729     /* Make sure it handles invalid args correctly. */
4730     hr = pCreateUri(http_urlW, 0, 0, &uri);
4731     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
4732     if(SUCCEEDED(hr)) {
4733         DWORD received = 0xdeadbeef;
4734
4735         hr = IUri_GetPropertyLength(uri, Uri_PROPERTY_STRING_START, NULL, 0);
4736         ok(hr == E_INVALIDARG, "Error: GetPropertyLength returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
4737
4738         hr = IUri_GetPropertyLength(uri, Uri_PROPERTY_DWORD_START, &received, 0);
4739         ok(hr == E_INVALIDARG, "Error: GetPropertyLength return 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
4740         ok(received == 0xdeadbeef, "Error: Expected 0xdeadbeef but got 0x%08x.\n", received);
4741     }
4742     if(uri) IUri_Release(uri);
4743
4744     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
4745         uri_properties test = uri_tests[i];
4746         LPWSTR uriW;
4747         uri = NULL;
4748
4749         uriW = a2w(test.uri);
4750         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
4751         if(test.create_todo) {
4752             todo_wine {
4753                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
4754                         hr, test.create_expected, i);
4755             }
4756         } else {
4757             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_test[%d].\n",
4758                     hr, test.create_expected, i);
4759         }
4760
4761         if(SUCCEEDED(hr)) {
4762             DWORD j;
4763
4764             for(j = Uri_PROPERTY_STRING_START; j <= Uri_PROPERTY_STRING_LAST; ++j) {
4765                 DWORD expectedLen, brokenLen, receivedLen;
4766                 uri_str_property prop = test.str_props[j];
4767
4768                 expectedLen = lstrlen(prop.value);
4769                 brokenLen = lstrlen(prop.broken_value);
4770
4771                 /* This won't be necessary once GetPropertyLength is implemented. */
4772                 receivedLen = -1;
4773
4774                 hr = IUri_GetPropertyLength(uri, j, &receivedLen, 0);
4775                 if(prop.todo) {
4776                     todo_wine {
4777                         ok(hr == prop.expected, "Error: GetPropertyLength returned 0x%08x, expected 0x%08x on uri_tests[%d].str_props[%d].\n",
4778                                 hr, prop.expected, i, j);
4779                     }
4780                     todo_wine {
4781                         ok(receivedLen == expectedLen || broken(receivedLen == brokenLen),
4782                                 "Error: Expected a length of %d but got %d on uri_tests[%d].str_props[%d].\n",
4783                                 expectedLen, receivedLen, i, j);
4784                     }
4785                 } else {
4786                     ok(hr == prop.expected, "Error: GetPropertyLength returned 0x%08x, expected 0x%08x on uri_tests[%d].str_props[%d].\n",
4787                             hr, prop.expected, i, j);
4788                     ok(receivedLen == expectedLen || broken(receivedLen == brokenLen),
4789                             "Error: Expected a length of %d but got %d on uri_tests[%d].str_props[%d].\n",
4790                             expectedLen, receivedLen, i, j);
4791                 }
4792             }
4793         }
4794
4795         if(uri) IUri_Release(uri);
4796
4797         heap_free(uriW);
4798     }
4799 }
4800
4801 static void test_IUri_GetProperties(void) {
4802     IUri *uri = NULL;
4803     HRESULT hr;
4804     DWORD i;
4805
4806     hr = pCreateUri(http_urlW, 0, 0, &uri);
4807     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
4808     if(SUCCEEDED(hr)) {
4809         hr = IUri_GetProperties(uri, NULL);
4810         ok(hr == E_INVALIDARG, "Error: GetProperties returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
4811     }
4812     if(uri) IUri_Release(uri);
4813
4814     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
4815         uri_properties test = uri_tests[i];
4816         LPWSTR uriW;
4817         uri = NULL;
4818
4819         uriW = a2w(test.uri);
4820         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
4821         if(test.create_todo) {
4822             todo_wine {
4823                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, test.create_expected);
4824             }
4825         } else {
4826             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, test.create_expected);
4827         }
4828
4829         if(SUCCEEDED(hr)) {
4830             DWORD received = 0;
4831             DWORD j;
4832
4833             hr = IUri_GetProperties(uri, &received);
4834             if(test.props_todo) {
4835                 todo_wine {
4836                     ok(hr == S_OK, "Error: GetProperties returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
4837                 }
4838             } else {
4839                 ok(hr == S_OK, "Error: GetProperties returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
4840             }
4841
4842             for(j = 0; j <= Uri_PROPERTY_DWORD_LAST; ++j) {
4843                 /* (1 << j) converts a Uri_PROPERTY to its corresponding Uri_HAS_* flag mask. */
4844                 if(test.props & (1 << j)) {
4845                     if(test.props_todo) {
4846                         todo_wine {
4847                             ok(received & (1 << j), "Error: Expected flag for property %d on uri_tests[%d].\n", j, i);
4848                         }
4849                     } else {
4850                         ok(received & (1 << j), "Error: Expected flag for property %d on uri_tests[%d].\n", j, i);
4851                     }
4852                 } else {
4853                     /* NOTE: Since received is initialized to 0, this test will always pass while
4854                      * GetProperties is unimplemented.
4855                      */
4856                     ok(!(received & (1 << j)), "Error: Received flag for property %d when not expected on uri_tests[%d].\n", j, i);
4857                 }
4858             }
4859         }
4860
4861         if(uri) IUri_Release(uri);
4862
4863         heap_free(uriW);
4864     }
4865 }
4866
4867 static void test_IUri_HasProperty(void) {
4868     IUri *uri = NULL;
4869     HRESULT hr;
4870     DWORD i;
4871
4872     hr = pCreateUri(http_urlW, 0, 0, &uri);
4873     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
4874     if(SUCCEEDED(hr)) {
4875         hr = IUri_HasProperty(uri, Uri_PROPERTY_RAW_URI, NULL);
4876         ok(hr == E_INVALIDARG, "Error: HasProperty returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
4877     }
4878     if(uri) IUri_Release(uri);
4879
4880     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
4881         uri_properties test = uri_tests[i];
4882         LPWSTR uriW;
4883         uri = NULL;
4884
4885         uriW = a2w(test.uri);
4886
4887         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
4888         if(test.create_todo) {
4889             todo_wine {
4890                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, test.create_expected);
4891             }
4892         } else {
4893             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, test.create_expected);
4894         }
4895
4896         if(SUCCEEDED(hr)) {
4897             DWORD j;
4898
4899             for(j = 0; j <= Uri_PROPERTY_DWORD_LAST; ++j) {
4900                 /* Assign -1, then explicitly test for TRUE or FALSE later. */
4901                 BOOL received = -1;
4902
4903                 hr = IUri_HasProperty(uri, j, &received);
4904                 if(test.props_todo) {
4905                     todo_wine {
4906                         ok(hr == S_OK, "Error: HasProperty returned 0x%08x, expected 0x%08x for property %d on uri_tests[%d].\n",
4907                                 hr, S_OK, j, i);
4908                     }
4909
4910                     /* Check if the property should be true. */
4911                     if(test.props & (1 << j)) {
4912                         todo_wine {
4913                             ok(received == TRUE, "Error: Expected to have property %d on uri_tests[%d].\n", j, i);
4914                         }
4915                     } else {
4916                         todo_wine {
4917                             ok(received == FALSE, "Error: Wasn't expecting to have property %d on uri_tests[%d].\n", j, i);
4918                         }
4919                     }
4920                 } else {
4921                     ok(hr == S_OK, "Error: HasProperty returned 0x%08x, expected 0x%08x for property %d on uri_tests[%d].\n",
4922                             hr, S_OK, j, i);
4923
4924                     if(test.props & (1 << j)) {
4925                         ok(received == TRUE, "Error: Expected to have property %d on uri_tests[%d].\n", j, i);
4926                     } else {
4927                         ok(received == FALSE, "Error: Wasn't expecting to have property %d on uri_tests[%d].\n", j, i);
4928                     }
4929                 }
4930             }
4931         }
4932
4933         if(uri) IUri_Release(uri);
4934
4935         heap_free(uriW);
4936     }
4937 }
4938
4939 static void test_IUri_IsEqual(void) {
4940     IUri *uriA, *uriB;
4941     HRESULT hrA, hrB;
4942     DWORD i;
4943
4944     uriA = uriB = NULL;
4945
4946     /* Make sure IsEqual handles invalid args correctly. */
4947     hrA = pCreateUri(http_urlW, 0, 0, &uriA);
4948     hrB = pCreateUri(http_urlW, 0, 0, &uriB);
4949     ok(hrA == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hrA, S_OK);
4950     ok(hrB == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hrB, S_OK);
4951     if(SUCCEEDED(hrA) && SUCCEEDED(hrB)) {
4952         BOOL equal = -1;
4953         hrA = IUri_IsEqual(uriA, NULL, &equal);
4954         ok(hrA == S_OK, "Error: IsEqual returned 0x%08x, expected 0x%08x.\n", hrA, S_OK);
4955         ok(equal == FALSE, "Error: Expected equal to be FALSE, but was %d instead.\n", equal);
4956
4957         hrA = IUri_IsEqual(uriA, uriB, NULL);
4958         ok(hrA == E_POINTER, "Error: IsEqual returned 0x%08x, expected 0x%08x.\n", hrA, E_POINTER);
4959     }
4960     if(uriA) IUri_Release(uriA);
4961     if(uriB) IUri_Release(uriB);
4962
4963     for(i = 0; i < sizeof(equality_tests)/sizeof(equality_tests[0]); ++i) {
4964         uri_equality test = equality_tests[i];
4965         LPWSTR uriA_W, uriB_W;
4966
4967         uriA = uriB = NULL;
4968
4969         uriA_W = a2w(test.a);
4970         uriB_W = a2w(test.b);
4971
4972         hrA = pCreateUri(uriA_W, test.create_flags_a, 0, &uriA);
4973         if(test.create_todo_a) {
4974             todo_wine {
4975                 ok(hrA == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x on equality_tests[%d].a\n",
4976                         hrA, S_OK, i);
4977             }
4978         } else {
4979             ok(hrA == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x on equality_tests[%d].a\n",
4980                     hrA, S_OK, i);
4981         }
4982
4983         hrB = pCreateUri(uriB_W, test.create_flags_b, 0, &uriB);
4984         if(test.create_todo_b) {
4985             todo_wine {
4986                 ok(hrB == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x on equality_tests[%d].b\n",
4987                         hrB, S_OK, i);
4988             }
4989         } else {
4990             ok(hrB == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x on equality_tests[%d].b\n",
4991                     hrB, S_OK, i);
4992         }
4993
4994         if(SUCCEEDED(hrA) && SUCCEEDED(hrB)) {
4995             BOOL equal = -1;
4996
4997             hrA = IUri_IsEqual(uriA, uriB, &equal);
4998             if(test.todo) {
4999                 todo_wine {
5000                     ok(hrA == S_OK, "Error: IsEqual returned 0x%08x, expected 0x%08x on equality_tests[%d].\n",
5001                             hrA, S_OK, i);
5002                 }
5003                 todo_wine {
5004                     ok(equal == test.equal, "Error: Expected the comparison to be %d on equality_tests[%d].\n", test.equal, i);
5005                 }
5006             } else {
5007                 ok(hrA == S_OK, "Error: IsEqual returned 0x%08x, expected 0x%08x on equality_tests[%d].\n", hrA, S_OK, i);
5008                 ok(equal == test.equal, "Error: Expected the comparison to be %d on equality_tests[%d].\n", test.equal, i);
5009             }
5010         }
5011         if(uriA) IUri_Release(uriA);
5012         if(uriB) IUri_Release(uriB);
5013
5014         heap_free(uriA_W);
5015         heap_free(uriB_W);
5016     }
5017 }
5018
5019 static void test_CreateUriWithFragment_InvalidArgs(void) {
5020     HRESULT hr;
5021     IUri *uri = (void*) 0xdeadbeef;
5022     const WCHAR fragmentW[] = {'#','f','r','a','g','m','e','n','t',0};
5023
5024     hr = pCreateUriWithFragment(NULL, fragmentW, 0, 0, &uri);
5025     ok(hr == E_INVALIDARG, "Error: CreateUriWithFragment returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
5026     ok(uri == NULL, "Error: Expected uri to be NULL, but was %p instead.\n", uri);
5027
5028     hr = pCreateUriWithFragment(http_urlW, fragmentW, 0, 0, NULL);
5029     ok(hr == E_INVALIDARG, "Error: CreateUriWithFragment returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
5030
5031     /* Original URI can't already contain a fragment component. */
5032     uri = (void*) 0xdeadbeef;
5033     hr = pCreateUriWithFragment(http_url_fragW, fragmentW, 0, 0, &uri);
5034     ok(hr == E_INVALIDARG, "Error: CreateUriWithFragment returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
5035     ok(uri == NULL, "Error: Expected uri to be NULL, but was %p instead.\n", uri);
5036 }
5037
5038 /* CreateUriWithFragment has the same invalid flag combinations as CreateUri. */
5039 static void test_CreateUriWithFragment_InvalidFlags(void) {
5040     DWORD i;
5041
5042     for(i = 0; i < sizeof(invalid_flag_tests)/sizeof(invalid_flag_tests[0]); ++i) {
5043         HRESULT hr;
5044         IUri *uri = (void*) 0xdeadbeef;
5045
5046         hr = pCreateUriWithFragment(http_urlW, NULL, invalid_flag_tests[i].flags, 0, &uri);
5047         ok(hr == invalid_flag_tests[i].expected, "Error: CreateUriWithFragment returned 0x%08x, expected 0x%08x. flags=0x%08x.\n",
5048             hr, invalid_flag_tests[i].expected, invalid_flag_tests[i].flags);
5049         ok(uri == NULL, "Error: Expected uri to be NULL, but was %p instead.\n", uri);
5050     }
5051 }
5052
5053 static void test_CreateUriWithFragment(void) {
5054     DWORD i;
5055
5056     for(i = 0; i < sizeof(uri_fragment_tests)/sizeof(uri_fragment_tests[0]); ++i) {
5057         HRESULT hr;
5058         IUri *uri = NULL;
5059         LPWSTR uriW, fragW;
5060         uri_with_fragment test = uri_fragment_tests[i];
5061
5062         uriW = a2w(test.uri);
5063         fragW = a2w(test.fragment);
5064
5065         hr = pCreateUriWithFragment(uriW, fragW, test.create_flags, 0, &uri);
5066         if(test.expected_todo) {
5067             todo_wine {
5068                 ok(hr == test.create_expected,
5069                     "Error: CreateUriWithFragment returned 0x%08x, expected 0x%08x on uri_fragment_tests[%d].\n",
5070                     hr, test.create_expected, i);
5071             }
5072         } else
5073             ok(hr == test.create_expected,
5074                 "Error: CreateUriWithFragment returned 0x%08x, expected 0x%08x on uri_fragment_tests[%d].\n",
5075                 hr, test.create_expected, i);
5076
5077         if(SUCCEEDED(hr)) {
5078             BSTR received = NULL;
5079
5080             hr = IUri_GetAbsoluteUri(uri, &received);
5081             if(test.expected_todo) {
5082                 todo_wine {
5083                     ok(hr == S_OK,
5084                         "Error: GetAbsoluteUri returned 0x%08x, expected 0x%08x on uri_fragment_tests[%d].\n",
5085                         hr, S_OK, i);
5086                 }
5087                 todo_wine {
5088                     ok(!strcmp_aw(test.expected_uri, received),
5089                         "Error: Expected %s but got %s on uri_fragment_tests[%d].\n",
5090                         test.expected_uri, wine_dbgstr_w(received), i);
5091                 }
5092             } else {
5093                 ok(hr == S_OK, "Error: GetAbsoluteUri returned 0x%08x, expected 0x%08x on uri_fragment_tests[%d].\n",
5094                     hr, S_OK, i);
5095                 ok(!strcmp_aw(test.expected_uri, received), "Error: Expected %s but got %s on uri_fragment_tests[%d].\n",
5096                     test.expected_uri, wine_dbgstr_w(received), i);
5097             }
5098
5099             SysFreeString(received);
5100         }
5101
5102         if(uri) IUri_Release(uri);
5103         heap_free(uriW);
5104     }
5105 }
5106
5107 static void test_CreateIUriBuilder(void) {
5108     HRESULT hr;
5109     IUriBuilder *builder = NULL;
5110     IUri *uri;
5111
5112     hr = pCreateIUriBuilder(NULL, 0, 0, NULL);
5113     ok(hr == E_POINTER, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x\n",
5114         hr, E_POINTER);
5115
5116     /* CreateIUriBuilder increases the ref count of the IUri it receives. */
5117     hr = pCreateUri(http_urlW, 0, 0, &uri);
5118     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
5119     if(SUCCEEDED(hr)) {
5120         ULONG cur_count, orig_count;
5121
5122         orig_count = get_refcnt(uri);
5123         hr = pCreateIUriBuilder(uri, 0, 0, &builder);
5124         ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
5125         ok(builder != NULL, "Error: Expecting builder not to be NULL\n");
5126
5127         cur_count = get_refcnt(uri);
5128         ok(cur_count == orig_count+1, "Error: Expected the ref count to be %u, but was %u instead.\n", orig_count+1, cur_count);
5129
5130         if(builder) IUriBuilder_Release(builder);
5131         cur_count = get_refcnt(uri);
5132         ok(cur_count == orig_count, "Error: Expected the ref count to be %u, but was %u instead.\n", orig_count, cur_count);
5133     }
5134     if(uri) IUri_Release(uri);
5135 }
5136
5137 static void test_IUriBuilder_CreateUri(IUriBuilder *builder, const uri_builder_test *test,
5138                                        DWORD test_index) {
5139     HRESULT hr;
5140     IUri *uri = NULL;
5141
5142     hr = IUriBuilder_CreateUri(builder, test->uri_flags, 0, 0, &uri);
5143     if(test->uri_todo) {
5144         todo_wine {
5145             ok(hr == test->uri_hres,
5146                 "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
5147                 hr, test->uri_hres, test_index);
5148         }
5149     } else {
5150         ok(hr == test->uri_hres,
5151             "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
5152             hr, test->uri_hres, test_index);
5153     }
5154
5155     if(SUCCEEDED(hr)) {
5156         BSTR received = NULL;
5157
5158         hr = IUri_GetAbsoluteUri(uri, &received);
5159         ok(hr == S_OK, "Error: IUri_GetAbsoluteUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
5160             hr, S_OK, test_index);
5161         ok(!strcmp_aw(test->uri_expected, received),
5162             "Error: Expected the URI to be %s but was %s instead on uri_builder_tests[%d].\n",
5163             test->uri_expected, wine_dbgstr_w(received), test_index);
5164         SysFreeString(received);
5165     }
5166     if(uri) IUri_Release(uri);
5167 }
5168
5169 static void test_IUriBuilder_CreateUriSimple(IUriBuilder *builder, const uri_builder_test *test,
5170                                        DWORD test_index) {
5171     HRESULT hr;
5172     IUri *uri = NULL;
5173
5174     hr = IUriBuilder_CreateUriSimple(builder, test->uri_simple_encode_flags, 0, &uri);
5175     if(test->uri_todo) {
5176         todo_wine {
5177             ok(hr == test->uri_simple_hres,
5178                 "Error: IUriBuilder_CreateUriSimple returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
5179                 hr, test->uri_simple_hres, test_index);
5180         }
5181     } else {
5182         ok(hr == test->uri_simple_hres,
5183             "Error: IUriBuilder_CreateUriSimple returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
5184             hr, test->uri_simple_hres, test_index);
5185     }
5186
5187     if(SUCCEEDED(hr)) {
5188         BSTR received = NULL;
5189
5190         hr = IUri_GetAbsoluteUri(uri, &received);
5191         ok(hr == S_OK, "Error: IUri_GetAbsoluteUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
5192             hr, S_OK, test_index);
5193         ok(!strcmp_aw(test->uri_simple_expected, received),
5194             "Error: Expected the URI to be %s but was %s instead on uri_builder_tests[%d].\n",
5195             test->uri_simple_expected, wine_dbgstr_w(received), test_index);
5196         SysFreeString(received);
5197     }
5198     if(uri) IUri_Release(uri);
5199 }
5200
5201 static void test_IUriBuilder_CreateUriWithFlags(IUriBuilder *builder, const uri_builder_test *test,
5202                                                 DWORD test_index) {
5203     HRESULT hr;
5204     IUri *uri = NULL;
5205
5206     hr = IUriBuilder_CreateUriWithFlags(builder, test->uri_with_flags, test->uri_with_builder_flags,
5207                                         test->uri_with_encode_flags, 0, &uri);
5208     if(test->uri_todo) {
5209         todo_wine {
5210             ok(hr == test->uri_with_hres,
5211                 "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
5212                 hr, test->uri_with_hres, test_index);
5213         }
5214     } else {
5215         ok(hr == test->uri_with_hres,
5216             "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
5217             hr, test->uri_with_hres, test_index);
5218     }
5219
5220     if(SUCCEEDED(hr)) {
5221         BSTR received = NULL;
5222
5223         hr = IUri_GetAbsoluteUri(uri, &received);
5224         ok(hr == S_OK, "Error: IUri_GetAbsoluteUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
5225             hr, S_OK, test_index);
5226         ok(!strcmp_aw(test->uri_with_expected, received),
5227             "Error: Expected the URI to be %s but was %s instead on uri_builder_tests[%d].\n",
5228             test->uri_with_expected, wine_dbgstr_w(received), test_index);
5229         SysFreeString(received);
5230     }
5231     if(uri) IUri_Release(uri);
5232 }
5233
5234 static void test_IUriBuilder_CreateInvalidArgs(void) {
5235     IUriBuilder *builder;
5236     HRESULT hr;
5237
5238     hr = pCreateIUriBuilder(NULL, 0, 0, &builder);
5239     ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
5240     if(SUCCEEDED(hr)) {
5241         IUri *test = NULL, *uri = (void*) 0xdeadbeef;
5242
5243         /* Test what happens if the IUriBuilder doesn't have a IUri set. */
5244         hr = IUriBuilder_CreateUri(builder, 0, 0, 0, &uri);
5245         ok(hr == INET_E_INVALID_URL, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, INET_E_INVALID_URL);
5246         ok(uri == NULL, "Error: Expected uri to be NULL, but was %p instead.\n", uri);
5247
5248         hr = IUriBuilder_CreateUri(builder, 0, 0, 0, NULL);
5249         ok(hr == E_POINTER, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
5250
5251         uri = (void*) 0xdeadbeef;
5252         hr = IUriBuilder_CreateUri(builder, 0, Uri_HAS_USER_NAME, 0, &uri);
5253         ok(hr == E_NOTIMPL, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, E_NOTIMPL);
5254         ok(uri == NULL, "Error: expected uri to be NULL, but was %p instead.\n", uri);
5255
5256         uri = (void*) 0xdeadbeef;
5257         hr = IUriBuilder_CreateUriSimple(builder, 0, 0, &uri);
5258         ok(hr == INET_E_INVALID_URL, "Error: IUriBuilder_CreateUriSimple returned 0x%08x, expected 0x%08x.\n",
5259             hr, INET_E_INVALID_URL);
5260         ok(!uri, "Error: Expected uri to be NULL, but was %p instead.\n", uri);
5261
5262         hr = IUriBuilder_CreateUriSimple(builder, 0, 0, NULL);
5263         ok(hr == E_POINTER, "Error: IUriBuilder_CreateUriSimple returned 0x%08x, expected 0x%08x.\n",
5264             hr, E_POINTER);
5265
5266         uri = (void*) 0xdeadbeef;
5267         hr = IUriBuilder_CreateUriSimple(builder, Uri_HAS_USER_NAME, 0, &uri);
5268         ok(hr == E_NOTIMPL, "Error: IUriBuilder_CreateUriSimple returned 0x%08x, expected 0x%08x.\n",
5269             hr, E_NOTIMPL);
5270         ok(!uri, "Error: Expected uri to NULL, but was %p instead.\n", uri);
5271
5272         uri = (void*) 0xdeadbeef;
5273         hr = IUriBuilder_CreateUriWithFlags(builder, 0, 0, 0, 0, &uri);
5274         ok(hr == INET_E_INVALID_URL,
5275             "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x.\n",
5276             hr, INET_E_INVALID_URL);
5277         ok(!uri, "Error: Expected uri to be NULL, but was %p instead.\n", uri);
5278
5279         hr = IUriBuilder_CreateUriWithFlags(builder, 0, 0, 0, 0, NULL);
5280         ok(hr == E_POINTER, "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x.\n",
5281             hr, E_POINTER);
5282
5283         uri = (void*) 0xdeadbeef;
5284         hr = IUriBuilder_CreateUriWithFlags(builder, 0, 0, Uri_HAS_USER_NAME, 0, &uri);
5285         ok(hr == E_NOTIMPL, "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x.\n",
5286             hr, E_NOTIMPL);
5287         ok(!uri, "Error: Expected uri to be NULL, but was %p instead.\n", uri);
5288
5289         hr = pCreateUri(http_urlW, 0, 0, &test);
5290         ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
5291         if(SUCCEEDED(hr)) {
5292             hr = IUriBuilder_SetIUri(builder, test);
5293             todo_wine { ok(hr == S_OK, "Error: IUriBuilder_SetIUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK); }
5294
5295             /* No longer returns E_NOTIMPL, since a IUri has been set and hasn't been modified. */
5296             uri = NULL;
5297             hr = IUriBuilder_CreateUri(builder, 0, Uri_HAS_USER_NAME, 0, &uri);
5298             todo_wine {
5299                 ok(hr == S_OK, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
5300             }
5301             todo_wine { ok(uri != NULL, "Error: The uri was NULL.\n"); }
5302             if(uri) IUri_Release(uri);
5303
5304             uri = NULL;
5305             hr = IUriBuilder_CreateUriSimple(builder, Uri_HAS_USER_NAME, 0, &uri);
5306             todo_wine {
5307                 ok(hr == S_OK, "Error: IUriBuilder_CreateUriSimple returned 0x%08x, expected 0x%08x.\n",
5308                     hr, S_OK);
5309             }
5310             todo_wine { ok(uri != NULL, "Error: uri was NULL.\n"); }
5311             if(uri) IUri_Release(uri);
5312
5313             uri = NULL;
5314             hr = IUriBuilder_CreateUriWithFlags(builder, 0, 0, 0, 0, &uri);
5315             todo_wine {
5316                 ok(hr == S_OK, "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x.\n",
5317                     hr, S_OK);
5318             }
5319             todo_wine { ok(uri != NULL, "Error: uri was NULL.\n"); }
5320             if(uri) IUri_Release(uri);
5321
5322             hr = IUriBuilder_SetFragment(builder, NULL);
5323             todo_wine { ok(hr == S_OK, "Error: IUriBuilder_SetFragment returned 0x%08x, expected 0x%08x.\n", hr, S_OK); }
5324
5325             /* The IUriBuilder is changed, so it returns E_NOTIMPL again. */
5326             uri = (void*) 0xdeadbeef;
5327             hr = IUriBuilder_CreateUri(builder, 0, Uri_HAS_USER_NAME, 0, &uri);
5328             ok(hr == E_NOTIMPL, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
5329             ok(!uri, "Error: Expected uri to be NULL but was %p instead.\n", uri);
5330
5331             uri = (void*) 0xdeadbeef;
5332             hr = IUriBuilder_CreateUriSimple(builder, Uri_HAS_USER_NAME, 0, &uri);
5333             ok(hr == E_NOTIMPL, "Error: IUriBuilder_CreateUriSimple returned 0x%08x, expected 0x%08x.\n",
5334                 hr, S_OK);
5335             ok(!uri, "Error: Expected uri to be NULL, but was %p instead.\n", uri);
5336
5337             uri = (void*) 0xdeadbeef;
5338             hr = IUriBuilder_CreateUriWithFlags(builder, 0, 0, Uri_HAS_USER_NAME, 0, &uri);
5339             ok(hr == E_NOTIMPL, "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x.\n",
5340                 hr, E_NOTIMPL);
5341             ok(!uri, "Error: Expected uri to be NULL, but was %p instead.\n", uri);
5342         }
5343         if(test) IUri_Release(test);
5344     }
5345     if(builder) IUriBuilder_Release(builder);
5346 }
5347
5348 /* Tests invalid args to the "Get*" functions. */
5349 static void test_IUriBuilder_GetInvalidArgs(void) {
5350     IUriBuilder *builder = NULL;
5351     HRESULT hr;
5352
5353     hr = pCreateIUriBuilder(NULL, 0, 0, &builder);
5354     ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
5355     if(SUCCEEDED(hr)) {
5356         LPCWSTR received = (void*) 0xdeadbeef;
5357         DWORD len = -1, port = -1;
5358         BOOL set = -1;
5359
5360         hr = IUriBuilder_GetFragment(builder, NULL, NULL);
5361         ok(hr == E_POINTER, "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x.\n",
5362             hr, E_POINTER);
5363         hr = IUriBuilder_GetFragment(builder, NULL, &received);
5364         ok(hr == E_POINTER, "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x.\n",
5365             hr, E_POINTER);
5366         ok(!received, "Error: Expected received to be NULL, but was %p instead.\n", received);
5367         hr = IUriBuilder_GetFragment(builder, &len, NULL);
5368         ok(hr == E_POINTER, "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x.\n",
5369             hr, E_POINTER);
5370         ok(!len, "Error: Expected len to be 0, but was %d instead.\n", len);
5371
5372         hr = IUriBuilder_GetHost(builder, NULL, NULL);
5373         ok(hr == E_POINTER, "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x.\n",
5374             hr, E_POINTER);
5375         received = (void*) 0xdeadbeef;
5376         hr = IUriBuilder_GetHost(builder, NULL, &received);
5377         ok(hr == E_POINTER, "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x.\n",
5378             hr, E_POINTER);
5379         ok(!received, "Error: Expected received to be NULL, but was %p instead.\n", received);
5380         len = -1;
5381         hr = IUriBuilder_GetHost(builder, &len, NULL);
5382         ok(hr == E_POINTER, "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x.\n",
5383             hr, E_POINTER);
5384         ok(!len, "Error: Expected len to be 0, but was %d instead.\n", len);
5385
5386         hr = IUriBuilder_GetPassword(builder, NULL, NULL);
5387         ok(hr == E_POINTER, "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x.\n",
5388             hr, E_POINTER);
5389         received = (void*) 0xdeadbeef;
5390         hr = IUriBuilder_GetPassword(builder, NULL, &received);
5391         ok(hr == E_POINTER, "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x.\n",
5392             hr, E_POINTER);
5393         ok(!received, "Error: Expected received to be NULL, but was %p instead.\n", received);
5394         len = -1;
5395         hr = IUriBuilder_GetPassword(builder, &len, NULL);
5396         ok(hr == E_POINTER, "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x.\n",
5397             hr, E_POINTER);
5398         ok(!len, "Error: Expected len to be 0, but was %d instead.\n", len);
5399
5400         hr = IUriBuilder_GetPath(builder, NULL, NULL);
5401         ok(hr == E_POINTER, "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x.\n",
5402             hr, E_POINTER);
5403         received = (void*) 0xdeadbeef;
5404         hr = IUriBuilder_GetPath(builder, NULL, &received);
5405         ok(hr == E_POINTER, "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x.\n",
5406             hr, E_POINTER);
5407         ok(!received, "Error: Expected received to be NULL, but was %p instead.\n", received);
5408         len = -1;
5409         hr = IUriBuilder_GetPath(builder, &len, NULL);
5410         ok(hr == E_POINTER, "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x.\n",
5411             hr, E_POINTER);
5412         ok(!len, "Error: Expected len to be 0, but was %d instead.\n", len);
5413
5414         hr = IUriBuilder_GetPort(builder, NULL, NULL);
5415         ok(hr == E_POINTER, "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x.\n",
5416             hr, E_POINTER);
5417         hr = IUriBuilder_GetPort(builder, NULL, &port);
5418         ok(hr == E_POINTER, "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x.\n",
5419             hr, E_POINTER);
5420         ok(!port, "Error: Expected port to be 0, but was %d instead.\n", port);
5421         hr = IUriBuilder_GetPort(builder, &set, NULL);
5422         ok(hr == E_POINTER, "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x.\n",
5423             hr, E_POINTER);
5424         ok(!set, "Error: Expected set to be FALSE, but was %d instead.\n", set);
5425
5426         hr = IUriBuilder_GetQuery(builder, NULL, NULL);
5427         ok(hr == E_POINTER, "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x.\n",
5428             hr, E_POINTER);
5429         received = (void*) 0xdeadbeef;
5430         hr = IUriBuilder_GetQuery(builder, NULL, &received);
5431         ok(hr == E_POINTER, "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x.\n",
5432             hr, E_POINTER);
5433         ok(!received, "Error: Expected received to be NULL, but was %p instead.\n", received);
5434         len = -1;
5435         hr = IUriBuilder_GetQuery(builder, &len, NULL);
5436         ok(hr == E_POINTER, "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x.\n",
5437             hr, E_POINTER);
5438         ok(!len, "Error: Expected len to be 0, but was %d instead.\n", len);
5439
5440         hr = IUriBuilder_GetSchemeName(builder, NULL, NULL);
5441         ok(hr == E_POINTER, "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x.\n",
5442             hr, E_POINTER);
5443         received = (void*) 0xdeadbeef;
5444         hr = IUriBuilder_GetSchemeName(builder, NULL, &received);
5445         ok(hr == E_POINTER, "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x.\n",
5446             hr, E_POINTER);
5447         ok(!received, "Error: Expected received to be NULL, but was %p instead.\n", received);
5448         len = -1;
5449         hr = IUriBuilder_GetSchemeName(builder, &len, NULL);
5450         ok(hr == E_POINTER, "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x.\n",
5451             hr, E_POINTER);
5452         ok(!len, "Error: Expected len to be 0, but was %d instead.\n", len);
5453
5454         hr = IUriBuilder_GetUserName(builder, NULL, NULL);
5455         ok(hr == E_POINTER, "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x.\n",
5456             hr, E_POINTER);
5457         received = (void*) 0xdeadbeef;
5458         hr = IUriBuilder_GetUserName(builder, NULL, &received);
5459         ok(hr == E_POINTER, "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x.\n",
5460             hr, E_POINTER);
5461         ok(!received, "Error: Expected received to be NULL, but was %p instead.\n", received);
5462         len = -1;
5463         hr = IUriBuilder_GetUserName(builder, &len, NULL);
5464         ok(hr == E_POINTER, "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x.\n",
5465             hr, E_POINTER);
5466         ok(!len, "Error: Expected len to be 0, but was %d instead.\n", len);
5467     }
5468     if(builder) IUriBuilder_Release(builder);
5469 }
5470
5471 static void test_IUriBuilder_GetFragment(IUriBuilder *builder, const uri_builder_test *test,
5472                                          DWORD test_index) {
5473     HRESULT hr;
5474     DWORD i;
5475     LPCWSTR received = NULL;
5476     DWORD len = -1;
5477     const uri_builder_property *prop = NULL;
5478
5479     /* Check if the property was set earlier. */
5480     for(i = 0; i < sizeof(test->properties)/sizeof(test->properties[0]); ++i) {
5481         if(test->properties[i].change && test->properties[i].property == Uri_PROPERTY_FRAGMENT)
5482             prop = &(test->properties[i]);
5483     }
5484
5485     if(prop) {
5486         /* Use expected_value unless it's NULL, then use value. */
5487         LPCSTR expected = prop->expected_value ? prop->expected_value : prop->value;
5488         hr = IUriBuilder_GetFragment(builder, &len, &received);
5489         if(prop->todo) {
5490             todo_wine {
5491                 ok(hr == (expected ? S_OK : S_FALSE),
5492                     "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
5493                     hr, (expected ? S_OK : S_FALSE), test_index);
5494             }
5495             if(SUCCEEDED(hr)) {
5496                 todo_wine {
5497                     ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
5498                         expected, wine_dbgstr_w(received), test_index);
5499                 }
5500                 todo_wine {
5501                     ok(lstrlen(expected) == len,
5502                         "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
5503                         lstrlen(expected), len, test_index);
5504                 }
5505             }
5506         } else {
5507             ok(hr == (expected ? S_OK : S_FALSE),
5508                 "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
5509                 hr, (expected ? S_OK : S_FALSE), test_index);
5510             ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
5511                 expected, wine_dbgstr_w(received), test_index);
5512             ok(lstrlen(expected) == len,
5513                 "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
5514                 lstrlen(expected), len, test_index);
5515         }
5516     } else {
5517         /* The property wasn't set earlier, so it should return whatever
5518          * the base IUri contains (if anything).
5519          */
5520         IUri *uri = NULL;
5521         hr = IUriBuilder_GetIUri(builder, &uri);
5522         todo_wine {
5523             ok(hr == S_OK,
5524                 "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
5525                 hr, S_OK, test_index);
5526         }
5527         if(SUCCEEDED(hr)) {
5528             BOOL has_prop = FALSE;
5529             BSTR expected = NULL;
5530
5531             hr = IUri_GetFragment(uri, &expected);
5532             ok(SUCCEEDED(hr),
5533                 "Error: Expected IUri_GetFragment to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
5534                 hr, test_index);
5535             has_prop = hr == S_OK;
5536
5537             hr = IUriBuilder_GetFragment(builder, &len, &received);
5538             if(has_prop) {
5539                 todo_wine {
5540                     ok(hr == S_OK,
5541                         "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
5542                         hr, S_OK, test_index);
5543                 }
5544                 if(SUCCEEDED(hr)) {
5545                     todo_wine {
5546                         ok(!lstrcmpW(expected, received),
5547                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].\n",
5548                             wine_dbgstr_w(expected), wine_dbgstr_w(received), test_index);
5549                     }
5550                     todo_wine {
5551                         ok(lstrlenW(expected) == len,
5552                             "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
5553                             lstrlenW(expected), len, test_index);
5554                     }
5555                 }
5556             } else {
5557                 todo_wine {
5558                     ok(hr == S_FALSE,
5559                         "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
5560                         hr, S_FALSE, test_index);
5561                 }
5562                 if(SUCCEEDED(hr)) {
5563                     todo_wine {
5564                         ok(!received, "Error: Expected received to be NULL on uri_builder_tests[%d].\n", test_index);
5565                     }
5566                     todo_wine {
5567                         ok(!len, "Error: Expected the length to be 0, but was %d instead on uri_builder_tests[%d].\n",
5568                             len, test_index);
5569                     }
5570                 }
5571             }
5572             SysFreeString(expected);
5573         }
5574         if(uri) IUri_Release(uri);
5575     }
5576 }
5577
5578 static void test_IUriBuilder_GetHost(IUriBuilder *builder, const uri_builder_test *test,
5579                                      DWORD test_index) {
5580     HRESULT hr;
5581     DWORD i;
5582     LPCWSTR received = NULL;
5583     DWORD len = -1;
5584     const uri_builder_property *prop = NULL;
5585
5586     /* Check if the property was set earlier. */
5587     for(i = 0; i < sizeof(test->properties)/sizeof(test->properties[0]); ++i) {
5588         if(test->properties[i].change && test->properties[i].property == Uri_PROPERTY_HOST)
5589             prop = &(test->properties[i]);
5590     }
5591
5592     if(prop) {
5593         /* Use expected_value unless it's NULL, then use value. */
5594         LPCSTR expected = prop->expected_value ? prop->expected_value : prop->value;
5595         hr = IUriBuilder_GetHost(builder, &len, &received);
5596         if(prop->todo) {
5597             todo_wine {
5598                 ok(hr == (expected ? S_OK : S_FALSE),
5599                     "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
5600                     hr, (expected ? S_OK : S_FALSE), test_index);
5601             }
5602             if(SUCCEEDED(hr)) {
5603                 todo_wine {
5604                     ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
5605                         expected, wine_dbgstr_w(received), test_index);
5606                 }
5607                 todo_wine {
5608                     ok(lstrlen(expected) == len,
5609                         "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
5610                         lstrlen(expected), len, test_index);
5611                 }
5612             }
5613         } else {
5614             ok(hr == (expected ? S_OK : S_FALSE),
5615                 "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
5616                 hr, (expected ? S_OK : S_FALSE), test_index);
5617             ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
5618                 expected, wine_dbgstr_w(received), test_index);
5619             ok(lstrlen(expected) == len,
5620                 "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
5621                 lstrlen(expected), len, test_index);
5622         }
5623     } else {
5624         /* The property wasn't set earlier, so it should return whatever
5625          * the base IUri contains (if anything).
5626          */
5627         IUri *uri = NULL;
5628         hr = IUriBuilder_GetIUri(builder, &uri);
5629         todo_wine {
5630             ok(hr == S_OK,
5631                 "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
5632                 hr, S_OK, test_index);
5633         }
5634         if(SUCCEEDED(hr)) {
5635             BOOL has_prop = FALSE;
5636             BSTR expected = NULL;
5637
5638             hr = IUri_GetHost(uri, &expected);
5639             ok(SUCCEEDED(hr),
5640                 "Error: Expected IUri_GetHost to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
5641                 hr, test_index);
5642             has_prop = hr == S_OK;
5643
5644             hr = IUriBuilder_GetHost(builder, &len, &received);
5645             if(has_prop) {
5646                 todo_wine {
5647                     ok(hr == S_OK,
5648                         "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
5649                         hr, S_OK, test_index);
5650                 }
5651                 if(SUCCEEDED(hr)) {
5652                     todo_wine {
5653                         ok(!lstrcmpW(expected, received),
5654                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].\n",
5655                             wine_dbgstr_w(expected), wine_dbgstr_w(received), test_index);
5656                     }
5657                     todo_wine {
5658                         ok(lstrlenW(expected) == len,
5659                             "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
5660                             lstrlenW(expected), len, test_index);
5661                     }
5662                 }
5663             } else {
5664                 todo_wine {
5665                     ok(hr == S_FALSE,
5666                         "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
5667                         hr, S_FALSE, test_index);
5668                 }
5669                 if(SUCCEEDED(hr)) {
5670                     todo_wine {
5671                         ok(!received, "Error: Expected received to be NULL on uri_builder_tests[%d].\n", test_index);
5672                     }
5673                     todo_wine {
5674                         ok(!len, "Error: Expected the length to be 0, but was %d instead on uri_builder_tests[%d].\n",
5675                             len, test_index);
5676                     }
5677                 }
5678             }
5679             SysFreeString(expected);
5680         }
5681         if(uri) IUri_Release(uri);
5682     }
5683 }
5684
5685 static void test_IUriBuilder_GetPassword(IUriBuilder *builder, const uri_builder_test *test,
5686                                          DWORD test_index) {
5687     HRESULT hr;
5688     DWORD i;
5689     LPCWSTR received = NULL;
5690     DWORD len = -1;
5691     const uri_builder_property *prop = NULL;
5692
5693     /* Check if the property was set earlier. */
5694     for(i = 0; i < sizeof(test->properties)/sizeof(test->properties[0]); ++i) {
5695         if(test->properties[i].change && test->properties[i].property == Uri_PROPERTY_PASSWORD)
5696             prop = &(test->properties[i]);
5697     }
5698
5699     if(prop) {
5700         /* Use expected_value unless it's NULL, then use value. */
5701         LPCSTR expected = prop->expected_value ? prop->expected_value : prop->value;
5702         hr = IUriBuilder_GetPassword(builder, &len, &received);
5703         if(prop->todo) {
5704             todo_wine {
5705                 ok(hr == (expected ? S_OK : S_FALSE),
5706                     "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
5707                     hr, (expected ? S_OK : S_FALSE), test_index);
5708             }
5709             if(SUCCEEDED(hr)) {
5710                 todo_wine {
5711                     ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
5712                         expected, wine_dbgstr_w(received), test_index);
5713                 }
5714                 todo_wine {
5715                     ok(lstrlen(expected) == len,
5716                         "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
5717                         lstrlen(expected), len, test_index);
5718                 }
5719             }
5720         } else {
5721             ok(hr == (expected ? S_OK : S_FALSE),
5722                 "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
5723                 hr, (expected ? S_OK : S_FALSE), test_index);
5724             ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
5725                 expected, wine_dbgstr_w(received), test_index);
5726             ok(lstrlen(expected) == len,
5727                 "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
5728                 lstrlen(expected), len, test_index);
5729         }
5730     } else {
5731         /* The property wasn't set earlier, so it should return whatever
5732          * the base IUri contains (if anything).
5733          */
5734         IUri *uri = NULL;
5735         hr = IUriBuilder_GetIUri(builder, &uri);
5736         todo_wine {
5737             ok(hr == S_OK,
5738                 "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
5739                 hr, S_OK, test_index);
5740         }
5741         if(SUCCEEDED(hr)) {
5742             BOOL has_prop = FALSE;
5743             BSTR expected = NULL;
5744
5745             hr = IUri_GetPassword(uri, &expected);
5746             ok(SUCCEEDED(hr),
5747                 "Error: Expected IUri_GetPassword to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
5748                 hr, test_index);
5749             has_prop = hr == S_OK;
5750
5751             hr = IUriBuilder_GetPassword(builder, &len, &received);
5752             if(has_prop) {
5753                 todo_wine {
5754                     ok(hr == S_OK,
5755                         "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
5756                         hr, S_OK, test_index);
5757                 }
5758                 if(SUCCEEDED(hr)) {
5759                     todo_wine {
5760                         ok(!lstrcmpW(expected, received),
5761                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].\n",
5762                             wine_dbgstr_w(expected), wine_dbgstr_w(received), test_index);
5763                     }
5764                     todo_wine {
5765                         ok(lstrlenW(expected) == len,
5766                             "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
5767                             lstrlenW(expected), len, test_index);
5768                     }
5769                 }
5770             } else {
5771                 todo_wine {
5772                     ok(hr == S_FALSE,
5773                         "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
5774                         hr, S_FALSE, test_index);
5775                 }
5776                 if(SUCCEEDED(hr)) {
5777                     todo_wine {
5778                         ok(!received, "Error: Expected received to be NULL on uri_builder_tests[%d].\n", test_index);
5779                     }
5780                     todo_wine {
5781                         ok(!len, "Error: Expected the length to be 0, but was %d instead on uri_builder_tests[%d].\n",
5782                             len, test_index);
5783                     }
5784                 }
5785             }
5786             SysFreeString(expected);
5787         }
5788         if(uri) IUri_Release(uri);
5789     }
5790 }
5791
5792 static void test_IUriBuilder_GetPath(IUriBuilder *builder, const uri_builder_test *test,
5793                                      DWORD test_index) {
5794     HRESULT hr;
5795     DWORD i;
5796     LPCWSTR received = NULL;
5797     DWORD len = -1;
5798     const uri_builder_property *prop = NULL;
5799
5800     /* Check if the property was set earlier. */
5801     for(i = 0; i < sizeof(test->properties)/sizeof(test->properties[0]); ++i) {
5802         if(test->properties[i].change && test->properties[i].property == Uri_PROPERTY_PATH)
5803             prop = &(test->properties[i]);
5804     }
5805
5806     if(prop) {
5807         /* Use expected_value unless it's NULL, then use value. */
5808         LPCSTR expected = prop->expected_value ? prop->expected_value : prop->value;
5809         hr = IUriBuilder_GetPath(builder, &len, &received);
5810         if(prop->todo) {
5811             todo_wine {
5812                 ok(hr == (expected ? S_OK : S_FALSE),
5813                     "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
5814                     hr, (expected ? S_OK : S_FALSE), test_index);
5815             }
5816             if(SUCCEEDED(hr)) {
5817                 todo_wine {
5818                     ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
5819                         expected, wine_dbgstr_w(received), test_index);
5820                 }
5821                 todo_wine {
5822                     ok(lstrlen(expected) == len,
5823                         "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
5824                         lstrlen(expected), len, test_index);
5825                 }
5826             }
5827         } else {
5828             ok(hr == (expected ? S_OK : S_FALSE),
5829                 "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
5830                 hr, (expected ? S_OK : S_FALSE), test_index);
5831             ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
5832                 expected, wine_dbgstr_w(received), test_index);
5833             ok(lstrlen(expected) == len,
5834                 "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
5835                 lstrlen(expected), len, test_index);
5836         }
5837     } else {
5838         /* The property wasn't set earlier, so it should return whatever
5839          * the base IUri contains (if anything).
5840          */
5841         IUri *uri = NULL;
5842         hr = IUriBuilder_GetIUri(builder, &uri);
5843         todo_wine {
5844             ok(hr == S_OK,
5845                 "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
5846                 hr, S_OK, test_index);
5847         }
5848         if(SUCCEEDED(hr)) {
5849             BOOL has_prop = FALSE;
5850             BSTR expected = NULL;
5851
5852             hr = IUri_GetPath(uri, &expected);
5853             ok(SUCCEEDED(hr),
5854                 "Error: Expected IUri_GetPath to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
5855                 hr, test_index);
5856             has_prop = hr == S_OK;
5857
5858             hr = IUriBuilder_GetPath(builder, &len, &received);
5859             if(has_prop) {
5860                 todo_wine {
5861                     ok(hr == S_OK,
5862                         "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
5863                         hr, S_OK, test_index);
5864                 }
5865                 if(SUCCEEDED(hr)) {
5866                     todo_wine {
5867                         ok(!lstrcmpW(expected, received),
5868                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].\n",
5869                             wine_dbgstr_w(expected), wine_dbgstr_w(received), test_index);
5870                     }
5871                     todo_wine {
5872                         ok(lstrlenW(expected) == len,
5873                             "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
5874                             lstrlenW(expected), len, test_index);
5875                     }
5876                 }
5877             } else {
5878                 todo_wine {
5879                     ok(hr == S_FALSE,
5880                         "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
5881                         hr, S_FALSE, test_index);
5882                 }
5883                 if(SUCCEEDED(hr)) {
5884                     todo_wine {
5885                         ok(!received, "Error: Expected received to be NULL on uri_builder_tests[%d].\n", test_index);
5886                     }
5887                     todo_wine {
5888                         ok(!len, "Error: Expected the length to be 0, but was %d instead on uri_builder_tests[%d].\n",
5889                             len, test_index);
5890                     }
5891                 }
5892             }
5893             SysFreeString(expected);
5894         }
5895         if(uri) IUri_Release(uri);
5896     }
5897 }
5898
5899 static void test_IUriBuilder_GetPort(IUriBuilder *builder, const uri_builder_test *test,
5900                                      DWORD test_index) {
5901     HRESULT hr;
5902     BOOL has_port = FALSE;
5903     DWORD received = -1;
5904
5905     if(test->port_prop.change) {
5906         DWORD expected = test->port_prop.value;
5907
5908         hr = IUriBuilder_GetPort(builder, &has_port, &received);
5909         if(test->port_prop.todo) {
5910             todo_wine {
5911                 ok(hr == S_OK,
5912                     "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
5913                     hr, S_OK, test_index);
5914             }
5915             if(SUCCEEDED(hr)) {
5916                 todo_wine {
5917                     ok(has_port == test->port_prop.set,
5918                         "Error: Expected has_port to be %d but was %d instead on uri_builder_tests[%d].\n",
5919                         test->port_prop.set, has_port, test_index);
5920                 }
5921                 todo_wine {
5922                     ok(received == expected,
5923                         "Error: Expected received to be %d, but was %d instead on uri_builder_tests[%d].\n",
5924                         expected, received, test_index);
5925                 }
5926             }
5927         } else {
5928             ok(hr == S_OK,
5929                 "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
5930                 hr, S_OK, test_index);
5931             ok(has_port == test->port_prop.set,
5932                 "Error: Expected has_port to be %d, but was %d instead on uri_builder_tests[%d].\n",
5933                 test->port_prop.set, has_port, test_index);
5934             ok(received == test->port_prop.value,
5935                 "Error: Expected port to be %d, but was %d instead on uri_builder_tests[%d].\n",
5936                 test->port_prop.value, received, test_index);
5937         }
5938     } else {
5939         IUri *uri = NULL;
5940
5941         hr = IUriBuilder_GetIUri(builder, &uri);
5942         todo_wine {
5943             ok(hr == S_OK,
5944                 "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
5945                 hr, S_OK, test_index);
5946         }
5947         if(SUCCEEDED(hr)) {
5948             DWORD expected;
5949             BOOL got_port = FALSE;
5950
5951             hr = IUri_GetPort(uri, &expected);
5952             ok(SUCCEEDED(hr),
5953                 "Error: Expected IUri_Port to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
5954                 hr, test_index);
5955             got_port = hr == S_OK;
5956
5957             hr = IUriBuilder_GetPort(builder, &has_port, &received);
5958             todo_wine {
5959                 ok(hr == S_OK,
5960                     "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
5961                     hr, S_OK, test_index);
5962             }
5963             if(SUCCEEDED(hr)) {
5964                 todo_wine {
5965                     ok(!has_port,
5966                         "Error: Expected has_port to be FALSE but was TRUE instead on uri_builder_tests[%d].\n",
5967                         test_index);
5968                 }
5969                 todo_wine {
5970                     ok(received == expected,
5971                         "Error: Expected received to be %d, but was %d instead on uri_builder_tests[%d].\n",
5972                         expected, received, test_index);
5973                 }
5974             }
5975         }
5976         if(uri) IUri_Release(uri);
5977     }
5978 }
5979
5980 static void test_IUriBuilder_GetQuery(IUriBuilder *builder, const uri_builder_test *test,
5981                                       DWORD test_index) {
5982     HRESULT hr;
5983     DWORD i;
5984     LPCWSTR received = NULL;
5985     DWORD len = -1;
5986     const uri_builder_property *prop = NULL;
5987
5988     /* Check if the property was set earlier. */
5989     for(i = 0; i < sizeof(test->properties)/sizeof(test->properties[0]); ++i) {
5990         if(test->properties[i].change && test->properties[i].property == Uri_PROPERTY_QUERY)
5991             prop = &(test->properties[i]);
5992     }
5993
5994     if(prop) {
5995         /* Use expected_value unless it's NULL, then use value. */
5996         LPCSTR expected = prop->expected_value ? prop->expected_value : prop->value;
5997         hr = IUriBuilder_GetQuery(builder, &len, &received);
5998         if(prop->todo) {
5999             todo_wine {
6000                 ok(hr == (expected ? S_OK : S_FALSE),
6001                     "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6002                     hr, (expected ? S_OK : S_FALSE), test_index);
6003             }
6004             if(SUCCEEDED(hr)) {
6005                 todo_wine {
6006                     ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
6007                         expected, wine_dbgstr_w(received), test_index);
6008                 }
6009                 todo_wine {
6010                     ok(lstrlen(expected) == len,
6011                         "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
6012                         lstrlen(expected), len, test_index);
6013                 }
6014             }
6015         } else {
6016             ok(hr == (expected ? S_OK : S_FALSE),
6017                 "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6018                 hr, (expected ? S_OK : S_FALSE), test_index);
6019             ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
6020                 expected, wine_dbgstr_w(received), test_index);
6021             ok(lstrlen(expected) == len,
6022                 "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
6023                 lstrlen(expected), len, test_index);
6024         }
6025     } else {
6026         /* The property wasn't set earlier, so it should return whatever
6027          * the base IUri contains (if anything).
6028          */
6029         IUri *uri = NULL;
6030         hr = IUriBuilder_GetIUri(builder, &uri);
6031         todo_wine {
6032             ok(hr == S_OK,
6033                 "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6034                 hr, S_OK, test_index);
6035         }
6036         if(SUCCEEDED(hr)) {
6037             BOOL has_prop = FALSE;
6038             BSTR expected = NULL;
6039
6040             hr = IUri_GetQuery(uri, &expected);
6041             ok(SUCCEEDED(hr),
6042                 "Error: Expected IUri_GetQuery to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
6043                 hr, test_index);
6044             has_prop = hr == S_OK;
6045
6046             hr = IUriBuilder_GetQuery(builder, &len, &received);
6047             if(has_prop) {
6048                 todo_wine {
6049                     ok(hr == S_OK,
6050                         "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6051                         hr, S_OK, test_index);
6052                 }
6053                 if(SUCCEEDED(hr)) {
6054                     todo_wine {
6055                         ok(!lstrcmpW(expected, received),
6056                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].\n",
6057                             wine_dbgstr_w(expected), wine_dbgstr_w(received), test_index);
6058                     }
6059                     todo_wine {
6060                         ok(lstrlenW(expected) == len,
6061                             "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
6062                             lstrlenW(expected), len, test_index);
6063                     }
6064                 }
6065             } else {
6066                 todo_wine {
6067                     ok(hr == S_FALSE,
6068                         "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6069                         hr, S_FALSE, test_index);
6070                 }
6071                 if(SUCCEEDED(hr)) {
6072                     todo_wine {
6073                         ok(!received, "Error: Expected received to be NULL on uri_builder_tests[%d].\n", test_index);
6074                     }
6075                     todo_wine {
6076                         ok(!len, "Error: Expected the length to be 0, but was %d instead on uri_builder_tests[%d].\n",
6077                             len, test_index);
6078                     }
6079                 }
6080             }
6081             SysFreeString(expected);
6082         }
6083         if(uri) IUri_Release(uri);
6084     }
6085 }
6086
6087 static void test_IUriBuilder_GetSchemeName(IUriBuilder *builder, const uri_builder_test *test,
6088                                            DWORD test_index) {
6089     HRESULT hr;
6090     DWORD i;
6091     LPCWSTR received = NULL;
6092     DWORD len = -1;
6093     const uri_builder_property *prop = NULL;
6094
6095     /* Check if the property was set earlier. */
6096     for(i = 0; i < sizeof(test->properties)/sizeof(test->properties[0]); ++i) {
6097         if(test->properties[i].change && test->properties[i].property == Uri_PROPERTY_SCHEME_NAME)
6098             prop = &(test->properties[i]);
6099     }
6100
6101     if(prop) {
6102         /* Use expected_value unless it's NULL, then use value. */
6103         LPCSTR expected = prop->expected_value ? prop->expected_value : prop->value;
6104         hr = IUriBuilder_GetSchemeName(builder, &len, &received);
6105         if(prop->todo) {
6106             todo_wine {
6107                 ok(hr == (expected ? S_OK : S_FALSE),
6108                     "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6109                     hr, (expected ? S_OK : S_FALSE), test_index);
6110             }
6111             if(SUCCEEDED(hr)) {
6112                 todo_wine {
6113                     ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
6114                         expected, wine_dbgstr_w(received), test_index);
6115                 }
6116                 todo_wine {
6117                     ok(lstrlen(expected) == len,
6118                         "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
6119                         lstrlen(expected), len, test_index);
6120                 }
6121             }
6122         } else {
6123             ok(hr == (expected ? S_OK : S_FALSE),
6124                 "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6125                 hr, (expected ? S_OK : S_FALSE), test_index);
6126             ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
6127                 expected, wine_dbgstr_w(received), test_index);
6128             ok(lstrlen(expected) == len,
6129                 "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
6130                 lstrlen(expected), len, test_index);
6131         }
6132     } else {
6133         /* The property wasn't set earlier, so it should return whatever
6134          * the base IUri contains (if anything).
6135          */
6136         IUri *uri = NULL;
6137         hr = IUriBuilder_GetIUri(builder, &uri);
6138         todo_wine {
6139             ok(hr == S_OK,
6140                 "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6141                 hr, S_OK, test_index);
6142         }
6143         if(SUCCEEDED(hr)) {
6144             BOOL has_prop = FALSE;
6145             BSTR expected = NULL;
6146
6147             hr = IUri_GetSchemeName(uri, &expected);
6148             ok(SUCCEEDED(hr),
6149                 "Error: Expected IUri_GetSchemeName to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
6150                 hr, test_index);
6151             has_prop = hr == S_OK;
6152
6153             hr = IUriBuilder_GetSchemeName(builder, &len, &received);
6154             if(has_prop) {
6155                 todo_wine {
6156                     ok(hr == S_OK,
6157                         "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6158                         hr, S_OK, test_index);
6159                 }
6160                 if(SUCCEEDED(hr)) {
6161                     todo_wine {
6162                         ok(!lstrcmpW(expected, received),
6163                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].\n",
6164                             wine_dbgstr_w(expected), wine_dbgstr_w(received), test_index);
6165                     }
6166                     todo_wine {
6167                         ok(lstrlenW(expected) == len,
6168                             "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
6169                             lstrlenW(expected), len, test_index);
6170                     }
6171                 }
6172             } else {
6173                 todo_wine {
6174                     ok(hr == S_FALSE,
6175                         "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6176                         hr, S_FALSE, test_index);
6177                 }
6178                 if(SUCCEEDED(hr)) {
6179                     todo_wine {
6180                         ok(!received, "Error: Expected received to be NULL on uri_builder_tests[%d].\n", test_index);
6181                     }
6182                     todo_wine {
6183                         ok(!len, "Error: Expected the length to be 0, but was %d instead on uri_builder_tests[%d].\n",
6184                             len, test_index);
6185                     }
6186                 }
6187             }
6188             SysFreeString(expected);
6189         }
6190         if(uri) IUri_Release(uri);
6191     }
6192 }
6193
6194 static void test_IUriBuilder_GetUserName(IUriBuilder *builder, const uri_builder_test *test,
6195                                          DWORD test_index) {
6196     HRESULT hr;
6197     DWORD i;
6198     LPCWSTR received = NULL;
6199     DWORD len = -1;
6200     const uri_builder_property *prop = NULL;
6201
6202     /* Check if the property was set earlier. */
6203     for(i = 0; i < sizeof(test->properties)/sizeof(test->properties[0]); ++i) {
6204         if(test->properties[i].change && test->properties[i].property == Uri_PROPERTY_USER_NAME)
6205             prop = &(test->properties[i]);
6206     }
6207
6208     if(prop) {
6209         /* Use expected_value unless it's NULL, then use value. */
6210         LPCSTR expected = prop->expected_value ? prop->expected_value : prop->value;
6211         hr = IUriBuilder_GetUserName(builder, &len, &received);
6212         if(prop->todo) {
6213             todo_wine {
6214                 ok(hr == (expected ? S_OK : S_FALSE),
6215                     "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6216                     hr, (expected ? S_OK : S_FALSE), test_index);
6217             }
6218             if(SUCCEEDED(hr)) {
6219                 todo_wine {
6220                     ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
6221                         expected, wine_dbgstr_w(received), test_index);
6222                 }
6223                 todo_wine {
6224                     ok(lstrlen(expected) == len,
6225                         "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
6226                         lstrlen(expected), len, test_index);
6227                 }
6228             }
6229         } else {
6230             ok(hr == (expected ? S_OK : S_FALSE),
6231                 "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6232                 hr, (expected ? S_OK : S_FALSE), test_index);
6233             ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
6234                 expected, wine_dbgstr_w(received), test_index);
6235             ok(lstrlen(expected) == len,
6236                 "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
6237                 lstrlen(expected), len, test_index);
6238         }
6239     } else {
6240         /* The property wasn't set earlier, so it should return whatever
6241          * the base IUri contains (if anything).
6242          */
6243         IUri *uri = NULL;
6244         hr = IUriBuilder_GetIUri(builder, &uri);
6245         todo_wine {
6246             ok(hr == S_OK,
6247                 "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6248                 hr, S_OK, test_index);
6249         }
6250         if(SUCCEEDED(hr)) {
6251             BOOL has_prop = FALSE;
6252             BSTR expected = NULL;
6253
6254             hr = IUri_GetUserName(uri, &expected);
6255             ok(SUCCEEDED(hr),
6256                 "Error: Expected IUri_GetUserName to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
6257                 hr, test_index);
6258             has_prop = hr == S_OK;
6259
6260             hr = IUriBuilder_GetUserName(builder, &len, &received);
6261             if(has_prop) {
6262                 todo_wine {
6263                     ok(hr == S_OK,
6264                         "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6265                         hr, S_OK, test_index);
6266                 }
6267                 if(SUCCEEDED(hr)) {
6268                     todo_wine {
6269                         ok(!lstrcmpW(expected, received),
6270                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].\n",
6271                             wine_dbgstr_w(expected), wine_dbgstr_w(received), test_index);
6272                     }
6273                     todo_wine {
6274                         ok(lstrlenW(expected) == len,
6275                             "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
6276                             lstrlenW(expected), len, test_index);
6277                     }
6278                 }
6279             } else {
6280                 todo_wine {
6281                     ok(hr == S_FALSE,
6282                         "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6283                         hr, S_FALSE, test_index);
6284                 }
6285                 if(SUCCEEDED(hr)) {
6286                     todo_wine {
6287                         ok(!received, "Error: Expected received to be NULL on uri_builder_tests[%d].\n", test_index);
6288                     }
6289                     todo_wine {
6290                         ok(!len, "Error: Expected the length to be 0, but was %d instead on uri_builder_tests[%d].\n",
6291                             len, test_index);
6292                     }
6293                 }
6294             }
6295             SysFreeString(expected);
6296         }
6297         if(uri) IUri_Release(uri);
6298     }
6299 }
6300
6301 /* Tests IUriBuilder functions. */
6302 static void test_IUriBuilder(void) {
6303     HRESULT hr;
6304     IUriBuilder *builder;
6305     DWORD i;
6306
6307     for(i = 0; i < sizeof(uri_builder_tests)/sizeof(uri_builder_tests[0]); ++i) {
6308         IUri *uri;
6309         uri_builder_test test = uri_builder_tests[i];
6310         LPWSTR uriW;
6311
6312         uriW = a2w(test.uri);
6313         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
6314         ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6315             hr, S_OK, i);
6316         if(SUCCEEDED(hr)) {
6317             hr = pCreateIUriBuilder(uri, 0, 0, &builder);
6318             if(test.create_builder_todo) {
6319                 todo_wine {
6320                     ok(hr == test.create_builder_expected,
6321                         "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6322                         hr, test.create_builder_expected, i);
6323                 }
6324             } else {
6325                 ok(hr == test.create_builder_expected,
6326                     "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6327                     hr, test.create_builder_expected, i);
6328             }
6329             if(SUCCEEDED(hr)) {
6330                 DWORD j;
6331                 BOOL modified = FALSE, received = FALSE;
6332
6333                 /* Perform all the string property changes. */
6334                 for(j = 0; j < URI_BUILDER_STR_PROPERTY_COUNT; ++j) {
6335                     uri_builder_property prop = test.properties[j];
6336                     if(prop.change) {
6337                         modified = TRUE;
6338                         change_property(builder, &prop, i);
6339                     }
6340                 }
6341
6342                 if(test.port_prop.change) {
6343                     hr = IUriBuilder_SetPort(builder, test.port_prop.set, test.port_prop.value);
6344                     modified = TRUE;
6345                     if(test.port_prop.todo) {
6346                         todo_wine {
6347                             ok(hr == test.port_prop.expected,
6348                                 "Error: IUriBuilder_SetPort returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6349                                 hr, test.port_prop.expected, i);
6350                         }
6351                     } else {
6352                         ok(hr == test.port_prop.expected,
6353                             "Error: IUriBuilder_SetPort returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6354                             hr, test.port_prop.expected, i);
6355                     }
6356                 }
6357
6358                 hr = IUriBuilder_HasBeenModified(builder, &received);
6359                 todo_wine {
6360                     ok(hr == S_OK,
6361                         "Error IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6362                         hr, S_OK, i);
6363                 }
6364                 if(SUCCEEDED(hr)) {
6365                     todo_wine {
6366                         ok(received == modified,
6367                             "Error: Expected received to be %d but was %d instead on uri_builder_tests[%d].\n",
6368                             modified, received, i);
6369                     }
6370                 }
6371
6372                 /* Test the "Get*" functions. */
6373                 test_IUriBuilder_GetFragment(builder, &test, i);
6374                 test_IUriBuilder_GetHost(builder, &test, i);
6375                 test_IUriBuilder_GetPassword(builder, &test, i);
6376                 test_IUriBuilder_GetPath(builder, &test, i);
6377                 test_IUriBuilder_GetPort(builder, &test, i);
6378                 test_IUriBuilder_GetQuery(builder, &test, i);
6379                 test_IUriBuilder_GetSchemeName(builder, &test, i);
6380                 test_IUriBuilder_GetUserName(builder, &test, i);
6381
6382                 test_IUriBuilder_CreateUri(builder, &test, i);
6383                 test_IUriBuilder_CreateUriSimple(builder, &test, i);
6384                 test_IUriBuilder_CreateUriWithFlags(builder, &test, i);
6385             }
6386             if(builder) IUriBuilder_Release(builder);
6387         }
6388         if(uri) IUri_Release(uri);
6389     }
6390 }
6391
6392 static void test_IUriBuilder_HasBeenModified(void) {
6393     HRESULT hr;
6394     IUriBuilder *builder = NULL;
6395
6396     hr = pCreateIUriBuilder(NULL, 0, 0, &builder);
6397     ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
6398     if(SUCCEEDED(hr)) {
6399         static const WCHAR hostW[] = {'w','i','n','e','h','q','.','c','o','m',0};
6400         IUri *uri = NULL;
6401         BOOL received;
6402
6403         hr = IUriBuilder_HasBeenModified(builder, NULL);
6404         ok(hr == E_POINTER, "Error: IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x.\n",
6405             hr, E_POINTER);
6406
6407         hr = IUriBuilder_SetHost(builder, hostW);
6408         todo_wine {
6409             ok(hr == S_OK, "Error: IUriBuilder_SetHost returned 0x%08x, expected 0x%08x.\n",
6410                 hr, S_OK);
6411         }
6412
6413         hr = IUriBuilder_HasBeenModified(builder, &received);
6414         todo_wine {
6415             ok(hr == S_OK, "Error: IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x.\n",
6416                 hr, S_OK);
6417         }
6418         if(SUCCEEDED(hr))
6419             todo_wine { ok(received == TRUE, "Error: Expected received to be TRUE.\n"); }
6420
6421         hr = pCreateUri(http_urlW, 0, 0, &uri);
6422         ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
6423         if(SUCCEEDED(hr)) {
6424             hr = IUriBuilder_SetIUri(builder, uri);
6425             todo_wine {
6426                 ok(hr == S_OK, "Error: IUriBuilder_SetIUri returned 0x%08x, expected 0x%08x.\n",
6427                     hr, S_OK);
6428             }
6429
6430             hr = IUriBuilder_HasBeenModified(builder, &received);
6431             todo_wine {
6432                 ok(hr == S_OK, "Error: IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x.\n",
6433                     hr, S_OK);
6434             }
6435             if(SUCCEEDED(hr))
6436                 todo_wine { ok(received == FALSE, "Error: Expected received to be FALSE.\n"); }
6437         }
6438         if(uri) IUri_Release(uri);
6439     }
6440     if(builder) IUriBuilder_Release(builder);
6441 }
6442
6443 /* Test IUriBuilder {Get,Set}IUri functions. */
6444 static void test_IUriBuilder_IUriProperty(void) {
6445     IUriBuilder *builder = NULL;
6446     HRESULT hr;
6447
6448     hr = pCreateIUriBuilder(NULL, 0, 0, &builder);
6449     ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
6450     if(SUCCEEDED(hr)) {
6451         IUri *uri = NULL;
6452
6453         hr = IUriBuilder_GetIUri(builder, NULL);
6454         ok(hr == E_POINTER, "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x.\n",
6455             hr, E_POINTER);
6456
6457         hr = pCreateUri(http_urlW, 0, 0, &uri);
6458         if(SUCCEEDED(hr)) {
6459             ULONG cur_count, orig_count;
6460
6461             /* IUriBuilder doesn't clone the IUri, it use the same IUri. */
6462             orig_count = get_refcnt(uri);
6463             hr = IUriBuilder_SetIUri(builder, uri);
6464             cur_count = get_refcnt(uri);
6465             if(SUCCEEDED(hr)) {
6466                 todo_wine {
6467                     ok(cur_count == orig_count+1, "Error: Expected uri ref count to be %d, but was %d instead.\n",
6468                         orig_count+1, cur_count);
6469                 }
6470             }
6471
6472             hr = IUriBuilder_SetIUri(builder, NULL);
6473             cur_count = get_refcnt(uri);
6474             if(SUCCEEDED(hr)) {
6475                 todo_wine {
6476                     ok(cur_count == orig_count, "Error: Expected uri ref count to be %d, but was %d instead.\n",
6477                         orig_count, cur_count);
6478                 }
6479             }
6480         }
6481         if(uri) IUri_Release(uri);
6482     }
6483     if(builder) IUriBuilder_Release(builder);
6484 }
6485
6486 static void test_IUriBuilder_RemoveProperties(void) {
6487     IUriBuilder *builder = NULL;
6488     HRESULT hr;
6489     DWORD i;
6490
6491     hr = pCreateIUriBuilder(NULL, 0, 0, &builder);
6492     ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
6493     if(SUCCEEDED(hr)) {
6494         /* Properties that can't be removed. */
6495         const DWORD invalid = Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_RAW_URI|Uri_HAS_HOST_TYPE|
6496                               Uri_HAS_SCHEME|Uri_HAS_ZONE;
6497
6498         for(i = Uri_PROPERTY_STRING_START; i <= Uri_PROPERTY_DWORD_LAST; ++i) {
6499             hr = IUriBuilder_RemoveProperties(builder, i << 1);
6500             if((i << 1) & invalid) {
6501                 todo_wine {
6502                     ok(hr == E_INVALIDARG,
6503                         "Error: IUriBuilder_RemoveProperties returned 0x%08x, expected 0x%08x with prop=%d.\n",
6504                         hr, E_INVALIDARG, i);
6505                 }
6506             } else {
6507                 todo_wine {
6508                     ok(hr == S_OK,
6509                         "Error: IUriBuilder_RemoveProperties returned 0x%08x, expected 0x%08x with prop=%d.\n",
6510                         hr, S_OK, i);
6511                 }
6512             }
6513         }
6514     }
6515     if(builder) IUriBuilder_Release(builder);
6516
6517     for(i = 0; i < sizeof(uri_builder_remove_tests)/sizeof(uri_builder_remove_tests[0]); ++i) {
6518         uri_builder_remove_test test = uri_builder_remove_tests[i];
6519         IUri *uri = NULL;
6520         LPWSTR uriW;
6521
6522         uriW = a2w(test.uri);
6523         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
6524         if(SUCCEEDED(hr)) {
6525             builder = NULL;
6526
6527             hr = pCreateIUriBuilder(uri, 0, 0, &builder);
6528             if(test.create_builder_todo) {
6529                 todo_wine {
6530                     ok(hr == test.create_builder_expected,
6531                         "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x on test %d.\n",
6532                         hr, test.create_builder_expected, i);
6533                 }
6534             } else {
6535                 ok(hr == test.create_builder_expected,
6536                     "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x on test %d.\n",
6537                     hr, test.create_builder_expected, i);
6538             }
6539             if(SUCCEEDED(hr)) {
6540                 hr = IUriBuilder_RemoveProperties(builder, test.remove_properties);
6541                 if(test.remove_todo) {
6542                     todo_wine {
6543                         ok(hr == test.remove_expected,
6544                             "Error: IUriBuilder_RemoveProperties returned 0x%08x, expected 0x%08x on test %d.\n",
6545                             hr, test.remove_expected, i);
6546                     }
6547                 } else {
6548                     ok(hr == test.remove_expected,
6549                         "Error: IUriBuilder returned 0x%08x, expected 0x%08x on test %d.\n",
6550                         hr, test.remove_expected, i);
6551                 }
6552                 if(SUCCEEDED(hr)) {
6553                     IUri *result = NULL;
6554
6555                     hr = IUriBuilder_CreateUri(builder, test.expected_flags, 0, 0, &result);
6556                     if(test.expected_todo) {
6557                         todo_wine {
6558                             ok(hr == test.expected_hres,
6559                                 "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x on test %d.\n",
6560                                 hr, test.expected_hres, i);
6561                         }
6562                     } else {
6563                         ok(hr == test.expected_hres,
6564                             "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x on test %d.\n",
6565                             hr, test.expected_hres, i);
6566                     }
6567                     if(SUCCEEDED(hr)) {
6568                         BSTR received = NULL;
6569
6570                         hr = IUri_GetAbsoluteUri(result, &received);
6571                         ok(!strcmp_aw(test.expected_uri, received),
6572                             "Error: Expected %s but got %s instead on test %d.\n",
6573                             test.expected_uri, wine_dbgstr_w(received), i);
6574                         SysFreeString(received);
6575                     }
6576                     if(result) IUri_Release(result);
6577                 }
6578             }
6579             if(builder) IUriBuilder_Release(builder);
6580         }
6581         if(uri) IUri_Release(uri);
6582         heap_free(uriW);
6583     }
6584 }
6585
6586 START_TEST(uri) {
6587     HMODULE hurlmon;
6588
6589     hurlmon = GetModuleHandle("urlmon.dll");
6590     pCreateUri = (void*) GetProcAddress(hurlmon, "CreateUri");
6591     pCreateUriWithFragment = (void*) GetProcAddress(hurlmon, "CreateUriWithFragment");
6592     pCreateIUriBuilder = (void*) GetProcAddress(hurlmon, "CreateIUriBuilder");
6593
6594     if(!pCreateUri) {
6595         win_skip("CreateUri is not present, skipping tests.\n");
6596         return;
6597     }
6598
6599     trace("test CreateUri invalid flags...\n");
6600     test_CreateUri_InvalidFlags();
6601
6602     trace("test CreateUri invalid args...\n");
6603     test_CreateUri_InvalidArgs();
6604
6605     trace("test CreateUri invalid URIs...\n");
6606     test_CreateUri_InvalidUri();
6607
6608     trace("test IUri_GetPropertyBSTR...\n");
6609     test_IUri_GetPropertyBSTR();
6610
6611     trace("test IUri_GetPropertyDWORD...\n");
6612     test_IUri_GetPropertyDWORD();
6613
6614     trace("test IUri_GetStrProperties...\n");
6615     test_IUri_GetStrProperties();
6616
6617     trace("test IUri_GetDwordProperties...\n");
6618     test_IUri_GetDwordProperties();
6619
6620     trace("test IUri_GetPropertyLength...\n");
6621     test_IUri_GetPropertyLength();
6622
6623     trace("test IUri_GetProperties...\n");
6624     test_IUri_GetProperties();
6625
6626     trace("test IUri_HasProperty...\n");
6627     test_IUri_HasProperty();
6628
6629     trace("test IUri_IsEqual...\n");
6630     test_IUri_IsEqual();
6631
6632     trace("test CreateUriWithFragment invalid args...\n");
6633     test_CreateUriWithFragment_InvalidArgs();
6634
6635     trace("test CreateUriWithFragment invalid flags...\n");
6636     test_CreateUriWithFragment_InvalidFlags();
6637
6638     trace("test CreateUriWithFragment...\n");
6639     test_CreateUriWithFragment();
6640
6641     trace("test CreateIUriBuilder...\n");
6642     test_CreateIUriBuilder();
6643
6644     trace("test IUriBuilder_CreateInvalidArgs...\n");
6645     test_IUriBuilder_CreateInvalidArgs();
6646
6647     trace("test IUriBuilder...\n");
6648     test_IUriBuilder();
6649
6650     trace("test IUriBuilder_GetInvalidArgs...\n");
6651     test_IUriBuilder_GetInvalidArgs();
6652
6653     trace("test IUriBuilder_HasBeenModified...\n");
6654     test_IUriBuilder_HasBeenModified();
6655
6656     trace("test IUriBuilder_IUriProperty...\n");
6657     test_IUriBuilder_IUriProperty();
6658
6659     trace("test IUriBuilder_RemoveProperties...\n");
6660     test_IUriBuilder_RemoveProperties();
6661 }