mshtml: Added IHTMLWindow2::focus implementation.
[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 #define CONST_VTABLE
27
28 #include "windef.h"
29 #include "winbase.h"
30 #include "urlmon.h"
31 #include "shlwapi.h"
32 #include "wininet.h"
33 #include "strsafe.h"
34
35 #define URI_STR_PROPERTY_COUNT Uri_PROPERTY_STRING_LAST+1
36 #define URI_DWORD_PROPERTY_COUNT (Uri_PROPERTY_DWORD_LAST - Uri_PROPERTY_DWORD_START)+1
37 #define URI_BUILDER_STR_PROPERTY_COUNT 7
38
39 #define DEFINE_EXPECT(func) \
40     static BOOL expect_ ## func = FALSE, called_ ## func = FALSE
41
42 #define SET_EXPECT(func) \
43     expect_ ## func = TRUE
44
45 #define CHECK_EXPECT(func) \
46     do { \
47         ok(expect_ ##func, "unexpected call " #func "\n"); \
48         expect_ ## func = FALSE; \
49         called_ ## func = TRUE; \
50     }while(0)
51
52 #define CHECK_EXPECT2(func) \
53     do { \
54         ok(expect_ ##func, "unexpected call " #func "\n"); \
55         called_ ## func = TRUE; \
56     }while(0)
57
58 #define CHECK_CALLED(func) \
59     do { \
60         ok(called_ ## func, "expected " #func "\n"); \
61         expect_ ## func = called_ ## func = FALSE; \
62     }while(0)
63
64 DEFINE_EXPECT(CombineUrl);
65 DEFINE_EXPECT(ParseUrl);
66
67 static HRESULT (WINAPI *pCreateUri)(LPCWSTR, DWORD, DWORD_PTR, IUri**);
68 static HRESULT (WINAPI *pCreateUriWithFragment)(LPCWSTR, LPCWSTR, DWORD, DWORD_PTR, IUri**);
69 static HRESULT (WINAPI *pCreateIUriBuilder)(IUri*, DWORD, DWORD_PTR, IUriBuilder**);
70 static HRESULT (WINAPI *pCoInternetCombineIUri)(IUri*,IUri*,DWORD,IUri**,DWORD_PTR);
71 static HRESULT (WINAPI *pCoInternetGetSession)(DWORD,IInternetSession**,DWORD);
72 static HRESULT (WINAPI *pCoInternetCombineUrlEx)(IUri*,LPCWSTR,DWORD,IUri**,DWORD_PTR);
73 static HRESULT (WINAPI *pCoInternetParseIUri)(IUri*,PARSEACTION,DWORD,LPWSTR,DWORD,DWORD*,DWORD_PTR);
74
75 static const WCHAR http_urlW[] = { 'h','t','t','p',':','/','/','w','w','w','.','w','i','n','e','h','q',
76         '.','o','r','g','/',0};
77 static const WCHAR http_url_fragW[] = { 'h','t','t','p',':','/','/','w','w','w','.','w','i','n','e','h','q',
78         '.','o','r','g','/','#','F','r','a','g',0};
79
80 static const WCHAR combine_baseW[] = {'w','i','n','e','t','e','s','t',':','?','t',
81         'e','s','t','i','n','g',0};
82 static const WCHAR combine_relativeW[] = {'?','t','e','s','t',0};
83 static const WCHAR combine_resultW[] = {'z','i','p',':','t','e','s','t',0};
84
85 static const WCHAR winetestW[] = {'w','i','n','e','t','e','s','t',0};
86
87 static const WCHAR parse_urlW[] = {'w','i','n','e','t','e','s','t',':','t','e','s','t',0};
88 static const WCHAR parse_resultW[] = {'z','i','p',':','t','e','s','t',0};
89
90 static PARSEACTION parse_action;
91 static DWORD parse_flags;
92
93 typedef struct _uri_create_flag_test {
94     DWORD   flags;
95     HRESULT expected;
96 } uri_create_flag_test;
97
98 static const uri_create_flag_test invalid_flag_tests[] = {
99     /* Set of invalid flag combinations to test for. */
100     {Uri_CREATE_DECODE_EXTRA_INFO | Uri_CREATE_NO_DECODE_EXTRA_INFO, E_INVALIDARG},
101     {Uri_CREATE_CANONICALIZE | Uri_CREATE_NO_CANONICALIZE, E_INVALIDARG},
102     {Uri_CREATE_CRACK_UNKNOWN_SCHEMES | Uri_CREATE_NO_CRACK_UNKNOWN_SCHEMES, E_INVALIDARG},
103     {Uri_CREATE_PRE_PROCESS_HTML_URI | Uri_CREATE_NO_PRE_PROCESS_HTML_URI, E_INVALIDARG},
104     {Uri_CREATE_IE_SETTINGS | Uri_CREATE_NO_IE_SETTINGS, E_INVALIDARG}
105 };
106
107 typedef struct _uri_str_property {
108     const char* value;
109     HRESULT     expected;
110     BOOL        todo;
111     const char* broken_value;
112 } uri_str_property;
113
114 typedef struct _uri_dword_property {
115     DWORD   value;
116     HRESULT expected;
117     BOOL    todo;
118 } uri_dword_property;
119
120 typedef struct _uri_properties {
121     const char*         uri;
122     DWORD               create_flags;
123     HRESULT             create_expected;
124     BOOL                create_todo;
125
126     uri_str_property    str_props[URI_STR_PROPERTY_COUNT];
127     uri_dword_property  dword_props[URI_DWORD_PROPERTY_COUNT];
128 } uri_properties;
129
130 static const uri_properties uri_tests[] = {
131     {   "http://www.winehq.org/tests/../tests/../..", 0, S_OK, FALSE,
132         {
133             {"http://www.winehq.org/",S_OK,FALSE},                      /* ABSOLUTE_URI */
134             {"www.winehq.org",S_OK,FALSE},                              /* AUTHORITY */
135             {"http://www.winehq.org/",S_OK,FALSE},                      /* DISPLAY_URI */
136             {"winehq.org",S_OK,FALSE},                                  /* DOMAIN */
137             {"",S_FALSE,FALSE},                                         /* EXTENSION */
138             {"",S_FALSE,FALSE},                                         /* FRAGMENT */
139             {"www.winehq.org",S_OK,FALSE},                              /* HOST */
140             {"",S_FALSE,FALSE},                                         /* PASSWORD */
141             {"/",S_OK,FALSE},                                           /* PATH */
142             {"/",S_OK,FALSE},                                           /* PATH_AND_QUERY */
143             {"",S_FALSE,FALSE},                                         /* QUERY */
144             {"http://www.winehq.org/tests/../tests/../..",S_OK,FALSE},  /* RAW_URI */
145             {"http",S_OK,FALSE},                                        /* SCHEME_NAME */
146             {"",S_FALSE,FALSE},                                         /* USER_INFO */
147             {"",S_FALSE,FALSE}                                          /* USER_NAME */
148         },
149         {
150             {Uri_HOST_DNS,S_OK,FALSE},                                  /* HOST_TYPE */
151             {80,S_OK,FALSE},                                            /* PORT */
152             {URL_SCHEME_HTTP,S_OK,FALSE},                               /* SCHEME */
153             {URLZONE_INVALID,E_NOTIMPL,FALSE}                           /* ZONE */
154         }
155     },
156     {   "http://winehq.org/tests/.././tests", 0, S_OK, FALSE,
157         {
158             {"http://winehq.org/tests",S_OK,FALSE},
159             {"winehq.org",S_OK,FALSE},
160             {"http://winehq.org/tests",S_OK,FALSE},
161             {"winehq.org",S_OK,FALSE},
162             {"",S_FALSE,FALSE},
163             {"",S_FALSE,FALSE},
164             {"winehq.org",S_OK,FALSE},
165             {"",S_FALSE,FALSE},
166             {"/tests",S_OK,FALSE},
167             {"/tests",S_OK,FALSE},
168             {"",S_FALSE,FALSE},
169             {"http://winehq.org/tests/.././tests",S_OK,FALSE},
170             {"http",S_OK,FALSE},
171             {"",S_FALSE,FALSE},
172             {"",S_FALSE,FALSE}
173         },
174         {
175             {Uri_HOST_DNS,S_OK,FALSE},
176             {80,S_OK,FALSE},
177             {URL_SCHEME_HTTP,S_OK,FALSE},
178             {URLZONE_INVALID,E_NOTIMPL,FALSE}
179         }
180     },
181     {   "HtTp://www.winehq.org/tests/..?query=x&return=y", 0, S_OK, FALSE,
182         {
183             {"http://www.winehq.org/?query=x&return=y",S_OK,FALSE},
184             {"www.winehq.org",S_OK,FALSE},
185             {"http://www.winehq.org/?query=x&return=y",S_OK,FALSE},
186             {"winehq.org",S_OK,FALSE},
187             {"",S_FALSE,FALSE},
188             {"",S_FALSE,FALSE},
189             {"www.winehq.org",S_OK,FALSE},
190             {"",S_FALSE,FALSE},
191             {"/",S_OK,FALSE},
192             {"/?query=x&return=y",S_OK,FALSE},
193             {"?query=x&return=y",S_OK,FALSE},
194             {"HtTp://www.winehq.org/tests/..?query=x&return=y",S_OK,FALSE},
195             {"http",S_OK,FALSE},
196             {"",S_FALSE,FALSE},
197             {"",S_FALSE,FALSE}
198         },
199         {
200             {Uri_HOST_DNS,S_OK,FALSE},
201             {80,S_OK,FALSE},
202             {URL_SCHEME_HTTP,S_OK,FALSE},
203             {URLZONE_INVALID,E_NOTIMPL,FALSE},
204         }
205     },
206     {   "hTTp://us%45r%3Ainfo@examp%4CE.com:80/path/a/b/./c/../%2E%2E/Forbidden'<|> Characters", 0, S_OK, FALSE,
207         {
208             {"http://usEr%3Ainfo@example.com/path/a/Forbidden'%3C%7C%3E%20Characters",S_OK,FALSE},
209             {"usEr%3Ainfo@example.com",S_OK,FALSE},
210             {"http://example.com/path/a/Forbidden'%3C%7C%3E%20Characters",S_OK,FALSE},
211             {"example.com",S_OK,FALSE},
212             {"",S_FALSE,FALSE},
213             {"",S_FALSE,FALSE},
214             {"example.com",S_OK,FALSE},
215             {"",S_FALSE,FALSE},
216             {"/path/a/Forbidden'%3C%7C%3E%20Characters",S_OK,FALSE},
217             {"/path/a/Forbidden'%3C%7C%3E%20Characters",S_OK,FALSE},
218             {"",S_FALSE,FALSE},
219             {"hTTp://us%45r%3Ainfo@examp%4CE.com:80/path/a/b/./c/../%2E%2E/Forbidden'<|> Characters",S_OK,FALSE},
220             {"http",S_OK,FALSE},
221             {"usEr%3Ainfo",S_OK,FALSE},
222             {"usEr%3Ainfo",S_OK,FALSE}
223         },
224         {
225             {Uri_HOST_DNS,S_OK,FALSE},
226             {80,S_OK,FALSE},
227             {URL_SCHEME_HTTP,S_OK,FALSE},
228             {URLZONE_INVALID,E_NOTIMPL,FALSE},
229         }
230     },
231     {   "ftp://winepass:wine@ftp.winehq.org:9999/dir/foo bar.txt", 0, S_OK, FALSE,
232         {
233             {"ftp://winepass:wine@ftp.winehq.org:9999/dir/foo%20bar.txt",S_OK,FALSE},
234             {"winepass:wine@ftp.winehq.org:9999",S_OK,FALSE},
235             {"ftp://ftp.winehq.org:9999/dir/foo%20bar.txt",S_OK,FALSE},
236             {"winehq.org",S_OK,FALSE},
237             {".txt",S_OK,FALSE},
238             {"",S_FALSE,FALSE},
239             {"ftp.winehq.org",S_OK,FALSE},
240             {"wine",S_OK,FALSE},
241             {"/dir/foo%20bar.txt",S_OK,FALSE},
242             {"/dir/foo%20bar.txt",S_OK,FALSE},
243             {"",S_FALSE,FALSE},
244             {"ftp://winepass:wine@ftp.winehq.org:9999/dir/foo bar.txt",S_OK,FALSE},
245             {"ftp",S_OK,FALSE},
246             {"winepass:wine",S_OK,FALSE},
247             {"winepass",S_OK,FALSE}
248         },
249         {
250             {Uri_HOST_DNS,S_OK,FALSE},
251             {9999,S_OK,FALSE},
252             {URL_SCHEME_FTP,S_OK,FALSE},
253             {URLZONE_INVALID,E_NOTIMPL,FALSE}
254         }
255     },
256     {   "file://c:\\tests\\../tests/foo%20bar.mp3", 0, S_OK, FALSE,
257         {
258             {"file:///c:/tests/foo%2520bar.mp3",S_OK,FALSE},
259             {"",S_FALSE,FALSE},
260             {"file:///c:/tests/foo%2520bar.mp3",S_OK,FALSE},
261             {"",S_FALSE,FALSE},
262             {".mp3",S_OK,FALSE},
263             {"",S_FALSE,FALSE},
264             {"",S_FALSE,FALSE},
265             {"",S_FALSE,FALSE},
266             {"/c:/tests/foo%2520bar.mp3",S_OK,FALSE},
267             {"/c:/tests/foo%2520bar.mp3",S_OK,FALSE},
268             {"",S_FALSE,FALSE},
269             {"file://c:\\tests\\../tests/foo%20bar.mp3",S_OK,FALSE},
270             {"file",S_OK,FALSE},
271             {"",S_FALSE,FALSE},
272             {"",S_FALSE,FALSE}
273         },
274         {
275             {Uri_HOST_UNKNOWN,S_OK,FALSE},
276             {0,S_FALSE,FALSE},
277             {URL_SCHEME_FILE,S_OK,FALSE},
278             {URLZONE_INVALID,E_NOTIMPL,FALSE}
279         }
280     },
281     {   "FILE://localhost/test dir\\../tests/test%20file.README.txt", 0, S_OK, FALSE,
282         {
283             {"file:///tests/test%20file.README.txt",S_OK,FALSE},
284             {"",S_FALSE,FALSE},
285             {"file:///tests/test%20file.README.txt",S_OK,FALSE},
286             {"",S_FALSE,FALSE},
287             {".txt",S_OK,FALSE},
288             {"",S_FALSE,FALSE},
289             {"",S_FALSE,FALSE},
290             {"",S_FALSE,FALSE},
291             {"/tests/test%20file.README.txt",S_OK,FALSE},
292             {"/tests/test%20file.README.txt",S_OK,FALSE},
293             {"",S_FALSE,FALSE},
294             {"FILE://localhost/test dir\\../tests/test%20file.README.txt",S_OK,FALSE},
295             {"file",S_OK,FALSE},
296             {"",S_FALSE,FALSE},
297             {"",S_FALSE,FALSE}
298         },
299         {
300             {Uri_HOST_UNKNOWN,S_OK,FALSE},
301             {0,S_FALSE,FALSE},
302             {URL_SCHEME_FILE,S_OK,FALSE},
303             {URLZONE_INVALID,E_NOTIMPL,FALSE}
304         }
305     },
306     {   "urn:nothing:should:happen here", 0, S_OK, FALSE,
307         {
308             {"urn:nothing:should:happen here",S_OK,FALSE},
309             {"",S_FALSE,FALSE},
310             {"urn:nothing:should:happen here",S_OK,FALSE},
311             {"",S_FALSE,FALSE},
312             {"",S_FALSE,FALSE},
313             {"",S_FALSE,FALSE},
314             {"",S_FALSE,FALSE},
315             {"",S_FALSE,FALSE},
316             {"nothing:should:happen here",S_OK,FALSE},
317             {"nothing:should:happen here",S_OK,FALSE},
318             {"",S_FALSE,FALSE},
319             {"urn:nothing:should:happen here",S_OK,FALSE},
320             {"urn",S_OK,FALSE},
321             {"",S_FALSE,FALSE},
322             {"",S_FALSE,FALSE}
323         },
324         {
325             {Uri_HOST_UNKNOWN,S_OK,FALSE},
326             {0,S_FALSE,FALSE},
327             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
328             {URLZONE_INVALID,E_NOTIMPL,FALSE}
329         }
330     },
331     {   "http://127.0.0.1/tests/../test dir/./test.txt", 0, S_OK, FALSE,
332         {
333             {"http://127.0.0.1/test%20dir/test.txt",S_OK,FALSE},
334             {"127.0.0.1",S_OK,FALSE},
335             {"http://127.0.0.1/test%20dir/test.txt",S_OK,FALSE},
336             {"",S_FALSE,FALSE},
337             {".txt",S_OK,FALSE},
338             {"",S_FALSE,FALSE},
339             {"127.0.0.1",S_OK,FALSE},
340             {"",S_FALSE,FALSE},
341             {"/test%20dir/test.txt",S_OK,FALSE},
342             {"/test%20dir/test.txt",S_OK,FALSE},
343             {"",S_FALSE,FALSE},
344             {"http://127.0.0.1/tests/../test dir/./test.txt",S_OK,FALSE},
345             {"http",S_OK,FALSE},
346             {"",S_FALSE,FALSE},
347             {"",S_FALSE,FALSE}
348         },
349         {
350             {Uri_HOST_IPV4,S_OK,FALSE},
351             {80,S_OK,FALSE},
352             {URL_SCHEME_HTTP,S_OK,FALSE},
353             {URLZONE_INVALID,E_NOTIMPL,FALSE}
354         }
355     },
356     {   "http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]", 0, S_OK, FALSE,
357         {
358             {"http://[fedc:ba98:7654:3210:fedc:ba98:7654:3210]/",S_OK,FALSE},
359             {"[fedc:ba98:7654:3210:fedc:ba98:7654:3210]",S_OK,FALSE},
360             {"http://[fedc:ba98:7654:3210:fedc:ba98:7654:3210]/",S_OK,FALSE},
361             {"",S_FALSE,FALSE},
362             {"",S_FALSE,FALSE},
363             {"",S_FALSE,FALSE},
364             {"fedc:ba98:7654:3210:fedc:ba98:7654:3210",S_OK,FALSE},
365             {"",S_FALSE,FALSE},
366             {"/",S_OK,FALSE},
367             {"/",S_OK,FALSE},
368             {"",S_FALSE,FALSE},
369             {"http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]",S_OK,FALSE},
370             {"http",S_OK,FALSE},
371             {"",S_FALSE,FALSE},
372             {"",S_FALSE,FALSE}
373         },
374         {
375             {Uri_HOST_IPV6,S_OK,FALSE},
376             {80,S_OK,FALSE},
377             {URL_SCHEME_HTTP,S_OK,FALSE},
378             {URLZONE_INVALID,E_NOTIMPL,FALSE}
379         }
380     },
381     {   "ftp://[::13.1.68.3]", 0, S_OK, FALSE,
382         {
383             {"ftp://[::13.1.68.3]/",S_OK,FALSE},
384             {"[::13.1.68.3]",S_OK,FALSE},
385             {"ftp://[::13.1.68.3]/",S_OK,FALSE},
386             {"",S_FALSE,FALSE},
387             {"",S_FALSE,FALSE},
388             {"",S_FALSE,FALSE},
389             {"::13.1.68.3",S_OK,FALSE},
390             {"",S_FALSE,FALSE},
391             {"/",S_OK,FALSE},
392             {"/",S_OK,FALSE},
393             {"",S_FALSE,FALSE},
394             {"ftp://[::13.1.68.3]",S_OK,FALSE},
395             {"ftp",S_OK,FALSE},
396             {"",S_FALSE,FALSE},
397             {"",S_FALSE,FALSE}
398         },
399         {
400             {Uri_HOST_IPV6,S_OK,FALSE},
401             {21,S_OK,FALSE},
402             {URL_SCHEME_FTP,S_OK,FALSE},
403             {URLZONE_INVALID,E_NOTIMPL,FALSE}
404         }
405     },
406     {   "http://[FEDC:BA98:0:0:0:0:0:3210]", 0, S_OK, FALSE,
407         {
408             {"http://[fedc:ba98::3210]/",S_OK,FALSE},
409             {"[fedc:ba98::3210]",S_OK,FALSE},
410             {"http://[fedc:ba98::3210]/",S_OK,FALSE},
411             {"",S_FALSE,FALSE},
412             {"",S_FALSE,FALSE},
413             {"",S_FALSE,FALSE},
414             {"fedc:ba98::3210",S_OK,FALSE},
415             {"",S_FALSE,FALSE},
416             {"/",S_OK,FALSE},
417             {"/",S_OK,FALSE},
418             {"",S_FALSE,FALSE},
419             {"http://[FEDC:BA98:0:0:0:0:0:3210]",S_OK,FALSE},
420             {"http",S_OK,FALSE},
421             {"",S_FALSE,FALSE},
422             {"",S_FALSE,FALSE},
423         },
424         {
425             {Uri_HOST_IPV6,S_OK,FALSE},
426             {80,S_OK,FALSE},
427             {URL_SCHEME_HTTP,S_OK,FALSE},
428             {URLZONE_INVALID,E_NOTIMPL,FALSE}
429         }
430     },
431     {   "1234://www.winehq.org", 0, S_OK, FALSE,
432         {
433             {"1234://www.winehq.org/",S_OK,FALSE},
434             {"www.winehq.org",S_OK,FALSE},
435             {"1234://www.winehq.org/",S_OK,FALSE},
436             {"winehq.org",S_OK,FALSE},
437             {"",S_FALSE,FALSE},
438             {"",S_FALSE,FALSE},
439             {"www.winehq.org",S_OK,FALSE},
440             {"",S_FALSE,FALSE},
441             {"/",S_OK,FALSE},
442             {"/",S_OK,FALSE},
443             {"",S_FALSE,FALSE},
444             {"1234://www.winehq.org",S_OK,FALSE},
445             {"1234",S_OK,FALSE},
446             {"",S_FALSE,FALSE},
447             {"",S_FALSE,FALSE}
448         },
449         {
450             {Uri_HOST_DNS,S_OK,FALSE},
451             {0,S_FALSE,FALSE},
452             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
453             {URLZONE_INVALID,E_NOTIMPL,FALSE}
454         }
455     },
456     /* Test's to make sure the parser/canonicalizer handles implicit file schemes correctly. */
457     {   "C:/test/test.mp3", Uri_CREATE_ALLOW_IMPLICIT_FILE_SCHEME, S_OK, FALSE,
458         {
459             {"file:///C:/test/test.mp3",S_OK,FALSE},
460             {"",S_FALSE,FALSE},
461             {"file:///C:/test/test.mp3",S_OK,FALSE},
462             {"",S_FALSE,FALSE},
463             {".mp3",S_OK,FALSE},
464             {"",S_FALSE,FALSE},
465             {"",S_FALSE,FALSE},
466             {"",S_FALSE,FALSE},
467             {"/C:/test/test.mp3",S_OK,FALSE},
468             {"/C:/test/test.mp3",S_OK,FALSE},
469             {"",S_FALSE,FALSE},
470             {"C:/test/test.mp3",S_OK,FALSE},
471             {"file",S_OK,FALSE},
472             {"",S_FALSE,FALSE},
473             {"",S_FALSE,FALSE}
474         },
475         {
476             {Uri_HOST_UNKNOWN,S_OK,FALSE},
477             {0,S_FALSE,FALSE},
478             {URL_SCHEME_FILE,S_OK,FALSE},
479             {URLZONE_INVALID,E_NOTIMPL,FALSE}
480         }
481     },
482     /* Test's to make sure the parser/canonicalizer handles implicit file schemes correctly. */
483     {   "\\\\Server/test.mp3", Uri_CREATE_ALLOW_IMPLICIT_FILE_SCHEME, S_OK, FALSE,
484         {
485             {"file://server/test.mp3",S_OK,FALSE},
486             {"server",S_OK,FALSE},
487             {"file://server/test.mp3",S_OK,FALSE},
488             {"",S_FALSE,FALSE},
489             {".mp3",S_OK,FALSE},
490             {"",S_FALSE,FALSE},
491             {"server",S_OK,FALSE},
492             {"",S_FALSE,FALSE},
493             {"/test.mp3",S_OK,FALSE},
494             {"/test.mp3",S_OK,FALSE},
495             {"",S_FALSE,FALSE},
496             {"\\\\Server/test.mp3",S_OK,FALSE},
497             {"file",S_OK,FALSE},
498             {"",S_FALSE,FALSE},
499             {"",S_FALSE,FALSE}
500         },
501         {
502             {Uri_HOST_DNS,S_OK,FALSE},
503             {0,S_FALSE,FALSE},
504             {URL_SCHEME_FILE,S_OK,FALSE},
505             {URLZONE_INVALID,E_NOTIMPL,FALSE}
506         }
507     },
508     {   "www.winehq.org/test", Uri_CREATE_ALLOW_IMPLICIT_WILDCARD_SCHEME, S_OK, FALSE,
509         {
510             {"*:www.winehq.org/test",S_OK,FALSE},
511             {"www.winehq.org",S_OK,FALSE},
512             {"*:www.winehq.org/test",S_OK,FALSE},
513             {"winehq.org",S_OK,FALSE},
514             {"",S_FALSE,FALSE},
515             {"",S_FALSE,FALSE},
516             {"www.winehq.org",S_OK,FALSE},
517             {"",S_FALSE,FALSE},
518             {"/test",S_OK,FALSE},
519             {"/test",S_OK,FALSE},
520             {"",S_FALSE,FALSE},
521             {"www.winehq.org/test",S_OK,FALSE},
522             {"*",S_OK,FALSE},
523             {"",S_FALSE,FALSE},
524             {"",S_FALSE,FALSE}
525         },
526         {
527             {Uri_HOST_DNS,S_OK,FALSE},
528             {0,S_FALSE,FALSE},
529             {URL_SCHEME_WILDCARD,S_OK,FALSE},
530             {URLZONE_INVALID,E_NOTIMPL,FALSE}
531         }
532     },
533     /* Valid since the '*' is the only character in the scheme name. */
534     {   "*:www.winehq.org/test", 0, S_OK, FALSE,
535         {
536             {"*:www.winehq.org/test",S_OK,FALSE},
537             {"www.winehq.org",S_OK,FALSE},
538             {"*:www.winehq.org/test",S_OK,FALSE},
539             {"winehq.org",S_OK,FALSE},
540             {"",S_FALSE,FALSE},
541             {"",S_FALSE,FALSE},
542             {"www.winehq.org",S_OK,FALSE},
543             {"",S_FALSE,FALSE},
544             {"/test",S_OK,FALSE},
545             {"/test",S_OK,FALSE},
546             {"",S_FALSE,FALSE},
547             {"*:www.winehq.org/test",S_OK,FALSE},
548             {"*",S_OK,FALSE},
549             {"",S_FALSE,FALSE},
550             {"",S_FALSE,FALSE}
551         },
552         {
553             {Uri_HOST_DNS,S_OK,FALSE},
554             {0,S_FALSE,FALSE},
555             {URL_SCHEME_WILDCARD,S_OK,FALSE},
556             {URLZONE_INVALID,E_NOTIMPL,FALSE}
557         }
558     },
559     {   "/../some dir/test.ext", Uri_CREATE_ALLOW_RELATIVE, S_OK, FALSE,
560         {
561             {"/../some dir/test.ext",S_OK,FALSE},
562             {"",S_FALSE,FALSE},
563             {"/../some dir/test.ext",S_OK,FALSE},
564             {"",S_FALSE,FALSE},
565             {".ext",S_OK,FALSE},
566             {"",S_FALSE,FALSE},
567             {"",S_FALSE,FALSE},
568             {"",S_FALSE,FALSE},
569             {"/../some dir/test.ext",S_OK,FALSE},
570             {"/../some dir/test.ext",S_OK,FALSE},
571             {"",S_FALSE,FALSE},
572             {"/../some dir/test.ext",S_OK,FALSE},
573             {"",S_FALSE,FALSE},
574             {"",S_FALSE,FALSE},
575             {"",S_FALSE,FALSE}
576         },
577         {
578             {Uri_HOST_UNKNOWN,S_OK,FALSE},
579             {0,S_FALSE,FALSE},
580             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
581             {URLZONE_INVALID,E_NOTIMPL,FALSE}
582         }
583     },
584     {   "//implicit/wildcard/uri scheme", Uri_CREATE_ALLOW_RELATIVE|Uri_CREATE_ALLOW_IMPLICIT_WILDCARD_SCHEME, S_OK, FALSE,
585         {
586             {"*://implicit/wildcard/uri%20scheme",S_OK,FALSE},
587             {"",S_OK,FALSE},
588             {"*://implicit/wildcard/uri%20scheme",S_OK,FALSE},
589             {"",S_FALSE,FALSE},
590             {"",S_FALSE,FALSE},
591             {"",S_FALSE,FALSE},
592             {"",S_OK,FALSE},
593             {"",S_FALSE,FALSE},
594             {"//implicit/wildcard/uri%20scheme",S_OK,FALSE},
595             {"//implicit/wildcard/uri%20scheme",S_OK,FALSE},
596             {"",S_FALSE,FALSE},
597             {"//implicit/wildcard/uri scheme",S_OK,FALSE},
598             {"*",S_OK,FALSE},
599             {"",S_FALSE,FALSE},
600             {"",S_FALSE,FALSE},
601         },
602         {
603             {Uri_HOST_UNKNOWN,S_OK,FALSE},
604             {0,S_FALSE,FALSE},
605             {URL_SCHEME_WILDCARD,S_OK,FALSE},
606             {URLZONE_INVALID,E_NOTIMPL,FALSE}
607         }
608     },
609     /* URI is considered opaque since CREATE_NO_CRACK_UNKNOWN_SCHEMES is set and its an unknown scheme. */
610     {   "zip://google.com", Uri_CREATE_NO_CRACK_UNKNOWN_SCHEMES, S_OK, FALSE,
611         {
612             {"zip:/.//google.com",S_OK,FALSE},
613             {"",S_FALSE,FALSE},
614             {"zip:/.//google.com",S_OK,FALSE},
615             {"",S_FALSE,FALSE},
616             {".com",S_OK,FALSE},
617             {"",S_FALSE,FALSE},
618             {"",S_FALSE,FALSE},
619             {"",S_FALSE,FALSE},
620             {"/.//google.com",S_OK,FALSE},
621             {"/.//google.com",S_OK,FALSE},
622             {"",S_FALSE,FALSE},
623             {"zip://google.com",S_OK,FALSE},
624             {"zip",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_UNKNOWN,S_OK,FALSE},
632             {URLZONE_INVALID,E_NOTIMPL,FALSE}
633         }
634     },
635     /* Windows uses the first occurrence of ':' to delimit the userinfo. */
636     {   "ftp://user:pass:word@winehq.org/", 0, S_OK, FALSE,
637         {
638             {"ftp://user:pass:word@winehq.org/",S_OK,FALSE},
639             {"user:pass:word@winehq.org",S_OK,FALSE},
640             {"ftp://winehq.org/",S_OK,FALSE},
641             {"winehq.org",S_OK,FALSE},
642             {"",S_FALSE,FALSE},
643             {"",S_FALSE,FALSE},
644             {"winehq.org",S_OK,FALSE},
645             {"pass:word",S_OK,FALSE},
646             {"/",S_OK,FALSE},
647             {"/",S_OK,FALSE},
648             {"",S_FALSE,FALSE},
649             {"ftp://user:pass:word@winehq.org/",S_OK,FALSE},
650             {"ftp",S_OK,FALSE},
651             {"user:pass:word",S_OK,FALSE},
652             {"user",S_OK,FALSE}
653         },
654         {
655             {Uri_HOST_DNS,S_OK,FALSE},
656             {21,S_OK,FALSE},
657             {URL_SCHEME_FTP,S_OK,FALSE},
658             {URLZONE_INVALID,E_NOTIMPL,FALSE}
659         }
660     },
661     /* Make sure % encoded unreserved characters are decoded. */
662     {   "ftp://w%49%4Ee:PA%53%53@ftp.google.com/", 0, S_OK, FALSE,
663         {
664             {"ftp://wINe:PASS@ftp.google.com/",S_OK,FALSE},
665             {"wINe:PASS@ftp.google.com",S_OK,FALSE},
666             {"ftp://ftp.google.com/",S_OK,FALSE},
667             {"google.com",S_OK,FALSE},
668             {"",S_FALSE,FALSE},
669             {"",S_FALSE,FALSE},
670             {"ftp.google.com",S_OK,FALSE},
671             {"PASS",S_OK,FALSE},
672             {"/",S_OK,FALSE},
673             {"/",S_OK,FALSE},
674             {"",S_FALSE,FALSE},
675             {"ftp://w%49%4Ee:PA%53%53@ftp.google.com/",S_OK,FALSE},
676             {"ftp",S_OK,FALSE},
677             {"wINe:PASS",S_OK,FALSE},
678             {"wINe",S_OK,FALSE}
679         },
680         {
681             {Uri_HOST_DNS,S_OK,FALSE},
682             {21,S_OK,FALSE},
683             {URL_SCHEME_FTP,S_OK,FALSE},
684             {URLZONE_INVALID,E_NOTIMPL,FALSE}
685         }
686     },
687     /* Make sure % encoded characters which are NOT unreserved are NOT decoded. */
688     {   "ftp://w%5D%5Be:PA%7B%7D@ftp.google.com/", 0, S_OK, FALSE,
689         {
690             {"ftp://w%5D%5Be:PA%7B%7D@ftp.google.com/",S_OK,FALSE},
691             {"w%5D%5Be:PA%7B%7D@ftp.google.com",S_OK,FALSE},
692             {"ftp://ftp.google.com/",S_OK,FALSE},
693             {"google.com",S_OK,FALSE},
694             {"",S_FALSE,FALSE},
695             {"",S_FALSE,FALSE},
696             {"ftp.google.com",S_OK,FALSE},
697             {"PA%7B%7D",S_OK,FALSE},
698             {"/",S_OK,FALSE},
699             {"/",S_OK,FALSE},
700             {"",S_FALSE,FALSE},
701             {"ftp://w%5D%5Be:PA%7B%7D@ftp.google.com/",S_OK,FALSE},
702             {"ftp",S_OK,FALSE},
703             {"w%5D%5Be:PA%7B%7D",S_OK,FALSE},
704             {"w%5D%5Be",S_OK,FALSE}
705         },
706         {
707             {Uri_HOST_DNS,S_OK,FALSE},
708             {21,S_OK,FALSE},
709             {URL_SCHEME_FTP,S_OK,FALSE},
710             {URLZONE_INVALID,E_NOTIMPL,FALSE}
711         }
712     },
713     /* You're allowed to have an empty password portion in the userinfo section. */
714     {   "ftp://empty:@ftp.google.com/", 0, S_OK, FALSE,
715         {
716             {"ftp://empty:@ftp.google.com/",S_OK,FALSE},
717             {"empty:@ftp.google.com",S_OK,FALSE},
718             {"ftp://ftp.google.com/",S_OK,FALSE},
719             {"google.com",S_OK,FALSE},
720             {"",S_FALSE,FALSE},
721             {"",S_FALSE,FALSE},
722             {"ftp.google.com",S_OK,FALSE},
723             {"",S_OK,FALSE},
724             {"/",S_OK,FALSE},
725             {"/",S_OK,FALSE},
726             {"",S_FALSE,FALSE},
727             {"ftp://empty:@ftp.google.com/",S_OK,FALSE},
728             {"ftp",S_OK,FALSE},
729             {"empty:",S_OK,FALSE},
730             {"empty",S_OK,FALSE}
731         },
732         {
733             {Uri_HOST_DNS,S_OK,FALSE},
734             {21,S_OK,FALSE},
735             {URL_SCHEME_FTP,S_OK,FALSE},
736             {URLZONE_INVALID,E_NOTIMPL,FALSE}
737         }
738     },
739     /* Make sure forbidden characters in "userinfo" get encoded. */
740     {   "ftp://\" \"weird@ftp.google.com/", 0, S_OK, FALSE,
741         {
742             {"ftp://%22%20%22weird@ftp.google.com/",S_OK,FALSE},
743             {"%22%20%22weird@ftp.google.com",S_OK,FALSE},
744             {"ftp://ftp.google.com/",S_OK,FALSE},
745             {"google.com",S_OK,FALSE},
746             {"",S_FALSE,FALSE},
747             {"",S_FALSE,FALSE},
748             {"ftp.google.com",S_OK,FALSE},
749             {"",S_FALSE,FALSE},
750             {"/",S_OK,FALSE},
751             {"/",S_OK,FALSE},
752             {"",S_FALSE,FALSE},
753             {"ftp://\" \"weird@ftp.google.com/",S_OK,FALSE},
754             {"ftp",S_OK,FALSE},
755             {"%22%20%22weird",S_OK,FALSE},
756             {"%22%20%22weird",S_OK,FALSE}
757         },
758         {
759             {Uri_HOST_DNS,S_OK,FALSE},
760             {21,S_OK,FALSE},
761             {URL_SCHEME_FTP,S_OK,FALSE},
762             {URLZONE_INVALID,E_NOTIMPL,FALSE}
763         }
764     },
765     /* Make sure the forbidden characters don't get percent encoded. */
766     {   "ftp://\" \"weird@ftp.google.com/", Uri_CREATE_NO_ENCODE_FORBIDDEN_CHARACTERS, S_OK, FALSE,
767         {
768             {"ftp://\" \"weird@ftp.google.com/",S_OK,FALSE},
769             {"\" \"weird@ftp.google.com",S_OK,FALSE},
770             {"ftp://ftp.google.com/",S_OK,FALSE},
771             {"google.com",S_OK,FALSE},
772             {"",S_FALSE,FALSE},
773             {"",S_FALSE,FALSE},
774             {"ftp.google.com",S_OK,FALSE},
775             {"",S_FALSE,FALSE},
776             {"/",S_OK,FALSE},
777             {"/",S_OK,FALSE},
778             {"",S_FALSE,FALSE},
779             {"ftp://\" \"weird@ftp.google.com/",S_OK,FALSE},
780             {"ftp",S_OK,FALSE},
781             {"\" \"weird",S_OK,FALSE},
782             {"\" \"weird",S_OK,FALSE}
783         },
784         {
785             {Uri_HOST_DNS,S_OK,FALSE},
786             {21,S_OK,FALSE},
787             {URL_SCHEME_FTP,S_OK,FALSE},
788             {URLZONE_INVALID,E_NOTIMPL,FALSE}
789         }
790     },
791     /* Allowed to have invalid % encoded because its an unknown scheme type. */
792     {   "zip://%xy:word@winehq.org/", 0, S_OK, FALSE,
793         {
794             {"zip://%xy:word@winehq.org/",S_OK,FALSE},
795             {"%xy:word@winehq.org",S_OK,FALSE},
796             {"zip://%xy:word@winehq.org/",S_OK,FALSE},
797             {"winehq.org",S_OK,FALSE},
798             {"",S_FALSE,FALSE},
799             {"",S_FALSE,FALSE},
800             {"winehq.org",S_OK,FALSE},
801             {"word",S_OK,FALSE},
802             {"/",S_OK,FALSE},
803             {"/",S_OK,FALSE},
804             {"",S_FALSE,FALSE},
805             {"zip://%xy:word@winehq.org/",S_OK,FALSE},
806             {"zip",S_OK,FALSE},
807             {"%xy:word",S_OK,FALSE},
808             {"%xy",S_OK,FALSE}
809         },
810         {
811             {Uri_HOST_DNS,S_OK,FALSE},
812             {0,S_FALSE,FALSE},
813             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
814             {URLZONE_INVALID,E_NOTIMPL,FALSE}
815         }
816     },
817     /* Unreserved, percent encoded characters aren't decoded in the userinfo becuase the scheme
818      * isn't known.
819      */
820     {   "zip://%2E:%52%53ord@winehq.org/", 0, S_OK, FALSE,
821         {
822             {"zip://%2E:%52%53ord@winehq.org/",S_OK,FALSE},
823             {"%2E:%52%53ord@winehq.org",S_OK,FALSE},
824             {"zip://%2E:%52%53ord@winehq.org/",S_OK,FALSE},
825             {"winehq.org",S_OK,FALSE},
826             {"",S_FALSE,FALSE},
827             {"",S_FALSE,FALSE},
828             {"winehq.org",S_OK,FALSE},
829             {"%52%53ord",S_OK,FALSE},
830             {"/",S_OK,FALSE},
831             {"/",S_OK,FALSE},
832             {"",S_FALSE,FALSE},
833             {"zip://%2E:%52%53ord@winehq.org/",S_OK,FALSE},
834             {"zip",S_OK,FALSE},
835             {"%2E:%52%53ord",S_OK,FALSE},
836             {"%2E",S_OK,FALSE}
837         },
838         {
839             {Uri_HOST_DNS,S_OK,FALSE},
840             {0,S_FALSE,FALSE},
841             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
842             {URLZONE_INVALID,E_NOTIMPL,FALSE}
843         }
844     },
845     {   "ftp://[](),'test':word@winehq.org/", 0, S_OK, FALSE,
846         {
847             {"ftp://[](),'test':word@winehq.org/",S_OK,FALSE},
848             {"[](),'test':word@winehq.org",S_OK,FALSE},
849             {"ftp://winehq.org/",S_OK,FALSE},
850             {"winehq.org",S_OK,FALSE},
851             {"",S_FALSE,FALSE},
852             {"",S_FALSE,FALSE},
853             {"winehq.org",S_OK,FALSE},
854             {"word",S_OK,FALSE},
855             {"/",S_OK,FALSE},
856             {"/",S_OK,FALSE},
857             {"",S_FALSE,FALSE},
858             {"ftp://[](),'test':word@winehq.org/",S_OK,FALSE},
859             {"ftp",S_OK,FALSE},
860             {"[](),'test':word",S_OK,FALSE},
861             {"[](),'test'",S_OK,FALSE}
862         },
863         {
864             {Uri_HOST_DNS,S_OK,FALSE},
865             {21,S_OK,FALSE},
866             {URL_SCHEME_FTP,S_OK,FALSE},
867             {URLZONE_INVALID,E_NOTIMPL,FALSE}
868         }
869     },
870     {   "ftp://test?:word@winehq.org/", 0, S_OK, FALSE,
871         {
872             {"ftp://test/?:word@winehq.org/",S_OK,FALSE},
873             {"test",S_OK,FALSE},
874             {"ftp://test/?:word@winehq.org/",S_OK,FALSE},
875             {"",S_FALSE,FALSE},
876             {"",S_FALSE,FALSE},
877             {"",S_FALSE,FALSE},
878             {"test",S_OK,FALSE},
879             {"",S_FALSE,FALSE},
880             {"/",S_OK,FALSE},
881             {"/?:word@winehq.org/",S_OK,FALSE},
882             {"?:word@winehq.org/",S_OK,FALSE},
883             {"ftp://test?:word@winehq.org/",S_OK,FALSE},
884             {"ftp",S_OK,FALSE},
885             {"",S_FALSE,FALSE},
886             {"",S_FALSE,FALSE}
887         },
888         {
889             {Uri_HOST_DNS,S_OK,FALSE},
890             {21,S_OK,FALSE},
891             {URL_SCHEME_FTP,S_OK,FALSE},
892             {URLZONE_INVALID,E_NOTIMPL,FALSE}
893         }
894     },
895     {   "ftp://test#:word@winehq.org/", 0, S_OK, FALSE,
896         {
897             {"ftp://test/#:word@winehq.org/",S_OK,FALSE},
898             {"test",S_OK,FALSE},
899             {"ftp://test/#:word@winehq.org/",S_OK,FALSE},
900             {"",S_FALSE,FALSE},
901             {"",S_FALSE,FALSE},
902             {"#:word@winehq.org/",S_OK,FALSE},
903             {"test",S_OK,FALSE},
904             {"",S_FALSE,FALSE},
905             {"/",S_OK,FALSE},
906             {"/",S_OK,FALSE},
907             {"",S_FALSE,FALSE},
908             {"ftp://test#:word@winehq.org/",S_OK,FALSE},
909             {"ftp",S_OK,FALSE},
910             {"",S_FALSE,FALSE},
911             {"",S_FALSE,FALSE}
912         },
913         {
914             {Uri_HOST_DNS,S_OK,FALSE},
915             {21,S_OK,FALSE},
916             {URL_SCHEME_FTP,S_OK,FALSE},
917             {URLZONE_INVALID,E_NOTIMPL,FALSE}
918         }
919     },
920     /* Allowed to have a backslash in the userinfo since it's an unknown scheme. */
921     {   "zip://test\\:word@winehq.org/", 0, S_OK, FALSE,
922         {
923             {"zip://test\\:word@winehq.org/",S_OK,FALSE},
924             {"test\\:word@winehq.org",S_OK,FALSE},
925             {"zip://test\\:word@winehq.org/",S_OK,FALSE},
926             {"winehq.org",S_OK,FALSE},
927             {"",S_FALSE,FALSE},
928             {"",S_FALSE,FALSE},
929             {"winehq.org",S_OK,FALSE},
930             {"word",S_OK,FALSE},
931             {"/",S_OK,FALSE},
932             {"/",S_OK,FALSE},
933             {"",S_FALSE,FALSE},
934             {"zip://test\\:word@winehq.org/",S_OK,FALSE},
935             {"zip",S_OK,FALSE},
936             {"test\\:word",S_OK,FALSE},
937             {"test\\",S_OK,FALSE}
938         },
939         {
940             {Uri_HOST_DNS,S_OK,FALSE},
941             {0,S_FALSE,FALSE},
942             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
943             {URLZONE_INVALID,E_NOTIMPL,FALSE}
944         }
945     },
946     /* It normalizes IPv4 addresses correctly. */
947     {   "http://127.000.000.100/", 0, S_OK, FALSE,
948         {
949             {"http://127.0.0.100/",S_OK,FALSE},
950             {"127.0.0.100",S_OK,FALSE},
951             {"http://127.0.0.100/",S_OK,FALSE},
952             {"",S_FALSE,FALSE},
953             {"",S_FALSE,FALSE},
954             {"",S_FALSE,FALSE},
955             {"127.0.0.100",S_OK,FALSE},
956             {"",S_FALSE,FALSE},
957             {"/",S_OK,FALSE},
958             {"/",S_OK,FALSE},
959             {"",S_FALSE,FALSE},
960             {"http://127.000.000.100/",S_OK,FALSE},
961             {"http",S_OK,FALSE},
962             {"",S_FALSE,FALSE},
963             {"",S_FALSE,FALSE}
964         },
965         {
966             {Uri_HOST_IPV4,S_OK,FALSE},
967             {80,S_OK,FALSE},
968             {URL_SCHEME_HTTP,S_OK,FALSE},
969             {URLZONE_INVALID,E_NOTIMPL,FALSE}
970         }
971     },
972     /* Make sure it normalizes partial IPv4 addresses correctly. */
973     {   "http://127.0/", 0, S_OK, FALSE,
974         {
975             {"http://127.0.0.0/",S_OK,FALSE},
976             {"127.0.0.0",S_OK,FALSE},
977             {"http://127.0.0.0/",S_OK,FALSE},
978             {"",S_FALSE,FALSE},
979             {"",S_FALSE,FALSE},
980             {"",S_FALSE,FALSE},
981             {"127.0.0.0",S_OK,FALSE},
982             {"",S_FALSE,FALSE},
983             {"/",S_OK,FALSE},
984             {"/",S_OK,FALSE},
985             {"",S_FALSE,FALSE},
986             {"http://127.0/",S_OK,FALSE},
987             {"http",S_OK,FALSE},
988             {"",S_FALSE,FALSE},
989             {"",S_FALSE,FALSE}
990         },
991         {
992             {Uri_HOST_IPV4,S_OK,FALSE},
993             {80,S_OK,FALSE},
994             {URL_SCHEME_HTTP,S_OK,FALSE},
995             {URLZONE_INVALID,E_NOTIMPL,FALSE}
996         }
997     },
998     /* Make sure it converts implicit IPv4's correctly. */
999     {   "http://123456/", 0, S_OK, FALSE,
1000         {
1001             {"http://0.1.226.64/",S_OK,FALSE},
1002             {"0.1.226.64",S_OK,FALSE},
1003             {"http://0.1.226.64/",S_OK,FALSE},
1004             {"",S_FALSE,FALSE},
1005             {"",S_FALSE,FALSE},
1006             {"",S_FALSE,FALSE},
1007             {"0.1.226.64",S_OK,FALSE},
1008             {"",S_FALSE,FALSE},
1009             {"/",S_OK,FALSE},
1010             {"/",S_OK,FALSE},
1011             {"",S_FALSE,FALSE},
1012             {"http://123456/",S_OK,FALSE},
1013             {"http",S_OK,FALSE},
1014             {"",S_FALSE,FALSE},
1015             {"",S_FALSE,FALSE}
1016         },
1017         {
1018             {Uri_HOST_IPV4,S_OK,FALSE},
1019             {80,S_OK,FALSE},
1020             {URL_SCHEME_HTTP,S_OK,FALSE},
1021             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1022         }
1023     },
1024     /* UINT_MAX */
1025     {   "http://4294967295/", 0, S_OK, FALSE,
1026         {
1027             {"http://255.255.255.255/",S_OK,FALSE},
1028             {"255.255.255.255",S_OK,FALSE},
1029             {"http://255.255.255.255/",S_OK,FALSE},
1030             {"",S_FALSE,FALSE},
1031             {"",S_FALSE,FALSE},
1032             {"",S_FALSE,FALSE},
1033             {"255.255.255.255",S_OK,FALSE},
1034             {"",S_FALSE,FALSE},
1035             {"/",S_OK,FALSE},
1036             {"/",S_OK,FALSE},
1037             {"",S_FALSE,FALSE},
1038             {"http://4294967295/",S_OK,FALSE},
1039             {"http",S_OK,FALSE},
1040             {"",S_FALSE,FALSE},
1041             {"",S_FALSE,FALSE}
1042         },
1043         {
1044             {Uri_HOST_IPV4,S_OK,FALSE},
1045             {80,S_OK,FALSE},
1046             {URL_SCHEME_HTTP,S_OK,FALSE},
1047             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1048         }
1049     },
1050     /* UINT_MAX+1 */
1051     {   "http://4294967296/", 0, S_OK, FALSE,
1052         {
1053             {"http://4294967296/",S_OK,FALSE},
1054             {"4294967296",S_OK,FALSE},
1055             {"http://4294967296/",S_OK,FALSE},
1056             {"",S_FALSE,FALSE},
1057             {"",S_FALSE,FALSE},
1058             {"",S_FALSE,FALSE},
1059             {"4294967296",S_OK,FALSE},
1060             {"",S_FALSE,FALSE},
1061             {"/",S_OK,FALSE},
1062             {"/",S_OK,FALSE},
1063             {"",S_FALSE,FALSE},
1064             {"http://4294967296/",S_OK,FALSE},
1065             {"http",S_OK,FALSE},
1066             {"",S_FALSE,FALSE},
1067             {"",S_FALSE,FALSE}
1068         },
1069         {
1070             {Uri_HOST_DNS,S_OK,FALSE},
1071             {80,S_OK,FALSE},
1072             {URL_SCHEME_HTTP,S_OK,FALSE},
1073             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1074         }
1075     },
1076     /* Window's doesn't normalize IP address for unknown schemes. */
1077     {   "1234://4294967295/", 0, S_OK, FALSE,
1078         {
1079             {"1234://4294967295/",S_OK,FALSE},
1080             {"4294967295",S_OK,FALSE},
1081             {"1234://4294967295/",S_OK,FALSE},
1082             {"",S_FALSE,FALSE},
1083             {"",S_FALSE,FALSE},
1084             {"",S_FALSE,FALSE},
1085             {"4294967295",S_OK,FALSE},
1086             {"",S_FALSE,FALSE},
1087             {"/",S_OK,FALSE},
1088             {"/",S_OK,FALSE},
1089             {"",S_FALSE,FALSE},
1090             {"1234://4294967295/",S_OK,FALSE},
1091             {"1234",S_OK,FALSE},
1092             {"",S_FALSE,FALSE},
1093             {"",S_FALSE,FALSE}
1094         },
1095         {
1096             {Uri_HOST_IPV4,S_OK,FALSE},
1097             {0,S_FALSE,FALSE},
1098             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1099             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1100         }
1101     },
1102     /* Window's doesn't normalize IP address for unknown schemes. */
1103     {   "1234://127.001/", 0, S_OK, FALSE,
1104         {
1105             {"1234://127.001/",S_OK,FALSE},
1106             {"127.001",S_OK,FALSE},
1107             {"1234://127.001/",S_OK,FALSE},
1108             {"",S_FALSE,FALSE},
1109             {"",S_FALSE,FALSE},
1110             {"",S_FALSE,FALSE},
1111             {"127.001",S_OK,FALSE},
1112             {"",S_FALSE,FALSE},
1113             {"/",S_OK,FALSE},
1114             {"/",S_OK,FALSE},
1115             {"",S_FALSE,FALSE},
1116             {"1234://127.001/",S_OK,FALSE},
1117             {"1234",S_OK,FALSE},
1118             {"",S_FALSE,FALSE},
1119             {"",S_FALSE,FALSE}
1120         },
1121         {
1122             {Uri_HOST_IPV4,S_OK,FALSE},
1123             {0,S_FALSE,FALSE},
1124             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1125             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1126         }
1127     },
1128     {   "http://[FEDC:BA98::3210]", 0, S_OK, FALSE,
1129         {
1130             {"http://[fedc:ba98::3210]/",S_OK,FALSE},
1131             {"[fedc:ba98::3210]",S_OK,FALSE},
1132             {"http://[fedc:ba98::3210]/",S_OK,FALSE},
1133             {"",S_FALSE,FALSE},
1134             {"",S_FALSE,FALSE},
1135             {"",S_FALSE,FALSE},
1136             {"fedc:ba98::3210",S_OK,FALSE},
1137             {"",S_FALSE,FALSE},
1138             {"/",S_OK,FALSE},
1139             {"/",S_OK,FALSE},
1140             {"",S_FALSE,FALSE},
1141             {"http://[FEDC:BA98::3210]",S_OK,FALSE},
1142             {"http",S_OK,FALSE},
1143             {"",S_FALSE,FALSE},
1144             {"",S_FALSE,FALSE},
1145         },
1146         {
1147             {Uri_HOST_IPV6,S_OK,FALSE},
1148             {80,S_OK,FALSE},
1149             {URL_SCHEME_HTTP,S_OK,FALSE},
1150             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1151         }
1152     },
1153     {   "http://[::]", 0, S_OK, FALSE,
1154         {
1155             {"http://[::]/",S_OK,FALSE},
1156             {"[::]",S_OK,FALSE},
1157             {"http://[::]/",S_OK,FALSE},
1158             {"",S_FALSE,FALSE},
1159             {"",S_FALSE,FALSE},
1160             {"",S_FALSE,FALSE},
1161             {"::",S_OK,FALSE},
1162             {"",S_FALSE,FALSE},
1163             {"/",S_OK,FALSE},
1164             {"/",S_OK,FALSE},
1165             {"",S_FALSE,FALSE},
1166             {"http://[::]",S_OK,FALSE},
1167             {"http",S_OK,FALSE},
1168             {"",S_FALSE,FALSE},
1169             {"",S_FALSE,FALSE},
1170         },
1171         {
1172             {Uri_HOST_IPV6,S_OK,FALSE},
1173             {80,S_OK,FALSE},
1174             {URL_SCHEME_HTTP,S_OK,FALSE},
1175             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1176         }
1177     },
1178     {   "http://[FEDC:BA98::]", 0, S_OK, FALSE,
1179         {
1180             {"http://[fedc:ba98::]/",S_OK,FALSE},
1181             {"[fedc:ba98::]",S_OK,FALSE},
1182             {"http://[fedc:ba98::]/",S_OK,FALSE},
1183             {"",S_FALSE,FALSE},
1184             {"",S_FALSE,FALSE},
1185             {"",S_FALSE,FALSE},
1186             {"fedc:ba98::",S_OK,FALSE},
1187             {"",S_FALSE,FALSE},
1188             {"/",S_OK,FALSE},
1189             {"/",S_OK,FALSE},
1190             {"",S_FALSE,FALSE},
1191             {"http://[FEDC:BA98::]",S_OK,FALSE},
1192             {"http",S_OK,FALSE},
1193             {"",S_FALSE,FALSE},
1194             {"",S_FALSE,FALSE},
1195         },
1196         {
1197             {Uri_HOST_IPV6,S_OK,FALSE},
1198             {80,S_OK,FALSE},
1199             {URL_SCHEME_HTTP,S_OK,FALSE},
1200             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1201         }
1202     },
1203     /* Valid even with 2 byte elision because it doesn't appear the beginning or end. */
1204     {   "http://[1::3:4:5:6:7:8]", 0, S_OK, FALSE,
1205         {
1206             {"http://[1:0:3:4:5:6:7:8]/",S_OK,FALSE},
1207             {"[1:0:3:4:5:6:7:8]",S_OK,FALSE},
1208             {"http://[1:0:3:4:5:6:7:8]/",S_OK,FALSE},
1209             {"",S_FALSE,FALSE},
1210             {"",S_FALSE,FALSE},
1211             {"",S_FALSE,FALSE},
1212             {"1:0:3:4:5:6:7:8",S_OK,FALSE},
1213             {"",S_FALSE,FALSE},
1214             {"/",S_OK,FALSE},
1215             {"/",S_OK,FALSE},
1216             {"",S_FALSE,FALSE},
1217             {"http://[1::3:4:5:6:7:8]",S_OK,FALSE},
1218             {"http",S_OK,FALSE},
1219             {"",S_FALSE,FALSE},
1220             {"",S_FALSE,FALSE},
1221         },
1222         {
1223             {Uri_HOST_IPV6,S_OK,FALSE},
1224             {80,S_OK,FALSE},
1225             {URL_SCHEME_HTTP,S_OK,FALSE},
1226             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1227         }
1228     },
1229     {   "http://[v2.34]/", 0, S_OK, FALSE,
1230         {
1231             {"http://[v2.34]/",S_OK,FALSE},
1232             {"[v2.34]",S_OK,FALSE},
1233             {"http://[v2.34]/",S_OK,FALSE},
1234             {"",S_FALSE,FALSE},
1235             {"",S_FALSE,FALSE},
1236             {"",S_FALSE,FALSE},
1237             {"[v2.34]",S_OK,FALSE},
1238             {"",S_FALSE,FALSE},
1239             {"/",S_OK,FALSE},
1240             {"/",S_OK,FALSE},
1241             {"",S_FALSE,FALSE},
1242             {"http://[v2.34]/",S_OK,FALSE},
1243             {"http",S_OK,FALSE},
1244             {"",S_FALSE,FALSE},
1245             {"",S_FALSE,FALSE}
1246         },
1247         {
1248             {Uri_HOST_UNKNOWN,S_OK,FALSE},
1249             {80,S_OK,FALSE},
1250             {URL_SCHEME_HTTP,S_OK,FALSE},
1251             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1252         }
1253     },
1254     /* Windows ignores ':' if they appear after a '[' on a non-IPLiteral host. */
1255     {   "http://[xyz:12345.com/test", 0, S_OK, FALSE,
1256         {
1257             {"http://[xyz:12345.com/test",S_OK,FALSE},
1258             {"[xyz:12345.com",S_OK,FALSE},
1259             {"http://[xyz:12345.com/test",S_OK,FALSE},
1260             {"[xyz:12345.com",S_OK,FALSE},
1261             {"",S_FALSE,FALSE},
1262             {"",S_FALSE,FALSE},
1263             {"[xyz:12345.com",S_OK,FALSE},
1264             {"",S_FALSE,FALSE},
1265             {"/test",S_OK,FALSE},
1266             {"/test",S_OK,FALSE},
1267             {"",S_FALSE,FALSE},
1268             {"http://[xyz:12345.com/test",S_OK,FALSE},
1269             {"http",S_OK,FALSE},
1270             {"",S_FALSE,FALSE},
1271             {"",S_FALSE,FALSE}
1272         },
1273         {
1274             {Uri_HOST_DNS,S_OK,FALSE},
1275             {80,S_OK,FALSE},
1276             {URL_SCHEME_HTTP,S_OK,FALSE},
1277             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1278         }
1279     },
1280     /* Valid URI since the '[' and ']' don't appear at the beginning and end
1281      * of the host name (respectively).
1282      */
1283     {   "ftp://www.[works].com/", 0, S_OK, FALSE,
1284         {
1285             {"ftp://www.[works].com/",S_OK,FALSE},
1286             {"www.[works].com",S_OK,FALSE},
1287             {"ftp://www.[works].com/",S_OK,FALSE},
1288             {"[works].com",S_OK,FALSE},
1289             {"",S_FALSE,FALSE},
1290             {"",S_FALSE,FALSE},
1291             {"www.[works].com",S_OK,FALSE},
1292             {"",S_FALSE,FALSE},
1293             {"/",S_OK,FALSE},
1294             {"/",S_OK,FALSE},
1295             {"",S_FALSE,FALSE},
1296             {"ftp://www.[works].com/",S_OK,FALSE},
1297             {"ftp",S_OK,FALSE},
1298             {"",S_FALSE,FALSE},
1299             {"",S_FALSE,FALSE}
1300         },
1301         {
1302             {Uri_HOST_DNS,S_OK,FALSE},
1303             {21,S_OK,FALSE},
1304             {URL_SCHEME_FTP,S_OK,FALSE},
1305             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1306         }
1307     },
1308     /* Considers ':' a delimiter since it appears after the ']'. */
1309     {   "http://www.google.com]:12345/", 0, S_OK, FALSE,
1310         {
1311             {"http://www.google.com]:12345/",S_OK,FALSE},
1312             {"www.google.com]:12345",S_OK,FALSE},
1313             {"http://www.google.com]:12345/",S_OK,FALSE},
1314             {"google.com]",S_OK,FALSE},
1315             {"",S_FALSE,FALSE},
1316             {"",S_FALSE,FALSE},
1317             {"www.google.com]",S_OK,FALSE},
1318             {"",S_FALSE,FALSE},
1319             {"/",S_OK,FALSE},
1320             {"/",S_OK,FALSE},
1321             {"",S_FALSE,FALSE},
1322             {"http://www.google.com]:12345/",S_OK,FALSE},
1323             {"http",S_OK,FALSE},
1324             {"",S_FALSE,FALSE},
1325             {"",S_FALSE,FALSE}
1326         },
1327         {
1328             {Uri_HOST_DNS,S_OK,FALSE},
1329             {12345,S_OK,FALSE},
1330             {URL_SCHEME_HTTP,S_OK,FALSE},
1331             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1332         }
1333     },
1334     /* Unknown scheme types can have invalid % encoded data in the hostname. */
1335     {   "zip://w%XXw%GEw.google.com/", 0, S_OK, FALSE,
1336         {
1337             {"zip://w%XXw%GEw.google.com/",S_OK,FALSE},
1338             {"w%XXw%GEw.google.com",S_OK,FALSE},
1339             {"zip://w%XXw%GEw.google.com/",S_OK,FALSE},
1340             {"google.com",S_OK,FALSE},
1341             {"",S_FALSE,FALSE},
1342             {"",S_FALSE,FALSE},
1343             {"w%XXw%GEw.google.com",S_OK,FALSE},
1344             {"",S_FALSE,FALSE},
1345             {"/",S_OK,FALSE},
1346             {"/",S_OK,FALSE},
1347             {"",S_FALSE,FALSE},
1348             {"zip://w%XXw%GEw.google.com/",S_OK,FALSE},
1349             {"zip",S_OK,FALSE},
1350             {"",S_FALSE,FALSE},
1351             {"",S_FALSE,FALSE}
1352         },
1353         {
1354             {Uri_HOST_DNS,S_OK,FALSE},
1355             {0,S_FALSE,FALSE},
1356             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1357             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1358         }
1359     },
1360     /* Unknown scheme types hostname doesn't get lower cased. */
1361     {   "zip://GOOGLE.com/", 0, S_OK, FALSE,
1362         {
1363             {"zip://GOOGLE.com/",S_OK,FALSE},
1364             {"GOOGLE.com",S_OK,FALSE},
1365             {"zip://GOOGLE.com/",S_OK,FALSE},
1366             {"GOOGLE.com",S_OK,FALSE},
1367             {"",S_FALSE,FALSE},
1368             {"",S_FALSE,FALSE},
1369             {"GOOGLE.com",S_OK,FALSE},
1370             {"",S_FALSE,FALSE},
1371             {"/",S_OK,FALSE},
1372             {"/",S_OK,FALSE},
1373             {"",S_FALSE,FALSE},
1374             {"zip://GOOGLE.com/",S_OK,FALSE},
1375             {"zip",S_OK,FALSE},
1376             {"",S_FALSE,FALSE},
1377             {"",S_FALSE,FALSE}
1378         },
1379         {
1380             {Uri_HOST_DNS,S_OK,FALSE},
1381             {0,S_FALSE,FALSE},
1382             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1383             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1384         }
1385     },
1386     /* Hostname get's lower cased for known scheme types. */
1387     {   "http://WWW.GOOGLE.com/", 0, S_OK, FALSE,
1388         {
1389             {"http://www.google.com/",S_OK,FALSE},
1390             {"www.google.com",S_OK,FALSE},
1391             {"http://www.google.com/",S_OK,FALSE},
1392             {"google.com",S_OK,FALSE},
1393             {"",S_FALSE,FALSE},
1394             {"",S_FALSE,FALSE},
1395             {"www.google.com",S_OK,FALSE},
1396             {"",S_FALSE,FALSE},
1397             {"/",S_OK,FALSE},
1398             {"/",S_OK,FALSE},
1399             {"",S_FALSE,FALSE},
1400             {"http://WWW.GOOGLE.com/",S_OK,FALSE},
1401             {"http",S_OK,FALSE},
1402             {"",S_FALSE,FALSE},
1403             {"",S_FALSE,FALSE}
1404         },
1405         {
1406             {Uri_HOST_DNS,S_OK,FALSE},
1407             {80,S_OK,FALSE},
1408             {URL_SCHEME_HTTP,S_OK,FALSE},
1409             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1410         }
1411     },
1412     /* Characters that get % encoded in the hostname also have their percent
1413      * encoded forms lower cased.
1414      */
1415     {   "http://www.%7Cgoogle|.com/", 0, S_OK, FALSE,
1416         {
1417             {"http://www.%7cgoogle%7c.com/",S_OK,FALSE},
1418             {"www.%7cgoogle%7c.com",S_OK,FALSE},
1419             {"http://www.%7cgoogle%7c.com/",S_OK,FALSE},
1420             {"%7cgoogle%7c.com",S_OK,FALSE},
1421             {"",S_FALSE,FALSE},
1422             {"",S_FALSE,FALSE},
1423             {"www.%7cgoogle%7c.com",S_OK,FALSE},
1424             {"",S_FALSE,FALSE},
1425             {"/",S_OK,FALSE},
1426             {"/",S_OK,FALSE},
1427             {"",S_FALSE,FALSE},
1428             {"http://www.%7Cgoogle|.com/",S_OK,FALSE},
1429             {"http",S_OK,FALSE},
1430             {"",S_FALSE,FALSE},
1431             {"",S_FALSE,FALSE}
1432         },
1433         {
1434             {Uri_HOST_DNS,S_OK,FALSE},
1435             {80,S_OK,FALSE},
1436             {URL_SCHEME_HTTP,S_OK,FALSE},
1437             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1438         }
1439     },
1440     /* IPv4 addresses attached to IPv6 can be included in elisions. */
1441     {   "http://[1:2:3:4:5:6:0.0.0.0]", 0, S_OK, FALSE,
1442         {
1443             {"http://[1:2:3:4:5:6::]/",S_OK,FALSE},
1444             {"[1:2:3:4:5:6::]",S_OK,FALSE},
1445             {"http://[1:2:3:4:5:6::]/",S_OK,FALSE},
1446             {"",S_FALSE,FALSE},
1447             {"",S_FALSE,FALSE},
1448             {"",S_FALSE,FALSE},
1449             {"1:2:3:4:5:6::",S_OK,FALSE},
1450             {"",S_FALSE,FALSE},
1451             {"/",S_OK,FALSE},
1452             {"/",S_OK,FALSE},
1453             {"",S_FALSE,FALSE},
1454             {"http://[1:2:3:4:5:6:0.0.0.0]",S_OK,FALSE},
1455             {"http",S_OK,FALSE},
1456             {"",S_FALSE,FALSE},
1457             {"",S_FALSE,FALSE},
1458         },
1459         {
1460             {Uri_HOST_IPV6,S_OK,FALSE},
1461             {80,S_OK,FALSE},
1462             {URL_SCHEME_HTTP,S_OK,FALSE},
1463             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1464         }
1465     },
1466     /* IPv4 addresses get normalized. */
1467     {   "http://[::001.002.003.000]", 0, S_OK, FALSE,
1468         {
1469             {"http://[::1.2.3.0]/",S_OK,FALSE},
1470             {"[::1.2.3.0]",S_OK,FALSE},
1471             {"http://[::1.2.3.0]/",S_OK,FALSE},
1472             {"",S_FALSE,FALSE},
1473             {"",S_FALSE,FALSE},
1474             {"",S_FALSE,FALSE},
1475             {"::1.2.3.0",S_OK,FALSE},
1476             {"",S_FALSE,FALSE},
1477             {"/",S_OK,FALSE},
1478             {"/",S_OK,FALSE},
1479             {"",S_FALSE,FALSE},
1480             {"http://[::001.002.003.000]",S_OK,FALSE},
1481             {"http",S_OK,FALSE},
1482             {"",S_FALSE,FALSE},
1483             {"",S_FALSE,FALSE},
1484         },
1485         {
1486             {Uri_HOST_IPV6,S_OK,FALSE},
1487             {80,S_OK,FALSE},
1488             {URL_SCHEME_HTTP,S_OK,FALSE},
1489             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1490         }
1491     },
1492     /* Windows doesn't do anything to IPv6's in unknown schemes. */
1493     {   "zip://[0001:0:000:0004:0005:0006:001.002.003.000]", 0, S_OK, FALSE,
1494         {
1495             {"zip://[0001:0:000:0004:0005:0006:001.002.003.000]/",S_OK,FALSE},
1496             {"[0001:0:000:0004:0005:0006:001.002.003.000]",S_OK,FALSE},
1497             {"zip://[0001:0:000:0004:0005:0006:001.002.003.000]/",S_OK,FALSE},
1498             {"",S_FALSE,FALSE},
1499             {"",S_FALSE,FALSE},
1500             {"",S_FALSE,FALSE},
1501             {"0001:0:000:0004:0005:0006:001.002.003.000",S_OK,FALSE},
1502             {"",S_FALSE,FALSE},
1503             {"/",S_OK,FALSE},
1504             {"/",S_OK,FALSE},
1505             {"",S_FALSE,FALSE},
1506             {"zip://[0001:0:000:0004:0005:0006:001.002.003.000]",S_OK,FALSE},
1507             {"zip",S_OK,FALSE},
1508             {"",S_FALSE,FALSE},
1509             {"",S_FALSE,FALSE},
1510         },
1511         {
1512             {Uri_HOST_IPV6,S_OK,FALSE},
1513             {0,S_FALSE,FALSE},
1514             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1515             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1516         }
1517     },
1518     /* IPv4 address is converted into 2 h16 components. */
1519     {   "http://[ffff::192.222.111.32]", 0, S_OK, FALSE,
1520         {
1521             {"http://[ffff::c0de:6f20]/",S_OK,FALSE},
1522             {"[ffff::c0de:6f20]",S_OK,FALSE},
1523             {"http://[ffff::c0de:6f20]/",S_OK,FALSE},
1524             {"",S_FALSE,FALSE},
1525             {"",S_FALSE,FALSE},
1526             {"",S_FALSE,FALSE},
1527             {"ffff::c0de:6f20",S_OK,FALSE},
1528             {"",S_FALSE,FALSE},
1529             {"/",S_OK,FALSE},
1530             {"/",S_OK,FALSE},
1531             {"",S_FALSE,FALSE},
1532             {"http://[ffff::192.222.111.32]",S_OK,FALSE},
1533             {"http",S_OK,FALSE},
1534             {"",S_FALSE,FALSE},
1535             {"",S_FALSE,FALSE},
1536         },
1537         {
1538             {Uri_HOST_IPV6,S_OK,FALSE},
1539             {80,S_OK,FALSE},
1540             {URL_SCHEME_HTTP,S_OK,FALSE},
1541             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1542         }
1543     },
1544     /* Max value for a port. */
1545     {   "http://google.com:65535", 0, S_OK, FALSE,
1546         {
1547             {"http://google.com:65535/",S_OK,FALSE},
1548             {"google.com:65535",S_OK,FALSE},
1549             {"http://google.com:65535/",S_OK,FALSE},
1550             {"google.com",S_OK,FALSE},
1551             {"",S_FALSE,FALSE},
1552             {"",S_FALSE,FALSE},
1553             {"google.com",S_OK,FALSE},
1554             {"",S_FALSE,FALSE},
1555             {"/",S_OK,FALSE},
1556             {"/",S_OK,FALSE},
1557             {"",S_FALSE,FALSE},
1558             {"http://google.com:65535",S_OK,FALSE},
1559             {"http",S_OK,FALSE},
1560             {"",S_FALSE,FALSE},
1561             {"",S_FALSE,FALSE}
1562         },
1563         {
1564             {Uri_HOST_DNS,S_OK,FALSE},
1565             {65535,S_OK,FALSE},
1566             {URL_SCHEME_HTTP,S_OK,FALSE},
1567             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1568         }
1569     },
1570     {   "zip://google.com:65536", 0, S_OK, FALSE,
1571         {
1572             {"zip://google.com:65536/",S_OK,FALSE},
1573             {"google.com:65536",S_OK,FALSE},
1574             {"zip://google.com:65536/",S_OK,FALSE},
1575             {"google.com:65536",S_OK,FALSE},
1576             {"",S_FALSE,FALSE},
1577             {"",S_FALSE,FALSE},
1578             {"google.com:65536",S_OK,FALSE},
1579             {"",S_FALSE,FALSE},
1580             {"/",S_OK,FALSE},
1581             {"/",S_OK,FALSE},
1582             {"",S_FALSE,FALSE},
1583             {"zip://google.com:65536",S_OK,FALSE},
1584             {"zip",S_OK,FALSE},
1585             {"",S_FALSE,FALSE},
1586             {"",S_FALSE,FALSE}
1587         },
1588         {
1589             {Uri_HOST_DNS,S_OK,FALSE},
1590             {0,S_FALSE,FALSE},
1591             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1592             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1593         }
1594     },
1595     {   "zip://google.com:65536:25", 0, S_OK, FALSE,
1596         {
1597             {"zip://google.com:65536:25/",S_OK,FALSE},
1598             {"google.com:65536:25",S_OK,FALSE},
1599             {"zip://google.com:65536:25/",S_OK,FALSE},
1600             {"google.com:65536:25",S_OK,FALSE},
1601             {"",S_FALSE,FALSE},
1602             {"",S_FALSE,FALSE},
1603             {"google.com:65536:25",S_OK,FALSE},
1604             {"",S_FALSE,FALSE},
1605             {"/",S_OK,FALSE},
1606             {"/",S_OK,FALSE},
1607             {"",S_FALSE,FALSE},
1608             {"zip://google.com:65536:25",S_OK,FALSE},
1609             {"zip",S_OK,FALSE},
1610             {"",S_FALSE,FALSE},
1611             {"",S_FALSE,FALSE}
1612         },
1613         {
1614             {Uri_HOST_DNS,S_OK,FALSE},
1615             {0,S_FALSE,FALSE},
1616             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1617             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1618         }
1619     },
1620     {   "zip://[::ffff]:abcd", 0, S_OK, FALSE,
1621         {
1622             {"zip://[::ffff]:abcd/",S_OK,FALSE},
1623             {"[::ffff]:abcd",S_OK,FALSE},
1624             {"zip://[::ffff]:abcd/",S_OK,FALSE},
1625             {"",S_FALSE,FALSE},
1626             {"",S_FALSE,FALSE},
1627             {"",S_FALSE,FALSE},
1628             {"[::ffff]:abcd",S_OK,FALSE},
1629             {"",S_FALSE,FALSE},
1630             {"/",S_OK,FALSE},
1631             {"/",S_OK,FALSE},
1632             {"",S_FALSE,FALSE},
1633             {"zip://[::ffff]:abcd",S_OK,FALSE},
1634             {"zip",S_OK,FALSE},
1635             {"",S_FALSE,FALSE},
1636             {"",S_FALSE,FALSE}
1637         },
1638         {
1639             {Uri_HOST_DNS,S_OK,FALSE},
1640             {0,S_FALSE,FALSE},
1641             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1642             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1643         }
1644     },
1645     {   "zip://127.0.0.1:abcd", 0, S_OK, FALSE,
1646         {
1647             {"zip://127.0.0.1:abcd/",S_OK,FALSE},
1648             {"127.0.0.1:abcd",S_OK,FALSE},
1649             {"zip://127.0.0.1:abcd/",S_OK,FALSE},
1650             {"0.1:abcd",S_OK,FALSE},
1651             {"",S_FALSE,FALSE},
1652             {"",S_FALSE,FALSE},
1653             {"127.0.0.1:abcd",S_OK,FALSE},
1654             {"",S_FALSE,FALSE},
1655             {"/",S_OK,FALSE},
1656             {"/",S_OK,FALSE},
1657             {"",S_FALSE,FALSE},
1658             {"zip://127.0.0.1:abcd",S_OK,FALSE},
1659             {"zip",S_OK,FALSE},
1660             {"",S_FALSE,FALSE},
1661             {"",S_FALSE,FALSE}
1662         },
1663         {
1664             {Uri_HOST_DNS,S_OK,FALSE},
1665             {0,S_FALSE,FALSE},
1666             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1667             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1668         }
1669     },
1670     /* Port is just copied over. */
1671     {   "http://google.com:00035", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
1672         {
1673             {"http://google.com:00035",S_OK,FALSE},
1674             {"google.com:00035",S_OK,FALSE},
1675             {"http://google.com:00035",S_OK,FALSE,"http://google.com:35"},
1676             {"google.com",S_OK,FALSE},
1677             {"",S_FALSE,FALSE},
1678             {"",S_FALSE,FALSE},
1679             {"google.com",S_OK,FALSE},
1680             {"",S_FALSE,FALSE},
1681             {"",S_FALSE,FALSE},
1682             {"",S_FALSE,FALSE},
1683             {"",S_FALSE,FALSE},
1684             {"http://google.com:00035",S_OK,FALSE},
1685             {"http",S_OK,FALSE},
1686             {"",S_FALSE,FALSE},
1687             {"",S_FALSE,FALSE}
1688         },
1689         {
1690             {Uri_HOST_DNS,S_OK,FALSE},
1691             {35,S_OK,FALSE},
1692             {URL_SCHEME_HTTP,S_OK,FALSE},
1693             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1694         }
1695     },
1696     /* Default port is copied over. */
1697     {   "http://google.com:80", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
1698         {
1699             {"http://google.com:80",S_OK,FALSE},
1700             {"google.com:80",S_OK,FALSE},
1701             {"http://google.com:80",S_OK,FALSE},
1702             {"google.com",S_OK,FALSE},
1703             {"",S_FALSE,FALSE},
1704             {"",S_FALSE,FALSE},
1705             {"google.com",S_OK,FALSE},
1706             {"",S_FALSE,FALSE},
1707             {"",S_FALSE,FALSE},
1708             {"",S_FALSE,FALSE},
1709             {"",S_FALSE,FALSE},
1710             {"http://google.com:80",S_OK,FALSE},
1711             {"http",S_OK,FALSE},
1712             {"",S_FALSE,FALSE},
1713             {"",S_FALSE,FALSE}
1714         },
1715         {
1716             {Uri_HOST_DNS,S_OK,FALSE},
1717             {80,S_OK,FALSE},
1718             {URL_SCHEME_HTTP,S_OK,FALSE},
1719             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1720         }
1721     },
1722     {   "http://google.com.uk", 0, S_OK, FALSE,
1723         {
1724             {"http://google.com.uk/",S_OK,FALSE},
1725             {"google.com.uk",S_OK,FALSE},
1726             {"http://google.com.uk/",S_OK,FALSE},
1727             {"google.com.uk",S_OK,FALSE},
1728             {"",S_FALSE,FALSE},
1729             {"",S_FALSE,FALSE},
1730             {"google.com.uk",S_OK,FALSE},
1731             {"",S_FALSE,FALSE},
1732             {"/",S_OK,FALSE},
1733             {"/",S_OK,FALSE},
1734             {"",S_FALSE,FALSE},
1735             {"http://google.com.uk",S_OK,FALSE},
1736             {"http",S_OK,FALSE},
1737             {"",S_FALSE,FALSE},
1738             {"",S_FALSE,FALSE}
1739         },
1740         {
1741             {Uri_HOST_DNS,S_OK,FALSE},
1742             {80,S_OK,FALSE},
1743             {URL_SCHEME_HTTP,S_OK,FALSE},
1744             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1745         }
1746     },
1747     {   "http://google.com.com", 0, S_OK, FALSE,
1748         {
1749             {"http://google.com.com/",S_OK,FALSE},
1750             {"google.com.com",S_OK,FALSE},
1751             {"http://google.com.com/",S_OK,FALSE},
1752             {"com.com",S_OK,FALSE},
1753             {"",S_FALSE,FALSE},
1754             {"",S_FALSE,FALSE},
1755             {"google.com.com",S_OK,FALSE},
1756             {"",S_FALSE,FALSE},
1757             {"/",S_OK,FALSE},
1758             {"/",S_OK,FALSE},
1759             {"",S_FALSE,FALSE},
1760             {"http://google.com.com",S_OK,FALSE},
1761             {"http",S_OK,FALSE},
1762             {"",S_FALSE,FALSE},
1763             {"",S_FALSE,FALSE}
1764         },
1765         {
1766             {Uri_HOST_DNS,S_OK,FALSE},
1767             {80,S_OK,FALSE},
1768             {URL_SCHEME_HTTP,S_OK,FALSE},
1769             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1770         }
1771     },
1772     {   "http://google.uk.1", 0, S_OK, FALSE,
1773         {
1774             {"http://google.uk.1/",S_OK,FALSE},
1775             {"google.uk.1",S_OK,FALSE},
1776             {"http://google.uk.1/",S_OK,FALSE},
1777             {"google.uk.1",S_OK,FALSE},
1778             {"",S_FALSE,FALSE},
1779             {"",S_FALSE,FALSE},
1780             {"google.uk.1",S_OK,FALSE},
1781             {"",S_FALSE,FALSE},
1782             {"/",S_OK,FALSE},
1783             {"/",S_OK,FALSE},
1784             {"",S_FALSE,FALSE},
1785             {"http://google.uk.1",S_OK,FALSE},
1786             {"http",S_OK,FALSE},
1787             {"",S_FALSE,FALSE},
1788             {"",S_FALSE,FALSE}
1789         },
1790         {
1791             {Uri_HOST_DNS,S_OK,FALSE},
1792             {80,S_OK,FALSE},
1793             {URL_SCHEME_HTTP,S_OK,FALSE},
1794             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1795         }
1796     },
1797     /* Since foo isn't a recognized 3 character TLD its considered the domain name. */
1798     {   "http://google.foo.uk", 0, S_OK, FALSE,
1799         {
1800             {"http://google.foo.uk/",S_OK,FALSE},
1801             {"google.foo.uk",S_OK,FALSE},
1802             {"http://google.foo.uk/",S_OK,FALSE},
1803             {"foo.uk",S_OK,FALSE},
1804             {"",S_FALSE,FALSE},
1805             {"",S_FALSE,FALSE},
1806             {"google.foo.uk",S_OK,FALSE},
1807             {"",S_FALSE,FALSE},
1808             {"/",S_OK,FALSE},
1809             {"/",S_OK,FALSE},
1810             {"",S_FALSE,FALSE},
1811             {"http://google.foo.uk",S_OK,FALSE},
1812             {"http",S_OK,FALSE},
1813             {"",S_FALSE,FALSE},
1814             {"",S_FALSE,FALSE}
1815         },
1816         {
1817             {Uri_HOST_DNS,S_OK,FALSE},
1818             {80,S_OK,FALSE},
1819             {URL_SCHEME_HTTP,S_OK,FALSE},
1820             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1821         }
1822     },
1823     {   "http://.com", 0, S_OK, FALSE,
1824         {
1825             {"http://.com/",S_OK,FALSE},
1826             {".com",S_OK,FALSE},
1827             {"http://.com/",S_OK,FALSE},
1828             {".com",S_OK,FALSE},
1829             {"",S_FALSE,FALSE},
1830             {"",S_FALSE,FALSE},
1831             {".com",S_OK,FALSE},
1832             {"",S_FALSE,FALSE},
1833             {"/",S_OK,FALSE},
1834             {"/",S_OK,FALSE},
1835             {"",S_FALSE,FALSE},
1836             {"http://.com",S_OK,FALSE},
1837             {"http",S_OK,FALSE},
1838             {"",S_FALSE,FALSE},
1839             {"",S_FALSE,FALSE}
1840         },
1841         {
1842             {Uri_HOST_DNS,S_OK,FALSE},
1843             {80,S_OK,FALSE},
1844             {URL_SCHEME_HTTP,S_OK,FALSE},
1845             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1846         }
1847     },
1848     {   "http://.uk", 0, S_OK, FALSE,
1849         {
1850             {"http://.uk/",S_OK,FALSE},
1851             {".uk",S_OK,FALSE},
1852             {"http://.uk/",S_OK,FALSE},
1853             {"",S_FALSE,FALSE},
1854             {"",S_FALSE,FALSE},
1855             {"",S_FALSE,FALSE},
1856             {".uk",S_OK,FALSE},
1857             {"",S_FALSE,FALSE},
1858             {"/",S_OK,FALSE},
1859             {"/",S_OK,FALSE},
1860             {"",S_FALSE,FALSE},
1861             {"http://.uk",S_OK,FALSE},
1862             {"http",S_OK,FALSE},
1863             {"",S_FALSE,FALSE},
1864             {"",S_FALSE,FALSE}
1865         },
1866         {
1867             {Uri_HOST_DNS,S_OK,FALSE},
1868             {80,S_OK,FALSE},
1869             {URL_SCHEME_HTTP,S_OK,FALSE},
1870             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1871         }
1872     },
1873     {   "http://www.co.google.com.[]", 0, S_OK, FALSE,
1874         {
1875             {"http://www.co.google.com.[]/",S_OK,FALSE},
1876             {"www.co.google.com.[]",S_OK,FALSE},
1877             {"http://www.co.google.com.[]/",S_OK,FALSE},
1878             {"google.com.[]",S_OK,FALSE},
1879             {"",S_FALSE,FALSE},
1880             {"",S_FALSE,FALSE},
1881             {"www.co.google.com.[]",S_OK,FALSE},
1882             {"",S_FALSE,FALSE},
1883             {"/",S_OK,FALSE},
1884             {"/",S_OK,FALSE},
1885             {"",S_FALSE,FALSE},
1886             {"http://www.co.google.com.[]",S_OK,FALSE},
1887             {"http",S_OK,FALSE},
1888             {"",S_FALSE,FALSE},
1889             {"",S_FALSE,FALSE}
1890         },
1891         {
1892             {Uri_HOST_DNS,S_OK,FALSE},
1893             {80,S_OK,FALSE},
1894             {URL_SCHEME_HTTP,S_OK,FALSE},
1895             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1896         }
1897     },
1898     {   "http://co.uk", 0, S_OK, FALSE,
1899         {
1900             {"http://co.uk/",S_OK,FALSE},
1901             {"co.uk",S_OK,FALSE},
1902             {"http://co.uk/",S_OK,FALSE},
1903             {"",S_FALSE,FALSE},
1904             {"",S_FALSE,FALSE},
1905             {"",S_FALSE,FALSE},
1906             {"co.uk",S_OK,FALSE},
1907             {"",S_FALSE,FALSE},
1908             {"/",S_OK,FALSE},
1909             {"/",S_OK,FALSE},
1910             {"",S_FALSE,FALSE},
1911             {"http://co.uk",S_OK,FALSE},
1912             {"http",S_OK,FALSE},
1913             {"",S_FALSE,FALSE},
1914             {"",S_FALSE,FALSE}
1915         },
1916         {
1917             {Uri_HOST_DNS,S_OK,FALSE},
1918             {80,S_OK,FALSE},
1919             {URL_SCHEME_HTTP,S_OK,FALSE},
1920             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1921         }
1922     },
1923     {   "http://www.co.google.us.test", 0, S_OK, FALSE,
1924         {
1925             {"http://www.co.google.us.test/",S_OK,FALSE},
1926             {"www.co.google.us.test",S_OK,FALSE},
1927             {"http://www.co.google.us.test/",S_OK,FALSE},
1928             {"us.test",S_OK,FALSE},
1929             {"",S_FALSE,FALSE},
1930             {"",S_FALSE,FALSE},
1931             {"www.co.google.us.test",S_OK,FALSE},
1932             {"",S_FALSE,FALSE},
1933             {"/",S_OK,FALSE},
1934             {"/",S_OK,FALSE},
1935             {"",S_FALSE,FALSE},
1936             {"http://www.co.google.us.test",S_OK,FALSE},
1937             {"http",S_OK,FALSE},
1938             {"",S_FALSE,FALSE},
1939             {"",S_FALSE,FALSE}
1940         },
1941         {
1942             {Uri_HOST_DNS,S_OK,FALSE},
1943             {80,S_OK,FALSE},
1944             {URL_SCHEME_HTTP,S_OK,FALSE},
1945             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1946         }
1947     },
1948     {   "http://gov.uk", 0, S_OK, FALSE,
1949         {
1950             {"http://gov.uk/",S_OK,FALSE},
1951             {"gov.uk",S_OK,FALSE},
1952             {"http://gov.uk/",S_OK,FALSE},
1953             {"",S_FALSE,FALSE},
1954             {"",S_FALSE,FALSE},
1955             {"",S_FALSE,FALSE},
1956             {"gov.uk",S_OK,FALSE},
1957             {"",S_FALSE,FALSE},
1958             {"/",S_OK,FALSE},
1959             {"/",S_OK,FALSE},
1960             {"",S_FALSE,FALSE},
1961             {"http://gov.uk",S_OK,FALSE},
1962             {"http",S_OK,FALSE},
1963             {"",S_FALSE,FALSE},
1964             {"",S_FALSE,FALSE}
1965         },
1966         {
1967             {Uri_HOST_DNS,S_OK,FALSE},
1968             {80,S_OK,FALSE},
1969             {URL_SCHEME_HTTP,S_OK,FALSE},
1970             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1971         }
1972     },
1973     {   "zip://www.google.com\\test", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
1974         {
1975             {"zip://www.google.com\\test",S_OK,FALSE},
1976             {"www.google.com\\test",S_OK,FALSE},
1977             {"zip://www.google.com\\test",S_OK,FALSE},
1978             {"google.com\\test",S_OK,FALSE},
1979             {"",S_FALSE,FALSE},
1980             {"",S_FALSE,FALSE},
1981             {"www.google.com\\test",S_OK,FALSE},
1982             {"",S_FALSE,FALSE},
1983             {"",S_FALSE,FALSE},
1984             {"",S_FALSE,FALSE},
1985             {"",S_FALSE,FALSE},
1986             {"zip://www.google.com\\test",S_OK,FALSE},
1987             {"zip",S_OK,FALSE},
1988             {"",S_FALSE,FALSE},
1989             {"",S_FALSE,FALSE}
1990         },
1991         {
1992             {Uri_HOST_DNS,S_OK,FALSE},
1993             {0,S_FALSE,FALSE},
1994             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1995             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1996         }
1997     },
1998     {   "urn:excepts:bad:%XY:encoded", 0, S_OK, FALSE,
1999         {
2000             {"urn:excepts:bad:%XY:encoded",S_OK,FALSE},
2001             {"",S_FALSE,FALSE},
2002             {"urn:excepts:bad:%XY:encoded",S_OK,FALSE},
2003             {"",S_FALSE,FALSE},
2004             {"",S_FALSE,FALSE},
2005             {"",S_FALSE,FALSE},
2006             {"",S_FALSE,FALSE},
2007             {"",S_FALSE,FALSE},
2008             {"excepts:bad:%XY:encoded",S_OK,FALSE},
2009             {"excepts:bad:%XY:encoded",S_OK,FALSE},
2010             {"",S_FALSE,FALSE},
2011             {"urn:excepts:bad:%XY:encoded",S_OK,FALSE},
2012             {"urn",S_OK,FALSE},
2013             {"",S_FALSE,FALSE},
2014             {"",S_FALSE,FALSE}
2015         },
2016         {
2017             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2018             {0,S_FALSE,FALSE},
2019             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2020             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2021         }
2022     },
2023     /* Since the original URI doesn't contain an extra '/' before the path no % encoded values
2024      * are decoded and all '%' are encoded.
2025      */
2026     {   "file://C:/te%3Es%2Et/tes%t.mp3", 0, S_OK, FALSE,
2027         {
2028             {"file:///C:/te%253Es%252Et/tes%25t.mp3",S_OK,FALSE},
2029             {"",S_FALSE,FALSE},
2030             {"file:///C:/te%253Es%252Et/tes%25t.mp3",S_OK,FALSE},
2031             {"",S_FALSE,FALSE},
2032             {".mp3",S_OK,FALSE},
2033             {"",S_FALSE,FALSE},
2034             {"",S_FALSE,FALSE},
2035             {"",S_FALSE,FALSE},
2036             {"/C:/te%253Es%252Et/tes%25t.mp3",S_OK,FALSE},
2037             {"/C:/te%253Es%252Et/tes%25t.mp3",S_OK,FALSE},
2038             {"",S_FALSE,FALSE},
2039             {"file://C:/te%3Es%2Et/tes%t.mp3",S_OK,FALSE},
2040             {"file",S_OK,FALSE},
2041             {"",S_FALSE,FALSE},
2042             {"",S_FALSE,FALSE}
2043         },
2044         {
2045             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2046             {0,S_FALSE,FALSE},
2047             {URL_SCHEME_FILE,S_OK,FALSE},
2048             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2049         }
2050     },
2051     /* Since there's a '/' in front of the drive letter, any percent encoded, non-forbidden character
2052      * is decoded and only %'s in front of invalid hex digits are encoded.
2053      */
2054     {   "file:///C:/te%3Es%2Et/t%23es%t.mp3", 0, S_OK, FALSE,
2055         {
2056             {"file:///C:/te%3Es.t/t#es%25t.mp3",S_OK,FALSE},
2057             {"",S_FALSE,FALSE},
2058             {"file:///C:/te%3Es.t/t#es%25t.mp3",S_OK,FALSE},
2059             {"",S_FALSE,FALSE},
2060             {".mp3",S_OK,FALSE},
2061             {"",S_FALSE,FALSE},
2062             {"",S_FALSE,FALSE},
2063             {"",S_FALSE,FALSE},
2064             {"/C:/te%3Es.t/t#es%25t.mp3",S_OK,FALSE},
2065             {"/C:/te%3Es.t/t#es%25t.mp3",S_OK,FALSE},
2066             {"",S_FALSE,FALSE},
2067             {"file:///C:/te%3Es%2Et/t%23es%t.mp3",S_OK,FALSE},
2068             {"file",S_OK,FALSE},
2069             {"",S_FALSE,FALSE},
2070             {"",S_FALSE,FALSE}
2071         },
2072         {
2073             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2074             {0,S_FALSE,FALSE},
2075             {URL_SCHEME_FILE,S_OK,FALSE},
2076             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2077         }
2078     },
2079     /* Only unreserved percent encoded characters are decoded for known schemes that aren't file. */
2080     {   "http://[::001.002.003.000]/%3F%23%2E%54/test", 0, S_OK, FALSE,
2081         {
2082             {"http://[::1.2.3.0]/%3F%23.T/test",S_OK,FALSE},
2083             {"[::1.2.3.0]",S_OK,FALSE},
2084             {"http://[::1.2.3.0]/%3F%23.T/test",S_OK,FALSE},
2085             {"",S_FALSE,FALSE},
2086             {"",S_FALSE,FALSE},
2087             {"",S_FALSE,FALSE},
2088             {"::1.2.3.0",S_OK,FALSE},
2089             {"",S_FALSE,FALSE},
2090             {"/%3F%23.T/test",S_OK,FALSE},
2091             {"/%3F%23.T/test",S_OK,FALSE},
2092             {"",S_FALSE,FALSE},
2093             {"http://[::001.002.003.000]/%3F%23%2E%54/test",S_OK,FALSE},
2094             {"http",S_OK,FALSE},
2095             {"",S_FALSE,FALSE},
2096             {"",S_FALSE,FALSE},
2097         },
2098         {
2099             {Uri_HOST_IPV6,S_OK,FALSE},
2100             {80,S_OK,FALSE},
2101             {URL_SCHEME_HTTP,S_OK,FALSE},
2102             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2103         }
2104     },
2105     /* Forbidden characters are always encoded for file URIs. */
2106     {   "file:///C:/\"test\"/test.mp3", Uri_CREATE_NO_ENCODE_FORBIDDEN_CHARACTERS, S_OK, FALSE,
2107         {
2108             {"file:///C:/%22test%22/test.mp3",S_OK,FALSE},
2109             {"",S_FALSE,FALSE},
2110             {"file:///C:/%22test%22/test.mp3",S_OK,FALSE},
2111             {"",S_FALSE,FALSE},
2112             {".mp3",S_OK,FALSE},
2113             {"",S_FALSE,FALSE},
2114             {"",S_FALSE,FALSE},
2115             {"",S_FALSE,FALSE},
2116             {"/C:/%22test%22/test.mp3",S_OK,FALSE},
2117             {"/C:/%22test%22/test.mp3",S_OK,FALSE},
2118             {"",S_FALSE,FALSE},
2119             {"file:///C:/\"test\"/test.mp3",S_OK,FALSE},
2120             {"file",S_OK,FALSE},
2121             {"",S_FALSE,FALSE},
2122             {"",S_FALSE,FALSE}
2123         },
2124         {
2125             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2126             {0,S_FALSE,FALSE},
2127             {URL_SCHEME_FILE,S_OK,FALSE},
2128             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2129         }
2130     },
2131     /* Forbidden characters are never encoded for unknown scheme types. */
2132     {   "1234://4294967295/<|>\" test<|>", 0, S_OK, FALSE,
2133         {
2134             {"1234://4294967295/<|>\" test<|>",S_OK,FALSE},
2135             {"4294967295",S_OK,FALSE},
2136             {"1234://4294967295/<|>\" test<|>",S_OK,FALSE},
2137             {"",S_FALSE,FALSE},
2138             {"",S_FALSE,FALSE},
2139             {"",S_FALSE,FALSE},
2140             {"4294967295",S_OK,FALSE},
2141             {"",S_FALSE,FALSE},
2142             {"/<|>\" test<|>",S_OK,FALSE},
2143             {"/<|>\" test<|>",S_OK,FALSE},
2144             {"",S_FALSE,FALSE},
2145             {"1234://4294967295/<|>\" test<|>",S_OK,FALSE},
2146             {"1234",S_OK,FALSE},
2147             {"",S_FALSE,FALSE},
2148             {"",S_FALSE,FALSE}
2149         },
2150         {
2151             {Uri_HOST_IPV4,S_OK,FALSE},
2152             {0,S_FALSE,FALSE},
2153             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2154             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2155         }
2156     },
2157     /* Make sure forbidden characters are percent encoded. */
2158     {   "http://gov.uk/<|> test<|>", 0, S_OK, FALSE,
2159         {
2160             {"http://gov.uk/%3C%7C%3E%20test%3C%7C%3E",S_OK,FALSE},
2161             {"gov.uk",S_OK,FALSE},
2162             {"http://gov.uk/%3C%7C%3E%20test%3C%7C%3E",S_OK,FALSE},
2163             {"",S_FALSE,FALSE},
2164             {"",S_FALSE,FALSE},
2165             {"",S_FALSE,FALSE},
2166             {"gov.uk",S_OK,FALSE},
2167             {"",S_FALSE,FALSE},
2168             {"/%3C%7C%3E%20test%3C%7C%3E",S_OK,FALSE},
2169             {"/%3C%7C%3E%20test%3C%7C%3E",S_OK,FALSE},
2170             {"",S_FALSE,FALSE},
2171             {"http://gov.uk/<|> test<|>",S_OK,FALSE},
2172             {"http",S_OK,FALSE},
2173             {"",S_FALSE,FALSE},
2174             {"",S_FALSE,FALSE}
2175         },
2176         {
2177             {Uri_HOST_DNS,S_OK,FALSE},
2178             {80,S_OK,FALSE},
2179             {URL_SCHEME_HTTP,S_OK,FALSE},
2180             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2181         }
2182     },
2183     {   "http://gov.uk/test/../test2/././../test3/.././././", 0, S_OK, FALSE,
2184         {
2185             {"http://gov.uk/",S_OK,FALSE},
2186             {"gov.uk",S_OK,FALSE},
2187             {"http://gov.uk/",S_OK,FALSE},
2188             {"",S_FALSE,FALSE},
2189             {"",S_FALSE,FALSE},
2190             {"",S_FALSE,FALSE},
2191             {"gov.uk",S_OK,FALSE},
2192             {"",S_FALSE,FALSE},
2193             {"/",S_OK,FALSE},
2194             {"/",S_OK,FALSE},
2195             {"",S_FALSE,FALSE},
2196             {"http://gov.uk/test/../test2/././../test3/.././././",S_OK,FALSE},
2197             {"http",S_OK,FALSE},
2198             {"",S_FALSE,FALSE},
2199             {"",S_FALSE,FALSE}
2200         },
2201         {
2202             {Uri_HOST_DNS,S_OK,FALSE},
2203             {80,S_OK,FALSE},
2204             {URL_SCHEME_HTTP,S_OK,FALSE},
2205             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2206         }
2207     },
2208     {   "http://gov.uk/test/test2/../../..", 0, S_OK, FALSE,
2209         {
2210             {"http://gov.uk/",S_OK,FALSE},
2211             {"gov.uk",S_OK,FALSE},
2212             {"http://gov.uk/",S_OK,FALSE},
2213             {"",S_FALSE,FALSE},
2214             {"",S_FALSE,FALSE},
2215             {"",S_FALSE,FALSE},
2216             {"gov.uk",S_OK,FALSE},
2217             {"",S_FALSE,FALSE},
2218             {"/",S_OK,FALSE},
2219             {"/",S_OK,FALSE},
2220             {"",S_FALSE,FALSE},
2221             {"http://gov.uk/test/test2/../../..",S_OK,FALSE},
2222             {"http",S_OK,FALSE},
2223             {"",S_FALSE,FALSE},
2224             {"",S_FALSE,FALSE}
2225         },
2226         {
2227             {Uri_HOST_DNS,S_OK,FALSE},
2228             {80,S_OK,FALSE},
2229             {URL_SCHEME_HTTP,S_OK,FALSE},
2230             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2231         }
2232     },
2233     {   "http://gov.uk/test/test2/../../.", 0, S_OK, FALSE,
2234         {
2235             {"http://gov.uk/",S_OK,FALSE},
2236             {"gov.uk",S_OK,FALSE},
2237             {"http://gov.uk/",S_OK,FALSE},
2238             {"",S_FALSE,FALSE},
2239             {"",S_FALSE,FALSE},
2240             {"",S_FALSE,FALSE},
2241             {"gov.uk",S_OK,FALSE},
2242             {"",S_FALSE,FALSE},
2243             {"/",S_OK,FALSE},
2244             {"/",S_OK,FALSE},
2245             {"",S_FALSE,FALSE},
2246             {"http://gov.uk/test/test2/../../.",S_OK,FALSE},
2247             {"http",S_OK,FALSE},
2248             {"",S_FALSE,FALSE},
2249             {"",S_FALSE,FALSE}
2250         },
2251         {
2252             {Uri_HOST_DNS,S_OK,FALSE},
2253             {80,S_OK,FALSE},
2254             {URL_SCHEME_HTTP,S_OK,FALSE},
2255             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2256         }
2257     },
2258     {   "file://c:\\tests\\../tests\\./.\\..\\foo%20bar.mp3", 0, S_OK, FALSE,
2259         {
2260             {"file:///c:/foo%2520bar.mp3",S_OK,FALSE},
2261             {"",S_FALSE,FALSE},
2262             {"file:///c:/foo%2520bar.mp3",S_OK,FALSE},
2263             {"",S_FALSE,FALSE},
2264             {".mp3",S_OK,FALSE},
2265             {"",S_FALSE,FALSE},
2266             {"",S_FALSE,FALSE},
2267             {"",S_FALSE,FALSE},
2268             {"/c:/foo%2520bar.mp3",S_OK,FALSE},
2269             {"/c:/foo%2520bar.mp3",S_OK,FALSE},
2270             {"",S_FALSE,FALSE},
2271             {"file://c:\\tests\\../tests\\./.\\..\\foo%20bar.mp3",S_OK,FALSE},
2272             {"file",S_OK,FALSE},
2273             {"",S_FALSE,FALSE},
2274             {"",S_FALSE,FALSE}
2275         },
2276         {
2277             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2278             {0,S_FALSE,FALSE},
2279             {URL_SCHEME_FILE,S_OK,FALSE},
2280             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2281         }
2282     },
2283     /* Dot removal happens for unknown scheme types. */
2284     {   "zip://gov.uk/test/test2/../../.", 0, S_OK, FALSE,
2285         {
2286             {"zip://gov.uk/",S_OK,FALSE},
2287             {"gov.uk",S_OK,FALSE},
2288             {"zip://gov.uk/",S_OK,FALSE},
2289             {"",S_FALSE,FALSE},
2290             {"",S_FALSE,FALSE},
2291             {"",S_FALSE,FALSE},
2292             {"gov.uk",S_OK,FALSE},
2293             {"",S_FALSE,FALSE},
2294             {"/",S_OK,FALSE},
2295             {"/",S_OK,FALSE},
2296             {"",S_FALSE,FALSE},
2297             {"zip://gov.uk/test/test2/../../.",S_OK,FALSE},
2298             {"zip",S_OK,FALSE},
2299             {"",S_FALSE,FALSE},
2300             {"",S_FALSE,FALSE}
2301         },
2302         {
2303             {Uri_HOST_DNS,S_OK,FALSE},
2304             {0,S_FALSE,FALSE},
2305             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2306             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2307         }
2308     },
2309     /* Dot removal doesn't happen if NO_CANONICALIZE is set. */
2310     {   "http://gov.uk/test/test2/../../.", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
2311         {
2312             {"http://gov.uk/test/test2/../../.",S_OK,FALSE},
2313             {"gov.uk",S_OK,FALSE},
2314             {"http://gov.uk/test/test2/../../.",S_OK,FALSE},
2315             {"",S_FALSE,FALSE},
2316             {".",S_OK,FALSE},
2317             {"",S_FALSE,FALSE},
2318             {"gov.uk",S_OK,FALSE},
2319             {"",S_FALSE,FALSE},
2320             {"/test/test2/../../.",S_OK,FALSE},
2321             {"/test/test2/../../.",S_OK,FALSE},
2322             {"",S_FALSE,FALSE},
2323             {"http://gov.uk/test/test2/../../.",S_OK,FALSE},
2324             {"http",S_OK,FALSE},
2325             {"",S_FALSE,FALSE},
2326             {"",S_FALSE,FALSE}
2327         },
2328         {
2329             {Uri_HOST_DNS,S_OK,FALSE},
2330             {80,S_OK,FALSE},
2331             {URL_SCHEME_HTTP,S_OK,FALSE},
2332             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2333         }
2334     },
2335     /* Dot removal doesn't happen for wildcard scheme types. */
2336     {   "*:gov.uk/test/test2/../../.", 0, S_OK, FALSE,
2337         {
2338             {"*:gov.uk/test/test2/../../.",S_OK,FALSE},
2339             {"gov.uk",S_OK,FALSE},
2340             {"*:gov.uk/test/test2/../../.",S_OK,FALSE},
2341             {"",S_FALSE,FALSE},
2342             {".",S_OK,FALSE},
2343             {"",S_FALSE,FALSE},
2344             {"gov.uk",S_OK,FALSE},
2345             {"",S_FALSE,FALSE},
2346             {"/test/test2/../../.",S_OK,FALSE},
2347             {"/test/test2/../../.",S_OK,FALSE},
2348             {"",S_FALSE,FALSE},
2349             {"*:gov.uk/test/test2/../../.",S_OK,FALSE},
2350             {"*",S_OK,FALSE},
2351             {"",S_FALSE,FALSE},
2352             {"",S_FALSE,FALSE}
2353         },
2354         {
2355             {Uri_HOST_DNS,S_OK,FALSE},
2356             {0,S_FALSE,FALSE},
2357             {URL_SCHEME_WILDCARD,S_OK,FALSE},
2358             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2359         }
2360     },
2361     /* Forbidden characters are encoded for opaque known scheme types. */
2362     {   "mailto:\"acco<|>unt@example.com\"", 0, S_OK, FALSE,
2363         {
2364             {"mailto:%22acco%3C%7C%3Eunt@example.com%22",S_OK,FALSE},
2365             {"",S_FALSE,FALSE},
2366             {"mailto:%22acco%3C%7C%3Eunt@example.com%22",S_OK,FALSE},
2367             {"",S_FALSE,FALSE},
2368             {".com%22",S_OK,FALSE},
2369             {"",S_FALSE,FALSE},
2370             {"",S_FALSE,FALSE},
2371             {"",S_FALSE,FALSE},
2372             {"%22acco%3C%7C%3Eunt@example.com%22",S_OK,FALSE},
2373             {"%22acco%3C%7C%3Eunt@example.com%22",S_OK,FALSE},
2374             {"",S_FALSE,FALSE},
2375             {"mailto:\"acco<|>unt@example.com\"",S_OK,FALSE},
2376             {"mailto",S_OK,FALSE},
2377             {"",S_FALSE,FALSE},
2378             {"",S_FALSE,FALSE}
2379         },
2380         {
2381             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2382             {0,S_FALSE,FALSE},
2383             {URL_SCHEME_MAILTO,S_OK,FALSE},
2384             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2385         }
2386     },
2387     {   "news:test.tes<|>t.com", 0, S_OK, FALSE,
2388         {
2389             {"news:test.tes%3C%7C%3Et.com",S_OK,FALSE},
2390             {"",S_FALSE,FALSE},
2391             {"news:test.tes%3C%7C%3Et.com",S_OK,FALSE},
2392             {"",S_FALSE,FALSE},
2393             {".com",S_OK,FALSE},
2394             {"",S_FALSE,FALSE},
2395             {"",S_FALSE,FALSE},
2396             {"",S_FALSE,FALSE},
2397             {"test.tes%3C%7C%3Et.com",S_OK,FALSE},
2398             {"test.tes%3C%7C%3Et.com",S_OK,FALSE},
2399             {"",S_FALSE,FALSE},
2400             {"news:test.tes<|>t.com",S_OK,FALSE},
2401             {"news",S_OK,FALSE},
2402             {"",S_FALSE,FALSE},
2403             {"",S_FALSE,FALSE}
2404         },
2405         {
2406             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2407             {0,S_FALSE,FALSE},
2408             {URL_SCHEME_NEWS,S_OK,FALSE},
2409             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2410         }
2411     },
2412     /* Don't encode forbidden characters. */
2413     {   "news:test.tes<|>t.com", Uri_CREATE_NO_ENCODE_FORBIDDEN_CHARACTERS, S_OK, FALSE,
2414         {
2415             {"news:test.tes<|>t.com",S_OK,FALSE},
2416             {"",S_FALSE,FALSE},
2417             {"news:test.tes<|>t.com",S_OK,FALSE},
2418             {"",S_FALSE,FALSE},
2419             {".com",S_OK,FALSE},
2420             {"",S_FALSE,FALSE},
2421             {"",S_FALSE,FALSE},
2422             {"",S_FALSE,FALSE},
2423             {"test.tes<|>t.com",S_OK,FALSE},
2424             {"test.tes<|>t.com",S_OK,FALSE},
2425             {"",S_FALSE,FALSE},
2426             {"news:test.tes<|>t.com",S_OK,FALSE},
2427             {"news",S_OK,FALSE},
2428             {"",S_FALSE,FALSE},
2429             {"",S_FALSE,FALSE}
2430         },
2431         {
2432             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2433             {0,S_FALSE,FALSE},
2434             {URL_SCHEME_NEWS,S_OK,FALSE},
2435             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2436         }
2437     },
2438     /* Forbidden characters aren't encoded for unknown, opaque URIs. */
2439     {   "urn:test.tes<|>t.com", 0, S_OK, FALSE,
2440         {
2441             {"urn:test.tes<|>t.com",S_OK,FALSE},
2442             {"",S_FALSE,FALSE},
2443             {"urn:test.tes<|>t.com",S_OK,FALSE},
2444             {"",S_FALSE,FALSE},
2445             {".com",S_OK,FALSE},
2446             {"",S_FALSE,FALSE},
2447             {"",S_FALSE,FALSE},
2448             {"",S_FALSE,FALSE},
2449             {"test.tes<|>t.com",S_OK,FALSE},
2450             {"test.tes<|>t.com",S_OK,FALSE},
2451             {"",S_FALSE,FALSE},
2452             {"urn:test.tes<|>t.com",S_OK,FALSE},
2453             {"urn",S_OK,FALSE},
2454             {"",S_FALSE,FALSE},
2455             {"",S_FALSE,FALSE}
2456         },
2457         {
2458             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2459             {0,S_FALSE,FALSE},
2460             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2461             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2462         }
2463     },
2464     /* Percent encoded unreserved characters are decoded for known opaque URIs. */
2465     {   "news:test.%74%65%73%74.com", 0, S_OK, FALSE,
2466         {
2467             {"news:test.test.com",S_OK,FALSE},
2468             {"",S_FALSE,FALSE},
2469             {"news:test.test.com",S_OK,FALSE},
2470             {"",S_FALSE,FALSE},
2471             {".com",S_OK,FALSE},
2472             {"",S_FALSE,FALSE},
2473             {"",S_FALSE,FALSE},
2474             {"",S_FALSE,FALSE},
2475             {"test.test.com",S_OK,FALSE},
2476             {"test.test.com",S_OK,FALSE},
2477             {"",S_FALSE,FALSE},
2478             {"news:test.%74%65%73%74.com",S_OK,FALSE},
2479             {"news",S_OK,FALSE},
2480             {"",S_FALSE,FALSE},
2481             {"",S_FALSE,FALSE}
2482         },
2483         {
2484             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2485             {0,S_FALSE,FALSE},
2486             {URL_SCHEME_NEWS,S_OK,FALSE},
2487             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2488         }
2489     },
2490     /* Percent encoded characters are still decoded for known scheme types. */
2491     {   "news:test.%74%65%73%74.com", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
2492         {
2493             {"news:test.test.com",S_OK,FALSE},
2494             {"",S_FALSE,FALSE},
2495             {"news:test.test.com",S_OK,FALSE},
2496             {"",S_FALSE,FALSE},
2497             {".com",S_OK,FALSE},
2498             {"",S_FALSE,FALSE},
2499             {"",S_FALSE,FALSE},
2500             {"",S_FALSE,FALSE},
2501             {"test.test.com",S_OK,FALSE},
2502             {"test.test.com",S_OK,FALSE},
2503             {"",S_FALSE,FALSE},
2504             {"news:test.%74%65%73%74.com",S_OK,FALSE},
2505             {"news",S_OK,FALSE},
2506             {"",S_FALSE,FALSE},
2507             {"",S_FALSE,FALSE}
2508         },
2509         {
2510             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2511             {0,S_FALSE,FALSE},
2512             {URL_SCHEME_NEWS,S_OK,FALSE},
2513             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2514         }
2515     },
2516     /* Percent encoded characters aren't decoded for unknown scheme types. */
2517     {   "urn:test.%74%65%73%74.com", 0, S_OK, FALSE,
2518         {
2519             {"urn:test.%74%65%73%74.com",S_OK,FALSE},
2520             {"",S_FALSE,FALSE},
2521             {"urn:test.%74%65%73%74.com",S_OK,FALSE},
2522             {"",S_FALSE,FALSE},
2523             {".com",S_OK,FALSE},
2524             {"",S_FALSE,FALSE},
2525             {"",S_FALSE,FALSE},
2526             {"",S_FALSE,FALSE},
2527             {"test.%74%65%73%74.com",S_OK,FALSE},
2528             {"test.%74%65%73%74.com",S_OK,FALSE},
2529             {"",S_FALSE,FALSE},
2530             {"urn:test.%74%65%73%74.com",S_OK,FALSE},
2531             {"urn",S_OK,FALSE},
2532             {"",S_FALSE,FALSE},
2533             {"",S_FALSE,FALSE}
2534         },
2535         {
2536             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2537             {0,S_FALSE,FALSE},
2538             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2539             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2540         }
2541     },
2542     /* Unknown scheme types can have invalid % encoded data in query string. */
2543     {   "zip://www.winehq.org/tests/..?query=%xx&return=y", 0, S_OK, FALSE,
2544         {
2545             {"zip://www.winehq.org/?query=%xx&return=y",S_OK,FALSE},
2546             {"www.winehq.org",S_OK,FALSE},
2547             {"zip://www.winehq.org/?query=%xx&return=y",S_OK,FALSE},
2548             {"winehq.org",S_OK,FALSE},
2549             {"",S_FALSE,FALSE},
2550             {"",S_FALSE,FALSE},
2551             {"www.winehq.org",S_OK,FALSE},
2552             {"",S_FALSE,FALSE},
2553             {"/",S_OK,FALSE},
2554             {"/?query=%xx&return=y",S_OK,FALSE},
2555             {"?query=%xx&return=y",S_OK,FALSE},
2556             {"zip://www.winehq.org/tests/..?query=%xx&return=y",S_OK,FALSE},
2557             {"zip",S_OK,FALSE},
2558             {"",S_FALSE,FALSE},
2559             {"",S_FALSE,FALSE}
2560         },
2561         {
2562             {Uri_HOST_DNS,S_OK,FALSE},
2563             {0,S_FALSE,FALSE},
2564             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2565             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2566         }
2567     },
2568     /* Known scheme types can have invalid % encoded data with the right flags. */
2569     {   "http://www.winehq.org/tests/..?query=%xx&return=y", Uri_CREATE_NO_DECODE_EXTRA_INFO, S_OK, FALSE,
2570         {
2571             {"http://www.winehq.org/?query=%xx&return=y",S_OK,FALSE},
2572             {"www.winehq.org",S_OK,FALSE},
2573             {"http://www.winehq.org/?query=%xx&return=y",S_OK,FALSE},
2574             {"winehq.org",S_OK,FALSE},
2575             {"",S_FALSE,FALSE},
2576             {"",S_FALSE,FALSE},
2577             {"www.winehq.org",S_OK,FALSE},
2578             {"",S_FALSE,FALSE},
2579             {"/",S_OK,FALSE},
2580             {"/?query=%xx&return=y",S_OK,FALSE},
2581             {"?query=%xx&return=y",S_OK,FALSE},
2582             {"http://www.winehq.org/tests/..?query=%xx&return=y",S_OK,FALSE},
2583             {"http",S_OK,FALSE},
2584             {"",S_FALSE,FALSE},
2585             {"",S_FALSE,FALSE}
2586         },
2587         {
2588             {Uri_HOST_DNS,S_OK,FALSE},
2589             {80,S_OK,FALSE},
2590             {URL_SCHEME_HTTP,S_OK,FALSE},
2591             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2592         }
2593     },
2594     /* Forbidden characters in query aren't percent encoded for known scheme types with this flag. */
2595     {   "http://www.winehq.org/tests/..?query=<|>&return=y", Uri_CREATE_NO_DECODE_EXTRA_INFO, S_OK, FALSE,
2596         {
2597             {"http://www.winehq.org/?query=<|>&return=y",S_OK,FALSE},
2598             {"www.winehq.org",S_OK,FALSE},
2599             {"http://www.winehq.org/?query=<|>&return=y",S_OK,FALSE},
2600             {"winehq.org",S_OK,FALSE},
2601             {"",S_FALSE,FALSE},
2602             {"",S_FALSE,FALSE},
2603             {"www.winehq.org",S_OK,FALSE},
2604             {"",S_FALSE,FALSE},
2605             {"/",S_OK,FALSE},
2606             {"/?query=<|>&return=y",S_OK,FALSE},
2607             {"?query=<|>&return=y",S_OK,FALSE},
2608             {"http://www.winehq.org/tests/..?query=<|>&return=y",S_OK,FALSE},
2609             {"http",S_OK,FALSE},
2610             {"",S_FALSE,FALSE},
2611             {"",S_FALSE,FALSE}
2612         },
2613         {
2614             {Uri_HOST_DNS,S_OK,FALSE},
2615             {80,S_OK,FALSE},
2616             {URL_SCHEME_HTTP,S_OK,FALSE},
2617             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2618         }
2619     },
2620     /* Forbidden characters in query aren't percent encoded for known scheme types with this flag. */
2621     {   "http://www.winehq.org/tests/..?query=<|>&return=y", Uri_CREATE_NO_ENCODE_FORBIDDEN_CHARACTERS, S_OK, FALSE,
2622         {
2623             {"http://www.winehq.org/?query=<|>&return=y",S_OK,FALSE},
2624             {"www.winehq.org",S_OK,FALSE},
2625             {"http://www.winehq.org/?query=<|>&return=y",S_OK,FALSE},
2626             {"winehq.org",S_OK,FALSE},
2627             {"",S_FALSE,FALSE},
2628             {"",S_FALSE,FALSE},
2629             {"www.winehq.org",S_OK,FALSE},
2630             {"",S_FALSE,FALSE},
2631             {"/",S_OK,FALSE},
2632             {"/?query=<|>&return=y",S_OK,FALSE},
2633             {"?query=<|>&return=y",S_OK,FALSE},
2634             {"http://www.winehq.org/tests/..?query=<|>&return=y",S_OK,FALSE},
2635             {"http",S_OK,FALSE},
2636             {"",S_FALSE,FALSE},
2637             {"",S_FALSE,FALSE}
2638         },
2639         {
2640             {Uri_HOST_DNS,S_OK,FALSE},
2641             {80,S_OK,FALSE},
2642             {URL_SCHEME_HTTP,S_OK,FALSE},
2643             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2644         }
2645     },
2646     /* Forbidden characters are encoded for known scheme types. */
2647     {   "http://www.winehq.org/tests/..?query=<|>&return=y", 0, S_OK, FALSE,
2648         {
2649             {"http://www.winehq.org/?query=%3C%7C%3E&return=y",S_OK,FALSE},
2650             {"www.winehq.org",S_OK,FALSE},
2651             {"http://www.winehq.org/?query=%3C%7C%3E&return=y",S_OK,FALSE},
2652             {"winehq.org",S_OK,FALSE},
2653             {"",S_FALSE,FALSE},
2654             {"",S_FALSE,FALSE},
2655             {"www.winehq.org",S_OK,FALSE},
2656             {"",S_FALSE,FALSE},
2657             {"/",S_OK,FALSE},
2658             {"/?query=%3C%7C%3E&return=y",S_OK,FALSE},
2659             {"?query=%3C%7C%3E&return=y",S_OK,FALSE},
2660             {"http://www.winehq.org/tests/..?query=<|>&return=y",S_OK,FALSE},
2661             {"http",S_OK,FALSE},
2662             {"",S_FALSE,FALSE},
2663             {"",S_FALSE,FALSE}
2664         },
2665         {
2666             {Uri_HOST_DNS,S_OK,FALSE},
2667             {80,S_OK,FALSE},
2668             {URL_SCHEME_HTTP,S_OK,FALSE},
2669             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2670         }
2671     },
2672     /* Forbidden characters are not encoded for unknown scheme types. */
2673     {   "zip://www.winehq.org/tests/..?query=<|>&return=y", 0, S_OK, FALSE,
2674         {
2675             {"zip://www.winehq.org/?query=<|>&return=y",S_OK,FALSE},
2676             {"www.winehq.org",S_OK,FALSE},
2677             {"zip://www.winehq.org/?query=<|>&return=y",S_OK,FALSE},
2678             {"winehq.org",S_OK,FALSE},
2679             {"",S_FALSE,FALSE},
2680             {"",S_FALSE,FALSE},
2681             {"www.winehq.org",S_OK,FALSE},
2682             {"",S_FALSE,FALSE},
2683             {"/",S_OK,FALSE},
2684             {"/?query=<|>&return=y",S_OK,FALSE},
2685             {"?query=<|>&return=y",S_OK,FALSE},
2686             {"zip://www.winehq.org/tests/..?query=<|>&return=y",S_OK,FALSE},
2687             {"zip",S_OK,FALSE},
2688             {"",S_FALSE,FALSE},
2689             {"",S_FALSE,FALSE}
2690         },
2691         {
2692             {Uri_HOST_DNS,S_OK,FALSE},
2693             {0,S_FALSE,FALSE},
2694             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2695             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2696         }
2697     },
2698     /* Percent encoded, unreserved characters are decoded for known scheme types. */
2699     {   "http://www.winehq.org/tests/..?query=%30%31&return=y", 0, S_OK, FALSE,
2700         {
2701             {"http://www.winehq.org/?query=01&return=y",S_OK,FALSE},
2702             {"www.winehq.org",S_OK,FALSE},
2703             {"http://www.winehq.org/?query=01&return=y",S_OK,FALSE},
2704             {"winehq.org",S_OK,FALSE},
2705             {"",S_FALSE,FALSE},
2706             {"",S_FALSE,FALSE},
2707             {"www.winehq.org",S_OK,FALSE},
2708             {"",S_FALSE,FALSE},
2709             {"/",S_OK,FALSE},
2710             {"/?query=01&return=y",S_OK,FALSE},
2711             {"?query=01&return=y",S_OK,FALSE},
2712             {"http://www.winehq.org/tests/..?query=%30%31&return=y",S_OK,FALSE},
2713             {"http",S_OK,FALSE},
2714             {"",S_FALSE,FALSE},
2715             {"",S_FALSE,FALSE}
2716         },
2717         {
2718             {Uri_HOST_DNS,S_OK,FALSE},
2719             {80,S_OK,FALSE},
2720             {URL_SCHEME_HTTP,S_OK,FALSE},
2721             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2722         }
2723     },
2724     /* Percent encoded, unreserved characters aren't decoded for unknown scheme types. */
2725     {   "zip://www.winehq.org/tests/..?query=%30%31&return=y", 0, S_OK, FALSE,
2726         {
2727             {"zip://www.winehq.org/?query=%30%31&return=y",S_OK,FALSE},
2728             {"www.winehq.org",S_OK,FALSE},
2729             {"zip://www.winehq.org/?query=%30%31&return=y",S_OK,FALSE},
2730             {"winehq.org",S_OK,FALSE},
2731             {"",S_FALSE,FALSE},
2732             {"",S_FALSE,FALSE},
2733             {"www.winehq.org",S_OK,FALSE},
2734             {"",S_FALSE,FALSE},
2735             {"/",S_OK,FALSE},
2736             {"/?query=%30%31&return=y",S_OK,FALSE},
2737             {"?query=%30%31&return=y",S_OK,FALSE},
2738             {"zip://www.winehq.org/tests/..?query=%30%31&return=y",S_OK,FALSE},
2739             {"zip",S_OK,FALSE},
2740             {"",S_FALSE,FALSE},
2741             {"",S_FALSE,FALSE}
2742         },
2743         {
2744             {Uri_HOST_DNS,S_OK,FALSE},
2745             {0,S_FALSE,FALSE},
2746             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2747             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2748         }
2749     },
2750     /* Percent encoded characters aren't decoded when NO_DECODE_EXTRA_INFO is set. */
2751     {   "http://www.winehq.org/tests/..?query=%30%31&return=y", Uri_CREATE_NO_DECODE_EXTRA_INFO, S_OK, FALSE,
2752         {
2753             {"http://www.winehq.org/?query=%30%31&return=y",S_OK,FALSE},
2754             {"www.winehq.org",S_OK,FALSE},
2755             {"http://www.winehq.org/?query=%30%31&return=y",S_OK,FALSE},
2756             {"winehq.org",S_OK,FALSE},
2757             {"",S_FALSE,FALSE},
2758             {"",S_FALSE,FALSE},
2759             {"www.winehq.org",S_OK,FALSE},
2760             {"",S_FALSE,FALSE},
2761             {"/",S_OK,FALSE},
2762             {"/?query=%30%31&return=y",S_OK,FALSE},
2763             {"?query=%30%31&return=y",S_OK,FALSE},
2764             {"http://www.winehq.org/tests/..?query=%30%31&return=y",S_OK,FALSE},
2765             {"http",S_OK,FALSE},
2766             {"",S_FALSE,FALSE},
2767             {"",S_FALSE,FALSE}
2768         },
2769         {
2770             {Uri_HOST_DNS,S_OK,FALSE},
2771             {80,S_OK,FALSE},
2772             {URL_SCHEME_HTTP,S_OK,FALSE},
2773             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2774         }
2775     },
2776     {   "http://www.winehq.org?query=12&return=y", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
2777         {
2778             {"http://www.winehq.org?query=12&return=y",S_OK,FALSE},
2779             {"www.winehq.org",S_OK,FALSE},
2780             {"http://www.winehq.org?query=12&return=y",S_OK,FALSE},
2781             {"winehq.org",S_OK,FALSE},
2782             {"",S_FALSE,FALSE},
2783             {"",S_FALSE,FALSE},
2784             {"www.winehq.org",S_OK,FALSE},
2785             {"",S_FALSE,FALSE},
2786             {"",S_FALSE,FALSE},
2787             {"?query=12&return=y",S_OK,FALSE},
2788             {"?query=12&return=y",S_OK,FALSE},
2789             {"http://www.winehq.org?query=12&return=y",S_OK,FALSE},
2790             {"http",S_OK,FALSE},
2791             {"",S_FALSE,FALSE},
2792             {"",S_FALSE,FALSE}
2793         },
2794         {
2795             {Uri_HOST_DNS,S_OK,FALSE},
2796             {80,S_OK,FALSE},
2797             {URL_SCHEME_HTTP,S_OK,FALSE},
2798             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2799         }
2800     },
2801     /* Unknown scheme types can have invalid % encoded data in fragments. */
2802     {   "zip://www.winehq.org/tests/#Te%xx", 0, S_OK, FALSE,
2803         {
2804             {"zip://www.winehq.org/tests/#Te%xx",S_OK,FALSE},
2805             {"www.winehq.org",S_OK,FALSE},
2806             {"zip://www.winehq.org/tests/#Te%xx",S_OK,FALSE},
2807             {"winehq.org",S_OK,FALSE},
2808             {"",S_FALSE,FALSE},
2809             {"#Te%xx",S_OK,FALSE},
2810             {"www.winehq.org",S_OK,FALSE},
2811             {"",S_FALSE,FALSE},
2812             {"/tests/",S_OK,FALSE},
2813             {"/tests/",S_OK,FALSE},
2814             {"",S_FALSE,FALSE},
2815             {"zip://www.winehq.org/tests/#Te%xx",S_OK,FALSE},
2816             {"zip",S_OK,FALSE},
2817             {"",S_FALSE,FALSE},
2818             {"",S_FALSE,FALSE}
2819         },
2820         {
2821             {Uri_HOST_DNS,S_OK,FALSE},
2822             {0,S_FALSE,FALSE},
2823             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2824             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2825         }
2826     },
2827     /* Forbidden characters in fragment aren't encoded for unknown schemes. */
2828     {   "zip://www.winehq.org/tests/#Te<|>", 0, S_OK, FALSE,
2829         {
2830             {"zip://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
2831             {"www.winehq.org",S_OK,FALSE},
2832             {"zip://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
2833             {"winehq.org",S_OK,FALSE},
2834             {"",S_FALSE,FALSE},
2835             {"#Te<|>",S_OK,FALSE},
2836             {"www.winehq.org",S_OK,FALSE},
2837             {"",S_FALSE,FALSE},
2838             {"/tests/",S_OK,FALSE},
2839             {"/tests/",S_OK,FALSE},
2840             {"",S_FALSE,FALSE},
2841             {"zip://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
2842             {"zip",S_OK,FALSE},
2843             {"",S_FALSE,FALSE},
2844             {"",S_FALSE,FALSE}
2845         },
2846         {
2847             {Uri_HOST_DNS,S_OK,FALSE},
2848             {0,S_FALSE,FALSE},
2849             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2850             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2851         }
2852     },
2853     /* Forbidden characters in the fragment are percent encoded for known schemes. */
2854     {   "http://www.winehq.org/tests/#Te<|>", 0, S_OK, FALSE,
2855         {
2856             {"http://www.winehq.org/tests/#Te%3C%7C%3E",S_OK,FALSE},
2857             {"www.winehq.org",S_OK,FALSE},
2858             {"http://www.winehq.org/tests/#Te%3C%7C%3E",S_OK,FALSE},
2859             {"winehq.org",S_OK,FALSE},
2860             {"",S_FALSE,FALSE},
2861             {"#Te%3C%7C%3E",S_OK,FALSE},
2862             {"www.winehq.org",S_OK,FALSE},
2863             {"",S_FALSE,FALSE},
2864             {"/tests/",S_OK,FALSE},
2865             {"/tests/",S_OK,FALSE},
2866             {"",S_FALSE,FALSE},
2867             {"http://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
2868             {"http",S_OK,FALSE},
2869             {"",S_FALSE,FALSE},
2870             {"",S_FALSE,FALSE}
2871         },
2872         {
2873             {Uri_HOST_DNS,S_OK,FALSE},
2874             {80,S_OK,FALSE},
2875             {URL_SCHEME_HTTP,S_OK,FALSE},
2876             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2877         }
2878     },
2879     /* Forbidden characters aren't encoded in the fragment with this flag. */
2880     {   "http://www.winehq.org/tests/#Te<|>", Uri_CREATE_NO_DECODE_EXTRA_INFO, S_OK, FALSE,
2881         {
2882             {"http://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
2883             {"www.winehq.org",S_OK,FALSE},
2884             {"http://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
2885             {"winehq.org",S_OK,FALSE},
2886             {"",S_FALSE,FALSE},
2887             {"#Te<|>",S_OK,FALSE},
2888             {"www.winehq.org",S_OK,FALSE},
2889             {"",S_FALSE,FALSE},
2890             {"/tests/",S_OK,FALSE},
2891             {"/tests/",S_OK,FALSE},
2892             {"",S_FALSE,FALSE},
2893             {"http://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
2894             {"http",S_OK,FALSE},
2895             {"",S_FALSE,FALSE},
2896             {"",S_FALSE,FALSE}
2897         },
2898         {
2899             {Uri_HOST_DNS,S_OK,FALSE},
2900             {80,S_OK,FALSE},
2901             {URL_SCHEME_HTTP,S_OK,FALSE},
2902             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2903         }
2904     },
2905     /* Forbidden characters aren't encoded in the fragment with this flag. */
2906     {   "http://www.winehq.org/tests/#Te<|>", Uri_CREATE_NO_ENCODE_FORBIDDEN_CHARACTERS, S_OK, FALSE,
2907         {
2908             {"http://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
2909             {"www.winehq.org",S_OK,FALSE},
2910             {"http://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
2911             {"winehq.org",S_OK,FALSE},
2912             {"",S_FALSE,FALSE},
2913             {"#Te<|>",S_OK,FALSE},
2914             {"www.winehq.org",S_OK,FALSE},
2915             {"",S_FALSE,FALSE},
2916             {"/tests/",S_OK,FALSE},
2917             {"/tests/",S_OK,FALSE},
2918             {"",S_FALSE,FALSE},
2919             {"http://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
2920             {"http",S_OK,FALSE},
2921             {"",S_FALSE,FALSE},
2922             {"",S_FALSE,FALSE}
2923         },
2924         {
2925             {Uri_HOST_DNS,S_OK,FALSE},
2926             {80,S_OK,FALSE},
2927             {URL_SCHEME_HTTP,S_OK,FALSE},
2928             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2929         }
2930     },
2931     /* Percent encoded, unreserved characters aren't decoded for known scheme types. */
2932     {   "zip://www.winehq.org/tests/#Te%30%31%32", 0, S_OK, FALSE,
2933         {
2934             {"zip://www.winehq.org/tests/#Te%30%31%32",S_OK,FALSE},
2935             {"www.winehq.org",S_OK,FALSE},
2936             {"zip://www.winehq.org/tests/#Te%30%31%32",S_OK,FALSE},
2937             {"winehq.org",S_OK,FALSE},
2938             {"",S_FALSE,FALSE},
2939             {"#Te%30%31%32",S_OK,FALSE},
2940             {"www.winehq.org",S_OK,FALSE},
2941             {"",S_FALSE,FALSE},
2942             {"/tests/",S_OK,FALSE},
2943             {"/tests/",S_OK,FALSE},
2944             {"",S_FALSE,FALSE},
2945             {"zip://www.winehq.org/tests/#Te%30%31%32",S_OK,FALSE},
2946             {"zip",S_OK,FALSE},
2947             {"",S_FALSE,FALSE},
2948             {"",S_FALSE,FALSE}
2949         },
2950         {
2951             {Uri_HOST_DNS,S_OK,FALSE},
2952             {0,S_FALSE,FALSE},
2953             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2954             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2955         }
2956     },
2957     /* Percent encoded, unreserved characters are decoded for known schemes. */
2958     {   "http://www.winehq.org/tests/#Te%30%31%32", 0, S_OK, FALSE,
2959         {
2960             {"http://www.winehq.org/tests/#Te012",S_OK,FALSE},
2961             {"www.winehq.org",S_OK,FALSE},
2962             {"http://www.winehq.org/tests/#Te012",S_OK,FALSE},
2963             {"winehq.org",S_OK,FALSE},
2964             {"",S_FALSE,FALSE},
2965             {"#Te012",S_OK,FALSE},
2966             {"www.winehq.org",S_OK,FALSE},
2967             {"",S_FALSE,FALSE},
2968             {"/tests/",S_OK,FALSE},
2969             {"/tests/",S_OK,FALSE},
2970             {"",S_FALSE,FALSE},
2971             {"http://www.winehq.org/tests/#Te%30%31%32",S_OK,FALSE},
2972             {"http",S_OK,FALSE},
2973             {"",S_FALSE,FALSE},
2974             {"",S_FALSE,FALSE}
2975         },
2976         {
2977             {Uri_HOST_DNS,S_OK,FALSE},
2978             {80,S_OK,FALSE},
2979             {URL_SCHEME_HTTP,S_OK,FALSE},
2980             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2981         }
2982     },
2983     /* Percent encoded, unreserved characters are decoded even if NO_CANONICALIZE is set. */
2984     {   "http://www.winehq.org/tests/#Te%30%31%32", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
2985         {
2986             {"http://www.winehq.org/tests/#Te012",S_OK,FALSE},
2987             {"www.winehq.org",S_OK,FALSE},
2988             {"http://www.winehq.org/tests/#Te012",S_OK,FALSE},
2989             {"winehq.org",S_OK,FALSE},
2990             {"",S_FALSE,FALSE},
2991             {"#Te012",S_OK,FALSE},
2992             {"www.winehq.org",S_OK,FALSE},
2993             {"",S_FALSE,FALSE},
2994             {"/tests/",S_OK,FALSE},
2995             {"/tests/",S_OK,FALSE},
2996             {"",S_FALSE,FALSE},
2997             {"http://www.winehq.org/tests/#Te%30%31%32",S_OK,FALSE},
2998             {"http",S_OK,FALSE},
2999             {"",S_FALSE,FALSE},
3000             {"",S_FALSE,FALSE}
3001         },
3002         {
3003             {Uri_HOST_DNS,S_OK,FALSE},
3004             {80,S_OK,FALSE},
3005             {URL_SCHEME_HTTP,S_OK,FALSE},
3006             {URLZONE_INVALID,E_NOTIMPL,FALSE},
3007         }
3008     },
3009     /* Percent encoded, unreserved characters aren't decoded when NO_DECODE_EXTRA is set. */
3010     {   "http://www.winehq.org/tests/#Te%30%31%32", Uri_CREATE_NO_DECODE_EXTRA_INFO, S_OK, FALSE,
3011         {
3012             {"http://www.winehq.org/tests/#Te%30%31%32",S_OK,FALSE},
3013             {"www.winehq.org",S_OK,FALSE},
3014             {"http://www.winehq.org/tests/#Te%30%31%32",S_OK,FALSE},
3015             {"winehq.org",S_OK,FALSE},
3016             {"",S_FALSE,FALSE},
3017             {"#Te%30%31%32",S_OK,FALSE},
3018             {"www.winehq.org",S_OK,FALSE},
3019             {"",S_FALSE,FALSE},
3020             {"/tests/",S_OK,FALSE},
3021             {"/tests/",S_OK,FALSE},
3022             {"",S_FALSE,FALSE},
3023             {"http://www.winehq.org/tests/#Te%30%31%32",S_OK,FALSE},
3024             {"http",S_OK,FALSE},
3025             {"",S_FALSE,FALSE},
3026             {"",S_FALSE,FALSE}
3027         },
3028         {
3029             {Uri_HOST_DNS,S_OK,FALSE},
3030             {80,S_OK,FALSE},
3031             {URL_SCHEME_HTTP,S_OK,FALSE},
3032             {URLZONE_INVALID,E_NOTIMPL,FALSE},
3033         }
3034     },
3035     /* Leading/Trailing whitespace is removed. */
3036     {   "    http://google.com/     ", 0, S_OK, FALSE,
3037         {
3038             {"http://google.com/",S_OK,FALSE},
3039             {"google.com",S_OK,FALSE},
3040             {"http://google.com/",S_OK,FALSE},
3041             {"google.com",S_OK,FALSE},
3042             {"",S_FALSE,FALSE},
3043             {"",S_FALSE,FALSE},
3044             {"google.com",S_OK,FALSE},
3045             {"",S_FALSE,FALSE},
3046             {"/",S_OK,FALSE},
3047             {"/",S_OK,FALSE},
3048             {"",S_FALSE,FALSE},
3049             {"http://google.com/",S_OK,FALSE},
3050             {"http",S_OK,FALSE},
3051             {"",S_FALSE,FALSE},
3052             {"",S_FALSE,FALSE}
3053         },
3054         {
3055             {Uri_HOST_DNS,S_OK,FALSE},
3056             {80,S_OK,FALSE},
3057             {URL_SCHEME_HTTP,S_OK,FALSE},
3058             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3059         }
3060     },
3061     {   "\t\t\r\nhttp\n://g\noogle.co\rm/\n\n\n", 0, S_OK, FALSE,
3062         {
3063             {"http://google.com/",S_OK,FALSE},
3064             {"google.com",S_OK,FALSE},
3065             {"http://google.com/",S_OK,FALSE},
3066             {"google.com",S_OK,FALSE},
3067             {"",S_FALSE,FALSE},
3068             {"",S_FALSE,FALSE},
3069             {"google.com",S_OK,FALSE},
3070             {"",S_FALSE,FALSE},
3071             {"/",S_OK,FALSE},
3072             {"/",S_OK,FALSE},
3073             {"",S_FALSE,FALSE},
3074             {"http://google.com/",S_OK,FALSE},
3075             {"http",S_OK,FALSE},
3076             {"",S_FALSE,FALSE},
3077             {"",S_FALSE,FALSE}
3078         },
3079         {
3080             {Uri_HOST_DNS,S_OK,FALSE},
3081             {80,S_OK,FALSE},
3082             {URL_SCHEME_HTTP,S_OK,FALSE},
3083             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3084         }
3085     },
3086     {   "http://g\noogle.co\rm/\n\n\n", Uri_CREATE_NO_PRE_PROCESS_HTML_URI, S_OK, FALSE,
3087         {
3088             {"http://g%0aoogle.co%0dm/%0A%0A%0A",S_OK,FALSE},
3089             {"g%0aoogle.co%0dm",S_OK,FALSE},
3090             {"http://g%0aoogle.co%0dm/%0A%0A%0A",S_OK,FALSE},
3091             {"g%0aoogle.co%0dm",S_OK,FALSE},
3092             {"",S_FALSE,FALSE},
3093             {"",S_FALSE,FALSE},
3094             {"g%0aoogle.co%0dm",S_OK,FALSE},
3095             {"",S_FALSE,FALSE},
3096             {"/%0A%0A%0A",S_OK,FALSE},
3097             {"/%0A%0A%0A",S_OK,FALSE},
3098             {"",S_FALSE,FALSE},
3099             {"http://g\noogle.co\rm/\n\n\n",S_OK,FALSE},
3100             {"http",S_OK,FALSE},
3101             {"",S_FALSE,FALSE},
3102             {"",S_FALSE,FALSE}
3103         },
3104         {
3105             {Uri_HOST_DNS,S_OK,FALSE},
3106             {80,S_OK,FALSE},
3107             {URL_SCHEME_HTTP,S_OK,FALSE},
3108             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3109         }
3110     },
3111     {   "zip://g\noogle.co\rm/\n\n\n", Uri_CREATE_NO_PRE_PROCESS_HTML_URI, S_OK, FALSE,
3112         {
3113             {"zip://g\noogle.co\rm/\n\n\n",S_OK,FALSE},
3114             {"g\noogle.co\rm",S_OK,FALSE},
3115             {"zip://g\noogle.co\rm/\n\n\n",S_OK,FALSE},
3116             {"g\noogle.co\rm",S_OK,FALSE},
3117             {"",S_FALSE,FALSE},
3118             {"",S_FALSE,FALSE},
3119             {"g\noogle.co\rm",S_OK,FALSE},
3120             {"",S_FALSE,FALSE},
3121             {"/\n\n\n",S_OK,FALSE},
3122             {"/\n\n\n",S_OK,FALSE},
3123             {"",S_FALSE,FALSE},
3124             {"zip://g\noogle.co\rm/\n\n\n",S_OK,FALSE},
3125             {"zip",S_OK,FALSE},
3126             {"",S_FALSE,FALSE},
3127             {"",S_FALSE,FALSE}
3128         },
3129         {
3130             {Uri_HOST_DNS,S_OK,FALSE},
3131             {0,S_FALSE,FALSE},
3132             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
3133             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3134         }
3135     },
3136     /* Since file URLs are usually hierarchical, it returns an empty string
3137      * for the absolute URI property since it was declared as an opaque URI.
3138      */
3139     {   "file:index.html", 0, S_OK, FALSE,
3140         {
3141             {"",S_FALSE,FALSE},
3142             {"",S_FALSE,FALSE},
3143             {"file:index.html",S_OK,FALSE},
3144             {"",S_FALSE,FALSE},
3145             {".html",S_OK,FALSE},
3146             {"",S_FALSE,FALSE},
3147             {"",S_FALSE,FALSE},
3148             {"",S_FALSE,FALSE},
3149             {"index.html",S_OK,FALSE},
3150             {"index.html",S_OK,FALSE},
3151             {"",S_FALSE,FALSE},
3152             {"file:index.html",S_OK,FALSE},
3153             {"file",S_OK,FALSE},
3154             {"",S_FALSE,FALSE},
3155             {"",S_FALSE,FALSE}
3156         },
3157         {
3158             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3159             {0,S_FALSE,FALSE},
3160             {URL_SCHEME_FILE,S_OK,FALSE},
3161             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3162         }
3163     },
3164     /* Doesn't have an absolute since it's opaque, but gets it port set. */
3165     {   "http:test.com/index.html", 0, S_OK, FALSE,
3166         {
3167             {"",S_FALSE,FALSE},
3168             {"",S_FALSE,FALSE},
3169             {"http:test.com/index.html",S_OK,FALSE},
3170             {"",S_FALSE,FALSE},
3171             {".html",S_OK,FALSE},
3172             {"",S_FALSE,FALSE},
3173             {"",S_FALSE,FALSE},
3174             {"",S_FALSE,FALSE},
3175             {"test.com/index.html",S_OK,FALSE},
3176             {"test.com/index.html",S_OK,FALSE},
3177             {"",S_FALSE,FALSE},
3178             {"http:test.com/index.html",S_OK,FALSE},
3179             {"http",S_OK,FALSE},
3180             {"",S_FALSE,FALSE},
3181             {"",S_FALSE,FALSE}
3182         },
3183         {
3184             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3185             {80,S_OK,FALSE},
3186             {URL_SCHEME_HTTP,S_OK,FALSE},
3187             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3188         }
3189     },
3190     {   "ftp:test.com/index.html", 0, S_OK, FALSE,
3191         {
3192             {"",S_FALSE,FALSE},
3193             {"",S_FALSE,FALSE},
3194             {"ftp:test.com/index.html",S_OK,FALSE},
3195             {"",S_FALSE,FALSE},
3196             {".html",S_OK,FALSE},
3197             {"",S_FALSE,FALSE},
3198             {"",S_FALSE,FALSE},
3199             {"",S_FALSE,FALSE},
3200             {"test.com/index.html",S_OK,FALSE},
3201             {"test.com/index.html",S_OK,FALSE},
3202             {"",S_FALSE,FALSE},
3203             {"ftp:test.com/index.html",S_OK,FALSE},
3204             {"ftp",S_OK,FALSE},
3205             {"",S_FALSE,FALSE},
3206             {"",S_FALSE,FALSE}
3207         },
3208         {
3209             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3210             {21,S_OK,FALSE},
3211             {URL_SCHEME_FTP,S_OK,FALSE},
3212             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3213         }
3214     },
3215     {   "file://C|/test.mp3", 0, S_OK, FALSE,
3216         {
3217             {"file:///C:/test.mp3",S_OK,FALSE},
3218             {"",S_FALSE,FALSE},
3219             {"file:///C:/test.mp3",S_OK,FALSE},
3220             {"",S_FALSE,FALSE},
3221             {".mp3",S_OK,FALSE},
3222             {"",S_FALSE,FALSE},
3223             {"",S_FALSE,FALSE},
3224             {"",S_FALSE,FALSE},
3225             {"/C:/test.mp3",S_OK,FALSE},
3226             {"/C:/test.mp3",S_OK,FALSE},
3227             {"",S_FALSE,FALSE},
3228             {"file://C|/test.mp3",S_OK,FALSE},
3229             {"file",S_OK,FALSE},
3230             {"",S_FALSE,FALSE},
3231             {"",S_FALSE,FALSE}
3232         },
3233         {
3234             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3235             {0,S_FALSE,FALSE},
3236             {URL_SCHEME_FILE,S_OK,FALSE},
3237             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3238         }
3239     },
3240     {   "file:///C|/test.mp3", 0, S_OK, FALSE,
3241         {
3242             {"file:///C:/test.mp3",S_OK,FALSE},
3243             {"",S_FALSE,FALSE},
3244             {"file:///C:/test.mp3",S_OK,FALSE},
3245             {"",S_FALSE,FALSE},
3246             {".mp3",S_OK,FALSE},
3247             {"",S_FALSE,FALSE},
3248             {"",S_FALSE,FALSE},
3249             {"",S_FALSE,FALSE},
3250             {"/C:/test.mp3",S_OK,FALSE},
3251             {"/C:/test.mp3",S_OK,FALSE},
3252             {"",S_FALSE,FALSE},
3253             {"file:///C|/test.mp3",S_OK,FALSE},
3254             {"file",S_OK,FALSE},
3255             {"",S_FALSE,FALSE},
3256             {"",S_FALSE,FALSE}
3257         },
3258         {
3259             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3260             {0,S_FALSE,FALSE},
3261             {URL_SCHEME_FILE,S_OK,FALSE},
3262             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3263         }
3264     },
3265     /* Extra '/' isn't added before "c:" since USE_DOS_PATH is set and '/' are converted
3266      * to '\\'.
3267      */
3268     {   "file://c:/dir/index.html", Uri_CREATE_FILE_USE_DOS_PATH, S_OK, FALSE,
3269         {
3270             {"file://c:\\dir\\index.html",S_OK,FALSE},
3271             {"",S_FALSE,FALSE},
3272             {"file://c:\\dir\\index.html",S_OK,FALSE},
3273             {"",S_FALSE,FALSE},
3274             {".html",S_OK,FALSE},
3275             {"",S_FALSE,FALSE},
3276             {"",S_FALSE,FALSE},
3277             {"",S_FALSE,FALSE},
3278             {"c:\\dir\\index.html",S_OK,FALSE},
3279             {"c:\\dir\\index.html",S_OK,FALSE},
3280             {"",S_FALSE,FALSE},
3281             {"file://c:/dir/index.html",S_OK,FALSE},
3282             {"file",S_OK,FALSE},
3283             {"",S_FALSE,FALSE},
3284             {"",S_FALSE,FALSE}
3285         },
3286         {
3287             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3288             {0,S_FALSE,FALSE},
3289             {URL_SCHEME_FILE,S_OK,FALSE},
3290             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3291         }
3292     },
3293     /* Extra '/' after "file://" is removed. */
3294     {   "file:///c:/dir/index.html", Uri_CREATE_FILE_USE_DOS_PATH, S_OK, FALSE,
3295         {
3296             {"file://c:\\dir\\index.html",S_OK,FALSE},
3297             {"",S_FALSE,FALSE},
3298             {"file://c:\\dir\\index.html",S_OK,FALSE},
3299             {"",S_FALSE,FALSE},
3300             {".html",S_OK,FALSE},
3301             {"",S_FALSE,FALSE},
3302             {"",S_FALSE,FALSE},
3303             {"",S_FALSE,FALSE},
3304             {"c:\\dir\\index.html",S_OK,FALSE},
3305             {"c:\\dir\\index.html",S_OK,FALSE},
3306             {"",S_FALSE,FALSE},
3307             {"file:///c:/dir/index.html",S_OK,FALSE},
3308             {"file",S_OK,FALSE},
3309             {"",S_FALSE,FALSE},
3310             {"",S_FALSE,FALSE}
3311         },
3312         {
3313             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3314             {0,S_FALSE,FALSE},
3315             {URL_SCHEME_FILE,S_OK,FALSE},
3316             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3317         }
3318     },
3319     /* Allow more characters when Uri_CREATE_FILE_USE_DOS_PATH is specified */
3320     {   "file:///c:/dir\\%%61%20%5Fname/file%2A.html", Uri_CREATE_FILE_USE_DOS_PATH, S_OK, FALSE,
3321         {
3322             {"file://c:\\dir\\%a _name\\file*.html",S_OK,FALSE},
3323             {"",S_FALSE,FALSE},
3324             {"file://c:\\dir\\%a _name\\file*.html",S_OK,FALSE},
3325             {"",S_FALSE,FALSE},
3326             {".html",S_OK,FALSE},
3327             {"",S_FALSE,FALSE},
3328             {"",S_FALSE,FALSE},
3329             {"",S_FALSE,FALSE},
3330             {"c:\\dir\\%a _name\\file*.html",S_OK,FALSE},
3331             {"c:\\dir\\%a _name\\file*.html",S_OK,FALSE},
3332             {"",S_FALSE,FALSE},
3333             {"file:///c:/dir\\%%61%20%5Fname/file%2A.html",S_OK,FALSE},
3334             {"file",S_OK,FALSE},
3335             {"",S_FALSE,FALSE},
3336             {"",S_FALSE,FALSE}
3337         },
3338         {
3339             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3340             {0,S_FALSE,FALSE},
3341             {URL_SCHEME_FILE,S_OK,FALSE},
3342             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3343         }
3344     },
3345     {   "file://c|/dir\\index.html", Uri_CREATE_FILE_USE_DOS_PATH, S_OK, FALSE,
3346         {
3347             {"file://c:\\dir\\index.html",S_OK,FALSE},
3348             {"",S_FALSE,FALSE},
3349             {"file://c:\\dir\\index.html",S_OK,FALSE},
3350             {"",S_FALSE,FALSE},
3351             {".html",S_OK,FALSE},
3352             {"",S_FALSE,FALSE},
3353             {"",S_FALSE,FALSE},
3354             {"",S_FALSE,FALSE},
3355             {"c:\\dir\\index.html",S_OK,FALSE},
3356             {"c:\\dir\\index.html",S_OK,FALSE},
3357             {"",S_FALSE,FALSE},
3358             {"file://c|/dir\\index.html",S_OK,FALSE},
3359             {"file",S_OK,FALSE},
3360             {"",S_FALSE,FALSE},
3361             {"",S_FALSE,FALSE}
3362         },
3363         {
3364             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3365             {0,S_FALSE,FALSE},
3366             {URL_SCHEME_FILE,S_OK,FALSE},
3367             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3368         }
3369     },
3370     /* The backslashes after the scheme name are converted to forward slashes. */
3371     {   "file:\\\\c:\\dir\\index.html", Uri_CREATE_FILE_USE_DOS_PATH, S_OK, FALSE,
3372         {
3373             {"file://c:\\dir\\index.html",S_OK,FALSE},
3374             {"",S_FALSE,FALSE},
3375             {"file://c:\\dir\\index.html",S_OK,FALSE},
3376             {"",S_FALSE,FALSE},
3377             {".html",S_OK,FALSE},
3378             {"",S_FALSE,FALSE},
3379             {"",S_FALSE,FALSE},
3380             {"",S_FALSE,FALSE},
3381             {"c:\\dir\\index.html",S_OK,FALSE},
3382             {"c:\\dir\\index.html",S_OK,FALSE},
3383             {"",S_FALSE,FALSE},
3384             {"file:\\\\c:\\dir\\index.html",S_OK,FALSE},
3385             {"file",S_OK,FALSE},
3386             {"",S_FALSE,FALSE},
3387             {"",S_FALSE,FALSE}
3388         },
3389         {
3390             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3391             {0,S_FALSE,FALSE},
3392             {URL_SCHEME_FILE,S_OK,FALSE},
3393             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3394         }
3395     },
3396     {   "file:\\\\c:/dir/index.html", 0, S_OK, FALSE,
3397         {
3398             {"file:///c:/dir/index.html",S_OK,FALSE},
3399             {"",S_FALSE,FALSE},
3400             {"file:///c:/dir/index.html",S_OK,FALSE},
3401             {"",S_FALSE,FALSE},
3402             {".html",S_OK,FALSE},
3403             {"",S_FALSE,FALSE},
3404             {"",S_FALSE,FALSE},
3405             {"",S_FALSE,FALSE},
3406             {"/c:/dir/index.html",S_OK,FALSE},
3407             {"/c:/dir/index.html",S_OK,FALSE},
3408             {"",S_FALSE,FALSE},
3409             {"file:\\\\c:/dir/index.html",S_OK,FALSE},
3410             {"file",S_OK,FALSE},
3411             {"",S_FALSE,FALSE},
3412             {"",S_FALSE,FALSE}
3413         },
3414         {
3415             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3416             {0,S_FALSE,FALSE},
3417             {URL_SCHEME_FILE,S_OK,FALSE},
3418             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3419         }
3420     },
3421     {   "http:\\\\google.com", 0, S_OK, FALSE,
3422         {
3423             {"http://google.com/",S_OK,FALSE},
3424             {"google.com",S_OK,FALSE},
3425             {"http://google.com/",S_OK,FALSE},
3426             {"google.com",S_OK,FALSE},
3427             {"",S_FALSE,FALSE},
3428             {"",S_FALSE,FALSE},
3429             {"google.com",S_OK,FALSE},
3430             {"",S_FALSE,FALSE},
3431             {"/",S_OK,FALSE},
3432             {"/",S_OK,FALSE},
3433             {"",S_FALSE,FALSE},
3434             {"http:\\\\google.com",S_OK,FALSE},
3435             {"http",S_OK,FALSE},
3436             {"",S_FALSE,FALSE},
3437             {"",S_FALSE,FALSE}
3438         },
3439         {
3440             {Uri_HOST_DNS,S_OK,FALSE},
3441             {80,S_OK,FALSE},
3442             {URL_SCHEME_HTTP,S_OK,FALSE},
3443             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3444         }
3445     },
3446     /* the "\\\\" aren't converted to "//" for unknown scheme types and it's considered opaque. */
3447     {   "zip:\\\\google.com", 0, S_OK, FALSE,
3448         {
3449             {"zip:\\\\google.com",S_OK,FALSE},
3450             {"",S_FALSE,FALSE},
3451             {"zip:\\\\google.com",S_OK,FALSE},
3452             {"",S_FALSE,FALSE},
3453             {".com",S_OK,FALSE},
3454             {"",S_FALSE,FALSE},
3455             {"",S_FALSE,FALSE},
3456             {"",S_FALSE,FALSE},
3457             {"\\\\google.com",S_OK,FALSE},
3458             {"\\\\google.com",S_OK,FALSE},
3459             {"",S_FALSE,FALSE},
3460             {"zip:\\\\google.com",S_OK,FALSE},
3461             {"zip",S_OK,FALSE},
3462             {"",S_FALSE,FALSE},
3463             {"",S_FALSE,FALSE}
3464         },
3465         {
3466             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3467             {0,S_FALSE,FALSE},
3468             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
3469             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3470         }
3471     },
3472     /* Dot segments aren't removed. */
3473     {   "file://c:\\dir\\../..\\./index.html", Uri_CREATE_FILE_USE_DOS_PATH, S_OK, FALSE,
3474         {
3475             {"file://c:\\dir\\..\\..\\.\\index.html",S_OK,FALSE},
3476             {"",S_FALSE,FALSE},
3477             {"file://c:\\dir\\..\\..\\.\\index.html",S_OK,FALSE},
3478             {"",S_FALSE,FALSE},
3479             {".html",S_OK,FALSE},
3480             {"",S_FALSE,FALSE},
3481             {"",S_FALSE,FALSE},
3482             {"",S_FALSE,FALSE},
3483             {"c:\\dir\\..\\..\\.\\index.html",S_OK,FALSE},
3484             {"c:\\dir\\..\\..\\.\\index.html",S_OK,FALSE},
3485             {"",S_FALSE,FALSE},
3486             {"file://c:\\dir\\../..\\./index.html",S_OK,FALSE},
3487             {"file",S_OK,FALSE},
3488             {"",S_FALSE,FALSE},
3489             {"",S_FALSE,FALSE}
3490         },
3491         {
3492             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3493             {0,S_FALSE,FALSE},
3494             {URL_SCHEME_FILE,S_OK,FALSE},
3495             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3496         }
3497     },
3498     /* Forbidden characters aren't percent encoded. */
3499     {   "file://c:\\dir\\i^|ndex.html", Uri_CREATE_FILE_USE_DOS_PATH, S_OK, FALSE,
3500         {
3501             {"file://c:\\dir\\i^|ndex.html",S_OK,FALSE},
3502             {"",S_FALSE,FALSE},
3503             {"file://c:\\dir\\i^|ndex.html",S_OK,FALSE},
3504             {"",S_FALSE,FALSE},
3505             {".html",S_OK,FALSE},
3506             {"",S_FALSE,FALSE},
3507             {"",S_FALSE,FALSE},
3508             {"",S_FALSE,FALSE},
3509             {"c:\\dir\\i^|ndex.html",S_OK,FALSE},
3510             {"c:\\dir\\i^|ndex.html",S_OK,FALSE},
3511             {"",S_FALSE,FALSE},
3512             {"file://c:\\dir\\i^|ndex.html",S_OK,FALSE},
3513             {"file",S_OK,FALSE},
3514             {"",S_FALSE,FALSE},
3515             {"",S_FALSE,FALSE}
3516         },
3517         {
3518             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3519             {0,S_FALSE,FALSE},
3520             {URL_SCHEME_FILE,S_OK,FALSE},
3521             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3522         }
3523     },
3524     /* The '\' are still converted to '/' even though it's an opaque file URI. */
3525     {   "file:c:\\dir\\../..\\index.html", 0, S_OK, FALSE,
3526         {
3527             {"",S_FALSE,FALSE},
3528             {"",S_FALSE,FALSE},
3529             {"file:c:/dir/../../index.html",S_OK,FALSE},
3530             {"",S_FALSE,FALSE},
3531             {".html",S_OK,FALSE},
3532             {"",S_FALSE,FALSE},
3533             {"",S_FALSE,FALSE},
3534             {"",S_FALSE,FALSE},
3535             {"c:/dir/../../index.html",S_OK,FALSE},
3536             {"c:/dir/../../index.html",S_OK,FALSE},
3537             {"",S_FALSE,FALSE},
3538             {"file:c:\\dir\\../..\\index.html",S_OK,FALSE},
3539             {"file",S_OK,FALSE},
3540             {"",S_FALSE,FALSE},
3541             {"",S_FALSE,FALSE}
3542         },
3543         {
3544             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3545             {0,S_FALSE,FALSE},
3546             {URL_SCHEME_FILE,S_OK,FALSE},
3547             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3548         }
3549     },
3550     /* '/' are still converted to '\' even though it's an opaque URI. */
3551     {   "file:c:/dir\\../..\\index.html", Uri_CREATE_FILE_USE_DOS_PATH, S_OK, FALSE,
3552         {
3553             {"",S_FALSE,FALSE},
3554             {"",S_FALSE,FALSE},
3555             {"file:c:\\dir\\..\\..\\index.html",S_OK,FALSE},
3556             {"",S_FALSE,FALSE},
3557             {".html",S_OK,FALSE},
3558             {"",S_FALSE,FALSE},
3559             {"",S_FALSE,FALSE},
3560             {"",S_FALSE,FALSE},
3561             {"c:\\dir\\..\\..\\index.html",S_OK,FALSE},
3562             {"c:\\dir\\..\\..\\index.html",S_OK,FALSE},
3563             {"",S_FALSE,FALSE},
3564             {"file:c:/dir\\../..\\index.html",S_OK,FALSE},
3565             {"file",S_OK,FALSE},
3566             {"",S_FALSE,FALSE},
3567             {"",S_FALSE,FALSE}
3568         },
3569         {
3570             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3571             {0,S_FALSE,FALSE},
3572             {URL_SCHEME_FILE,S_OK,FALSE},
3573             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3574         }
3575     },
3576     /* Forbidden characters aren't percent encoded. */
3577     {   "file:c:\\in^|dex.html", Uri_CREATE_FILE_USE_DOS_PATH, S_OK, FALSE,
3578         {
3579             {"",S_FALSE,FALSE},
3580             {"",S_FALSE,FALSE},
3581             {"file:c:\\in^|dex.html",S_OK,FALSE},
3582             {"",S_FALSE,FALSE},
3583             {".html",S_OK,FALSE},
3584             {"",S_FALSE,FALSE},
3585             {"",S_FALSE,FALSE},
3586             {"",S_FALSE,FALSE},
3587             {"c:\\in^|dex.html",S_OK,FALSE},
3588             {"c:\\in^|dex.html",S_OK,FALSE},
3589             {"",S_FALSE,FALSE},
3590             {"file:c:\\in^|dex.html",S_OK,FALSE},
3591             {"file",S_OK,FALSE},
3592             {"",S_FALSE,FALSE},
3593             {"",S_FALSE,FALSE}
3594         },
3595         {
3596             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3597             {0,S_FALSE,FALSE},
3598             {URL_SCHEME_FILE,S_OK,FALSE},
3599             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3600         }
3601     },
3602     /* Doesn't have a UserName since the ':' appears at the beginning of the
3603      * userinfo section.
3604      */
3605     {   "http://:password@gov.uk", 0, S_OK, FALSE,
3606         {
3607             {"http://:password@gov.uk/",S_OK,FALSE},
3608             {":password@gov.uk",S_OK,FALSE},
3609             {"http://gov.uk/",S_OK,FALSE},
3610             {"",S_FALSE,FALSE},
3611             {"",S_FALSE,FALSE},
3612             {"",S_FALSE,FALSE},
3613             {"gov.uk",S_OK,FALSE},
3614             {"password",S_OK,FALSE},
3615             {"/",S_OK,FALSE},
3616             {"/",S_OK,FALSE},
3617             {"",S_FALSE,FALSE},
3618             {"http://:password@gov.uk",S_OK,FALSE},
3619             {"http",S_OK,FALSE},
3620             {":password",S_OK,FALSE},
3621             {"",S_FALSE,FALSE}
3622         },
3623         {
3624             {Uri_HOST_DNS,S_OK,FALSE},
3625             {80,S_OK,FALSE},
3626             {URL_SCHEME_HTTP,S_OK,FALSE},
3627             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3628         }
3629     },
3630     /* Has a UserName since the userinfo section doesn't contain a password. */
3631     {   "http://@gov.uk", 0, S_OK, FALSE,
3632         {
3633             {"http://gov.uk/",S_OK,FALSE,"http://@gov.uk/"},
3634             {"@gov.uk",S_OK,FALSE},
3635             {"http://gov.uk/",S_OK,FALSE},
3636             {"",S_FALSE,FALSE},
3637             {"",S_FALSE,FALSE},
3638             {"",S_FALSE,FALSE},
3639             {"gov.uk",S_OK,FALSE},
3640             {"",S_FALSE,FALSE},
3641             {"/",S_OK,FALSE},
3642             {"/",S_OK,FALSE},
3643             {"",S_FALSE,FALSE},
3644             {"http://@gov.uk",S_OK,FALSE},
3645             {"http",S_OK,FALSE},
3646             {"",S_OK,FALSE},
3647             {"",S_OK,FALSE}
3648         },
3649         {
3650             {Uri_HOST_DNS,S_OK,FALSE},
3651             {80,S_OK,FALSE},
3652             {URL_SCHEME_HTTP,S_OK,FALSE},
3653             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3654         }
3655     },
3656     /* ":@" not included in the absolute URI. */
3657     {   "http://:@gov.uk", 0, S_OK, FALSE,
3658         {
3659             {"http://gov.uk/",S_OK,FALSE,"http://:@gov.uk/"},
3660             {":@gov.uk",S_OK,FALSE},
3661             {"http://gov.uk/",S_OK,FALSE},
3662             {"",S_FALSE,FALSE},
3663             {"",S_FALSE,FALSE},
3664             {"",S_FALSE,FALSE},
3665             {"gov.uk",S_OK,FALSE},
3666             {"",S_OK,FALSE},
3667             {"/",S_OK,FALSE},
3668             {"/",S_OK,FALSE},
3669             {"",S_FALSE,FALSE},
3670             {"http://:@gov.uk",S_OK,FALSE},
3671             {"http",S_OK,FALSE},
3672             {":",S_OK,FALSE},
3673             {"",S_FALSE,FALSE}
3674         },
3675         {
3676             {Uri_HOST_DNS,S_OK,FALSE},
3677             {80,S_OK,FALSE},
3678             {URL_SCHEME_HTTP,S_OK,FALSE},
3679             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3680         }
3681     },
3682     /* '@' is included because it's an unknown scheme type. */
3683     {   "zip://@gov.uk", 0, S_OK, FALSE,
3684         {
3685             {"zip://@gov.uk/",S_OK,FALSE},
3686             {"@gov.uk",S_OK,FALSE},
3687             {"zip://@gov.uk/",S_OK,FALSE},
3688             {"",S_FALSE,FALSE},
3689             {"",S_FALSE,FALSE},
3690             {"",S_FALSE,FALSE},
3691             {"gov.uk",S_OK,FALSE},
3692             {"",S_FALSE,FALSE},
3693             {"/",S_OK,FALSE},
3694             {"/",S_OK,FALSE},
3695             {"",S_FALSE,FALSE},
3696             {"zip://@gov.uk",S_OK,FALSE},
3697             {"zip",S_OK,FALSE},
3698             {"",S_OK,FALSE},
3699             {"",S_OK,FALSE}
3700         },
3701         {
3702             {Uri_HOST_DNS,S_OK,FALSE},
3703             {0,S_FALSE,FALSE},
3704             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
3705             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3706         }
3707     },
3708     /* ":@" are included because it's an unknown scheme type. */
3709     {   "zip://:@gov.uk", 0, S_OK, FALSE,
3710         {
3711             {"zip://:@gov.uk/",S_OK,FALSE},
3712             {":@gov.uk",S_OK,FALSE},
3713             {"zip://:@gov.uk/",S_OK,FALSE},
3714             {"",S_FALSE,FALSE},
3715             {"",S_FALSE,FALSE},
3716             {"",S_FALSE,FALSE},
3717             {"gov.uk",S_OK,FALSE},
3718             {"",S_OK,FALSE},
3719             {"/",S_OK,FALSE},
3720             {"/",S_OK,FALSE},
3721             {"",S_FALSE,FALSE},
3722             {"zip://:@gov.uk",S_OK,FALSE},
3723             {"zip",S_OK,FALSE},
3724             {":",S_OK,FALSE},
3725             {"",S_FALSE,FALSE}
3726         },
3727         {
3728             {Uri_HOST_DNS,S_OK,FALSE},
3729             {0,S_FALSE,FALSE},
3730             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
3731             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3732         }
3733     },
3734     {   "about:blank", 0, S_OK, FALSE,
3735         {
3736             {"about:blank",S_OK,FALSE},
3737             {"",S_FALSE,FALSE},
3738             {"about:blank",S_OK,FALSE},
3739             {"",S_FALSE,FALSE},
3740             {"",S_FALSE,FALSE},
3741             {"",S_FALSE,FALSE},
3742             {"",S_FALSE,FALSE},
3743             {"",S_FALSE,FALSE},
3744             {"blank",S_OK,FALSE},
3745             {"blank",S_OK,FALSE},
3746             {"",S_FALSE,FALSE},
3747             {"about:blank",S_OK,FALSE},
3748             {"about",S_OK,FALSE},
3749             {"",S_FALSE,FALSE},
3750             {"",S_FALSE,FALSE}
3751         },
3752         {
3753             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3754             {0,S_FALSE,FALSE},
3755             {URL_SCHEME_ABOUT,S_OK,FALSE},
3756             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3757         }
3758     },
3759     {   "mk:@MSITStore:C:\\Program Files/AutoCAD 2008\\Help/acad_acg.chm::/WSfacf1429558a55de1a7524c1004e616f8b-322b.htm",0,S_OK,FALSE,
3760         {
3761             {"mk:@MSITStore:C:\\Program%20Files/AutoCAD%202008\\Help/acad_acg.chm::/WSfacf1429558a55de1a7524c1004e616f8b-322b.htm",S_OK,FALSE},
3762             {"",S_FALSE,FALSE},
3763             {"mk:@MSITStore:C:\\Program%20Files/AutoCAD%202008\\Help/acad_acg.chm::/WSfacf1429558a55de1a7524c1004e616f8b-322b.htm",S_OK,FALSE},
3764             {"",S_FALSE,FALSE},
3765             {".htm",S_OK,FALSE},
3766             {"",S_FALSE,FALSE},
3767             {"",S_FALSE,FALSE},
3768             {"",S_FALSE,FALSE},
3769             {"@MSITStore:C:\\Program%20Files/AutoCAD%202008\\Help/acad_acg.chm::/WSfacf1429558a55de1a7524c1004e616f8b-322b.htm",S_OK,FALSE},
3770             {"@MSITStore:C:\\Program%20Files/AutoCAD%202008\\Help/acad_acg.chm::/WSfacf1429558a55de1a7524c1004e616f8b-322b.htm",S_OK,FALSE},
3771             {"",S_FALSE,FALSE},
3772             {"mk:@MSITStore:C:\\Program Files/AutoCAD 2008\\Help/acad_acg.chm::/WSfacf1429558a55de1a7524c1004e616f8b-322b.htm",S_OK,FALSE},
3773             {"mk",S_OK,FALSE},
3774             {"",S_FALSE,FALSE},
3775             {"",S_FALSE,FALSE}
3776         },
3777         {
3778             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3779             {0,S_FALSE,FALSE},
3780             {URL_SCHEME_MK,S_OK,FALSE},
3781             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3782         }
3783     },
3784     {   "mk:@MSITStore:Z:\\home\\test\\chm\\silqhelp.chm::/thesilqquickstartguide.htm",0,S_OK,FALSE,
3785         {
3786             {"mk:@MSITStore:Z:\\home\\test\\chm\\silqhelp.chm::/thesilqquickstartguide.htm",S_OK,FALSE},
3787             {"",S_FALSE,FALSE},
3788             {"mk:@MSITStore:Z:\\home\\test\\chm\\silqhelp.chm::/thesilqquickstartguide.htm",S_OK,FALSE},
3789             {"",S_FALSE,FALSE},
3790             {".htm",S_OK,FALSE},
3791             {"",S_FALSE,FALSE},
3792             {"",S_FALSE,FALSE},
3793             {"",S_FALSE,FALSE},
3794             {"@MSITStore:Z:\\home\\test\\chm\\silqhelp.chm::/thesilqquickstartguide.htm",S_OK,FALSE},
3795             {"@MSITStore:Z:\\home\\test\\chm\\silqhelp.chm::/thesilqquickstartguide.htm",S_OK,FALSE},
3796             {"",S_FALSE,FALSE},
3797             {"mk:@MSITStore:Z:\\home\\test\\chm\\silqhelp.chm::/thesilqquickstartguide.htm",S_OK,FALSE},
3798             {"mk",S_OK,FALSE},
3799             {"",S_FALSE,FALSE},
3800             {"",S_FALSE,FALSE}
3801         },
3802         {
3803             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3804             {0,S_FALSE,FALSE},
3805             {URL_SCHEME_MK,S_OK,FALSE},
3806             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3807         }
3808     },
3809     /* Two '\' are added to the URI when USE_DOS_PATH is set, and it's a UNC path. */
3810     {   "file://server/dir/index.html", Uri_CREATE_FILE_USE_DOS_PATH, S_OK, FALSE,
3811         {
3812             {"file://\\\\server\\dir\\index.html",S_OK,FALSE},
3813             {"server",S_OK,FALSE},
3814             {"file://\\\\server\\dir\\index.html",S_OK,FALSE},
3815             {"",S_FALSE,FALSE},
3816             {".html",S_OK,FALSE},
3817             {"",S_FALSE,FALSE},
3818             {"server",S_OK,FALSE},
3819             {"",S_FALSE,FALSE},
3820             {"\\dir\\index.html",S_OK,FALSE},
3821             {"\\dir\\index.html",S_OK,FALSE},
3822             {"",S_FALSE,FALSE},
3823             {"file://server/dir/index.html",S_OK,FALSE},
3824             {"file",S_OK,FALSE},
3825             {"",S_FALSE,FALSE},
3826             {"",S_FALSE,FALSE}
3827         },
3828         {
3829             {Uri_HOST_DNS,S_OK,FALSE},
3830             {0,S_FALSE,FALSE},
3831             {URL_SCHEME_FILE,S_OK,FALSE},
3832             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3833         }
3834     },
3835     /* When CreateUri generates an IUri, it still displays the default port in the
3836      * authority.
3837      */
3838     {   "http://google.com:80/", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
3839         {
3840             {"http://google.com:80/",S_OK,FALSE},
3841             {"google.com:80",S_OK,FALSE},
3842             {"http://google.com:80/",S_OK,FALSE},
3843             {"google.com",S_OK,FALSE},
3844             {"",S_FALSE,FALSE},
3845             {"",S_FALSE,FALSE},
3846             {"google.com",S_OK,FALSE},
3847             {"",S_FALSE,FALSE},
3848             {"/",S_OK,FALSE},
3849             {"/",S_OK,FALSE},
3850             {"",S_FALSE,FALSE},
3851             {"http://google.com:80/",S_OK,FALSE},
3852             {"http",S_OK,FALSE},
3853             {"",S_FALSE,FALSE},
3854             {"",S_FALSE,FALSE}
3855         },
3856         {
3857             {Uri_HOST_DNS,S_OK,FALSE},
3858             {80,S_OK,FALSE},
3859             {URL_SCHEME_HTTP,S_OK,FALSE},
3860             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3861         }
3862     },
3863     /* For res URIs the host is everything up until the first '/'. */
3864     {   "res://C:\\dir\\file.exe/DATA/test.html", 0, S_OK, FALSE,
3865         {
3866             {"res://C:\\dir\\file.exe/DATA/test.html",S_OK,FALSE},
3867             {"C:\\dir\\file.exe",S_OK,FALSE},
3868             {"res://C:\\dir\\file.exe/DATA/test.html",S_OK,FALSE},
3869             {"",S_FALSE,FALSE},
3870             {".html",S_OK,FALSE},
3871             {"",S_FALSE,FALSE},
3872             {"C:\\dir\\file.exe",S_OK,FALSE},
3873             {"",S_FALSE,FALSE},
3874             {"/DATA/test.html",S_OK,FALSE},
3875             {"/DATA/test.html",S_OK,FALSE},
3876             {"",S_FALSE,FALSE},
3877             {"res://C:\\dir\\file.exe/DATA/test.html",S_OK,FALSE},
3878             {"res",S_OK,FALSE},
3879             {"",S_FALSE,FALSE},
3880             {"",S_FALSE,FALSE}
3881         },
3882         {
3883             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3884             {0,S_FALSE,FALSE},
3885             {URL_SCHEME_RES,S_OK,FALSE},
3886             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3887         }
3888     },
3889     /* Res URI can contain a '|' in the host name. */
3890     {   "res://c:\\di|r\\file.exe/test", 0, S_OK, FALSE,
3891         {
3892             {"res://c:\\di|r\\file.exe/test",S_OK,FALSE},
3893             {"c:\\di|r\\file.exe",S_OK,FALSE},
3894             {"res://c:\\di|r\\file.exe/test",S_OK,FALSE},
3895             {"",S_FALSE,FALSE},
3896             {"",S_FALSE,FALSE},
3897             {"",S_FALSE,FALSE},
3898             {"c:\\di|r\\file.exe",S_OK,FALSE},
3899             {"",S_FALSE,FALSE},
3900             {"/test",S_OK,FALSE},
3901             {"/test",S_OK,FALSE},
3902             {"",S_FALSE,FALSE},
3903             {"res://c:\\di|r\\file.exe/test",S_OK,FALSE},
3904             {"res",S_OK,FALSE},
3905             {"",S_FALSE,FALSE},
3906             {"",S_FALSE,FALSE}
3907         },
3908         {
3909             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3910             {0,S_FALSE,FALSE},
3911             {URL_SCHEME_RES,S_OK,FALSE},
3912             {URLZONE_INVALID,E_NOTIMPL,FALSE},
3913         }
3914     },
3915     /* Res URIs can have invalid percent encoded values. */
3916     {   "res://c:\\dir%xx\\file.exe/test", 0, S_OK, FALSE,
3917         {
3918             {"res://c:\\dir%xx\\file.exe/test",S_OK,FALSE},
3919             {"c:\\dir%xx\\file.exe",S_OK,FALSE},
3920             {"res://c:\\dir%xx\\file.exe/test",S_OK,FALSE},
3921             {"",S_FALSE,FALSE},
3922             {"",S_FALSE,FALSE},
3923             {"",S_FALSE,FALSE},
3924             {"c:\\dir%xx\\file.exe",S_OK,FALSE},
3925             {"",S_FALSE,FALSE},
3926             {"/test",S_OK,FALSE},
3927             {"/test",S_OK,FALSE},
3928             {"",S_FALSE,FALSE},
3929             {"res://c:\\dir%xx\\file.exe/test",S_OK,FALSE},
3930             {"res",S_OK,FALSE},
3931             {"",S_FALSE,FALSE},
3932             {"",S_FALSE,FALSE}
3933         },
3934         {
3935             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3936             {0,S_FALSE,FALSE},
3937             {URL_SCHEME_RES,S_OK,FALSE},
3938             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3939         }
3940     },
3941     /* Res doesn't get forbidden characters percent encoded in it's path. */
3942     {   "res://c:\\test/tes<|>t", 0, S_OK, FALSE,
3943         {
3944             {"res://c:\\test/tes<|>t",S_OK,FALSE},
3945             {"c:\\test",S_OK,FALSE},
3946             {"res://c:\\test/tes<|>t",S_OK,FALSE},
3947             {"",S_FALSE,FALSE},
3948             {"",S_FALSE,FALSE},
3949             {"",S_FALSE,FALSE},
3950             {"c:\\test",S_OK,FALSE},
3951             {"",S_FALSE,FALSE},
3952             {"/tes<|>t",S_OK,FALSE},
3953             {"/tes<|>t",S_OK,FALSE},
3954             {"",S_FALSE,FALSE},
3955             {"res://c:\\test/tes<|>t",S_OK,FALSE},
3956             {"res",S_OK,FALSE},
3957             {"",S_FALSE,FALSE},
3958             {"",S_FALSE,FALSE}
3959         },
3960         {
3961             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3962             {0,S_FALSE,FALSE},
3963             {URL_SCHEME_RES,S_OK,FALSE},
3964             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3965         }
3966     },
3967     {   "mk:@MSITStore:Z:\\dir\\test.chm::/html/../images/xxx.jpg", 0, S_OK, FALSE,
3968         {
3969             {"mk:@MSITStore:Z:\\dir\\test.chm::/images/xxx.jpg",S_OK,FALSE},
3970             {"",S_FALSE,FALSE},
3971             {"mk:@MSITStore:Z:\\dir\\test.chm::/images/xxx.jpg",S_OK,FALSE},
3972             {"",S_FALSE,FALSE},
3973             {".jpg",S_OK,FALSE},
3974             {"",S_FALSE,FALSE},
3975             {"",S_FALSE,FALSE},
3976             {"",S_FALSE,FALSE},
3977             {"@MSITStore:Z:\\dir\\test.chm::/images/xxx.jpg",S_OK,FALSE},
3978             {"@MSITStore:Z:\\dir\\test.chm::/images/xxx.jpg",S_OK,FALSE},
3979             {"",S_FALSE,FALSE},
3980             {"mk:@MSITStore:Z:\\dir\\test.chm::/html/../images/xxx.jpg",S_OK,FALSE},
3981             {"mk",S_OK,FALSE},
3982             {"",S_FALSE,FALSE},
3983             {"",S_FALSE,FALSE}
3984         },
3985         {
3986             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3987             {0,S_FALSE,FALSE},
3988             {URL_SCHEME_MK,S_OK,FALSE},
3989             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3990         }
3991     },
3992     {   "mk:@MSITStore:Z:\\dir\\test.chm::/html/../images/xxx.jpg", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
3993         {
3994             {"mk:@MSITStore:Z:\\dir\\test.chm::/html/../images/xxx.jpg",S_OK,FALSE},
3995             {"",S_FALSE,FALSE},
3996             {"mk:@MSITStore:Z:\\dir\\test.chm::/html/../images/xxx.jpg",S_OK,FALSE},
3997             {"",S_FALSE,FALSE},
3998             {".jpg",S_OK,FALSE},
3999             {"",S_FALSE,FALSE},
4000             {"",S_FALSE,FALSE},
4001             {"",S_FALSE,FALSE},
4002             {"@MSITStore:Z:\\dir\\test.chm::/html/../images/xxx.jpg",S_OK,FALSE},
4003             {"@MSITStore:Z:\\dir\\test.chm::/html/../images/xxx.jpg",S_OK,FALSE},
4004             {"",S_FALSE,FALSE},
4005             {"mk:@MSITStore:Z:\\dir\\test.chm::/html/../images/xxx.jpg",S_OK,FALSE},
4006             {"mk",S_OK,FALSE},
4007             {"",S_FALSE,FALSE},
4008             {"",S_FALSE,FALSE}
4009         },
4010         {
4011             {Uri_HOST_UNKNOWN,S_OK,FALSE},
4012             {0,S_FALSE,FALSE},
4013             {URL_SCHEME_MK,S_OK,FALSE},
4014             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4015         }
4016     },
4017     {   "xx:@MSITStore:Z:\\dir\\test.chm::/html/../images/xxx.jpg", 0, S_OK, FALSE,
4018         {
4019             {"xx:@MSITStore:Z:\\dir\\test.chm::/html/../images/xxx.jpg",S_OK,FALSE},
4020             {"",S_FALSE,FALSE},
4021             {"xx:@MSITStore:Z:\\dir\\test.chm::/html/../images/xxx.jpg",S_OK,FALSE},
4022             {"",S_FALSE,FALSE},
4023             {".jpg",S_OK,FALSE},
4024             {"",S_FALSE,FALSE},
4025             {"",S_FALSE,FALSE},
4026             {"",S_FALSE,FALSE},
4027             {"@MSITStore:Z:\\dir\\test.chm::/html/../images/xxx.jpg",S_OK,FALSE},
4028             {"@MSITStore:Z:\\dir\\test.chm::/html/../images/xxx.jpg",S_OK,FALSE},
4029             {"",S_FALSE,FALSE},
4030             {"xx:@MSITStore:Z:\\dir\\test.chm::/html/../images/xxx.jpg",S_OK,FALSE},
4031             {"xx",S_OK,FALSE},
4032             {"",S_FALSE,FALSE},
4033             {"",S_FALSE,FALSE}
4034         },
4035         {
4036             {Uri_HOST_UNKNOWN,S_OK,FALSE},
4037             {0,S_FALSE,FALSE},
4038             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
4039             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4040         }
4041     },
4042     {   "mk:@MSITStore:Z:\\dir\\test.chm::/html/../../images/xxx.jpg", 0, S_OK, FALSE,
4043         {
4044             {"mk:@MSITStore:Z:\\dir\\images/xxx.jpg",S_OK,FALSE},
4045             {"",S_FALSE,FALSE},
4046             {"mk:@MSITStore:Z:\\dir\\images/xxx.jpg",S_OK,FALSE},
4047             {"",S_FALSE,FALSE},
4048             {".jpg",S_OK,FALSE},
4049             {"",S_FALSE,FALSE},
4050             {"",S_FALSE,FALSE},
4051             {"",S_FALSE,FALSE},
4052             {"@MSITStore:Z:\\dir\\images/xxx.jpg",S_OK,FALSE},
4053             {"@MSITStore:Z:\\dir\\images/xxx.jpg",S_OK,FALSE},
4054             {"",S_FALSE,FALSE},
4055             {"mk:@MSITStore:Z:\\dir\\test.chm::/html/../../images/xxx.jpg",S_OK,FALSE},
4056             {"mk",S_OK,FALSE},
4057             {"",S_FALSE,FALSE},
4058             {"",S_FALSE,FALSE}
4059         },
4060         {
4061             {Uri_HOST_UNKNOWN,S_OK,FALSE},
4062             {0,S_FALSE,FALSE},
4063             {URL_SCHEME_MK,S_OK,FALSE},
4064             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4065         }
4066     },
4067     {   "mk:@MSITStore:Z:\\dir\\dir2\\..\\test.chm::/html/../../images/xxx.jpg", 0, S_OK, FALSE,
4068         {
4069             {"mk:@MSITStore:Z:\\dir\\images/xxx.jpg",S_OK,FALSE},
4070             {"",S_FALSE,FALSE},
4071             {"mk:@MSITStore:Z:\\dir\\images/xxx.jpg",S_OK,FALSE},
4072             {"",S_FALSE,FALSE},
4073             {".jpg",S_OK,FALSE},
4074             {"",S_FALSE,FALSE},
4075             {"",S_FALSE,FALSE},
4076             {"",S_FALSE,FALSE},
4077             {"@MSITStore:Z:\\dir\\images/xxx.jpg",S_OK,FALSE},
4078             {"@MSITStore:Z:\\dir\\images/xxx.jpg",S_OK,FALSE},
4079             {"",S_FALSE,FALSE},
4080             {"mk:@MSITStore:Z:\\dir\\dir2\\..\\test.chm::/html/../../images/xxx.jpg",S_OK,FALSE},
4081             {"mk",S_OK,FALSE},
4082             {"",S_FALSE,FALSE},
4083             {"",S_FALSE,FALSE}
4084         },
4085         {
4086             {Uri_HOST_UNKNOWN,S_OK,FALSE},
4087             {0,S_FALSE,FALSE},
4088             {URL_SCHEME_MK,S_OK,FALSE},
4089             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4090         }
4091     },
4092     {   "mk:@MSITStore:Z:\\dir\\test.chm::/html/../../../../images/xxx.jpg", 0, S_OK, FALSE,
4093         {
4094             {"mk:images/xxx.jpg",S_OK,FALSE},
4095             {"",S_FALSE,FALSE},
4096             {"mk:images/xxx.jpg",S_OK,FALSE},
4097             {"",S_FALSE,FALSE},
4098             {".jpg",S_OK,FALSE},
4099             {"",S_FALSE,FALSE},
4100             {"",S_FALSE,FALSE},
4101             {"",S_FALSE,FALSE},
4102             {"images/xxx.jpg",S_OK,FALSE},
4103             {"images/xxx.jpg",S_OK,FALSE},
4104             {"",S_FALSE,FALSE},
4105             {"mk:@MSITStore:Z:\\dir\\test.chm::/html/../../../../images/xxx.jpg",S_OK,FALSE},
4106             {"mk",S_OK,FALSE},
4107             {"",S_FALSE,FALSE},
4108             {"",S_FALSE,FALSE}
4109         },
4110         {
4111             {Uri_HOST_UNKNOWN,S_OK,FALSE},
4112             {0,S_FALSE,FALSE},
4113             {URL_SCHEME_MK,S_OK,FALSE},
4114             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4115         }
4116     }
4117 };
4118
4119 typedef struct _invalid_uri {
4120     const char* uri;
4121     DWORD       flags;
4122     BOOL        todo;
4123 } invalid_uri;
4124
4125 static const invalid_uri invalid_uri_tests[] = {
4126     /* Has to have a scheme name. */
4127     {"://www.winehq.org",0,FALSE},
4128     /* Window's doesn't like URI's which are implicitly file paths without the
4129      * ALLOW_IMPLICIT_FILE_SCHEME flag set.
4130      */
4131     {"C:/test/test.mp3",0,FALSE},
4132     {"\\\\Server/test/test.mp3",0,FALSE},
4133     {"C:/test/test.mp3",Uri_CREATE_ALLOW_IMPLICIT_WILDCARD_SCHEME,FALSE},
4134     {"\\\\Server/test/test.mp3",Uri_CREATE_ALLOW_RELATIVE,FALSE},
4135     /* Invalid schemes. */
4136     {"*abcd://not.valid.com",0,FALSE},
4137     {"*a*b*c*d://not.valid.com",0,FALSE},
4138     /* Not allowed to have invalid % encoded data. */
4139     {"ftp://google.co%XX/",0,FALSE},
4140     /* To many h16 components. */
4141     {"http://[1:2:3:4:5:6:7:8:9]",0,FALSE},
4142     /* Not enough room for IPv4 address. */
4143     {"http://[1:2:3:4:5:6:7:192.0.1.0]",0,FALSE},
4144     /* Not enough h16 components. */
4145     {"http://[1:2:3:4]",0,FALSE},
4146     /* Not enough components including IPv4. */
4147     {"http://[1:192.0.1.0]",0,FALSE},
4148     /* Not allowed to have partial IPv4 in IPv6. */
4149     {"http://[::192.0]",0,FALSE},
4150     /* Can't have elision of 1 h16 at beginning of address. */
4151     {"http://[::2:3:4:5:6:7:8]",0,FALSE},
4152     /* Can't have elision of 1 h16 at end of address. */
4153     {"http://[1:2:3:4:5:6:7::]",0,FALSE},
4154     /* Expects a valid IP Literal. */
4155     {"ftp://[not.valid.uri]/",0,FALSE},
4156     /* Expects valid port for a known scheme type. */
4157     {"ftp://www.winehq.org:123fgh",0,FALSE},
4158     /* Port exceeds USHORT_MAX for known scheme type. */
4159     {"ftp://www.winehq.org:65536",0,FALSE},
4160     /* Invalid port with IPv4 address. */
4161     {"http://www.winehq.org:1abcd",0,FALSE},
4162     /* Invalid port with IPv6 address. */
4163     {"http://[::ffff]:32xy",0,FALSE},
4164     /* Not allowed to have backslashes with NO_CANONICALIZE. */
4165     {"gopher://www.google.com\\test",Uri_CREATE_NO_CANONICALIZE,FALSE},
4166     /* Not allowed to have invalid % encoded data in opaque URI path. */
4167     {"news:test%XX",0,FALSE},
4168     {"mailto:wine@winehq%G8.com",0,FALSE},
4169     /* Known scheme types can't have invalid % encoded data in query string. */
4170     {"http://google.com/?query=te%xx",0,FALSE},
4171     /* Invalid % encoded data in fragment of know scheme type. */
4172     {"ftp://google.com/#Test%xx",0,FALSE},
4173     {"  http://google.com/",Uri_CREATE_NO_PRE_PROCESS_HTML_URI,FALSE},
4174     {"\n\nhttp://google.com/",Uri_CREATE_NO_PRE_PROCESS_HTML_URI,FALSE},
4175     {"file://c:\\test<test",Uri_CREATE_FILE_USE_DOS_PATH,FALSE},
4176     {"file://c:\\test>test",Uri_CREATE_FILE_USE_DOS_PATH,FALSE},
4177     {"file://c:\\test\"test",Uri_CREATE_FILE_USE_DOS_PATH,FALSE},
4178     {"file:c:\\test<test",Uri_CREATE_FILE_USE_DOS_PATH,FALSE},
4179     {"file:c:\\test>test",Uri_CREATE_FILE_USE_DOS_PATH,FALSE},
4180     {"file:c:\\test\"test",Uri_CREATE_FILE_USE_DOS_PATH,FALSE},
4181     /* res URIs aren't allowed to have forbidden dos path characters in the
4182      * hostname.
4183      */
4184     {"res://c:\\te<st\\test/test",0,FALSE},
4185     {"res://c:\\te>st\\test/test",0,FALSE},
4186     {"res://c:\\te\"st\\test/test",0,FALSE},
4187     {"res://c:\\test/te%xxst",0,FALSE}
4188 };
4189
4190 typedef struct _uri_equality {
4191     const char* a;
4192     DWORD       create_flags_a;
4193     BOOL        create_todo_a;
4194     const char* b;
4195     DWORD       create_flags_b;
4196     BOOL        create_todo_b;
4197     BOOL        equal;
4198     BOOL        todo;
4199 } uri_equality;
4200
4201 static const uri_equality equality_tests[] = {
4202     {
4203         "HTTP://www.winehq.org/test dir/./",0,FALSE,
4204         "http://www.winehq.org/test dir/../test dir/",0,FALSE,
4205         TRUE, FALSE
4206     },
4207     {
4208         /* http://www.winehq.org/test%20dir */
4209         "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,
4210         "http://www.winehq.org/test dir",0,FALSE,
4211         TRUE, FALSE
4212     },
4213     {
4214         "c:\\test.mp3",Uri_CREATE_ALLOW_IMPLICIT_FILE_SCHEME,FALSE,
4215         "file:///c:/test.mp3",0,FALSE,
4216         TRUE, FALSE
4217     },
4218     {
4219         "ftp://ftp.winehq.org/",0,FALSE,
4220         "ftp://ftp.winehq.org",0,FALSE,
4221         TRUE, FALSE
4222     },
4223     {
4224         "ftp://ftp.winehq.org/test/test2/../../testB/",0,FALSE,
4225         "ftp://ftp.winehq.org/t%45stB/",0,FALSE,
4226         FALSE, FALSE
4227     },
4228     {
4229         "http://google.com/TEST",0,FALSE,
4230         "http://google.com/test",0,FALSE,
4231         FALSE, FALSE
4232     },
4233     {
4234         "http://GOOGLE.com/",0,FALSE,
4235         "http://google.com/",0,FALSE,
4236         TRUE, FALSE
4237     },
4238     /* Performs case insensitive compare of host names (for known scheme types). */
4239     {
4240         "ftp://GOOGLE.com/",Uri_CREATE_NO_CANONICALIZE,FALSE,
4241         "ftp://google.com/",0,FALSE,
4242         TRUE, FALSE
4243     },
4244     {
4245         "zip://GOOGLE.com/",0,FALSE,
4246         "zip://google.com/",0,FALSE,
4247         FALSE, FALSE
4248     },
4249     {
4250         "file:///c:/TEST/TeST/",0,FALSE,
4251         "file:///c:/test/test/",0,FALSE,
4252         TRUE, FALSE
4253     },
4254     {
4255         "file:///server/TEST",0,FALSE,
4256         "file:///SERVER/TEST",0,FALSE,
4257         TRUE, FALSE
4258     },
4259     {
4260         "http://google.com",Uri_CREATE_NO_CANONICALIZE,FALSE,
4261         "http://google.com/",0,FALSE,
4262         TRUE, FALSE
4263     },
4264     {
4265         "ftp://google.com:21/",0,FALSE,
4266         "ftp://google.com/",0,FALSE,
4267         TRUE, FALSE
4268     },
4269     {
4270         "http://google.com:80/",Uri_CREATE_NO_CANONICALIZE,FALSE,
4271         "http://google.com/",0,FALSE,
4272         TRUE, FALSE
4273     },
4274     {
4275         "http://google.com:70/",0,FALSE,
4276         "http://google.com:71/",0,FALSE,
4277         FALSE, FALSE
4278     }
4279 };
4280
4281 typedef struct _uri_with_fragment {
4282     const char* uri;
4283     const char* fragment;
4284     DWORD       create_flags;
4285     HRESULT     create_expected;
4286     BOOL        create_todo;
4287
4288     const char* expected_uri;
4289     BOOL        expected_todo;
4290 } uri_with_fragment;
4291
4292 static const uri_with_fragment uri_fragment_tests[] = {
4293     {
4294         "http://google.com/","#fragment",0,S_OK,FALSE,
4295         "http://google.com/#fragment",FALSE
4296     },
4297     {
4298         "http://google.com/","fragment",0,S_OK,FALSE,
4299         "http://google.com/#fragment",FALSE
4300     },
4301     {
4302         "zip://test.com/","?test",0,S_OK,FALSE,
4303         "zip://test.com/#?test",FALSE
4304     },
4305     /* The fragment can be empty. */
4306     {
4307         "ftp://ftp.google.com/","",0,S_OK,FALSE,
4308         "ftp://ftp.google.com/#",FALSE
4309     }
4310 };
4311
4312 typedef struct _uri_builder_property {
4313     BOOL            change;
4314     const char      *value;
4315     const char      *expected_value;
4316     Uri_PROPERTY    property;
4317     HRESULT         expected;
4318     BOOL            todo;
4319 } uri_builder_property;
4320
4321 typedef struct _uri_builder_port {
4322     BOOL    change;
4323     BOOL    set;
4324     DWORD   value;
4325     HRESULT expected;
4326     BOOL    todo;
4327 } uri_builder_port;
4328
4329 typedef struct _uri_builder_str_property {
4330     const char* expected;
4331     HRESULT     result;
4332     BOOL        todo;
4333 } uri_builder_str_property;
4334
4335 typedef struct _uri_builder_dword_property {
4336     DWORD   expected;
4337     HRESULT result;
4338     BOOL    todo;
4339 } uri_builder_dword_property;
4340
4341 typedef struct _uri_builder_test {
4342     const char                  *uri;
4343     DWORD                       create_flags;
4344     HRESULT                     create_builder_expected;
4345     BOOL                        create_builder_todo;
4346
4347     uri_builder_property        properties[URI_BUILDER_STR_PROPERTY_COUNT];
4348
4349     uri_builder_port            port_prop;
4350
4351     DWORD                       uri_flags;
4352     HRESULT                     uri_hres;
4353     BOOL                        uri_todo;
4354
4355     DWORD                       uri_simple_encode_flags;
4356     HRESULT                     uri_simple_hres;
4357     BOOL                        uri_simple_todo;
4358
4359     DWORD                       uri_with_flags;
4360     DWORD                       uri_with_builder_flags;
4361     DWORD                       uri_with_encode_flags;
4362     HRESULT                     uri_with_hres;
4363     BOOL                        uri_with_todo;
4364
4365     uri_builder_str_property    expected_str_props[URI_STR_PROPERTY_COUNT];
4366     uri_builder_dword_property  expected_dword_props[URI_DWORD_PROPERTY_COUNT];
4367 } uri_builder_test;
4368
4369 static const uri_builder_test uri_builder_tests[] = {
4370     {   "http://google.com/",0,S_OK,FALSE,
4371         {
4372             {TRUE,"#fragment",NULL,Uri_PROPERTY_FRAGMENT,S_OK,FALSE},
4373             {TRUE,"password",NULL,Uri_PROPERTY_PASSWORD,S_OK,FALSE},
4374             {TRUE,"?query=x",NULL,Uri_PROPERTY_QUERY,S_OK,FALSE},
4375             {TRUE,"username",NULL,Uri_PROPERTY_USER_NAME,S_OK,FALSE}
4376         },
4377         {FALSE},
4378         0,S_OK,FALSE,
4379         0,S_OK,FALSE,
4380         0,0,0,S_OK,FALSE,
4381         {
4382             {"http://username:password@google.com/?query=x#fragment",S_OK},
4383             {"username:password@google.com",S_OK},
4384             {"http://google.com/?query=x#fragment",S_OK},
4385             {"google.com",S_OK},
4386             {"",S_FALSE},
4387             {"#fragment",S_OK},
4388             {"google.com",S_OK},
4389             {"password",S_OK},
4390             {"/",S_OK},
4391             {"/?query=x",S_OK},
4392             {"?query=x",S_OK},
4393             {"http://username:password@google.com/?query=x#fragment",S_OK},
4394             {"http",S_OK},
4395             {"username:password",S_OK},
4396             {"username",S_OK}
4397         },
4398         {
4399             {Uri_HOST_DNS,S_OK},
4400             {80,S_OK},
4401             {URL_SCHEME_HTTP,S_OK},
4402             {URLZONE_INVALID,E_NOTIMPL}
4403         }
4404     },
4405     {   "http://google.com/",0,S_OK,FALSE,
4406         {
4407             {TRUE,"test",NULL,Uri_PROPERTY_SCHEME_NAME,S_OK,FALSE}
4408         },
4409         {TRUE,TRUE,120,S_OK,FALSE},
4410         0,S_OK,FALSE,
4411         0,S_OK,FALSE,
4412         0,0,0,S_OK,FALSE,
4413         {
4414             {"test://google.com:120/",S_OK},
4415             {"google.com:120",S_OK},
4416             {"test://google.com:120/",S_OK},
4417             {"google.com",S_OK},
4418             {"",S_FALSE},
4419             {"",S_FALSE},
4420             {"google.com",S_OK},
4421             {"",S_FALSE},
4422             {"/",S_OK},
4423             {"/",S_OK},
4424             {"",S_FALSE},
4425             {"test://google.com:120/",S_OK},
4426             {"test",S_OK},
4427             {"",S_FALSE},
4428             {"",S_FALSE}
4429         },
4430         {
4431             {Uri_HOST_DNS,S_OK},
4432             {120,S_OK},
4433             {URL_SCHEME_UNKNOWN,S_OK},
4434             {URLZONE_INVALID,E_NOTIMPL}
4435         }
4436     },
4437     {   "/Test/test dir",Uri_CREATE_ALLOW_RELATIVE,S_OK,FALSE,
4438         {
4439             {TRUE,"http",NULL,Uri_PROPERTY_SCHEME_NAME,S_OK,FALSE},
4440             {TRUE,"::192.2.3.4",NULL,Uri_PROPERTY_HOST,S_OK,FALSE},
4441             {TRUE,NULL,NULL,Uri_PROPERTY_PATH,S_OK,FALSE}
4442         },
4443         {FALSE},
4444         0,S_OK,FALSE,
4445         0,S_OK,FALSE,
4446         0,0,0,S_OK,FALSE,
4447         {
4448             {"http://[::192.2.3.4]/",S_OK},
4449             {"[::192.2.3.4]",S_OK},
4450             {"http://[::192.2.3.4]/",S_OK},
4451             {"",S_FALSE},
4452             {"",S_FALSE},
4453             {"",S_FALSE},
4454             {"::192.2.3.4",S_OK},
4455             {"",S_FALSE},
4456             {"/",S_OK},
4457             {"/",S_OK},
4458             {"",S_FALSE},
4459             {"http://[::192.2.3.4]/",S_OK},
4460             {"http",S_OK},
4461             {"",S_FALSE},
4462             {"",S_FALSE}
4463         },
4464         {
4465             {Uri_HOST_IPV6,S_OK},
4466             {80,S_OK},
4467             {URL_SCHEME_HTTP,S_OK},
4468             {URLZONE_INVALID,E_NOTIMPL}
4469         }
4470     },
4471     {   "http://google.com/",0,S_OK,FALSE,
4472         {
4473             {TRUE,"Frag","#Frag",Uri_PROPERTY_FRAGMENT,S_OK,FALSE}
4474         },
4475         {FALSE},
4476         0,S_OK,FALSE,
4477         0,S_OK,FALSE,
4478         0,0,0,S_OK,FALSE,
4479         {
4480             {"http://google.com/#Frag",S_OK},
4481             {"google.com",S_OK},
4482             {"http://google.com/#Frag",S_OK},
4483             {"google.com",S_OK},
4484             {"",S_FALSE},
4485             {"#Frag",S_OK},
4486             {"google.com",S_OK},
4487             {"",S_FALSE},
4488             {"/",S_OK},
4489             {"/",S_OK},
4490             {"",S_FALSE},
4491             {"http://google.com/#Frag",S_OK},
4492             {"http",S_OK},
4493             {"",S_FALSE},
4494             {"",S_FALSE}
4495         },
4496         {
4497             {Uri_HOST_DNS,S_OK},
4498             {80,S_OK},
4499             {URL_SCHEME_HTTP,S_OK},
4500             {URLZONE_INVALID,E_NOTIMPL}
4501         }
4502     },
4503     {   "http://google.com/",0,S_OK,FALSE,
4504         {
4505             {TRUE,"","#",Uri_PROPERTY_FRAGMENT,S_OK,FALSE},
4506         },
4507         {FALSE},
4508         0,S_OK,FALSE,
4509         0,S_OK,FALSE,
4510         0,0,0,S_OK,FALSE,
4511         {
4512             {"http://google.com/#",S_OK},
4513             {"google.com",S_OK},
4514             {"http://google.com/#",S_OK},
4515             {"google.com",S_OK},
4516             {"",S_FALSE},
4517             {"#",S_OK},
4518             {"google.com",S_OK},
4519             {"",S_FALSE},
4520             {"/",S_OK},
4521             {"/",S_OK},
4522             {"",S_FALSE},
4523             {"http://google.com/#",S_OK},
4524             {"http",S_OK},
4525             {"",S_FALSE},
4526             {"",S_FALSE}
4527         },
4528         {
4529             {Uri_HOST_DNS,S_OK},
4530             {80,S_OK},
4531             {URL_SCHEME_HTTP,S_OK},
4532             {URLZONE_INVALID,E_NOTIMPL}
4533         }
4534     },
4535     {   "http://google.com/",0,S_OK,FALSE,
4536         {
4537             {TRUE,":password",NULL,Uri_PROPERTY_PASSWORD,S_OK,FALSE}
4538         },
4539         {FALSE},
4540         0,S_OK,FALSE,
4541         0,S_OK,FALSE,
4542         0,0,0,S_OK,FALSE,
4543         {
4544             {"http://::password@google.com/",S_OK},
4545             {"::password@google.com",S_OK},
4546             {"http://google.com/",S_OK},
4547             {"google.com",S_OK},
4548             {"",S_FALSE},
4549             {"",S_FALSE},
4550             {"google.com",S_OK},
4551             {":password",S_OK},
4552             {"/",S_OK},
4553             {"/",S_OK},
4554             {"",S_FALSE},
4555             {"http://::password@google.com/",S_OK},
4556             {"http",S_OK},
4557             {"::password",S_OK},
4558             {"",S_FALSE}
4559         },
4560         {
4561             {Uri_HOST_DNS,S_OK},
4562             {80,S_OK},
4563             {URL_SCHEME_HTTP,S_OK},
4564             {URLZONE_INVALID,E_NOTIMPL}
4565         }
4566     },
4567     {   "test/test",Uri_CREATE_ALLOW_RELATIVE,S_OK,FALSE,
4568         {
4569             {TRUE,"password",NULL,Uri_PROPERTY_PASSWORD,S_OK,FALSE}
4570         },
4571         {FALSE},
4572         Uri_CREATE_ALLOW_RELATIVE,S_OK,FALSE,
4573         0,S_OK,FALSE,
4574         Uri_CREATE_ALLOW_RELATIVE,0,0,S_OK,FALSE,
4575         {
4576             {":password@test/test",S_OK},
4577             {":password@",S_OK},
4578             {":password@test/test",S_OK},
4579             {"",S_FALSE},
4580             {"",S_FALSE},
4581             {"",S_FALSE},
4582             {"",S_FALSE},
4583             {"password",S_OK},
4584             {"test/test",S_OK},
4585             {"test/test",S_OK},
4586             {"",S_FALSE},
4587             {":password@test/test",S_OK},
4588             {"",S_FALSE},
4589             {":password",S_OK},
4590             {"",S_FALSE}
4591         },
4592         {
4593             {Uri_HOST_UNKNOWN,S_OK},
4594             {0,S_FALSE},
4595             {URL_SCHEME_UNKNOWN,S_OK},
4596             {URLZONE_INVALID,E_NOTIMPL}
4597         }
4598     },
4599     {   "http://google.com/",0,S_OK,FALSE,
4600         {
4601             {TRUE,"test/test",NULL,Uri_PROPERTY_PATH,S_OK,FALSE},
4602         },
4603         {FALSE},
4604         0,S_OK,FALSE,
4605         0,S_OK,FALSE,
4606         0,0,0,S_OK,FALSE,
4607         {
4608             {"http://google.com/test/test",S_OK},
4609             {"google.com",S_OK},
4610             {"http://google.com/test/test",S_OK},
4611             {"google.com",S_OK},
4612             {"",S_FALSE},
4613             {"",S_FALSE},
4614             {"google.com",S_OK},
4615             {"",S_FALSE},
4616             {"/test/test",S_OK},
4617             {"/test/test",S_OK},
4618             {"",S_FALSE},
4619             {"http://google.com/test/test",S_OK},
4620             {"http",S_OK},
4621             {"",S_FALSE},
4622             {"",S_FALSE}
4623         },
4624         {
4625             {Uri_HOST_DNS,S_OK},
4626             {80,S_OK},
4627             {URL_SCHEME_HTTP,S_OK},
4628             {URLZONE_INVALID,E_NOTIMPL}
4629         }
4630     },
4631     {   "zip:testing/test",0,S_OK,FALSE,
4632         {
4633             {TRUE,"test",NULL,Uri_PROPERTY_PATH,S_OK,FALSE},
4634         },
4635         {FALSE},
4636         0,S_OK,FALSE,
4637         0,S_OK,FALSE,
4638         0,0,0,S_OK,FALSE,
4639         {
4640             {"zip:test",S_OK},
4641             {"",S_FALSE},
4642             {"zip:test",S_OK},
4643             {"",S_FALSE},
4644             {"",S_FALSE},
4645             {"",S_FALSE},
4646             {"",S_FALSE},
4647             {"",S_FALSE},
4648             {"test",S_OK},
4649             {"test",S_OK},
4650             {"",S_FALSE},
4651             {"zip:test",S_OK},
4652             {"zip",S_OK},
4653             {"",S_FALSE},
4654             {"",S_FALSE}
4655         },
4656         {
4657             {Uri_HOST_UNKNOWN,S_OK},
4658             {0,S_FALSE},
4659             {URL_SCHEME_UNKNOWN,S_OK},
4660             {URLZONE_INVALID,E_NOTIMPL}
4661         }
4662     },
4663     {   "http://google.com/",0,S_OK,FALSE,
4664         {
4665             {FALSE},
4666         },
4667         /* 555 will be returned from GetPort even though FALSE was passed as the hasPort parameter. */
4668         {TRUE,FALSE,555,S_OK,FALSE},
4669         0,S_OK,FALSE,
4670         0,S_OK,FALSE,
4671         0,0,0,S_OK,FALSE,
4672         {
4673             {"http://google.com/",S_OK},
4674             {"google.com",S_OK},
4675             {"http://google.com/",S_OK},
4676             {"google.com",S_OK},
4677             {"",S_FALSE},
4678             {"",S_FALSE},
4679             {"google.com",S_OK},
4680             {"",S_FALSE},
4681             {"/",S_OK},
4682             {"/",S_OK},
4683             {"",S_FALSE},
4684             {"http://google.com/",S_OK},
4685             {"http",S_OK},
4686             {"",S_FALSE},
4687             {"",S_FALSE}
4688         },
4689         {
4690             {Uri_HOST_DNS,S_OK},
4691             /* Still returns 80, even though earlier the port was disabled. */
4692             {80,S_OK},
4693             {URL_SCHEME_HTTP,S_OK},
4694             {URLZONE_INVALID,E_NOTIMPL}
4695         }
4696     },
4697     {   "http://google.com/",0,S_OK,FALSE,
4698         {
4699             {FALSE},
4700         },
4701         /* Instead of getting "TRUE" back as the "hasPort" parameter in GetPort,
4702          * you'll get 122345 instead.
4703          */
4704         {TRUE,122345,222,S_OK,FALSE},
4705         0,S_OK,FALSE,
4706         0,S_OK,FALSE,
4707         0,0,0,S_OK,FALSE,
4708         {
4709             {"http://google.com:222/",S_OK},
4710             {"google.com:222",S_OK},
4711             {"http://google.com:222/",S_OK},
4712             {"google.com",S_OK},
4713             {"",S_FALSE},
4714             {"",S_FALSE},
4715             {"google.com",S_OK},
4716             {"",S_FALSE},
4717             {"/",S_OK},
4718             {"/",S_OK},
4719             {"",S_FALSE},
4720             {"http://google.com:222/",S_OK},
4721             {"http",S_OK},
4722             {"",S_FALSE},
4723             {"",S_FALSE}
4724         },
4725         {
4726             {Uri_HOST_DNS,S_OK},
4727             {222,S_OK},
4728             {URL_SCHEME_HTTP,S_OK},
4729             {URLZONE_INVALID,E_NOTIMPL}
4730         }
4731     },
4732     /* IUri's created with the IUriBuilder can have ports that exceed USHORT_MAX. */
4733     {   "http://google.com/",0,S_OK,FALSE,
4734         {
4735             {FALSE},
4736         },
4737         {TRUE,TRUE,999999,S_OK,FALSE},
4738         0,S_OK,FALSE,
4739         0,S_OK,FALSE,
4740         0,0,0,S_OK,FALSE,
4741         {
4742             {"http://google.com:999999/",S_OK},
4743             {"google.com:999999",S_OK},
4744             {"http://google.com:999999/",S_OK},
4745             {"google.com",S_OK},
4746             {"",S_FALSE},
4747             {"",S_FALSE},
4748             {"google.com",S_OK},
4749             {"",S_FALSE},
4750             {"/",S_OK},
4751             {"/",S_OK},
4752             {"",S_FALSE},
4753             {"http://google.com:999999/",S_OK},
4754             {"http",S_OK},
4755             {"",S_FALSE},
4756             {"",S_FALSE}
4757         },
4758         {
4759             {Uri_HOST_DNS,S_OK},
4760             {999999,S_OK},
4761             {URL_SCHEME_HTTP,S_OK},
4762             {URLZONE_INVALID,E_NOTIMPL}
4763         }
4764     },
4765     {   "http://google.com/",0,S_OK,FALSE,
4766         {
4767             {TRUE,"test","?test",Uri_PROPERTY_QUERY,S_OK,FALSE},
4768         },
4769
4770         {FALSE},
4771         0,S_OK,FALSE,
4772         0,S_OK,FALSE,
4773         0,0,0,S_OK,FALSE,
4774         {
4775             {"http://google.com/?test",S_OK},
4776             {"google.com",S_OK},
4777             {"http://google.com/?test",S_OK},
4778             {"google.com",S_OK},
4779             {"",S_FALSE},
4780             {"",S_FALSE},
4781             {"google.com",S_OK},
4782             {"",S_FALSE},
4783             {"/",S_OK},
4784             {"/?test",S_OK},
4785             {"?test",S_OK},
4786             {"http://google.com/?test",S_OK},
4787             {"http",S_OK},
4788             {"",S_FALSE},
4789             {"",S_FALSE}
4790         },
4791         {
4792             {Uri_HOST_DNS,S_OK},
4793             {80,S_OK},
4794             {URL_SCHEME_HTTP,S_OK},
4795             {URLZONE_INVALID,E_NOTIMPL}
4796         }
4797     },
4798     {   "http://:password@google.com/",0,S_OK,FALSE,
4799         {
4800             {FALSE},
4801         },
4802         {FALSE},
4803         0,S_OK,FALSE,
4804         0,S_OK,FALSE,
4805         0,0,0,S_OK,FALSE,
4806         {
4807             {"http://:password@google.com/",S_OK},
4808             {":password@google.com",S_OK},
4809             {"http://google.com/",S_OK},
4810             {"google.com",S_OK},
4811             {"",S_FALSE},
4812             {"",S_FALSE},
4813             {"google.com",S_OK},
4814             {"password",S_OK},
4815             {"/",S_OK},
4816             {"/",S_OK},
4817             {"",S_FALSE},
4818             {"http://:password@google.com/",S_OK},
4819             {"http",S_OK},
4820             {":password",S_OK},
4821             {"",S_FALSE}
4822         },
4823         {
4824             {Uri_HOST_DNS,S_OK},
4825             {80,S_OK},
4826             {URL_SCHEME_HTTP,S_OK},
4827             {URLZONE_INVALID,E_NOTIMPL}
4828         }
4829     },
4830     /* IUriBuilder doesn't need a base IUri to build a IUri. */
4831     {   NULL,0,S_OK,FALSE,
4832         {
4833             {TRUE,"http",NULL,Uri_PROPERTY_SCHEME_NAME,S_OK,FALSE},
4834             {TRUE,"google.com",NULL,Uri_PROPERTY_HOST,S_OK,FALSE}
4835         },
4836         {FALSE},
4837         0,S_OK,FALSE,
4838         0,S_OK,FALSE,
4839         0,0,0,S_OK,FALSE,
4840         {
4841             {"http://google.com/",S_OK},
4842             {"google.com",S_OK},
4843             {"http://google.com/",S_OK},
4844             {"google.com",S_OK},
4845             {"",S_FALSE},
4846             {"",S_FALSE},
4847             {"google.com",S_OK},
4848             {"",S_FALSE},
4849             {"/",S_OK},
4850             {"/",S_OK},
4851             {"",S_FALSE},
4852             {"http://google.com/",S_OK},
4853             {"http",S_OK},
4854             {"",S_FALSE},
4855             {"",S_FALSE}
4856         },
4857         {
4858             {Uri_HOST_DNS,S_OK},
4859             {80,S_OK},
4860             {URL_SCHEME_HTTP,S_OK},
4861             {URLZONE_INVALID,E_NOTIMPL}
4862         }
4863     },
4864     /* Can't set the scheme name to NULL. */
4865     {   "zip://google.com/",0,S_OK,FALSE,
4866         {
4867             {TRUE,NULL,"zip",Uri_PROPERTY_SCHEME_NAME,E_INVALIDARG,FALSE}
4868         },
4869         {FALSE},
4870         0,S_OK,FALSE,
4871         0,S_OK,FALSE,
4872         0,0,0,S_OK,FALSE,
4873         {
4874             {"zip://google.com/",S_OK},
4875             {"google.com",S_OK},
4876             {"zip://google.com/",S_OK},
4877             {"google.com",S_OK},
4878             {"",S_FALSE},
4879             {"",S_FALSE},
4880             {"google.com",S_OK},
4881             {"",S_FALSE},
4882             {"/",S_OK},
4883             {"/",S_OK},
4884             {"",S_FALSE},
4885             {"zip://google.com/",S_OK},
4886             {"zip",S_OK},
4887             {"",S_FALSE},
4888             {"",S_FALSE}
4889         },
4890         {
4891             {Uri_HOST_DNS,S_OK},
4892             {0,S_FALSE},
4893             {URL_SCHEME_UNKNOWN,S_OK},
4894             {URLZONE_INVALID,E_NOTIMPL}
4895         }
4896     },
4897     /* Can't set the scheme name to an empty string. */
4898     {   "zip://google.com/",0,S_OK,FALSE,
4899         {
4900             {TRUE,"","zip",Uri_PROPERTY_SCHEME_NAME,E_INVALIDARG,FALSE}
4901         },
4902         {FALSE},
4903         0,S_OK,FALSE,
4904         0,S_OK,FALSE,
4905         0,0,0,S_OK,FALSE,
4906         {
4907             {"zip://google.com/",S_OK},
4908             {"google.com",S_OK},
4909             {"zip://google.com/",S_OK},
4910             {"google.com",S_OK},
4911             {"",S_FALSE},
4912             {"",S_FALSE},
4913             {"google.com",S_OK},
4914             {"",S_FALSE},
4915             {"/",S_OK},
4916             {"/",S_OK},
4917             {"",S_FALSE},
4918             {"zip://google.com/",S_OK},
4919             {"zip",S_OK},
4920             {"",S_FALSE},
4921             {"",S_FALSE}
4922         },
4923         {
4924             {Uri_HOST_DNS,S_OK},
4925             {0,S_FALSE},
4926             {URL_SCHEME_UNKNOWN,S_OK},
4927             {URLZONE_INVALID,E_NOTIMPL}
4928         }
4929     },
4930     /* -1 to CreateUri makes it use the same flags as the base IUri was created with.
4931      * CreateUriSimple always uses the flags the base IUri was created with (if any).
4932      */
4933     {   "http://google.com/../../",Uri_CREATE_NO_CANONICALIZE,S_OK,FALSE,
4934         {{FALSE}},
4935         {FALSE},
4936         -1,S_OK,FALSE,
4937         0,S_OK,FALSE,
4938         0,UriBuilder_USE_ORIGINAL_FLAGS,0,S_OK,FALSE,
4939         {
4940             {"http://google.com/../../",S_OK},
4941             {"google.com",S_OK},
4942             {"http://google.com/../../",S_OK},
4943             {"google.com",S_OK},
4944             {"",S_FALSE},
4945             {"",S_FALSE},
4946             {"google.com",S_OK},
4947             {"",S_FALSE},
4948             {"/../../",S_OK},
4949             {"/../../",S_OK},
4950             {"",S_FALSE},
4951             {"http://google.com/../../",S_OK},
4952             {"http",S_OK},
4953             {"",S_FALSE},
4954             {"",S_FALSE}
4955         },
4956         {
4957             {Uri_HOST_DNS,S_OK},
4958             {80,S_OK},
4959             {URL_SCHEME_HTTP,S_OK},
4960             {URLZONE_INVALID,E_NOTIMPL}
4961         }
4962     },
4963     {   "http://google.com/",0,S_OK,FALSE,
4964         {
4965             {TRUE,"#Fr<|>g",NULL,Uri_PROPERTY_FRAGMENT,S_OK,FALSE}
4966         },
4967         {FALSE},
4968         -1,S_OK,FALSE,
4969         0,S_OK,FALSE,
4970         Uri_CREATE_NO_DECODE_EXTRA_INFO,UriBuilder_USE_ORIGINAL_FLAGS,0,S_OK,FALSE,
4971         {
4972             {"http://google.com/#Fr%3C%7C%3Eg",S_OK},
4973             {"google.com",S_OK},
4974             {"http://google.com/#Fr%3C%7C%3Eg",S_OK},
4975             {"google.com",S_OK},
4976             {"",S_FALSE},
4977             {"#Fr%3C%7C%3Eg",S_OK},
4978             {"google.com",S_OK},
4979             {"",S_FALSE},
4980             {"/",S_OK},
4981             {"/",S_OK},
4982             {"",S_FALSE},
4983             {"http://google.com/#Fr<|>g",S_OK},
4984             {"http",S_OK},
4985             {"",S_FALSE},
4986             {"",S_FALSE}
4987         },
4988         {
4989             {Uri_HOST_DNS,S_OK},
4990             {80,S_OK},
4991             {URL_SCHEME_HTTP,S_OK},
4992             {URLZONE_INVALID,E_NOTIMPL}
4993         }
4994     },
4995     {   "http://google.com/",0,S_OK,FALSE,
4996         {
4997             {TRUE,"#Fr<|>g",NULL,Uri_PROPERTY_FRAGMENT,S_OK,FALSE}
4998         },
4999         {FALSE},
5000         Uri_CREATE_CANONICALIZE|Uri_CREATE_NO_CANONICALIZE,E_INVALIDARG,FALSE,
5001         0,S_OK,FALSE,
5002         Uri_CREATE_CANONICALIZE|Uri_CREATE_NO_CANONICALIZE,UriBuilder_USE_ORIGINAL_FLAGS,0,S_OK,FALSE,
5003         {
5004             {"http://google.com/#Fr%3C%7C%3Eg",S_OK},
5005             {"google.com",S_OK},
5006             {"http://google.com/#Fr%3C%7C%3Eg",S_OK},
5007             {"google.com",S_OK},
5008             {"",S_FALSE},
5009             {"#Fr%3C%7C%3Eg",S_OK},
5010             {"google.com",S_OK},
5011             {"",S_FALSE},
5012             {"/",S_OK},
5013             {"/",S_OK},
5014             {"",S_FALSE},
5015             {"http://google.com/#Fr<|>g",S_OK},
5016             {"http",S_OK},
5017             {"",S_FALSE},
5018             {"",S_FALSE}
5019         },
5020         {
5021             {Uri_HOST_DNS,S_OK},
5022             {80,S_OK},
5023             {URL_SCHEME_HTTP,S_OK},
5024             {URLZONE_INVALID,E_NOTIMPL}
5025         }
5026     },
5027     {   NULL,0,S_OK,FALSE,
5028         {
5029             {TRUE,"/test/test/",NULL,Uri_PROPERTY_PATH,S_OK,FALSE},
5030             {TRUE,"#Fr<|>g",NULL,Uri_PROPERTY_FRAGMENT,S_OK,FALSE}
5031         },
5032         {FALSE},
5033         0,INET_E_INVALID_URL,FALSE,
5034         0,INET_E_INVALID_URL,FALSE,
5035         0,0,0,INET_E_INVALID_URL,FALSE
5036     },
5037     {   "http://google.com/",0,S_OK,FALSE,
5038         {
5039             {TRUE,"ht%xxtp",NULL,Uri_PROPERTY_SCHEME_NAME,S_OK,FALSE}
5040         },
5041         {FALSE},
5042         0,INET_E_INVALID_URL,FALSE,
5043         0,INET_E_INVALID_URL,FALSE,
5044         0,0,0,INET_E_INVALID_URL,FALSE
5045     },
5046     /* File scheme's can't have a username set. */
5047     {   "file://google.com/",0,S_OK,FALSE,
5048         {
5049             {TRUE,"username",NULL,Uri_PROPERTY_USER_NAME,S_OK,FALSE}
5050         },
5051         {FALSE},
5052         0,INET_E_INVALID_URL,FALSE,
5053         0,INET_E_INVALID_URL,FALSE,
5054         0,0,0,INET_E_INVALID_URL,FALSE
5055     },
5056     /* File schemes can't have a password set. */
5057     {   "file://google.com/",0,S_OK,FALSE,
5058         {
5059             {TRUE,"password",NULL,Uri_PROPERTY_PASSWORD,S_OK,FALSE}
5060         },
5061         {FALSE},
5062         0,INET_E_INVALID_URL,FALSE,
5063         0,INET_E_INVALID_URL,FALSE,
5064         0,0,0,INET_E_INVALID_URL,FALSE
5065     },
5066     /* UserName can't contain any character that is a delimeter for another
5067      * component that appears after it in a normal URI.
5068      */
5069     {   "http://google.com/",0,S_OK,FALSE,
5070         {
5071             {TRUE,"user:pass",NULL,Uri_PROPERTY_USER_NAME,S_OK,FALSE}
5072         },
5073         {FALSE},
5074         0,INET_E_INVALID_URL,FALSE,
5075         0,INET_E_INVALID_URL,FALSE,
5076         0,0,0,INET_E_INVALID_URL,FALSE
5077     },
5078     {   "http://google.com/",0,S_OK,FALSE,
5079         {
5080             {TRUE,"user@google.com",NULL,Uri_PROPERTY_USER_NAME,S_OK,FALSE}
5081         },
5082         {FALSE},
5083         0,INET_E_INVALID_URL,FALSE,
5084         0,INET_E_INVALID_URL,FALSE,
5085         0,0,0,INET_E_INVALID_URL,FALSE
5086     },
5087     {   "http://google.com/",0,S_OK,FALSE,
5088         {
5089             {TRUE,"user/path",NULL,Uri_PROPERTY_USER_NAME,S_OK,FALSE}
5090         },
5091         {FALSE},
5092         0,INET_E_INVALID_URL,FALSE,
5093         0,INET_E_INVALID_URL,FALSE,
5094         0,0,0,INET_E_INVALID_URL,FALSE
5095     },
5096     {   "http://google.com/",0,S_OK,FALSE,
5097         {
5098             {TRUE,"user?Query",NULL,Uri_PROPERTY_USER_NAME,S_OK,FALSE}
5099         },
5100         {FALSE},
5101         0,INET_E_INVALID_URL,FALSE,
5102         0,INET_E_INVALID_URL,FALSE,
5103         0,0,0,INET_E_INVALID_URL,FALSE
5104     },
5105     {   "http://google.com/",0,S_OK,FALSE,
5106         {
5107             {TRUE,"user#Frag",NULL,Uri_PROPERTY_USER_NAME,S_OK,FALSE}
5108         },
5109         {FALSE},
5110         0,INET_E_INVALID_URL,FALSE,
5111         0,INET_E_INVALID_URL,FALSE,
5112         0,0,0,INET_E_INVALID_URL,FALSE
5113     },
5114     {   "http://google.com/",0,S_OK,FALSE,
5115         {
5116             {TRUE,"pass@google.com",NULL,Uri_PROPERTY_PASSWORD,S_OK,FALSE}
5117         },
5118         {FALSE},
5119         0,INET_E_INVALID_URL,FALSE,
5120         0,INET_E_INVALID_URL,FALSE,
5121         0,0,0,INET_E_INVALID_URL,FALSE
5122     },
5123     {   "http://google.com/",0,S_OK,FALSE,
5124         {
5125             {TRUE,"pass/path",NULL,Uri_PROPERTY_PASSWORD,S_OK,FALSE}
5126         },
5127         {FALSE},
5128         0,INET_E_INVALID_URL,FALSE,
5129         0,INET_E_INVALID_URL,FALSE,
5130         0,0,0,INET_E_INVALID_URL,FALSE
5131     },
5132     {   "http://google.com/",0,S_OK,FALSE,
5133         {
5134             {TRUE,"pass?query",NULL,Uri_PROPERTY_PASSWORD,S_OK,FALSE}
5135         },
5136         {FALSE},
5137         0,INET_E_INVALID_URL,FALSE,
5138         0,INET_E_INVALID_URL,FALSE,
5139        0,0,0,INET_E_INVALID_URL,FALSE
5140     },
5141     {   "http://google.com/",0,S_OK,FALSE,
5142         {
5143             {TRUE,"pass#frag",NULL,Uri_PROPERTY_PASSWORD,S_OK,FALSE}
5144         },
5145         {FALSE},
5146         0,INET_E_INVALID_URL,FALSE,
5147         0,INET_E_INVALID_URL,FALSE,
5148         0,0,0,INET_E_INVALID_URL,FALSE
5149     },
5150     {   "http://google.com/",0,S_OK,FALSE,
5151         {
5152             {TRUE,"winehq.org/test",NULL,Uri_PROPERTY_HOST,S_OK,FALSE}
5153         },
5154         {FALSE},
5155         0,INET_E_INVALID_URL,FALSE,
5156         0,INET_E_INVALID_URL,FALSE,
5157         0,0,0,INET_E_INVALID_URL,FALSE
5158     },
5159     {   "http://google.com/",0,S_OK,FALSE,
5160         {
5161             {TRUE,"winehq.org?test",NULL,Uri_PROPERTY_HOST,S_OK,FALSE}
5162         },
5163         {FALSE},
5164         0,INET_E_INVALID_URL,FALSE,
5165         0,INET_E_INVALID_URL,FALSE,
5166         0,0,0,INET_E_INVALID_URL,FALSE
5167     },
5168     {   "http://google.com/",0,S_OK,FALSE,
5169         {
5170             {TRUE,"winehq.org#test",NULL,Uri_PROPERTY_HOST,S_OK,FALSE}
5171         },
5172         {FALSE},
5173         0,INET_E_INVALID_URL,FALSE,
5174         0,INET_E_INVALID_URL,FALSE,
5175         0,0,0,INET_E_INVALID_URL,FALSE
5176     },
5177     /* Hostname is allowed to contain a ':' (even for known scheme types). */
5178     {   "http://google.com/",0,S_OK,FALSE,
5179         {
5180             {TRUE,"winehq.org:test",NULL,Uri_PROPERTY_HOST,S_OK,FALSE},
5181         },
5182         {FALSE},
5183         0,S_OK,FALSE,
5184         0,S_OK,FALSE,
5185         0,0,0,S_OK,FALSE,
5186         {
5187             {"http://winehq.org:test/",S_OK},
5188             {"winehq.org:test",S_OK},
5189             {"http://winehq.org:test/",S_OK},
5190             {"winehq.org:test",S_OK},
5191             {"",S_FALSE},
5192             {"",S_FALSE},
5193             {"winehq.org:test",S_OK},
5194             {"",S_FALSE},
5195             {"/",S_OK},
5196             {"/",S_OK},
5197             {"",S_FALSE},
5198             {"http://winehq.org:test/",S_OK},
5199             {"http",S_OK},
5200             {"",S_FALSE},
5201             {"",S_FALSE}
5202         },
5203         {
5204             {Uri_HOST_DNS,S_OK},
5205             {80,S_OK},
5206             {URL_SCHEME_HTTP,S_OK},
5207             {URLZONE_INVALID,E_NOTIMPL}
5208         }
5209     },
5210     /* Can't set the host name to NULL. */
5211     {   "http://google.com/",0,S_OK,FALSE,
5212         {
5213             {TRUE,NULL,"google.com",Uri_PROPERTY_HOST,E_INVALIDARG,FALSE}
5214         },
5215         {FALSE},
5216         0,S_OK,FALSE,
5217         0,S_OK,FALSE,
5218         0,0,0,S_OK,FALSE,
5219         {
5220             {"http://google.com/",S_OK},
5221             {"google.com",S_OK},
5222             {"http://google.com/",S_OK},
5223             {"google.com",S_OK},
5224             {"",S_FALSE},
5225             {"",S_FALSE},
5226             {"google.com",S_OK},
5227             {"",S_FALSE},
5228             {"/",S_OK},
5229             {"/",S_OK},
5230             {"",S_FALSE},
5231             {"http://google.com/",S_OK},
5232             {"http",S_OK},
5233             {"",S_FALSE},
5234             {"",S_FALSE}
5235         },
5236         {
5237             {Uri_HOST_DNS,S_OK},
5238             {80,S_OK},
5239             {URL_SCHEME_HTTP,S_OK},
5240             {URLZONE_INVALID,E_NOTIMPL}
5241         }
5242     },
5243     /* Can set the host name to an empty string. */
5244     {   "http://google.com/",0,S_OK,FALSE,
5245         {
5246             {TRUE,"",NULL,Uri_PROPERTY_HOST,S_OK,FALSE}
5247         },
5248         {FALSE},
5249         0,S_OK,FALSE,
5250         0,S_OK,FALSE,
5251         0,0,0,S_OK,FALSE,
5252         {
5253             {"http:///",S_OK},
5254             {"",S_OK},
5255             {"http:///",S_OK},
5256             {"",S_FALSE},
5257             {"",S_FALSE},
5258             {"",S_FALSE},
5259             {"",S_OK},
5260             {"",S_FALSE},
5261             {"/",S_OK},
5262             {"/",S_OK},
5263             {"",S_FALSE},
5264             {"http:///",S_OK},
5265             {"http",S_OK},
5266             {"",S_FALSE},
5267             {"",S_FALSE}
5268         },
5269         {
5270             {Uri_HOST_UNKNOWN,S_OK},
5271             {80,S_OK},
5272             {URL_SCHEME_HTTP,S_OK},
5273             {URLZONE_INVALID,E_NOTIMPL}
5274         }
5275     },
5276     {   "http://google.com/",0,S_OK,FALSE,
5277         {
5278             {TRUE,"/path?query",NULL,Uri_PROPERTY_PATH,S_OK,FALSE}
5279         },
5280         {FALSE},
5281         0,INET_E_INVALID_URL,FALSE,
5282         0,INET_E_INVALID_URL,FALSE,
5283         0,0,0,INET_E_INVALID_URL,FALSE
5284     },
5285     {   "http://google.com/",0,S_OK,FALSE,
5286         {
5287             {TRUE,"/path#test",NULL,Uri_PROPERTY_PATH,S_OK,FALSE}
5288         },
5289         {FALSE},
5290         0,INET_E_INVALID_URL,FALSE,
5291         0,INET_E_INVALID_URL,FALSE,
5292         0,0,0,INET_E_INVALID_URL,FALSE
5293     },
5294     {   "http://google.com/",0,S_OK,FALSE,
5295         {
5296             {TRUE,"?path#test",NULL,Uri_PROPERTY_QUERY,S_OK,FALSE}
5297         },
5298         {FALSE},
5299         0,INET_E_INVALID_URL,FALSE,
5300         0,INET_E_INVALID_URL,FALSE,
5301         0,0,0,INET_E_INVALID_URL,FALSE
5302     }
5303 };
5304
5305 typedef struct _uri_builder_remove_test {
5306     const char  *uri;
5307     DWORD       create_flags;
5308     HRESULT     create_builder_expected;
5309     BOOL        create_builder_todo;
5310
5311     DWORD       remove_properties;
5312     HRESULT     remove_expected;
5313     BOOL        remove_todo;
5314
5315     const char  *expected_uri;
5316     DWORD       expected_flags;
5317     HRESULT     expected_hres;
5318     BOOL        expected_todo;
5319 } uri_builder_remove_test;
5320
5321 static const uri_builder_remove_test uri_builder_remove_tests[] = {
5322     {   "http://google.com/test?test=y#Frag",0,S_OK,FALSE,
5323         Uri_HAS_FRAGMENT|Uri_HAS_PATH|Uri_HAS_QUERY,S_OK,FALSE,
5324         "http://google.com/",0,S_OK,FALSE
5325     },
5326     {   "http://user:pass@winehq.org/",0,S_OK,FALSE,
5327         Uri_HAS_USER_NAME|Uri_HAS_PASSWORD,S_OK,FALSE,
5328         "http://winehq.org/",0,S_OK,FALSE
5329     },
5330     {   "zip://google.com?Test=x",0,S_OK,FALSE,
5331         Uri_HAS_HOST,S_OK,FALSE,
5332         "zip:/?Test=x",0,S_OK,FALSE
5333     },
5334     /* Doesn't remove the whole userinfo component. */
5335     {   "http://username:pass@google.com/",0,S_OK,FALSE,
5336         Uri_HAS_USER_INFO,S_OK,FALSE,
5337         "http://username:pass@google.com/",0,S_OK,FALSE
5338     },
5339     /* Doesn't remove the domain. */
5340     {   "http://google.com/",0,S_OK,FALSE,
5341         Uri_HAS_DOMAIN,S_OK,FALSE,
5342         "http://google.com/",0,S_OK,FALSE
5343     },
5344     {   "http://google.com:120/",0,S_OK,FALSE,
5345         Uri_HAS_AUTHORITY,S_OK,FALSE,
5346         "http://google.com:120/",0,S_OK,FALSE
5347     },
5348     {   "http://google.com/test.com/",0,S_OK,FALSE,
5349         Uri_HAS_EXTENSION,S_OK,FALSE,
5350         "http://google.com/test.com/",0,S_OK,FALSE
5351     },
5352     {   "http://google.com/?test=x",0,S_OK,FALSE,
5353         Uri_HAS_PATH_AND_QUERY,S_OK,FALSE,
5354         "http://google.com/?test=x",0,S_OK,FALSE
5355     },
5356     /* Can't remove the scheme name. */
5357     {   "http://google.com/?test=x",0,S_OK,FALSE,
5358         Uri_HAS_SCHEME_NAME|Uri_HAS_QUERY,E_INVALIDARG,FALSE,
5359         "http://google.com/?test=x",0,S_OK,FALSE
5360     }
5361 };
5362
5363 typedef struct _uri_combine_str_property {
5364     const char  *value;
5365     HRESULT     expected;
5366     BOOL        todo;
5367     const char  *broken_value;
5368     const char  *value_ex;
5369 } uri_combine_str_property;
5370
5371 typedef struct _uri_combine_test {
5372     const char  *base_uri;
5373     DWORD       base_create_flags;
5374     const char  *relative_uri;
5375     DWORD       relative_create_flags;
5376     DWORD       combine_flags;
5377     HRESULT     expected;
5378     BOOL        todo;
5379
5380     uri_combine_str_property    str_props[URI_STR_PROPERTY_COUNT];
5381     uri_dword_property          dword_props[URI_DWORD_PROPERTY_COUNT];
5382 } uri_combine_test;
5383
5384 static const uri_combine_test uri_combine_tests[] = {
5385     {   "http://google.com/fun/stuff",0,
5386         "../not/fun/stuff",Uri_CREATE_ALLOW_RELATIVE,
5387         0,S_OK,FALSE,
5388         {
5389             {"http://google.com/not/fun/stuff",S_OK},
5390             {"google.com",S_OK},
5391             {"http://google.com/not/fun/stuff",S_OK},
5392             {"google.com",S_OK},
5393             {"",S_FALSE},
5394             {"",S_FALSE},
5395             {"google.com",S_OK},
5396             {"",S_FALSE},
5397             {"/not/fun/stuff",S_OK},
5398             {"/not/fun/stuff",S_OK},
5399             {"",S_FALSE},
5400             {"http://google.com/not/fun/stuff",S_OK},
5401             {"http",S_OK},
5402             {"",S_FALSE},
5403             {"",S_FALSE}
5404         },
5405         {
5406             {Uri_HOST_DNS,S_OK},
5407             {80,S_OK},
5408             {URL_SCHEME_HTTP,S_OK},
5409             {URLZONE_INVALID,E_NOTIMPL}
5410         }
5411     },
5412     {   "http://google.com/test",0,
5413         "zip://test.com/cool",0,
5414         0,S_OK,FALSE,
5415         {
5416             {"zip://test.com/cool",S_OK},
5417             {"test.com",S_OK},
5418             {"zip://test.com/cool",S_OK},
5419             {"test.com",S_OK},
5420             {"",S_FALSE},
5421             {"",S_FALSE},
5422             {"test.com",S_OK},
5423             {"",S_FALSE},
5424             {"/cool",S_OK},
5425             {"/cool",S_OK},
5426             {"",S_FALSE},
5427             {"zip://test.com/cool",S_OK},
5428             {"zip",S_OK},
5429             {"",S_FALSE},
5430             {"",S_FALSE}
5431         },
5432         {
5433             {Uri_HOST_DNS,S_OK},
5434             {0,S_FALSE},
5435             {URL_SCHEME_UNKNOWN,S_OK},
5436             {URLZONE_INVALID,E_NOTIMPL}
5437         }
5438     },
5439     {   "http://google.com/use/base/path",0,
5440         "?relative",Uri_CREATE_ALLOW_RELATIVE,
5441         0,S_OK,FALSE,
5442         {
5443             {"http://google.com/use/base/path?relative",S_OK},
5444             {"google.com",S_OK},
5445             {"http://google.com/use/base/path?relative",S_OK},
5446             {"google.com",S_OK},
5447             {"",S_FALSE},
5448             {"",S_FALSE},
5449             {"google.com",S_OK},
5450             {"",S_FALSE},
5451             {"/use/base/path",S_OK},
5452             {"/use/base/path?relative",S_OK},
5453             {"?relative",S_OK},
5454             {"http://google.com/use/base/path?relative",S_OK},
5455             {"http",S_OK},
5456             {"",S_FALSE},
5457             {"",S_FALSE}
5458         },
5459         {
5460             {Uri_HOST_DNS,S_OK},
5461             {80,S_OK},
5462             {URL_SCHEME_HTTP,S_OK},
5463             {URLZONE_INVALID,E_NOTIMPL}
5464         }
5465     },
5466     {   "http://google.com/path",0,
5467         "/test/../test/.././testing",Uri_CREATE_ALLOW_RELATIVE,
5468         0,S_OK,FALSE,
5469         {
5470             {"http://google.com/testing",S_OK},
5471             {"google.com",S_OK},
5472             {"http://google.com/testing",S_OK},
5473             {"google.com",S_OK},
5474             {"",S_FALSE},
5475             {"",S_FALSE},
5476             {"google.com",S_OK},
5477             {"",S_FALSE},
5478             {"/testing",S_OK},
5479             {"/testing",S_OK},
5480             {"",S_FALSE},
5481             {"http://google.com/testing",S_OK},
5482             {"http",S_OK},
5483             {"",S_FALSE},
5484             {"",S_FALSE}
5485         },
5486         {
5487             {Uri_HOST_DNS,S_OK},
5488             {80,S_OK},
5489             {URL_SCHEME_HTTP,S_OK},
5490             {URLZONE_INVALID,E_NOTIMPL}
5491         }
5492     },
5493     {   "http://google.com/path",0,
5494         "/test/../test/.././testing",Uri_CREATE_ALLOW_RELATIVE,
5495         URL_DONT_SIMPLIFY,S_OK,FALSE,
5496         {
5497             {"http://google.com:80/test/../test/.././testing",S_OK},
5498             {"google.com",S_OK},
5499             {"http://google.com:80/test/../test/.././testing",S_OK},
5500             {"google.com",S_OK},
5501             {"",S_FALSE},
5502             {"",S_FALSE},
5503             {"google.com",S_OK},
5504             {"",S_FALSE},
5505             {"/test/../test/.././testing",S_OK},
5506             {"/test/../test/.././testing",S_OK},
5507             {"",S_FALSE},
5508             {"http://google.com:80/test/../test/.././testing",S_OK},
5509             {"http",S_OK},
5510             {"",S_FALSE},
5511             {"",S_FALSE}
5512         },
5513         {
5514             {Uri_HOST_DNS,S_OK},
5515             {80,S_OK},
5516             {URL_SCHEME_HTTP,S_OK},
5517             {URLZONE_INVALID,E_NOTIMPL}
5518         }
5519     },
5520     {   "http://winehq.org/test/abc",0,
5521         "testing/abc/../test",Uri_CREATE_ALLOW_RELATIVE,
5522         0,S_OK,FALSE,
5523         {
5524             {"http://winehq.org/test/testing/test",S_OK},
5525             {"winehq.org",S_OK},
5526             {"http://winehq.org/test/testing/test",S_OK},
5527             {"winehq.org",S_OK},
5528             {"",S_FALSE},
5529             {"",S_FALSE},
5530             {"winehq.org",S_OK},
5531             {"",S_FALSE},
5532             {"/test/testing/test",S_OK},
5533             {"/test/testing/test",S_OK},
5534             {"",S_FALSE},
5535             {"http://winehq.org/test/testing/test",S_OK},
5536             {"http",S_OK},
5537             {"",S_FALSE},
5538             {"",S_FALSE}
5539         },
5540         {
5541             {Uri_HOST_DNS,S_OK},
5542             {80,S_OK},
5543             {URL_SCHEME_HTTP,S_OK},
5544             {URLZONE_INVALID,E_NOTIMPL}
5545         }
5546     },
5547     {   "http://winehq.org/test/abc",0,
5548         "testing/abc/../test",Uri_CREATE_ALLOW_RELATIVE,
5549         URL_DONT_SIMPLIFY,S_OK,FALSE,
5550         {
5551             {"http://winehq.org:80/test/testing/abc/../test",S_OK},
5552             /* Default port is hidden in the authority. */
5553             {"winehq.org",S_OK},
5554             {"http://winehq.org:80/test/testing/abc/../test",S_OK},
5555             {"winehq.org",S_OK},
5556             {"",S_FALSE},
5557             {"",S_FALSE},
5558             {"winehq.org",S_OK},
5559             {"",S_FALSE},
5560             {"/test/testing/abc/../test",S_OK},
5561             {"/test/testing/abc/../test",S_OK},
5562             {"",S_FALSE},
5563             {"http://winehq.org:80/test/testing/abc/../test",S_OK},
5564             {"http",S_OK},
5565             {"",S_FALSE},
5566             {"",S_FALSE}
5567         },
5568         {
5569             {Uri_HOST_DNS,S_OK},
5570             {80,S_OK},
5571             {URL_SCHEME_HTTP,S_OK},
5572             {URLZONE_INVALID,E_NOTIMPL}
5573         }
5574     },
5575     {   "http://winehq.org/test?query",0,
5576         "testing",Uri_CREATE_ALLOW_RELATIVE,
5577         0,S_OK,FALSE,
5578         {
5579             {"http://winehq.org/testing",S_OK},
5580             {"winehq.org",S_OK},
5581             {"http://winehq.org/testing",S_OK},
5582             {"winehq.org",S_OK},
5583             {"",S_FALSE},
5584             {"",S_FALSE},
5585             {"winehq.org",S_OK},
5586             {"",S_FALSE},
5587             {"/testing",S_OK},
5588             {"/testing",S_OK},
5589             {"",S_FALSE},
5590             {"http://winehq.org/testing",S_OK},
5591             {"http",S_OK},
5592             {"",S_FALSE},
5593             {"",S_FALSE}
5594         },
5595         {
5596             {Uri_HOST_DNS,S_OK},
5597             {80,S_OK},
5598             {URL_SCHEME_HTTP,S_OK},
5599             {URLZONE_INVALID,E_NOTIMPL}
5600         }
5601     },
5602     {   "http://winehq.org/test#frag",0,
5603         "testing",Uri_CREATE_ALLOW_RELATIVE,
5604         0,S_OK,FALSE,
5605         {
5606             {"http://winehq.org/testing",S_OK},
5607             {"winehq.org",S_OK},
5608             {"http://winehq.org/testing",S_OK},
5609             {"winehq.org",S_OK},
5610             {"",S_FALSE},
5611             {"",S_FALSE},
5612             {"winehq.org",S_OK},
5613             {"",S_FALSE},
5614             {"/testing",S_OK},
5615             {"/testing",S_OK},
5616             {"",S_FALSE},
5617             {"http://winehq.org/testing",S_OK},
5618             {"http",S_OK},
5619             {"",S_FALSE},
5620             {"",S_FALSE}
5621         },
5622         {
5623             {Uri_HOST_DNS,S_OK},
5624             {80,S_OK},
5625             {URL_SCHEME_HTTP,S_OK},
5626             {URLZONE_INVALID,E_NOTIMPL}
5627         }
5628     },
5629     {   "testing?query#frag",Uri_CREATE_ALLOW_RELATIVE,
5630         "test",Uri_CREATE_ALLOW_RELATIVE,
5631         0,S_OK,FALSE,
5632         {
5633             {"test",S_OK},
5634             {"",S_FALSE},
5635             {"test",S_OK},
5636             {"",S_FALSE},
5637             {"",S_FALSE},
5638             {"",S_FALSE},
5639             {"",S_FALSE},
5640             {"",S_FALSE},
5641             {"test",S_OK},
5642             {"test",S_OK},
5643             {"",S_FALSE},
5644             {"test",S_OK},
5645             {"",S_FALSE},
5646             {"",S_FALSE},
5647             {"",S_FALSE}
5648         },
5649         {
5650             {Uri_HOST_UNKNOWN,S_OK},
5651             {0,S_FALSE},
5652             {URL_SCHEME_UNKNOWN,S_OK},
5653             {URLZONE_INVALID,E_NOTIMPL}
5654         }
5655     },
5656     {   "file:///c:/test/test",0,
5657         "/testing.mp3",Uri_CREATE_ALLOW_RELATIVE,
5658         URL_FILE_USE_PATHURL,S_OK,FALSE,
5659         {
5660             {"file://c:\\testing.mp3",S_OK},
5661             {"",S_FALSE},
5662             {"file://c:\\testing.mp3",S_OK},
5663             {"",S_FALSE},
5664             {".mp3",S_OK},
5665             {"",S_FALSE},
5666             {"",S_FALSE},
5667             {"",S_FALSE},
5668             {"c:\\testing.mp3",S_OK},
5669             {"c:\\testing.mp3",S_OK},
5670             {"",S_FALSE},
5671             {"file://c:\\testing.mp3",S_OK},
5672             {"file",S_OK},
5673             {"",S_FALSE},
5674             {"",S_FALSE}
5675         },
5676         {
5677             {Uri_HOST_UNKNOWN,S_OK},
5678             {0,S_FALSE},
5679             {URL_SCHEME_FILE,S_OK},
5680             {URLZONE_INVALID,E_NOTIMPL}
5681         }
5682     },
5683     {   "file:///c:/test/test",0,
5684         "/testing.mp3",Uri_CREATE_ALLOW_RELATIVE,
5685         0,S_OK,FALSE,
5686         {
5687             {"file:///c:/testing.mp3",S_OK},
5688             {"",S_FALSE},
5689             {"file:///c:/testing.mp3",S_OK},
5690             {"",S_FALSE},
5691             {".mp3",S_OK},
5692             {"",S_FALSE},
5693             {"",S_FALSE},
5694             {"",S_FALSE},
5695             {"/c:/testing.mp3",S_OK},
5696             {"/c:/testing.mp3",S_OK},
5697             {"",S_FALSE},
5698             {"file:///c:/testing.mp3",S_OK},
5699             {"file",S_OK},
5700             {"",S_FALSE},
5701             {"",S_FALSE}
5702         },
5703         {
5704             {Uri_HOST_UNKNOWN,S_OK},
5705             {0,S_FALSE},
5706             {URL_SCHEME_FILE,S_OK},
5707             {URLZONE_INVALID,E_NOTIMPL}
5708         }
5709     },
5710     {   "file://test.com/test/test",0,
5711         "/testing.mp3",Uri_CREATE_ALLOW_RELATIVE,
5712         URL_FILE_USE_PATHURL,S_OK,FALSE,
5713         {
5714             {"file://\\\\test.com\\testing.mp3",S_OK},
5715             {"test.com",S_OK},
5716             {"file://\\\\test.com\\testing.mp3",S_OK},
5717             {"test.com",S_OK},
5718             {".mp3",S_OK},
5719             {"",S_FALSE},
5720             {"test.com",S_OK},
5721             {"",S_FALSE},
5722             {"\\testing.mp3",S_OK},
5723             {"\\testing.mp3",S_OK},
5724             {"",S_FALSE},
5725             {"file://\\\\test.com\\testing.mp3",S_OK},
5726             {"file",S_OK},
5727             {"",S_FALSE},
5728             {"",S_FALSE}
5729         },
5730         {
5731             {Uri_HOST_DNS,S_OK},
5732             {0,S_FALSE},
5733             {URL_SCHEME_FILE,S_OK},
5734             {URLZONE_INVALID,E_NOTIMPL}
5735         }
5736     },
5737     /* URL_DONT_SIMPLIFY has no effect. */
5738     {   "http://google.com/test",0,
5739         "zip://test.com/cool/../cool/test",0,
5740         URL_DONT_SIMPLIFY,S_OK,FALSE,
5741         {
5742             {"zip://test.com/cool/test",S_OK,FALSE,NULL,"zip://test.com/cool/../cool/test"},
5743             {"test.com",S_OK},
5744             {"zip://test.com/cool/test",S_OK,FALSE,NULL,"zip://test.com/cool/../cool/test"},
5745             {"test.com",S_OK},
5746             {"",S_FALSE},
5747             {"",S_FALSE},
5748             {"test.com",S_OK},
5749             {"",S_FALSE},
5750             {"/cool/test",S_OK,FALSE,NULL,"/cool/../cool/test"},
5751             {"/cool/test",S_OK,FALSE,NULL,"/cool/../cool/test"},
5752             {"",S_FALSE},
5753             /* The resulting IUri has the same Raw URI as the relative URI (only IE 8).
5754              * On IE 7 it reduces the path in the Raw URI.
5755              */
5756             {"zip://test.com/cool/../cool/test",S_OK,FALSE,"zip://test.com/cool/test"},
5757             {"zip",S_OK},
5758             {"",S_FALSE},
5759             {"",S_FALSE}
5760         },
5761         {
5762             {Uri_HOST_DNS,S_OK},
5763             {0,S_FALSE},
5764             {URL_SCHEME_UNKNOWN,S_OK},
5765             {URLZONE_INVALID,E_NOTIMPL}
5766         }
5767     },
5768     /* FILE_USE_PATHURL has no effect in IE 8, in IE 7 the
5769      * resulting URI is converted into a dos path.
5770      */
5771     {   "http://google.com/test",0,
5772         "file:///c:/test/",0,
5773         URL_FILE_USE_PATHURL,S_OK,FALSE,
5774         {
5775             {"file:///c:/test/",S_OK,FALSE,"file://c:\\test\\"},
5776             {"",S_FALSE},
5777             {"file:///c:/test/",S_OK,FALSE,"file://c:\\test\\"},
5778             {"",S_FALSE},
5779             {"",S_FALSE},
5780             {"",S_FALSE},
5781             {"",S_FALSE},
5782             {"",S_FALSE},
5783             {"/c:/test/",S_OK,FALSE,"c:\\test\\"},
5784             {"/c:/test/",S_OK,FALSE,"c:\\test\\"},
5785             {"",S_FALSE},
5786             {"file:///c:/test/",S_OK,FALSE,"file://c:\\test\\"},
5787             {"file",S_OK},
5788             {"",S_FALSE},
5789             {"",S_FALSE}
5790         },
5791         {
5792             {Uri_HOST_UNKNOWN,S_OK},
5793             {0,S_FALSE},
5794             {URL_SCHEME_FILE,S_OK},
5795             {URLZONE_INVALID,E_NOTIMPL}
5796         }
5797     },
5798     {   "http://google.com/test",0,
5799         "http://test.com/test#%30test",0,
5800         URL_DONT_UNESCAPE_EXTRA_INFO,S_OK,FALSE,
5801         {
5802             {"http://test.com/test#0test",S_OK,FALSE,NULL,"http://test.com/test#%30test"},
5803             {"test.com",S_OK},
5804             {"http://test.com/test#0test",S_OK,FALSE,NULL,"http://test.com/test#%30test"},
5805             {"test.com",S_OK},
5806             {"",S_FALSE},
5807             {"#0test",S_OK,FALSE,NULL,"#%30test"},
5808             {"test.com",S_OK},
5809             {"",S_FALSE},
5810             {"/test",S_OK},
5811             {"/test",S_OK},
5812             {"",S_FALSE},
5813             /* IE 7 decodes the %30 to a 0 in the Raw URI. */
5814             {"http://test.com/test#%30test",S_OK,FALSE,"http://test.com/test#0test"},
5815             {"http",S_OK},
5816             {"",S_FALSE},
5817             {"",S_FALSE}
5818         },
5819         {
5820             {Uri_HOST_DNS,S_OK},
5821             {80,S_OK},
5822             {URL_SCHEME_HTTP,S_OK},
5823             {URLZONE_INVALID,E_NOTIMPL}
5824         }
5825     },
5826     /* Windows validates the path component from the relative Uri. */
5827     {   "http://google.com/test",0,
5828         "/Te%XXst",Uri_CREATE_ALLOW_RELATIVE,
5829         0,E_INVALIDARG,FALSE
5830     },
5831     /* Windows doesn't validate the query from the relative Uri. */
5832     {   "http://google.com/test",0,
5833         "?Tes%XXt",Uri_CREATE_ALLOW_RELATIVE,
5834         0,S_OK,FALSE,
5835         {
5836             {"http://google.com/test?Tes%XXt",S_OK},
5837             {"google.com",S_OK},
5838             {"http://google.com/test?Tes%XXt",S_OK},
5839             {"google.com",S_OK},
5840             {"",S_FALSE},
5841             {"",S_FALSE},
5842             {"google.com",S_OK},
5843             {"",S_FALSE},
5844             {"/test",S_OK},
5845             {"/test?Tes%XXt",S_OK},
5846             {"?Tes%XXt",S_OK},
5847             {"http://google.com/test?Tes%XXt",S_OK},
5848             {"http",S_OK},
5849             {"",S_FALSE},
5850             {"",S_FALSE}
5851         },
5852         {
5853             {Uri_HOST_DNS,S_OK},
5854             {80,S_OK},
5855             {URL_SCHEME_HTTP,S_OK},
5856             {URLZONE_INVALID,E_NOTIMPL}
5857         }
5858     },
5859     /* Windows doesn't validate the fragment from the relative Uri. */
5860     {   "http://google.com/test",0,
5861         "#Tes%XXt",Uri_CREATE_ALLOW_RELATIVE,
5862         0,S_OK,FALSE,
5863         {
5864             {"http://google.com/test#Tes%XXt",S_OK},
5865             {"google.com",S_OK},
5866             {"http://google.com/test#Tes%XXt",S_OK},
5867             {"google.com",S_OK},
5868             {"",S_FALSE},
5869             {"#Tes%XXt",S_OK},
5870             {"google.com",S_OK},
5871             {"",S_FALSE},
5872             {"/test",S_OK},
5873             {"/test",S_OK},
5874             {"",S_FALSE},
5875             {"http://google.com/test#Tes%XXt",S_OK},
5876             {"http",S_OK},
5877             {"",S_FALSE},
5878             {"",S_FALSE}
5879         },
5880         {
5881             {Uri_HOST_DNS,S_OK},
5882             {80,S_OK},
5883             {URL_SCHEME_HTTP,S_OK},
5884             {URLZONE_INVALID,E_NOTIMPL}
5885         }
5886     },
5887     /* Creates an IUri which contains an invalid dos path char. */
5888     {   "file:///c:/test",0,
5889         "/test<ing",Uri_CREATE_ALLOW_RELATIVE,
5890         URL_FILE_USE_PATHURL,S_OK,FALSE,
5891         {
5892             {"file://c:\\test<ing",S_OK},
5893             {"",S_FALSE},
5894             {"file://c:\\test<ing",S_OK},
5895             {"",S_FALSE},
5896             {"",S_FALSE},
5897             {"",S_FALSE},
5898             {"",S_FALSE},
5899             {"",S_FALSE},
5900             {"c:\\test<ing",S_OK},
5901             {"c:\\test<ing",S_OK},
5902             {"",S_FALSE},
5903             {"file://c:\\test<ing",S_OK},
5904             {"file",S_OK},
5905             {"",S_FALSE},
5906             {"",S_FALSE}
5907         },
5908         {
5909             {Uri_HOST_UNKNOWN,S_OK},
5910             {0,S_FALSE},
5911             {URL_SCHEME_FILE,S_OK},
5912             {URLZONE_INVALID,E_NOTIMPL}
5913         }
5914     },
5915     /* Appends the path after the drive letter (if any). */
5916     {   "file:///c:/test",0,
5917         "/c:/testing",Uri_CREATE_ALLOW_RELATIVE,
5918         0,S_OK,FALSE,
5919         {
5920             {"file:///c:/c:/testing",S_OK},
5921             {"",S_FALSE},
5922             {"file:///c:/c:/testing",S_OK},
5923             {"",S_FALSE},
5924             {"",S_FALSE},
5925             {"",S_FALSE},
5926             {"",S_FALSE},
5927             {"",S_FALSE},
5928             {"/c:/c:/testing",S_OK},
5929             {"/c:/c:/testing",S_OK},
5930             {"",S_FALSE},
5931             {"file:///c:/c:/testing",S_OK},
5932             {"file",S_OK},
5933             {"",S_FALSE},
5934             {"",S_FALSE}
5935         },
5936         {
5937             {Uri_HOST_UNKNOWN,S_OK},
5938             {0,S_FALSE},
5939             {URL_SCHEME_FILE,S_OK},
5940             {URLZONE_INVALID,E_NOTIMPL}
5941         }
5942     },
5943     /* A '/' is added if the base URI doesn't have a path and the
5944      * relative URI doesn't contain a path (since the base URI is
5945      * hierarchical.
5946      */
5947     {   "http://google.com",Uri_CREATE_NO_CANONICALIZE,
5948         "?test",Uri_CREATE_ALLOW_RELATIVE,
5949         0,S_OK,FALSE,
5950         {
5951             {"http://google.com/?test",S_OK},
5952             {"google.com",S_OK},
5953             {"http://google.com/?test",S_OK},
5954             {"google.com",S_OK},
5955             {"",S_FALSE},
5956             {"",S_FALSE},
5957             {"google.com",S_OK},
5958             {"",S_FALSE},
5959             {"/",S_OK},
5960             {"/?test",S_OK},
5961             {"?test",S_OK},
5962             {"http://google.com/?test",S_OK},
5963             {"http",S_OK},
5964             {"",S_FALSE},
5965             {"",S_FALSE}
5966         },
5967         {
5968             {Uri_HOST_DNS,S_OK},
5969             {80,S_OK},
5970             {URL_SCHEME_HTTP,S_OK},
5971             {URLZONE_INVALID,E_NOTIMPL}
5972         }
5973     },
5974     {   "zip://google.com",Uri_CREATE_NO_CANONICALIZE,
5975         "?test",Uri_CREATE_ALLOW_RELATIVE,
5976         0,S_OK,FALSE,
5977         {
5978             {"zip://google.com/?test",S_OK},
5979             {"google.com",S_OK},
5980             {"zip://google.com/?test",S_OK},
5981             {"google.com",S_OK},
5982             {"",S_FALSE},
5983             {"",S_FALSE},
5984             {"google.com",S_OK},
5985             {"",S_FALSE},
5986             {"/",S_OK},
5987             {"/?test",S_OK},
5988             {"?test",S_OK},
5989             {"zip://google.com/?test",S_OK},
5990             {"zip",S_OK},
5991             {"",S_FALSE},
5992             {"",S_FALSE}
5993         },
5994         {
5995             {Uri_HOST_DNS,S_OK},
5996             {0,S_FALSE},
5997             {URL_SCHEME_UNKNOWN,S_OK},
5998             {URLZONE_INVALID,E_NOTIMPL}
5999         }
6000     },
6001     /* No path is appended since the base URI is opaque. */
6002     {   "zip:?testing",0,
6003         "?test",Uri_CREATE_ALLOW_RELATIVE,
6004         0,S_OK,FALSE,
6005         {
6006             {"zip:?test",S_OK},
6007             {"",S_FALSE},
6008             {"zip:?test",S_OK},
6009             {"",S_FALSE},
6010             {"",S_FALSE},
6011             {"",S_FALSE},
6012             {"",S_FALSE},
6013             {"",S_FALSE},
6014             {"",S_OK},
6015             {"?test",S_OK},
6016             {"?test",S_OK},
6017             {"zip:?test",S_OK},
6018             {"zip",S_OK},
6019             {"",S_FALSE},
6020             {"",S_FALSE}
6021         },
6022         {
6023             {Uri_HOST_UNKNOWN,S_OK},
6024             {0,S_FALSE},
6025             {URL_SCHEME_UNKNOWN,S_OK},
6026             {URLZONE_INVALID,E_NOTIMPL}
6027         }
6028     },
6029     {   "file:///c:/",0,
6030         "../testing/test",Uri_CREATE_ALLOW_RELATIVE,
6031         0,S_OK,FALSE,
6032         {
6033             {"file:///c:/testing/test",S_OK},
6034             {"",S_FALSE},
6035             {"file:///c:/testing/test",S_OK},
6036             {"",S_FALSE},
6037             {"",S_FALSE},
6038             {"",S_FALSE},
6039             {"",S_FALSE},
6040             {"",S_FALSE},
6041             {"/c:/testing/test",S_OK},
6042             {"/c:/testing/test",S_OK},
6043             {"",S_FALSE},
6044             {"file:///c:/testing/test",S_OK},
6045             {"file",S_OK},
6046             {"",S_FALSE},
6047             {"",S_FALSE}
6048         },
6049         {
6050             {Uri_HOST_UNKNOWN,S_OK},
6051             {0,S_FALSE},
6052             {URL_SCHEME_FILE,S_OK},
6053             {URLZONE_INVALID,E_NOTIMPL}
6054         }
6055     }
6056 };
6057
6058 typedef struct _uri_parse_test {
6059     const char  *uri;
6060     DWORD       uri_flags;
6061     PARSEACTION action;
6062     DWORD       flags;
6063     const char  *property;
6064     HRESULT     expected;
6065     BOOL        todo;
6066 } uri_parse_test;
6067
6068 static const uri_parse_test uri_parse_tests[] = {
6069     /* PARSE_CANONICALIZE tests. */
6070     {"zip://google.com/test<|>",0,PARSE_CANONICALIZE,0,"zip://google.com/test<|>",S_OK,FALSE},
6071     {"http://google.com/test<|>",0,PARSE_CANONICALIZE,0,"http://google.com/test%3C%7C%3E",S_OK,FALSE},
6072     {"http://google.com/%30%23%3F",0,PARSE_CANONICALIZE,URL_UNESCAPE,"http://google.com/0#?",S_OK,FALSE},
6073     {"test <|>",Uri_CREATE_ALLOW_RELATIVE,PARSE_CANONICALIZE,URL_ESCAPE_UNSAFE,"test %3C%7C%3E",S_OK,FALSE},
6074     {"test <|>",Uri_CREATE_ALLOW_RELATIVE,PARSE_CANONICALIZE,URL_ESCAPE_SPACES_ONLY,"test%20<|>",S_OK,FALSE},
6075     {"test%20<|>",Uri_CREATE_ALLOW_RELATIVE,PARSE_CANONICALIZE,URL_UNESCAPE|URL_ESCAPE_UNSAFE,"test%20%3C%7C%3E",S_OK,FALSE},
6076     {"http://google.com/%20",0,PARSE_CANONICALIZE,URL_ESCAPE_PERCENT,"http://google.com/%2520",S_OK,FALSE},
6077     {"http://google.com/test/../",Uri_CREATE_NO_CANONICALIZE,PARSE_CANONICALIZE,URL_DONT_SIMPLIFY,"http://google.com/test/../",S_OK,FALSE},
6078     {"http://google.com/test/../",Uri_CREATE_NO_CANONICALIZE,PARSE_CANONICALIZE,URL_NO_META,"http://google.com/test/../",S_OK,FALSE},
6079     {"http://google.com/test/../",Uri_CREATE_NO_CANONICALIZE,PARSE_CANONICALIZE,0,"http://google.com/",S_OK,FALSE},
6080     {"zip://google.com/test/../",Uri_CREATE_NO_CANONICALIZE,PARSE_CANONICALIZE,0,"zip://google.com/",S_OK,FALSE},
6081     {"file:///c:/test/../test",Uri_CREATE_NO_CANONICALIZE,PARSE_CANONICALIZE,URL_DONT_SIMPLIFY,"file:///c:/test/../test",S_OK,FALSE},
6082
6083     /* PARSE_FRIENDLY tests. */
6084     {"http://test@google.com/test#test",0,PARSE_FRIENDLY,0,"http://google.com/test#test",S_OK,FALSE},
6085     {"zip://test@google.com/test",0,PARSE_FRIENDLY,0,"zip://test@google.com/test",S_OK,FALSE},
6086
6087     /* PARSE_ROOTDOCUMENT tests. */
6088     {"http://google.com:200/test/test",0,PARSE_ROOTDOCUMENT,0,"http://google.com:200/",S_OK,FALSE},
6089     {"http://google.com",Uri_CREATE_NO_CANONICALIZE,PARSE_ROOTDOCUMENT,0,"http://google.com/",S_OK,FALSE},
6090     {"zip://google.com/",0,PARSE_ROOTDOCUMENT,0,"",S_OK,FALSE},
6091     {"file:///c:/testing/",0,PARSE_ROOTDOCUMENT,0,"",S_OK,FALSE},
6092     {"file://server/test",0,PARSE_ROOTDOCUMENT,0,"",S_OK,FALSE},
6093     {"zip:test/test",0,PARSE_ROOTDOCUMENT,0,"",S_OK,FALSE},
6094
6095     /* PARSE_DOCUMENT tests. */
6096     {"http://test@google.com/test?query#frag",0,PARSE_DOCUMENT,0,"http://test@google.com/test?query",S_OK,FALSE},
6097     {"http:testing#frag",0,PARSE_DOCUMENT,0,"",S_OK,FALSE},
6098     {"file:///c:/test#frag",0,PARSE_DOCUMENT,0,"",S_OK,FALSE},
6099     {"zip://google.com/#frag",0,PARSE_DOCUMENT,0,"",S_OK,FALSE},
6100     {"zip:test#frag",0,PARSE_DOCUMENT,0,"",S_OK,FALSE},
6101     {"testing#frag",Uri_CREATE_ALLOW_RELATIVE,PARSE_DOCUMENT,0,"",S_OK,FALSE},
6102
6103     /* PARSE_PATH_FROM_URL tests. */
6104     {"file:///c:/test.mp3",0,PARSE_PATH_FROM_URL,0,"c:\\test.mp3",S_OK,FALSE},
6105     {"file:///c:/t<|>est.mp3",0,PARSE_PATH_FROM_URL,0,"c:\\t<|>est.mp3",S_OK,FALSE},
6106     {"file:///c:/te%XX t/",0,PARSE_PATH_FROM_URL,0,"c:\\te%XX t\\",S_OK,FALSE},
6107     {"file://server/test",0,PARSE_PATH_FROM_URL,0,"\\\\server\\test",S_OK,FALSE},
6108     {"http://google.com/",0,PARSE_PATH_FROM_URL,0,"",E_INVALIDARG,FALSE},
6109
6110     /* PARSE_URL_FROM_PATH tests. */
6111     /* This function almost seems to useless (just returns the absolute uri). */
6112     {"test.com",Uri_CREATE_ALLOW_RELATIVE,PARSE_URL_FROM_PATH,0,"test.com",S_OK,FALSE},
6113     {"/test/test",Uri_CREATE_ALLOW_RELATIVE,PARSE_URL_FROM_PATH,0,"/test/test",S_OK,FALSE},
6114     {"file://c:\\test\\test",Uri_CREATE_FILE_USE_DOS_PATH,PARSE_URL_FROM_PATH,0,"file://c:\\test\\test",S_OK,FALSE},
6115     {"file:c:/test",0,PARSE_URL_FROM_PATH,0,"",S_OK,FALSE},
6116     {"http:google.com/",0,PARSE_URL_FROM_PATH,0,"",S_OK,FALSE},
6117
6118     /* PARSE_SCHEMA tests. */
6119     {"http://google.com/test",0,PARSE_SCHEMA,0,"http",S_OK,FALSE},
6120     {"test",Uri_CREATE_ALLOW_RELATIVE,PARSE_SCHEMA,0,"",S_OK,FALSE},
6121
6122     /* PARSE_SITE tests. */
6123     {"http://google.uk.com/",0,PARSE_SITE,0,"google.uk.com",S_OK,FALSE},
6124     {"http://google.com.com/",0,PARSE_SITE,0,"google.com.com",S_OK,FALSE},
6125     {"google.com",Uri_CREATE_ALLOW_RELATIVE,PARSE_SITE,0,"",S_OK,FALSE},
6126     {"file://server/test",0,PARSE_SITE,0,"server",S_OK,FALSE},
6127
6128     /* PARSE_DOMAIN tests. */
6129     {"http://google.com.uk/",0,PARSE_DOMAIN,0,"google.com.uk",S_OK,FALSE},
6130     {"http://google.com.com/",0,PARSE_DOMAIN,0,"com.com",S_OK,FALSE},
6131     {"test/test",Uri_CREATE_ALLOW_RELATIVE,PARSE_DOMAIN,0,"",S_OK,FALSE},
6132     {"file://server/test",0,PARSE_DOMAIN,0,"",S_OK,FALSE},
6133
6134     /* PARSE_LOCATION and PARSE_ANCHOR tests. */
6135     {"http://google.com/test#Test",0,PARSE_ANCHOR,0,"#Test",S_OK,FALSE},
6136     {"http://google.com/test#Test",0,PARSE_LOCATION,0,"#Test",S_OK,FALSE},
6137     {"test",Uri_CREATE_ALLOW_RELATIVE,PARSE_ANCHOR,0,"",S_OK,FALSE},
6138     {"test",Uri_CREATE_ALLOW_RELATIVE,PARSE_LOCATION,0,"",S_OK,FALSE}
6139 };
6140
6141 static inline LPWSTR a2w(LPCSTR str) {
6142     LPWSTR ret = NULL;
6143
6144     if(str) {
6145         DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
6146         ret = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
6147         MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len);
6148     }
6149
6150     return ret;
6151 }
6152
6153 static inline BOOL heap_free(void* mem) {
6154     return HeapFree(GetProcessHeap(), 0, mem);
6155 }
6156
6157 static inline DWORD strcmp_aw(LPCSTR strA, LPCWSTR strB) {
6158     LPWSTR strAW = a2w(strA);
6159     DWORD ret = lstrcmpW(strAW, strB);
6160     heap_free(strAW);
6161     return ret;
6162 }
6163
6164 static inline ULONG get_refcnt(IUri *uri) {
6165     IUri_AddRef(uri);
6166     return IUri_Release(uri);
6167 }
6168
6169 static void change_property(IUriBuilder *builder, const uri_builder_property *prop,
6170                             DWORD test_index) {
6171     HRESULT hr;
6172     LPWSTR valueW;
6173
6174     valueW = a2w(prop->value);
6175     switch(prop->property) {
6176     case Uri_PROPERTY_FRAGMENT:
6177         hr = IUriBuilder_SetFragment(builder, valueW);
6178         if(prop->todo) {
6179             todo_wine {
6180                 ok(hr == prop->expected,
6181                     "Error: IUriBuilder_SetFragment returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6182                     hr, prop->expected, test_index);
6183             }
6184         } else {
6185             ok(hr == prop->expected,
6186                 "Error: IUriBuilder_SetFragment returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6187                 hr, prop->expected, test_index);
6188         }
6189         break;
6190     case Uri_PROPERTY_HOST:
6191         hr = IUriBuilder_SetHost(builder, valueW);
6192         if(prop->todo) {
6193             todo_wine {
6194                 ok(hr == prop->expected,
6195                     "Error: IUriBuilder_SetHost returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6196                     hr, prop->expected, test_index);
6197             }
6198         } else {
6199             ok(hr == prop->expected,
6200                 "Error: IUriBuilder_SetHost returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6201                 hr, prop->expected, test_index);
6202         }
6203         break;
6204     case Uri_PROPERTY_PASSWORD:
6205         hr = IUriBuilder_SetPassword(builder, valueW);
6206         if(prop->todo) {
6207             todo_wine {
6208                 ok(hr == prop->expected,
6209                     "Error: IUriBuilder_SetPassword returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6210                     hr, prop->expected, test_index);
6211             }
6212         } else {
6213             ok(hr == prop->expected,
6214                 "Error: IUriBuilder_SetPassword returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6215                 hr, prop->expected, test_index);
6216         }
6217         break;
6218     case Uri_PROPERTY_PATH:
6219         hr = IUriBuilder_SetPath(builder, valueW);
6220         if(prop->todo) {
6221             todo_wine {
6222                 ok(hr == prop->expected,
6223                     "Error: IUriBuilder_SetPath returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6224                     hr, prop->expected, test_index);
6225             }
6226         } else {
6227             ok(hr == prop->expected,
6228                 "Error: IUriBuilder_SetPath returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6229                 hr, prop->expected, test_index);
6230         }
6231         break;
6232     case Uri_PROPERTY_QUERY:
6233         hr = IUriBuilder_SetQuery(builder, valueW);
6234         if(prop->todo) {
6235             todo_wine {
6236                 ok(hr == prop->expected,
6237                     "Error: IUriBuilder_SetQuery returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6238                     hr, prop->expected, test_index);
6239             }
6240         } else {
6241             ok(hr == prop->expected,
6242                 "Error: IUriBuilder_SetQuery returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6243                 hr, prop->expected, test_index);
6244         }
6245         break;
6246     case Uri_PROPERTY_SCHEME_NAME:
6247         hr = IUriBuilder_SetSchemeName(builder, valueW);
6248         if(prop->todo) {
6249             todo_wine {
6250                 ok(hr == prop->expected,
6251                     "Error: IUriBuilder_SetSchemeName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6252                     hr, prop->expected, test_index);
6253             }
6254         } else {
6255             ok(hr == prop->expected,
6256                 "Error: IUriBuilder_SetSchemeName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6257                 hr, prop->expected, test_index);
6258         }
6259         break;
6260     case Uri_PROPERTY_USER_NAME:
6261         hr = IUriBuilder_SetUserName(builder, valueW);
6262         if(prop->todo) {
6263             todo_wine {
6264                 ok(hr == prop->expected,
6265                     "Error: IUriBuilder_SetUserName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6266                     hr, prop->expected, test_index);
6267             }
6268         } else {
6269             ok(hr == prop->expected,
6270                 "Error: IUriBuilder_SetUserName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6271                 hr, prop->expected, test_index);
6272         }
6273         break;
6274     default:
6275         trace("Unsupported operation for %d on uri_builder_tests[%d].\n", prop->property, test_index);
6276     }
6277
6278     heap_free(valueW);
6279 }
6280
6281 /*
6282  * Simple tests to make sure the CreateUri function handles invalid flag combinations
6283  * correctly.
6284  */
6285 static void test_CreateUri_InvalidFlags(void) {
6286     DWORD i;
6287
6288     for(i = 0; i < sizeof(invalid_flag_tests)/sizeof(invalid_flag_tests[0]); ++i) {
6289         HRESULT hr;
6290         IUri *uri = (void*) 0xdeadbeef;
6291
6292         hr = pCreateUri(http_urlW, invalid_flag_tests[i].flags, 0, &uri);
6293         ok(hr == invalid_flag_tests[i].expected, "Error: CreateUri returned 0x%08x, expected 0x%08x, flags=0x%08x\n",
6294                 hr, invalid_flag_tests[i].expected, invalid_flag_tests[i].flags);
6295         ok(uri == NULL, "Error: expected the IUri to be NULL, but it was %p instead\n", uri);
6296     }
6297 }
6298
6299 static void test_CreateUri_InvalidArgs(void) {
6300     HRESULT hr;
6301     IUri *uri = (void*) 0xdeadbeef;
6302
6303     const WCHAR invalidW[] = {'i','n','v','a','l','i','d',0};
6304     static const WCHAR emptyW[] = {0};
6305
6306     hr = pCreateUri(http_urlW, 0, 0, NULL);
6307     ok(hr == E_INVALIDARG, "Error: CreateUri returned 0x%08x, expected 0x%08x\n", hr, E_INVALIDARG);
6308
6309     hr = pCreateUri(NULL, 0, 0, &uri);
6310     ok(hr == E_INVALIDARG, "Error: CreateUri returned 0x%08x, expected 0x%08x\n", hr, E_INVALIDARG);
6311     ok(uri == NULL, "Error: Expected the IUri to be NULL, but it was %p instead\n", uri);
6312
6313     uri = (void*) 0xdeadbeef;
6314     hr = pCreateUri(invalidW, 0, 0, &uri);
6315     ok(hr == E_INVALIDARG, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
6316     ok(uri == NULL, "Error: Expected the IUri to be NULL, but it was %p instead\n", uri);
6317
6318     uri = (void*) 0xdeadbeef;
6319     hr = pCreateUri(emptyW, 0, 0, &uri);
6320     ok(hr == E_INVALIDARG, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
6321     ok(uri == NULL, "Error: Expected the IUri to be NULL, but it was %p instead\n", uri);
6322 }
6323
6324 static void test_CreateUri_InvalidUri(void) {
6325     DWORD i;
6326
6327     for(i = 0; i < sizeof(invalid_uri_tests)/sizeof(invalid_uri_tests[0]); ++i) {
6328         invalid_uri test = invalid_uri_tests[i];
6329         IUri *uri = NULL;
6330         LPWSTR uriW;
6331         HRESULT hr;
6332
6333         uriW = a2w(test.uri);
6334         hr = pCreateUri(uriW, test.flags, 0, &uri);
6335         if(test.todo) {
6336             todo_wine {
6337                 ok(hr == E_INVALIDARG, "Error: CreateUri returned 0x%08x, expected 0x%08x on invalid_uri_tests[%d].\n",
6338                     hr, E_INVALIDARG, i);
6339             }
6340         } else {
6341             ok(hr == E_INVALIDARG, "Error: CreateUri returned 0x%08x, expected 0x%08x on invalid_uri_tests[%d].\n",
6342                 hr, E_INVALIDARG, i);
6343         }
6344         if(uri) IUri_Release(uri);
6345
6346         heap_free(uriW);
6347     }
6348 }
6349
6350 static void test_IUri_GetPropertyBSTR(void) {
6351     IUri *uri = NULL;
6352     HRESULT hr;
6353     DWORD i;
6354
6355     /* Make sure GetPropertyBSTR handles invalid args correctly. */
6356     hr = pCreateUri(http_urlW, 0, 0, &uri);
6357     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
6358     if(SUCCEEDED(hr)) {
6359         BSTR received = NULL;
6360
6361         hr = IUri_GetPropertyBSTR(uri, Uri_PROPERTY_RAW_URI, NULL, 0);
6362         ok(hr == E_POINTER, "Error: GetPropertyBSTR returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
6363
6364         /* Make sure it handles a invalid Uri_PROPERTY's correctly. */
6365         hr = IUri_GetPropertyBSTR(uri, Uri_PROPERTY_PORT, &received, 0);
6366         ok(hr == S_OK, "Error: GetPropertyBSTR returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
6367         ok(received != NULL, "Error: Expected the string not to be NULL.\n");
6368         ok(!SysStringLen(received), "Error: Expected the string to be of len=0 but it was %d instead.\n", SysStringLen(received));
6369         SysFreeString(received);
6370
6371         /* Make sure it handles the ZONE property correctly. */
6372         received = NULL;
6373         hr = IUri_GetPropertyBSTR(uri, Uri_PROPERTY_ZONE, &received, 0);
6374         ok(hr == S_FALSE, "Error: GetPropertyBSTR returned 0x%08x, expected 0x%08x.\n", hr, S_FALSE);
6375         ok(received != NULL, "Error: Expected the string not to be NULL.\n");
6376         ok(!SysStringLen(received), "Error: Expected the string to be of len=0 but it was %d instead.\n", SysStringLen(received));
6377         SysFreeString(received);
6378     }
6379     if(uri) IUri_Release(uri);
6380
6381     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
6382         uri_properties test = uri_tests[i];
6383         LPWSTR uriW;
6384         uri = NULL;
6385
6386         uriW = a2w(test.uri);
6387         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
6388         if(test.create_todo) {
6389             todo_wine {
6390                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x. Failed on uri_tests[%d].\n",
6391                         hr, test.create_expected, i);
6392             }
6393         } else {
6394             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x. Failed on uri_tests[%d].\n",
6395                     hr, test.create_expected, i);
6396         }
6397
6398         if(SUCCEEDED(hr)) {
6399             DWORD j;
6400
6401             /* Checks all the string properties of the uri. */
6402             for(j = Uri_PROPERTY_STRING_START; j <= Uri_PROPERTY_STRING_LAST; ++j) {
6403                 BSTR received = NULL;
6404                 uri_str_property prop = test.str_props[j];
6405
6406                 hr = IUri_GetPropertyBSTR(uri, j, &received, 0);
6407                 if(prop.todo) {
6408                     todo_wine {
6409                         ok(hr == prop.expected, "GetPropertyBSTR returned 0x%08x, expected 0x%08x. On uri_tests[%d].str_props[%d].\n",
6410                                 hr, prop.expected, i, j);
6411                     }
6412                     todo_wine {
6413                         ok(!strcmp_aw(prop.value, received) || broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
6414                                 "Expected %s but got %s on uri_tests[%d].str_props[%d].\n",
6415                                 prop.value, wine_dbgstr_w(received), i, j);
6416                     }
6417                 } else {
6418                     ok(hr == prop.expected, "GetPropertyBSTR returned 0x%08x, expected 0x%08x. On uri_tests[%d].str_props[%d].\n",
6419                             hr, prop.expected, i, j);
6420                     ok(!strcmp_aw(prop.value, received) || broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
6421                             "Expected %s but got %s on uri_tests[%d].str_props[%d].\n",
6422                             prop.value, wine_dbgstr_w(received), i, j);
6423                 }
6424
6425                 SysFreeString(received);
6426             }
6427         }
6428
6429         if(uri) IUri_Release(uri);
6430
6431         heap_free(uriW);
6432     }
6433 }
6434
6435 static void test_IUri_GetPropertyDWORD(void) {
6436     IUri *uri = NULL;
6437     HRESULT hr;
6438     DWORD i;
6439
6440     hr = pCreateUri(http_urlW, 0, 0, &uri);
6441     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
6442     if(SUCCEEDED(hr)) {
6443         DWORD received = 0xdeadbeef;
6444
6445         hr = IUri_GetPropertyDWORD(uri, Uri_PROPERTY_DWORD_START, NULL, 0);
6446         ok(hr == E_INVALIDARG, "Error: GetPropertyDWORD returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
6447
6448         hr = IUri_GetPropertyDWORD(uri, Uri_PROPERTY_ABSOLUTE_URI, &received, 0);
6449         ok(hr == E_INVALIDARG, "Error: GetPropertyDWORD returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
6450         ok(received == 0, "Error: Expected received=%d but instead received=%d.\n", 0, received);
6451     }
6452     if(uri) IUri_Release(uri);
6453
6454     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
6455         uri_properties test = uri_tests[i];
6456         LPWSTR uriW;
6457         uri = NULL;
6458
6459         uriW = a2w(test.uri);
6460         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
6461         if(test.create_todo) {
6462             todo_wine {
6463                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x. Failed on uri_tests[%d].\n",
6464                         hr, test.create_expected, i);
6465             }
6466         } else {
6467             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x. Failed on uri_tests[%d].\n",
6468                     hr, test.create_expected, i);
6469         }
6470
6471         if(SUCCEEDED(hr)) {
6472             DWORD j;
6473
6474             /* Checks all the DWORD properties of the uri. */
6475             for(j = 0; j < sizeof(test.dword_props)/sizeof(test.dword_props[0]); ++j) {
6476                 DWORD received;
6477                 uri_dword_property prop = test.dword_props[j];
6478
6479                 hr = IUri_GetPropertyDWORD(uri, j+Uri_PROPERTY_DWORD_START, &received, 0);
6480                 if(prop.todo) {
6481                     todo_wine {
6482                         ok(hr == prop.expected, "GetPropertyDWORD returned 0x%08x, expected 0x%08x. On uri_tests[%d].dword_props[%d].\n",
6483                                 hr, prop.expected, i, j);
6484                     }
6485                     todo_wine {
6486                         ok(prop.value == received, "Expected %d but got %d on uri_tests[%d].dword_props[%d].\n",
6487                                 prop.value, received, i, j);
6488                     }
6489                 } else {
6490                     ok(hr == prop.expected, "GetPropertyDWORD returned 0x%08x, expected 0x%08x. On uri_tests[%d].dword_props[%d].\n",
6491                             hr, prop.expected, i, j);
6492                     ok(prop.value == received, "Expected %d but got %d on uri_tests[%d].dword_props[%d].\n",
6493                             prop.value, received, i, j);
6494                 }
6495             }
6496         }
6497
6498         if(uri) IUri_Release(uri);
6499
6500         heap_free(uriW);
6501     }
6502 }
6503
6504 /* Tests all the 'Get*' property functions which deal with strings. */
6505 static void test_IUri_GetStrProperties(void) {
6506     IUri *uri = NULL;
6507     HRESULT hr;
6508     DWORD i;
6509
6510     /* Make sure all the 'Get*' string property functions handle invalid args correctly. */
6511     hr = pCreateUri(http_urlW, 0, 0, &uri);
6512     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
6513     if(SUCCEEDED(hr)) {
6514         hr = IUri_GetAbsoluteUri(uri, NULL);
6515         ok(hr == E_POINTER, "Error: GetAbsoluteUri returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
6516
6517         hr = IUri_GetAuthority(uri, NULL);
6518         ok(hr == E_POINTER, "Error: GetAuthority returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
6519
6520         hr = IUri_GetDisplayUri(uri, NULL);
6521         ok(hr == E_POINTER, "Error: GetDisplayUri returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
6522
6523         hr = IUri_GetDomain(uri, NULL);
6524         ok(hr == E_POINTER, "Error: GetDomain returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
6525
6526         hr = IUri_GetExtension(uri, NULL);
6527         ok(hr == E_POINTER, "Error: GetExtension returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
6528
6529         hr = IUri_GetFragment(uri, NULL);
6530         ok(hr == E_POINTER, "Error: GetFragment returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
6531
6532         hr = IUri_GetHost(uri, NULL);
6533         ok(hr == E_POINTER, "Error: GetHost returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
6534
6535         hr = IUri_GetPassword(uri, NULL);
6536         ok(hr == E_POINTER, "Error: GetPassword returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
6537
6538         hr = IUri_GetPath(uri, NULL);
6539         ok(hr == E_POINTER, "Error: GetPath returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
6540
6541         hr = IUri_GetPathAndQuery(uri, NULL);
6542         ok(hr == E_POINTER, "Error: GetPathAndQuery returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
6543
6544         hr = IUri_GetQuery(uri, NULL);
6545         ok(hr == E_POINTER, "Error: GetQuery returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
6546
6547         hr = IUri_GetRawUri(uri, NULL);
6548         ok(hr == E_POINTER, "Error: GetRawUri returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
6549
6550         hr = IUri_GetSchemeName(uri, NULL);
6551         ok(hr == E_POINTER, "Error: GetSchemeName returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
6552
6553         hr = IUri_GetUserInfo(uri, NULL);
6554         ok(hr == E_POINTER, "Error: GetUserInfo returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
6555
6556         hr = IUri_GetUserName(uri, NULL);
6557         ok(hr == E_POINTER, "Error: GetUserName returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
6558     }
6559     if(uri) IUri_Release(uri);
6560
6561     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
6562         uri_properties test = uri_tests[i];
6563         LPWSTR uriW;
6564         uri = NULL;
6565
6566         uriW = a2w(test.uri);
6567         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
6568         if(test.create_todo) {
6569             todo_wine {
6570                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6571                         hr, test.create_expected, i);
6572             }
6573         } else {
6574             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6575                     hr, test.create_expected, i);
6576         }
6577
6578         if(SUCCEEDED(hr)) {
6579             uri_str_property prop;
6580             BSTR received = NULL;
6581
6582             /* GetAbsoluteUri() tests. */
6583             prop = test.str_props[Uri_PROPERTY_ABSOLUTE_URI];
6584             hr = IUri_GetAbsoluteUri(uri, &received);
6585             if(prop.todo) {
6586                 todo_wine {
6587                     ok(hr == prop.expected, "Error: GetAbsoluteUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6588                             hr, prop.expected, i);
6589                 }
6590                 todo_wine {
6591                     ok(!strcmp_aw(prop.value, received) || broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
6592                             "Error: Expected %s but got %s on uri_tests[%d].\n",
6593                             prop.value, wine_dbgstr_w(received), i);
6594                 }
6595             } else {
6596                 ok(hr == prop.expected, "Error: GetAbsoluteUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6597                         hr, prop.expected, i);
6598                 ok(!strcmp_aw(prop.value, received) || broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
6599                         "Error: Expected %s but got %s on uri_tests[%d].\n",
6600                         prop.value, wine_dbgstr_w(received), i);
6601             }
6602             SysFreeString(received);
6603             received = NULL;
6604
6605             /* GetAuthority() tests. */
6606             prop = test.str_props[Uri_PROPERTY_AUTHORITY];
6607             hr = IUri_GetAuthority(uri, &received);
6608             if(prop.todo) {
6609                 todo_wine {
6610                     ok(hr == prop.expected, "Error: GetAuthority returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6611                             hr, prop.expected, i);
6612                 }
6613                 todo_wine {
6614                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6615                             prop.value, wine_dbgstr_w(received), i);
6616                 }
6617             } else {
6618                 ok(hr == prop.expected, "Error: GetAuthority returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6619                         hr, prop.expected, i);
6620                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6621                         prop.value, wine_dbgstr_w(received), i);
6622             }
6623             SysFreeString(received);
6624             received = NULL;
6625
6626             /* GetDisplayUri() tests. */
6627             prop = test.str_props[Uri_PROPERTY_DISPLAY_URI];
6628             hr = IUri_GetDisplayUri(uri, &received);
6629             if(prop.todo) {
6630                 todo_wine {
6631                     ok(hr == prop.expected, "Error: GetDisplayUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6632                             hr, prop.expected, i);
6633                 }
6634                 todo_wine {
6635                     ok(!strcmp_aw(prop.value, received) || broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
6636                             "Error: Expected %s but got %s on uri_test[%d].\n",
6637                             prop.value, wine_dbgstr_w(received), i);
6638                 }
6639             } else {
6640                 ok(hr == prop.expected, "Error: GetDisplayUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6641                         hr, prop.expected, i);
6642                 ok(!strcmp_aw(prop.value, received) || broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
6643                         "Error: Expected %s but got %s on uri_tests[%d].\n",
6644                         prop.value, wine_dbgstr_w(received), i);
6645             }
6646             SysFreeString(received);
6647             received = NULL;
6648
6649             /* GetDomain() tests. */
6650             prop = test.str_props[Uri_PROPERTY_DOMAIN];
6651             hr = IUri_GetDomain(uri, &received);
6652             if(prop.todo) {
6653                 todo_wine {
6654                     ok(hr == prop.expected, "Error: GetDomain returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6655                             hr, prop.expected, i);
6656                 }
6657                 todo_wine {
6658                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6659                             prop.value, wine_dbgstr_w(received), i);
6660                 }
6661             } else {
6662                 ok(hr == prop.expected, "Error: GetDomain returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6663                         hr, prop.expected, i);
6664                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6665                         prop.value, wine_dbgstr_w(received), i);
6666             }
6667             SysFreeString(received);
6668             received = NULL;
6669
6670             /* GetExtension() tests. */
6671             prop = test.str_props[Uri_PROPERTY_EXTENSION];
6672             hr = IUri_GetExtension(uri, &received);
6673             if(prop.todo) {
6674                 todo_wine {
6675                     ok(hr == prop.expected, "Error: GetExtension returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6676                             hr, prop.expected, i);
6677                 }
6678                 todo_wine {
6679                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6680                             prop.value, wine_dbgstr_w(received), i);
6681                 }
6682             } else {
6683                 ok(hr == prop.expected, "Error: GetExtension returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6684                         hr, prop.expected, i);
6685                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6686                         prop.value, wine_dbgstr_w(received), i);
6687             }
6688             SysFreeString(received);
6689             received = NULL;
6690
6691             /* GetFragment() tests. */
6692             prop = test.str_props[Uri_PROPERTY_FRAGMENT];
6693             hr = IUri_GetFragment(uri, &received);
6694             if(prop.todo) {
6695                 todo_wine {
6696                     ok(hr == prop.expected, "Error: GetFragment returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6697                             hr, prop.expected, i);
6698                 }
6699                 todo_wine {
6700                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6701                             prop.value, wine_dbgstr_w(received), i);
6702                 }
6703             } else {
6704                 ok(hr == prop.expected, "Error: GetFragment returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6705                         hr, prop.expected, i);
6706                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6707                         prop.value, wine_dbgstr_w(received), i);
6708             }
6709             SysFreeString(received);
6710             received = NULL;
6711
6712             /* GetHost() tests. */
6713             prop = test.str_props[Uri_PROPERTY_HOST];
6714             hr = IUri_GetHost(uri, &received);
6715             if(prop.todo) {
6716                 todo_wine {
6717                     ok(hr == prop.expected, "Error: GetHost returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6718                             hr, prop.expected, i);
6719                 }
6720                 todo_wine {
6721                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6722                             prop.value, wine_dbgstr_w(received), i);
6723                 }
6724             } else {
6725                 ok(hr == prop.expected, "Error: GetHost returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6726                         hr, prop.expected, i);
6727                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6728                         prop.value, wine_dbgstr_w(received), i);
6729             }
6730             SysFreeString(received);
6731             received = NULL;
6732
6733             /* GetPassword() tests. */
6734             prop = test.str_props[Uri_PROPERTY_PASSWORD];
6735             hr = IUri_GetPassword(uri, &received);
6736             if(prop.todo) {
6737                 todo_wine {
6738                     ok(hr == prop.expected, "Error: GetPassword returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6739                             hr, prop.expected, i);
6740                 }
6741                 todo_wine {
6742                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6743                             prop.value, wine_dbgstr_w(received), i);
6744                 }
6745             } else {
6746                 ok(hr == prop.expected, "Error: GetPassword returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6747                         hr, prop.expected, i);
6748                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6749                         prop.value, wine_dbgstr_w(received), i);
6750             }
6751             SysFreeString(received);
6752             received = NULL;
6753
6754             /* GetPath() tests. */
6755             prop = test.str_props[Uri_PROPERTY_PATH];
6756             hr = IUri_GetPath(uri, &received);
6757             if(prop.todo) {
6758                 todo_wine {
6759                     ok(hr == prop.expected, "Error: GetPath returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6760                             hr, prop.expected, i);
6761                 }
6762                 todo_wine {
6763                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6764                             prop.value, wine_dbgstr_w(received), i);
6765                 }
6766             } else {
6767                 ok(hr == prop.expected, "Error: GetPath returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6768                         hr, prop.expected, i);
6769                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6770                         prop.value, wine_dbgstr_w(received), i);
6771             }
6772             SysFreeString(received);
6773             received = NULL;
6774
6775             /* GetPathAndQuery() tests. */
6776             prop = test.str_props[Uri_PROPERTY_PATH_AND_QUERY];
6777             hr = IUri_GetPathAndQuery(uri, &received);
6778             if(prop.todo) {
6779                 todo_wine {
6780                     ok(hr == prop.expected, "Error: GetPathAndQuery returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6781                             hr, prop.expected, i);
6782                 }
6783                 todo_wine {
6784                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6785                             prop.value, wine_dbgstr_w(received), i);
6786                 }
6787             } else {
6788                 ok(hr == prop.expected, "Error: GetPathAndQuery returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6789                         hr, prop.expected, i);
6790                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6791                         prop.value, wine_dbgstr_w(received), i);
6792             }
6793             SysFreeString(received);
6794             received = NULL;
6795
6796             /* GetQuery() tests. */
6797             prop = test.str_props[Uri_PROPERTY_QUERY];
6798             hr = IUri_GetQuery(uri, &received);
6799             if(prop.todo) {
6800                 todo_wine {
6801                     ok(hr == prop.expected, "Error: GetQuery returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6802                             hr, prop.expected, i);
6803                 }
6804                 todo_wine {
6805                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6806                             prop.value, wine_dbgstr_w(received), i);
6807                 }
6808             } else {
6809                 ok(hr == prop.expected, "Error: GetQuery returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6810                         hr, prop.expected, i);
6811                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6812                         prop.value, wine_dbgstr_w(received), i);
6813             }
6814             SysFreeString(received);
6815             received = NULL;
6816
6817             /* GetRawUri() tests. */
6818             prop = test.str_props[Uri_PROPERTY_RAW_URI];
6819             hr = IUri_GetRawUri(uri, &received);
6820             if(prop.todo) {
6821                 todo_wine {
6822                     ok(hr == prop.expected, "Error: GetRawUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6823                             hr, prop.expected, i);
6824                 }
6825                 todo_wine {
6826                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6827                             prop.value, wine_dbgstr_w(received), i);
6828                 }
6829             } else {
6830                 ok(hr == prop.expected, "Error: GetRawUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6831                         hr, prop.expected, i);
6832                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6833                         prop.value, wine_dbgstr_w(received), i);
6834             }
6835             SysFreeString(received);
6836             received = NULL;
6837
6838             /* GetSchemeName() tests. */
6839             prop = test.str_props[Uri_PROPERTY_SCHEME_NAME];
6840             hr = IUri_GetSchemeName(uri, &received);
6841             if(prop.todo) {
6842                 todo_wine {
6843                     ok(hr == prop.expected, "Error: GetSchemeName returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6844                             hr, prop.expected, i);
6845                 }
6846                 todo_wine {
6847                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6848                             prop.value, wine_dbgstr_w(received), i);
6849                 }
6850             } else {
6851                 ok(hr == prop.expected, "Error: GetSchemeName returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6852                         hr, prop.expected, i);
6853                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6854                         prop.value, wine_dbgstr_w(received), i);
6855             }
6856             SysFreeString(received);
6857             received = NULL;
6858
6859             /* GetUserInfo() tests. */
6860             prop = test.str_props[Uri_PROPERTY_USER_INFO];
6861             hr = IUri_GetUserInfo(uri, &received);
6862             if(prop.todo) {
6863                 todo_wine {
6864                     ok(hr == prop.expected, "Error: GetUserInfo returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6865                             hr, prop.expected, i);
6866                 }
6867                 todo_wine {
6868                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6869                             prop.value, wine_dbgstr_w(received), i);
6870                 }
6871             } else {
6872                 ok(hr == prop.expected, "Error: GetUserInfo returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6873                         hr, prop.expected, i);
6874                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6875                         prop.value, wine_dbgstr_w(received), i);
6876             }
6877             SysFreeString(received);
6878             received = NULL;
6879
6880             /* GetUserName() tests. */
6881             prop = test.str_props[Uri_PROPERTY_USER_NAME];
6882             hr = IUri_GetUserName(uri, &received);
6883             if(prop.todo) {
6884                 todo_wine {
6885                     ok(hr == prop.expected, "Error: GetUserName returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6886                             hr, prop.expected, i);
6887                 }
6888                 todo_wine {
6889                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6890                             prop.value, wine_dbgstr_w(received), i);
6891                 }
6892             } else {
6893                 ok(hr == prop.expected, "Error: GetUserName returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6894                         hr, prop.expected, i);
6895                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6896                         prop.value, wine_dbgstr_w(received), i);
6897             }
6898             SysFreeString(received);
6899         }
6900
6901         if(uri) IUri_Release(uri);
6902
6903         heap_free(uriW);
6904     }
6905 }
6906
6907 static void test_IUri_GetDwordProperties(void) {
6908     IUri *uri = NULL;
6909     HRESULT hr;
6910     DWORD i;
6911
6912     /* Make sure all the 'Get*' dword property functions handle invalid args correctly. */
6913     hr = pCreateUri(http_urlW, 0, 0, &uri);
6914     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
6915     if(SUCCEEDED(hr)) {
6916         hr = IUri_GetHostType(uri, NULL);
6917         ok(hr == E_INVALIDARG, "Error: GetHostType returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
6918
6919         hr = IUri_GetPort(uri, NULL);
6920         ok(hr == E_INVALIDARG, "Error: GetPort returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
6921
6922         hr = IUri_GetScheme(uri, NULL);
6923         ok(hr == E_INVALIDARG, "Error: GetScheme returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
6924
6925         hr = IUri_GetZone(uri, NULL);
6926         ok(hr == E_INVALIDARG, "Error: GetZone returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
6927     }
6928     if(uri) IUri_Release(uri);
6929
6930     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
6931         uri_properties test = uri_tests[i];
6932         LPWSTR uriW;
6933         uri = NULL;
6934
6935         uriW = a2w(test.uri);
6936         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
6937         if(test.create_todo) {
6938             todo_wine {
6939                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6940                         hr, test.create_expected, i);
6941             }
6942         } else {
6943             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6944                     hr, test.create_expected, i);
6945         }
6946
6947         if(SUCCEEDED(hr)) {
6948             uri_dword_property prop;
6949             DWORD received;
6950
6951             /* Assign an insane value so tests don't accidentally pass when
6952              * they shouldn't!
6953              */
6954             received = -9999999;
6955
6956             /* GetHostType() tests. */
6957             prop = test.dword_props[Uri_PROPERTY_HOST_TYPE-Uri_PROPERTY_DWORD_START];
6958             hr = IUri_GetHostType(uri, &received);
6959             if(prop.todo) {
6960                 todo_wine {
6961                     ok(hr == prop.expected, "Error: GetHostType returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6962                             hr, prop.expected, i);
6963                 }
6964                 todo_wine {
6965                     ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
6966                 }
6967             } else {
6968                 ok(hr == prop.expected, "Error: GetHostType returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6969                         hr, prop.expected, i);
6970                 ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
6971             }
6972             received = -9999999;
6973
6974             /* GetPort() tests. */
6975             prop = test.dword_props[Uri_PROPERTY_PORT-Uri_PROPERTY_DWORD_START];
6976             hr = IUri_GetPort(uri, &received);
6977             if(prop.todo) {
6978                 todo_wine {
6979                     ok(hr == prop.expected, "Error: GetPort returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6980                             hr, prop.expected, i);
6981                 }
6982                 todo_wine {
6983                     ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
6984                 }
6985             } else {
6986                 ok(hr == prop.expected, "Error: GetPort returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6987                         hr, prop.expected, i);
6988                 ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
6989             }
6990             received = -9999999;
6991
6992             /* GetScheme() tests. */
6993             prop = test.dword_props[Uri_PROPERTY_SCHEME-Uri_PROPERTY_DWORD_START];
6994             hr = IUri_GetScheme(uri, &received);
6995             if(prop.todo) {
6996                 todo_wine {
6997                     ok(hr == prop.expected, "Error: GetScheme returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6998                             hr, prop.expected, i);
6999                 }
7000                 todo_wine {
7001                     ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
7002                 }
7003             } else {
7004                 ok(hr == prop.expected, "Error: GetScheme returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7005                         hr, prop.expected, i);
7006                 ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
7007             }
7008             received = -9999999;
7009
7010             /* GetZone() tests. */
7011             prop = test.dword_props[Uri_PROPERTY_ZONE-Uri_PROPERTY_DWORD_START];
7012             hr = IUri_GetZone(uri, &received);
7013             if(prop.todo) {
7014                 todo_wine {
7015                     ok(hr == prop.expected, "Error: GetZone returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7016                             hr, prop.expected, i);
7017                 }
7018                 todo_wine {
7019                     ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
7020                 }
7021             } else {
7022                 ok(hr == prop.expected, "Error: GetZone returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7023                         hr, prop.expected, i);
7024                 ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
7025             }
7026         }
7027
7028         if(uri) IUri_Release(uri);
7029
7030         heap_free(uriW);
7031     }
7032 }
7033
7034 static void test_IUri_GetPropertyLength(void) {
7035     IUri *uri = NULL;
7036     HRESULT hr;
7037     DWORD i;
7038
7039     /* Make sure it handles invalid args correctly. */
7040     hr = pCreateUri(http_urlW, 0, 0, &uri);
7041     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7042     if(SUCCEEDED(hr)) {
7043         DWORD received = 0xdeadbeef;
7044
7045         hr = IUri_GetPropertyLength(uri, Uri_PROPERTY_STRING_START, NULL, 0);
7046         ok(hr == E_INVALIDARG, "Error: GetPropertyLength returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
7047
7048         hr = IUri_GetPropertyLength(uri, Uri_PROPERTY_DWORD_START, &received, 0);
7049         ok(hr == E_INVALIDARG, "Error: GetPropertyLength return 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
7050         ok(received == 0xdeadbeef, "Error: Expected 0xdeadbeef but got 0x%08x.\n", received);
7051     }
7052     if(uri) IUri_Release(uri);
7053
7054     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
7055         uri_properties test = uri_tests[i];
7056         LPWSTR uriW;
7057         uri = NULL;
7058
7059         uriW = a2w(test.uri);
7060         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
7061         if(test.create_todo) {
7062             todo_wine {
7063                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7064                         hr, test.create_expected, i);
7065             }
7066         } else {
7067             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_test[%d].\n",
7068                     hr, test.create_expected, i);
7069         }
7070
7071         if(SUCCEEDED(hr)) {
7072             DWORD j;
7073
7074             for(j = Uri_PROPERTY_STRING_START; j <= Uri_PROPERTY_STRING_LAST; ++j) {
7075                 DWORD expectedLen, brokenLen, receivedLen;
7076                 uri_str_property prop = test.str_props[j];
7077
7078                 expectedLen = lstrlen(prop.value);
7079                 brokenLen = lstrlen(prop.broken_value);
7080
7081                 /* This won't be necessary once GetPropertyLength is implemented. */
7082                 receivedLen = -1;
7083
7084                 hr = IUri_GetPropertyLength(uri, j, &receivedLen, 0);
7085                 if(prop.todo) {
7086                     todo_wine {
7087                         ok(hr == prop.expected, "Error: GetPropertyLength returned 0x%08x, expected 0x%08x on uri_tests[%d].str_props[%d].\n",
7088                                 hr, prop.expected, i, j);
7089                     }
7090                     todo_wine {
7091                         ok(receivedLen == expectedLen || broken(receivedLen == brokenLen),
7092                                 "Error: Expected a length of %d but got %d on uri_tests[%d].str_props[%d].\n",
7093                                 expectedLen, receivedLen, i, j);
7094                     }
7095                 } else {
7096                     ok(hr == prop.expected, "Error: GetPropertyLength returned 0x%08x, expected 0x%08x on uri_tests[%d].str_props[%d].\n",
7097                             hr, prop.expected, i, j);
7098                     ok(receivedLen == expectedLen || broken(receivedLen == brokenLen),
7099                             "Error: Expected a length of %d but got %d on uri_tests[%d].str_props[%d].\n",
7100                             expectedLen, receivedLen, i, j);
7101                 }
7102             }
7103         }
7104
7105         if(uri) IUri_Release(uri);
7106
7107         heap_free(uriW);
7108     }
7109 }
7110
7111 static DWORD compute_expected_props(uri_properties *test)
7112 {
7113     DWORD ret = 0, i;
7114
7115     for(i=Uri_PROPERTY_STRING_START; i <= Uri_PROPERTY_STRING_LAST; i++) {
7116         if(test->str_props[i-Uri_PROPERTY_STRING_START].expected == S_OK)
7117             ret |= 1<<i;
7118     }
7119
7120     for(i=Uri_PROPERTY_DWORD_START; i <= Uri_PROPERTY_DWORD_LAST; i++) {
7121         if(test->dword_props[i-Uri_PROPERTY_DWORD_START].expected == S_OK)
7122             ret |= 1<<i;
7123     }
7124
7125     return ret;
7126 }
7127
7128 static void test_IUri_GetProperties(void) {
7129     IUri *uri = NULL;
7130     HRESULT hr;
7131     DWORD i;
7132
7133     hr = pCreateUri(http_urlW, 0, 0, &uri);
7134     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7135     if(SUCCEEDED(hr)) {
7136         hr = IUri_GetProperties(uri, NULL);
7137         ok(hr == E_INVALIDARG, "Error: GetProperties returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
7138     }
7139     if(uri) IUri_Release(uri);
7140
7141     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
7142         uri_properties test = uri_tests[i];
7143         LPWSTR uriW;
7144         uri = NULL;
7145
7146         uriW = a2w(test.uri);
7147         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
7148         if(test.create_todo) {
7149             todo_wine {
7150                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, test.create_expected);
7151             }
7152         } else {
7153             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, test.create_expected);
7154         }
7155
7156         if(SUCCEEDED(hr)) {
7157             DWORD received = 0, expected_props;
7158             DWORD j;
7159
7160             hr = IUri_GetProperties(uri, &received);
7161             ok(hr == S_OK, "Error: GetProperties returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7162
7163             expected_props = compute_expected_props(&test);
7164
7165             for(j = 0; j <= Uri_PROPERTY_DWORD_LAST; ++j) {
7166                 /* (1 << j) converts a Uri_PROPERTY to its corresponding Uri_HAS_* flag mask. */
7167                 if(expected_props & (1 << j))
7168                     ok(received & (1 << j), "Error: Expected flag for property %d on uri_tests[%d].\n", j, i);
7169                 else
7170                     ok(!(received & (1 << j)), "Error: Received flag for property %d when not expected on uri_tests[%d].\n", j, i);
7171             }
7172         }
7173
7174         if(uri) IUri_Release(uri);
7175
7176         heap_free(uriW);
7177     }
7178 }
7179
7180 static void test_IUri_HasProperty(void) {
7181     IUri *uri = NULL;
7182     HRESULT hr;
7183     DWORD i;
7184
7185     hr = pCreateUri(http_urlW, 0, 0, &uri);
7186     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7187     if(SUCCEEDED(hr)) {
7188         hr = IUri_HasProperty(uri, Uri_PROPERTY_RAW_URI, NULL);
7189         ok(hr == E_INVALIDARG, "Error: HasProperty returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
7190     }
7191     if(uri) IUri_Release(uri);
7192
7193     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
7194         uri_properties test = uri_tests[i];
7195         LPWSTR uriW;
7196         uri = NULL;
7197
7198         uriW = a2w(test.uri);
7199
7200         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
7201         if(test.create_todo) {
7202             todo_wine {
7203                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, test.create_expected);
7204             }
7205         } else {
7206             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, test.create_expected);
7207         }
7208
7209         if(SUCCEEDED(hr)) {
7210             DWORD expected_props, j;
7211
7212             expected_props = compute_expected_props(&test);
7213
7214             for(j = 0; j <= Uri_PROPERTY_DWORD_LAST; ++j) {
7215                 /* Assign -1, then explicitly test for TRUE or FALSE later. */
7216                 BOOL received = -1;
7217
7218                 hr = IUri_HasProperty(uri, j, &received);
7219                 ok(hr == S_OK, "Error: HasProperty returned 0x%08x, expected 0x%08x for property %d on uri_tests[%d].\n",
7220                         hr, S_OK, j, i);
7221
7222                 if(expected_props & (1 << j)) {
7223                     ok(received == TRUE, "Error: Expected to have property %d on uri_tests[%d].\n", j, i);
7224                 } else {
7225                     ok(received == FALSE, "Error: Wasn't expecting to have property %d on uri_tests[%d].\n", j, i);
7226                 }
7227             }
7228         }
7229
7230         if(uri) IUri_Release(uri);
7231
7232         heap_free(uriW);
7233     }
7234 }
7235
7236 static void test_IUri_IsEqual(void) {
7237     IUri *uriA, *uriB;
7238     HRESULT hrA, hrB;
7239     DWORD i;
7240
7241     uriA = uriB = NULL;
7242
7243     /* Make sure IsEqual handles invalid args correctly. */
7244     hrA = pCreateUri(http_urlW, 0, 0, &uriA);
7245     hrB = pCreateUri(http_urlW, 0, 0, &uriB);
7246     ok(hrA == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hrA, S_OK);
7247     ok(hrB == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hrB, S_OK);
7248     if(SUCCEEDED(hrA) && SUCCEEDED(hrB)) {
7249         BOOL equal = -1;
7250         hrA = IUri_IsEqual(uriA, NULL, &equal);
7251         ok(hrA == S_OK, "Error: IsEqual returned 0x%08x, expected 0x%08x.\n", hrA, S_OK);
7252         ok(equal == FALSE, "Error: Expected equal to be FALSE, but was %d instead.\n", equal);
7253
7254         hrA = IUri_IsEqual(uriA, uriB, NULL);
7255         ok(hrA == E_POINTER, "Error: IsEqual returned 0x%08x, expected 0x%08x.\n", hrA, E_POINTER);
7256     }
7257     if(uriA) IUri_Release(uriA);
7258     if(uriB) IUri_Release(uriB);
7259
7260     for(i = 0; i < sizeof(equality_tests)/sizeof(equality_tests[0]); ++i) {
7261         uri_equality test = equality_tests[i];
7262         LPWSTR uriA_W, uriB_W;
7263
7264         uriA = uriB = NULL;
7265
7266         uriA_W = a2w(test.a);
7267         uriB_W = a2w(test.b);
7268
7269         hrA = pCreateUri(uriA_W, test.create_flags_a, 0, &uriA);
7270         if(test.create_todo_a) {
7271             todo_wine {
7272                 ok(hrA == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x on equality_tests[%d].a\n",
7273                         hrA, S_OK, i);
7274             }
7275         } else {
7276             ok(hrA == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x on equality_tests[%d].a\n",
7277                     hrA, S_OK, i);
7278         }
7279
7280         hrB = pCreateUri(uriB_W, test.create_flags_b, 0, &uriB);
7281         if(test.create_todo_b) {
7282             todo_wine {
7283                 ok(hrB == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x on equality_tests[%d].b\n",
7284                         hrB, S_OK, i);
7285             }
7286         } else {
7287             ok(hrB == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x on equality_tests[%d].b\n",
7288                     hrB, S_OK, i);
7289         }
7290
7291         if(SUCCEEDED(hrA) && SUCCEEDED(hrB)) {
7292             BOOL equal = -1;
7293
7294             hrA = IUri_IsEqual(uriA, uriB, &equal);
7295             if(test.todo) {
7296                 todo_wine {
7297                     ok(hrA == S_OK, "Error: IsEqual returned 0x%08x, expected 0x%08x on equality_tests[%d].\n",
7298                             hrA, S_OK, i);
7299                 }
7300                 todo_wine {
7301                     ok(equal == test.equal, "Error: Expected the comparison to be %d on equality_tests[%d].\n", test.equal, i);
7302                 }
7303             } else {
7304                 ok(hrA == S_OK, "Error: IsEqual returned 0x%08x, expected 0x%08x on equality_tests[%d].\n", hrA, S_OK, i);
7305                 ok(equal == test.equal, "Error: Expected the comparison to be %d on equality_tests[%d].\n", test.equal, i);
7306             }
7307         }
7308         if(uriA) IUri_Release(uriA);
7309         if(uriB) IUri_Release(uriB);
7310
7311         heap_free(uriA_W);
7312         heap_free(uriB_W);
7313     }
7314 }
7315
7316 static void test_CreateUriWithFragment_InvalidArgs(void) {
7317     HRESULT hr;
7318     IUri *uri = (void*) 0xdeadbeef;
7319     const WCHAR fragmentW[] = {'#','f','r','a','g','m','e','n','t',0};
7320
7321     hr = pCreateUriWithFragment(NULL, fragmentW, 0, 0, &uri);
7322     ok(hr == E_INVALIDARG, "Error: CreateUriWithFragment returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
7323     ok(uri == NULL, "Error: Expected uri to be NULL, but was %p instead.\n", uri);
7324
7325     hr = pCreateUriWithFragment(http_urlW, fragmentW, 0, 0, NULL);
7326     ok(hr == E_INVALIDARG, "Error: CreateUriWithFragment returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
7327
7328     /* Original URI can't already contain a fragment component. */
7329     uri = (void*) 0xdeadbeef;
7330     hr = pCreateUriWithFragment(http_url_fragW, fragmentW, 0, 0, &uri);
7331     ok(hr == E_INVALIDARG, "Error: CreateUriWithFragment returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
7332     ok(uri == NULL, "Error: Expected uri to be NULL, but was %p instead.\n", uri);
7333 }
7334
7335 /* CreateUriWithFragment has the same invalid flag combinations as CreateUri. */
7336 static void test_CreateUriWithFragment_InvalidFlags(void) {
7337     DWORD i;
7338
7339     for(i = 0; i < sizeof(invalid_flag_tests)/sizeof(invalid_flag_tests[0]); ++i) {
7340         HRESULT hr;
7341         IUri *uri = (void*) 0xdeadbeef;
7342
7343         hr = pCreateUriWithFragment(http_urlW, NULL, invalid_flag_tests[i].flags, 0, &uri);
7344         ok(hr == invalid_flag_tests[i].expected, "Error: CreateUriWithFragment returned 0x%08x, expected 0x%08x. flags=0x%08x.\n",
7345             hr, invalid_flag_tests[i].expected, invalid_flag_tests[i].flags);
7346         ok(uri == NULL, "Error: Expected uri to be NULL, but was %p instead.\n", uri);
7347     }
7348 }
7349
7350 static void test_CreateUriWithFragment(void) {
7351     DWORD i;
7352
7353     for(i = 0; i < sizeof(uri_fragment_tests)/sizeof(uri_fragment_tests[0]); ++i) {
7354         HRESULT hr;
7355         IUri *uri = NULL;
7356         LPWSTR uriW, fragW;
7357         uri_with_fragment test = uri_fragment_tests[i];
7358
7359         uriW = a2w(test.uri);
7360         fragW = a2w(test.fragment);
7361
7362         hr = pCreateUriWithFragment(uriW, fragW, test.create_flags, 0, &uri);
7363         if(test.expected_todo) {
7364             todo_wine {
7365                 ok(hr == test.create_expected,
7366                     "Error: CreateUriWithFragment returned 0x%08x, expected 0x%08x on uri_fragment_tests[%d].\n",
7367                     hr, test.create_expected, i);
7368             }
7369         } else
7370             ok(hr == test.create_expected,
7371                 "Error: CreateUriWithFragment returned 0x%08x, expected 0x%08x on uri_fragment_tests[%d].\n",
7372                 hr, test.create_expected, i);
7373
7374         if(SUCCEEDED(hr)) {
7375             BSTR received = NULL;
7376
7377             hr = IUri_GetAbsoluteUri(uri, &received);
7378             if(test.expected_todo) {
7379                 todo_wine {
7380                     ok(hr == S_OK,
7381                         "Error: GetAbsoluteUri returned 0x%08x, expected 0x%08x on uri_fragment_tests[%d].\n",
7382                         hr, S_OK, i);
7383                 }
7384                 todo_wine {
7385                     ok(!strcmp_aw(test.expected_uri, received),
7386                         "Error: Expected %s but got %s on uri_fragment_tests[%d].\n",
7387                         test.expected_uri, wine_dbgstr_w(received), i);
7388                 }
7389             } else {
7390                 ok(hr == S_OK, "Error: GetAbsoluteUri returned 0x%08x, expected 0x%08x on uri_fragment_tests[%d].\n",
7391                     hr, S_OK, i);
7392                 ok(!strcmp_aw(test.expected_uri, received), "Error: Expected %s but got %s on uri_fragment_tests[%d].\n",
7393                     test.expected_uri, wine_dbgstr_w(received), i);
7394             }
7395
7396             SysFreeString(received);
7397         }
7398
7399         if(uri) IUri_Release(uri);
7400         heap_free(uriW);
7401         heap_free(fragW);
7402     }
7403 }
7404
7405 static void test_CreateIUriBuilder(void) {
7406     HRESULT hr;
7407     IUriBuilder *builder = NULL;
7408     IUri *uri;
7409
7410     hr = pCreateIUriBuilder(NULL, 0, 0, NULL);
7411     ok(hr == E_POINTER, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x\n",
7412         hr, E_POINTER);
7413
7414     /* CreateIUriBuilder increases the ref count of the IUri it receives. */
7415     hr = pCreateUri(http_urlW, 0, 0, &uri);
7416     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7417     if(SUCCEEDED(hr)) {
7418         ULONG cur_count, orig_count;
7419
7420         orig_count = get_refcnt(uri);
7421         hr = pCreateIUriBuilder(uri, 0, 0, &builder);
7422         ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7423         ok(builder != NULL, "Error: Expecting builder not to be NULL\n");
7424
7425         cur_count = get_refcnt(uri);
7426         ok(cur_count == orig_count+1, "Error: Expected the ref count to be %u, but was %u instead.\n", orig_count+1, cur_count);
7427
7428         if(builder) IUriBuilder_Release(builder);
7429         cur_count = get_refcnt(uri);
7430         ok(cur_count == orig_count, "Error: Expected the ref count to be %u, but was %u instead.\n", orig_count, cur_count);
7431     }
7432     if(uri) IUri_Release(uri);
7433 }
7434
7435 static void test_IUriBuilder_CreateUri(IUriBuilder *builder, const uri_builder_test *test,
7436                                        DWORD test_index) {
7437     HRESULT hr;
7438     IUri *uri = NULL;
7439
7440     hr = IUriBuilder_CreateUri(builder, test->uri_flags, 0, 0, &uri);
7441     if(test->uri_todo) {
7442         todo_wine {
7443             ok(hr == test->uri_hres,
7444                 "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7445                 hr, test->uri_hres, test_index);
7446         }
7447     } else {
7448         ok(hr == test->uri_hres,
7449             "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7450             hr, test->uri_hres, test_index);
7451     }
7452
7453     if(SUCCEEDED(hr)) {
7454         DWORD i;
7455
7456         for(i = 0; i < sizeof(test->expected_str_props)/sizeof(test->expected_str_props[0]); ++i) {
7457             uri_builder_str_property prop = test->expected_str_props[i];
7458             BSTR received = NULL;
7459
7460             hr = IUri_GetPropertyBSTR(uri, i, &received, 0);
7461             if(prop.todo) {
7462                 todo_wine {
7463                     ok(hr == prop.result,
7464                         "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_str_props[%d].\n",
7465                         hr, prop.result, test_index, i);
7466                 }
7467             } else {
7468                 ok(hr == prop.result,
7469                     "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_str_props[%d].\n",
7470                     hr, prop.result, test_index, i);
7471             }
7472             if(SUCCEEDED(hr)) {
7473                 if(prop.todo) {
7474                     todo_wine {
7475                         ok(!strcmp_aw(prop.expected, received),
7476                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].expected_str_props[%d].\n",
7477                             prop.expected, wine_dbgstr_w(received), test_index, i);
7478                     }
7479                 } else {
7480                     ok(!strcmp_aw(prop.expected, received),
7481                         "Error: Expected %s but got %s instead on uri_builder_tests[%d].expected_str_props[%d].\n",
7482                         prop.expected, wine_dbgstr_w(received), test_index, i);
7483                 }
7484             }
7485             SysFreeString(received);
7486         }
7487
7488         for(i = 0; i < sizeof(test->expected_dword_props)/sizeof(test->expected_dword_props[0]); ++i) {
7489             uri_builder_dword_property prop = test->expected_dword_props[i];
7490             DWORD received = -2;
7491
7492             hr = IUri_GetPropertyDWORD(uri, i+Uri_PROPERTY_DWORD_START, &received, 0);
7493             if(prop.todo) {
7494                 todo_wine {
7495                     ok(hr == prop.result,
7496                         "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_dword_props[%d].\n",
7497                         hr, prop.result, test_index, i);
7498                 }
7499             } else {
7500                 ok(hr == prop.result,
7501                     "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_dword_props[%d].\n",
7502                     hr, prop.result, test_index, i);
7503             }
7504             if(SUCCEEDED(hr)) {
7505                 if(prop.todo) {
7506                     todo_wine {
7507                         ok(received == prop.expected,
7508                             "Error: Expected %d but got %d instead on uri_builder_tests[%d].expected_dword_props[%d].\n",
7509                             prop.expected, received, test_index, i);
7510                     }
7511                 } else {
7512                     ok(received == prop.expected,
7513                         "Error: Expected %d but got %d instead on uri_builder_tests[%d].expected_dword_props[%d].\n",
7514                         prop.expected, received, test_index, i);
7515                 }
7516             }
7517         }
7518     }
7519     if(uri) IUri_Release(uri);
7520 }
7521
7522 static void test_IUriBuilder_CreateUriSimple(IUriBuilder *builder, const uri_builder_test *test,
7523                                        DWORD test_index) {
7524     HRESULT hr;
7525     IUri *uri = NULL;
7526
7527     hr = IUriBuilder_CreateUriSimple(builder, test->uri_simple_encode_flags, 0, &uri);
7528     if(test->uri_simple_todo) {
7529         todo_wine {
7530             ok(hr == test->uri_simple_hres,
7531                 "Error: IUriBuilder_CreateUriSimple returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7532                 hr, test->uri_simple_hres, test_index);
7533         }
7534     } else {
7535         ok(hr == test->uri_simple_hres,
7536             "Error: IUriBuilder_CreateUriSimple returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7537             hr, test->uri_simple_hres, test_index);
7538     }
7539
7540     if(SUCCEEDED(hr)) {
7541         DWORD i;
7542
7543         for(i = 0; i < sizeof(test->expected_str_props)/sizeof(test->expected_str_props[0]); ++i) {
7544             uri_builder_str_property prop = test->expected_str_props[i];
7545             BSTR received = NULL;
7546
7547             hr = IUri_GetPropertyBSTR(uri, i, &received, 0);
7548             if(prop.todo) {
7549                 todo_wine {
7550                     ok(hr == prop.result,
7551                         "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_str_props[%d].\n",
7552                         hr, prop.result, test_index, i);
7553                 }
7554             } else {
7555                 ok(hr == prop.result,
7556                     "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_str_props[%d].\n",
7557                     hr, prop.result, test_index, i);
7558             }
7559             if(SUCCEEDED(hr)) {
7560                 if(prop.todo) {
7561                     todo_wine {
7562                         ok(!strcmp_aw(prop.expected, received),
7563                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].expected_str_props[%d].\n",
7564                             prop.expected, wine_dbgstr_w(received), test_index, i);
7565                     }
7566                 } else {
7567                     ok(!strcmp_aw(prop.expected, received),
7568                         "Error: Expected %s but got %s instead on uri_builder_tests[%d].expected_str_props[%d].\n",
7569                         prop.expected, wine_dbgstr_w(received), test_index, i);
7570                 }
7571             }
7572             SysFreeString(received);
7573         }
7574
7575         for(i = 0; i < sizeof(test->expected_dword_props)/sizeof(test->expected_dword_props[0]); ++i) {
7576             uri_builder_dword_property prop = test->expected_dword_props[i];
7577             DWORD received = -2;
7578
7579             hr = IUri_GetPropertyDWORD(uri, i+Uri_PROPERTY_DWORD_START, &received, 0);
7580             if(prop.todo) {
7581                 todo_wine {
7582                     ok(hr == prop.result,
7583                         "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_dword_props[%d].\n",
7584                         hr, prop.result, test_index, i);
7585                 }
7586             } else {
7587                 ok(hr == prop.result,
7588                     "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_dword_props[%d].\n",
7589                     hr, prop.result, test_index, i);
7590             }
7591             if(SUCCEEDED(hr)) {
7592                 if(prop.todo) {
7593                     todo_wine {
7594                         ok(received == prop.expected,
7595                             "Error: Expected %d but got %d instead on uri_builder_tests[%d].expected_dword_props[%d].\n",
7596                             prop.expected, received, test_index, i);
7597                     }
7598                 } else {
7599                     ok(received == prop.expected,
7600                         "Error: Expected %d but got %d instead on uri_builder_tests[%d].expected_dword_props[%d].\n",
7601                         prop.expected, received, test_index, i);
7602                 }
7603             }
7604         }
7605     }
7606     if(uri) IUri_Release(uri);
7607 }
7608
7609 static void test_IUriBuilder_CreateUriWithFlags(IUriBuilder *builder, const uri_builder_test *test,
7610                                                 DWORD test_index) {
7611     HRESULT hr;
7612     IUri *uri = NULL;
7613
7614     hr = IUriBuilder_CreateUriWithFlags(builder, test->uri_with_flags, test->uri_with_builder_flags,
7615                                         test->uri_with_encode_flags, 0, &uri);
7616     if(test->uri_with_todo) {
7617         todo_wine {
7618             ok(hr == test->uri_with_hres,
7619                 "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7620                 hr, test->uri_with_hres, test_index);
7621         }
7622     } else {
7623         ok(hr == test->uri_with_hres,
7624             "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7625             hr, test->uri_with_hres, test_index);
7626     }
7627
7628     if(SUCCEEDED(hr)) {
7629         DWORD i;
7630
7631         for(i = 0; i < sizeof(test->expected_str_props)/sizeof(test->expected_str_props[0]); ++i) {
7632             uri_builder_str_property prop = test->expected_str_props[i];
7633             BSTR received = NULL;
7634
7635             hr = IUri_GetPropertyBSTR(uri, i, &received, 0);
7636             if(prop.todo) {
7637                 todo_wine {
7638                     ok(hr == prop.result,
7639                         "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_str_props[%d].\n",
7640                         hr, prop.result, test_index, i);
7641                 }
7642             } else {
7643                 ok(hr == prop.result,
7644                     "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_str_props[%d].\n",
7645                     hr, prop.result, test_index, i);
7646             }
7647             if(SUCCEEDED(hr)) {
7648                 if(prop.todo) {
7649                     todo_wine {
7650                         ok(!strcmp_aw(prop.expected, received),
7651                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].expected_str_props[%d].\n",
7652                             prop.expected, wine_dbgstr_w(received), test_index, i);
7653                     }
7654                 } else {
7655                     ok(!strcmp_aw(prop.expected, received),
7656                         "Error: Expected %s but got %s instead on uri_builder_tests[%d].expected_str_props[%d].\n",
7657                         prop.expected, wine_dbgstr_w(received), test_index, i);
7658                 }
7659             }
7660             SysFreeString(received);
7661         }
7662
7663         for(i = 0; i < sizeof(test->expected_dword_props)/sizeof(test->expected_dword_props[0]); ++i) {
7664             uri_builder_dword_property prop = test->expected_dword_props[i];
7665             DWORD received = -2;
7666
7667             hr = IUri_GetPropertyDWORD(uri, i+Uri_PROPERTY_DWORD_START, &received, 0);
7668             if(prop.todo) {
7669                 todo_wine {
7670                     ok(hr == prop.result,
7671                         "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_dword_props[%d].\n",
7672                         hr, prop.result, test_index, i);
7673                 }
7674             } else {
7675                 ok(hr == prop.result,
7676                     "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_dword_props[%d].\n",
7677                     hr, prop.result, test_index, i);
7678             }
7679             if(SUCCEEDED(hr)) {
7680                 if(prop.todo) {
7681                     todo_wine {
7682                         ok(received == prop.expected,
7683                             "Error: Expected %d but got %d instead on uri_builder_tests[%d].expected_dword_props[%d].\n",
7684                             prop.expected, received, test_index, i);
7685                     }
7686                 } else {
7687                     ok(received == prop.expected,
7688                         "Error: Expected %d but got %d instead on uri_builder_tests[%d].expected_dword_props[%d].\n",
7689                         prop.expected, received, test_index, i);
7690                 }
7691             }
7692         }
7693     }
7694     if(uri) IUri_Release(uri);
7695 }
7696
7697 static void test_IUriBuilder_CreateInvalidArgs(void) {
7698     IUriBuilder *builder;
7699     HRESULT hr;
7700
7701     hr = pCreateIUriBuilder(NULL, 0, 0, &builder);
7702     ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7703     if(SUCCEEDED(hr)) {
7704         IUri *test = NULL, *uri = (void*) 0xdeadbeef;
7705
7706         /* Test what happens if the IUriBuilder doesn't have a IUri set. */
7707         hr = IUriBuilder_CreateUri(builder, 0, 0, 0, NULL);
7708         ok(hr == E_POINTER, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
7709
7710         uri = (void*) 0xdeadbeef;
7711         hr = IUriBuilder_CreateUri(builder, 0, Uri_HAS_USER_NAME, 0, &uri);
7712         ok(hr == E_NOTIMPL, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, E_NOTIMPL);
7713         ok(uri == NULL, "Error: expected uri to be NULL, but was %p instead.\n", uri);
7714
7715         hr = IUriBuilder_CreateUriSimple(builder, 0, 0, NULL);
7716         ok(hr == E_POINTER, "Error: IUriBuilder_CreateUriSimple returned 0x%08x, expected 0x%08x.\n",
7717             hr, E_POINTER);
7718
7719         uri = (void*) 0xdeadbeef;
7720         hr = IUriBuilder_CreateUriSimple(builder, Uri_HAS_USER_NAME, 0, &uri);
7721         ok(hr == E_NOTIMPL, "Error: IUriBuilder_CreateUriSimple returned 0x%08x, expected 0x%08x.\n",
7722             hr, E_NOTIMPL);
7723         ok(!uri, "Error: Expected uri to NULL, but was %p instead.\n", uri);
7724
7725         hr = IUriBuilder_CreateUriWithFlags(builder, 0, 0, 0, 0, NULL);
7726         ok(hr == E_POINTER, "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x.\n",
7727             hr, E_POINTER);
7728
7729         uri = (void*) 0xdeadbeef;
7730         hr = IUriBuilder_CreateUriWithFlags(builder, 0, 0, Uri_HAS_USER_NAME, 0, &uri);
7731         ok(hr == E_NOTIMPL, "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x.\n",
7732             hr, E_NOTIMPL);
7733         ok(!uri, "Error: Expected uri to be NULL, but was %p instead.\n", uri);
7734
7735         hr = pCreateUri(http_urlW, 0, 0, &test);
7736         ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7737         if(SUCCEEDED(hr)) {
7738             hr = IUriBuilder_SetIUri(builder, test);
7739             ok(hr == S_OK, "Error: IUriBuilder_SetIUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7740
7741             /* No longer returns E_NOTIMPL, since a IUri has been set and hasn't been modified. */
7742             uri = NULL;
7743             hr = IUriBuilder_CreateUri(builder, 0, Uri_HAS_USER_NAME, 0, &uri);
7744             ok(hr == S_OK, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7745             ok(uri != NULL, "Error: The uri was NULL.\n");
7746             if(uri) IUri_Release(uri);
7747
7748             uri = NULL;
7749             hr = IUriBuilder_CreateUriSimple(builder, Uri_HAS_USER_NAME, 0, &uri);
7750             ok(hr == S_OK, "Error: IUriBuilder_CreateUriSimple returned 0x%08x, expected 0x%08x.\n",
7751                 hr, S_OK);
7752             ok(uri != NULL, "Error: uri was NULL.\n");
7753             if(uri) IUri_Release(uri);
7754
7755             uri = NULL;
7756             hr = IUriBuilder_CreateUriWithFlags(builder, 0, 0, 0, 0, &uri);
7757             ok(hr == S_OK, "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x.\n",
7758                 hr, S_OK);
7759             ok(uri != NULL, "Error: uri was NULL.\n");
7760             if(uri) IUri_Release(uri);
7761
7762             hr = IUriBuilder_SetFragment(builder, NULL);
7763             ok(hr == S_OK, "Error: IUriBuilder_SetFragment returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7764
7765             /* The IUriBuilder is changed, so it returns E_NOTIMPL again. */
7766             uri = (void*) 0xdeadbeef;
7767             hr = IUriBuilder_CreateUri(builder, 0, Uri_HAS_USER_NAME, 0, &uri);
7768             ok(hr == E_NOTIMPL, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7769             ok(!uri, "Error: Expected uri to be NULL but was %p instead.\n", uri);
7770
7771             uri = (void*) 0xdeadbeef;
7772             hr = IUriBuilder_CreateUriSimple(builder, Uri_HAS_USER_NAME, 0, &uri);
7773             ok(hr == E_NOTIMPL, "Error: IUriBuilder_CreateUriSimple returned 0x%08x, expected 0x%08x.\n",
7774                 hr, S_OK);
7775             ok(!uri, "Error: Expected uri to be NULL, but was %p instead.\n", uri);
7776
7777             uri = (void*) 0xdeadbeef;
7778             hr = IUriBuilder_CreateUriWithFlags(builder, 0, 0, Uri_HAS_USER_NAME, 0, &uri);
7779             ok(hr == E_NOTIMPL, "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x.\n",
7780                 hr, E_NOTIMPL);
7781             ok(!uri, "Error: Expected uri to be NULL, but was %p instead.\n", uri);
7782         }
7783         if(test) IUri_Release(test);
7784     }
7785     if(builder) IUriBuilder_Release(builder);
7786 }
7787
7788 /* Tests invalid args to the "Get*" functions. */
7789 static void test_IUriBuilder_GetInvalidArgs(void) {
7790     IUriBuilder *builder = NULL;
7791     HRESULT hr;
7792
7793     hr = pCreateIUriBuilder(NULL, 0, 0, &builder);
7794     ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7795     if(SUCCEEDED(hr)) {
7796         LPCWSTR received = (void*) 0xdeadbeef;
7797         DWORD len = -1, port = -1;
7798         BOOL set = -1;
7799
7800         hr = IUriBuilder_GetFragment(builder, NULL, NULL);
7801         ok(hr == E_POINTER, "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x.\n",
7802             hr, E_POINTER);
7803         hr = IUriBuilder_GetFragment(builder, NULL, &received);
7804         ok(hr == E_POINTER, "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x.\n",
7805             hr, E_POINTER);
7806         ok(!received, "Error: Expected received to be NULL, but was %p instead.\n", received);
7807         hr = IUriBuilder_GetFragment(builder, &len, NULL);
7808         ok(hr == E_POINTER, "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x.\n",
7809             hr, E_POINTER);
7810         ok(!len, "Error: Expected len to be 0, but was %d instead.\n", len);
7811
7812         hr = IUriBuilder_GetHost(builder, NULL, NULL);
7813         ok(hr == E_POINTER, "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x.\n",
7814             hr, E_POINTER);
7815         received = (void*) 0xdeadbeef;
7816         hr = IUriBuilder_GetHost(builder, NULL, &received);
7817         ok(hr == E_POINTER, "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x.\n",
7818             hr, E_POINTER);
7819         ok(!received, "Error: Expected received to be NULL, but was %p instead.\n", received);
7820         len = -1;
7821         hr = IUriBuilder_GetHost(builder, &len, NULL);
7822         ok(hr == E_POINTER, "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x.\n",
7823             hr, E_POINTER);
7824         ok(!len, "Error: Expected len to be 0, but was %d instead.\n", len);
7825
7826         hr = IUriBuilder_GetPassword(builder, NULL, NULL);
7827         ok(hr == E_POINTER, "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x.\n",
7828             hr, E_POINTER);
7829         received = (void*) 0xdeadbeef;
7830         hr = IUriBuilder_GetPassword(builder, NULL, &received);
7831         ok(hr == E_POINTER, "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x.\n",
7832             hr, E_POINTER);
7833         ok(!received, "Error: Expected received to be NULL, but was %p instead.\n", received);
7834         len = -1;
7835         hr = IUriBuilder_GetPassword(builder, &len, NULL);
7836         ok(hr == E_POINTER, "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x.\n",
7837             hr, E_POINTER);
7838         ok(!len, "Error: Expected len to be 0, but was %d instead.\n", len);
7839
7840         hr = IUriBuilder_GetPath(builder, NULL, NULL);
7841         ok(hr == E_POINTER, "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x.\n",
7842             hr, E_POINTER);
7843         received = (void*) 0xdeadbeef;
7844         hr = IUriBuilder_GetPath(builder, NULL, &received);
7845         ok(hr == E_POINTER, "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x.\n",
7846             hr, E_POINTER);
7847         ok(!received, "Error: Expected received to be NULL, but was %p instead.\n", received);
7848         len = -1;
7849         hr = IUriBuilder_GetPath(builder, &len, NULL);
7850         ok(hr == E_POINTER, "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x.\n",
7851             hr, E_POINTER);
7852         ok(!len, "Error: Expected len to be 0, but was %d instead.\n", len);
7853
7854         hr = IUriBuilder_GetPort(builder, NULL, NULL);
7855         ok(hr == E_POINTER, "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x.\n",
7856             hr, E_POINTER);
7857         hr = IUriBuilder_GetPort(builder, NULL, &port);
7858         ok(hr == E_POINTER, "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x.\n",
7859             hr, E_POINTER);
7860         ok(!port, "Error: Expected port to be 0, but was %d instead.\n", port);
7861         hr = IUriBuilder_GetPort(builder, &set, NULL);
7862         ok(hr == E_POINTER, "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x.\n",
7863             hr, E_POINTER);
7864         ok(!set, "Error: Expected set to be FALSE, but was %d instead.\n", set);
7865
7866         hr = IUriBuilder_GetQuery(builder, NULL, NULL);
7867         ok(hr == E_POINTER, "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x.\n",
7868             hr, E_POINTER);
7869         received = (void*) 0xdeadbeef;
7870         hr = IUriBuilder_GetQuery(builder, NULL, &received);
7871         ok(hr == E_POINTER, "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x.\n",
7872             hr, E_POINTER);
7873         ok(!received, "Error: Expected received to be NULL, but was %p instead.\n", received);
7874         len = -1;
7875         hr = IUriBuilder_GetQuery(builder, &len, NULL);
7876         ok(hr == E_POINTER, "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x.\n",
7877             hr, E_POINTER);
7878         ok(!len, "Error: Expected len to be 0, but was %d instead.\n", len);
7879
7880         hr = IUriBuilder_GetSchemeName(builder, NULL, NULL);
7881         ok(hr == E_POINTER, "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x.\n",
7882             hr, E_POINTER);
7883         received = (void*) 0xdeadbeef;
7884         hr = IUriBuilder_GetSchemeName(builder, NULL, &received);
7885         ok(hr == E_POINTER, "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x.\n",
7886             hr, E_POINTER);
7887         ok(!received, "Error: Expected received to be NULL, but was %p instead.\n", received);
7888         len = -1;
7889         hr = IUriBuilder_GetSchemeName(builder, &len, NULL);
7890         ok(hr == E_POINTER, "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x.\n",
7891             hr, E_POINTER);
7892         ok(!len, "Error: Expected len to be 0, but was %d instead.\n", len);
7893
7894         hr = IUriBuilder_GetUserName(builder, NULL, NULL);
7895         ok(hr == E_POINTER, "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x.\n",
7896             hr, E_POINTER);
7897         received = (void*) 0xdeadbeef;
7898         hr = IUriBuilder_GetUserName(builder, NULL, &received);
7899         ok(hr == E_POINTER, "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x.\n",
7900             hr, E_POINTER);
7901         ok(!received, "Error: Expected received to be NULL, but was %p instead.\n", received);
7902         len = -1;
7903         hr = IUriBuilder_GetUserName(builder, &len, NULL);
7904         ok(hr == E_POINTER, "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x.\n",
7905             hr, E_POINTER);
7906         ok(!len, "Error: Expected len to be 0, but was %d instead.\n", len);
7907     }
7908     if(builder) IUriBuilder_Release(builder);
7909 }
7910
7911 static void test_IUriBuilder_GetFragment(IUriBuilder *builder, const uri_builder_test *test,
7912                                          DWORD test_index) {
7913     HRESULT hr;
7914     DWORD i;
7915     LPCWSTR received = NULL;
7916     DWORD len = -1;
7917     const uri_builder_property *prop = NULL;
7918
7919     /* Check if the property was set earlier. */
7920     for(i = 0; i < sizeof(test->properties)/sizeof(test->properties[0]); ++i) {
7921         if(test->properties[i].change && test->properties[i].property == Uri_PROPERTY_FRAGMENT)
7922             prop = &(test->properties[i]);
7923     }
7924
7925     if(prop) {
7926         /* Use expected_value unless it's NULL, then use value. */
7927         LPCSTR expected = prop->expected_value ? prop->expected_value : prop->value;
7928         hr = IUriBuilder_GetFragment(builder, &len, &received);
7929         if(prop->todo) {
7930             todo_wine {
7931                 ok(hr == (expected ? S_OK : S_FALSE),
7932                     "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7933                     hr, (expected ? S_OK : S_FALSE), test_index);
7934             }
7935             if(SUCCEEDED(hr)) {
7936                 todo_wine {
7937                     ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
7938                         expected, wine_dbgstr_w(received), test_index);
7939                 }
7940                 todo_wine {
7941                     ok(lstrlen(expected) == len,
7942                         "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
7943                         lstrlen(expected), len, test_index);
7944                 }
7945             }
7946         } else {
7947             ok(hr == (expected ? S_OK : S_FALSE),
7948                 "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7949                 hr, (expected ? S_OK : S_FALSE), test_index);
7950             ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
7951                 expected, wine_dbgstr_w(received), test_index);
7952             ok(lstrlen(expected) == len,
7953                 "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
7954                 lstrlen(expected), len, test_index);
7955         }
7956     } else {
7957         /* The property wasn't set earlier, so it should return whatever
7958          * the base IUri contains (if anything).
7959          */
7960         IUri *uri = NULL;
7961         hr = IUriBuilder_GetIUri(builder, &uri);
7962         ok(hr == S_OK,
7963             "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7964             hr, S_OK, test_index);
7965         if(SUCCEEDED(hr)) {
7966             if(!uri) {
7967                 received = (void*) 0xdeadbeef;
7968                 len = -1;
7969
7970                 hr = IUriBuilder_GetFragment(builder, &len, &received);
7971                 ok(hr == S_FALSE,
7972                     "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7973                     hr, S_FALSE, test_index);
7974                 if(SUCCEEDED(hr)) {
7975                     ok(!len, "Error: Expected len to be 0, but was %d instead on uri_builder_tests[%d].\n",
7976                         len, test_index);
7977                     ok(!received, "Error: Expected received to be NULL, but was %p instead on uri_builder_tests[%d].\n",
7978                         received, test_index);
7979                 }
7980             } else {
7981                 BOOL has_prop = FALSE;
7982                 BSTR expected = NULL;
7983
7984                 hr = IUri_GetFragment(uri, &expected);
7985                 ok(SUCCEEDED(hr),
7986                     "Error: Expected IUri_GetFragment to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
7987                     hr, test_index);
7988                 has_prop = hr == S_OK;
7989
7990                 hr = IUriBuilder_GetFragment(builder, &len, &received);
7991                 if(has_prop) {
7992                     ok(hr == S_OK,
7993                         "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7994                         hr, S_OK, test_index);
7995                     if(SUCCEEDED(hr)) {
7996                         ok(!lstrcmpW(expected, received),
7997                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].\n",
7998                             wine_dbgstr_w(expected), wine_dbgstr_w(received), test_index);
7999                         ok(lstrlenW(expected) == len,
8000                             "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8001                             lstrlenW(expected), len, test_index);
8002                     }
8003                 } else {
8004                     ok(hr == S_FALSE,
8005                         "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8006                         hr, S_FALSE, test_index);
8007                     if(SUCCEEDED(hr)) {
8008                         ok(!received, "Error: Expected received to be NULL on uri_builder_tests[%d].\n", test_index);
8009                         ok(!len, "Error: Expected the length to be 0, but was %d instead on uri_builder_tests[%d].\n",
8010                             len, test_index);
8011                     }
8012                 }
8013                 SysFreeString(expected);
8014             }
8015         }
8016         if(uri) IUri_Release(uri);
8017     }
8018 }
8019
8020 static void test_IUriBuilder_GetHost(IUriBuilder *builder, const uri_builder_test *test,
8021                                      DWORD test_index) {
8022     HRESULT hr;
8023     DWORD i;
8024     LPCWSTR received = NULL;
8025     DWORD len = -1;
8026     const uri_builder_property *prop = NULL;
8027
8028     /* Check if the property was set earlier. */
8029     for(i = 0; i < sizeof(test->properties)/sizeof(test->properties[0]); ++i) {
8030         if(test->properties[i].change && test->properties[i].property == Uri_PROPERTY_HOST)
8031             prop = &(test->properties[i]);
8032     }
8033
8034     if(prop) {
8035         /* Use expected_value unless it's NULL, then use value. */
8036         LPCSTR expected = prop->expected_value ? prop->expected_value : prop->value;
8037         hr = IUriBuilder_GetHost(builder, &len, &received);
8038         if(prop->todo) {
8039             todo_wine {
8040                 ok(hr == (expected ? S_OK : S_FALSE),
8041                     "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8042                     hr, (expected ? S_OK : S_FALSE), test_index);
8043             }
8044             if(SUCCEEDED(hr)) {
8045                 todo_wine {
8046                     ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
8047                         expected, wine_dbgstr_w(received), test_index);
8048                 }
8049                 todo_wine {
8050                     ok(lstrlen(expected) == len,
8051                         "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8052                         lstrlen(expected), len, test_index);
8053                 }
8054             }
8055         } else {
8056             ok(hr == (expected ? S_OK : S_FALSE),
8057                 "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8058                 hr, (expected ? S_OK : S_FALSE), test_index);
8059             ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
8060                 expected, wine_dbgstr_w(received), test_index);
8061             ok(lstrlen(expected) == len,
8062                 "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8063                 lstrlen(expected), len, test_index);
8064         }
8065     } else {
8066         /* The property wasn't set earlier, so it should return whatever
8067          * the base IUri contains (if anything).
8068          */
8069         IUri *uri = NULL;
8070         hr = IUriBuilder_GetIUri(builder, &uri);
8071         ok(hr == S_OK,
8072             "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8073             hr, S_OK, test_index);
8074         if(SUCCEEDED(hr)) {
8075             if(!uri) {
8076                 received = (void*) 0xdeadbeef;
8077                 len = -1;
8078
8079                 hr = IUriBuilder_GetHost(builder, &len, &received);
8080                 ok(hr == S_FALSE,
8081                     "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8082                     hr, S_FALSE, test_index);
8083                 if(SUCCEEDED(hr)) {
8084                     ok(!len, "Error: Expected len to be 0, but was %d instead on uri_builder_tests[%d].\n",
8085                         len, test_index);
8086                     ok(!received, "Error: Expected received to be NULL, but was %p instead on uri_builder_tests[%d].\n",
8087                         received, test_index);
8088                 }
8089             } else {
8090                 BOOL has_prop = FALSE;
8091                 BSTR expected = NULL;
8092
8093                 hr = IUri_GetHost(uri, &expected);
8094                 ok(SUCCEEDED(hr),
8095                     "Error: Expected IUri_GetHost to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
8096                     hr, test_index);
8097                 has_prop = hr == S_OK;
8098
8099                 hr = IUriBuilder_GetHost(builder, &len, &received);
8100                 if(has_prop) {
8101                     ok(hr == S_OK,
8102                         "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8103                         hr, S_OK, test_index);
8104                     if(SUCCEEDED(hr)) {
8105                         ok(!lstrcmpW(expected, received),
8106                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].\n",
8107                             wine_dbgstr_w(expected), wine_dbgstr_w(received), test_index);
8108                         ok(lstrlenW(expected) == len,
8109                             "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8110                             lstrlenW(expected), len, test_index);
8111                     }
8112                 } else {
8113                     ok(hr == S_FALSE,
8114                         "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8115                         hr, S_FALSE, test_index);
8116                     if(SUCCEEDED(hr)) {
8117                         ok(!received, "Error: Expected received to be NULL on uri_builder_tests[%d].\n", test_index);
8118                         ok(!len, "Error: Expected the length to be 0, but was %d instead on uri_builder_tests[%d].\n",
8119                             len, test_index);
8120                     }
8121                 }
8122                 SysFreeString(expected);
8123             }
8124         }
8125         if(uri) IUri_Release(uri);
8126     }
8127 }
8128
8129 static void test_IUriBuilder_GetPassword(IUriBuilder *builder, const uri_builder_test *test,
8130                                          DWORD test_index) {
8131     HRESULT hr;
8132     DWORD i;
8133     LPCWSTR received = NULL;
8134     DWORD len = -1;
8135     const uri_builder_property *prop = NULL;
8136
8137     /* Check if the property was set earlier. */
8138     for(i = 0; i < sizeof(test->properties)/sizeof(test->properties[0]); ++i) {
8139         if(test->properties[i].change && test->properties[i].property == Uri_PROPERTY_PASSWORD)
8140             prop = &(test->properties[i]);
8141     }
8142
8143     if(prop) {
8144         /* Use expected_value unless it's NULL, then use value. */
8145         LPCSTR expected = prop->expected_value ? prop->expected_value : prop->value;
8146         hr = IUriBuilder_GetPassword(builder, &len, &received);
8147         if(prop->todo) {
8148             todo_wine {
8149                 ok(hr == (expected ? S_OK : S_FALSE),
8150                     "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8151                     hr, (expected ? S_OK : S_FALSE), test_index);
8152             }
8153             if(SUCCEEDED(hr)) {
8154                 todo_wine {
8155                     ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
8156                         expected, wine_dbgstr_w(received), test_index);
8157                 }
8158                 todo_wine {
8159                     ok(lstrlen(expected) == len,
8160                         "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8161                         lstrlen(expected), len, test_index);
8162                 }
8163             }
8164         } else {
8165             ok(hr == (expected ? S_OK : S_FALSE),
8166                 "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8167                 hr, (expected ? S_OK : S_FALSE), test_index);
8168             ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
8169                 expected, wine_dbgstr_w(received), test_index);
8170             ok(lstrlen(expected) == len,
8171                 "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8172                 lstrlen(expected), len, test_index);
8173         }
8174     } else {
8175         /* The property wasn't set earlier, so it should return whatever
8176          * the base IUri contains (if anything).
8177          */
8178         IUri *uri = NULL;
8179         hr = IUriBuilder_GetIUri(builder, &uri);
8180         ok(hr == S_OK,
8181             "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8182             hr, S_OK, test_index);
8183         if(SUCCEEDED(hr)) {
8184             if(!uri) {
8185                 received = (void*) 0xdeadbeef;
8186                 len = -1;
8187
8188                 hr = IUriBuilder_GetPassword(builder, &len, &received);
8189                 ok(hr == S_FALSE,
8190                     "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8191                     hr, S_FALSE, test_index);
8192                 if(SUCCEEDED(hr)) {
8193                     ok(!len, "Error: Expected len to be 0, but was %d instead on uri_builder_tests[%d].\n",
8194                         len, test_index);
8195                     ok(!received, "Error: Expected received to be NULL, but was %p instead on uri_builder_tests[%d].\n",
8196                         received, test_index);
8197                 }
8198             } else {
8199                 BOOL has_prop = FALSE;
8200                 BSTR expected = NULL;
8201
8202                 hr = IUri_GetPassword(uri, &expected);
8203                 ok(SUCCEEDED(hr),
8204                     "Error: Expected IUri_GetPassword to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
8205                     hr, test_index);
8206                 has_prop = hr == S_OK;
8207
8208                 hr = IUriBuilder_GetPassword(builder, &len, &received);
8209                 if(has_prop) {
8210                     ok(hr == S_OK,
8211                         "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8212                         hr, S_OK, test_index);
8213                     if(SUCCEEDED(hr)) {
8214                         ok(!lstrcmpW(expected, received),
8215                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].\n",
8216                             wine_dbgstr_w(expected), wine_dbgstr_w(received), test_index);
8217                         ok(lstrlenW(expected) == len,
8218                             "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8219                             lstrlenW(expected), len, test_index);
8220                     }
8221                 } else {
8222                     ok(hr == S_FALSE,
8223                         "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8224                         hr, S_FALSE, test_index);
8225                     if(SUCCEEDED(hr)) {
8226                         ok(!received, "Error: Expected received to be NULL on uri_builder_tests[%d].\n", test_index);
8227                         ok(!len, "Error: Expected the length to be 0, but was %d instead on uri_builder_tests[%d].\n",
8228                             len, test_index);
8229                     }
8230                 }
8231                 SysFreeString(expected);
8232             }
8233         }
8234         if(uri) IUri_Release(uri);
8235     }
8236 }
8237
8238 static void test_IUriBuilder_GetPath(IUriBuilder *builder, const uri_builder_test *test,
8239                                      DWORD test_index) {
8240     HRESULT hr;
8241     DWORD i;
8242     LPCWSTR received = NULL;
8243     DWORD len = -1;
8244     const uri_builder_property *prop = NULL;
8245
8246     /* Check if the property was set earlier. */
8247     for(i = 0; i < sizeof(test->properties)/sizeof(test->properties[0]); ++i) {
8248         if(test->properties[i].change && test->properties[i].property == Uri_PROPERTY_PATH)
8249             prop = &(test->properties[i]);
8250     }
8251
8252     if(prop) {
8253         /* Use expected_value unless it's NULL, then use value. */
8254         LPCSTR expected = prop->expected_value ? prop->expected_value : prop->value;
8255         hr = IUriBuilder_GetPath(builder, &len, &received);
8256         if(prop->todo) {
8257             todo_wine {
8258                 ok(hr == (expected ? S_OK : S_FALSE),
8259                     "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8260                     hr, (expected ? S_OK : S_FALSE), test_index);
8261             }
8262             if(SUCCEEDED(hr)) {
8263                 todo_wine {
8264                     ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
8265                         expected, wine_dbgstr_w(received), test_index);
8266                 }
8267                 todo_wine {
8268                     ok(lstrlen(expected) == len,
8269                         "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8270                         lstrlen(expected), len, test_index);
8271                 }
8272             }
8273         } else {
8274             ok(hr == (expected ? S_OK : S_FALSE),
8275                 "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8276                 hr, (expected ? S_OK : S_FALSE), test_index);
8277             ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
8278                 expected, wine_dbgstr_w(received), test_index);
8279             ok(lstrlen(expected) == len,
8280                 "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8281                 lstrlen(expected), len, test_index);
8282         }
8283     } else {
8284         /* The property wasn't set earlier, so it should return whatever
8285          * the base IUri contains (if anything).
8286          */
8287         IUri *uri = NULL;
8288         hr = IUriBuilder_GetIUri(builder, &uri);
8289         ok(hr == S_OK,
8290             "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8291             hr, S_OK, test_index);
8292         if(SUCCEEDED(hr)) {
8293             if(!uri) {
8294                 received = (void*) 0xdeadbeef;
8295                 len = -1;
8296
8297                 hr = IUriBuilder_GetPath(builder, &len, &received);
8298                 ok(hr == S_FALSE,
8299                     "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8300                     hr, S_FALSE, test_index);
8301                 if(SUCCEEDED(hr)) {
8302                     ok(!len, "Error: Expected len to be 0, but was %d instead on uri_builder_tests[%d].\n",
8303                         len, test_index);
8304                     ok(!received, "Error: Expected received to be NULL, but was %p instead on uri_builder_tests[%d].\n",
8305                         received, test_index);
8306                 }
8307             } else {
8308                 BOOL has_prop = FALSE;
8309                 BSTR expected = NULL;
8310
8311                 hr = IUri_GetPath(uri, &expected);
8312                 ok(SUCCEEDED(hr),
8313                     "Error: Expected IUri_GetPath to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
8314                     hr, test_index);
8315                 has_prop = hr == S_OK;
8316
8317                 hr = IUriBuilder_GetPath(builder, &len, &received);
8318                 if(has_prop) {
8319                     ok(hr == S_OK,
8320                         "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8321                         hr, S_OK, test_index);
8322                     if(SUCCEEDED(hr)) {
8323                         ok(!lstrcmpW(expected, received),
8324                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].\n",
8325                             wine_dbgstr_w(expected), wine_dbgstr_w(received), test_index);
8326                         ok(lstrlenW(expected) == len,
8327                             "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8328                             lstrlenW(expected), len, test_index);
8329                     }
8330                 } else {
8331                     ok(hr == S_FALSE,
8332                         "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8333                         hr, S_FALSE, test_index);
8334                     if(SUCCEEDED(hr)) {
8335                         ok(!received, "Error: Expected received to be NULL on uri_builder_tests[%d].\n", test_index);
8336                         ok(!len, "Error: Expected the length to be 0, but was %d instead on uri_builder_tests[%d].\n",
8337                             len, test_index);
8338                     }
8339                 }
8340                 SysFreeString(expected);
8341             }
8342         }
8343         if(uri) IUri_Release(uri);
8344     }
8345 }
8346
8347 static void test_IUriBuilder_GetPort(IUriBuilder *builder, const uri_builder_test *test,
8348                                      DWORD test_index) {
8349     HRESULT hr;
8350     BOOL has_port = FALSE;
8351     DWORD received = -1;
8352
8353     if(test->port_prop.change) {
8354         DWORD expected = test->port_prop.value;
8355
8356         hr = IUriBuilder_GetPort(builder, &has_port, &received);
8357         if(test->port_prop.todo) {
8358             todo_wine {
8359                 ok(hr == S_OK,
8360                     "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8361                     hr, S_OK, test_index);
8362             }
8363             if(SUCCEEDED(hr)) {
8364                 todo_wine {
8365                     ok(has_port == test->port_prop.set,
8366                         "Error: Expected has_port to be %d but was %d instead on uri_builder_tests[%d].\n",
8367                         test->port_prop.set, has_port, test_index);
8368                 }
8369                 todo_wine {
8370                     ok(received == expected,
8371                         "Error: Expected received to be %d, but was %d instead on uri_builder_tests[%d].\n",
8372                         expected, received, test_index);
8373                 }
8374             }
8375         } else {
8376             ok(hr == S_OK,
8377                 "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8378                 hr, S_OK, test_index);
8379             ok(has_port == test->port_prop.set,
8380                 "Error: Expected has_port to be %d, but was %d instead on uri_builder_tests[%d].\n",
8381                 test->port_prop.set, has_port, test_index);
8382             ok(received == test->port_prop.value,
8383                 "Error: Expected port to be %d, but was %d instead on uri_builder_tests[%d].\n",
8384                 test->port_prop.value, received, test_index);
8385         }
8386     } else {
8387         IUri *uri = NULL;
8388
8389         hr = IUriBuilder_GetIUri(builder, &uri);
8390         ok(hr == S_OK,
8391             "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8392             hr, S_OK, test_index);
8393         if(SUCCEEDED(hr)) {
8394             if(!uri) {
8395                 hr = IUriBuilder_GetPort(builder, &has_port, &received);
8396                 ok(hr == S_OK,
8397                     "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8398                     hr, S_OK, test_index);
8399                 if(SUCCEEDED(hr)) {
8400                     ok(has_port == FALSE,
8401                         "Error: Expected has_port to be FALSE, but was %d instead on uri_builder_tests[%d].\n",
8402                         has_port, test_index);
8403                     ok(!received, "Error: Expected received to be 0, but was %d instead on uri_builder_tests[%d].\n",
8404                         received, test_index);
8405                 }
8406             } else {
8407                 DWORD expected;
8408
8409                 hr = IUri_GetPort(uri, &expected);
8410                 ok(SUCCEEDED(hr),
8411                     "Error: Expected IUri_Port to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
8412                     hr, test_index);
8413
8414                 hr = IUriBuilder_GetPort(builder, &has_port, &received);
8415                 ok(hr == S_OK,
8416                     "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8417                     hr, S_OK, test_index);
8418                 if(SUCCEEDED(hr)) {
8419                     ok(!has_port,
8420                         "Error: Expected has_port to be FALSE but was TRUE instead on uri_builder_tests[%d].\n",
8421                         test_index);
8422                     ok(received == expected,
8423                         "Error: Expected received to be %d, but was %d instead on uri_builder_tests[%d].\n",
8424                         expected, received, test_index);
8425                 }
8426             }
8427         }
8428         if(uri) IUri_Release(uri);
8429     }
8430 }
8431
8432 static void test_IUriBuilder_GetQuery(IUriBuilder *builder, const uri_builder_test *test,
8433                                       DWORD test_index) {
8434     HRESULT hr;
8435     DWORD i;
8436     LPCWSTR received = NULL;
8437     DWORD len = -1;
8438     const uri_builder_property *prop = NULL;
8439
8440     /* Check if the property was set earlier. */
8441     for(i = 0; i < sizeof(test->properties)/sizeof(test->properties[0]); ++i) {
8442         if(test->properties[i].change && test->properties[i].property == Uri_PROPERTY_QUERY)
8443             prop = &(test->properties[i]);
8444     }
8445
8446     if(prop) {
8447         /* Use expected_value unless it's NULL, then use value. */
8448         LPCSTR expected = prop->expected_value ? prop->expected_value : prop->value;
8449         hr = IUriBuilder_GetQuery(builder, &len, &received);
8450         if(prop->todo) {
8451             todo_wine {
8452                 ok(hr == (expected ? S_OK : S_FALSE),
8453                     "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8454                     hr, (expected ? S_OK : S_FALSE), test_index);
8455             }
8456             if(SUCCEEDED(hr)) {
8457                 todo_wine {
8458                     ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
8459                         expected, wine_dbgstr_w(received), test_index);
8460                 }
8461                 todo_wine {
8462                     ok(lstrlen(expected) == len,
8463                         "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8464                         lstrlen(expected), len, test_index);
8465                 }
8466             }
8467         } else {
8468             ok(hr == (expected ? S_OK : S_FALSE),
8469                 "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8470                 hr, (expected ? S_OK : S_FALSE), test_index);
8471             ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
8472                 expected, wine_dbgstr_w(received), test_index);
8473             ok(lstrlen(expected) == len,
8474                 "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8475                 lstrlen(expected), len, test_index);
8476         }
8477     } else {
8478         /* The property wasn't set earlier, so it should return whatever
8479          * the base IUri contains (if anything).
8480          */
8481         IUri *uri = NULL;
8482         hr = IUriBuilder_GetIUri(builder, &uri);
8483         ok(hr == S_OK,
8484             "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8485             hr, S_OK, test_index);
8486         if(SUCCEEDED(hr)) {
8487             if(!uri) {
8488                 received = (void*) 0xdeadbeef;
8489                 len = -1;
8490
8491                 hr = IUriBuilder_GetQuery(builder, &len, &received);
8492                 ok(hr == S_FALSE,
8493                     "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8494                     hr, S_FALSE, test_index);
8495                 if(SUCCEEDED(hr)) {
8496                     ok(!len, "Error: Expected len to be 0, but was %d instead on uri_builder_tests[%d].\n",
8497                         len, test_index);
8498                     ok(!received, "Error: Expected received to be NULL, but was %p instead on uri_builder_tests[%d].\n",
8499                         received, test_index);
8500                 }
8501             } else {
8502                 BOOL has_prop = FALSE;
8503                 BSTR expected = NULL;
8504
8505                 hr = IUri_GetQuery(uri, &expected);
8506                 ok(SUCCEEDED(hr),
8507                     "Error: Expected IUri_GetQuery to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
8508                     hr, test_index);
8509                 has_prop = hr == S_OK;
8510
8511                 hr = IUriBuilder_GetQuery(builder, &len, &received);
8512                 if(has_prop) {
8513                     ok(hr == S_OK,
8514                         "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8515                         hr, S_OK, test_index);
8516                     if(SUCCEEDED(hr)) {
8517                         ok(!lstrcmpW(expected, received),
8518                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].\n",
8519                             wine_dbgstr_w(expected), wine_dbgstr_w(received), test_index);
8520                         ok(lstrlenW(expected) == len,
8521                             "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8522                             lstrlenW(expected), len, test_index);
8523                     }
8524                 } else {
8525                     ok(hr == S_FALSE,
8526                         "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8527                         hr, S_FALSE, test_index);
8528                     if(SUCCEEDED(hr)) {
8529                         ok(!received, "Error: Expected received to be NULL on uri_builder_tests[%d].\n", test_index);
8530                         ok(!len, "Error: Expected the length to be 0, but was %d instead on uri_builder_tests[%d].\n",
8531                             len, test_index);
8532                     }
8533                 }
8534                 SysFreeString(expected);
8535             }
8536         }
8537         if(uri) IUri_Release(uri);
8538     }
8539 }
8540
8541 static void test_IUriBuilder_GetSchemeName(IUriBuilder *builder, const uri_builder_test *test,
8542                                            DWORD test_index) {
8543     HRESULT hr;
8544     DWORD i;
8545     LPCWSTR received = NULL;
8546     DWORD len = -1;
8547     const uri_builder_property *prop = NULL;
8548
8549     /* Check if the property was set earlier. */
8550     for(i = 0; i < sizeof(test->properties)/sizeof(test->properties[0]); ++i) {
8551         if(test->properties[i].change && test->properties[i].property == Uri_PROPERTY_SCHEME_NAME)
8552             prop = &(test->properties[i]);
8553     }
8554
8555     if(prop) {
8556         /* Use expected_value unless it's NULL, then use value. */
8557         LPCSTR expected = prop->expected_value ? prop->expected_value : prop->value;
8558         hr = IUriBuilder_GetSchemeName(builder, &len, &received);
8559         if(prop->todo) {
8560             todo_wine {
8561                 ok(hr == (expected ? S_OK : S_FALSE),
8562                     "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8563                     hr, (expected ? S_OK : S_FALSE), test_index);
8564             }
8565             if(SUCCEEDED(hr)) {
8566                 todo_wine {
8567                     ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
8568                         expected, wine_dbgstr_w(received), test_index);
8569                 }
8570                 todo_wine {
8571                     ok(lstrlen(expected) == len,
8572                         "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8573                         lstrlen(expected), len, test_index);
8574                 }
8575             }
8576         } else {
8577             ok(hr == (expected ? S_OK : S_FALSE),
8578                 "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8579                 hr, (expected ? S_OK : S_FALSE), test_index);
8580             ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
8581                 expected, wine_dbgstr_w(received), test_index);
8582             ok(lstrlen(expected) == len,
8583                 "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8584                 lstrlen(expected), len, test_index);
8585         }
8586     } else {
8587         /* The property wasn't set earlier, so it should return whatever
8588          * the base IUri contains (if anything).
8589          */
8590         IUri *uri = NULL;
8591         hr = IUriBuilder_GetIUri(builder, &uri);
8592         ok(hr == S_OK,
8593             "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8594             hr, S_OK, test_index);
8595         if(SUCCEEDED(hr)) {
8596             if(!uri) {
8597                 received = (void*) 0xdeadbeef;
8598                 len = -1;
8599
8600                 hr = IUriBuilder_GetSchemeName(builder, &len, &received);
8601                 ok(hr == S_FALSE,
8602                     "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8603                     hr, S_FALSE, test_index);
8604                 if(SUCCEEDED(hr)) {
8605                     ok(!len, "Error: Expected len to be 0, but was %d instead on uri_builder_tests[%d].\n",
8606                         len, test_index);
8607                     ok(!received, "Error: Expected received to be NULL, but was %p instead on uri_builder_tests[%d].\n",
8608                         received, test_index);
8609                 }
8610             } else {
8611                 BOOL has_prop = FALSE;
8612                 BSTR expected = NULL;
8613
8614                 hr = IUri_GetSchemeName(uri, &expected);
8615                 ok(SUCCEEDED(hr),
8616                     "Error: Expected IUri_GetSchemeName to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
8617                     hr, test_index);
8618                 has_prop = hr == S_OK;
8619
8620                 hr = IUriBuilder_GetSchemeName(builder, &len, &received);
8621                 if(has_prop) {
8622                     ok(hr == S_OK,
8623                         "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8624                         hr, S_OK, test_index);
8625                     if(SUCCEEDED(hr)) {
8626                         ok(!lstrcmpW(expected, received),
8627                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].\n",
8628                             wine_dbgstr_w(expected), wine_dbgstr_w(received), test_index);
8629                         ok(lstrlenW(expected) == len,
8630                             "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8631                             lstrlenW(expected), len, test_index);
8632                     }
8633                 } else {
8634                     ok(hr == S_FALSE,
8635                         "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8636                         hr, S_FALSE, test_index);
8637                     if(SUCCEEDED(hr)) {
8638                         ok(!received, "Error: Expected received to be NULL on uri_builder_tests[%d].\n", test_index);
8639                         ok(!len, "Error: Expected the length to be 0, but was %d instead on uri_builder_tests[%d].\n",
8640                             len, test_index);
8641                     }
8642                 }
8643                 SysFreeString(expected);
8644             }
8645         }
8646         if(uri) IUri_Release(uri);
8647     }
8648 }
8649
8650 static void test_IUriBuilder_GetUserName(IUriBuilder *builder, const uri_builder_test *test,
8651                                          DWORD test_index) {
8652     HRESULT hr;
8653     DWORD i;
8654     LPCWSTR received = NULL;
8655     DWORD len = -1;
8656     const uri_builder_property *prop = NULL;
8657
8658     /* Check if the property was set earlier. */
8659     for(i = 0; i < sizeof(test->properties)/sizeof(test->properties[0]); ++i) {
8660         if(test->properties[i].change && test->properties[i].property == Uri_PROPERTY_USER_NAME)
8661             prop = &(test->properties[i]);
8662     }
8663
8664     if(prop && prop->value && *prop->value) {
8665         /* Use expected_value unless it's NULL, then use value. */
8666         LPCSTR expected = prop->expected_value ? prop->expected_value : prop->value;
8667         hr = IUriBuilder_GetUserName(builder, &len, &received);
8668         if(prop->todo) {
8669             todo_wine {
8670                 ok(hr == (expected ? S_OK : S_FALSE),
8671                     "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8672                     hr, (expected ? S_OK : S_FALSE), test_index);
8673             }
8674             if(SUCCEEDED(hr)) {
8675                 todo_wine {
8676                     ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
8677                         expected, wine_dbgstr_w(received), test_index);
8678                 }
8679                 todo_wine {
8680                     ok(lstrlen(expected) == len,
8681                         "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8682                         lstrlen(expected), len, test_index);
8683                 }
8684             }
8685         } else {
8686             ok(hr == (expected ? S_OK : S_FALSE),
8687                 "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8688                 hr, (expected ? S_OK : S_FALSE), test_index);
8689             ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
8690                 expected, wine_dbgstr_w(received), test_index);
8691             ok(lstrlen(expected) == len,
8692                 "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8693                 lstrlen(expected), len, test_index);
8694         }
8695     } else {
8696         /* The property wasn't set earlier, so it should return whatever
8697          * the base IUri contains (if anything).
8698          */
8699         IUri *uri = NULL;
8700         hr = IUriBuilder_GetIUri(builder, &uri);
8701         ok(hr == S_OK,
8702             "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8703             hr, S_OK, test_index);
8704         if(SUCCEEDED(hr)) {
8705             if(!uri) {
8706                 received = (void*) 0xdeadbeef;
8707                 len = -1;
8708
8709                 hr = IUriBuilder_GetUserName(builder, &len, &received);
8710                 ok(hr == S_FALSE,
8711                     "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8712                     hr, S_FALSE, test_index);
8713                 if(SUCCEEDED(hr)) {
8714                     ok(!len, "Error: Expected len to be 0, but was %d instead on uri_builder_tests[%d].\n",
8715                         len, test_index);
8716                     ok(!received, "Error: Expected received to be NULL, but was %p instead on uri_builder_tests[%d].\n",
8717                         received, test_index);
8718                 }
8719             } else {
8720                 BSTR expected = NULL;
8721                 BOOL has_prop = FALSE;
8722
8723                 hr = IUri_GetUserName(uri, &expected);
8724                 ok(SUCCEEDED(hr),
8725                     "Error: Expected IUri_GetUserName to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
8726                     hr, test_index);
8727                 has_prop = hr == S_OK;
8728
8729                 hr = IUriBuilder_GetUserName(builder, &len, &received);
8730                 if(has_prop) {
8731                     ok(hr == S_OK,
8732                         "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8733                         hr, S_OK, test_index);
8734                     if(SUCCEEDED(hr)) {
8735                         ok(!lstrcmpW(expected, received),
8736                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].\n",
8737                             wine_dbgstr_w(expected), wine_dbgstr_w(received), test_index);
8738                         ok(lstrlenW(expected) == len,
8739                             "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8740                             lstrlenW(expected), len, test_index);
8741                     }
8742                 } else {
8743                     ok(hr == S_FALSE,
8744                         "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8745                         hr, S_FALSE, test_index);
8746                     if(SUCCEEDED(hr)) {
8747                         ok(!received, "Error: Expected received to be NULL on uri_builder_tests[%d].\n", test_index);
8748                         ok(!len, "Error: Expected the length to be 0, but was %d instead on uri_builder_tests[%d].\n",
8749                             len, test_index);
8750                     }
8751                 }
8752                 SysFreeString(expected);
8753             }
8754         }
8755         if(uri) IUri_Release(uri);
8756     }
8757 }
8758
8759 /* Tests IUriBuilder functions. */
8760 static void test_IUriBuilder(void) {
8761     HRESULT hr;
8762     IUriBuilder *builder;
8763     DWORD i;
8764
8765     for(i = 0; i < sizeof(uri_builder_tests)/sizeof(uri_builder_tests[0]); ++i) {
8766         IUri *uri = NULL;
8767         uri_builder_test test = uri_builder_tests[i];
8768         LPWSTR uriW = NULL;
8769
8770         if(test.uri) {
8771             uriW = a2w(test.uri);
8772             hr = pCreateUri(uriW, test.create_flags, 0, &uri);
8773             ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8774                 hr, S_OK, i);
8775             if(FAILED(hr)) continue;
8776         }
8777         hr = pCreateIUriBuilder(uri, 0, 0, &builder);
8778         if(test.create_builder_todo) {
8779             todo_wine {
8780                 ok(hr == test.create_builder_expected,
8781                     "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8782                     hr, test.create_builder_expected, i);
8783             }
8784         } else {
8785             ok(hr == test.create_builder_expected,
8786                 "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8787                 hr, test.create_builder_expected, i);
8788         }
8789         if(SUCCEEDED(hr)) {
8790             DWORD j;
8791             BOOL modified = FALSE, received = FALSE;
8792
8793             /* Perform all the string property changes. */
8794             for(j = 0; j < URI_BUILDER_STR_PROPERTY_COUNT; ++j) {
8795                 uri_builder_property prop = test.properties[j];
8796                 if(prop.change) {
8797                     change_property(builder, &prop, i);
8798                     if(prop.property != Uri_PROPERTY_SCHEME_NAME &&
8799                        prop.property != Uri_PROPERTY_HOST)
8800                         modified = TRUE;
8801                     else if(prop.value && *prop.value)
8802                         modified = TRUE;
8803                     else if(prop.value && !*prop.value && prop.property == Uri_PROPERTY_HOST)
8804                         /* Host name property can't be NULL, but it can be empty. */
8805                         modified = TRUE;
8806                 }
8807             }
8808
8809             if(test.port_prop.change) {
8810                 hr = IUriBuilder_SetPort(builder, test.port_prop.set, test.port_prop.value);
8811                 modified = TRUE;
8812                 if(test.port_prop.todo) {
8813                     todo_wine {
8814                         ok(hr == test.port_prop.expected,
8815                             "Error: IUriBuilder_SetPort returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8816                             hr, test.port_prop.expected, i);
8817                     }
8818                 } else {
8819                     ok(hr == test.port_prop.expected,
8820                         "Error: IUriBuilder_SetPort returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8821                         hr, test.port_prop.expected, i);
8822                 }
8823             }
8824
8825             hr = IUriBuilder_HasBeenModified(builder, &received);
8826             ok(hr == S_OK,
8827                 "Error IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8828                 hr, S_OK, i);
8829             if(SUCCEEDED(hr))
8830                 ok(received == modified,
8831                     "Error: Expected received to be %d but was %d instead on uri_builder_tests[%d].\n",
8832                     modified, received, i);
8833
8834             /* Test the "Get*" functions. */
8835             test_IUriBuilder_GetFragment(builder, &test, i);
8836             test_IUriBuilder_GetHost(builder, &test, i);
8837             test_IUriBuilder_GetPassword(builder, &test, i);
8838             test_IUriBuilder_GetPath(builder, &test, i);
8839             test_IUriBuilder_GetPort(builder, &test, i);
8840             test_IUriBuilder_GetQuery(builder, &test, i);
8841             test_IUriBuilder_GetSchemeName(builder, &test, i);
8842             test_IUriBuilder_GetUserName(builder, &test, i);
8843
8844             test_IUriBuilder_CreateUri(builder, &test, i);
8845             test_IUriBuilder_CreateUriSimple(builder, &test, i);
8846             test_IUriBuilder_CreateUriWithFlags(builder, &test, i);
8847         }
8848         if(builder) IUriBuilder_Release(builder);
8849         if(uri) IUri_Release(uri);
8850         heap_free(uriW);
8851     }
8852 }
8853
8854 static void test_IUriBuilder_HasBeenModified(void) {
8855     HRESULT hr;
8856     IUriBuilder *builder = NULL;
8857
8858     hr = pCreateIUriBuilder(NULL, 0, 0, &builder);
8859     ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8860     if(SUCCEEDED(hr)) {
8861         static const WCHAR hostW[] = {'g','o','o','g','l','e','.','c','o','m',0};
8862         IUri *uri = NULL;
8863         BOOL received;
8864
8865         hr = IUriBuilder_HasBeenModified(builder, NULL);
8866         ok(hr == E_POINTER, "Error: IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x.\n",
8867             hr, E_POINTER);
8868
8869         hr = IUriBuilder_SetHost(builder, hostW);
8870         ok(hr == S_OK, "Error: IUriBuilder_SetHost returned 0x%08x, expected 0x%08x.\n",
8871             hr, S_OK);
8872
8873         hr = IUriBuilder_HasBeenModified(builder, &received);
8874         ok(hr == S_OK, "Error: IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x.\n",
8875             hr, S_OK);
8876         if(SUCCEEDED(hr))
8877             ok(received == TRUE, "Error: Expected received to be TRUE.\n");
8878
8879         hr = pCreateUri(http_urlW, 0, 0, &uri);
8880         ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8881         if(SUCCEEDED(hr)) {
8882             LPCWSTR prop;
8883             DWORD len = -1;
8884
8885             hr = IUriBuilder_SetIUri(builder, uri);
8886             ok(hr == S_OK, "Error: IUriBuilder_SetIUri returned 0x%08x, expected 0x%08x.\n",
8887                 hr, S_OK);
8888
8889             hr = IUriBuilder_HasBeenModified(builder, &received);
8890             ok(hr == S_OK, "Error: IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x.\n",
8891                 hr, S_OK);
8892             if(SUCCEEDED(hr))
8893                 ok(received == FALSE, "Error: Expected received to be FALSE.\n");
8894
8895             /* Test what happens with you call SetIUri with the same IUri again. */
8896             hr = IUriBuilder_SetHost(builder, hostW);
8897             ok(hr == S_OK, "Error: IUriBuilder_SetHost returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8898
8899             hr = IUriBuilder_HasBeenModified(builder, &received);
8900             ok(hr == S_OK, "Error: IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x.\n",
8901                 hr, S_OK);
8902             if(SUCCEEDED(hr))
8903                 ok(received == TRUE, "Error: Expected received to be TRUE.\n");
8904
8905             hr = IUriBuilder_SetIUri(builder, uri);
8906             ok(hr == S_OK, "Error: IUriBuilder_SetIUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8907
8908             /* IUriBuilder already had 'uri' as it's IUri property and so Windows doesn't
8909              * reset any of the changes that were made to the IUriBuilder.
8910              */
8911             hr = IUriBuilder_HasBeenModified(builder, &received);
8912             ok(hr == S_OK, "Error: IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8913             if(SUCCEEDED(hr))
8914                 ok(received == TRUE, "Error: Expected received to be TRUE.\n");
8915
8916             hr = IUriBuilder_GetHost(builder, &len, &prop);
8917             ok(hr == S_OK, "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8918             if(SUCCEEDED(hr)) {
8919                 ok(!lstrcmpW(prop, hostW), "Error: Expected %s but got %s instead.\n",
8920                     wine_dbgstr_w(hostW), wine_dbgstr_w(prop));
8921                 ok(len == lstrlenW(hostW), "Error: Expected len to be %d, but was %d instead.\n",
8922                     lstrlenW(hostW), len);
8923             }
8924
8925             hr = IUriBuilder_SetIUri(builder, NULL);
8926             ok(hr == S_OK, "Error: IUriBuilder_SetIUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8927
8928             hr = IUriBuilder_SetHost(builder, hostW);
8929             ok(hr == S_OK, "Error: IUriBuilder_SetHost returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8930             hr = IUriBuilder_HasBeenModified(builder, &received);
8931             ok(hr == S_OK, "Error: IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x.\n",
8932                 hr, S_OK);
8933             if(SUCCEEDED(hr))
8934                 ok(received == TRUE, "Error: Expected received to be TRUE.\n");
8935
8936             hr = IUriBuilder_SetIUri(builder, NULL);
8937             ok(hr == S_OK, "Error: IUriBuilder_SetIUri returned 0x%08x, expected 0x%09x.\n", hr, S_OK);
8938
8939             hr = IUriBuilder_HasBeenModified(builder, &received);
8940             ok(hr == S_OK, "Error: IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x.\n",
8941                 hr, S_OK);
8942             if(SUCCEEDED(hr))
8943                 ok(received == TRUE, "Error: Expected received to be TRUE.\n");
8944
8945             hr = IUriBuilder_GetHost(builder, &len, &prop);
8946             ok(hr == S_OK, "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8947             if(SUCCEEDED(hr)) {
8948                 ok(!lstrcmpW(prop, hostW), "Error: Expected %s but got %s instead.\n",
8949                     wine_dbgstr_w(hostW), wine_dbgstr_w(prop));
8950                 ok(len == lstrlenW(hostW), "Error: Expected len to %d, but was %d instead.\n",
8951                     lstrlenW(hostW), len);
8952             }
8953         }
8954         if(uri) IUri_Release(uri);
8955     }
8956     if(builder) IUriBuilder_Release(builder);
8957 }
8958
8959 /* Test IUriBuilder {Get,Set}IUri functions. */
8960 static void test_IUriBuilder_IUriProperty(void) {
8961     IUriBuilder *builder = NULL;
8962     HRESULT hr;
8963
8964     hr = pCreateIUriBuilder(NULL, 0, 0, &builder);
8965     ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8966     if(SUCCEEDED(hr)) {
8967         IUri *uri = NULL;
8968
8969         hr = IUriBuilder_GetIUri(builder, NULL);
8970         ok(hr == E_POINTER, "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x.\n",
8971             hr, E_POINTER);
8972
8973         hr = pCreateUri(http_urlW, 0, 0, &uri);
8974         if(SUCCEEDED(hr)) {
8975             IUri *test = NULL;
8976             ULONG cur_count, orig_count;
8977
8978             /* IUriBuilder doesn't clone the IUri, it use the same IUri. */
8979             orig_count = get_refcnt(uri);
8980             hr = IUriBuilder_SetIUri(builder, uri);
8981             cur_count = get_refcnt(uri);
8982             if(SUCCEEDED(hr))
8983                 ok(cur_count == orig_count+1, "Error: Expected uri ref count to be %d, but was %d instead.\n",
8984                     orig_count+1, cur_count);
8985
8986             hr = IUriBuilder_SetIUri(builder, NULL);
8987             cur_count = get_refcnt(uri);
8988             if(SUCCEEDED(hr))
8989                 ok(cur_count == orig_count, "Error: Expected uri ref count to be %d, but was %d instead.\n",
8990                     orig_count, cur_count);
8991
8992             /* CreateUri* functions will return back the same IUri if nothing has changed. */
8993             hr = IUriBuilder_SetIUri(builder, uri);
8994             ok(hr == S_OK, "Error: IUriBuilder_SetIUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8995             orig_count = get_refcnt(uri);
8996
8997             hr = IUriBuilder_CreateUri(builder, 0, 0, 0, &test);
8998             ok(hr == S_OK, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8999             if(SUCCEEDED(hr)) {
9000                 cur_count = get_refcnt(uri);
9001                 ok(cur_count == orig_count+1, "Error: Expected uri ref count to be %d, but was %d instead.\n",
9002                     orig_count+1, cur_count);
9003                 ok(test == uri, "Error: Expected test to be %p, but was %p instead.\n",
9004                     uri, test);
9005             }
9006             if(test) IUri_Release(test);
9007
9008             test = NULL;
9009             hr = IUriBuilder_CreateUri(builder, -1, 0, 0, &test);
9010             ok(hr == S_OK, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9011             if(SUCCEEDED(hr)) {
9012                 cur_count = get_refcnt(uri);
9013                 ok(cur_count == orig_count+1, "Error: Expected uri ref count to be %d, but was %d instead.\n",
9014                     orig_count+1, cur_count);
9015                 ok(test == uri, "Error: Expected test to be %p, but was %p instead.\n", uri, test);
9016             }
9017             if(test) IUri_Release(test);
9018
9019             /* Doesn't return the same IUri, if the flag combination is different then the one that created
9020              * the base IUri.
9021              */
9022             test = NULL;
9023             hr = IUriBuilder_CreateUri(builder, Uri_CREATE_ALLOW_RELATIVE, 0, 0, &test);
9024             ok(hr == S_OK, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9025             if(SUCCEEDED(hr))
9026                 ok(test != uri, "Error: Wasn't expecting 'test' to be 'uri'\n");
9027
9028             if(test) IUri_Release(test);
9029
9030             /* Still returns the same IUri, even though the base one wasn't created with CREATE_CANONICALIZE
9031              * explicitly set (because it's a default flags).
9032              */
9033             test = NULL;
9034             hr = IUriBuilder_CreateUri(builder, Uri_CREATE_CANONICALIZE, 0, 0, &test);
9035             ok(hr == S_OK, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9036             if(SUCCEEDED(hr)) {
9037                 cur_count = get_refcnt(uri);
9038                 ok(cur_count == orig_count+1, "Error: Expected uri ref count to be %d, but was %d instead.\n",
9039                     orig_count+1, cur_count);
9040                 ok(test == uri, "Error: Expected 'test' to be %p, but was %p instead.\n", uri, test);
9041             }
9042             if(test) IUri_Release(test);
9043
9044             test = NULL;
9045             hr = IUriBuilder_CreateUriSimple(builder, 0, 0, &test);
9046             ok(hr == S_OK, "Error: IUriBuilder_CreateUriSimple returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9047             if(SUCCEEDED(hr)) {
9048                 cur_count = get_refcnt(uri);
9049                 ok(cur_count == orig_count+1, "Error: Expected uri ref count to be %d, but was %d instead.\n",
9050                     orig_count+1, cur_count);
9051                 ok(test == uri, "Error: Expected test to be %p, but was %p instead.\n", uri, test);
9052             }
9053             if(test) IUri_Release(test);
9054
9055             test = NULL;
9056             hr = IUriBuilder_CreateUriWithFlags(builder, 0, 0, 0, 0, &test);
9057             ok(hr == S_OK, "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x.\n",
9058                 hr, S_OK);
9059             if(SUCCEEDED(hr)) {
9060                 cur_count = get_refcnt(uri);
9061                 ok(cur_count == orig_count+1, "Error: Expected uri ref count to be %d, but was %d instead.\n",
9062                     orig_count+1, cur_count);
9063                 ok(test == uri, "Error: Expected test to be %p, but was %p instead.\n", uri, test);
9064             }
9065             if(test) IUri_Release(test);
9066
9067             /* Doesn't return the same IUri, if the flag combination is different then the one that created
9068              * the base IUri.
9069              */
9070             test = NULL;
9071             hr = IUriBuilder_CreateUriWithFlags(builder, Uri_CREATE_ALLOW_RELATIVE, 0, 0, 0, &test);
9072             ok(hr == S_OK, "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9073             if(SUCCEEDED(hr))
9074                 ok(test != uri, "Error: Wasn't expecting 'test' to be 'uri'\n");
9075
9076             if(test) IUri_Release(test);
9077
9078             /* Still returns the same IUri, even though the base one wasn't created with CREATE_CANONICALIZE
9079              * explicitly set (because it's a default flags).
9080              */
9081             test = NULL;
9082             hr = IUriBuilder_CreateUriWithFlags(builder, Uri_CREATE_CANONICALIZE, 0, 0, 0, &test);
9083             ok(hr == S_OK, "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9084             if(SUCCEEDED(hr)) {
9085                 cur_count = get_refcnt(uri);
9086                 ok(cur_count == orig_count+1, "Error: Expected uri ref count to be %d, but was %d instead.\n",
9087                     orig_count+1, cur_count);
9088                 ok(test == uri, "Error: Expected 'test' to be %p, but was %p instead.\n", uri, test);
9089             }
9090             if(test) IUri_Release(test);
9091         }
9092         if(uri) IUri_Release(uri);
9093     }
9094     if(builder) IUriBuilder_Release(builder);
9095 }
9096
9097 static void test_IUriBuilder_RemoveProperties(void) {
9098     IUriBuilder *builder = NULL;
9099     HRESULT hr;
9100     DWORD i;
9101
9102     hr = pCreateIUriBuilder(NULL, 0, 0, &builder);
9103     ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9104     if(SUCCEEDED(hr)) {
9105         /* Properties that can't be removed. */
9106         const DWORD invalid = Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_RAW_URI|Uri_HAS_HOST_TYPE|
9107                               Uri_HAS_SCHEME|Uri_HAS_ZONE;
9108
9109         for(i = Uri_PROPERTY_STRING_START; i <= Uri_PROPERTY_DWORD_LAST; ++i) {
9110             hr = IUriBuilder_RemoveProperties(builder, i << 1);
9111             if((i << 1) & invalid) {
9112                 ok(hr == E_INVALIDARG,
9113                     "Error: IUriBuilder_RemoveProperties returned 0x%08x, expected 0x%08x with prop=%d.\n",
9114                     hr, E_INVALIDARG, i);
9115             } else {
9116                 ok(hr == S_OK,
9117                     "Error: IUriBuilder_RemoveProperties returned 0x%08x, expected 0x%08x with prop=%d.\n",
9118                     hr, S_OK, i);
9119             }
9120         }
9121
9122         /* Also doesn't accept anything that's outside the range of the
9123          * Uri_HAS flags.
9124          */
9125         hr = IUriBuilder_RemoveProperties(builder, (Uri_PROPERTY_DWORD_LAST+1) << 1);
9126         ok(hr == E_INVALIDARG, "Error: IUriBuilder_RemoveProperties returned 0x%08x, expected 0x%08x.\n",
9127             hr, E_INVALIDARG);
9128     }
9129     if(builder) IUriBuilder_Release(builder);
9130
9131     for(i = 0; i < sizeof(uri_builder_remove_tests)/sizeof(uri_builder_remove_tests[0]); ++i) {
9132         uri_builder_remove_test test = uri_builder_remove_tests[i];
9133         IUri *uri = NULL;
9134         LPWSTR uriW;
9135
9136         uriW = a2w(test.uri);
9137         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
9138         if(SUCCEEDED(hr)) {
9139             builder = NULL;
9140
9141             hr = pCreateIUriBuilder(uri, 0, 0, &builder);
9142             if(test.create_builder_todo) {
9143                 todo_wine {
9144                     ok(hr == test.create_builder_expected,
9145                         "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x on test %d.\n",
9146                         hr, test.create_builder_expected, i);
9147                 }
9148             } else {
9149                 ok(hr == test.create_builder_expected,
9150                     "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x on test %d.\n",
9151                     hr, test.create_builder_expected, i);
9152             }
9153             if(SUCCEEDED(hr)) {
9154                 hr = IUriBuilder_RemoveProperties(builder, test.remove_properties);
9155                 if(test.remove_todo) {
9156                     todo_wine {
9157                         ok(hr == test.remove_expected,
9158                             "Error: IUriBuilder_RemoveProperties returned 0x%08x, expected 0x%08x on test %d.\n",
9159                             hr, test.remove_expected, i);
9160                     }
9161                 } else {
9162                     ok(hr == test.remove_expected,
9163                         "Error: IUriBuilder returned 0x%08x, expected 0x%08x on test %d.\n",
9164                         hr, test.remove_expected, i);
9165                 }
9166                 if(SUCCEEDED(hr)) {
9167                     IUri *result = NULL;
9168
9169                     hr = IUriBuilder_CreateUri(builder, test.expected_flags, 0, 0, &result);
9170                     if(test.expected_todo) {
9171                         todo_wine {
9172                             ok(hr == test.expected_hres,
9173                                 "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x on test %d.\n",
9174                                 hr, test.expected_hres, i);
9175                         }
9176                     } else {
9177                         ok(hr == test.expected_hres,
9178                             "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x on test %d.\n",
9179                             hr, test.expected_hres, i);
9180                     }
9181                     if(SUCCEEDED(hr)) {
9182                         BSTR received = NULL;
9183
9184                         hr = IUri_GetAbsoluteUri(result, &received);
9185                         ok(!strcmp_aw(test.expected_uri, received),
9186                             "Error: Expected %s but got %s instead on test %d.\n",
9187                             test.expected_uri, wine_dbgstr_w(received), i);
9188                         SysFreeString(received);
9189                     }
9190                     if(result) IUri_Release(result);
9191                 }
9192             }
9193             if(builder) IUriBuilder_Release(builder);
9194         }
9195         if(uri) IUri_Release(uri);
9196         heap_free(uriW);
9197     }
9198 }
9199
9200 static void test_IUriBuilder_Misc(void) {
9201     HRESULT hr;
9202     IUri *uri;
9203
9204     hr = pCreateUri(http_urlW, 0, 0, &uri);
9205     if(SUCCEEDED(hr)) {
9206         IUriBuilder *builder;
9207
9208         hr = pCreateIUriBuilder(uri, 0, 0, &builder);
9209         ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9210         if(SUCCEEDED(hr)) {
9211             BOOL has = -1;
9212             DWORD port = -1;
9213
9214             hr = IUriBuilder_GetPort(builder, &has, &port);
9215             ok(hr == S_OK, "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9216             if(SUCCEEDED(hr)) {
9217                 /* 'has' will be set to FALSE, even though uri had a port. */
9218                 ok(has == FALSE, "Error: Expected 'has' to be FALSE, was %d instead.\n", has);
9219                 /* Still sets 'port' to 80. */
9220                 ok(port == 80, "Error: Expected the port to be 80, but, was %d instead.\n", port);
9221             }
9222         }
9223         if(builder) IUriBuilder_Release(builder);
9224     }
9225     if(uri) IUri_Release(uri);
9226 }
9227
9228 static void test_IUriBuilderFactory(void) {
9229     HRESULT hr;
9230     IUri *uri;
9231     IUriBuilderFactory *factory;
9232     IUriBuilder *builder;
9233
9234     hr = pCreateUri(http_urlW, 0, 0, &uri);
9235     ok(SUCCEEDED(hr), "Error: CreateUri returned 0x%08x.\n", hr);
9236     if(SUCCEEDED(hr)) {
9237         factory = NULL;
9238         hr = IUri_QueryInterface(uri, &IID_IUriBuilderFactory, (void**)&factory);
9239         ok(hr == S_OK, "Error: Expected S_OK, but got 0x%08x.\n", hr);
9240         ok(factory != NULL, "Error: Expected 'factory' to not be NULL.\n");
9241
9242         if(SUCCEEDED(hr)) {
9243             builder = (void*) 0xdeadbeef;
9244             hr = IUriBuilderFactory_CreateIUriBuilder(factory, 10, 0, &builder);
9245             ok(hr == E_INVALIDARG, "Error: CreateInitializedIUriBuilder returned 0x%08x, expected 0x%08x.\n",
9246                 hr, E_INVALIDARG);
9247             ok(!builder, "Error: Expected 'builder' to be NULL, but was %p.\n", builder);
9248
9249             builder = (void*) 0xdeadbeef;
9250             hr = IUriBuilderFactory_CreateIUriBuilder(factory, 0, 10, &builder);
9251             ok(hr == E_INVALIDARG, "Error: CreateInitializedIUriBuilder returned 0x%08x, expected 0x%08x.\n",
9252                 hr, E_INVALIDARG);
9253             ok(!builder, "Error: Expected 'builder' to be NULL, but was %p.\n", builder);
9254
9255             hr = IUriBuilderFactory_CreateIUriBuilder(factory, 0, 0, NULL);
9256             ok(hr == E_POINTER, "Error: CreateInitializedIUriBuilder returned 0x%08x, expected 0x%08x.\n",
9257                 hr, E_POINTER);
9258
9259             builder = NULL;
9260             hr = IUriBuilderFactory_CreateIUriBuilder(factory, 0, 0, &builder);
9261             ok(hr == S_OK, "Error: CreateInitializedIUriBuilder returned 0x%08x, expected 0x%08x.\n",
9262                 hr, S_OK);
9263             if(SUCCEEDED(hr)) {
9264                 IUri *tmp = (void*) 0xdeadbeef;
9265                 LPCWSTR result;
9266                 DWORD result_len;
9267
9268                 hr = IUriBuilder_GetIUri(builder, &tmp);
9269                 ok(hr == S_OK, "Error: GetIUri returned 0x%08x, expected 0x%08x.\n",
9270                     hr, S_OK);
9271                 ok(!tmp, "Error: Expected 'tmp' to be NULL, but was %p instead.\n", tmp);
9272
9273                 hr = IUriBuilder_GetHost(builder, &result_len, &result);
9274                 ok(hr == S_FALSE, "Error: GetHost returned 0x%08x, expected 0x%08x.\n",
9275                     hr, S_FALSE);
9276             }
9277             if(builder) IUriBuilder_Release(builder);
9278
9279             builder = (void*) 0xdeadbeef;
9280             hr = IUriBuilderFactory_CreateInitializedIUriBuilder(factory, 10, 0, &builder);
9281             ok(hr == E_INVALIDARG, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n",
9282                 hr, E_INVALIDARG);
9283             ok(!builder, "Error: Expected 'builder' to be NULL, but was %p.\n", builder);
9284
9285             builder = (void*) 0xdeadbeef;
9286             hr = IUriBuilderFactory_CreateInitializedIUriBuilder(factory, 0, 10, &builder);
9287             ok(hr == E_INVALIDARG, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n",
9288                 hr, E_INVALIDARG);
9289             ok(!builder, "Error: Expected 'builder' to be NULL, but was %p.\n", builder);
9290
9291             hr = IUriBuilderFactory_CreateInitializedIUriBuilder(factory, 0, 0, NULL);
9292             ok(hr == E_POINTER, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n",
9293                 hr, E_POINTER);
9294
9295             builder = NULL;
9296             hr = IUriBuilderFactory_CreateInitializedIUriBuilder(factory, 0, 0, &builder);
9297             ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n",
9298                 hr, S_OK);
9299             if(SUCCEEDED(hr)) {
9300                 IUri *tmp = NULL;
9301
9302                 hr = IUriBuilder_GetIUri(builder, &tmp);
9303                 ok(hr == S_OK, "Error: GetIUri return 0x%08x, expected 0x%08x.\n",
9304                     hr, S_OK);
9305                 ok(tmp == uri, "Error: Expected tmp to be %p, but was %p.\n", uri, tmp);
9306                 if(uri) IUri_Release(uri);
9307             }
9308             if(builder) IUriBuilder_Release(builder);
9309         }
9310         if(factory) IUriBuilderFactory_Release(factory);
9311     }
9312     if(uri) IUri_Release(uri);
9313 }
9314
9315 static void test_CoInternetCombineIUri(void) {
9316     HRESULT hr;
9317     IUri *base, *relative, *result;
9318     DWORD i;
9319
9320     base = NULL;
9321     hr = pCreateUri(http_urlW, 0, 0, &base);
9322     ok(SUCCEEDED(hr), "Error: Expected CreateUri to succeed, got 0x%08x.\n", hr);
9323     if(SUCCEEDED(hr)) {
9324         result = (void*) 0xdeadbeef;
9325         hr = pCoInternetCombineIUri(base, NULL, 0, &result, 0);
9326         ok(hr == E_INVALIDARG, "Error: CoInternetCombineIUri returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
9327         ok(!result, "Error: Expected 'result' to be NULL, was %p.\n", result);
9328     }
9329
9330     relative = NULL;
9331     hr = pCreateUri(http_urlW, 0, 0, &relative);
9332     ok(SUCCEEDED(hr), "Error: Expected CreateUri to succeed, got 0x%08x.\n", hr);
9333     if(SUCCEEDED(hr)) {
9334         result = (void*) 0xdeadbeef;
9335         hr = pCoInternetCombineIUri(NULL, relative, 0, &result, 0);
9336         ok(hr == E_INVALIDARG, "Error: CoInternetCombineIUri returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
9337         ok(!result, "Error: Expected 'result' to be NULL, was %p.\n", result);
9338     }
9339
9340     hr = pCoInternetCombineIUri(base, relative, 0, NULL, 0);
9341     ok(hr == E_INVALIDARG, "Error: CoInternetCombineIUri returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
9342
9343     if(base) IUri_Release(base);
9344     if(relative) IUri_Release(relative);
9345
9346     for(i = 0; i < sizeof(uri_combine_tests)/sizeof(uri_combine_tests[0]); ++i) {
9347         LPWSTR baseW = a2w(uri_combine_tests[i].base_uri);
9348
9349         hr = pCreateUri(baseW, uri_combine_tests[i].base_create_flags, 0, &base);
9350         ok(SUCCEEDED(hr), "Error: Expected CreateUri to succeed, got 0x%08x on uri_combine_tests[%d].\n", hr, i);
9351         if(SUCCEEDED(hr)) {
9352             LPWSTR relativeW = a2w(uri_combine_tests[i].relative_uri);
9353
9354             hr = pCreateUri(relativeW, uri_combine_tests[i].relative_create_flags, 0, &relative);
9355             ok(SUCCEEDED(hr), "Error: Expected CreateUri to succeed, got 0x%08x on uri_combine_tests[%d].\n", hr, i);
9356             if(SUCCEEDED(hr)) {
9357                 result = NULL;
9358
9359                 hr = pCoInternetCombineIUri(base, relative, uri_combine_tests[i].combine_flags, &result, 0);
9360                 if(uri_combine_tests[i].todo) {
9361                     todo_wine {
9362                         ok(hr == uri_combine_tests[i].expected,
9363                             "Error: CoInternetCombineIUri returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].\n",
9364                             hr, uri_combine_tests[i].expected, i);
9365                     }
9366                 } else {
9367                     ok(hr == uri_combine_tests[i].expected,
9368                         "Error: CoInternetCombineIUri returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].\n",
9369                         hr, uri_combine_tests[i]. expected, i);
9370                 }
9371                 if(SUCCEEDED(hr)) {
9372                     DWORD j;
9373
9374                     for(j = 0; j < sizeof(uri_combine_tests[i].str_props)/sizeof(uri_combine_tests[i].str_props[0]); ++j) {
9375                         uri_combine_str_property prop = uri_combine_tests[i].str_props[j];
9376                         BSTR received;
9377
9378                         hr = IUri_GetPropertyBSTR(result, j, &received, 0);
9379                         if(prop.todo) {
9380                             todo_wine {
9381                                 ok(hr == prop.expected,
9382                                     "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].str_props[%d].\n",
9383                                     hr, prop.expected, i, j);
9384                             }
9385                             todo_wine {
9386                                 ok(!strcmp_aw(prop.value, received) ||
9387                                    broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
9388                                     "Error: Expected %s but got %s instead on uri_combine_tests[%d].str_props[%d].\n",
9389                                     prop.value, wine_dbgstr_w(received), i, j);
9390                             }
9391                         } else {
9392                             ok(hr == prop.expected,
9393                                 "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].str_props[%d].\n",
9394                                 hr, prop.expected, i, j);
9395                             ok(!strcmp_aw(prop.value, received) ||
9396                                broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
9397                                 "Error: Expected %s but got %s instead on uri_combine_tests[%d].str_props[%d].\n",
9398                                 prop.value, wine_dbgstr_w(received), i, j);
9399                         }
9400                         SysFreeString(received);
9401                     }
9402
9403                     for(j = 0; j < sizeof(uri_combine_tests[i].dword_props)/sizeof(uri_combine_tests[i].dword_props[0]); ++j) {
9404                         uri_dword_property prop = uri_combine_tests[i].dword_props[j];
9405                         DWORD received;
9406
9407                         hr = IUri_GetPropertyDWORD(result, j+Uri_PROPERTY_DWORD_START, &received, 0);
9408                         if(prop.todo) {
9409                             todo_wine {
9410                                 ok(hr == prop.expected,
9411                                     "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].dword_props[%d].\n",
9412                                     hr, prop.expected, i, j);
9413                             }
9414                             todo_wine {
9415                                 ok(prop.value == received, "Error: Expected %d, but got %d instead on uri_combine_tests[%d].dword_props[%d].\n",
9416                                     prop.value, received, i, j);
9417                             }
9418                         } else {
9419                             ok(hr == prop.expected,
9420                                 "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].dword_props[%d].\n",
9421                                 hr, prop.expected, i, j);
9422                             ok(prop.value == received, "Error: Expected %d, but got %d instead on uri_combine_tests[%d].dword_props[%d].\n",
9423                                 prop.value, received, i, j);
9424                         }
9425                     }
9426                 }
9427                 if(result) IUri_Release(result);
9428             }
9429             if(relative) IUri_Release(relative);
9430             heap_free(relativeW);
9431         }
9432         if(base) IUri_Release(base);
9433         heap_free(baseW);
9434     }
9435 }
9436
9437 static HRESULT WINAPI InternetProtocolInfo_QueryInterface(IInternetProtocolInfo *iface,
9438                                                           REFIID riid, void **ppv)
9439 {
9440     ok(0, "unexpected call\n");
9441     return E_NOINTERFACE;
9442 }
9443
9444 static ULONG WINAPI InternetProtocolInfo_AddRef(IInternetProtocolInfo *iface)
9445 {
9446     return 2;
9447 }
9448
9449 static ULONG WINAPI InternetProtocolInfo_Release(IInternetProtocolInfo *iface)
9450 {
9451     return 1;
9452 }
9453
9454 static HRESULT WINAPI InternetProtocolInfo_ParseUrl(IInternetProtocolInfo *iface, LPCWSTR pwzUrl,
9455         PARSEACTION ParseAction, DWORD dwParseFlags, LPWSTR pwzResult, DWORD cchResult,
9456         DWORD *pcchResult, DWORD dwReserved)
9457 {
9458     CHECK_EXPECT(ParseUrl);
9459     ok(!lstrcmpW(pwzUrl, parse_urlW), "Error: Expected %s, but got %s instead.\n",
9460         wine_dbgstr_w(parse_urlW), wine_dbgstr_w(pwzUrl));
9461     ok(ParseAction == parse_action, "Error: Expected %d, but got %d.\n", parse_action, ParseAction);
9462     ok(dwParseFlags == parse_flags, "Error: Expected 0x%08x, but got 0x%08x.\n", parse_flags, dwParseFlags);
9463     ok(cchResult == 200, "Error: Got %d.\n", cchResult);
9464
9465     memcpy(pwzResult, parse_resultW, sizeof(parse_resultW));
9466     *pcchResult = lstrlenW(parse_resultW);
9467
9468     return S_OK;
9469 }
9470
9471 static HRESULT WINAPI InternetProtocolInfo_CombineUrl(IInternetProtocolInfo *iface,
9472         LPCWSTR pwzBaseUrl, LPCWSTR pwzRelativeUrl, DWORD dwCombineFlags,
9473         LPWSTR pwzResult, DWORD cchResult, DWORD *pcchResult, DWORD dwReserved)
9474 {
9475     CHECK_EXPECT(CombineUrl);
9476     ok(!lstrcmpW(pwzBaseUrl, combine_baseW), "Error: Expected %s, but got %s instead.\n",
9477         wine_dbgstr_w(combine_baseW), wine_dbgstr_w(pwzBaseUrl));
9478     ok(!lstrcmpW(pwzRelativeUrl, combine_relativeW), "Error: Expected %s, but got %s instead.\n",
9479         wine_dbgstr_w(combine_relativeW), wine_dbgstr_w(pwzRelativeUrl));
9480     ok(dwCombineFlags == (URL_DONT_SIMPLIFY|URL_FILE_USE_PATHURL|URL_DONT_UNESCAPE_EXTRA_INFO),
9481         "Error: Expected 0, but got 0x%08x.\n", dwCombineFlags);
9482     ok(cchResult == INTERNET_MAX_URL_LENGTH+1, "Error: Got %d.\n", cchResult);
9483
9484     memcpy(pwzResult, combine_resultW, sizeof(combine_resultW));
9485     *pcchResult = lstrlenW(combine_resultW);
9486
9487     return S_OK;
9488 }
9489
9490 static HRESULT WINAPI InternetProtocolInfo_CompareUrl(IInternetProtocolInfo *iface,
9491         LPCWSTR pwzUrl1, LPCWSTR pwzUrl2, DWORD dwCompareFlags)
9492 {
9493     ok(0, "unexpected call\n");
9494     return E_NOTIMPL;
9495 }
9496
9497 static HRESULT WINAPI InternetProtocolInfo_QueryInfo(IInternetProtocolInfo *iface,
9498         LPCWSTR pwzUrl, QUERYOPTION OueryOption, DWORD dwQueryFlags, LPVOID pBuffer,
9499         DWORD cbBuffer, DWORD *pcbBuf, DWORD dwReserved)
9500 {
9501     ok(0, "unexpected call\n");
9502     return E_NOTIMPL;
9503 }
9504
9505 static const IInternetProtocolInfoVtbl InternetProtocolInfoVtbl = {
9506     InternetProtocolInfo_QueryInterface,
9507     InternetProtocolInfo_AddRef,
9508     InternetProtocolInfo_Release,
9509     InternetProtocolInfo_ParseUrl,
9510     InternetProtocolInfo_CombineUrl,
9511     InternetProtocolInfo_CompareUrl,
9512     InternetProtocolInfo_QueryInfo
9513 };
9514
9515 static IInternetProtocolInfo protocol_info = { &InternetProtocolInfoVtbl };
9516
9517 static HRESULT WINAPI ClassFactory_QueryInterface(IClassFactory *iface, REFIID riid, void **ppv)
9518 {
9519     if(IsEqualGUID(&IID_IInternetProtocolInfo, riid)) {
9520         *ppv = &protocol_info;
9521         return S_OK;
9522     }
9523
9524     ok(0, "unexpected call\n");
9525     return E_NOINTERFACE;
9526 }
9527
9528 static ULONG WINAPI ClassFactory_AddRef(IClassFactory *iface)
9529 {
9530     return 2;
9531 }
9532
9533 static ULONG WINAPI ClassFactory_Release(IClassFactory *iface)
9534 {
9535     return 1;
9536 }
9537
9538 static HRESULT WINAPI ClassFactory_CreateInstance(IClassFactory *iface, IUnknown *pOuter,
9539                                         REFIID riid, void **ppv)
9540 {
9541     ok(0, "unexpected call\n");
9542     return E_NOTIMPL;
9543 }
9544
9545 static HRESULT WINAPI ClassFactory_LockServer(IClassFactory *iface, BOOL dolock)
9546 {
9547     ok(0, "unexpected call\n");
9548     return S_OK;
9549 }
9550
9551 static const IClassFactoryVtbl ClassFactoryVtbl = {
9552     ClassFactory_QueryInterface,
9553     ClassFactory_AddRef,
9554     ClassFactory_Release,
9555     ClassFactory_CreateInstance,
9556     ClassFactory_LockServer
9557 };
9558
9559 static IClassFactory protocol_cf = { &ClassFactoryVtbl };
9560
9561 static void register_protocols(void)
9562 {
9563     IInternetSession *session;
9564     HRESULT hres;
9565
9566     hres = pCoInternetGetSession(0, &session, 0);
9567     ok(hres == S_OK, "CoInternetGetSession failed: %08x\n", hres);
9568     if(FAILED(hres))
9569         return;
9570
9571     hres = IInternetSession_RegisterNameSpace(session, &protocol_cf, &IID_NULL,
9572             winetestW, 0, NULL, 0);
9573     ok(hres == S_OK, "RegisterNameSpace failed: %08x\n", hres);
9574
9575     IInternetSession_Release(session);
9576 }
9577
9578 static void unregister_protocols(void) {
9579     IInternetSession *session;
9580     HRESULT hr;
9581
9582     hr = pCoInternetGetSession(0, &session, 0);
9583     ok(hr == S_OK, "CoInternetGetSession failed: 0x%08x\n", hr);
9584     if(FAILED(hr))
9585         return;
9586
9587     hr = IInternetSession_UnregisterNameSpace(session, &protocol_cf, winetestW);
9588     ok(hr == S_OK, "UnregisterNameSpace failed: 0x%08x\n", hr);
9589
9590     IInternetSession_Release(session);
9591 }
9592
9593 static void test_CoInternetCombineIUri_Pluggable(void) {
9594     HRESULT hr;
9595     IUri *base = NULL;
9596
9597     hr = pCreateUri(combine_baseW, 0, 0, &base);
9598     ok(SUCCEEDED(hr), "Error: CreateUri returned 0x%08x.\n", hr);
9599     if(SUCCEEDED(hr)) {
9600         IUri *relative = NULL;
9601
9602         hr = pCreateUri(combine_relativeW, Uri_CREATE_ALLOW_RELATIVE, 0, &relative);
9603         ok(SUCCEEDED(hr), "Error: CreateUri returned 0x%08x.\n", hr);
9604         if(SUCCEEDED(hr)) {
9605             IUri *result = NULL;
9606
9607             SET_EXPECT(CombineUrl);
9608
9609             hr = pCoInternetCombineIUri(base, relative, URL_DONT_SIMPLIFY|URL_FILE_USE_PATHURL|URL_DONT_UNESCAPE_EXTRA_INFO,
9610                                         &result, 0);
9611             ok(hr == S_OK, "Error: CoInternetCombineIUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9612
9613             CHECK_CALLED(CombineUrl);
9614
9615             if(SUCCEEDED(hr)) {
9616                 BSTR received = NULL;
9617                 hr = IUri_GetAbsoluteUri(result, &received);
9618                 ok(hr == S_OK, "Error: Expected S_OK, but got 0x%08x instead.\n", hr);
9619                 if(SUCCEEDED(hr)) {
9620                     ok(!lstrcmpW(combine_resultW, received), "Error: Expected %s, but got %s.\n",
9621                         wine_dbgstr_w(combine_resultW), wine_dbgstr_w(received));
9622                 }
9623                 SysFreeString(received);
9624             }
9625             if(result) IUri_Release(result);
9626         }
9627         if(relative) IUri_Release(relative);
9628     }
9629     if(base) IUri_Release(base);
9630 }
9631
9632 static void test_CoInternetCombineUrlEx(void) {
9633     HRESULT hr;
9634     IUri *base, *result;
9635     DWORD i;
9636
9637     base = NULL;
9638     hr = pCreateUri(http_urlW, 0, 0, &base);
9639     ok(SUCCEEDED(hr), "Error: CreateUri returned 0x%08x.\n", hr);
9640     if(SUCCEEDED(hr)) {
9641         result = (void*) 0xdeadbeef;
9642         hr = pCoInternetCombineUrlEx(base, NULL, 0, &result, 0);
9643         ok(hr == E_UNEXPECTED, "Error: CoInternetCombineUrlEx returned 0x%08x, expected 0x%08x.\n",
9644             hr, E_UNEXPECTED);
9645         ok(!result, "Error: Expected 'result' to be NULL was %p instead.\n", result);
9646     }
9647
9648     result = (void*) 0xdeadbeef;
9649     hr = pCoInternetCombineUrlEx(NULL, http_urlW, 0, &result, 0);
9650     ok(hr == E_INVALIDARG, "Error: CoInternetCombineUrlEx returned 0x%08x, expected 0x%08x.\n",
9651         hr, E_INVALIDARG);
9652     ok(!result, "Error: Expected 'result' to be NULL, but was %p instead.\n", result);
9653
9654     result = (void*) 0xdeadbeef;
9655     hr = pCoInternetCombineUrlEx(NULL, NULL, 0, &result, 0);
9656     ok(hr == E_UNEXPECTED, "Error: CoInternetCombineUrlEx returned 0x%08x, expected 0x%08x.\n",
9657         hr, E_UNEXPECTED);
9658     ok(!result, "Error: Expected 'result' to be NULL, but was %p instead.\n", result);
9659
9660     hr = pCoInternetCombineUrlEx(base, http_urlW, 0, NULL, 0);
9661     ok(hr == E_POINTER, "Error: CoInternetCombineUrlEx returned 0x%08x, expected 0x%08x.\n",
9662         hr, E_POINTER);
9663     if(base) IUri_Release(base);
9664
9665     for(i = 0; i < sizeof(uri_combine_tests)/sizeof(uri_combine_tests[0]); ++i) {
9666         LPWSTR baseW = a2w(uri_combine_tests[i].base_uri);
9667
9668         hr = pCreateUri(baseW, uri_combine_tests[i].base_create_flags, 0, &base);
9669         ok(SUCCEEDED(hr), "Error: CreateUri returned 0x%08x on uri_combine_tests[%d].\n", hr, i);
9670         if(SUCCEEDED(hr)) {
9671             LPWSTR relativeW = a2w(uri_combine_tests[i].relative_uri);
9672
9673             hr = pCoInternetCombineUrlEx(base, relativeW, uri_combine_tests[i].combine_flags,
9674                                          &result, 0);
9675             if(uri_combine_tests[i].todo) {
9676                 todo_wine {
9677                     ok(hr == uri_combine_tests[i].expected,
9678                         "Error: CoInternetCombineUrlEx returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].\n",
9679                         hr, uri_combine_tests[i].expected, i);
9680                 }
9681             } else {
9682                 ok(hr == uri_combine_tests[i].expected,
9683                     "Error: CoInternetCombineUrlEx returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].\n",
9684                     hr, uri_combine_tests[i]. expected, i);
9685             }
9686             if(SUCCEEDED(hr)) {
9687                 DWORD j;
9688
9689                 for(j = 0; j < sizeof(uri_combine_tests[i].str_props)/sizeof(uri_combine_tests[i].str_props[0]); ++j) {
9690                     uri_combine_str_property prop = uri_combine_tests[i].str_props[j];
9691                     BSTR received;
9692                     LPCSTR value = (prop.value_ex) ? prop.value_ex : prop.value;
9693
9694                     hr = IUri_GetPropertyBSTR(result, j, &received, 0);
9695                     if(prop.todo) {
9696                         todo_wine {
9697                             ok(hr == prop.expected,
9698                                 "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].str_props[%d].\n",
9699                                 hr, prop.expected, i, j);
9700                         }
9701                         todo_wine {
9702                             ok(!strcmp_aw(value, received) ||
9703                                broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
9704                                 "Error: Expected %s but got %s instead on uri_combine_tests[%d].str_props[%d].\n",
9705                                 value, wine_dbgstr_w(received), i, j);
9706                         }
9707                     } else {
9708                         ok(hr == prop.expected,
9709                             "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].str_props[%d].\n",
9710                             hr, prop.expected, i, j);
9711                         ok(!strcmp_aw(value, received) ||
9712                            broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
9713                             "Error: Expected %s but got %s instead on uri_combine_tests[%d].str_props[%d].\n",
9714                             value, wine_dbgstr_w(received), i, j);
9715                     }
9716                     SysFreeString(received);
9717                 }
9718
9719                 for(j = 0; j < sizeof(uri_combine_tests[i].dword_props)/sizeof(uri_combine_tests[i].dword_props[0]); ++j) {
9720                     uri_dword_property prop = uri_combine_tests[i].dword_props[j];
9721                     DWORD received;
9722
9723                     hr = IUri_GetPropertyDWORD(result, j+Uri_PROPERTY_DWORD_START, &received, 0);
9724                     if(prop.todo) {
9725                         todo_wine {
9726                             ok(hr == prop.expected,
9727                                 "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].dword_props[%d].\n",
9728                                 hr, prop.expected, i, j);
9729                         }
9730                         todo_wine {
9731                             ok(prop.value == received, "Error: Expected %d, but got %d instead on uri_combine_tests[%d].dword_props[%d].\n",
9732                                 prop.value, received, i, j);
9733                         }
9734                     } else {
9735                         ok(hr == prop.expected,
9736                             "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].dword_props[%d].\n",
9737                             hr, prop.expected, i, j);
9738                         ok(prop.value == received, "Error: Expected %d, but got %d instead on uri_combine_tests[%d].dword_props[%d].\n",
9739                             prop.value, received, i, j);
9740                     }
9741                 }
9742             }
9743             if(result) IUri_Release(result);
9744             heap_free(relativeW);
9745         }
9746         if(base) IUri_Release(base);
9747         heap_free(baseW);
9748     }
9749 }
9750
9751 static void test_CoInternetCombineUrlEx_Pluggable(void) {
9752     HRESULT hr;
9753     IUri *base = NULL;
9754
9755     hr = pCreateUri(combine_baseW, 0, 0, &base);
9756     ok(SUCCEEDED(hr), "Error: CreateUri returned 0x%08x.\n", hr);
9757     if(SUCCEEDED(hr)) {
9758         IUri *result = NULL;
9759
9760         SET_EXPECT(CombineUrl);
9761
9762         hr = pCoInternetCombineUrlEx(base, combine_relativeW, URL_DONT_SIMPLIFY|URL_FILE_USE_PATHURL|URL_DONT_UNESCAPE_EXTRA_INFO,
9763                                      &result, 0);
9764         ok(hr == S_OK, "Error: CoInternetCombineUrlEx returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9765
9766         CHECK_CALLED(CombineUrl);
9767
9768         if(SUCCEEDED(hr)) {
9769             BSTR received = NULL;
9770             hr = IUri_GetAbsoluteUri(result, &received);
9771             ok(hr == S_OK, "Error: Expected S_OK, but got 0x%08x instead.\n", hr);
9772             if(SUCCEEDED(hr)) {
9773                 ok(!lstrcmpW(combine_resultW, received), "Error: Expected %s, but got %s.\n",
9774                     wine_dbgstr_w(combine_resultW), wine_dbgstr_w(received));
9775             }
9776             SysFreeString(received);
9777         }
9778         if(result) IUri_Release(result);
9779     }
9780     if(base) IUri_Release(base);
9781 }
9782
9783 static void test_CoInternetParseIUri_InvalidArgs(void) {
9784     HRESULT hr;
9785     IUri *uri = NULL;
9786     WCHAR tmp[3];
9787     DWORD result = -1;
9788
9789     hr = pCoInternetParseIUri(NULL, PARSE_CANONICALIZE, 0, tmp, 3, &result, 0);
9790     ok(hr == E_INVALIDARG, "Error: CoInternetParseIUri returned 0x%08x, expected 0x%08x.\n",
9791         hr, E_INVALIDARG);
9792     ok(!result, "Error: Expected 'result' to be 0, but was %d.\n", result);
9793
9794     hr = pCreateUri(http_urlW, 0, 0, &uri);
9795     ok(SUCCEEDED(hr), "Error: CreateUri returned 0x%08x.\n", hr);
9796     if(SUCCEEDED(hr)) {
9797         DWORD expected_len;
9798
9799         result = -1;
9800         hr = pCoInternetParseIUri(uri, PARSE_CANONICALIZE, 0, NULL, 0, &result, 0);
9801         ok(hr == E_INVALIDARG, "Error: CoInternetParseIUri returned 0x%08x, expected 0x%08x.\n",
9802             hr, E_INVALIDARG);
9803         ok(!result, "Error: Expected 'result' to be 0, but was %d.\n", result);
9804
9805         hr = pCoInternetParseIUri(uri, PARSE_CANONICALIZE, 0, tmp, 3, NULL, 0);
9806         ok(hr == E_POINTER, "Error: CoInternetParseIUri returned 0x%08x, expected 0x%08x.\n",
9807             hr, E_POINTER);
9808
9809         result = -1;
9810         hr = pCoInternetParseIUri(uri, PARSE_SECURITY_URL, 0, tmp, 3, &result, 0);
9811         ok(hr == E_FAIL, "Error: CoInternetParseIUri returned 0x%08x expected 0x%08x.\n",
9812             hr, E_FAIL);
9813         ok(!result, "Error: Expected 'result' to be 0, but was %d.\n", result);
9814
9815         result = -1;
9816         hr = pCoInternetParseIUri(uri, PARSE_MIME, 0, tmp, 3, &result, 0);
9817         ok(hr == E_FAIL, "Error: CoInternetParseIUri returned 0x%08x, expected 0x%08x.\n",
9818             hr, E_FAIL);
9819         ok(!result, "Error: Expected 'result' to be 0, but was %d.\n", result);
9820
9821         result = -1;
9822         hr = pCoInternetParseIUri(uri, PARSE_SERVER, 0, tmp, 3, &result, 0);
9823         ok(hr == E_FAIL, "Error: CoInternetParseIUri returned 0x%08x, expected 0x%08x.\n",
9824             hr, E_FAIL);
9825         ok(!result, "Error: Expected 'result' to be 0, but was %d.\n", result);
9826
9827         result = -1;
9828         hr = pCoInternetParseIUri(uri, PARSE_SECURITY_DOMAIN, 0, tmp, 3, &result, 0);
9829         ok(hr == E_FAIL, "Error: CoInternetParseIUri returned 0x%08x, expected 0x%08x.\n",
9830             hr, E_FAIL);
9831         ok(!result, "Error: Expected 'result' to be 0, but was %d.\n", result);
9832
9833         expected_len = lstrlenW(http_urlW);
9834         result = -1;
9835         hr = pCoInternetParseIUri(uri, PARSE_CANONICALIZE, 0, tmp, 3, &result, 0);
9836         ok(hr == STRSAFE_E_INSUFFICIENT_BUFFER,
9837             "Error: CoInternetParseIUri returned 0x%08x, expected 0x%08x.\n",
9838             hr, STRSAFE_E_INSUFFICIENT_BUFFER);
9839         ok(result == expected_len, "Error: Expected 'result' to be %d, but was %d instead.\n",
9840             expected_len, result);
9841     }
9842     if(uri) IUri_Release(uri);
9843 }
9844
9845 static void test_CoInternetParseIUri(void) {
9846     DWORD i;
9847
9848     for(i = 0; i < sizeof(uri_parse_tests)/sizeof(uri_parse_tests[0]); ++i) {
9849         HRESULT hr;
9850         IUri *uri;
9851         LPWSTR uriW;
9852         uri_parse_test test = uri_parse_tests[i];
9853
9854         uriW = a2w(test.uri);
9855         hr = pCreateUri(uriW, test.uri_flags, 0, &uri);
9856         ok(SUCCEEDED(hr), "Error: CreateUri returned 0x%08x on uri_parse_tests[%d].\n", hr, i);
9857         if(SUCCEEDED(hr)) {
9858             WCHAR result[INTERNET_MAX_URL_LENGTH+1];
9859             DWORD result_len = -1;
9860
9861             hr = pCoInternetParseIUri(uri, test.action, test.flags, result, INTERNET_MAX_URL_LENGTH+1, &result_len, 0);
9862             if(test.todo) {
9863                 todo_wine {
9864                     ok(hr == test.expected,
9865                         "Error: CoInternetParseIUri returned 0x%08x, expected 0x%08x on uri_parse_tests[%d].\n",
9866                         hr, test.expected, i);
9867                 }
9868             } else {
9869                 ok(hr == test.expected,
9870                     "Error: CoInternetParseIUri returned 0x%08x, expected 0x%08x on uri_parse_tests[%d].\n",
9871                     hr, test.expected, i);
9872             }
9873             if(SUCCEEDED(hr)) {
9874                 DWORD len = lstrlenA(test.property);
9875                 ok(!strcmp_aw(test.property, result),
9876                     "Error: Expected %s but got %s instead on uri_parse_tests[%d].\n",
9877                     test.property, wine_dbgstr_w(result), i);
9878                 ok(len == result_len,
9879                     "Error: Expected %d, but got %d instead on uri_parse_tests[%d].\n",
9880                     len, result_len, i);
9881             } else {
9882                 ok(!result_len,
9883                     "Error: Expected 'result_len' to be 0, but was %d on uri_parse_tests[%d].\n",
9884                     result_len, i);
9885             }
9886         }
9887         if(uri) IUri_Release(uri);
9888         heap_free(uriW);
9889     }
9890 }
9891
9892 static void test_CoInternetParseIUri_Pluggable(void) {
9893     HRESULT hr;
9894     IUri *uri = NULL;
9895
9896     hr = pCreateUri(parse_urlW, 0, 0, &uri);
9897     ok(SUCCEEDED(hr), "Error: Expected CreateUri to succeed, but got 0x%08x.\n", hr);
9898     if(SUCCEEDED(hr)) {
9899         WCHAR result[200];
9900         DWORD result_len;
9901
9902         SET_EXPECT(ParseUrl);
9903
9904         parse_action = PARSE_CANONICALIZE;
9905         parse_flags = URL_UNESCAPE|URL_ESCAPE_UNSAFE;
9906
9907         hr = pCoInternetParseIUri(uri, parse_action, parse_flags, result, 200, &result_len, 0);
9908         ok(hr == S_OK, "Error: CoInternetParseIUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9909
9910         CHECK_CALLED(ParseUrl);
9911
9912         if(SUCCEEDED(hr)) {
9913             ok(result_len == lstrlenW(parse_resultW), "Error: Expected %d, but got %d.\n",
9914                 lstrlenW(parse_resultW), result_len);
9915             ok(!lstrcmpW(result, parse_resultW), "Error: Expected %s, but got %s.\n",
9916                 wine_dbgstr_w(parse_resultW), wine_dbgstr_w(result));
9917         }
9918     }
9919     if(uri) IUri_Release(uri);
9920 }
9921
9922 START_TEST(uri) {
9923     HMODULE hurlmon;
9924
9925     hurlmon = GetModuleHandle("urlmon.dll");
9926     pCoInternetGetSession = (void*) GetProcAddress(hurlmon, "CoInternetGetSession");
9927     pCreateUri = (void*) GetProcAddress(hurlmon, "CreateUri");
9928     pCreateUriWithFragment = (void*) GetProcAddress(hurlmon, "CreateUriWithFragment");
9929     pCreateIUriBuilder = (void*) GetProcAddress(hurlmon, "CreateIUriBuilder");
9930     pCoInternetCombineIUri = (void*) GetProcAddress(hurlmon, "CoInternetCombineIUri");
9931     pCoInternetCombineUrlEx = (void*) GetProcAddress(hurlmon, "CoInternetCombineUrlEx");
9932     pCoInternetParseIUri = (void*) GetProcAddress(hurlmon, "CoInternetParseIUri");
9933
9934     if(!pCreateUri) {
9935         win_skip("CreateUri is not present, skipping tests.\n");
9936         return;
9937     }
9938
9939     trace("test CreateUri invalid flags...\n");
9940     test_CreateUri_InvalidFlags();
9941
9942     trace("test CreateUri invalid args...\n");
9943     test_CreateUri_InvalidArgs();
9944
9945     trace("test CreateUri invalid URIs...\n");
9946     test_CreateUri_InvalidUri();
9947
9948     trace("test IUri_GetPropertyBSTR...\n");
9949     test_IUri_GetPropertyBSTR();
9950
9951     trace("test IUri_GetPropertyDWORD...\n");
9952     test_IUri_GetPropertyDWORD();
9953
9954     trace("test IUri_GetStrProperties...\n");
9955     test_IUri_GetStrProperties();
9956
9957     trace("test IUri_GetDwordProperties...\n");
9958     test_IUri_GetDwordProperties();
9959
9960     trace("test IUri_GetPropertyLength...\n");
9961     test_IUri_GetPropertyLength();
9962
9963     trace("test IUri_GetProperties...\n");
9964     test_IUri_GetProperties();
9965
9966     trace("test IUri_HasProperty...\n");
9967     test_IUri_HasProperty();
9968
9969     trace("test IUri_IsEqual...\n");
9970     test_IUri_IsEqual();
9971
9972     trace("test CreateUriWithFragment invalid args...\n");
9973     test_CreateUriWithFragment_InvalidArgs();
9974
9975     trace("test CreateUriWithFragment invalid flags...\n");
9976     test_CreateUriWithFragment_InvalidFlags();
9977
9978     trace("test CreateUriWithFragment...\n");
9979     test_CreateUriWithFragment();
9980
9981     trace("test CreateIUriBuilder...\n");
9982     test_CreateIUriBuilder();
9983
9984     trace("test IUriBuilder_CreateInvalidArgs...\n");
9985     test_IUriBuilder_CreateInvalidArgs();
9986
9987     trace("test IUriBuilder...\n");
9988     test_IUriBuilder();
9989
9990     trace("test IUriBuilder_GetInvalidArgs...\n");
9991     test_IUriBuilder_GetInvalidArgs();
9992
9993     trace("test IUriBuilder_HasBeenModified...\n");
9994     test_IUriBuilder_HasBeenModified();
9995
9996     trace("test IUriBuilder_IUriProperty...\n");
9997     test_IUriBuilder_IUriProperty();
9998
9999     trace("test IUriBuilder_RemoveProperties...\n");
10000     test_IUriBuilder_RemoveProperties();
10001
10002     trace("test IUriBuilder miscellaneous...\n");
10003     test_IUriBuilder_Misc();
10004
10005     trace("test IUriBuilderFactory...\n");
10006     test_IUriBuilderFactory();
10007
10008     trace("test CoInternetCombineIUri...\n");
10009     test_CoInternetCombineIUri();
10010
10011     trace("test CoInternetCombineUrlEx...\n");
10012     test_CoInternetCombineUrlEx();
10013
10014     trace("test CoInternetParseIUri Invalid Args...\n");
10015     test_CoInternetParseIUri_InvalidArgs();
10016
10017     trace("test CoInternetParseIUri...\n");
10018     test_CoInternetParseIUri();
10019
10020     register_protocols();
10021
10022     trace("test CoInternetCombineIUri pluggable...\n");
10023     test_CoInternetCombineIUri_Pluggable();
10024
10025     trace("test CoInternetCombineUrlEx Pluggable...\n");
10026     test_CoInternetCombineUrlEx_Pluggable();
10027
10028     trace("test CoInternetParseIUri pluggable...\n");
10029     test_CoInternetParseIUri_Pluggable();
10030
10031     unregister_protocols();
10032 }