d3d9: Implement IDirect3DVertexBuffer9 private data handling on top of wined3d_resource.
[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     /* Make sure already percent encoded characters don't get unencoded. */
792     {   "ftp://\"%20\"weird@ftp.google.com/\"%20\"weird", Uri_CREATE_NO_ENCODE_FORBIDDEN_CHARACTERS, S_OK, FALSE,
793         {
794             {"ftp://\"%20\"weird@ftp.google.com/\"%20\"weird",S_OK,FALSE},
795             {"\"%20\"weird@ftp.google.com",S_OK,FALSE},
796             {"ftp://ftp.google.com/\"%20\"weird",S_OK,FALSE},
797             {"google.com",S_OK,FALSE},
798             {"",S_FALSE,FALSE},
799             {"",S_FALSE,FALSE},
800             {"ftp.google.com",S_OK,FALSE},
801             {"",S_FALSE,FALSE},
802             {"/\"%20\"weird",S_OK,FALSE},
803             {"/\"%20\"weird",S_OK,FALSE},
804             {"",S_FALSE,FALSE},
805             {"ftp://\"%20\"weird@ftp.google.com/\"%20\"weird",S_OK,FALSE},
806             {"ftp",S_OK,FALSE},
807             {"\"%20\"weird",S_OK,FALSE},
808             {"\"%20\"weird",S_OK,FALSE}
809         },
810         {
811             {Uri_HOST_DNS,S_OK,FALSE},
812             {21,S_OK,FALSE},
813             {URL_SCHEME_FTP,S_OK,FALSE},
814             {URLZONE_INVALID,E_NOTIMPL,FALSE}
815         }
816     },
817     /* Allowed to have invalid % encoded because its an unknown scheme type. */
818     {   "zip://%xy:word@winehq.org/", 0, S_OK, FALSE,
819         {
820             {"zip://%xy:word@winehq.org/",S_OK,FALSE},
821             {"%xy:word@winehq.org",S_OK,FALSE},
822             {"zip://%xy:word@winehq.org/",S_OK,FALSE},
823             {"winehq.org",S_OK,FALSE},
824             {"",S_FALSE,FALSE},
825             {"",S_FALSE,FALSE},
826             {"winehq.org",S_OK,FALSE},
827             {"word",S_OK,FALSE},
828             {"/",S_OK,FALSE},
829             {"/",S_OK,FALSE},
830             {"",S_FALSE,FALSE},
831             {"zip://%xy:word@winehq.org/",S_OK,FALSE},
832             {"zip",S_OK,FALSE},
833             {"%xy:word",S_OK,FALSE},
834             {"%xy",S_OK,FALSE}
835         },
836         {
837             {Uri_HOST_DNS,S_OK,FALSE},
838             {0,S_FALSE,FALSE},
839             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
840             {URLZONE_INVALID,E_NOTIMPL,FALSE}
841         }
842     },
843     /* Unreserved, percent encoded characters aren't decoded in the userinfo becuase the scheme
844      * isn't known.
845      */
846     {   "zip://%2E:%52%53ord@winehq.org/", 0, S_OK, FALSE,
847         {
848             {"zip://%2E:%52%53ord@winehq.org/",S_OK,FALSE},
849             {"%2E:%52%53ord@winehq.org",S_OK,FALSE},
850             {"zip://%2E:%52%53ord@winehq.org/",S_OK,FALSE},
851             {"winehq.org",S_OK,FALSE},
852             {"",S_FALSE,FALSE},
853             {"",S_FALSE,FALSE},
854             {"winehq.org",S_OK,FALSE},
855             {"%52%53ord",S_OK,FALSE},
856             {"/",S_OK,FALSE},
857             {"/",S_OK,FALSE},
858             {"",S_FALSE,FALSE},
859             {"zip://%2E:%52%53ord@winehq.org/",S_OK,FALSE},
860             {"zip",S_OK,FALSE},
861             {"%2E:%52%53ord",S_OK,FALSE},
862             {"%2E",S_OK,FALSE}
863         },
864         {
865             {Uri_HOST_DNS,S_OK,FALSE},
866             {0,S_FALSE,FALSE},
867             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
868             {URLZONE_INVALID,E_NOTIMPL,FALSE}
869         }
870     },
871     {   "ftp://[](),'test':word@winehq.org/", 0, S_OK, FALSE,
872         {
873             {"ftp://[](),'test':word@winehq.org/",S_OK,FALSE},
874             {"[](),'test':word@winehq.org",S_OK,FALSE},
875             {"ftp://winehq.org/",S_OK,FALSE},
876             {"winehq.org",S_OK,FALSE},
877             {"",S_FALSE,FALSE},
878             {"",S_FALSE,FALSE},
879             {"winehq.org",S_OK,FALSE},
880             {"word",S_OK,FALSE},
881             {"/",S_OK,FALSE},
882             {"/",S_OK,FALSE},
883             {"",S_FALSE,FALSE},
884             {"ftp://[](),'test':word@winehq.org/",S_OK,FALSE},
885             {"ftp",S_OK,FALSE},
886             {"[](),'test':word",S_OK,FALSE},
887             {"[](),'test'",S_OK,FALSE}
888         },
889         {
890             {Uri_HOST_DNS,S_OK,FALSE},
891             {21,S_OK,FALSE},
892             {URL_SCHEME_FTP,S_OK,FALSE},
893             {URLZONE_INVALID,E_NOTIMPL,FALSE}
894         }
895     },
896     {   "ftp://test?:word@winehq.org/", 0, S_OK, FALSE,
897         {
898             {"ftp://test/?:word@winehq.org/",S_OK,FALSE},
899             {"test",S_OK,FALSE},
900             {"ftp://test/?:word@winehq.org/",S_OK,FALSE},
901             {"",S_FALSE,FALSE},
902             {"",S_FALSE,FALSE},
903             {"",S_FALSE,FALSE},
904             {"test",S_OK,FALSE},
905             {"",S_FALSE,FALSE},
906             {"/",S_OK,FALSE},
907             {"/?:word@winehq.org/",S_OK,FALSE},
908             {"?:word@winehq.org/",S_OK,FALSE},
909             {"ftp://test?:word@winehq.org/",S_OK,FALSE},
910             {"ftp",S_OK,FALSE},
911             {"",S_FALSE,FALSE},
912             {"",S_FALSE,FALSE}
913         },
914         {
915             {Uri_HOST_DNS,S_OK,FALSE},
916             {21,S_OK,FALSE},
917             {URL_SCHEME_FTP,S_OK,FALSE},
918             {URLZONE_INVALID,E_NOTIMPL,FALSE}
919         }
920     },
921     {   "ftp://test#:word@winehq.org/", 0, S_OK, FALSE,
922         {
923             {"ftp://test/#:word@winehq.org/",S_OK,FALSE},
924             {"test",S_OK,FALSE},
925             {"ftp://test/#:word@winehq.org/",S_OK,FALSE},
926             {"",S_FALSE,FALSE},
927             {"",S_FALSE,FALSE},
928             {"#:word@winehq.org/",S_OK,FALSE},
929             {"test",S_OK,FALSE},
930             {"",S_FALSE,FALSE},
931             {"/",S_OK,FALSE},
932             {"/",S_OK,FALSE},
933             {"",S_FALSE,FALSE},
934             {"ftp://test#:word@winehq.org/",S_OK,FALSE},
935             {"ftp",S_OK,FALSE},
936             {"",S_FALSE,FALSE},
937             {"",S_FALSE,FALSE}
938         },
939         {
940             {Uri_HOST_DNS,S_OK,FALSE},
941             {21,S_OK,FALSE},
942             {URL_SCHEME_FTP,S_OK,FALSE},
943             {URLZONE_INVALID,E_NOTIMPL,FALSE}
944         }
945     },
946     /* Allowed to have a backslash in the userinfo since it's an unknown scheme. */
947     {   "zip://test\\:word@winehq.org/", 0, S_OK, FALSE,
948         {
949             {"zip://test\\:word@winehq.org/",S_OK,FALSE},
950             {"test\\:word@winehq.org",S_OK,FALSE},
951             {"zip://test\\:word@winehq.org/",S_OK,FALSE},
952             {"winehq.org",S_OK,FALSE},
953             {"",S_FALSE,FALSE},
954             {"",S_FALSE,FALSE},
955             {"winehq.org",S_OK,FALSE},
956             {"word",S_OK,FALSE},
957             {"/",S_OK,FALSE},
958             {"/",S_OK,FALSE},
959             {"",S_FALSE,FALSE},
960             {"zip://test\\:word@winehq.org/",S_OK,FALSE},
961             {"zip",S_OK,FALSE},
962             {"test\\:word",S_OK,FALSE},
963             {"test\\",S_OK,FALSE}
964         },
965         {
966             {Uri_HOST_DNS,S_OK,FALSE},
967             {0,S_FALSE,FALSE},
968             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
969             {URLZONE_INVALID,E_NOTIMPL,FALSE}
970         }
971     },
972     /* It normalizes IPv4 addresses correctly. */
973     {   "http://127.000.000.100/", 0, S_OK, FALSE,
974         {
975             {"http://127.0.0.100/",S_OK,FALSE},
976             {"127.0.0.100",S_OK,FALSE},
977             {"http://127.0.0.100/",S_OK,FALSE},
978             {"",S_FALSE,FALSE},
979             {"",S_FALSE,FALSE},
980             {"",S_FALSE,FALSE},
981             {"127.0.0.100",S_OK,FALSE},
982             {"",S_FALSE,FALSE},
983             {"/",S_OK,FALSE},
984             {"/",S_OK,FALSE},
985             {"",S_FALSE,FALSE},
986             {"http://127.000.000.100/",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 normalizes partial IPv4 addresses correctly. */
999     {   "http://127.0/", 0, S_OK, FALSE,
1000         {
1001             {"http://127.0.0.0/",S_OK,FALSE},
1002             {"127.0.0.0",S_OK,FALSE},
1003             {"http://127.0.0.0/",S_OK,FALSE},
1004             {"",S_FALSE,FALSE},
1005             {"",S_FALSE,FALSE},
1006             {"",S_FALSE,FALSE},
1007             {"127.0.0.0",S_OK,FALSE},
1008             {"",S_FALSE,FALSE},
1009             {"/",S_OK,FALSE},
1010             {"/",S_OK,FALSE},
1011             {"",S_FALSE,FALSE},
1012             {"http://127.0/",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     /* Make sure it converts implicit IPv4's correctly. */
1025     {   "http://123456/", 0, S_OK, FALSE,
1026         {
1027             {"http://0.1.226.64/",S_OK,FALSE},
1028             {"0.1.226.64",S_OK,FALSE},
1029             {"http://0.1.226.64/",S_OK,FALSE},
1030             {"",S_FALSE,FALSE},
1031             {"",S_FALSE,FALSE},
1032             {"",S_FALSE,FALSE},
1033             {"0.1.226.64",S_OK,FALSE},
1034             {"",S_FALSE,FALSE},
1035             {"/",S_OK,FALSE},
1036             {"/",S_OK,FALSE},
1037             {"",S_FALSE,FALSE},
1038             {"http://123456/",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 */
1051     {   "http://4294967295/", 0, S_OK, FALSE,
1052         {
1053             {"http://255.255.255.255/",S_OK,FALSE},
1054             {"255.255.255.255",S_OK,FALSE},
1055             {"http://255.255.255.255/",S_OK,FALSE},
1056             {"",S_FALSE,FALSE},
1057             {"",S_FALSE,FALSE},
1058             {"",S_FALSE,FALSE},
1059             {"255.255.255.255",S_OK,FALSE},
1060             {"",S_FALSE,FALSE},
1061             {"/",S_OK,FALSE},
1062             {"/",S_OK,FALSE},
1063             {"",S_FALSE,FALSE},
1064             {"http://4294967295/",S_OK,FALSE},
1065             {"http",S_OK,FALSE},
1066             {"",S_FALSE,FALSE},
1067             {"",S_FALSE,FALSE}
1068         },
1069         {
1070             {Uri_HOST_IPV4,S_OK,FALSE},
1071             {80,S_OK,FALSE},
1072             {URL_SCHEME_HTTP,S_OK,FALSE},
1073             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1074         }
1075     },
1076     /* UINT_MAX+1 */
1077     {   "http://4294967296/", 0, S_OK, FALSE,
1078         {
1079             {"http://4294967296/",S_OK,FALSE},
1080             {"4294967296",S_OK,FALSE},
1081             {"http://4294967296/",S_OK,FALSE},
1082             {"",S_FALSE,FALSE},
1083             {"",S_FALSE,FALSE},
1084             {"",S_FALSE,FALSE},
1085             {"4294967296",S_OK,FALSE},
1086             {"",S_FALSE,FALSE},
1087             {"/",S_OK,FALSE},
1088             {"/",S_OK,FALSE},
1089             {"",S_FALSE,FALSE},
1090             {"http://4294967296/",S_OK,FALSE},
1091             {"http",S_OK,FALSE},
1092             {"",S_FALSE,FALSE},
1093             {"",S_FALSE,FALSE}
1094         },
1095         {
1096             {Uri_HOST_DNS,S_OK,FALSE},
1097             {80,S_OK,FALSE},
1098             {URL_SCHEME_HTTP,S_OK,FALSE},
1099             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1100         }
1101     },
1102     /* Window's doesn't normalize IP address for unknown schemes. */
1103     {   "1234://4294967295/", 0, S_OK, FALSE,
1104         {
1105             {"1234://4294967295/",S_OK,FALSE},
1106             {"4294967295",S_OK,FALSE},
1107             {"1234://4294967295/",S_OK,FALSE},
1108             {"",S_FALSE,FALSE},
1109             {"",S_FALSE,FALSE},
1110             {"",S_FALSE,FALSE},
1111             {"4294967295",S_OK,FALSE},
1112             {"",S_FALSE,FALSE},
1113             {"/",S_OK,FALSE},
1114             {"/",S_OK,FALSE},
1115             {"",S_FALSE,FALSE},
1116             {"1234://4294967295/",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     /* Window's doesn't normalize IP address for unknown schemes. */
1129     {   "1234://127.001/", 0, S_OK, FALSE,
1130         {
1131             {"1234://127.001/",S_OK,FALSE},
1132             {"127.001",S_OK,FALSE},
1133             {"1234://127.001/",S_OK,FALSE},
1134             {"",S_FALSE,FALSE},
1135             {"",S_FALSE,FALSE},
1136             {"",S_FALSE,FALSE},
1137             {"127.001",S_OK,FALSE},
1138             {"",S_FALSE,FALSE},
1139             {"/",S_OK,FALSE},
1140             {"/",S_OK,FALSE},
1141             {"",S_FALSE,FALSE},
1142             {"1234://127.001/",S_OK,FALSE},
1143             {"1234",S_OK,FALSE},
1144             {"",S_FALSE,FALSE},
1145             {"",S_FALSE,FALSE}
1146         },
1147         {
1148             {Uri_HOST_IPV4,S_OK,FALSE},
1149             {0,S_FALSE,FALSE},
1150             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1151             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1152         }
1153     },
1154     {   "http://[FEDC:BA98::3210]", 0, S_OK, FALSE,
1155         {
1156             {"http://[fedc:ba98::3210]/",S_OK,FALSE},
1157             {"[fedc:ba98::3210]",S_OK,FALSE},
1158             {"http://[fedc:ba98::3210]/",S_OK,FALSE},
1159             {"",S_FALSE,FALSE},
1160             {"",S_FALSE,FALSE},
1161             {"",S_FALSE,FALSE},
1162             {"fedc:ba98::3210",S_OK,FALSE},
1163             {"",S_FALSE,FALSE},
1164             {"/",S_OK,FALSE},
1165             {"/",S_OK,FALSE},
1166             {"",S_FALSE,FALSE},
1167             {"http://[FEDC:BA98::3210]",S_OK,FALSE},
1168             {"http",S_OK,FALSE},
1169             {"",S_FALSE,FALSE},
1170             {"",S_FALSE,FALSE},
1171         },
1172         {
1173             {Uri_HOST_IPV6,S_OK,FALSE},
1174             {80,S_OK,FALSE},
1175             {URL_SCHEME_HTTP,S_OK,FALSE},
1176             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1177         }
1178     },
1179     {   "http://[::]", 0, S_OK, FALSE,
1180         {
1181             {"http://[::]/",S_OK,FALSE},
1182             {"[::]",S_OK,FALSE},
1183             {"http://[::]/",S_OK,FALSE},
1184             {"",S_FALSE,FALSE},
1185             {"",S_FALSE,FALSE},
1186             {"",S_FALSE,FALSE},
1187             {"::",S_OK,FALSE},
1188             {"",S_FALSE,FALSE},
1189             {"/",S_OK,FALSE},
1190             {"/",S_OK,FALSE},
1191             {"",S_FALSE,FALSE},
1192             {"http://[::]",S_OK,FALSE},
1193             {"http",S_OK,FALSE},
1194             {"",S_FALSE,FALSE},
1195             {"",S_FALSE,FALSE},
1196         },
1197         {
1198             {Uri_HOST_IPV6,S_OK,FALSE},
1199             {80,S_OK,FALSE},
1200             {URL_SCHEME_HTTP,S_OK,FALSE},
1201             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1202         }
1203     },
1204     {   "http://[FEDC:BA98::]", 0, S_OK, FALSE,
1205         {
1206             {"http://[fedc:ba98::]/",S_OK,FALSE},
1207             {"[fedc:ba98::]",S_OK,FALSE},
1208             {"http://[fedc:ba98::]/",S_OK,FALSE},
1209             {"",S_FALSE,FALSE},
1210             {"",S_FALSE,FALSE},
1211             {"",S_FALSE,FALSE},
1212             {"fedc:ba98::",S_OK,FALSE},
1213             {"",S_FALSE,FALSE},
1214             {"/",S_OK,FALSE},
1215             {"/",S_OK,FALSE},
1216             {"",S_FALSE,FALSE},
1217             {"http://[FEDC:BA98::]",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     /* Valid even with 2 byte elision because it doesn't appear the beginning or end. */
1230     {   "http://[1::3:4:5:6:7:8]", 0, S_OK, FALSE,
1231         {
1232             {"http://[1:0:3:4:5:6:7:8]/",S_OK,FALSE},
1233             {"[1:0:3:4:5:6:7:8]",S_OK,FALSE},
1234             {"http://[1:0:3:4:5:6:7:8]/",S_OK,FALSE},
1235             {"",S_FALSE,FALSE},
1236             {"",S_FALSE,FALSE},
1237             {"",S_FALSE,FALSE},
1238             {"1:0:3:4:5:6:7:8",S_OK,FALSE},
1239             {"",S_FALSE,FALSE},
1240             {"/",S_OK,FALSE},
1241             {"/",S_OK,FALSE},
1242             {"",S_FALSE,FALSE},
1243             {"http://[1::3:4:5:6:7:8]",S_OK,FALSE},
1244             {"http",S_OK,FALSE},
1245             {"",S_FALSE,FALSE},
1246             {"",S_FALSE,FALSE},
1247         },
1248         {
1249             {Uri_HOST_IPV6,S_OK,FALSE},
1250             {80,S_OK,FALSE},
1251             {URL_SCHEME_HTTP,S_OK,FALSE},
1252             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1253         }
1254     },
1255     {   "http://[v2.34]/", 0, S_OK, FALSE,
1256         {
1257             {"http://[v2.34]/",S_OK,FALSE},
1258             {"[v2.34]",S_OK,FALSE},
1259             {"http://[v2.34]/",S_OK,FALSE},
1260             {"",S_FALSE,FALSE},
1261             {"",S_FALSE,FALSE},
1262             {"",S_FALSE,FALSE},
1263             {"[v2.34]",S_OK,FALSE},
1264             {"",S_FALSE,FALSE},
1265             {"/",S_OK,FALSE},
1266             {"/",S_OK,FALSE},
1267             {"",S_FALSE,FALSE},
1268             {"http://[v2.34]/",S_OK,FALSE},
1269             {"http",S_OK,FALSE},
1270             {"",S_FALSE,FALSE},
1271             {"",S_FALSE,FALSE}
1272         },
1273         {
1274             {Uri_HOST_UNKNOWN,S_OK,FALSE},
1275             {80,S_OK,FALSE},
1276             {URL_SCHEME_HTTP,S_OK,FALSE},
1277             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1278         }
1279     },
1280     /* Windows ignores ':' if they appear after a '[' on a non-IPLiteral host. */
1281     {   "http://[xyz:12345.com/test", 0, S_OK, FALSE,
1282         {
1283             {"http://[xyz:12345.com/test",S_OK,FALSE},
1284             {"[xyz:12345.com",S_OK,FALSE},
1285             {"http://[xyz:12345.com/test",S_OK,FALSE},
1286             {"[xyz:12345.com",S_OK,FALSE},
1287             {"",S_FALSE,FALSE},
1288             {"",S_FALSE,FALSE},
1289             {"[xyz:12345.com",S_OK,FALSE},
1290             {"",S_FALSE,FALSE},
1291             {"/test",S_OK,FALSE},
1292             {"/test",S_OK,FALSE},
1293             {"",S_FALSE,FALSE},
1294             {"http://[xyz:12345.com/test",S_OK,FALSE},
1295             {"http",S_OK,FALSE},
1296             {"",S_FALSE,FALSE},
1297             {"",S_FALSE,FALSE}
1298         },
1299         {
1300             {Uri_HOST_DNS,S_OK,FALSE},
1301             {80,S_OK,FALSE},
1302             {URL_SCHEME_HTTP,S_OK,FALSE},
1303             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1304         }
1305     },
1306     /* Valid URI since the '[' and ']' don't appear at the beginning and end
1307      * of the host name (respectively).
1308      */
1309     {   "ftp://www.[works].com/", 0, S_OK, FALSE,
1310         {
1311             {"ftp://www.[works].com/",S_OK,FALSE},
1312             {"www.[works].com",S_OK,FALSE},
1313             {"ftp://www.[works].com/",S_OK,FALSE},
1314             {"[works].com",S_OK,FALSE},
1315             {"",S_FALSE,FALSE},
1316             {"",S_FALSE,FALSE},
1317             {"www.[works].com",S_OK,FALSE},
1318             {"",S_FALSE,FALSE},
1319             {"/",S_OK,FALSE},
1320             {"/",S_OK,FALSE},
1321             {"",S_FALSE,FALSE},
1322             {"ftp://www.[works].com/",S_OK,FALSE},
1323             {"ftp",S_OK,FALSE},
1324             {"",S_FALSE,FALSE},
1325             {"",S_FALSE,FALSE}
1326         },
1327         {
1328             {Uri_HOST_DNS,S_OK,FALSE},
1329             {21,S_OK,FALSE},
1330             {URL_SCHEME_FTP,S_OK,FALSE},
1331             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1332         }
1333     },
1334     /* Considers ':' a delimiter since it appears after the ']'. */
1335     {   "http://www.google.com]:12345/", 0, S_OK, FALSE,
1336         {
1337             {"http://www.google.com]:12345/",S_OK,FALSE},
1338             {"www.google.com]:12345",S_OK,FALSE},
1339             {"http://www.google.com]:12345/",S_OK,FALSE},
1340             {"google.com]",S_OK,FALSE},
1341             {"",S_FALSE,FALSE},
1342             {"",S_FALSE,FALSE},
1343             {"www.google.com]",S_OK,FALSE},
1344             {"",S_FALSE,FALSE},
1345             {"/",S_OK,FALSE},
1346             {"/",S_OK,FALSE},
1347             {"",S_FALSE,FALSE},
1348             {"http://www.google.com]:12345/",S_OK,FALSE},
1349             {"http",S_OK,FALSE},
1350             {"",S_FALSE,FALSE},
1351             {"",S_FALSE,FALSE}
1352         },
1353         {
1354             {Uri_HOST_DNS,S_OK,FALSE},
1355             {12345,S_OK,FALSE},
1356             {URL_SCHEME_HTTP,S_OK,FALSE},
1357             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1358         }
1359     },
1360     /* Unknown scheme types can have invalid % encoded data in the hostname. */
1361     {   "zip://w%XXw%GEw.google.com/", 0, S_OK, FALSE,
1362         {
1363             {"zip://w%XXw%GEw.google.com/",S_OK,FALSE},
1364             {"w%XXw%GEw.google.com",S_OK,FALSE},
1365             {"zip://w%XXw%GEw.google.com/",S_OK,FALSE},
1366             {"google.com",S_OK,FALSE},
1367             {"",S_FALSE,FALSE},
1368             {"",S_FALSE,FALSE},
1369             {"w%XXw%GEw.google.com",S_OK,FALSE},
1370             {"",S_FALSE,FALSE},
1371             {"/",S_OK,FALSE},
1372             {"/",S_OK,FALSE},
1373             {"",S_FALSE,FALSE},
1374             {"zip://w%XXw%GEw.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     /* Unknown scheme types hostname doesn't get lower cased. */
1387     {   "zip://GOOGLE.com/", 0, S_OK, FALSE,
1388         {
1389             {"zip://GOOGLE.com/",S_OK,FALSE},
1390             {"GOOGLE.com",S_OK,FALSE},
1391             {"zip://GOOGLE.com/",S_OK,FALSE},
1392             {"GOOGLE.com",S_OK,FALSE},
1393             {"",S_FALSE,FALSE},
1394             {"",S_FALSE,FALSE},
1395             {"GOOGLE.com",S_OK,FALSE},
1396             {"",S_FALSE,FALSE},
1397             {"/",S_OK,FALSE},
1398             {"/",S_OK,FALSE},
1399             {"",S_FALSE,FALSE},
1400             {"zip://GOOGLE.com/",S_OK,FALSE},
1401             {"zip",S_OK,FALSE},
1402             {"",S_FALSE,FALSE},
1403             {"",S_FALSE,FALSE}
1404         },
1405         {
1406             {Uri_HOST_DNS,S_OK,FALSE},
1407             {0,S_FALSE,FALSE},
1408             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1409             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1410         }
1411     },
1412     /* Hostname get's lower cased for known scheme types. */
1413     {   "http://WWW.GOOGLE.com/", 0, S_OK, FALSE,
1414         {
1415             {"http://www.google.com/",S_OK,FALSE},
1416             {"www.google.com",S_OK,FALSE},
1417             {"http://www.google.com/",S_OK,FALSE},
1418             {"google.com",S_OK,FALSE},
1419             {"",S_FALSE,FALSE},
1420             {"",S_FALSE,FALSE},
1421             {"www.google.com",S_OK,FALSE},
1422             {"",S_FALSE,FALSE},
1423             {"/",S_OK,FALSE},
1424             {"/",S_OK,FALSE},
1425             {"",S_FALSE,FALSE},
1426             {"http://WWW.GOOGLE.com/",S_OK,FALSE},
1427             {"http",S_OK,FALSE},
1428             {"",S_FALSE,FALSE},
1429             {"",S_FALSE,FALSE}
1430         },
1431         {
1432             {Uri_HOST_DNS,S_OK,FALSE},
1433             {80,S_OK,FALSE},
1434             {URL_SCHEME_HTTP,S_OK,FALSE},
1435             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1436         }
1437     },
1438     /* Characters that get % encoded in the hostname also have their percent
1439      * encoded forms lower cased.
1440      */
1441     {   "http://www.%7Cgoogle|.com/", 0, S_OK, FALSE,
1442         {
1443             {"http://www.%7cgoogle%7c.com/",S_OK,FALSE},
1444             {"www.%7cgoogle%7c.com",S_OK,FALSE},
1445             {"http://www.%7cgoogle%7c.com/",S_OK,FALSE},
1446             {"%7cgoogle%7c.com",S_OK,FALSE},
1447             {"",S_FALSE,FALSE},
1448             {"",S_FALSE,FALSE},
1449             {"www.%7cgoogle%7c.com",S_OK,FALSE},
1450             {"",S_FALSE,FALSE},
1451             {"/",S_OK,FALSE},
1452             {"/",S_OK,FALSE},
1453             {"",S_FALSE,FALSE},
1454             {"http://www.%7Cgoogle|.com/",S_OK,FALSE},
1455             {"http",S_OK,FALSE},
1456             {"",S_FALSE,FALSE},
1457             {"",S_FALSE,FALSE}
1458         },
1459         {
1460             {Uri_HOST_DNS,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 attached to IPv6 can be included in elisions. */
1467     {   "http://[1:2:3:4:5:6:0.0.0.0]", 0, S_OK, FALSE,
1468         {
1469             {"http://[1:2:3:4:5:6::]/",S_OK,FALSE},
1470             {"[1:2:3:4:5:6::]",S_OK,FALSE},
1471             {"http://[1:2:3:4:5:6::]/",S_OK,FALSE},
1472             {"",S_FALSE,FALSE},
1473             {"",S_FALSE,FALSE},
1474             {"",S_FALSE,FALSE},
1475             {"1:2:3:4:5:6::",S_OK,FALSE},
1476             {"",S_FALSE,FALSE},
1477             {"/",S_OK,FALSE},
1478             {"/",S_OK,FALSE},
1479             {"",S_FALSE,FALSE},
1480             {"http://[1:2:3:4:5:6:0.0.0.0]",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     /* IPv4 addresses get normalized. */
1493     {   "http://[::001.002.003.000]", 0, S_OK, FALSE,
1494         {
1495             {"http://[::1.2.3.0]/",S_OK,FALSE},
1496             {"[::1.2.3.0]",S_OK,FALSE},
1497             {"http://[::1.2.3.0]/",S_OK,FALSE},
1498             {"",S_FALSE,FALSE},
1499             {"",S_FALSE,FALSE},
1500             {"",S_FALSE,FALSE},
1501             {"::1.2.3.0",S_OK,FALSE},
1502             {"",S_FALSE,FALSE},
1503             {"/",S_OK,FALSE},
1504             {"/",S_OK,FALSE},
1505             {"",S_FALSE,FALSE},
1506             {"http://[::001.002.003.000]",S_OK,FALSE},
1507             {"http",S_OK,FALSE},
1508             {"",S_FALSE,FALSE},
1509             {"",S_FALSE,FALSE},
1510         },
1511         {
1512             {Uri_HOST_IPV6,S_OK,FALSE},
1513             {80,S_OK,FALSE},
1514             {URL_SCHEME_HTTP,S_OK,FALSE},
1515             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1516         }
1517     },
1518     /* Windows doesn't do anything to IPv6's in unknown schemes. */
1519     {   "zip://[0001:0:000:0004:0005:0006:001.002.003.000]", 0, S_OK, FALSE,
1520         {
1521             {"zip://[0001:0:000:0004:0005:0006:001.002.003.000]/",S_OK,FALSE},
1522             {"[0001:0:000:0004:0005:0006:001.002.003.000]",S_OK,FALSE},
1523             {"zip://[0001:0:000:0004:0005:0006:001.002.003.000]/",S_OK,FALSE},
1524             {"",S_FALSE,FALSE},
1525             {"",S_FALSE,FALSE},
1526             {"",S_FALSE,FALSE},
1527             {"0001:0:000:0004:0005:0006:001.002.003.000",S_OK,FALSE},
1528             {"",S_FALSE,FALSE},
1529             {"/",S_OK,FALSE},
1530             {"/",S_OK,FALSE},
1531             {"",S_FALSE,FALSE},
1532             {"zip://[0001:0:000:0004:0005:0006:001.002.003.000]",S_OK,FALSE},
1533             {"zip",S_OK,FALSE},
1534             {"",S_FALSE,FALSE},
1535             {"",S_FALSE,FALSE},
1536         },
1537         {
1538             {Uri_HOST_IPV6,S_OK,FALSE},
1539             {0,S_FALSE,FALSE},
1540             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1541             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1542         }
1543     },
1544     /* IPv4 address is converted into 2 h16 components. */
1545     {   "http://[ffff::192.222.111.32]", 0, S_OK, FALSE,
1546         {
1547             {"http://[ffff::c0de:6f20]/",S_OK,FALSE},
1548             {"[ffff::c0de:6f20]",S_OK,FALSE},
1549             {"http://[ffff::c0de:6f20]/",S_OK,FALSE},
1550             {"",S_FALSE,FALSE},
1551             {"",S_FALSE,FALSE},
1552             {"",S_FALSE,FALSE},
1553             {"ffff::c0de:6f20",S_OK,FALSE},
1554             {"",S_FALSE,FALSE},
1555             {"/",S_OK,FALSE},
1556             {"/",S_OK,FALSE},
1557             {"",S_FALSE,FALSE},
1558             {"http://[ffff::192.222.111.32]",S_OK,FALSE},
1559             {"http",S_OK,FALSE},
1560             {"",S_FALSE,FALSE},
1561             {"",S_FALSE,FALSE},
1562         },
1563         {
1564             {Uri_HOST_IPV6,S_OK,FALSE},
1565             {80,S_OK,FALSE},
1566             {URL_SCHEME_HTTP,S_OK,FALSE},
1567             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1568         }
1569     },
1570     /* Max value for a port. */
1571     {   "http://google.com:65535", 0, S_OK, FALSE,
1572         {
1573             {"http://google.com:65535/",S_OK,FALSE},
1574             {"google.com:65535",S_OK,FALSE},
1575             {"http://google.com:65535/",S_OK,FALSE},
1576             {"google.com",S_OK,FALSE},
1577             {"",S_FALSE,FALSE},
1578             {"",S_FALSE,FALSE},
1579             {"google.com",S_OK,FALSE},
1580             {"",S_FALSE,FALSE},
1581             {"/",S_OK,FALSE},
1582             {"/",S_OK,FALSE},
1583             {"",S_FALSE,FALSE},
1584             {"http://google.com:65535",S_OK,FALSE},
1585             {"http",S_OK,FALSE},
1586             {"",S_FALSE,FALSE},
1587             {"",S_FALSE,FALSE}
1588         },
1589         {
1590             {Uri_HOST_DNS,S_OK,FALSE},
1591             {65535,S_OK,FALSE},
1592             {URL_SCHEME_HTTP,S_OK,FALSE},
1593             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1594         }
1595     },
1596     {   "zip://google.com:65536", 0, S_OK, FALSE,
1597         {
1598             {"zip://google.com:65536/",S_OK,FALSE},
1599             {"google.com:65536",S_OK,FALSE},
1600             {"zip://google.com:65536/",S_OK,FALSE},
1601             {"google.com:65536",S_OK,FALSE},
1602             {"",S_FALSE,FALSE},
1603             {"",S_FALSE,FALSE},
1604             {"google.com:65536",S_OK,FALSE},
1605             {"",S_FALSE,FALSE},
1606             {"/",S_OK,FALSE},
1607             {"/",S_OK,FALSE},
1608             {"",S_FALSE,FALSE},
1609             {"zip://google.com:65536",S_OK,FALSE},
1610             {"zip",S_OK,FALSE},
1611             {"",S_FALSE,FALSE},
1612             {"",S_FALSE,FALSE}
1613         },
1614         {
1615             {Uri_HOST_DNS,S_OK,FALSE},
1616             {0,S_FALSE,FALSE},
1617             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1618             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1619         }
1620     },
1621     {   "zip://google.com:65536:25", 0, S_OK, FALSE,
1622         {
1623             {"zip://google.com:65536:25/",S_OK,FALSE},
1624             {"google.com:65536:25",S_OK,FALSE},
1625             {"zip://google.com:65536:25/",S_OK,FALSE},
1626             {"google.com:65536:25",S_OK,FALSE},
1627             {"",S_FALSE,FALSE},
1628             {"",S_FALSE,FALSE},
1629             {"google.com:65536:25",S_OK,FALSE},
1630             {"",S_FALSE,FALSE},
1631             {"/",S_OK,FALSE},
1632             {"/",S_OK,FALSE},
1633             {"",S_FALSE,FALSE},
1634             {"zip://google.com:65536:25",S_OK,FALSE},
1635             {"zip",S_OK,FALSE},
1636             {"",S_FALSE,FALSE},
1637             {"",S_FALSE,FALSE}
1638         },
1639         {
1640             {Uri_HOST_DNS,S_OK,FALSE},
1641             {0,S_FALSE,FALSE},
1642             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1643             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1644         }
1645     },
1646     {   "zip://[::ffff]:abcd", 0, S_OK, FALSE,
1647         {
1648             {"zip://[::ffff]:abcd/",S_OK,FALSE},
1649             {"[::ffff]:abcd",S_OK,FALSE},
1650             {"zip://[::ffff]:abcd/",S_OK,FALSE},
1651             {"",S_FALSE,FALSE},
1652             {"",S_FALSE,FALSE},
1653             {"",S_FALSE,FALSE},
1654             {"[::ffff]:abcd",S_OK,FALSE},
1655             {"",S_FALSE,FALSE},
1656             {"/",S_OK,FALSE},
1657             {"/",S_OK,FALSE},
1658             {"",S_FALSE,FALSE},
1659             {"zip://[::ffff]:abcd",S_OK,FALSE},
1660             {"zip",S_OK,FALSE},
1661             {"",S_FALSE,FALSE},
1662             {"",S_FALSE,FALSE}
1663         },
1664         {
1665             {Uri_HOST_DNS,S_OK,FALSE},
1666             {0,S_FALSE,FALSE},
1667             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1668             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1669         }
1670     },
1671     {   "zip://127.0.0.1:abcd", 0, S_OK, FALSE,
1672         {
1673             {"zip://127.0.0.1:abcd/",S_OK,FALSE},
1674             {"127.0.0.1:abcd",S_OK,FALSE},
1675             {"zip://127.0.0.1:abcd/",S_OK,FALSE},
1676             {"0.1:abcd",S_OK,FALSE},
1677             {"",S_FALSE,FALSE},
1678             {"",S_FALSE,FALSE},
1679             {"127.0.0.1:abcd",S_OK,FALSE},
1680             {"",S_FALSE,FALSE},
1681             {"/",S_OK,FALSE},
1682             {"/",S_OK,FALSE},
1683             {"",S_FALSE,FALSE},
1684             {"zip://127.0.0.1:abcd",S_OK,FALSE},
1685             {"zip",S_OK,FALSE},
1686             {"",S_FALSE,FALSE},
1687             {"",S_FALSE,FALSE}
1688         },
1689         {
1690             {Uri_HOST_DNS,S_OK,FALSE},
1691             {0,S_FALSE,FALSE},
1692             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1693             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1694         }
1695     },
1696     /* Port is just copied over. */
1697     {   "http://google.com:00035", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
1698         {
1699             {"http://google.com:00035",S_OK,FALSE},
1700             {"google.com:00035",S_OK,FALSE},
1701             {"http://google.com:00035",S_OK,FALSE,"http://google.com:35"},
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:00035",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             {35,S_OK,FALSE},
1718             {URL_SCHEME_HTTP,S_OK,FALSE},
1719             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1720         }
1721     },
1722     /* Default port is copied over. */
1723     {   "http://google.com:80", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
1724         {
1725             {"http://google.com:80",S_OK,FALSE},
1726             {"google.com:80",S_OK,FALSE},
1727             {"http://google.com:80",S_OK,FALSE},
1728             {"google.com",S_OK,FALSE},
1729             {"",S_FALSE,FALSE},
1730             {"",S_FALSE,FALSE},
1731             {"google.com",S_OK,FALSE},
1732             {"",S_FALSE,FALSE},
1733             {"",S_FALSE,FALSE},
1734             {"",S_FALSE,FALSE},
1735             {"",S_FALSE,FALSE},
1736             {"http://google.com:80",S_OK,FALSE},
1737             {"http",S_OK,FALSE},
1738             {"",S_FALSE,FALSE},
1739             {"",S_FALSE,FALSE}
1740         },
1741         {
1742             {Uri_HOST_DNS,S_OK,FALSE},
1743             {80,S_OK,FALSE},
1744             {URL_SCHEME_HTTP,S_OK,FALSE},
1745             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1746         }
1747     },
1748     {   "http://google.com.uk", 0, S_OK, FALSE,
1749         {
1750             {"http://google.com.uk/",S_OK,FALSE},
1751             {"google.com.uk",S_OK,FALSE},
1752             {"http://google.com.uk/",S_OK,FALSE},
1753             {"google.com.uk",S_OK,FALSE},
1754             {"",S_FALSE,FALSE},
1755             {"",S_FALSE,FALSE},
1756             {"google.com.uk",S_OK,FALSE},
1757             {"",S_FALSE,FALSE},
1758             {"/",S_OK,FALSE},
1759             {"/",S_OK,FALSE},
1760             {"",S_FALSE,FALSE},
1761             {"http://google.com.uk",S_OK,FALSE},
1762             {"http",S_OK,FALSE},
1763             {"",S_FALSE,FALSE},
1764             {"",S_FALSE,FALSE}
1765         },
1766         {
1767             {Uri_HOST_DNS,S_OK,FALSE},
1768             {80,S_OK,FALSE},
1769             {URL_SCHEME_HTTP,S_OK,FALSE},
1770             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1771         }
1772     },
1773     {   "http://google.com.com", 0, S_OK, FALSE,
1774         {
1775             {"http://google.com.com/",S_OK,FALSE},
1776             {"google.com.com",S_OK,FALSE},
1777             {"http://google.com.com/",S_OK,FALSE},
1778             {"com.com",S_OK,FALSE},
1779             {"",S_FALSE,FALSE},
1780             {"",S_FALSE,FALSE},
1781             {"google.com.com",S_OK,FALSE},
1782             {"",S_FALSE,FALSE},
1783             {"/",S_OK,FALSE},
1784             {"/",S_OK,FALSE},
1785             {"",S_FALSE,FALSE},
1786             {"http://google.com.com",S_OK,FALSE},
1787             {"http",S_OK,FALSE},
1788             {"",S_FALSE,FALSE},
1789             {"",S_FALSE,FALSE}
1790         },
1791         {
1792             {Uri_HOST_DNS,S_OK,FALSE},
1793             {80,S_OK,FALSE},
1794             {URL_SCHEME_HTTP,S_OK,FALSE},
1795             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1796         }
1797     },
1798     {   "http://google.uk.1", 0, S_OK, FALSE,
1799         {
1800             {"http://google.uk.1/",S_OK,FALSE},
1801             {"google.uk.1",S_OK,FALSE},
1802             {"http://google.uk.1/",S_OK,FALSE},
1803             {"google.uk.1",S_OK,FALSE},
1804             {"",S_FALSE,FALSE},
1805             {"",S_FALSE,FALSE},
1806             {"google.uk.1",S_OK,FALSE},
1807             {"",S_FALSE,FALSE},
1808             {"/",S_OK,FALSE},
1809             {"/",S_OK,FALSE},
1810             {"",S_FALSE,FALSE},
1811             {"http://google.uk.1",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     /* Since foo isn't a recognized 3 character TLD its considered the domain name. */
1824     {   "http://google.foo.uk", 0, S_OK, FALSE,
1825         {
1826             {"http://google.foo.uk/",S_OK,FALSE},
1827             {"google.foo.uk",S_OK,FALSE},
1828             {"http://google.foo.uk/",S_OK,FALSE},
1829             {"foo.uk",S_OK,FALSE},
1830             {"",S_FALSE,FALSE},
1831             {"",S_FALSE,FALSE},
1832             {"google.foo.uk",S_OK,FALSE},
1833             {"",S_FALSE,FALSE},
1834             {"/",S_OK,FALSE},
1835             {"/",S_OK,FALSE},
1836             {"",S_FALSE,FALSE},
1837             {"http://google.foo.uk",S_OK,FALSE},
1838             {"http",S_OK,FALSE},
1839             {"",S_FALSE,FALSE},
1840             {"",S_FALSE,FALSE}
1841         },
1842         {
1843             {Uri_HOST_DNS,S_OK,FALSE},
1844             {80,S_OK,FALSE},
1845             {URL_SCHEME_HTTP,S_OK,FALSE},
1846             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1847         }
1848     },
1849     {   "http://.com", 0, S_OK, FALSE,
1850         {
1851             {"http://.com/",S_OK,FALSE},
1852             {".com",S_OK,FALSE},
1853             {"http://.com/",S_OK,FALSE},
1854             {".com",S_OK,FALSE},
1855             {"",S_FALSE,FALSE},
1856             {"",S_FALSE,FALSE},
1857             {".com",S_OK,FALSE},
1858             {"",S_FALSE,FALSE},
1859             {"/",S_OK,FALSE},
1860             {"/",S_OK,FALSE},
1861             {"",S_FALSE,FALSE},
1862             {"http://.com",S_OK,FALSE},
1863             {"http",S_OK,FALSE},
1864             {"",S_FALSE,FALSE},
1865             {"",S_FALSE,FALSE}
1866         },
1867         {
1868             {Uri_HOST_DNS,S_OK,FALSE},
1869             {80,S_OK,FALSE},
1870             {URL_SCHEME_HTTP,S_OK,FALSE},
1871             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1872         }
1873     },
1874     {   "http://.uk", 0, S_OK, FALSE,
1875         {
1876             {"http://.uk/",S_OK,FALSE},
1877             {".uk",S_OK,FALSE},
1878             {"http://.uk/",S_OK,FALSE},
1879             {"",S_FALSE,FALSE},
1880             {"",S_FALSE,FALSE},
1881             {"",S_FALSE,FALSE},
1882             {".uk",S_OK,FALSE},
1883             {"",S_FALSE,FALSE},
1884             {"/",S_OK,FALSE},
1885             {"/",S_OK,FALSE},
1886             {"",S_FALSE,FALSE},
1887             {"http://.uk",S_OK,FALSE},
1888             {"http",S_OK,FALSE},
1889             {"",S_FALSE,FALSE},
1890             {"",S_FALSE,FALSE}
1891         },
1892         {
1893             {Uri_HOST_DNS,S_OK,FALSE},
1894             {80,S_OK,FALSE},
1895             {URL_SCHEME_HTTP,S_OK,FALSE},
1896             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1897         }
1898     },
1899     {   "http://www.co.google.com.[]", 0, S_OK, FALSE,
1900         {
1901             {"http://www.co.google.com.[]/",S_OK,FALSE},
1902             {"www.co.google.com.[]",S_OK,FALSE},
1903             {"http://www.co.google.com.[]/",S_OK,FALSE},
1904             {"google.com.[]",S_OK,FALSE},
1905             {"",S_FALSE,FALSE},
1906             {"",S_FALSE,FALSE},
1907             {"www.co.google.com.[]",S_OK,FALSE},
1908             {"",S_FALSE,FALSE},
1909             {"/",S_OK,FALSE},
1910             {"/",S_OK,FALSE},
1911             {"",S_FALSE,FALSE},
1912             {"http://www.co.google.com.[]",S_OK,FALSE},
1913             {"http",S_OK,FALSE},
1914             {"",S_FALSE,FALSE},
1915             {"",S_FALSE,FALSE}
1916         },
1917         {
1918             {Uri_HOST_DNS,S_OK,FALSE},
1919             {80,S_OK,FALSE},
1920             {URL_SCHEME_HTTP,S_OK,FALSE},
1921             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1922         }
1923     },
1924     {   "http://co.uk", 0, S_OK, FALSE,
1925         {
1926             {"http://co.uk/",S_OK,FALSE},
1927             {"co.uk",S_OK,FALSE},
1928             {"http://co.uk/",S_OK,FALSE},
1929             {"",S_FALSE,FALSE},
1930             {"",S_FALSE,FALSE},
1931             {"",S_FALSE,FALSE},
1932             {"co.uk",S_OK,FALSE},
1933             {"",S_FALSE,FALSE},
1934             {"/",S_OK,FALSE},
1935             {"/",S_OK,FALSE},
1936             {"",S_FALSE,FALSE},
1937             {"http://co.uk",S_OK,FALSE},
1938             {"http",S_OK,FALSE},
1939             {"",S_FALSE,FALSE},
1940             {"",S_FALSE,FALSE}
1941         },
1942         {
1943             {Uri_HOST_DNS,S_OK,FALSE},
1944             {80,S_OK,FALSE},
1945             {URL_SCHEME_HTTP,S_OK,FALSE},
1946             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1947         }
1948     },
1949     {   "http://www.co.google.us.test", 0, S_OK, FALSE,
1950         {
1951             {"http://www.co.google.us.test/",S_OK,FALSE},
1952             {"www.co.google.us.test",S_OK,FALSE},
1953             {"http://www.co.google.us.test/",S_OK,FALSE},
1954             {"us.test",S_OK,FALSE},
1955             {"",S_FALSE,FALSE},
1956             {"",S_FALSE,FALSE},
1957             {"www.co.google.us.test",S_OK,FALSE},
1958             {"",S_FALSE,FALSE},
1959             {"/",S_OK,FALSE},
1960             {"/",S_OK,FALSE},
1961             {"",S_FALSE,FALSE},
1962             {"http://www.co.google.us.test",S_OK,FALSE},
1963             {"http",S_OK,FALSE},
1964             {"",S_FALSE,FALSE},
1965             {"",S_FALSE,FALSE}
1966         },
1967         {
1968             {Uri_HOST_DNS,S_OK,FALSE},
1969             {80,S_OK,FALSE},
1970             {URL_SCHEME_HTTP,S_OK,FALSE},
1971             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1972         }
1973     },
1974     {   "http://gov.uk", 0, S_OK, FALSE,
1975         {
1976             {"http://gov.uk/",S_OK,FALSE},
1977             {"gov.uk",S_OK,FALSE},
1978             {"http://gov.uk/",S_OK,FALSE},
1979             {"",S_FALSE,FALSE},
1980             {"",S_FALSE,FALSE},
1981             {"",S_FALSE,FALSE},
1982             {"gov.uk",S_OK,FALSE},
1983             {"",S_FALSE,FALSE},
1984             {"/",S_OK,FALSE},
1985             {"/",S_OK,FALSE},
1986             {"",S_FALSE,FALSE},
1987             {"http://gov.uk",S_OK,FALSE},
1988             {"http",S_OK,FALSE},
1989             {"",S_FALSE,FALSE},
1990             {"",S_FALSE,FALSE}
1991         },
1992         {
1993             {Uri_HOST_DNS,S_OK,FALSE},
1994             {80,S_OK,FALSE},
1995             {URL_SCHEME_HTTP,S_OK,FALSE},
1996             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1997         }
1998     },
1999     {   "zip://www.google.com\\test", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
2000         {
2001             {"zip://www.google.com\\test",S_OK,FALSE},
2002             {"www.google.com\\test",S_OK,FALSE},
2003             {"zip://www.google.com\\test",S_OK,FALSE},
2004             {"google.com\\test",S_OK,FALSE},
2005             {"",S_FALSE,FALSE},
2006             {"",S_FALSE,FALSE},
2007             {"www.google.com\\test",S_OK,FALSE},
2008             {"",S_FALSE,FALSE},
2009             {"",S_FALSE,FALSE},
2010             {"",S_FALSE,FALSE},
2011             {"",S_FALSE,FALSE},
2012             {"zip://www.google.com\\test",S_OK,FALSE},
2013             {"zip",S_OK,FALSE},
2014             {"",S_FALSE,FALSE},
2015             {"",S_FALSE,FALSE}
2016         },
2017         {
2018             {Uri_HOST_DNS,S_OK,FALSE},
2019             {0,S_FALSE,FALSE},
2020             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2021             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2022         }
2023     },
2024     {   "urn:excepts:bad:%XY:encoded", 0, S_OK, FALSE,
2025         {
2026             {"urn:excepts:bad:%XY:encoded",S_OK,FALSE},
2027             {"",S_FALSE,FALSE},
2028             {"urn:excepts:bad:%XY:encoded",S_OK,FALSE},
2029             {"",S_FALSE,FALSE},
2030             {"",S_FALSE,FALSE},
2031             {"",S_FALSE,FALSE},
2032             {"",S_FALSE,FALSE},
2033             {"",S_FALSE,FALSE},
2034             {"excepts:bad:%XY:encoded",S_OK,FALSE},
2035             {"excepts:bad:%XY:encoded",S_OK,FALSE},
2036             {"",S_FALSE,FALSE},
2037             {"urn:excepts:bad:%XY:encoded",S_OK,FALSE},
2038             {"urn",S_OK,FALSE},
2039             {"",S_FALSE,FALSE},
2040             {"",S_FALSE,FALSE}
2041         },
2042         {
2043             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2044             {0,S_FALSE,FALSE},
2045             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2046             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2047         }
2048     },
2049     /* Since the original URI doesn't contain an extra '/' before the path no % encoded values
2050      * are decoded and all '%' are encoded.
2051      */
2052     {   "file://C:/te%3Es%2Et/tes%t.mp3", 0, S_OK, FALSE,
2053         {
2054             {"file:///C:/te%253Es%252Et/tes%25t.mp3",S_OK,FALSE},
2055             {"",S_FALSE,FALSE},
2056             {"file:///C:/te%253Es%252Et/tes%25t.mp3",S_OK,FALSE},
2057             {"",S_FALSE,FALSE},
2058             {".mp3",S_OK,FALSE},
2059             {"",S_FALSE,FALSE},
2060             {"",S_FALSE,FALSE},
2061             {"",S_FALSE,FALSE},
2062             {"/C:/te%253Es%252Et/tes%25t.mp3",S_OK,FALSE},
2063             {"/C:/te%253Es%252Et/tes%25t.mp3",S_OK,FALSE},
2064             {"",S_FALSE,FALSE},
2065             {"file://C:/te%3Es%2Et/tes%t.mp3",S_OK,FALSE},
2066             {"file",S_OK,FALSE},
2067             {"",S_FALSE,FALSE},
2068             {"",S_FALSE,FALSE}
2069         },
2070         {
2071             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2072             {0,S_FALSE,FALSE},
2073             {URL_SCHEME_FILE,S_OK,FALSE},
2074             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2075         }
2076     },
2077     /* Since there's a '/' in front of the drive letter, any percent encoded, non-forbidden character
2078      * is decoded and only %'s in front of invalid hex digits are encoded.
2079      */
2080     {   "file:///C:/te%3Es%2Et/t%23es%t.mp3", 0, S_OK, FALSE,
2081         {
2082             {"file:///C:/te%3Es.t/t#es%25t.mp3",S_OK,FALSE},
2083             {"",S_FALSE,FALSE},
2084             {"file:///C:/te%3Es.t/t#es%25t.mp3",S_OK,FALSE},
2085             {"",S_FALSE,FALSE},
2086             {".mp3",S_OK,FALSE},
2087             {"",S_FALSE,FALSE},
2088             {"",S_FALSE,FALSE},
2089             {"",S_FALSE,FALSE},
2090             {"/C:/te%3Es.t/t#es%25t.mp3",S_OK,FALSE},
2091             {"/C:/te%3Es.t/t#es%25t.mp3",S_OK,FALSE},
2092             {"",S_FALSE,FALSE},
2093             {"file:///C:/te%3Es%2Et/t%23es%t.mp3",S_OK,FALSE},
2094             {"file",S_OK,FALSE},
2095             {"",S_FALSE,FALSE},
2096             {"",S_FALSE,FALSE}
2097         },
2098         {
2099             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2100             {0,S_FALSE,FALSE},
2101             {URL_SCHEME_FILE,S_OK,FALSE},
2102             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2103         }
2104     },
2105     /* Only unreserved percent encoded characters are decoded for known schemes that aren't file. */
2106     {   "http://[::001.002.003.000]/%3F%23%2E%54/test", 0, S_OK, FALSE,
2107         {
2108             {"http://[::1.2.3.0]/%3F%23.T/test",S_OK,FALSE},
2109             {"[::1.2.3.0]",S_OK,FALSE},
2110             {"http://[::1.2.3.0]/%3F%23.T/test",S_OK,FALSE},
2111             {"",S_FALSE,FALSE},
2112             {"",S_FALSE,FALSE},
2113             {"",S_FALSE,FALSE},
2114             {"::1.2.3.0",S_OK,FALSE},
2115             {"",S_FALSE,FALSE},
2116             {"/%3F%23.T/test",S_OK,FALSE},
2117             {"/%3F%23.T/test",S_OK,FALSE},
2118             {"",S_FALSE,FALSE},
2119             {"http://[::001.002.003.000]/%3F%23%2E%54/test",S_OK,FALSE},
2120             {"http",S_OK,FALSE},
2121             {"",S_FALSE,FALSE},
2122             {"",S_FALSE,FALSE},
2123         },
2124         {
2125             {Uri_HOST_IPV6,S_OK,FALSE},
2126             {80,S_OK,FALSE},
2127             {URL_SCHEME_HTTP,S_OK,FALSE},
2128             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2129         }
2130     },
2131     /* Forbidden characters are always encoded for file URIs. */
2132     {   "file:///C:/\"test\"/test.mp3", Uri_CREATE_NO_ENCODE_FORBIDDEN_CHARACTERS, S_OK, FALSE,
2133         {
2134             {"file:///C:/%22test%22/test.mp3",S_OK,FALSE},
2135             {"",S_FALSE,FALSE},
2136             {"file:///C:/%22test%22/test.mp3",S_OK,FALSE},
2137             {"",S_FALSE,FALSE},
2138             {".mp3",S_OK,FALSE},
2139             {"",S_FALSE,FALSE},
2140             {"",S_FALSE,FALSE},
2141             {"",S_FALSE,FALSE},
2142             {"/C:/%22test%22/test.mp3",S_OK,FALSE},
2143             {"/C:/%22test%22/test.mp3",S_OK,FALSE},
2144             {"",S_FALSE,FALSE},
2145             {"file:///C:/\"test\"/test.mp3",S_OK,FALSE},
2146             {"file",S_OK,FALSE},
2147             {"",S_FALSE,FALSE},
2148             {"",S_FALSE,FALSE}
2149         },
2150         {
2151             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2152             {0,S_FALSE,FALSE},
2153             {URL_SCHEME_FILE,S_OK,FALSE},
2154             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2155         }
2156     },
2157     /* Forbidden characters are never encoded for unknown scheme types. */
2158     {   "1234://4294967295/<|>\" test<|>", 0, S_OK, FALSE,
2159         {
2160             {"1234://4294967295/<|>\" test<|>",S_OK,FALSE},
2161             {"4294967295",S_OK,FALSE},
2162             {"1234://4294967295/<|>\" test<|>",S_OK,FALSE},
2163             {"",S_FALSE,FALSE},
2164             {"",S_FALSE,FALSE},
2165             {"",S_FALSE,FALSE},
2166             {"4294967295",S_OK,FALSE},
2167             {"",S_FALSE,FALSE},
2168             {"/<|>\" test<|>",S_OK,FALSE},
2169             {"/<|>\" test<|>",S_OK,FALSE},
2170             {"",S_FALSE,FALSE},
2171             {"1234://4294967295/<|>\" test<|>",S_OK,FALSE},
2172             {"1234",S_OK,FALSE},
2173             {"",S_FALSE,FALSE},
2174             {"",S_FALSE,FALSE}
2175         },
2176         {
2177             {Uri_HOST_IPV4,S_OK,FALSE},
2178             {0,S_FALSE,FALSE},
2179             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2180             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2181         }
2182     },
2183     /* Make sure forbidden characters are percent encoded. */
2184     {   "http://gov.uk/<|> test<|>", 0, S_OK, FALSE,
2185         {
2186             {"http://gov.uk/%3C%7C%3E%20test%3C%7C%3E",S_OK,FALSE},
2187             {"gov.uk",S_OK,FALSE},
2188             {"http://gov.uk/%3C%7C%3E%20test%3C%7C%3E",S_OK,FALSE},
2189             {"",S_FALSE,FALSE},
2190             {"",S_FALSE,FALSE},
2191             {"",S_FALSE,FALSE},
2192             {"gov.uk",S_OK,FALSE},
2193             {"",S_FALSE,FALSE},
2194             {"/%3C%7C%3E%20test%3C%7C%3E",S_OK,FALSE},
2195             {"/%3C%7C%3E%20test%3C%7C%3E",S_OK,FALSE},
2196             {"",S_FALSE,FALSE},
2197             {"http://gov.uk/<|> test<|>",S_OK,FALSE},
2198             {"http",S_OK,FALSE},
2199             {"",S_FALSE,FALSE},
2200             {"",S_FALSE,FALSE}
2201         },
2202         {
2203             {Uri_HOST_DNS,S_OK,FALSE},
2204             {80,S_OK,FALSE},
2205             {URL_SCHEME_HTTP,S_OK,FALSE},
2206             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2207         }
2208     },
2209     {   "http://gov.uk/test/../test2/././../test3/.././././", 0, S_OK, FALSE,
2210         {
2211             {"http://gov.uk/",S_OK,FALSE},
2212             {"gov.uk",S_OK,FALSE},
2213             {"http://gov.uk/",S_OK,FALSE},
2214             {"",S_FALSE,FALSE},
2215             {"",S_FALSE,FALSE},
2216             {"",S_FALSE,FALSE},
2217             {"gov.uk",S_OK,FALSE},
2218             {"",S_FALSE,FALSE},
2219             {"/",S_OK,FALSE},
2220             {"/",S_OK,FALSE},
2221             {"",S_FALSE,FALSE},
2222             {"http://gov.uk/test/../test2/././../test3/.././././",S_OK,FALSE},
2223             {"http",S_OK,FALSE},
2224             {"",S_FALSE,FALSE},
2225             {"",S_FALSE,FALSE}
2226         },
2227         {
2228             {Uri_HOST_DNS,S_OK,FALSE},
2229             {80,S_OK,FALSE},
2230             {URL_SCHEME_HTTP,S_OK,FALSE},
2231             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2232         }
2233     },
2234     {   "http://gov.uk/test/test2/../../..", 0, S_OK, FALSE,
2235         {
2236             {"http://gov.uk/",S_OK,FALSE},
2237             {"gov.uk",S_OK,FALSE},
2238             {"http://gov.uk/",S_OK,FALSE},
2239             {"",S_FALSE,FALSE},
2240             {"",S_FALSE,FALSE},
2241             {"",S_FALSE,FALSE},
2242             {"gov.uk",S_OK,FALSE},
2243             {"",S_FALSE,FALSE},
2244             {"/",S_OK,FALSE},
2245             {"/",S_OK,FALSE},
2246             {"",S_FALSE,FALSE},
2247             {"http://gov.uk/test/test2/../../..",S_OK,FALSE},
2248             {"http",S_OK,FALSE},
2249             {"",S_FALSE,FALSE},
2250             {"",S_FALSE,FALSE}
2251         },
2252         {
2253             {Uri_HOST_DNS,S_OK,FALSE},
2254             {80,S_OK,FALSE},
2255             {URL_SCHEME_HTTP,S_OK,FALSE},
2256             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2257         }
2258     },
2259     {   "http://gov.uk/test/test2/../../.", 0, S_OK, FALSE,
2260         {
2261             {"http://gov.uk/",S_OK,FALSE},
2262             {"gov.uk",S_OK,FALSE},
2263             {"http://gov.uk/",S_OK,FALSE},
2264             {"",S_FALSE,FALSE},
2265             {"",S_FALSE,FALSE},
2266             {"",S_FALSE,FALSE},
2267             {"gov.uk",S_OK,FALSE},
2268             {"",S_FALSE,FALSE},
2269             {"/",S_OK,FALSE},
2270             {"/",S_OK,FALSE},
2271             {"",S_FALSE,FALSE},
2272             {"http://gov.uk/test/test2/../../.",S_OK,FALSE},
2273             {"http",S_OK,FALSE},
2274             {"",S_FALSE,FALSE},
2275             {"",S_FALSE,FALSE}
2276         },
2277         {
2278             {Uri_HOST_DNS,S_OK,FALSE},
2279             {80,S_OK,FALSE},
2280             {URL_SCHEME_HTTP,S_OK,FALSE},
2281             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2282         }
2283     },
2284     {   "file://c:\\tests\\../tests\\./.\\..\\foo%20bar.mp3", 0, S_OK, FALSE,
2285         {
2286             {"file:///c:/foo%2520bar.mp3",S_OK,FALSE},
2287             {"",S_FALSE,FALSE},
2288             {"file:///c:/foo%2520bar.mp3",S_OK,FALSE},
2289             {"",S_FALSE,FALSE},
2290             {".mp3",S_OK,FALSE},
2291             {"",S_FALSE,FALSE},
2292             {"",S_FALSE,FALSE},
2293             {"",S_FALSE,FALSE},
2294             {"/c:/foo%2520bar.mp3",S_OK,FALSE},
2295             {"/c:/foo%2520bar.mp3",S_OK,FALSE},
2296             {"",S_FALSE,FALSE},
2297             {"file://c:\\tests\\../tests\\./.\\..\\foo%20bar.mp3",S_OK,FALSE},
2298             {"file",S_OK,FALSE},
2299             {"",S_FALSE,FALSE},
2300             {"",S_FALSE,FALSE}
2301         },
2302         {
2303             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2304             {0,S_FALSE,FALSE},
2305             {URL_SCHEME_FILE,S_OK,FALSE},
2306             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2307         }
2308     },
2309     /* Dot removal happens for unknown scheme types. */
2310     {   "zip://gov.uk/test/test2/../../.", 0, S_OK, FALSE,
2311         {
2312             {"zip://gov.uk/",S_OK,FALSE},
2313             {"gov.uk",S_OK,FALSE},
2314             {"zip://gov.uk/",S_OK,FALSE},
2315             {"",S_FALSE,FALSE},
2316             {"",S_FALSE,FALSE},
2317             {"",S_FALSE,FALSE},
2318             {"gov.uk",S_OK,FALSE},
2319             {"",S_FALSE,FALSE},
2320             {"/",S_OK,FALSE},
2321             {"/",S_OK,FALSE},
2322             {"",S_FALSE,FALSE},
2323             {"zip://gov.uk/test/test2/../../.",S_OK,FALSE},
2324             {"zip",S_OK,FALSE},
2325             {"",S_FALSE,FALSE},
2326             {"",S_FALSE,FALSE}
2327         },
2328         {
2329             {Uri_HOST_DNS,S_OK,FALSE},
2330             {0,S_FALSE,FALSE},
2331             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2332             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2333         }
2334     },
2335     /* Dot removal doesn't happen if NO_CANONICALIZE is set. */
2336     {   "http://gov.uk/test/test2/../../.", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
2337         {
2338             {"http://gov.uk/test/test2/../../.",S_OK,FALSE},
2339             {"gov.uk",S_OK,FALSE},
2340             {"http://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             {"http://gov.uk/test/test2/../../.",S_OK,FALSE},
2350             {"http",S_OK,FALSE},
2351             {"",S_FALSE,FALSE},
2352             {"",S_FALSE,FALSE}
2353         },
2354         {
2355             {Uri_HOST_DNS,S_OK,FALSE},
2356             {80,S_OK,FALSE},
2357             {URL_SCHEME_HTTP,S_OK,FALSE},
2358             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2359         }
2360     },
2361     /* Dot removal doesn't happen for wildcard scheme types. */
2362     {   "*:gov.uk/test/test2/../../.", 0, S_OK, FALSE,
2363         {
2364             {"*:gov.uk/test/test2/../../.",S_OK,FALSE},
2365             {"gov.uk",S_OK,FALSE},
2366             {"*:gov.uk/test/test2/../../.",S_OK,FALSE},
2367             {"",S_FALSE,FALSE},
2368             {".",S_OK,FALSE},
2369             {"",S_FALSE,FALSE},
2370             {"gov.uk",S_OK,FALSE},
2371             {"",S_FALSE,FALSE},
2372             {"/test/test2/../../.",S_OK,FALSE},
2373             {"/test/test2/../../.",S_OK,FALSE},
2374             {"",S_FALSE,FALSE},
2375             {"*:gov.uk/test/test2/../../.",S_OK,FALSE},
2376             {"*",S_OK,FALSE},
2377             {"",S_FALSE,FALSE},
2378             {"",S_FALSE,FALSE}
2379         },
2380         {
2381             {Uri_HOST_DNS,S_OK,FALSE},
2382             {0,S_FALSE,FALSE},
2383             {URL_SCHEME_WILDCARD,S_OK,FALSE},
2384             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2385         }
2386     },
2387     /* Forbidden characters are encoded for opaque known scheme types. */
2388     {   "mailto:\"acco<|>unt@example.com\"", 0, S_OK, FALSE,
2389         {
2390             {"mailto:%22acco%3C%7C%3Eunt@example.com%22",S_OK,FALSE},
2391             {"",S_FALSE,FALSE},
2392             {"mailto:%22acco%3C%7C%3Eunt@example.com%22",S_OK,FALSE},
2393             {"",S_FALSE,FALSE},
2394             {".com%22",S_OK,FALSE},
2395             {"",S_FALSE,FALSE},
2396             {"",S_FALSE,FALSE},
2397             {"",S_FALSE,FALSE},
2398             {"%22acco%3C%7C%3Eunt@example.com%22",S_OK,FALSE},
2399             {"%22acco%3C%7C%3Eunt@example.com%22",S_OK,FALSE},
2400             {"",S_FALSE,FALSE},
2401             {"mailto:\"acco<|>unt@example.com\"",S_OK,FALSE},
2402             {"mailto",S_OK,FALSE},
2403             {"",S_FALSE,FALSE},
2404             {"",S_FALSE,FALSE}
2405         },
2406         {
2407             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2408             {0,S_FALSE,FALSE},
2409             {URL_SCHEME_MAILTO,S_OK,FALSE},
2410             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2411         }
2412     },
2413     {   "news:test.tes<|>t.com", 0, S_OK, FALSE,
2414         {
2415             {"news:test.tes%3C%7C%3Et.com",S_OK,FALSE},
2416             {"",S_FALSE,FALSE},
2417             {"news:test.tes%3C%7C%3Et.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%3C%7C%3Et.com",S_OK,FALSE},
2424             {"test.tes%3C%7C%3Et.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     /* Don't encode forbidden characters. */
2439     {   "news:test.tes<|>t.com", Uri_CREATE_NO_ENCODE_FORBIDDEN_CHARACTERS, S_OK, FALSE,
2440         {
2441             {"news:test.tes<|>t.com",S_OK,FALSE},
2442             {"",S_FALSE,FALSE},
2443             {"news: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             {"news:test.tes<|>t.com",S_OK,FALSE},
2453             {"news",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_NEWS,S_OK,FALSE},
2461             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2462         }
2463     },
2464     /* Forbidden characters aren't encoded for unknown, opaque URIs. */
2465     {   "urn:test.tes<|>t.com", 0, S_OK, FALSE,
2466         {
2467             {"urn:test.tes<|>t.com",S_OK,FALSE},
2468             {"",S_FALSE,FALSE},
2469             {"urn:test.tes<|>t.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.tes<|>t.com",S_OK,FALSE},
2476             {"test.tes<|>t.com",S_OK,FALSE},
2477             {"",S_FALSE,FALSE},
2478             {"urn:test.tes<|>t.com",S_OK,FALSE},
2479             {"urn",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_UNKNOWN,S_OK,FALSE},
2487             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2488         }
2489     },
2490     /* Percent encoded unreserved characters are decoded for known opaque URIs. */
2491     {   "news:test.%74%65%73%74.com", 0, 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 are still decoded for known scheme types. */
2517     {   "news:test.%74%65%73%74.com", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
2518         {
2519             {"news:test.test.com",S_OK,FALSE},
2520             {"",S_FALSE,FALSE},
2521             {"news:test.test.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.test.com",S_OK,FALSE},
2528             {"test.test.com",S_OK,FALSE},
2529             {"",S_FALSE,FALSE},
2530             {"news:test.%74%65%73%74.com",S_OK,FALSE},
2531             {"news",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_NEWS,S_OK,FALSE},
2539             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2540         }
2541     },
2542     /* Percent encoded characters aren't decoded for unknown scheme types. */
2543     {   "urn:test.%74%65%73%74.com", 0, S_OK, FALSE,
2544         {
2545             {"urn:test.%74%65%73%74.com",S_OK,FALSE},
2546             {"",S_FALSE,FALSE},
2547             {"urn:test.%74%65%73%74.com",S_OK,FALSE},
2548             {"",S_FALSE,FALSE},
2549             {".com",S_OK,FALSE},
2550             {"",S_FALSE,FALSE},
2551             {"",S_FALSE,FALSE},
2552             {"",S_FALSE,FALSE},
2553             {"test.%74%65%73%74.com",S_OK,FALSE},
2554             {"test.%74%65%73%74.com",S_OK,FALSE},
2555             {"",S_FALSE,FALSE},
2556             {"urn:test.%74%65%73%74.com",S_OK,FALSE},
2557             {"urn",S_OK,FALSE},
2558             {"",S_FALSE,FALSE},
2559             {"",S_FALSE,FALSE}
2560         },
2561         {
2562             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2563             {0,S_FALSE,FALSE},
2564             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2565             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2566         }
2567     },
2568     /* Unknown scheme types can have invalid % encoded data in query string. */
2569     {   "zip://www.winehq.org/tests/..?query=%xx&return=y", 0, S_OK, FALSE,
2570         {
2571             {"zip://www.winehq.org/?query=%xx&return=y",S_OK,FALSE},
2572             {"www.winehq.org",S_OK,FALSE},
2573             {"zip://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             {"zip://www.winehq.org/tests/..?query=%xx&return=y",S_OK,FALSE},
2583             {"zip",S_OK,FALSE},
2584             {"",S_FALSE,FALSE},
2585             {"",S_FALSE,FALSE}
2586         },
2587         {
2588             {Uri_HOST_DNS,S_OK,FALSE},
2589             {0,S_FALSE,FALSE},
2590             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2591             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2592         }
2593     },
2594     /* Known scheme types can have invalid % encoded data with the right flags. */
2595     {   "http://www.winehq.org/tests/..?query=%xx&return=y", Uri_CREATE_NO_DECODE_EXTRA_INFO, S_OK, FALSE,
2596         {
2597             {"http://www.winehq.org/?query=%xx&return=y",S_OK,FALSE},
2598             {"www.winehq.org",S_OK,FALSE},
2599             {"http://www.winehq.org/?query=%xx&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=%xx&return=y",S_OK,FALSE},
2607             {"?query=%xx&return=y",S_OK,FALSE},
2608             {"http://www.winehq.org/tests/..?query=%xx&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_DECODE_EXTRA_INFO, 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 in query aren't percent encoded for known scheme types with this flag. */
2647     {   "http://www.winehq.org/tests/..?query=<|>&return=y", Uri_CREATE_NO_ENCODE_FORBIDDEN_CHARACTERS, S_OK, FALSE,
2648         {
2649             {"http://www.winehq.org/?query=<|>&return=y",S_OK,FALSE},
2650             {"www.winehq.org",S_OK,FALSE},
2651             {"http://www.winehq.org/?query=<|>&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=<|>&return=y",S_OK,FALSE},
2659             {"?query=<|>&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 encoded for known scheme types. */
2673     {   "http://www.winehq.org/tests/..?query=<|>&return=y", 0, S_OK, FALSE,
2674         {
2675             {"http://www.winehq.org/?query=%3C%7C%3E&return=y",S_OK,FALSE},
2676             {"www.winehq.org",S_OK,FALSE},
2677             {"http://www.winehq.org/?query=%3C%7C%3E&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=%3C%7C%3E&return=y",S_OK,FALSE},
2685             {"?query=%3C%7C%3E&return=y",S_OK,FALSE},
2686             {"http://www.winehq.org/tests/..?query=<|>&return=y",S_OK,FALSE},
2687             {"http",S_OK,FALSE},
2688             {"",S_FALSE,FALSE},
2689             {"",S_FALSE,FALSE}
2690         },
2691         {
2692             {Uri_HOST_DNS,S_OK,FALSE},
2693             {80,S_OK,FALSE},
2694             {URL_SCHEME_HTTP,S_OK,FALSE},
2695             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2696         }
2697     },
2698     /* Forbidden characters are not encoded for unknown scheme types. */
2699     {   "zip://www.winehq.org/tests/..?query=<|>&return=y", 0, S_OK, FALSE,
2700         {
2701             {"zip://www.winehq.org/?query=<|>&return=y",S_OK,FALSE},
2702             {"www.winehq.org",S_OK,FALSE},
2703             {"zip://www.winehq.org/?query=<|>&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=<|>&return=y",S_OK,FALSE},
2711             {"?query=<|>&return=y",S_OK,FALSE},
2712             {"zip://www.winehq.org/tests/..?query=<|>&return=y",S_OK,FALSE},
2713             {"zip",S_OK,FALSE},
2714             {"",S_FALSE,FALSE},
2715             {"",S_FALSE,FALSE}
2716         },
2717         {
2718             {Uri_HOST_DNS,S_OK,FALSE},
2719             {0,S_FALSE,FALSE},
2720             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2721             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2722         }
2723     },
2724     /* Percent encoded, unreserved characters are decoded for known scheme types. */
2725     {   "http://www.winehq.org/tests/..?query=%30%31&return=y", 0, S_OK, FALSE,
2726         {
2727             {"http://www.winehq.org/?query=01&return=y",S_OK,FALSE},
2728             {"www.winehq.org",S_OK,FALSE},
2729             {"http://www.winehq.org/?query=01&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=01&return=y",S_OK,FALSE},
2737             {"?query=01&return=y",S_OK,FALSE},
2738             {"http://www.winehq.org/tests/..?query=%30%31&return=y",S_OK,FALSE},
2739             {"http",S_OK,FALSE},
2740             {"",S_FALSE,FALSE},
2741             {"",S_FALSE,FALSE}
2742         },
2743         {
2744             {Uri_HOST_DNS,S_OK,FALSE},
2745             {80,S_OK,FALSE},
2746             {URL_SCHEME_HTTP,S_OK,FALSE},
2747             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2748         }
2749     },
2750     /* Percent encoded, unreserved characters aren't decoded for unknown scheme types. */
2751     {   "zip://www.winehq.org/tests/..?query=%30%31&return=y", 0, S_OK, FALSE,
2752         {
2753             {"zip://www.winehq.org/?query=%30%31&return=y",S_OK,FALSE},
2754             {"www.winehq.org",S_OK,FALSE},
2755             {"zip://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             {"zip://www.winehq.org/tests/..?query=%30%31&return=y",S_OK,FALSE},
2765             {"zip",S_OK,FALSE},
2766             {"",S_FALSE,FALSE},
2767             {"",S_FALSE,FALSE}
2768         },
2769         {
2770             {Uri_HOST_DNS,S_OK,FALSE},
2771             {0,S_FALSE,FALSE},
2772             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2773             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2774         }
2775     },
2776     /* Percent encoded characters aren't decoded when NO_DECODE_EXTRA_INFO is set. */
2777     {   "http://www.winehq.org/tests/..?query=%30%31&return=y", Uri_CREATE_NO_DECODE_EXTRA_INFO, S_OK, FALSE,
2778         {
2779             {"http://www.winehq.org/?query=%30%31&return=y",S_OK,FALSE},
2780             {"www.winehq.org",S_OK,FALSE},
2781             {"http://www.winehq.org/?query=%30%31&return=y",S_OK,FALSE},
2782             {"winehq.org",S_OK,FALSE},
2783             {"",S_FALSE,FALSE},
2784             {"",S_FALSE,FALSE},
2785             {"www.winehq.org",S_OK,FALSE},
2786             {"",S_FALSE,FALSE},
2787             {"/",S_OK,FALSE},
2788             {"/?query=%30%31&return=y",S_OK,FALSE},
2789             {"?query=%30%31&return=y",S_OK,FALSE},
2790             {"http://www.winehq.org/tests/..?query=%30%31&return=y",S_OK,FALSE},
2791             {"http",S_OK,FALSE},
2792             {"",S_FALSE,FALSE},
2793             {"",S_FALSE,FALSE}
2794         },
2795         {
2796             {Uri_HOST_DNS,S_OK,FALSE},
2797             {80,S_OK,FALSE},
2798             {URL_SCHEME_HTTP,S_OK,FALSE},
2799             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2800         }
2801     },
2802     {   "http://www.winehq.org?query=12&return=y", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
2803         {
2804             {"http://www.winehq.org?query=12&return=y",S_OK,FALSE},
2805             {"www.winehq.org",S_OK,FALSE},
2806             {"http://www.winehq.org?query=12&return=y",S_OK,FALSE},
2807             {"winehq.org",S_OK,FALSE},
2808             {"",S_FALSE,FALSE},
2809             {"",S_FALSE,FALSE},
2810             {"www.winehq.org",S_OK,FALSE},
2811             {"",S_FALSE,FALSE},
2812             {"",S_FALSE,FALSE},
2813             {"?query=12&return=y",S_OK,FALSE},
2814             {"?query=12&return=y",S_OK,FALSE},
2815             {"http://www.winehq.org?query=12&return=y",S_OK,FALSE},
2816             {"http",S_OK,FALSE},
2817             {"",S_FALSE,FALSE},
2818             {"",S_FALSE,FALSE}
2819         },
2820         {
2821             {Uri_HOST_DNS,S_OK,FALSE},
2822             {80,S_OK,FALSE},
2823             {URL_SCHEME_HTTP,S_OK,FALSE},
2824             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2825         }
2826     },
2827     /* Unknown scheme types can have invalid % encoded data in fragments. */
2828     {   "zip://www.winehq.org/tests/#Te%xx", 0, S_OK, FALSE,
2829         {
2830             {"zip://www.winehq.org/tests/#Te%xx",S_OK,FALSE},
2831             {"www.winehq.org",S_OK,FALSE},
2832             {"zip://www.winehq.org/tests/#Te%xx",S_OK,FALSE},
2833             {"winehq.org",S_OK,FALSE},
2834             {"",S_FALSE,FALSE},
2835             {"#Te%xx",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%xx",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 fragment aren't encoded for unknown schemes. */
2854     {   "zip://www.winehq.org/tests/#Te<|>", 0, S_OK, FALSE,
2855         {
2856             {"zip://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
2857             {"www.winehq.org",S_OK,FALSE},
2858             {"zip://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
2859             {"winehq.org",S_OK,FALSE},
2860             {"",S_FALSE,FALSE},
2861             {"#Te<|>",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             {"zip://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
2868             {"zip",S_OK,FALSE},
2869             {"",S_FALSE,FALSE},
2870             {"",S_FALSE,FALSE}
2871         },
2872         {
2873             {Uri_HOST_DNS,S_OK,FALSE},
2874             {0,S_FALSE,FALSE},
2875             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2876             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2877         }
2878     },
2879     /* Forbidden characters in the fragment are percent encoded for known schemes. */
2880     {   "http://www.winehq.org/tests/#Te<|>", 0, S_OK, FALSE,
2881         {
2882             {"http://www.winehq.org/tests/#Te%3C%7C%3E",S_OK,FALSE},
2883             {"www.winehq.org",S_OK,FALSE},
2884             {"http://www.winehq.org/tests/#Te%3C%7C%3E",S_OK,FALSE},
2885             {"winehq.org",S_OK,FALSE},
2886             {"",S_FALSE,FALSE},
2887             {"#Te%3C%7C%3E",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_DECODE_EXTRA_INFO, 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     /* Forbidden characters aren't encoded in the fragment with this flag. */
2932     {   "http://www.winehq.org/tests/#Te<|>", Uri_CREATE_NO_ENCODE_FORBIDDEN_CHARACTERS, S_OK, FALSE,
2933         {
2934             {"http://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
2935             {"www.winehq.org",S_OK,FALSE},
2936             {"http://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
2937             {"winehq.org",S_OK,FALSE},
2938             {"",S_FALSE,FALSE},
2939             {"#Te<|>",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             {"http://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
2946             {"http",S_OK,FALSE},
2947             {"",S_FALSE,FALSE},
2948             {"",S_FALSE,FALSE}
2949         },
2950         {
2951             {Uri_HOST_DNS,S_OK,FALSE},
2952             {80,S_OK,FALSE},
2953             {URL_SCHEME_HTTP,S_OK,FALSE},
2954             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2955         }
2956     },
2957     /* Percent encoded, unreserved characters aren't decoded for known scheme types. */
2958     {   "zip://www.winehq.org/tests/#Te%30%31%32", 0, S_OK, FALSE,
2959         {
2960             {"zip://www.winehq.org/tests/#Te%30%31%32",S_OK,FALSE},
2961             {"www.winehq.org",S_OK,FALSE},
2962             {"zip://www.winehq.org/tests/#Te%30%31%32",S_OK,FALSE},
2963             {"winehq.org",S_OK,FALSE},
2964             {"",S_FALSE,FALSE},
2965             {"#Te%30%31%32",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             {"zip://www.winehq.org/tests/#Te%30%31%32",S_OK,FALSE},
2972             {"zip",S_OK,FALSE},
2973             {"",S_FALSE,FALSE},
2974             {"",S_FALSE,FALSE}
2975         },
2976         {
2977             {Uri_HOST_DNS,S_OK,FALSE},
2978             {0,S_FALSE,FALSE},
2979             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2980             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2981         }
2982     },
2983     /* Percent encoded, unreserved characters are decoded for known schemes. */
2984     {   "http://www.winehq.org/tests/#Te%30%31%32", 0, 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 are decoded even if NO_CANONICALIZE is set. */
3010     {   "http://www.winehq.org/tests/#Te%30%31%32", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
3011         {
3012             {"http://www.winehq.org/tests/#Te012",S_OK,FALSE},
3013             {"www.winehq.org",S_OK,FALSE},
3014             {"http://www.winehq.org/tests/#Te012",S_OK,FALSE},
3015             {"winehq.org",S_OK,FALSE},
3016             {"",S_FALSE,FALSE},
3017             {"#Te012",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     /* Percent encoded, unreserved characters aren't decoded when NO_DECODE_EXTRA is set. */
3036     {   "http://www.winehq.org/tests/#Te%30%31%32", Uri_CREATE_NO_DECODE_EXTRA_INFO, S_OK, FALSE,
3037         {
3038             {"http://www.winehq.org/tests/#Te%30%31%32",S_OK,FALSE},
3039             {"www.winehq.org",S_OK,FALSE},
3040             {"http://www.winehq.org/tests/#Te%30%31%32",S_OK,FALSE},
3041             {"winehq.org",S_OK,FALSE},
3042             {"",S_FALSE,FALSE},
3043             {"#Te%30%31%32",S_OK,FALSE},
3044             {"www.winehq.org",S_OK,FALSE},
3045             {"",S_FALSE,FALSE},
3046             {"/tests/",S_OK,FALSE},
3047             {"/tests/",S_OK,FALSE},
3048             {"",S_FALSE,FALSE},
3049             {"http://www.winehq.org/tests/#Te%30%31%32",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     /* Leading/Trailing whitespace is removed. */
3062     {   "    http://google.com/     ", 0, S_OK, FALSE,
3063         {
3064             {"http://google.com/",S_OK,FALSE},
3065             {"google.com",S_OK,FALSE},
3066             {"http://google.com/",S_OK,FALSE},
3067             {"google.com",S_OK,FALSE},
3068             {"",S_FALSE,FALSE},
3069             {"",S_FALSE,FALSE},
3070             {"google.com",S_OK,FALSE},
3071             {"",S_FALSE,FALSE},
3072             {"/",S_OK,FALSE},
3073             {"/",S_OK,FALSE},
3074             {"",S_FALSE,FALSE},
3075             {"http://google.com/",S_OK,FALSE},
3076             {"http",S_OK,FALSE},
3077             {"",S_FALSE,FALSE},
3078             {"",S_FALSE,FALSE}
3079         },
3080         {
3081             {Uri_HOST_DNS,S_OK,FALSE},
3082             {80,S_OK,FALSE},
3083             {URL_SCHEME_HTTP,S_OK,FALSE},
3084             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3085         }
3086     },
3087     {   "\t\t\r\nhttp\n://g\noogle.co\rm/\n\n\n", 0, S_OK, FALSE,
3088         {
3089             {"http://google.com/",S_OK,FALSE},
3090             {"google.com",S_OK,FALSE},
3091             {"http://google.com/",S_OK,FALSE},
3092             {"google.com",S_OK,FALSE},
3093             {"",S_FALSE,FALSE},
3094             {"",S_FALSE,FALSE},
3095             {"google.com",S_OK,FALSE},
3096             {"",S_FALSE,FALSE},
3097             {"/",S_OK,FALSE},
3098             {"/",S_OK,FALSE},
3099             {"",S_FALSE,FALSE},
3100             {"http://google.com/",S_OK,FALSE},
3101             {"http",S_OK,FALSE},
3102             {"",S_FALSE,FALSE},
3103             {"",S_FALSE,FALSE}
3104         },
3105         {
3106             {Uri_HOST_DNS,S_OK,FALSE},
3107             {80,S_OK,FALSE},
3108             {URL_SCHEME_HTTP,S_OK,FALSE},
3109             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3110         }
3111     },
3112     {   "http://g\noogle.co\rm/\n\n\n", Uri_CREATE_NO_PRE_PROCESS_HTML_URI, S_OK, FALSE,
3113         {
3114             {"http://g%0aoogle.co%0dm/%0A%0A%0A",S_OK,FALSE},
3115             {"g%0aoogle.co%0dm",S_OK,FALSE},
3116             {"http://g%0aoogle.co%0dm/%0A%0A%0A",S_OK,FALSE},
3117             {"g%0aoogle.co%0dm",S_OK,FALSE},
3118             {"",S_FALSE,FALSE},
3119             {"",S_FALSE,FALSE},
3120             {"g%0aoogle.co%0dm",S_OK,FALSE},
3121             {"",S_FALSE,FALSE},
3122             {"/%0A%0A%0A",S_OK,FALSE},
3123             {"/%0A%0A%0A",S_OK,FALSE},
3124             {"",S_FALSE,FALSE},
3125             {"http://g\noogle.co\rm/\n\n\n",S_OK,FALSE},
3126             {"http",S_OK,FALSE},
3127             {"",S_FALSE,FALSE},
3128             {"",S_FALSE,FALSE}
3129         },
3130         {
3131             {Uri_HOST_DNS,S_OK,FALSE},
3132             {80,S_OK,FALSE},
3133             {URL_SCHEME_HTTP,S_OK,FALSE},
3134             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3135         }
3136     },
3137     {   "zip://g\noogle.co\rm/\n\n\n", Uri_CREATE_NO_PRE_PROCESS_HTML_URI, S_OK, FALSE,
3138         {
3139             {"zip://g\noogle.co\rm/\n\n\n",S_OK,FALSE},
3140             {"g\noogle.co\rm",S_OK,FALSE},
3141             {"zip://g\noogle.co\rm/\n\n\n",S_OK,FALSE},
3142             {"g\noogle.co\rm",S_OK,FALSE},
3143             {"",S_FALSE,FALSE},
3144             {"",S_FALSE,FALSE},
3145             {"g\noogle.co\rm",S_OK,FALSE},
3146             {"",S_FALSE,FALSE},
3147             {"/\n\n\n",S_OK,FALSE},
3148             {"/\n\n\n",S_OK,FALSE},
3149             {"",S_FALSE,FALSE},
3150             {"zip://g\noogle.co\rm/\n\n\n",S_OK,FALSE},
3151             {"zip",S_OK,FALSE},
3152             {"",S_FALSE,FALSE},
3153             {"",S_FALSE,FALSE}
3154         },
3155         {
3156             {Uri_HOST_DNS,S_OK,FALSE},
3157             {0,S_FALSE,FALSE},
3158             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
3159             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3160         }
3161     },
3162     /* Since file URLs are usually hierarchical, it returns an empty string
3163      * for the absolute URI property since it was declared as an opaque URI.
3164      */
3165     {   "file:index.html", 0, S_OK, FALSE,
3166         {
3167             {"",S_FALSE,FALSE},
3168             {"",S_FALSE,FALSE},
3169             {"file: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             {"index.html",S_OK,FALSE},
3176             {"index.html",S_OK,FALSE},
3177             {"",S_FALSE,FALSE},
3178             {"file:index.html",S_OK,FALSE},
3179             {"file",S_OK,FALSE},
3180             {"",S_FALSE,FALSE},
3181             {"",S_FALSE,FALSE}
3182         },
3183         {
3184             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3185             {0,S_FALSE,FALSE},
3186             {URL_SCHEME_FILE,S_OK,FALSE},
3187             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3188         }
3189     },
3190     /* Doesn't have an absolute since it's opaque, but gets it port set. */
3191     {   "http:test.com/index.html", 0, S_OK, FALSE,
3192         {
3193             {"",S_FALSE,FALSE},
3194             {"",S_FALSE,FALSE},
3195             {"http:test.com/index.html",S_OK,FALSE},
3196             {"",S_FALSE,FALSE},
3197             {".html",S_OK,FALSE},
3198             {"",S_FALSE,FALSE},
3199             {"",S_FALSE,FALSE},
3200             {"",S_FALSE,FALSE},
3201             {"test.com/index.html",S_OK,FALSE},
3202             {"test.com/index.html",S_OK,FALSE},
3203             {"",S_FALSE,FALSE},
3204             {"http:test.com/index.html",S_OK,FALSE},
3205             {"http",S_OK,FALSE},
3206             {"",S_FALSE,FALSE},
3207             {"",S_FALSE,FALSE}
3208         },
3209         {
3210             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3211             {80,S_OK,FALSE},
3212             {URL_SCHEME_HTTP,S_OK,FALSE},
3213             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3214         }
3215     },
3216     {   "ftp:test.com/index.html", 0, S_OK, FALSE,
3217         {
3218             {"",S_FALSE,FALSE},
3219             {"",S_FALSE,FALSE},
3220             {"ftp:test.com/index.html",S_OK,FALSE},
3221             {"",S_FALSE,FALSE},
3222             {".html",S_OK,FALSE},
3223             {"",S_FALSE,FALSE},
3224             {"",S_FALSE,FALSE},
3225             {"",S_FALSE,FALSE},
3226             {"test.com/index.html",S_OK,FALSE},
3227             {"test.com/index.html",S_OK,FALSE},
3228             {"",S_FALSE,FALSE},
3229             {"ftp:test.com/index.html",S_OK,FALSE},
3230             {"ftp",S_OK,FALSE},
3231             {"",S_FALSE,FALSE},
3232             {"",S_FALSE,FALSE}
3233         },
3234         {
3235             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3236             {21,S_OK,FALSE},
3237             {URL_SCHEME_FTP,S_OK,FALSE},
3238             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3239         }
3240     },
3241     {   "file://C|/test.mp3", 0, S_OK, FALSE,
3242         {
3243             {"file:///C:/test.mp3",S_OK,FALSE},
3244             {"",S_FALSE,FALSE},
3245             {"file:///C:/test.mp3",S_OK,FALSE},
3246             {"",S_FALSE,FALSE},
3247             {".mp3",S_OK,FALSE},
3248             {"",S_FALSE,FALSE},
3249             {"",S_FALSE,FALSE},
3250             {"",S_FALSE,FALSE},
3251             {"/C:/test.mp3",S_OK,FALSE},
3252             {"/C:/test.mp3",S_OK,FALSE},
3253             {"",S_FALSE,FALSE},
3254             {"file://C|/test.mp3",S_OK,FALSE},
3255             {"file",S_OK,FALSE},
3256             {"",S_FALSE,FALSE},
3257             {"",S_FALSE,FALSE}
3258         },
3259         {
3260             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3261             {0,S_FALSE,FALSE},
3262             {URL_SCHEME_FILE,S_OK,FALSE},
3263             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3264         }
3265     },
3266     {   "file:///C|/test.mp3", 0, S_OK, FALSE,
3267         {
3268             {"file:///C:/test.mp3",S_OK,FALSE},
3269             {"",S_FALSE,FALSE},
3270             {"file:///C:/test.mp3",S_OK,FALSE},
3271             {"",S_FALSE,FALSE},
3272             {".mp3",S_OK,FALSE},
3273             {"",S_FALSE,FALSE},
3274             {"",S_FALSE,FALSE},
3275             {"",S_FALSE,FALSE},
3276             {"/C:/test.mp3",S_OK,FALSE},
3277             {"/C:/test.mp3",S_OK,FALSE},
3278             {"",S_FALSE,FALSE},
3279             {"file:///C|/test.mp3",S_OK,FALSE},
3280             {"file",S_OK,FALSE},
3281             {"",S_FALSE,FALSE},
3282             {"",S_FALSE,FALSE}
3283         },
3284         {
3285             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3286             {0,S_FALSE,FALSE},
3287             {URL_SCHEME_FILE,S_OK,FALSE},
3288             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3289         }
3290     },
3291     /* Extra '/' isn't added before "c:" since USE_DOS_PATH is set and '/' are converted
3292      * to '\\'.
3293      */
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     /* Extra '/' after "file://" is removed. */
3320     {   "file:///c:/dir/index.html", Uri_CREATE_FILE_USE_DOS_PATH, S_OK, FALSE,
3321         {
3322             {"file://c:\\dir\\index.html",S_OK,FALSE},
3323             {"",S_FALSE,FALSE},
3324             {"file://c:\\dir\\index.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\\index.html",S_OK,FALSE},
3331             {"c:\\dir\\index.html",S_OK,FALSE},
3332             {"",S_FALSE,FALSE},
3333             {"file:///c:/dir/index.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     /* Allow more characters when Uri_CREATE_FILE_USE_DOS_PATH is specified */
3346     {   "file:///c:/dir\\%%61%20%5Fname/file%2A.html", Uri_CREATE_FILE_USE_DOS_PATH, S_OK, FALSE,
3347         {
3348             {"file://c:\\dir\\%a _name\\file*.html",S_OK,FALSE},
3349             {"",S_FALSE,FALSE},
3350             {"file://c:\\dir\\%a _name\\file*.html",S_OK,FALSE},
3351             {"",S_FALSE,FALSE},
3352             {".html",S_OK,FALSE},
3353             {"",S_FALSE,FALSE},
3354             {"",S_FALSE,FALSE},
3355             {"",S_FALSE,FALSE},
3356             {"c:\\dir\\%a _name\\file*.html",S_OK,FALSE},
3357             {"c:\\dir\\%a _name\\file*.html",S_OK,FALSE},
3358             {"",S_FALSE,FALSE},
3359             {"file:///c:/dir\\%%61%20%5Fname/file%2A.html",S_OK,FALSE},
3360             {"file",S_OK,FALSE},
3361             {"",S_FALSE,FALSE},
3362             {"",S_FALSE,FALSE}
3363         },
3364         {
3365             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3366             {0,S_FALSE,FALSE},
3367             {URL_SCHEME_FILE,S_OK,FALSE},
3368             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3369         }
3370     },
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     /* The backslashes after the scheme name are converted to forward slashes. */
3397     {   "file:\\\\c:\\dir\\index.html", Uri_CREATE_FILE_USE_DOS_PATH, S_OK, FALSE,
3398         {
3399             {"file://c:\\dir\\index.html",S_OK,FALSE},
3400             {"",S_FALSE,FALSE},
3401             {"file://c:\\dir\\index.html",S_OK,FALSE},
3402             {"",S_FALSE,FALSE},
3403             {".html",S_OK,FALSE},
3404             {"",S_FALSE,FALSE},
3405             {"",S_FALSE,FALSE},
3406             {"",S_FALSE,FALSE},
3407             {"c:\\dir\\index.html",S_OK,FALSE},
3408             {"c:\\dir\\index.html",S_OK,FALSE},
3409             {"",S_FALSE,FALSE},
3410             {"file:\\\\c:\\dir\\index.html",S_OK,FALSE},
3411             {"file",S_OK,FALSE},
3412             {"",S_FALSE,FALSE},
3413             {"",S_FALSE,FALSE}
3414         },
3415         {
3416             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3417             {0,S_FALSE,FALSE},
3418             {URL_SCHEME_FILE,S_OK,FALSE},
3419             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3420         }
3421     },
3422     {   "file:\\\\c:/dir/index.html", 0, S_OK, FALSE,
3423         {
3424             {"file:///c:/dir/index.html",S_OK,FALSE},
3425             {"",S_FALSE,FALSE},
3426             {"file:///c:/dir/index.html",S_OK,FALSE},
3427             {"",S_FALSE,FALSE},
3428             {".html",S_OK,FALSE},
3429             {"",S_FALSE,FALSE},
3430             {"",S_FALSE,FALSE},
3431             {"",S_FALSE,FALSE},
3432             {"/c:/dir/index.html",S_OK,FALSE},
3433             {"/c:/dir/index.html",S_OK,FALSE},
3434             {"",S_FALSE,FALSE},
3435             {"file:\\\\c:/dir/index.html",S_OK,FALSE},
3436             {"file",S_OK,FALSE},
3437             {"",S_FALSE,FALSE},
3438             {"",S_FALSE,FALSE}
3439         },
3440         {
3441             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3442             {0,S_FALSE,FALSE},
3443             {URL_SCHEME_FILE,S_OK,FALSE},
3444             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3445         }
3446     },
3447     {   "http:\\\\google.com", 0, S_OK, FALSE,
3448         {
3449             {"http://google.com/",S_OK,FALSE},
3450             {"google.com",S_OK,FALSE},
3451             {"http://google.com/",S_OK,FALSE},
3452             {"google.com",S_OK,FALSE},
3453             {"",S_FALSE,FALSE},
3454             {"",S_FALSE,FALSE},
3455             {"google.com",S_OK,FALSE},
3456             {"",S_FALSE,FALSE},
3457             {"/",S_OK,FALSE},
3458             {"/",S_OK,FALSE},
3459             {"",S_FALSE,FALSE},
3460             {"http:\\\\google.com",S_OK,FALSE},
3461             {"http",S_OK,FALSE},
3462             {"",S_FALSE,FALSE},
3463             {"",S_FALSE,FALSE}
3464         },
3465         {
3466             {Uri_HOST_DNS,S_OK,FALSE},
3467             {80,S_OK,FALSE},
3468             {URL_SCHEME_HTTP,S_OK,FALSE},
3469             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3470         }
3471     },
3472     /* the "\\\\" aren't converted to "//" for unknown scheme types and it's considered opaque. */
3473     {   "zip:\\\\google.com", 0, S_OK, FALSE,
3474         {
3475             {"zip:\\\\google.com",S_OK,FALSE},
3476             {"",S_FALSE,FALSE},
3477             {"zip:\\\\google.com",S_OK,FALSE},
3478             {"",S_FALSE,FALSE},
3479             {".com",S_OK,FALSE},
3480             {"",S_FALSE,FALSE},
3481             {"",S_FALSE,FALSE},
3482             {"",S_FALSE,FALSE},
3483             {"\\\\google.com",S_OK,FALSE},
3484             {"\\\\google.com",S_OK,FALSE},
3485             {"",S_FALSE,FALSE},
3486             {"zip:\\\\google.com",S_OK,FALSE},
3487             {"zip",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_UNKNOWN,S_OK,FALSE},
3495             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3496         }
3497     },
3498     /* Dot segments aren't removed. */
3499     {   "file://c:\\dir\\../..\\./index.html", Uri_CREATE_FILE_USE_DOS_PATH, S_OK, FALSE,
3500         {
3501             {"file://c:\\dir\\..\\..\\.\\index.html",S_OK,FALSE},
3502             {"",S_FALSE,FALSE},
3503             {"file://c:\\dir\\..\\..\\.\\index.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\\..\\..\\.\\index.html",S_OK,FALSE},
3510             {"c:\\dir\\..\\..\\.\\index.html",S_OK,FALSE},
3511             {"",S_FALSE,FALSE},
3512             {"file://c:\\dir\\../..\\./index.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     /* Forbidden characters aren't percent encoded. */
3525     {   "file://c:\\dir\\i^|ndex.html", Uri_CREATE_FILE_USE_DOS_PATH, S_OK, FALSE,
3526         {
3527             {"file://c:\\dir\\i^|ndex.html",S_OK,FALSE},
3528             {"",S_FALSE,FALSE},
3529             {"file://c:\\dir\\i^|ndex.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\\i^|ndex.html",S_OK,FALSE},
3536             {"c:\\dir\\i^|ndex.html",S_OK,FALSE},
3537             {"",S_FALSE,FALSE},
3538             {"file://c:\\dir\\i^|ndex.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     /* The '\' are still converted to '/' even though it's an opaque file URI. */
3551     {   "file:c:\\dir\\../..\\index.html", 0, 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     /* '/' are still converted to '\' even though it's an opaque URI. */
3577     {   "file:c:/dir\\../..\\index.html", Uri_CREATE_FILE_USE_DOS_PATH, S_OK, FALSE,
3578         {
3579             {"",S_FALSE,FALSE},
3580             {"",S_FALSE,FALSE},
3581             {"file:c:\\dir\\..\\..\\index.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:\\dir\\..\\..\\index.html",S_OK,FALSE},
3588             {"c:\\dir\\..\\..\\index.html",S_OK,FALSE},
3589             {"",S_FALSE,FALSE},
3590             {"file:c:/dir\\../..\\index.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     /* Forbidden characters aren't percent encoded. */
3603     {   "file:c:\\in^|dex.html", Uri_CREATE_FILE_USE_DOS_PATH, S_OK, FALSE,
3604         {
3605             {"",S_FALSE,FALSE},
3606             {"",S_FALSE,FALSE},
3607             {"file:c:\\in^|dex.html",S_OK,FALSE},
3608             {"",S_FALSE,FALSE},
3609             {".html",S_OK,FALSE},
3610             {"",S_FALSE,FALSE},
3611             {"",S_FALSE,FALSE},
3612             {"",S_FALSE,FALSE},
3613             {"c:\\in^|dex.html",S_OK,FALSE},
3614             {"c:\\in^|dex.html",S_OK,FALSE},
3615             {"",S_FALSE,FALSE},
3616             {"file:c:\\in^|dex.html",S_OK,FALSE},
3617             {"file",S_OK,FALSE},
3618             {"",S_FALSE,FALSE},
3619             {"",S_FALSE,FALSE}
3620         },
3621         {
3622             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3623             {0,S_FALSE,FALSE},
3624             {URL_SCHEME_FILE,S_OK,FALSE},
3625             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3626         }
3627     },
3628     /* Doesn't have a UserName since the ':' appears at the beginning of the
3629      * userinfo section.
3630      */
3631     {   "http://:password@gov.uk", 0, S_OK, FALSE,
3632         {
3633             {"http://:password@gov.uk/",S_OK,FALSE},
3634             {":password@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             {"password",S_OK,FALSE},
3641             {"/",S_OK,FALSE},
3642             {"/",S_OK,FALSE},
3643             {"",S_FALSE,FALSE},
3644             {"http://:password@gov.uk",S_OK,FALSE},
3645             {"http",S_OK,FALSE},
3646             {":password",S_OK,FALSE},
3647             {"",S_FALSE,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     /* Has a UserName since the userinfo section doesn't contain a password. */
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_FALSE,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_OK,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     /* ":@" not included in the absolute URI. */
3683     {   "http://:@gov.uk", 0, S_OK, FALSE,
3684         {
3685             {"http://gov.uk/",S_OK,FALSE,"http://:@gov.uk/"},
3686             {":@gov.uk",S_OK,FALSE},
3687             {"http://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_OK,FALSE},
3693             {"/",S_OK,FALSE},
3694             {"/",S_OK,FALSE},
3695             {"",S_FALSE,FALSE},
3696             {"http://:@gov.uk",S_OK,FALSE},
3697             {"http",S_OK,FALSE},
3698             {":",S_OK,FALSE},
3699             {"",S_FALSE,FALSE}
3700         },
3701         {
3702             {Uri_HOST_DNS,S_OK,FALSE},
3703             {80,S_OK,FALSE},
3704             {URL_SCHEME_HTTP,S_OK,FALSE},
3705             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3706         }
3707     },
3708     /* '@' is 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_FALSE,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_OK,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     /* ":@" are included because it's an unknown scheme type. */
3735     {   "zip://:@gov.uk", 0, S_OK, FALSE,
3736         {
3737             {"zip://:@gov.uk/",S_OK,FALSE},
3738             {":@gov.uk",S_OK,FALSE},
3739             {"zip://:@gov.uk/",S_OK,FALSE},
3740             {"",S_FALSE,FALSE},
3741             {"",S_FALSE,FALSE},
3742             {"",S_FALSE,FALSE},
3743             {"gov.uk",S_OK,FALSE},
3744             {"",S_OK,FALSE},
3745             {"/",S_OK,FALSE},
3746             {"/",S_OK,FALSE},
3747             {"",S_FALSE,FALSE},
3748             {"zip://:@gov.uk",S_OK,FALSE},
3749             {"zip",S_OK,FALSE},
3750             {":",S_OK,FALSE},
3751             {"",S_FALSE,FALSE}
3752         },
3753         {
3754             {Uri_HOST_DNS,S_OK,FALSE},
3755             {0,S_FALSE,FALSE},
3756             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
3757             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3758         }
3759     },
3760     {   "about:blank", 0, S_OK, FALSE,
3761         {
3762             {"about:blank",S_OK,FALSE},
3763             {"",S_FALSE,FALSE},
3764             {"about:blank",S_OK,FALSE},
3765             {"",S_FALSE,FALSE},
3766             {"",S_FALSE,FALSE},
3767             {"",S_FALSE,FALSE},
3768             {"",S_FALSE,FALSE},
3769             {"",S_FALSE,FALSE},
3770             {"blank",S_OK,FALSE},
3771             {"blank",S_OK,FALSE},
3772             {"",S_FALSE,FALSE},
3773             {"about:blank",S_OK,FALSE},
3774             {"about",S_OK,FALSE},
3775             {"",S_FALSE,FALSE},
3776             {"",S_FALSE,FALSE}
3777         },
3778         {
3779             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3780             {0,S_FALSE,FALSE},
3781             {URL_SCHEME_ABOUT,S_OK,FALSE},
3782             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3783         }
3784     },
3785     {   "mk:@MSITStore:C:\\Program Files/AutoCAD 2008\\Help/acad_acg.chm::/WSfacf1429558a55de1a7524c1004e616f8b-322b.htm",0,S_OK,FALSE,
3786         {
3787             {"mk:@MSITStore:C:\\Program%20Files/AutoCAD%202008\\Help/acad_acg.chm::/WSfacf1429558a55de1a7524c1004e616f8b-322b.htm",S_OK,FALSE},
3788             {"",S_FALSE,FALSE},
3789             {"mk:@MSITStore:C:\\Program%20Files/AutoCAD%202008\\Help/acad_acg.chm::/WSfacf1429558a55de1a7524c1004e616f8b-322b.htm",S_OK,FALSE},
3790             {"",S_FALSE,FALSE},
3791             {".htm",S_OK,FALSE},
3792             {"",S_FALSE,FALSE},
3793             {"",S_FALSE,FALSE},
3794             {"",S_FALSE,FALSE},
3795             {"@MSITStore:C:\\Program%20Files/AutoCAD%202008\\Help/acad_acg.chm::/WSfacf1429558a55de1a7524c1004e616f8b-322b.htm",S_OK,FALSE},
3796             {"@MSITStore:C:\\Program%20Files/AutoCAD%202008\\Help/acad_acg.chm::/WSfacf1429558a55de1a7524c1004e616f8b-322b.htm",S_OK,FALSE},
3797             {"",S_FALSE,FALSE},
3798             {"mk:@MSITStore:C:\\Program Files/AutoCAD 2008\\Help/acad_acg.chm::/WSfacf1429558a55de1a7524c1004e616f8b-322b.htm",S_OK,FALSE},
3799             {"mk",S_OK,FALSE},
3800             {"",S_FALSE,FALSE},
3801             {"",S_FALSE,FALSE}
3802         },
3803         {
3804             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3805             {0,S_FALSE,FALSE},
3806             {URL_SCHEME_MK,S_OK,FALSE},
3807             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3808         }
3809     },
3810     {   "mk:@MSITStore:Z:\\home\\test\\chm\\silqhelp.chm::/thesilqquickstartguide.htm",0,S_OK,FALSE,
3811         {
3812             {"mk:@MSITStore:Z:\\home\\test\\chm\\silqhelp.chm::/thesilqquickstartguide.htm",S_OK,FALSE},
3813             {"",S_FALSE,FALSE},
3814             {"mk:@MSITStore:Z:\\home\\test\\chm\\silqhelp.chm::/thesilqquickstartguide.htm",S_OK,FALSE},
3815             {"",S_FALSE,FALSE},
3816             {".htm",S_OK,FALSE},
3817             {"",S_FALSE,FALSE},
3818             {"",S_FALSE,FALSE},
3819             {"",S_FALSE,FALSE},
3820             {"@MSITStore:Z:\\home\\test\\chm\\silqhelp.chm::/thesilqquickstartguide.htm",S_OK,FALSE},
3821             {"@MSITStore:Z:\\home\\test\\chm\\silqhelp.chm::/thesilqquickstartguide.htm",S_OK,FALSE},
3822             {"",S_FALSE,FALSE},
3823             {"mk:@MSITStore:Z:\\home\\test\\chm\\silqhelp.chm::/thesilqquickstartguide.htm",S_OK,FALSE},
3824             {"mk",S_OK,FALSE},
3825             {"",S_FALSE,FALSE},
3826             {"",S_FALSE,FALSE}
3827         },
3828         {
3829             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3830             {0,S_FALSE,FALSE},
3831             {URL_SCHEME_MK,S_OK,FALSE},
3832             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3833         }
3834     },
3835     /* Two '\' are added to the URI when USE_DOS_PATH is set, and it's a UNC path. */
3836     {   "file://server/dir/index.html", Uri_CREATE_FILE_USE_DOS_PATH, S_OK, FALSE,
3837         {
3838             {"file://\\\\server\\dir\\index.html",S_OK,FALSE},
3839             {"server",S_OK,FALSE},
3840             {"file://\\\\server\\dir\\index.html",S_OK,FALSE},
3841             {"",S_FALSE,FALSE},
3842             {".html",S_OK,FALSE},
3843             {"",S_FALSE,FALSE},
3844             {"server",S_OK,FALSE},
3845             {"",S_FALSE,FALSE},
3846             {"\\dir\\index.html",S_OK,FALSE},
3847             {"\\dir\\index.html",S_OK,FALSE},
3848             {"",S_FALSE,FALSE},
3849             {"file://server/dir/index.html",S_OK,FALSE},
3850             {"file",S_OK,FALSE},
3851             {"",S_FALSE,FALSE},
3852             {"",S_FALSE,FALSE}
3853         },
3854         {
3855             {Uri_HOST_DNS,S_OK,FALSE},
3856             {0,S_FALSE,FALSE},
3857             {URL_SCHEME_FILE,S_OK,FALSE},
3858             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3859         }
3860     },
3861     /* When CreateUri generates an IUri, it still displays the default port in the
3862      * authority.
3863      */
3864     {   "http://google.com:80/", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
3865         {
3866             {"http://google.com:80/",S_OK,FALSE},
3867             {"google.com:80",S_OK,FALSE},
3868             {"http://google.com:80/",S_OK,FALSE},
3869             {"google.com",S_OK,FALSE},
3870             {"",S_FALSE,FALSE},
3871             {"",S_FALSE,FALSE},
3872             {"google.com",S_OK,FALSE},
3873             {"",S_FALSE,FALSE},
3874             {"/",S_OK,FALSE},
3875             {"/",S_OK,FALSE},
3876             {"",S_FALSE,FALSE},
3877             {"http://google.com:80/",S_OK,FALSE},
3878             {"http",S_OK,FALSE},
3879             {"",S_FALSE,FALSE},
3880             {"",S_FALSE,FALSE}
3881         },
3882         {
3883             {Uri_HOST_DNS,S_OK,FALSE},
3884             {80,S_OK,FALSE},
3885             {URL_SCHEME_HTTP,S_OK,FALSE},
3886             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3887         }
3888     },
3889     /* For res URIs the host is everything up until the first '/'. */
3890     {   "res://C:\\dir\\file.exe/DATA/test.html", 0, S_OK, FALSE,
3891         {
3892             {"res://C:\\dir\\file.exe/DATA/test.html",S_OK,FALSE},
3893             {"C:\\dir\\file.exe",S_OK,FALSE},
3894             {"res://C:\\dir\\file.exe/DATA/test.html",S_OK,FALSE},
3895             {"",S_FALSE,FALSE},
3896             {".html",S_OK,FALSE},
3897             {"",S_FALSE,FALSE},
3898             {"C:\\dir\\file.exe",S_OK,FALSE},
3899             {"",S_FALSE,FALSE},
3900             {"/DATA/test.html",S_OK,FALSE},
3901             {"/DATA/test.html",S_OK,FALSE},
3902             {"",S_FALSE,FALSE},
3903             {"res://C:\\dir\\file.exe/DATA/test.html",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 URI can contain a '|' in the host name. */
3916     {   "res://c:\\di|r\\file.exe/test", 0, S_OK, FALSE,
3917         {
3918             {"res://c:\\di|r\\file.exe/test",S_OK,FALSE},
3919             {"c:\\di|r\\file.exe",S_OK,FALSE},
3920             {"res://c:\\di|r\\file.exe/test",S_OK,FALSE},
3921             {"",S_FALSE,FALSE},
3922             {"",S_FALSE,FALSE},
3923             {"",S_FALSE,FALSE},
3924             {"c:\\di|r\\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:\\di|r\\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 URIs can have invalid percent encoded values. */
3942     {   "res://c:\\dir%xx\\file.exe/test", 0, S_OK, FALSE,
3943         {
3944             {"res://c:\\dir%xx\\file.exe/test",S_OK,FALSE},
3945             {"c:\\dir%xx\\file.exe",S_OK,FALSE},
3946             {"res://c:\\dir%xx\\file.exe/test",S_OK,FALSE},
3947             {"",S_FALSE,FALSE},
3948             {"",S_FALSE,FALSE},
3949             {"",S_FALSE,FALSE},
3950             {"c:\\dir%xx\\file.exe",S_OK,FALSE},
3951             {"",S_FALSE,FALSE},
3952             {"/test",S_OK,FALSE},
3953             {"/test",S_OK,FALSE},
3954             {"",S_FALSE,FALSE},
3955             {"res://c:\\dir%xx\\file.exe/test",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     /* Res doesn't get forbidden characters percent encoded in it's path. */
3968     {   "res://c:\\test/tes<|>t", 0, S_OK, FALSE,
3969         {
3970             {"res://c:\\test/tes<|>t",S_OK,FALSE},
3971             {"c:\\test",S_OK,FALSE},
3972             {"res://c:\\test/tes<|>t",S_OK,FALSE},
3973             {"",S_FALSE,FALSE},
3974             {"",S_FALSE,FALSE},
3975             {"",S_FALSE,FALSE},
3976             {"c:\\test",S_OK,FALSE},
3977             {"",S_FALSE,FALSE},
3978             {"/tes<|>t",S_OK,FALSE},
3979             {"/tes<|>t",S_OK,FALSE},
3980             {"",S_FALSE,FALSE},
3981             {"res://c:\\test/tes<|>t",S_OK,FALSE},
3982             {"res",S_OK,FALSE},
3983             {"",S_FALSE,FALSE},
3984             {"",S_FALSE,FALSE}
3985         },
3986         {
3987             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3988             {0,S_FALSE,FALSE},
3989             {URL_SCHEME_RES,S_OK,FALSE},
3990             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3991         }
3992     },
3993     {   "mk:@MSITStore:Z:\\dir\\test.chm::/html/../images/xxx.jpg", 0, S_OK, FALSE,
3994         {
3995             {"mk:@MSITStore:Z:\\dir\\test.chm::/images/xxx.jpg",S_OK,FALSE},
3996             {"",S_FALSE,FALSE},
3997             {"mk:@MSITStore:Z:\\dir\\test.chm::/images/xxx.jpg",S_OK,FALSE},
3998             {"",S_FALSE,FALSE},
3999             {".jpg",S_OK,FALSE},
4000             {"",S_FALSE,FALSE},
4001             {"",S_FALSE,FALSE},
4002             {"",S_FALSE,FALSE},
4003             {"@MSITStore:Z:\\dir\\test.chm::/images/xxx.jpg",S_OK,FALSE},
4004             {"@MSITStore:Z:\\dir\\test.chm::/images/xxx.jpg",S_OK,FALSE},
4005             {"",S_FALSE,FALSE},
4006             {"mk:@MSITStore:Z:\\dir\\test.chm::/html/../images/xxx.jpg",S_OK,FALSE},
4007             {"mk",S_OK,FALSE},
4008             {"",S_FALSE,FALSE},
4009             {"",S_FALSE,FALSE}
4010         },
4011         {
4012             {Uri_HOST_UNKNOWN,S_OK,FALSE},
4013             {0,S_FALSE,FALSE},
4014             {URL_SCHEME_MK,S_OK,FALSE},
4015             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4016         }
4017     },
4018     {   "mk:@MSITStore:Z:\\dir\\test.chm::/html/../images/xxx.jpg", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
4019         {
4020             {"mk:@MSITStore:Z:\\dir\\test.chm::/html/../images/xxx.jpg",S_OK,FALSE},
4021             {"",S_FALSE,FALSE},
4022             {"mk:@MSITStore:Z:\\dir\\test.chm::/html/../images/xxx.jpg",S_OK,FALSE},
4023             {"",S_FALSE,FALSE},
4024             {".jpg",S_OK,FALSE},
4025             {"",S_FALSE,FALSE},
4026             {"",S_FALSE,FALSE},
4027             {"",S_FALSE,FALSE},
4028             {"@MSITStore:Z:\\dir\\test.chm::/html/../images/xxx.jpg",S_OK,FALSE},
4029             {"@MSITStore:Z:\\dir\\test.chm::/html/../images/xxx.jpg",S_OK,FALSE},
4030             {"",S_FALSE,FALSE},
4031             {"mk:@MSITStore:Z:\\dir\\test.chm::/html/../images/xxx.jpg",S_OK,FALSE},
4032             {"mk",S_OK,FALSE},
4033             {"",S_FALSE,FALSE},
4034             {"",S_FALSE,FALSE}
4035         },
4036         {
4037             {Uri_HOST_UNKNOWN,S_OK,FALSE},
4038             {0,S_FALSE,FALSE},
4039             {URL_SCHEME_MK,S_OK,FALSE},
4040             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4041         }
4042     },
4043     {   "xx:@MSITStore:Z:\\dir\\test.chm::/html/../images/xxx.jpg", 0, S_OK, FALSE,
4044         {
4045             {"xx:@MSITStore:Z:\\dir\\test.chm::/html/../images/xxx.jpg",S_OK,FALSE},
4046             {"",S_FALSE,FALSE},
4047             {"xx:@MSITStore:Z:\\dir\\test.chm::/html/../images/xxx.jpg",S_OK,FALSE},
4048             {"",S_FALSE,FALSE},
4049             {".jpg",S_OK,FALSE},
4050             {"",S_FALSE,FALSE},
4051             {"",S_FALSE,FALSE},
4052             {"",S_FALSE,FALSE},
4053             {"@MSITStore:Z:\\dir\\test.chm::/html/../images/xxx.jpg",S_OK,FALSE},
4054             {"@MSITStore:Z:\\dir\\test.chm::/html/../images/xxx.jpg",S_OK,FALSE},
4055             {"",S_FALSE,FALSE},
4056             {"xx:@MSITStore:Z:\\dir\\test.chm::/html/../images/xxx.jpg",S_OK,FALSE},
4057             {"xx",S_OK,FALSE},
4058             {"",S_FALSE,FALSE},
4059             {"",S_FALSE,FALSE}
4060         },
4061         {
4062             {Uri_HOST_UNKNOWN,S_OK,FALSE},
4063             {0,S_FALSE,FALSE},
4064             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
4065             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4066         }
4067     },
4068     {   "mk:@MSITStore:Z:\\dir\\test.chm::/html/../../images/xxx.jpg", 0, S_OK, FALSE,
4069         {
4070             {"mk:@MSITStore:Z:\\dir\\images/xxx.jpg",S_OK,FALSE},
4071             {"",S_FALSE,FALSE},
4072             {"mk:@MSITStore:Z:\\dir\\images/xxx.jpg",S_OK,FALSE},
4073             {"",S_FALSE,FALSE},
4074             {".jpg",S_OK,FALSE},
4075             {"",S_FALSE,FALSE},
4076             {"",S_FALSE,FALSE},
4077             {"",S_FALSE,FALSE},
4078             {"@MSITStore:Z:\\dir\\images/xxx.jpg",S_OK,FALSE},
4079             {"@MSITStore:Z:\\dir\\images/xxx.jpg",S_OK,FALSE},
4080             {"",S_FALSE,FALSE},
4081             {"mk:@MSITStore:Z:\\dir\\test.chm::/html/../../images/xxx.jpg",S_OK,FALSE},
4082             {"mk",S_OK,FALSE},
4083             {"",S_FALSE,FALSE},
4084             {"",S_FALSE,FALSE}
4085         },
4086         {
4087             {Uri_HOST_UNKNOWN,S_OK,FALSE},
4088             {0,S_FALSE,FALSE},
4089             {URL_SCHEME_MK,S_OK,FALSE},
4090             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4091         }
4092     },
4093     {   "mk:@MSITStore:Z:\\dir\\dir2\\..\\test.chm::/html/../../images/xxx.jpg", 0, S_OK, FALSE,
4094         {
4095             {"mk:@MSITStore:Z:\\dir\\images/xxx.jpg",S_OK,FALSE},
4096             {"",S_FALSE,FALSE},
4097             {"mk:@MSITStore:Z:\\dir\\images/xxx.jpg",S_OK,FALSE},
4098             {"",S_FALSE,FALSE},
4099             {".jpg",S_OK,FALSE},
4100             {"",S_FALSE,FALSE},
4101             {"",S_FALSE,FALSE},
4102             {"",S_FALSE,FALSE},
4103             {"@MSITStore:Z:\\dir\\images/xxx.jpg",S_OK,FALSE},
4104             {"@MSITStore:Z:\\dir\\images/xxx.jpg",S_OK,FALSE},
4105             {"",S_FALSE,FALSE},
4106             {"mk:@MSITStore:Z:\\dir\\dir2\\..\\test.chm::/html/../../images/xxx.jpg",S_OK,FALSE},
4107             {"mk",S_OK,FALSE},
4108             {"",S_FALSE,FALSE},
4109             {"",S_FALSE,FALSE}
4110         },
4111         {
4112             {Uri_HOST_UNKNOWN,S_OK,FALSE},
4113             {0,S_FALSE,FALSE},
4114             {URL_SCHEME_MK,S_OK,FALSE},
4115             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4116         }
4117     },
4118     {   "mk:@MSITStore:Z:\\dir\\test.chm::/html/../../../../images/xxx.jpg", 0, S_OK, FALSE,
4119         {
4120             {"mk:images/xxx.jpg",S_OK,FALSE},
4121             {"",S_FALSE,FALSE},
4122             {"mk:images/xxx.jpg",S_OK,FALSE},
4123             {"",S_FALSE,FALSE},
4124             {".jpg",S_OK,FALSE},
4125             {"",S_FALSE,FALSE},
4126             {"",S_FALSE,FALSE},
4127             {"",S_FALSE,FALSE},
4128             {"images/xxx.jpg",S_OK,FALSE},
4129             {"images/xxx.jpg",S_OK,FALSE},
4130             {"",S_FALSE,FALSE},
4131             {"mk:@MSITStore:Z:\\dir\\test.chm::/html/../../../../images/xxx.jpg",S_OK,FALSE},
4132             {"mk",S_OK,FALSE},
4133             {"",S_FALSE,FALSE},
4134             {"",S_FALSE,FALSE}
4135         },
4136         {
4137             {Uri_HOST_UNKNOWN,S_OK,FALSE},
4138             {0,S_FALSE,FALSE},
4139             {URL_SCHEME_MK,S_OK,FALSE},
4140             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4141         }
4142     }
4143 };
4144
4145 typedef struct _invalid_uri {
4146     const char* uri;
4147     DWORD       flags;
4148     BOOL        todo;
4149 } invalid_uri;
4150
4151 static const invalid_uri invalid_uri_tests[] = {
4152     /* Has to have a scheme name. */
4153     {"://www.winehq.org",0,FALSE},
4154     /* Window's doesn't like URI's which are implicitly file paths without the
4155      * ALLOW_IMPLICIT_FILE_SCHEME flag set.
4156      */
4157     {"C:/test/test.mp3",0,FALSE},
4158     {"\\\\Server/test/test.mp3",0,FALSE},
4159     {"C:/test/test.mp3",Uri_CREATE_ALLOW_IMPLICIT_WILDCARD_SCHEME,FALSE},
4160     {"\\\\Server/test/test.mp3",Uri_CREATE_ALLOW_RELATIVE,FALSE},
4161     /* Invalid schemes. */
4162     {"*abcd://not.valid.com",0,FALSE},
4163     {"*a*b*c*d://not.valid.com",0,FALSE},
4164     /* Not allowed to have invalid % encoded data. */
4165     {"ftp://google.co%XX/",0,FALSE},
4166     /* To many h16 components. */
4167     {"http://[1:2:3:4:5:6:7:8:9]",0,FALSE},
4168     /* Not enough room for IPv4 address. */
4169     {"http://[1:2:3:4:5:6:7:192.0.1.0]",0,FALSE},
4170     /* Not enough h16 components. */
4171     {"http://[1:2:3:4]",0,FALSE},
4172     /* Not enough components including IPv4. */
4173     {"http://[1:192.0.1.0]",0,FALSE},
4174     /* Not allowed to have partial IPv4 in IPv6. */
4175     {"http://[::192.0]",0,FALSE},
4176     /* Can't have elision of 1 h16 at beginning of address. */
4177     {"http://[::2:3:4:5:6:7:8]",0,FALSE},
4178     /* Can't have elision of 1 h16 at end of address. */
4179     {"http://[1:2:3:4:5:6:7::]",0,FALSE},
4180     /* Expects a valid IP Literal. */
4181     {"ftp://[not.valid.uri]/",0,FALSE},
4182     /* Expects valid port for a known scheme type. */
4183     {"ftp://www.winehq.org:123fgh",0,FALSE},
4184     /* Port exceeds USHORT_MAX for known scheme type. */
4185     {"ftp://www.winehq.org:65536",0,FALSE},
4186     /* Invalid port with IPv4 address. */
4187     {"http://www.winehq.org:1abcd",0,FALSE},
4188     /* Invalid port with IPv6 address. */
4189     {"http://[::ffff]:32xy",0,FALSE},
4190     /* Not allowed to have backslashes with NO_CANONICALIZE. */
4191     {"gopher://www.google.com\\test",Uri_CREATE_NO_CANONICALIZE,FALSE},
4192     /* Not allowed to have invalid % encoded data in opaque URI path. */
4193     {"news:test%XX",0,FALSE},
4194     {"mailto:wine@winehq%G8.com",0,FALSE},
4195     /* Known scheme types can't have invalid % encoded data in query string. */
4196     {"http://google.com/?query=te%xx",0,FALSE},
4197     /* Invalid % encoded data in fragment of know scheme type. */
4198     {"ftp://google.com/#Test%xx",0,FALSE},
4199     {"  http://google.com/",Uri_CREATE_NO_PRE_PROCESS_HTML_URI,FALSE},
4200     {"\n\nhttp://google.com/",Uri_CREATE_NO_PRE_PROCESS_HTML_URI,FALSE},
4201     {"file://c:\\test<test",Uri_CREATE_FILE_USE_DOS_PATH,FALSE},
4202     {"file://c:\\test>test",Uri_CREATE_FILE_USE_DOS_PATH,FALSE},
4203     {"file://c:\\test\"test",Uri_CREATE_FILE_USE_DOS_PATH,FALSE},
4204     {"file:c:\\test<test",Uri_CREATE_FILE_USE_DOS_PATH,FALSE},
4205     {"file:c:\\test>test",Uri_CREATE_FILE_USE_DOS_PATH,FALSE},
4206     {"file:c:\\test\"test",Uri_CREATE_FILE_USE_DOS_PATH,FALSE},
4207     /* res URIs aren't allowed to have forbidden dos path characters in the
4208      * hostname.
4209      */
4210     {"res://c:\\te<st\\test/test",0,FALSE},
4211     {"res://c:\\te>st\\test/test",0,FALSE},
4212     {"res://c:\\te\"st\\test/test",0,FALSE},
4213     {"res://c:\\test/te%xxst",0,FALSE}
4214 };
4215
4216 typedef struct _uri_equality {
4217     const char* a;
4218     DWORD       create_flags_a;
4219     BOOL        create_todo_a;
4220     const char* b;
4221     DWORD       create_flags_b;
4222     BOOL        create_todo_b;
4223     BOOL        equal;
4224     BOOL        todo;
4225 } uri_equality;
4226
4227 static const uri_equality equality_tests[] = {
4228     {
4229         "HTTP://www.winehq.org/test dir/./",0,FALSE,
4230         "http://www.winehq.org/test dir/../test dir/",0,FALSE,
4231         TRUE, FALSE
4232     },
4233     {
4234         /* http://www.winehq.org/test%20dir */
4235         "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,
4236         "http://www.winehq.org/test dir",0,FALSE,
4237         TRUE, FALSE
4238     },
4239     {
4240         "c:\\test.mp3",Uri_CREATE_ALLOW_IMPLICIT_FILE_SCHEME,FALSE,
4241         "file:///c:/test.mp3",0,FALSE,
4242         TRUE, FALSE
4243     },
4244     {
4245         "ftp://ftp.winehq.org/",0,FALSE,
4246         "ftp://ftp.winehq.org",0,FALSE,
4247         TRUE, FALSE
4248     },
4249     {
4250         "ftp://ftp.winehq.org/test/test2/../../testB/",0,FALSE,
4251         "ftp://ftp.winehq.org/t%45stB/",0,FALSE,
4252         FALSE, FALSE
4253     },
4254     {
4255         "http://google.com/TEST",0,FALSE,
4256         "http://google.com/test",0,FALSE,
4257         FALSE, FALSE
4258     },
4259     {
4260         "http://GOOGLE.com/",0,FALSE,
4261         "http://google.com/",0,FALSE,
4262         TRUE, FALSE
4263     },
4264     /* Performs case insensitive compare of host names (for known scheme types). */
4265     {
4266         "ftp://GOOGLE.com/",Uri_CREATE_NO_CANONICALIZE,FALSE,
4267         "ftp://google.com/",0,FALSE,
4268         TRUE, FALSE
4269     },
4270     {
4271         "zip://GOOGLE.com/",0,FALSE,
4272         "zip://google.com/",0,FALSE,
4273         FALSE, FALSE
4274     },
4275     {
4276         "file:///c:/TEST/TeST/",0,FALSE,
4277         "file:///c:/test/test/",0,FALSE,
4278         TRUE, FALSE
4279     },
4280     {
4281         "file:///server/TEST",0,FALSE,
4282         "file:///SERVER/TEST",0,FALSE,
4283         TRUE, FALSE
4284     },
4285     {
4286         "http://google.com",Uri_CREATE_NO_CANONICALIZE,FALSE,
4287         "http://google.com/",0,FALSE,
4288         TRUE, FALSE
4289     },
4290     {
4291         "ftp://google.com:21/",0,FALSE,
4292         "ftp://google.com/",0,FALSE,
4293         TRUE, FALSE
4294     },
4295     {
4296         "http://google.com:80/",Uri_CREATE_NO_CANONICALIZE,FALSE,
4297         "http://google.com/",0,FALSE,
4298         TRUE, FALSE
4299     },
4300     {
4301         "http://google.com:70/",0,FALSE,
4302         "http://google.com:71/",0,FALSE,
4303         FALSE, FALSE
4304     }
4305 };
4306
4307 typedef struct _uri_with_fragment {
4308     const char* uri;
4309     const char* fragment;
4310     DWORD       create_flags;
4311     HRESULT     create_expected;
4312     BOOL        create_todo;
4313
4314     const char* expected_uri;
4315     BOOL        expected_todo;
4316 } uri_with_fragment;
4317
4318 static const uri_with_fragment uri_fragment_tests[] = {
4319     {
4320         "http://google.com/","#fragment",0,S_OK,FALSE,
4321         "http://google.com/#fragment",FALSE
4322     },
4323     {
4324         "http://google.com/","fragment",0,S_OK,FALSE,
4325         "http://google.com/#fragment",FALSE
4326     },
4327     {
4328         "zip://test.com/","?test",0,S_OK,FALSE,
4329         "zip://test.com/#?test",FALSE
4330     },
4331     /* The fragment can be empty. */
4332     {
4333         "ftp://ftp.google.com/","",0,S_OK,FALSE,
4334         "ftp://ftp.google.com/#",FALSE
4335     }
4336 };
4337
4338 typedef struct _uri_builder_property {
4339     BOOL            change;
4340     const char      *value;
4341     const char      *expected_value;
4342     Uri_PROPERTY    property;
4343     HRESULT         expected;
4344     BOOL            todo;
4345 } uri_builder_property;
4346
4347 typedef struct _uri_builder_port {
4348     BOOL    change;
4349     BOOL    set;
4350     DWORD   value;
4351     HRESULT expected;
4352     BOOL    todo;
4353 } uri_builder_port;
4354
4355 typedef struct _uri_builder_str_property {
4356     const char* expected;
4357     HRESULT     result;
4358     BOOL        todo;
4359 } uri_builder_str_property;
4360
4361 typedef struct _uri_builder_dword_property {
4362     DWORD   expected;
4363     HRESULT result;
4364     BOOL    todo;
4365 } uri_builder_dword_property;
4366
4367 typedef struct _uri_builder_test {
4368     const char                  *uri;
4369     DWORD                       create_flags;
4370     HRESULT                     create_builder_expected;
4371     BOOL                        create_builder_todo;
4372
4373     uri_builder_property        properties[URI_BUILDER_STR_PROPERTY_COUNT];
4374
4375     uri_builder_port            port_prop;
4376
4377     DWORD                       uri_flags;
4378     HRESULT                     uri_hres;
4379     BOOL                        uri_todo;
4380
4381     DWORD                       uri_simple_encode_flags;
4382     HRESULT                     uri_simple_hres;
4383     BOOL                        uri_simple_todo;
4384
4385     DWORD                       uri_with_flags;
4386     DWORD                       uri_with_builder_flags;
4387     DWORD                       uri_with_encode_flags;
4388     HRESULT                     uri_with_hres;
4389     BOOL                        uri_with_todo;
4390
4391     uri_builder_str_property    expected_str_props[URI_STR_PROPERTY_COUNT];
4392     uri_builder_dword_property  expected_dword_props[URI_DWORD_PROPERTY_COUNT];
4393 } uri_builder_test;
4394
4395 static const uri_builder_test uri_builder_tests[] = {
4396     {   "http://google.com/",0,S_OK,FALSE,
4397         {
4398             {TRUE,"#fragment",NULL,Uri_PROPERTY_FRAGMENT,S_OK,FALSE},
4399             {TRUE,"password",NULL,Uri_PROPERTY_PASSWORD,S_OK,FALSE},
4400             {TRUE,"?query=x",NULL,Uri_PROPERTY_QUERY,S_OK,FALSE},
4401             {TRUE,"username",NULL,Uri_PROPERTY_USER_NAME,S_OK,FALSE}
4402         },
4403         {FALSE},
4404         0,S_OK,FALSE,
4405         0,S_OK,FALSE,
4406         0,0,0,S_OK,FALSE,
4407         {
4408             {"http://username:password@google.com/?query=x#fragment",S_OK},
4409             {"username:password@google.com",S_OK},
4410             {"http://google.com/?query=x#fragment",S_OK},
4411             {"google.com",S_OK},
4412             {"",S_FALSE},
4413             {"#fragment",S_OK},
4414             {"google.com",S_OK},
4415             {"password",S_OK},
4416             {"/",S_OK},
4417             {"/?query=x",S_OK},
4418             {"?query=x",S_OK},
4419             {"http://username:password@google.com/?query=x#fragment",S_OK},
4420             {"http",S_OK},
4421             {"username:password",S_OK},
4422             {"username",S_OK}
4423         },
4424         {
4425             {Uri_HOST_DNS,S_OK},
4426             {80,S_OK},
4427             {URL_SCHEME_HTTP,S_OK},
4428             {URLZONE_INVALID,E_NOTIMPL}
4429         }
4430     },
4431     {   "http://google.com/",0,S_OK,FALSE,
4432         {
4433             {TRUE,"test",NULL,Uri_PROPERTY_SCHEME_NAME,S_OK,FALSE}
4434         },
4435         {TRUE,TRUE,120,S_OK,FALSE},
4436         0,S_OK,FALSE,
4437         0,S_OK,FALSE,
4438         0,0,0,S_OK,FALSE,
4439         {
4440             {"test://google.com:120/",S_OK},
4441             {"google.com:120",S_OK},
4442             {"test://google.com:120/",S_OK},
4443             {"google.com",S_OK},
4444             {"",S_FALSE},
4445             {"",S_FALSE},
4446             {"google.com",S_OK},
4447             {"",S_FALSE},
4448             {"/",S_OK},
4449             {"/",S_OK},
4450             {"",S_FALSE},
4451             {"test://google.com:120/",S_OK},
4452             {"test",S_OK},
4453             {"",S_FALSE},
4454             {"",S_FALSE}
4455         },
4456         {
4457             {Uri_HOST_DNS,S_OK},
4458             {120,S_OK},
4459             {URL_SCHEME_UNKNOWN,S_OK},
4460             {URLZONE_INVALID,E_NOTIMPL}
4461         }
4462     },
4463     {   "/Test/test dir",Uri_CREATE_ALLOW_RELATIVE,S_OK,FALSE,
4464         {
4465             {TRUE,"http",NULL,Uri_PROPERTY_SCHEME_NAME,S_OK,FALSE},
4466             {TRUE,"::192.2.3.4",NULL,Uri_PROPERTY_HOST,S_OK,FALSE},
4467             {TRUE,NULL,NULL,Uri_PROPERTY_PATH,S_OK,FALSE}
4468         },
4469         {FALSE},
4470         0,S_OK,FALSE,
4471         0,S_OK,FALSE,
4472         0,0,0,S_OK,FALSE,
4473         {
4474             {"http://[::192.2.3.4]/",S_OK},
4475             {"[::192.2.3.4]",S_OK},
4476             {"http://[::192.2.3.4]/",S_OK},
4477             {"",S_FALSE},
4478             {"",S_FALSE},
4479             {"",S_FALSE},
4480             {"::192.2.3.4",S_OK},
4481             {"",S_FALSE},
4482             {"/",S_OK},
4483             {"/",S_OK},
4484             {"",S_FALSE},
4485             {"http://[::192.2.3.4]/",S_OK},
4486             {"http",S_OK},
4487             {"",S_FALSE},
4488             {"",S_FALSE}
4489         },
4490         {
4491             {Uri_HOST_IPV6,S_OK},
4492             {80,S_OK},
4493             {URL_SCHEME_HTTP,S_OK},
4494             {URLZONE_INVALID,E_NOTIMPL}
4495         }
4496     },
4497     {   "http://google.com/",0,S_OK,FALSE,
4498         {
4499             {TRUE,"Frag","#Frag",Uri_PROPERTY_FRAGMENT,S_OK,FALSE}
4500         },
4501         {FALSE},
4502         0,S_OK,FALSE,
4503         0,S_OK,FALSE,
4504         0,0,0,S_OK,FALSE,
4505         {
4506             {"http://google.com/#Frag",S_OK},
4507             {"google.com",S_OK},
4508             {"http://google.com/#Frag",S_OK},
4509             {"google.com",S_OK},
4510             {"",S_FALSE},
4511             {"#Frag",S_OK},
4512             {"google.com",S_OK},
4513             {"",S_FALSE},
4514             {"/",S_OK},
4515             {"/",S_OK},
4516             {"",S_FALSE},
4517             {"http://google.com/#Frag",S_OK},
4518             {"http",S_OK},
4519             {"",S_FALSE},
4520             {"",S_FALSE}
4521         },
4522         {
4523             {Uri_HOST_DNS,S_OK},
4524             {80,S_OK},
4525             {URL_SCHEME_HTTP,S_OK},
4526             {URLZONE_INVALID,E_NOTIMPL}
4527         }
4528     },
4529     {   "http://google.com/",0,S_OK,FALSE,
4530         {
4531             {TRUE,"","#",Uri_PROPERTY_FRAGMENT,S_OK,FALSE},
4532         },
4533         {FALSE},
4534         0,S_OK,FALSE,
4535         0,S_OK,FALSE,
4536         0,0,0,S_OK,FALSE,
4537         {
4538             {"http://google.com/#",S_OK},
4539             {"google.com",S_OK},
4540             {"http://google.com/#",S_OK},
4541             {"google.com",S_OK},
4542             {"",S_FALSE},
4543             {"#",S_OK},
4544             {"google.com",S_OK},
4545             {"",S_FALSE},
4546             {"/",S_OK},
4547             {"/",S_OK},
4548             {"",S_FALSE},
4549             {"http://google.com/#",S_OK},
4550             {"http",S_OK},
4551             {"",S_FALSE},
4552             {"",S_FALSE}
4553         },
4554         {
4555             {Uri_HOST_DNS,S_OK},
4556             {80,S_OK},
4557             {URL_SCHEME_HTTP,S_OK},
4558             {URLZONE_INVALID,E_NOTIMPL}
4559         }
4560     },
4561     {   "http://google.com/",0,S_OK,FALSE,
4562         {
4563             {TRUE,":password",NULL,Uri_PROPERTY_PASSWORD,S_OK,FALSE}
4564         },
4565         {FALSE},
4566         0,S_OK,FALSE,
4567         0,S_OK,FALSE,
4568         0,0,0,S_OK,FALSE,
4569         {
4570             {"http://::password@google.com/",S_OK},
4571             {"::password@google.com",S_OK},
4572             {"http://google.com/",S_OK},
4573             {"google.com",S_OK},
4574             {"",S_FALSE},
4575             {"",S_FALSE},
4576             {"google.com",S_OK},
4577             {":password",S_OK},
4578             {"/",S_OK},
4579             {"/",S_OK},
4580             {"",S_FALSE},
4581             {"http://::password@google.com/",S_OK},
4582             {"http",S_OK},
4583             {"::password",S_OK},
4584             {"",S_FALSE}
4585         },
4586         {
4587             {Uri_HOST_DNS,S_OK},
4588             {80,S_OK},
4589             {URL_SCHEME_HTTP,S_OK},
4590             {URLZONE_INVALID,E_NOTIMPL}
4591         }
4592     },
4593     {   "test/test",Uri_CREATE_ALLOW_RELATIVE,S_OK,FALSE,
4594         {
4595             {TRUE,"password",NULL,Uri_PROPERTY_PASSWORD,S_OK,FALSE}
4596         },
4597         {FALSE},
4598         Uri_CREATE_ALLOW_RELATIVE,S_OK,FALSE,
4599         0,S_OK,FALSE,
4600         Uri_CREATE_ALLOW_RELATIVE,0,0,S_OK,FALSE,
4601         {
4602             {":password@test/test",S_OK},
4603             {":password@",S_OK},
4604             {":password@test/test",S_OK},
4605             {"",S_FALSE},
4606             {"",S_FALSE},
4607             {"",S_FALSE},
4608             {"",S_FALSE},
4609             {"password",S_OK},
4610             {"test/test",S_OK},
4611             {"test/test",S_OK},
4612             {"",S_FALSE},
4613             {":password@test/test",S_OK},
4614             {"",S_FALSE},
4615             {":password",S_OK},
4616             {"",S_FALSE}
4617         },
4618         {
4619             {Uri_HOST_UNKNOWN,S_OK},
4620             {0,S_FALSE},
4621             {URL_SCHEME_UNKNOWN,S_OK},
4622             {URLZONE_INVALID,E_NOTIMPL}
4623         }
4624     },
4625     {   "http://google.com/",0,S_OK,FALSE,
4626         {
4627             {TRUE,"test/test",NULL,Uri_PROPERTY_PATH,S_OK,FALSE},
4628         },
4629         {FALSE},
4630         0,S_OK,FALSE,
4631         0,S_OK,FALSE,
4632         0,0,0,S_OK,FALSE,
4633         {
4634             {"http://google.com/test/test",S_OK},
4635             {"google.com",S_OK},
4636             {"http://google.com/test/test",S_OK},
4637             {"google.com",S_OK},
4638             {"",S_FALSE},
4639             {"",S_FALSE},
4640             {"google.com",S_OK},
4641             {"",S_FALSE},
4642             {"/test/test",S_OK},
4643             {"/test/test",S_OK},
4644             {"",S_FALSE},
4645             {"http://google.com/test/test",S_OK},
4646             {"http",S_OK},
4647             {"",S_FALSE},
4648             {"",S_FALSE}
4649         },
4650         {
4651             {Uri_HOST_DNS,S_OK},
4652             {80,S_OK},
4653             {URL_SCHEME_HTTP,S_OK},
4654             {URLZONE_INVALID,E_NOTIMPL}
4655         }
4656     },
4657     {   "zip:testing/test",0,S_OK,FALSE,
4658         {
4659             {TRUE,"test",NULL,Uri_PROPERTY_PATH,S_OK,FALSE},
4660         },
4661         {FALSE},
4662         0,S_OK,FALSE,
4663         0,S_OK,FALSE,
4664         0,0,0,S_OK,FALSE,
4665         {
4666             {"zip:test",S_OK},
4667             {"",S_FALSE},
4668             {"zip:test",S_OK},
4669             {"",S_FALSE},
4670             {"",S_FALSE},
4671             {"",S_FALSE},
4672             {"",S_FALSE},
4673             {"",S_FALSE},
4674             {"test",S_OK},
4675             {"test",S_OK},
4676             {"",S_FALSE},
4677             {"zip:test",S_OK},
4678             {"zip",S_OK},
4679             {"",S_FALSE},
4680             {"",S_FALSE}
4681         },
4682         {
4683             {Uri_HOST_UNKNOWN,S_OK},
4684             {0,S_FALSE},
4685             {URL_SCHEME_UNKNOWN,S_OK},
4686             {URLZONE_INVALID,E_NOTIMPL}
4687         }
4688     },
4689     {   "http://google.com/",0,S_OK,FALSE,
4690         {
4691             {FALSE},
4692         },
4693         /* 555 will be returned from GetPort even though FALSE was passed as the hasPort parameter. */
4694         {TRUE,FALSE,555,S_OK,FALSE},
4695         0,S_OK,FALSE,
4696         0,S_OK,FALSE,
4697         0,0,0,S_OK,FALSE,
4698         {
4699             {"http://google.com/",S_OK},
4700             {"google.com",S_OK},
4701             {"http://google.com/",S_OK},
4702             {"google.com",S_OK},
4703             {"",S_FALSE},
4704             {"",S_FALSE},
4705             {"google.com",S_OK},
4706             {"",S_FALSE},
4707             {"/",S_OK},
4708             {"/",S_OK},
4709             {"",S_FALSE},
4710             {"http://google.com/",S_OK},
4711             {"http",S_OK},
4712             {"",S_FALSE},
4713             {"",S_FALSE}
4714         },
4715         {
4716             {Uri_HOST_DNS,S_OK},
4717             /* Still returns 80, even though earlier the port was disabled. */
4718             {80,S_OK},
4719             {URL_SCHEME_HTTP,S_OK},
4720             {URLZONE_INVALID,E_NOTIMPL}
4721         }
4722     },
4723     {   "http://google.com/",0,S_OK,FALSE,
4724         {
4725             {FALSE},
4726         },
4727         /* Instead of getting "TRUE" back as the "hasPort" parameter in GetPort,
4728          * you'll get 122345 instead.
4729          */
4730         {TRUE,122345,222,S_OK,FALSE},
4731         0,S_OK,FALSE,
4732         0,S_OK,FALSE,
4733         0,0,0,S_OK,FALSE,
4734         {
4735             {"http://google.com:222/",S_OK},
4736             {"google.com:222",S_OK},
4737             {"http://google.com:222/",S_OK},
4738             {"google.com",S_OK},
4739             {"",S_FALSE},
4740             {"",S_FALSE},
4741             {"google.com",S_OK},
4742             {"",S_FALSE},
4743             {"/",S_OK},
4744             {"/",S_OK},
4745             {"",S_FALSE},
4746             {"http://google.com:222/",S_OK},
4747             {"http",S_OK},
4748             {"",S_FALSE},
4749             {"",S_FALSE}
4750         },
4751         {
4752             {Uri_HOST_DNS,S_OK},
4753             {222,S_OK},
4754             {URL_SCHEME_HTTP,S_OK},
4755             {URLZONE_INVALID,E_NOTIMPL}
4756         }
4757     },
4758     /* IUri's created with the IUriBuilder can have ports that exceed USHORT_MAX. */
4759     {   "http://google.com/",0,S_OK,FALSE,
4760         {
4761             {FALSE},
4762         },
4763         {TRUE,TRUE,999999,S_OK,FALSE},
4764         0,S_OK,FALSE,
4765         0,S_OK,FALSE,
4766         0,0,0,S_OK,FALSE,
4767         {
4768             {"http://google.com:999999/",S_OK},
4769             {"google.com:999999",S_OK},
4770             {"http://google.com:999999/",S_OK},
4771             {"google.com",S_OK},
4772             {"",S_FALSE},
4773             {"",S_FALSE},
4774             {"google.com",S_OK},
4775             {"",S_FALSE},
4776             {"/",S_OK},
4777             {"/",S_OK},
4778             {"",S_FALSE},
4779             {"http://google.com:999999/",S_OK},
4780             {"http",S_OK},
4781             {"",S_FALSE},
4782             {"",S_FALSE}
4783         },
4784         {
4785             {Uri_HOST_DNS,S_OK},
4786             {999999,S_OK},
4787             {URL_SCHEME_HTTP,S_OK},
4788             {URLZONE_INVALID,E_NOTIMPL}
4789         }
4790     },
4791     {   "http://google.com/",0,S_OK,FALSE,
4792         {
4793             {TRUE,"test","?test",Uri_PROPERTY_QUERY,S_OK,FALSE},
4794         },
4795
4796         {FALSE},
4797         0,S_OK,FALSE,
4798         0,S_OK,FALSE,
4799         0,0,0,S_OK,FALSE,
4800         {
4801             {"http://google.com/?test",S_OK},
4802             {"google.com",S_OK},
4803             {"http://google.com/?test",S_OK},
4804             {"google.com",S_OK},
4805             {"",S_FALSE},
4806             {"",S_FALSE},
4807             {"google.com",S_OK},
4808             {"",S_FALSE},
4809             {"/",S_OK},
4810             {"/?test",S_OK},
4811             {"?test",S_OK},
4812             {"http://google.com/?test",S_OK},
4813             {"http",S_OK},
4814             {"",S_FALSE},
4815             {"",S_FALSE}
4816         },
4817         {
4818             {Uri_HOST_DNS,S_OK},
4819             {80,S_OK},
4820             {URL_SCHEME_HTTP,S_OK},
4821             {URLZONE_INVALID,E_NOTIMPL}
4822         }
4823     },
4824     {   "http://:password@google.com/",0,S_OK,FALSE,
4825         {
4826             {FALSE},
4827         },
4828         {FALSE},
4829         0,S_OK,FALSE,
4830         0,S_OK,FALSE,
4831         0,0,0,S_OK,FALSE,
4832         {
4833             {"http://:password@google.com/",S_OK},
4834             {":password@google.com",S_OK},
4835             {"http://google.com/",S_OK},
4836             {"google.com",S_OK},
4837             {"",S_FALSE},
4838             {"",S_FALSE},
4839             {"google.com",S_OK},
4840             {"password",S_OK},
4841             {"/",S_OK},
4842             {"/",S_OK},
4843             {"",S_FALSE},
4844             {"http://:password@google.com/",S_OK},
4845             {"http",S_OK},
4846             {":password",S_OK},
4847             {"",S_FALSE}
4848         },
4849         {
4850             {Uri_HOST_DNS,S_OK},
4851             {80,S_OK},
4852             {URL_SCHEME_HTTP,S_OK},
4853             {URLZONE_INVALID,E_NOTIMPL}
4854         }
4855     },
4856     /* IUriBuilder doesn't need a base IUri to build a IUri. */
4857     {   NULL,0,S_OK,FALSE,
4858         {
4859             {TRUE,"http",NULL,Uri_PROPERTY_SCHEME_NAME,S_OK,FALSE},
4860             {TRUE,"google.com",NULL,Uri_PROPERTY_HOST,S_OK,FALSE}
4861         },
4862         {FALSE},
4863         0,S_OK,FALSE,
4864         0,S_OK,FALSE,
4865         0,0,0,S_OK,FALSE,
4866         {
4867             {"http://google.com/",S_OK},
4868             {"google.com",S_OK},
4869             {"http://google.com/",S_OK},
4870             {"google.com",S_OK},
4871             {"",S_FALSE},
4872             {"",S_FALSE},
4873             {"google.com",S_OK},
4874             {"",S_FALSE},
4875             {"/",S_OK},
4876             {"/",S_OK},
4877             {"",S_FALSE},
4878             {"http://google.com/",S_OK},
4879             {"http",S_OK},
4880             {"",S_FALSE},
4881             {"",S_FALSE}
4882         },
4883         {
4884             {Uri_HOST_DNS,S_OK},
4885             {80,S_OK},
4886             {URL_SCHEME_HTTP,S_OK},
4887             {URLZONE_INVALID,E_NOTIMPL}
4888         }
4889     },
4890     /* Can't set the scheme name to NULL. */
4891     {   "zip://google.com/",0,S_OK,FALSE,
4892         {
4893             {TRUE,NULL,"zip",Uri_PROPERTY_SCHEME_NAME,E_INVALIDARG,FALSE}
4894         },
4895         {FALSE},
4896         0,S_OK,FALSE,
4897         0,S_OK,FALSE,
4898         0,0,0,S_OK,FALSE,
4899         {
4900             {"zip://google.com/",S_OK},
4901             {"google.com",S_OK},
4902             {"zip://google.com/",S_OK},
4903             {"google.com",S_OK},
4904             {"",S_FALSE},
4905             {"",S_FALSE},
4906             {"google.com",S_OK},
4907             {"",S_FALSE},
4908             {"/",S_OK},
4909             {"/",S_OK},
4910             {"",S_FALSE},
4911             {"zip://google.com/",S_OK},
4912             {"zip",S_OK},
4913             {"",S_FALSE},
4914             {"",S_FALSE}
4915         },
4916         {
4917             {Uri_HOST_DNS,S_OK},
4918             {0,S_FALSE},
4919             {URL_SCHEME_UNKNOWN,S_OK},
4920             {URLZONE_INVALID,E_NOTIMPL}
4921         }
4922     },
4923     /* Can't set the scheme name to an empty string. */
4924     {   "zip://google.com/",0,S_OK,FALSE,
4925         {
4926             {TRUE,"","zip",Uri_PROPERTY_SCHEME_NAME,E_INVALIDARG,FALSE}
4927         },
4928         {FALSE},
4929         0,S_OK,FALSE,
4930         0,S_OK,FALSE,
4931         0,0,0,S_OK,FALSE,
4932         {
4933             {"zip://google.com/",S_OK},
4934             {"google.com",S_OK},
4935             {"zip://google.com/",S_OK},
4936             {"google.com",S_OK},
4937             {"",S_FALSE},
4938             {"",S_FALSE},
4939             {"google.com",S_OK},
4940             {"",S_FALSE},
4941             {"/",S_OK},
4942             {"/",S_OK},
4943             {"",S_FALSE},
4944             {"zip://google.com/",S_OK},
4945             {"zip",S_OK},
4946             {"",S_FALSE},
4947             {"",S_FALSE}
4948         },
4949         {
4950             {Uri_HOST_DNS,S_OK},
4951             {0,S_FALSE},
4952             {URL_SCHEME_UNKNOWN,S_OK},
4953             {URLZONE_INVALID,E_NOTIMPL}
4954         }
4955     },
4956     /* -1 to CreateUri makes it use the same flags as the base IUri was created with.
4957      * CreateUriSimple always uses the flags the base IUri was created with (if any).
4958      */
4959     {   "http://google.com/../../",Uri_CREATE_NO_CANONICALIZE,S_OK,FALSE,
4960         {{FALSE}},
4961         {FALSE},
4962         -1,S_OK,FALSE,
4963         0,S_OK,FALSE,
4964         0,UriBuilder_USE_ORIGINAL_FLAGS,0,S_OK,FALSE,
4965         {
4966             {"http://google.com/../../",S_OK},
4967             {"google.com",S_OK},
4968             {"http://google.com/../../",S_OK},
4969             {"google.com",S_OK},
4970             {"",S_FALSE},
4971             {"",S_FALSE},
4972             {"google.com",S_OK},
4973             {"",S_FALSE},
4974             {"/../../",S_OK},
4975             {"/../../",S_OK},
4976             {"",S_FALSE},
4977             {"http://google.com/../../",S_OK},
4978             {"http",S_OK},
4979             {"",S_FALSE},
4980             {"",S_FALSE}
4981         },
4982         {
4983             {Uri_HOST_DNS,S_OK},
4984             {80,S_OK},
4985             {URL_SCHEME_HTTP,S_OK},
4986             {URLZONE_INVALID,E_NOTIMPL}
4987         }
4988     },
4989     {   "http://google.com/",0,S_OK,FALSE,
4990         {
4991             {TRUE,"#Fr<|>g",NULL,Uri_PROPERTY_FRAGMENT,S_OK,FALSE}
4992         },
4993         {FALSE},
4994         -1,S_OK,FALSE,
4995         0,S_OK,FALSE,
4996         Uri_CREATE_NO_DECODE_EXTRA_INFO,UriBuilder_USE_ORIGINAL_FLAGS,0,S_OK,FALSE,
4997         {
4998             {"http://google.com/#Fr%3C%7C%3Eg",S_OK},
4999             {"google.com",S_OK},
5000             {"http://google.com/#Fr%3C%7C%3Eg",S_OK},
5001             {"google.com",S_OK},
5002             {"",S_FALSE},
5003             {"#Fr%3C%7C%3Eg",S_OK},
5004             {"google.com",S_OK},
5005             {"",S_FALSE},
5006             {"/",S_OK},
5007             {"/",S_OK},
5008             {"",S_FALSE},
5009             {"http://google.com/#Fr<|>g",S_OK},
5010             {"http",S_OK},
5011             {"",S_FALSE},
5012             {"",S_FALSE}
5013         },
5014         {
5015             {Uri_HOST_DNS,S_OK},
5016             {80,S_OK},
5017             {URL_SCHEME_HTTP,S_OK},
5018             {URLZONE_INVALID,E_NOTIMPL}
5019         }
5020     },
5021     {   "http://google.com/",0,S_OK,FALSE,
5022         {
5023             {TRUE,"#Fr<|>g",NULL,Uri_PROPERTY_FRAGMENT,S_OK,FALSE}
5024         },
5025         {FALSE},
5026         Uri_CREATE_CANONICALIZE|Uri_CREATE_NO_CANONICALIZE,E_INVALIDARG,FALSE,
5027         0,S_OK,FALSE,
5028         Uri_CREATE_CANONICALIZE|Uri_CREATE_NO_CANONICALIZE,UriBuilder_USE_ORIGINAL_FLAGS,0,S_OK,FALSE,
5029         {
5030             {"http://google.com/#Fr%3C%7C%3Eg",S_OK},
5031             {"google.com",S_OK},
5032             {"http://google.com/#Fr%3C%7C%3Eg",S_OK},
5033             {"google.com",S_OK},
5034             {"",S_FALSE},
5035             {"#Fr%3C%7C%3Eg",S_OK},
5036             {"google.com",S_OK},
5037             {"",S_FALSE},
5038             {"/",S_OK},
5039             {"/",S_OK},
5040             {"",S_FALSE},
5041             {"http://google.com/#Fr<|>g",S_OK},
5042             {"http",S_OK},
5043             {"",S_FALSE},
5044             {"",S_FALSE}
5045         },
5046         {
5047             {Uri_HOST_DNS,S_OK},
5048             {80,S_OK},
5049             {URL_SCHEME_HTTP,S_OK},
5050             {URLZONE_INVALID,E_NOTIMPL}
5051         }
5052     },
5053     {   NULL,0,S_OK,FALSE,
5054         {
5055             {TRUE,"/test/test/",NULL,Uri_PROPERTY_PATH,S_OK,FALSE},
5056             {TRUE,"#Fr<|>g",NULL,Uri_PROPERTY_FRAGMENT,S_OK,FALSE}
5057         },
5058         {FALSE},
5059         0,INET_E_INVALID_URL,FALSE,
5060         0,INET_E_INVALID_URL,FALSE,
5061         0,0,0,INET_E_INVALID_URL,FALSE
5062     },
5063     {   "http://google.com/",0,S_OK,FALSE,
5064         {
5065             {TRUE,"ht%xxtp",NULL,Uri_PROPERTY_SCHEME_NAME,S_OK,FALSE}
5066         },
5067         {FALSE},
5068         0,INET_E_INVALID_URL,FALSE,
5069         0,INET_E_INVALID_URL,FALSE,
5070         0,0,0,INET_E_INVALID_URL,FALSE
5071     },
5072     /* File scheme's can't have a username set. */
5073     {   "file://google.com/",0,S_OK,FALSE,
5074         {
5075             {TRUE,"username",NULL,Uri_PROPERTY_USER_NAME,S_OK,FALSE}
5076         },
5077         {FALSE},
5078         0,INET_E_INVALID_URL,FALSE,
5079         0,INET_E_INVALID_URL,FALSE,
5080         0,0,0,INET_E_INVALID_URL,FALSE
5081     },
5082     /* File schemes can't have a password set. */
5083     {   "file://google.com/",0,S_OK,FALSE,
5084         {
5085             {TRUE,"password",NULL,Uri_PROPERTY_PASSWORD,S_OK,FALSE}
5086         },
5087         {FALSE},
5088         0,INET_E_INVALID_URL,FALSE,
5089         0,INET_E_INVALID_URL,FALSE,
5090         0,0,0,INET_E_INVALID_URL,FALSE
5091     },
5092     /* UserName can't contain any character that is a delimeter for another
5093      * component that appears after it in a normal URI.
5094      */
5095     {   "http://google.com/",0,S_OK,FALSE,
5096         {
5097             {TRUE,"user:pass",NULL,Uri_PROPERTY_USER_NAME,S_OK,FALSE}
5098         },
5099         {FALSE},
5100         0,INET_E_INVALID_URL,FALSE,
5101         0,INET_E_INVALID_URL,FALSE,
5102         0,0,0,INET_E_INVALID_URL,FALSE
5103     },
5104     {   "http://google.com/",0,S_OK,FALSE,
5105         {
5106             {TRUE,"user@google.com",NULL,Uri_PROPERTY_USER_NAME,S_OK,FALSE}
5107         },
5108         {FALSE},
5109         0,INET_E_INVALID_URL,FALSE,
5110         0,INET_E_INVALID_URL,FALSE,
5111         0,0,0,INET_E_INVALID_URL,FALSE
5112     },
5113     {   "http://google.com/",0,S_OK,FALSE,
5114         {
5115             {TRUE,"user/path",NULL,Uri_PROPERTY_USER_NAME,S_OK,FALSE}
5116         },
5117         {FALSE},
5118         0,INET_E_INVALID_URL,FALSE,
5119         0,INET_E_INVALID_URL,FALSE,
5120         0,0,0,INET_E_INVALID_URL,FALSE
5121     },
5122     {   "http://google.com/",0,S_OK,FALSE,
5123         {
5124             {TRUE,"user?Query",NULL,Uri_PROPERTY_USER_NAME,S_OK,FALSE}
5125         },
5126         {FALSE},
5127         0,INET_E_INVALID_URL,FALSE,
5128         0,INET_E_INVALID_URL,FALSE,
5129         0,0,0,INET_E_INVALID_URL,FALSE
5130     },
5131     {   "http://google.com/",0,S_OK,FALSE,
5132         {
5133             {TRUE,"user#Frag",NULL,Uri_PROPERTY_USER_NAME,S_OK,FALSE}
5134         },
5135         {FALSE},
5136         0,INET_E_INVALID_URL,FALSE,
5137         0,INET_E_INVALID_URL,FALSE,
5138         0,0,0,INET_E_INVALID_URL,FALSE
5139     },
5140     {   "http://google.com/",0,S_OK,FALSE,
5141         {
5142             {TRUE,"pass@google.com",NULL,Uri_PROPERTY_PASSWORD,S_OK,FALSE}
5143         },
5144         {FALSE},
5145         0,INET_E_INVALID_URL,FALSE,
5146         0,INET_E_INVALID_URL,FALSE,
5147         0,0,0,INET_E_INVALID_URL,FALSE
5148     },
5149     {   "http://google.com/",0,S_OK,FALSE,
5150         {
5151             {TRUE,"pass/path",NULL,Uri_PROPERTY_PASSWORD,S_OK,FALSE}
5152         },
5153         {FALSE},
5154         0,INET_E_INVALID_URL,FALSE,
5155         0,INET_E_INVALID_URL,FALSE,
5156         0,0,0,INET_E_INVALID_URL,FALSE
5157     },
5158     {   "http://google.com/",0,S_OK,FALSE,
5159         {
5160             {TRUE,"pass?query",NULL,Uri_PROPERTY_PASSWORD,S_OK,FALSE}
5161         },
5162         {FALSE},
5163         0,INET_E_INVALID_URL,FALSE,
5164         0,INET_E_INVALID_URL,FALSE,
5165        0,0,0,INET_E_INVALID_URL,FALSE
5166     },
5167     {   "http://google.com/",0,S_OK,FALSE,
5168         {
5169             {TRUE,"pass#frag",NULL,Uri_PROPERTY_PASSWORD,S_OK,FALSE}
5170         },
5171         {FALSE},
5172         0,INET_E_INVALID_URL,FALSE,
5173         0,INET_E_INVALID_URL,FALSE,
5174         0,0,0,INET_E_INVALID_URL,FALSE
5175     },
5176     {   "http://google.com/",0,S_OK,FALSE,
5177         {
5178             {TRUE,"winehq.org/test",NULL,Uri_PROPERTY_HOST,S_OK,FALSE}
5179         },
5180         {FALSE},
5181         0,INET_E_INVALID_URL,FALSE,
5182         0,INET_E_INVALID_URL,FALSE,
5183         0,0,0,INET_E_INVALID_URL,FALSE
5184     },
5185     {   "http://google.com/",0,S_OK,FALSE,
5186         {
5187             {TRUE,"winehq.org?test",NULL,Uri_PROPERTY_HOST,S_OK,FALSE}
5188         },
5189         {FALSE},
5190         0,INET_E_INVALID_URL,FALSE,
5191         0,INET_E_INVALID_URL,FALSE,
5192         0,0,0,INET_E_INVALID_URL,FALSE
5193     },
5194     {   "http://google.com/",0,S_OK,FALSE,
5195         {
5196             {TRUE,"winehq.org#test",NULL,Uri_PROPERTY_HOST,S_OK,FALSE}
5197         },
5198         {FALSE},
5199         0,INET_E_INVALID_URL,FALSE,
5200         0,INET_E_INVALID_URL,FALSE,
5201         0,0,0,INET_E_INVALID_URL,FALSE
5202     },
5203     /* Hostname is allowed to contain a ':' (even for known scheme types). */
5204     {   "http://google.com/",0,S_OK,FALSE,
5205         {
5206             {TRUE,"winehq.org:test",NULL,Uri_PROPERTY_HOST,S_OK,FALSE},
5207         },
5208         {FALSE},
5209         0,S_OK,FALSE,
5210         0,S_OK,FALSE,
5211         0,0,0,S_OK,FALSE,
5212         {
5213             {"http://winehq.org:test/",S_OK},
5214             {"winehq.org:test",S_OK},
5215             {"http://winehq.org:test/",S_OK},
5216             {"winehq.org:test",S_OK},
5217             {"",S_FALSE},
5218             {"",S_FALSE},
5219             {"winehq.org:test",S_OK},
5220             {"",S_FALSE},
5221             {"/",S_OK},
5222             {"/",S_OK},
5223             {"",S_FALSE},
5224             {"http://winehq.org:test/",S_OK},
5225             {"http",S_OK},
5226             {"",S_FALSE},
5227             {"",S_FALSE}
5228         },
5229         {
5230             {Uri_HOST_DNS,S_OK},
5231             {80,S_OK},
5232             {URL_SCHEME_HTTP,S_OK},
5233             {URLZONE_INVALID,E_NOTIMPL}
5234         }
5235     },
5236     /* Can't set the host name to NULL. */
5237     {   "http://google.com/",0,S_OK,FALSE,
5238         {
5239             {TRUE,NULL,"google.com",Uri_PROPERTY_HOST,E_INVALIDARG,FALSE}
5240         },
5241         {FALSE},
5242         0,S_OK,FALSE,
5243         0,S_OK,FALSE,
5244         0,0,0,S_OK,FALSE,
5245         {
5246             {"http://google.com/",S_OK},
5247             {"google.com",S_OK},
5248             {"http://google.com/",S_OK},
5249             {"google.com",S_OK},
5250             {"",S_FALSE},
5251             {"",S_FALSE},
5252             {"google.com",S_OK},
5253             {"",S_FALSE},
5254             {"/",S_OK},
5255             {"/",S_OK},
5256             {"",S_FALSE},
5257             {"http://google.com/",S_OK},
5258             {"http",S_OK},
5259             {"",S_FALSE},
5260             {"",S_FALSE}
5261         },
5262         {
5263             {Uri_HOST_DNS,S_OK},
5264             {80,S_OK},
5265             {URL_SCHEME_HTTP,S_OK},
5266             {URLZONE_INVALID,E_NOTIMPL}
5267         }
5268     },
5269     /* Can set the host name to an empty string. */
5270     {   "http://google.com/",0,S_OK,FALSE,
5271         {
5272             {TRUE,"",NULL,Uri_PROPERTY_HOST,S_OK,FALSE}
5273         },
5274         {FALSE},
5275         0,S_OK,FALSE,
5276         0,S_OK,FALSE,
5277         0,0,0,S_OK,FALSE,
5278         {
5279             {"http:///",S_OK},
5280             {"",S_OK},
5281             {"http:///",S_OK},
5282             {"",S_FALSE},
5283             {"",S_FALSE},
5284             {"",S_FALSE},
5285             {"",S_OK},
5286             {"",S_FALSE},
5287             {"/",S_OK},
5288             {"/",S_OK},
5289             {"",S_FALSE},
5290             {"http:///",S_OK},
5291             {"http",S_OK},
5292             {"",S_FALSE},
5293             {"",S_FALSE}
5294         },
5295         {
5296             {Uri_HOST_UNKNOWN,S_OK},
5297             {80,S_OK},
5298             {URL_SCHEME_HTTP,S_OK},
5299             {URLZONE_INVALID,E_NOTIMPL}
5300         }
5301     },
5302     {   "http://google.com/",0,S_OK,FALSE,
5303         {
5304             {TRUE,"/path?query",NULL,Uri_PROPERTY_PATH,S_OK,FALSE}
5305         },
5306         {FALSE},
5307         0,INET_E_INVALID_URL,FALSE,
5308         0,INET_E_INVALID_URL,FALSE,
5309         0,0,0,INET_E_INVALID_URL,FALSE
5310     },
5311     {   "http://google.com/",0,S_OK,FALSE,
5312         {
5313             {TRUE,"/path#test",NULL,Uri_PROPERTY_PATH,S_OK,FALSE}
5314         },
5315         {FALSE},
5316         0,INET_E_INVALID_URL,FALSE,
5317         0,INET_E_INVALID_URL,FALSE,
5318         0,0,0,INET_E_INVALID_URL,FALSE
5319     },
5320     {   "http://google.com/",0,S_OK,FALSE,
5321         {
5322             {TRUE,"?path#test",NULL,Uri_PROPERTY_QUERY,S_OK,FALSE}
5323         },
5324         {FALSE},
5325         0,INET_E_INVALID_URL,FALSE,
5326         0,INET_E_INVALID_URL,FALSE,
5327         0,0,0,INET_E_INVALID_URL,FALSE
5328     }
5329 };
5330
5331 typedef struct _uri_builder_remove_test {
5332     const char  *uri;
5333     DWORD       create_flags;
5334     HRESULT     create_builder_expected;
5335     BOOL        create_builder_todo;
5336
5337     DWORD       remove_properties;
5338     HRESULT     remove_expected;
5339     BOOL        remove_todo;
5340
5341     const char  *expected_uri;
5342     DWORD       expected_flags;
5343     HRESULT     expected_hres;
5344     BOOL        expected_todo;
5345 } uri_builder_remove_test;
5346
5347 static const uri_builder_remove_test uri_builder_remove_tests[] = {
5348     {   "http://google.com/test?test=y#Frag",0,S_OK,FALSE,
5349         Uri_HAS_FRAGMENT|Uri_HAS_PATH|Uri_HAS_QUERY,S_OK,FALSE,
5350         "http://google.com/",0,S_OK,FALSE
5351     },
5352     {   "http://user:pass@winehq.org/",0,S_OK,FALSE,
5353         Uri_HAS_USER_NAME|Uri_HAS_PASSWORD,S_OK,FALSE,
5354         "http://winehq.org/",0,S_OK,FALSE
5355     },
5356     {   "zip://google.com?Test=x",0,S_OK,FALSE,
5357         Uri_HAS_HOST,S_OK,FALSE,
5358         "zip:/?Test=x",0,S_OK,FALSE
5359     },
5360     /* Doesn't remove the whole userinfo component. */
5361     {   "http://username:pass@google.com/",0,S_OK,FALSE,
5362         Uri_HAS_USER_INFO,S_OK,FALSE,
5363         "http://username:pass@google.com/",0,S_OK,FALSE
5364     },
5365     /* Doesn't remove the domain. */
5366     {   "http://google.com/",0,S_OK,FALSE,
5367         Uri_HAS_DOMAIN,S_OK,FALSE,
5368         "http://google.com/",0,S_OK,FALSE
5369     },
5370     {   "http://google.com:120/",0,S_OK,FALSE,
5371         Uri_HAS_AUTHORITY,S_OK,FALSE,
5372         "http://google.com:120/",0,S_OK,FALSE
5373     },
5374     {   "http://google.com/test.com/",0,S_OK,FALSE,
5375         Uri_HAS_EXTENSION,S_OK,FALSE,
5376         "http://google.com/test.com/",0,S_OK,FALSE
5377     },
5378     {   "http://google.com/?test=x",0,S_OK,FALSE,
5379         Uri_HAS_PATH_AND_QUERY,S_OK,FALSE,
5380         "http://google.com/?test=x",0,S_OK,FALSE
5381     },
5382     /* Can't remove the scheme name. */
5383     {   "http://google.com/?test=x",0,S_OK,FALSE,
5384         Uri_HAS_SCHEME_NAME|Uri_HAS_QUERY,E_INVALIDARG,FALSE,
5385         "http://google.com/?test=x",0,S_OK,FALSE
5386     }
5387 };
5388
5389 typedef struct _uri_combine_str_property {
5390     const char  *value;
5391     HRESULT     expected;
5392     BOOL        todo;
5393     const char  *broken_value;
5394     const char  *value_ex;
5395 } uri_combine_str_property;
5396
5397 typedef struct _uri_combine_test {
5398     const char  *base_uri;
5399     DWORD       base_create_flags;
5400     const char  *relative_uri;
5401     DWORD       relative_create_flags;
5402     DWORD       combine_flags;
5403     HRESULT     expected;
5404     BOOL        todo;
5405
5406     uri_combine_str_property    str_props[URI_STR_PROPERTY_COUNT];
5407     uri_dword_property          dword_props[URI_DWORD_PROPERTY_COUNT];
5408 } uri_combine_test;
5409
5410 static const uri_combine_test uri_combine_tests[] = {
5411     {   "http://google.com/fun/stuff",0,
5412         "../not/fun/stuff",Uri_CREATE_ALLOW_RELATIVE,
5413         0,S_OK,FALSE,
5414         {
5415             {"http://google.com/not/fun/stuff",S_OK},
5416             {"google.com",S_OK},
5417             {"http://google.com/not/fun/stuff",S_OK},
5418             {"google.com",S_OK},
5419             {"",S_FALSE},
5420             {"",S_FALSE},
5421             {"google.com",S_OK},
5422             {"",S_FALSE},
5423             {"/not/fun/stuff",S_OK},
5424             {"/not/fun/stuff",S_OK},
5425             {"",S_FALSE},
5426             {"http://google.com/not/fun/stuff",S_OK},
5427             {"http",S_OK},
5428             {"",S_FALSE},
5429             {"",S_FALSE}
5430         },
5431         {
5432             {Uri_HOST_DNS,S_OK},
5433             {80,S_OK},
5434             {URL_SCHEME_HTTP,S_OK},
5435             {URLZONE_INVALID,E_NOTIMPL}
5436         }
5437     },
5438     {   "http://google.com/test",0,
5439         "zip://test.com/cool",0,
5440         0,S_OK,FALSE,
5441         {
5442             {"zip://test.com/cool",S_OK},
5443             {"test.com",S_OK},
5444             {"zip://test.com/cool",S_OK},
5445             {"test.com",S_OK},
5446             {"",S_FALSE},
5447             {"",S_FALSE},
5448             {"test.com",S_OK},
5449             {"",S_FALSE},
5450             {"/cool",S_OK},
5451             {"/cool",S_OK},
5452             {"",S_FALSE},
5453             {"zip://test.com/cool",S_OK},
5454             {"zip",S_OK},
5455             {"",S_FALSE},
5456             {"",S_FALSE}
5457         },
5458         {
5459             {Uri_HOST_DNS,S_OK},
5460             {0,S_FALSE},
5461             {URL_SCHEME_UNKNOWN,S_OK},
5462             {URLZONE_INVALID,E_NOTIMPL}
5463         }
5464     },
5465     {   "http://google.com/use/base/path",0,
5466         "?relative",Uri_CREATE_ALLOW_RELATIVE,
5467         0,S_OK,FALSE,
5468         {
5469             {"http://google.com/use/base/path?relative",S_OK},
5470             {"google.com",S_OK},
5471             {"http://google.com/use/base/path?relative",S_OK},
5472             {"google.com",S_OK},
5473             {"",S_FALSE},
5474             {"",S_FALSE},
5475             {"google.com",S_OK},
5476             {"",S_FALSE},
5477             {"/use/base/path",S_OK},
5478             {"/use/base/path?relative",S_OK},
5479             {"?relative",S_OK},
5480             {"http://google.com/use/base/path?relative",S_OK},
5481             {"http",S_OK},
5482             {"",S_FALSE},
5483             {"",S_FALSE}
5484         },
5485         {
5486             {Uri_HOST_DNS,S_OK},
5487             {80,S_OK},
5488             {URL_SCHEME_HTTP,S_OK},
5489             {URLZONE_INVALID,E_NOTIMPL}
5490         }
5491     },
5492     {   "http://google.com/path",0,
5493         "/test/../test/.././testing",Uri_CREATE_ALLOW_RELATIVE,
5494         0,S_OK,FALSE,
5495         {
5496             {"http://google.com/testing",S_OK},
5497             {"google.com",S_OK},
5498             {"http://google.com/testing",S_OK},
5499             {"google.com",S_OK},
5500             {"",S_FALSE},
5501             {"",S_FALSE},
5502             {"google.com",S_OK},
5503             {"",S_FALSE},
5504             {"/testing",S_OK},
5505             {"/testing",S_OK},
5506             {"",S_FALSE},
5507             {"http://google.com/testing",S_OK},
5508             {"http",S_OK},
5509             {"",S_FALSE},
5510             {"",S_FALSE}
5511         },
5512         {
5513             {Uri_HOST_DNS,S_OK},
5514             {80,S_OK},
5515             {URL_SCHEME_HTTP,S_OK},
5516             {URLZONE_INVALID,E_NOTIMPL}
5517         }
5518     },
5519     {   "http://google.com/path",0,
5520         "/test/../test/.././testing",Uri_CREATE_ALLOW_RELATIVE,
5521         URL_DONT_SIMPLIFY,S_OK,FALSE,
5522         {
5523             {"http://google.com:80/test/../test/.././testing",S_OK},
5524             {"google.com",S_OK},
5525             {"http://google.com:80/test/../test/.././testing",S_OK},
5526             {"google.com",S_OK},
5527             {"",S_FALSE},
5528             {"",S_FALSE},
5529             {"google.com",S_OK},
5530             {"",S_FALSE},
5531             {"/test/../test/.././testing",S_OK},
5532             {"/test/../test/.././testing",S_OK},
5533             {"",S_FALSE},
5534             {"http://google.com:80/test/../test/.././testing",S_OK},
5535             {"http",S_OK},
5536             {"",S_FALSE},
5537             {"",S_FALSE}
5538         },
5539         {
5540             {Uri_HOST_DNS,S_OK},
5541             {80,S_OK},
5542             {URL_SCHEME_HTTP,S_OK},
5543             {URLZONE_INVALID,E_NOTIMPL}
5544         }
5545     },
5546     {   "http://winehq.org/test/abc",0,
5547         "testing/abc/../test",Uri_CREATE_ALLOW_RELATIVE,
5548         0,S_OK,FALSE,
5549         {
5550             {"http://winehq.org/test/testing/test",S_OK},
5551             {"winehq.org",S_OK},
5552             {"http://winehq.org/test/testing/test",S_OK},
5553             {"winehq.org",S_OK},
5554             {"",S_FALSE},
5555             {"",S_FALSE},
5556             {"winehq.org",S_OK},
5557             {"",S_FALSE},
5558             {"/test/testing/test",S_OK},
5559             {"/test/testing/test",S_OK},
5560             {"",S_FALSE},
5561             {"http://winehq.org/test/testing/test",S_OK},
5562             {"http",S_OK},
5563             {"",S_FALSE},
5564             {"",S_FALSE}
5565         },
5566         {
5567             {Uri_HOST_DNS,S_OK},
5568             {80,S_OK},
5569             {URL_SCHEME_HTTP,S_OK},
5570             {URLZONE_INVALID,E_NOTIMPL}
5571         }
5572     },
5573     {   "http://winehq.org/test/abc",0,
5574         "testing/abc/../test",Uri_CREATE_ALLOW_RELATIVE,
5575         URL_DONT_SIMPLIFY,S_OK,FALSE,
5576         {
5577             {"http://winehq.org:80/test/testing/abc/../test",S_OK},
5578             /* Default port is hidden in the authority. */
5579             {"winehq.org",S_OK},
5580             {"http://winehq.org:80/test/testing/abc/../test",S_OK},
5581             {"winehq.org",S_OK},
5582             {"",S_FALSE},
5583             {"",S_FALSE},
5584             {"winehq.org",S_OK},
5585             {"",S_FALSE},
5586             {"/test/testing/abc/../test",S_OK},
5587             {"/test/testing/abc/../test",S_OK},
5588             {"",S_FALSE},
5589             {"http://winehq.org:80/test/testing/abc/../test",S_OK},
5590             {"http",S_OK},
5591             {"",S_FALSE},
5592             {"",S_FALSE}
5593         },
5594         {
5595             {Uri_HOST_DNS,S_OK},
5596             {80,S_OK},
5597             {URL_SCHEME_HTTP,S_OK},
5598             {URLZONE_INVALID,E_NOTIMPL}
5599         }
5600     },
5601     {   "http://winehq.org/test?query",0,
5602         "testing",Uri_CREATE_ALLOW_RELATIVE,
5603         0,S_OK,FALSE,
5604         {
5605             {"http://winehq.org/testing",S_OK},
5606             {"winehq.org",S_OK},
5607             {"http://winehq.org/testing",S_OK},
5608             {"winehq.org",S_OK},
5609             {"",S_FALSE},
5610             {"",S_FALSE},
5611             {"winehq.org",S_OK},
5612             {"",S_FALSE},
5613             {"/testing",S_OK},
5614             {"/testing",S_OK},
5615             {"",S_FALSE},
5616             {"http://winehq.org/testing",S_OK},
5617             {"http",S_OK},
5618             {"",S_FALSE},
5619             {"",S_FALSE}
5620         },
5621         {
5622             {Uri_HOST_DNS,S_OK},
5623             {80,S_OK},
5624             {URL_SCHEME_HTTP,S_OK},
5625             {URLZONE_INVALID,E_NOTIMPL}
5626         }
5627     },
5628     {   "http://winehq.org/test#frag",0,
5629         "testing",Uri_CREATE_ALLOW_RELATIVE,
5630         0,S_OK,FALSE,
5631         {
5632             {"http://winehq.org/testing",S_OK},
5633             {"winehq.org",S_OK},
5634             {"http://winehq.org/testing",S_OK},
5635             {"winehq.org",S_OK},
5636             {"",S_FALSE},
5637             {"",S_FALSE},
5638             {"winehq.org",S_OK},
5639             {"",S_FALSE},
5640             {"/testing",S_OK},
5641             {"/testing",S_OK},
5642             {"",S_FALSE},
5643             {"http://winehq.org/testing",S_OK},
5644             {"http",S_OK},
5645             {"",S_FALSE},
5646             {"",S_FALSE}
5647         },
5648         {
5649             {Uri_HOST_DNS,S_OK},
5650             {80,S_OK},
5651             {URL_SCHEME_HTTP,S_OK},
5652             {URLZONE_INVALID,E_NOTIMPL}
5653         }
5654     },
5655     {   "testing?query#frag",Uri_CREATE_ALLOW_RELATIVE,
5656         "test",Uri_CREATE_ALLOW_RELATIVE,
5657         0,S_OK,FALSE,
5658         {
5659             {"test",S_OK},
5660             {"",S_FALSE},
5661             {"test",S_OK},
5662             {"",S_FALSE},
5663             {"",S_FALSE},
5664             {"",S_FALSE},
5665             {"",S_FALSE},
5666             {"",S_FALSE},
5667             {"test",S_OK},
5668             {"test",S_OK},
5669             {"",S_FALSE},
5670             {"test",S_OK},
5671             {"",S_FALSE},
5672             {"",S_FALSE},
5673             {"",S_FALSE}
5674         },
5675         {
5676             {Uri_HOST_UNKNOWN,S_OK},
5677             {0,S_FALSE},
5678             {URL_SCHEME_UNKNOWN,S_OK},
5679             {URLZONE_INVALID,E_NOTIMPL}
5680         }
5681     },
5682     {   "file:///c:/test/test",0,
5683         "/testing.mp3",Uri_CREATE_ALLOW_RELATIVE,
5684         URL_FILE_USE_PATHURL,S_OK,FALSE,
5685         {
5686             {"file://c:\\testing.mp3",S_OK},
5687             {"",S_FALSE},
5688             {"file://c:\\testing.mp3",S_OK},
5689             {"",S_FALSE},
5690             {".mp3",S_OK},
5691             {"",S_FALSE},
5692             {"",S_FALSE},
5693             {"",S_FALSE},
5694             {"c:\\testing.mp3",S_OK},
5695             {"c:\\testing.mp3",S_OK},
5696             {"",S_FALSE},
5697             {"file://c:\\testing.mp3",S_OK},
5698             {"file",S_OK},
5699             {"",S_FALSE},
5700             {"",S_FALSE}
5701         },
5702         {
5703             {Uri_HOST_UNKNOWN,S_OK},
5704             {0,S_FALSE},
5705             {URL_SCHEME_FILE,S_OK},
5706             {URLZONE_INVALID,E_NOTIMPL}
5707         }
5708     },
5709     {   "file:///c:/test/test",0,
5710         "/testing.mp3",Uri_CREATE_ALLOW_RELATIVE,
5711         0,S_OK,FALSE,
5712         {
5713             {"file:///c:/testing.mp3",S_OK},
5714             {"",S_FALSE},
5715             {"file:///c:/testing.mp3",S_OK},
5716             {"",S_FALSE},
5717             {".mp3",S_OK},
5718             {"",S_FALSE},
5719             {"",S_FALSE},
5720             {"",S_FALSE},
5721             {"/c:/testing.mp3",S_OK},
5722             {"/c:/testing.mp3",S_OK},
5723             {"",S_FALSE},
5724             {"file:///c:/testing.mp3",S_OK},
5725             {"file",S_OK},
5726             {"",S_FALSE},
5727             {"",S_FALSE}
5728         },
5729         {
5730             {Uri_HOST_UNKNOWN,S_OK},
5731             {0,S_FALSE},
5732             {URL_SCHEME_FILE,S_OK},
5733             {URLZONE_INVALID,E_NOTIMPL}
5734         }
5735     },
5736     {   "file://test.com/test/test",0,
5737         "/testing.mp3",Uri_CREATE_ALLOW_RELATIVE,
5738         URL_FILE_USE_PATHURL,S_OK,FALSE,
5739         {
5740             {"file://\\\\test.com\\testing.mp3",S_OK},
5741             {"test.com",S_OK},
5742             {"file://\\\\test.com\\testing.mp3",S_OK},
5743             {"test.com",S_OK},
5744             {".mp3",S_OK},
5745             {"",S_FALSE},
5746             {"test.com",S_OK},
5747             {"",S_FALSE},
5748             {"\\testing.mp3",S_OK},
5749             {"\\testing.mp3",S_OK},
5750             {"",S_FALSE},
5751             {"file://\\\\test.com\\testing.mp3",S_OK},
5752             {"file",S_OK},
5753             {"",S_FALSE},
5754             {"",S_FALSE}
5755         },
5756         {
5757             {Uri_HOST_DNS,S_OK},
5758             {0,S_FALSE},
5759             {URL_SCHEME_FILE,S_OK},
5760             {URLZONE_INVALID,E_NOTIMPL}
5761         }
5762     },
5763     /* URL_DONT_SIMPLIFY has no effect. */
5764     {   "http://google.com/test",0,
5765         "zip://test.com/cool/../cool/test",0,
5766         URL_DONT_SIMPLIFY,S_OK,FALSE,
5767         {
5768             {"zip://test.com/cool/test",S_OK,FALSE,NULL,"zip://test.com/cool/../cool/test"},
5769             {"test.com",S_OK},
5770             {"zip://test.com/cool/test",S_OK,FALSE,NULL,"zip://test.com/cool/../cool/test"},
5771             {"test.com",S_OK},
5772             {"",S_FALSE},
5773             {"",S_FALSE},
5774             {"test.com",S_OK},
5775             {"",S_FALSE},
5776             {"/cool/test",S_OK,FALSE,NULL,"/cool/../cool/test"},
5777             {"/cool/test",S_OK,FALSE,NULL,"/cool/../cool/test"},
5778             {"",S_FALSE},
5779             /* The resulting IUri has the same Raw URI as the relative URI (only IE 8).
5780              * On IE 7 it reduces the path in the Raw URI.
5781              */
5782             {"zip://test.com/cool/../cool/test",S_OK,FALSE,"zip://test.com/cool/test"},
5783             {"zip",S_OK},
5784             {"",S_FALSE},
5785             {"",S_FALSE}
5786         },
5787         {
5788             {Uri_HOST_DNS,S_OK},
5789             {0,S_FALSE},
5790             {URL_SCHEME_UNKNOWN,S_OK},
5791             {URLZONE_INVALID,E_NOTIMPL}
5792         }
5793     },
5794     /* FILE_USE_PATHURL has no effect in IE 8, in IE 7 the
5795      * resulting URI is converted into a dos path.
5796      */
5797     {   "http://google.com/test",0,
5798         "file:///c:/test/",0,
5799         URL_FILE_USE_PATHURL,S_OK,FALSE,
5800         {
5801             {"file:///c:/test/",S_OK,FALSE,"file://c:\\test\\"},
5802             {"",S_FALSE},
5803             {"file:///c:/test/",S_OK,FALSE,"file://c:\\test\\"},
5804             {"",S_FALSE},
5805             {"",S_FALSE},
5806             {"",S_FALSE},
5807             {"",S_FALSE},
5808             {"",S_FALSE},
5809             {"/c:/test/",S_OK,FALSE,"c:\\test\\"},
5810             {"/c:/test/",S_OK,FALSE,"c:\\test\\"},
5811             {"",S_FALSE},
5812             {"file:///c:/test/",S_OK,FALSE,"file://c:\\test\\"},
5813             {"file",S_OK},
5814             {"",S_FALSE},
5815             {"",S_FALSE}
5816         },
5817         {
5818             {Uri_HOST_UNKNOWN,S_OK},
5819             {0,S_FALSE},
5820             {URL_SCHEME_FILE,S_OK},
5821             {URLZONE_INVALID,E_NOTIMPL}
5822         }
5823     },
5824     {   "http://google.com/test",0,
5825         "http://test.com/test#%30test",0,
5826         URL_DONT_UNESCAPE_EXTRA_INFO,S_OK,FALSE,
5827         {
5828             {"http://test.com/test#0test",S_OK,FALSE,NULL,"http://test.com/test#%30test"},
5829             {"test.com",S_OK},
5830             {"http://test.com/test#0test",S_OK,FALSE,NULL,"http://test.com/test#%30test"},
5831             {"test.com",S_OK},
5832             {"",S_FALSE},
5833             {"#0test",S_OK,FALSE,NULL,"#%30test"},
5834             {"test.com",S_OK},
5835             {"",S_FALSE},
5836             {"/test",S_OK},
5837             {"/test",S_OK},
5838             {"",S_FALSE},
5839             /* IE 7 decodes the %30 to a 0 in the Raw URI. */
5840             {"http://test.com/test#%30test",S_OK,FALSE,"http://test.com/test#0test"},
5841             {"http",S_OK},
5842             {"",S_FALSE},
5843             {"",S_FALSE}
5844         },
5845         {
5846             {Uri_HOST_DNS,S_OK},
5847             {80,S_OK},
5848             {URL_SCHEME_HTTP,S_OK},
5849             {URLZONE_INVALID,E_NOTIMPL}
5850         }
5851     },
5852     /* Windows validates the path component from the relative Uri. */
5853     {   "http://google.com/test",0,
5854         "/Te%XXst",Uri_CREATE_ALLOW_RELATIVE,
5855         0,E_INVALIDARG,FALSE
5856     },
5857     /* Windows doesn't validate the query from the relative Uri. */
5858     {   "http://google.com/test",0,
5859         "?Tes%XXt",Uri_CREATE_ALLOW_RELATIVE,
5860         0,S_OK,FALSE,
5861         {
5862             {"http://google.com/test?Tes%XXt",S_OK},
5863             {"google.com",S_OK},
5864             {"http://google.com/test?Tes%XXt",S_OK},
5865             {"google.com",S_OK},
5866             {"",S_FALSE},
5867             {"",S_FALSE},
5868             {"google.com",S_OK},
5869             {"",S_FALSE},
5870             {"/test",S_OK},
5871             {"/test?Tes%XXt",S_OK},
5872             {"?Tes%XXt",S_OK},
5873             {"http://google.com/test?Tes%XXt",S_OK},
5874             {"http",S_OK},
5875             {"",S_FALSE},
5876             {"",S_FALSE}
5877         },
5878         {
5879             {Uri_HOST_DNS,S_OK},
5880             {80,S_OK},
5881             {URL_SCHEME_HTTP,S_OK},
5882             {URLZONE_INVALID,E_NOTIMPL}
5883         }
5884     },
5885     /* Windows doesn't validate the fragment from the relative Uri. */
5886     {   "http://google.com/test",0,
5887         "#Tes%XXt",Uri_CREATE_ALLOW_RELATIVE,
5888         0,S_OK,FALSE,
5889         {
5890             {"http://google.com/test#Tes%XXt",S_OK},
5891             {"google.com",S_OK},
5892             {"http://google.com/test#Tes%XXt",S_OK},
5893             {"google.com",S_OK},
5894             {"",S_FALSE},
5895             {"#Tes%XXt",S_OK},
5896             {"google.com",S_OK},
5897             {"",S_FALSE},
5898             {"/test",S_OK},
5899             {"/test",S_OK},
5900             {"",S_FALSE},
5901             {"http://google.com/test#Tes%XXt",S_OK},
5902             {"http",S_OK},
5903             {"",S_FALSE},
5904             {"",S_FALSE}
5905         },
5906         {
5907             {Uri_HOST_DNS,S_OK},
5908             {80,S_OK},
5909             {URL_SCHEME_HTTP,S_OK},
5910             {URLZONE_INVALID,E_NOTIMPL}
5911         }
5912     },
5913     /* Creates an IUri which contains an invalid dos path char. */
5914     {   "file:///c:/test",0,
5915         "/test<ing",Uri_CREATE_ALLOW_RELATIVE,
5916         URL_FILE_USE_PATHURL,S_OK,FALSE,
5917         {
5918             {"file://c:\\test<ing",S_OK},
5919             {"",S_FALSE},
5920             {"file://c:\\test<ing",S_OK},
5921             {"",S_FALSE},
5922             {"",S_FALSE},
5923             {"",S_FALSE},
5924             {"",S_FALSE},
5925             {"",S_FALSE},
5926             {"c:\\test<ing",S_OK},
5927             {"c:\\test<ing",S_OK},
5928             {"",S_FALSE},
5929             {"file://c:\\test<ing",S_OK},
5930             {"file",S_OK},
5931             {"",S_FALSE},
5932             {"",S_FALSE}
5933         },
5934         {
5935             {Uri_HOST_UNKNOWN,S_OK},
5936             {0,S_FALSE},
5937             {URL_SCHEME_FILE,S_OK},
5938             {URLZONE_INVALID,E_NOTIMPL}
5939         }
5940     },
5941     /* Appends the path after the drive letter (if any). */
5942     {   "file:///c:/test",0,
5943         "/c:/testing",Uri_CREATE_ALLOW_RELATIVE,
5944         0,S_OK,FALSE,
5945         {
5946             {"file:///c:/c:/testing",S_OK},
5947             {"",S_FALSE},
5948             {"file:///c:/c:/testing",S_OK},
5949             {"",S_FALSE},
5950             {"",S_FALSE},
5951             {"",S_FALSE},
5952             {"",S_FALSE},
5953             {"",S_FALSE},
5954             {"/c:/c:/testing",S_OK},
5955             {"/c:/c:/testing",S_OK},
5956             {"",S_FALSE},
5957             {"file:///c:/c:/testing",S_OK},
5958             {"file",S_OK},
5959             {"",S_FALSE},
5960             {"",S_FALSE}
5961         },
5962         {
5963             {Uri_HOST_UNKNOWN,S_OK},
5964             {0,S_FALSE},
5965             {URL_SCHEME_FILE,S_OK},
5966             {URLZONE_INVALID,E_NOTIMPL}
5967         }
5968     },
5969     /* A '/' is added if the base URI doesn't have a path and the
5970      * relative URI doesn't contain a path (since the base URI is
5971      * hierarchical.
5972      */
5973     {   "http://google.com",Uri_CREATE_NO_CANONICALIZE,
5974         "?test",Uri_CREATE_ALLOW_RELATIVE,
5975         0,S_OK,FALSE,
5976         {
5977             {"http://google.com/?test",S_OK},
5978             {"google.com",S_OK},
5979             {"http://google.com/?test",S_OK},
5980             {"google.com",S_OK},
5981             {"",S_FALSE},
5982             {"",S_FALSE},
5983             {"google.com",S_OK},
5984             {"",S_FALSE},
5985             {"/",S_OK},
5986             {"/?test",S_OK},
5987             {"?test",S_OK},
5988             {"http://google.com/?test",S_OK},
5989             {"http",S_OK},
5990             {"",S_FALSE},
5991             {"",S_FALSE}
5992         },
5993         {
5994             {Uri_HOST_DNS,S_OK},
5995             {80,S_OK},
5996             {URL_SCHEME_HTTP,S_OK},
5997             {URLZONE_INVALID,E_NOTIMPL}
5998         }
5999     },
6000     {   "zip://google.com",Uri_CREATE_NO_CANONICALIZE,
6001         "?test",Uri_CREATE_ALLOW_RELATIVE,
6002         0,S_OK,FALSE,
6003         {
6004             {"zip://google.com/?test",S_OK},
6005             {"google.com",S_OK},
6006             {"zip://google.com/?test",S_OK},
6007             {"google.com",S_OK},
6008             {"",S_FALSE},
6009             {"",S_FALSE},
6010             {"google.com",S_OK},
6011             {"",S_FALSE},
6012             {"/",S_OK},
6013             {"/?test",S_OK},
6014             {"?test",S_OK},
6015             {"zip://google.com/?test",S_OK},
6016             {"zip",S_OK},
6017             {"",S_FALSE},
6018             {"",S_FALSE}
6019         },
6020         {
6021             {Uri_HOST_DNS,S_OK},
6022             {0,S_FALSE},
6023             {URL_SCHEME_UNKNOWN,S_OK},
6024             {URLZONE_INVALID,E_NOTIMPL}
6025         }
6026     },
6027     /* No path is appended since the base URI is opaque. */
6028     {   "zip:?testing",0,
6029         "?test",Uri_CREATE_ALLOW_RELATIVE,
6030         0,S_OK,FALSE,
6031         {
6032             {"zip:?test",S_OK},
6033             {"",S_FALSE},
6034             {"zip:?test",S_OK},
6035             {"",S_FALSE},
6036             {"",S_FALSE},
6037             {"",S_FALSE},
6038             {"",S_FALSE},
6039             {"",S_FALSE},
6040             {"",S_OK},
6041             {"?test",S_OK},
6042             {"?test",S_OK},
6043             {"zip:?test",S_OK},
6044             {"zip",S_OK},
6045             {"",S_FALSE},
6046             {"",S_FALSE}
6047         },
6048         {
6049             {Uri_HOST_UNKNOWN,S_OK},
6050             {0,S_FALSE},
6051             {URL_SCHEME_UNKNOWN,S_OK},
6052             {URLZONE_INVALID,E_NOTIMPL}
6053         }
6054     },
6055     {   "file:///c:/",0,
6056         "../testing/test",Uri_CREATE_ALLOW_RELATIVE,
6057         0,S_OK,FALSE,
6058         {
6059             {"file:///c:/testing/test",S_OK},
6060             {"",S_FALSE},
6061             {"file:///c:/testing/test",S_OK},
6062             {"",S_FALSE},
6063             {"",S_FALSE},
6064             {"",S_FALSE},
6065             {"",S_FALSE},
6066             {"",S_FALSE},
6067             {"/c:/testing/test",S_OK},
6068             {"/c:/testing/test",S_OK},
6069             {"",S_FALSE},
6070             {"file:///c:/testing/test",S_OK},
6071             {"file",S_OK},
6072             {"",S_FALSE},
6073             {"",S_FALSE}
6074         },
6075         {
6076             {Uri_HOST_UNKNOWN,S_OK},
6077             {0,S_FALSE},
6078             {URL_SCHEME_FILE,S_OK},
6079             {URLZONE_INVALID,E_NOTIMPL}
6080         }
6081     },
6082     {   "http://winehq.org/dir/testfile",0,
6083         "test?querystring",Uri_CREATE_ALLOW_RELATIVE,
6084         0,S_OK,FALSE,
6085         {
6086             {"http://winehq.org/dir/test?querystring",S_OK},
6087             {"winehq.org",S_OK},
6088             {"http://winehq.org/dir/test?querystring",S_OK},
6089             {"winehq.org",S_OK},
6090             {"",S_FALSE},
6091             {"",S_FALSE},
6092             {"winehq.org",S_OK},
6093             {"",S_FALSE},
6094             {"/dir/test",S_OK},
6095             {"/dir/test?querystring",S_OK},
6096             {"?querystring",S_OK},
6097             {"http://winehq.org/dir/test?querystring",S_OK},
6098             {"http",S_OK},
6099             {"",S_FALSE},
6100             {"",S_FALSE}
6101         },
6102         {
6103             {Uri_HOST_DNS,S_OK},
6104             {80,S_OK},
6105             {URL_SCHEME_HTTP,S_OK},
6106             {URLZONE_INVALID,E_NOTIMPL}
6107         }
6108     },
6109     {   "http://winehq.org/dir/test",0,
6110         "test?querystring",Uri_CREATE_ALLOW_RELATIVE,
6111         0,S_OK,FALSE,
6112         {
6113             {"http://winehq.org/dir/test?querystring",S_OK},
6114             {"winehq.org",S_OK},
6115             {"http://winehq.org/dir/test?querystring",S_OK},
6116             {"winehq.org",S_OK},
6117             {"",S_FALSE},
6118             {"",S_FALSE},
6119             {"winehq.org",S_OK},
6120             {"",S_FALSE},
6121             {"/dir/test",S_OK},
6122             {"/dir/test?querystring",S_OK},
6123             {"?querystring",S_OK},
6124             {"http://winehq.org/dir/test?querystring",S_OK},
6125             {"http",S_OK},
6126             {"",S_FALSE},
6127             {"",S_FALSE}
6128         },
6129         {
6130             {Uri_HOST_DNS,S_OK},
6131             {80,S_OK},
6132             {URL_SCHEME_HTTP,S_OK},
6133             {URLZONE_INVALID,E_NOTIMPL}
6134         }
6135     },
6136     {   "http://winehq.org/dir/test?querystring",0,
6137         "#hash",Uri_CREATE_ALLOW_RELATIVE,
6138         0,S_OK,FALSE,
6139         {
6140             {"http://winehq.org/dir/test?querystring#hash",S_OK},
6141             {"winehq.org",S_OK},
6142             {"http://winehq.org/dir/test?querystring#hash",S_OK},
6143             {"winehq.org",S_OK},
6144             {"",S_FALSE},
6145             {"#hash",S_OK},
6146             {"winehq.org",S_OK},
6147             {"",S_FALSE},
6148             {"/dir/test",S_OK},
6149             {"/dir/test?querystring",S_OK},
6150             {"?querystring",S_OK},
6151             {"http://winehq.org/dir/test?querystring#hash",S_OK},
6152             {"http",S_OK},
6153             {"",S_FALSE},
6154             {"",S_FALSE}
6155         },
6156         {
6157             {Uri_HOST_DNS,S_OK},
6158             {80,S_OK},
6159             {URL_SCHEME_HTTP,S_OK},
6160             {URLZONE_INVALID,E_NOTIMPL}
6161         }
6162     }
6163 };
6164
6165 typedef struct _uri_parse_test {
6166     const char  *uri;
6167     DWORD       uri_flags;
6168     PARSEACTION action;
6169     DWORD       flags;
6170     const char  *property;
6171     HRESULT     expected;
6172     BOOL        todo;
6173 } uri_parse_test;
6174
6175 static const uri_parse_test uri_parse_tests[] = {
6176     /* PARSE_CANONICALIZE tests. */
6177     {"zip://google.com/test<|>",0,PARSE_CANONICALIZE,0,"zip://google.com/test<|>",S_OK,FALSE},
6178     {"http://google.com/test<|>",0,PARSE_CANONICALIZE,0,"http://google.com/test%3C%7C%3E",S_OK,FALSE},
6179     {"http://google.com/%30%23%3F",0,PARSE_CANONICALIZE,URL_UNESCAPE,"http://google.com/0#?",S_OK,FALSE},
6180     {"test <|>",Uri_CREATE_ALLOW_RELATIVE,PARSE_CANONICALIZE,URL_ESCAPE_UNSAFE,"test %3C%7C%3E",S_OK,FALSE},
6181     {"test <|>",Uri_CREATE_ALLOW_RELATIVE,PARSE_CANONICALIZE,URL_ESCAPE_SPACES_ONLY,"test%20<|>",S_OK,FALSE},
6182     {"test%20<|>",Uri_CREATE_ALLOW_RELATIVE,PARSE_CANONICALIZE,URL_UNESCAPE|URL_ESCAPE_UNSAFE,"test%20%3C%7C%3E",S_OK,FALSE},
6183     {"http://google.com/%20",0,PARSE_CANONICALIZE,URL_ESCAPE_PERCENT,"http://google.com/%2520",S_OK,FALSE},
6184     {"http://google.com/test/../",Uri_CREATE_NO_CANONICALIZE,PARSE_CANONICALIZE,URL_DONT_SIMPLIFY,"http://google.com/test/../",S_OK,FALSE},
6185     {"http://google.com/test/../",Uri_CREATE_NO_CANONICALIZE,PARSE_CANONICALIZE,URL_NO_META,"http://google.com/test/../",S_OK,FALSE},
6186     {"http://google.com/test/../",Uri_CREATE_NO_CANONICALIZE,PARSE_CANONICALIZE,0,"http://google.com/",S_OK,FALSE},
6187     {"zip://google.com/test/../",Uri_CREATE_NO_CANONICALIZE,PARSE_CANONICALIZE,0,"zip://google.com/",S_OK,FALSE},
6188     {"file:///c:/test/../test",Uri_CREATE_NO_CANONICALIZE,PARSE_CANONICALIZE,URL_DONT_SIMPLIFY,"file:///c:/test/../test",S_OK,FALSE},
6189
6190     /* PARSE_FRIENDLY tests. */
6191     {"http://test@google.com/test#test",0,PARSE_FRIENDLY,0,"http://google.com/test#test",S_OK,FALSE},
6192     {"zip://test@google.com/test",0,PARSE_FRIENDLY,0,"zip://test@google.com/test",S_OK,FALSE},
6193
6194     /* PARSE_ROOTDOCUMENT tests. */
6195     {"http://google.com:200/test/test",0,PARSE_ROOTDOCUMENT,0,"http://google.com:200/",S_OK,FALSE},
6196     {"http://google.com",Uri_CREATE_NO_CANONICALIZE,PARSE_ROOTDOCUMENT,0,"http://google.com/",S_OK,FALSE},
6197     {"zip://google.com/",0,PARSE_ROOTDOCUMENT,0,"",S_OK,FALSE},
6198     {"file:///c:/testing/",0,PARSE_ROOTDOCUMENT,0,"",S_OK,FALSE},
6199     {"file://server/test",0,PARSE_ROOTDOCUMENT,0,"",S_OK,FALSE},
6200     {"zip:test/test",0,PARSE_ROOTDOCUMENT,0,"",S_OK,FALSE},
6201
6202     /* PARSE_DOCUMENT tests. */
6203     {"http://test@google.com/test?query#frag",0,PARSE_DOCUMENT,0,"http://test@google.com/test?query",S_OK,FALSE},
6204     {"http:testing#frag",0,PARSE_DOCUMENT,0,"",S_OK,FALSE},
6205     {"file:///c:/test#frag",0,PARSE_DOCUMENT,0,"",S_OK,FALSE},
6206     {"zip://google.com/#frag",0,PARSE_DOCUMENT,0,"",S_OK,FALSE},
6207     {"zip:test#frag",0,PARSE_DOCUMENT,0,"",S_OK,FALSE},
6208     {"testing#frag",Uri_CREATE_ALLOW_RELATIVE,PARSE_DOCUMENT,0,"",S_OK,FALSE},
6209
6210     /* PARSE_PATH_FROM_URL tests. */
6211     {"file:///c:/test.mp3",0,PARSE_PATH_FROM_URL,0,"c:\\test.mp3",S_OK,FALSE},
6212     {"file:///c:/t<|>est.mp3",0,PARSE_PATH_FROM_URL,0,"c:\\t<|>est.mp3",S_OK,FALSE},
6213     {"file:///c:/te%XX t/",0,PARSE_PATH_FROM_URL,0,"c:\\te%XX t\\",S_OK,FALSE},
6214     {"file://server/test",0,PARSE_PATH_FROM_URL,0,"\\\\server\\test",S_OK,FALSE},
6215     {"http://google.com/",0,PARSE_PATH_FROM_URL,0,"",E_INVALIDARG,FALSE},
6216
6217     /* PARSE_URL_FROM_PATH tests. */
6218     /* This function almost seems to useless (just returns the absolute uri). */
6219     {"test.com",Uri_CREATE_ALLOW_RELATIVE,PARSE_URL_FROM_PATH,0,"test.com",S_OK,FALSE},
6220     {"/test/test",Uri_CREATE_ALLOW_RELATIVE,PARSE_URL_FROM_PATH,0,"/test/test",S_OK,FALSE},
6221     {"file://c:\\test\\test",Uri_CREATE_FILE_USE_DOS_PATH,PARSE_URL_FROM_PATH,0,"file://c:\\test\\test",S_OK,FALSE},
6222     {"file:c:/test",0,PARSE_URL_FROM_PATH,0,"",S_OK,FALSE},
6223     {"http:google.com/",0,PARSE_URL_FROM_PATH,0,"",S_OK,FALSE},
6224
6225     /* PARSE_SCHEMA tests. */
6226     {"http://google.com/test",0,PARSE_SCHEMA,0,"http",S_OK,FALSE},
6227     {"test",Uri_CREATE_ALLOW_RELATIVE,PARSE_SCHEMA,0,"",S_OK,FALSE},
6228
6229     /* PARSE_SITE tests. */
6230     {"http://google.uk.com/",0,PARSE_SITE,0,"google.uk.com",S_OK,FALSE},
6231     {"http://google.com.com/",0,PARSE_SITE,0,"google.com.com",S_OK,FALSE},
6232     {"google.com",Uri_CREATE_ALLOW_RELATIVE,PARSE_SITE,0,"",S_OK,FALSE},
6233     {"file://server/test",0,PARSE_SITE,0,"server",S_OK,FALSE},
6234
6235     /* PARSE_DOMAIN tests. */
6236     {"http://google.com.uk/",0,PARSE_DOMAIN,0,"google.com.uk",S_OK,FALSE},
6237     {"http://google.com.com/",0,PARSE_DOMAIN,0,"com.com",S_OK,FALSE},
6238     {"test/test",Uri_CREATE_ALLOW_RELATIVE,PARSE_DOMAIN,0,"",S_OK,FALSE},
6239     {"file://server/test",0,PARSE_DOMAIN,0,"",S_OK,FALSE},
6240
6241     /* PARSE_LOCATION and PARSE_ANCHOR tests. */
6242     {"http://google.com/test#Test",0,PARSE_ANCHOR,0,"#Test",S_OK,FALSE},
6243     {"http://google.com/test#Test",0,PARSE_LOCATION,0,"#Test",S_OK,FALSE},
6244     {"test",Uri_CREATE_ALLOW_RELATIVE,PARSE_ANCHOR,0,"",S_OK,FALSE},
6245     {"test",Uri_CREATE_ALLOW_RELATIVE,PARSE_LOCATION,0,"",S_OK,FALSE}
6246 };
6247
6248 static inline LPWSTR a2w(LPCSTR str) {
6249     LPWSTR ret = NULL;
6250
6251     if(str) {
6252         DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
6253         ret = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
6254         MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len);
6255     }
6256
6257     return ret;
6258 }
6259
6260 static inline BOOL heap_free(void* mem) {
6261     return HeapFree(GetProcessHeap(), 0, mem);
6262 }
6263
6264 static inline DWORD strcmp_aw(LPCSTR strA, LPCWSTR strB) {
6265     LPWSTR strAW = a2w(strA);
6266     DWORD ret = lstrcmpW(strAW, strB);
6267     heap_free(strAW);
6268     return ret;
6269 }
6270
6271 static inline ULONG get_refcnt(IUri *uri) {
6272     IUri_AddRef(uri);
6273     return IUri_Release(uri);
6274 }
6275
6276 static void change_property(IUriBuilder *builder, const uri_builder_property *prop,
6277                             DWORD test_index) {
6278     HRESULT hr;
6279     LPWSTR valueW;
6280
6281     valueW = a2w(prop->value);
6282     switch(prop->property) {
6283     case Uri_PROPERTY_FRAGMENT:
6284         hr = IUriBuilder_SetFragment(builder, valueW);
6285         if(prop->todo) {
6286             todo_wine {
6287                 ok(hr == prop->expected,
6288                     "Error: IUriBuilder_SetFragment returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6289                     hr, prop->expected, test_index);
6290             }
6291         } else {
6292             ok(hr == prop->expected,
6293                 "Error: IUriBuilder_SetFragment returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6294                 hr, prop->expected, test_index);
6295         }
6296         break;
6297     case Uri_PROPERTY_HOST:
6298         hr = IUriBuilder_SetHost(builder, valueW);
6299         if(prop->todo) {
6300             todo_wine {
6301                 ok(hr == prop->expected,
6302                     "Error: IUriBuilder_SetHost returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6303                     hr, prop->expected, test_index);
6304             }
6305         } else {
6306             ok(hr == prop->expected,
6307                 "Error: IUriBuilder_SetHost returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6308                 hr, prop->expected, test_index);
6309         }
6310         break;
6311     case Uri_PROPERTY_PASSWORD:
6312         hr = IUriBuilder_SetPassword(builder, valueW);
6313         if(prop->todo) {
6314             todo_wine {
6315                 ok(hr == prop->expected,
6316                     "Error: IUriBuilder_SetPassword returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6317                     hr, prop->expected, test_index);
6318             }
6319         } else {
6320             ok(hr == prop->expected,
6321                 "Error: IUriBuilder_SetPassword returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6322                 hr, prop->expected, test_index);
6323         }
6324         break;
6325     case Uri_PROPERTY_PATH:
6326         hr = IUriBuilder_SetPath(builder, valueW);
6327         if(prop->todo) {
6328             todo_wine {
6329                 ok(hr == prop->expected,
6330                     "Error: IUriBuilder_SetPath returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6331                     hr, prop->expected, test_index);
6332             }
6333         } else {
6334             ok(hr == prop->expected,
6335                 "Error: IUriBuilder_SetPath returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6336                 hr, prop->expected, test_index);
6337         }
6338         break;
6339     case Uri_PROPERTY_QUERY:
6340         hr = IUriBuilder_SetQuery(builder, valueW);
6341         if(prop->todo) {
6342             todo_wine {
6343                 ok(hr == prop->expected,
6344                     "Error: IUriBuilder_SetQuery returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6345                     hr, prop->expected, test_index);
6346             }
6347         } else {
6348             ok(hr == prop->expected,
6349                 "Error: IUriBuilder_SetQuery returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6350                 hr, prop->expected, test_index);
6351         }
6352         break;
6353     case Uri_PROPERTY_SCHEME_NAME:
6354         hr = IUriBuilder_SetSchemeName(builder, valueW);
6355         if(prop->todo) {
6356             todo_wine {
6357                 ok(hr == prop->expected,
6358                     "Error: IUriBuilder_SetSchemeName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6359                     hr, prop->expected, test_index);
6360             }
6361         } else {
6362             ok(hr == prop->expected,
6363                 "Error: IUriBuilder_SetSchemeName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6364                 hr, prop->expected, test_index);
6365         }
6366         break;
6367     case Uri_PROPERTY_USER_NAME:
6368         hr = IUriBuilder_SetUserName(builder, valueW);
6369         if(prop->todo) {
6370             todo_wine {
6371                 ok(hr == prop->expected,
6372                     "Error: IUriBuilder_SetUserName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6373                     hr, prop->expected, test_index);
6374             }
6375         } else {
6376             ok(hr == prop->expected,
6377                 "Error: IUriBuilder_SetUserName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6378                 hr, prop->expected, test_index);
6379         }
6380         break;
6381     default:
6382         trace("Unsupported operation for %d on uri_builder_tests[%d].\n", prop->property, test_index);
6383     }
6384
6385     heap_free(valueW);
6386 }
6387
6388 /*
6389  * Simple tests to make sure the CreateUri function handles invalid flag combinations
6390  * correctly.
6391  */
6392 static void test_CreateUri_InvalidFlags(void) {
6393     DWORD i;
6394
6395     for(i = 0; i < sizeof(invalid_flag_tests)/sizeof(invalid_flag_tests[0]); ++i) {
6396         HRESULT hr;
6397         IUri *uri = (void*) 0xdeadbeef;
6398
6399         hr = pCreateUri(http_urlW, invalid_flag_tests[i].flags, 0, &uri);
6400         ok(hr == invalid_flag_tests[i].expected, "Error: CreateUri returned 0x%08x, expected 0x%08x, flags=0x%08x\n",
6401                 hr, invalid_flag_tests[i].expected, invalid_flag_tests[i].flags);
6402         ok(uri == NULL, "Error: expected the IUri to be NULL, but it was %p instead\n", uri);
6403     }
6404 }
6405
6406 static void test_CreateUri_InvalidArgs(void) {
6407     HRESULT hr;
6408     IUri *uri = (void*) 0xdeadbeef;
6409
6410     const WCHAR invalidW[] = {'i','n','v','a','l','i','d',0};
6411     static const WCHAR emptyW[] = {0};
6412
6413     hr = pCreateUri(http_urlW, 0, 0, NULL);
6414     ok(hr == E_INVALIDARG, "Error: CreateUri returned 0x%08x, expected 0x%08x\n", hr, E_INVALIDARG);
6415
6416     hr = pCreateUri(NULL, 0, 0, &uri);
6417     ok(hr == E_INVALIDARG, "Error: CreateUri returned 0x%08x, expected 0x%08x\n", hr, E_INVALIDARG);
6418     ok(uri == NULL, "Error: Expected the IUri to be NULL, but it was %p instead\n", uri);
6419
6420     uri = (void*) 0xdeadbeef;
6421     hr = pCreateUri(invalidW, 0, 0, &uri);
6422     ok(hr == E_INVALIDARG, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
6423     ok(uri == NULL, "Error: Expected the IUri to be NULL, but it was %p instead\n", uri);
6424
6425     uri = (void*) 0xdeadbeef;
6426     hr = pCreateUri(emptyW, 0, 0, &uri);
6427     ok(hr == E_INVALIDARG, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
6428     ok(uri == NULL, "Error: Expected the IUri to be NULL, but it was %p instead\n", uri);
6429 }
6430
6431 static void test_CreateUri_InvalidUri(void) {
6432     DWORD i;
6433
6434     for(i = 0; i < sizeof(invalid_uri_tests)/sizeof(invalid_uri_tests[0]); ++i) {
6435         invalid_uri test = invalid_uri_tests[i];
6436         IUri *uri = NULL;
6437         LPWSTR uriW;
6438         HRESULT hr;
6439
6440         uriW = a2w(test.uri);
6441         hr = pCreateUri(uriW, test.flags, 0, &uri);
6442         if(test.todo) {
6443             todo_wine {
6444                 ok(hr == E_INVALIDARG, "Error: CreateUri returned 0x%08x, expected 0x%08x on invalid_uri_tests[%d].\n",
6445                     hr, E_INVALIDARG, i);
6446             }
6447         } else {
6448             ok(hr == E_INVALIDARG, "Error: CreateUri returned 0x%08x, expected 0x%08x on invalid_uri_tests[%d].\n",
6449                 hr, E_INVALIDARG, i);
6450         }
6451         if(uri) IUri_Release(uri);
6452
6453         heap_free(uriW);
6454     }
6455 }
6456
6457 static void test_IUri_GetPropertyBSTR(void) {
6458     IUri *uri = NULL;
6459     HRESULT hr;
6460     DWORD i;
6461
6462     /* Make sure GetPropertyBSTR handles invalid args correctly. */
6463     hr = pCreateUri(http_urlW, 0, 0, &uri);
6464     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
6465     if(SUCCEEDED(hr)) {
6466         BSTR received = NULL;
6467
6468         hr = IUri_GetPropertyBSTR(uri, Uri_PROPERTY_RAW_URI, NULL, 0);
6469         ok(hr == E_POINTER, "Error: GetPropertyBSTR returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
6470
6471         /* Make sure it handles a invalid Uri_PROPERTY's correctly. */
6472         hr = IUri_GetPropertyBSTR(uri, Uri_PROPERTY_PORT, &received, 0);
6473         ok(hr == S_OK, "Error: GetPropertyBSTR returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
6474         ok(received != NULL, "Error: Expected the string not to be NULL.\n");
6475         ok(!SysStringLen(received), "Error: Expected the string to be of len=0 but it was %d instead.\n", SysStringLen(received));
6476         SysFreeString(received);
6477
6478         /* Make sure it handles the ZONE property correctly. */
6479         received = NULL;
6480         hr = IUri_GetPropertyBSTR(uri, Uri_PROPERTY_ZONE, &received, 0);
6481         ok(hr == S_FALSE, "Error: GetPropertyBSTR returned 0x%08x, expected 0x%08x.\n", hr, S_FALSE);
6482         ok(received != NULL, "Error: Expected the string not to be NULL.\n");
6483         ok(!SysStringLen(received), "Error: Expected the string to be of len=0 but it was %d instead.\n", SysStringLen(received));
6484         SysFreeString(received);
6485     }
6486     if(uri) IUri_Release(uri);
6487
6488     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
6489         uri_properties test = uri_tests[i];
6490         LPWSTR uriW;
6491         uri = NULL;
6492
6493         uriW = a2w(test.uri);
6494         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
6495         if(test.create_todo) {
6496             todo_wine {
6497                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x. Failed on uri_tests[%d].\n",
6498                         hr, test.create_expected, i);
6499             }
6500         } else {
6501             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x. Failed on uri_tests[%d].\n",
6502                     hr, test.create_expected, i);
6503         }
6504
6505         if(SUCCEEDED(hr)) {
6506             DWORD j;
6507
6508             /* Checks all the string properties of the uri. */
6509             for(j = Uri_PROPERTY_STRING_START; j <= Uri_PROPERTY_STRING_LAST; ++j) {
6510                 BSTR received = NULL;
6511                 uri_str_property prop = test.str_props[j];
6512
6513                 hr = IUri_GetPropertyBSTR(uri, j, &received, 0);
6514                 if(prop.todo) {
6515                     todo_wine {
6516                         ok(hr == prop.expected, "GetPropertyBSTR returned 0x%08x, expected 0x%08x. On uri_tests[%d].str_props[%d].\n",
6517                                 hr, prop.expected, i, j);
6518                     }
6519                     todo_wine {
6520                         ok(!strcmp_aw(prop.value, received) || broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
6521                                 "Expected %s but got %s on uri_tests[%d].str_props[%d].\n",
6522                                 prop.value, wine_dbgstr_w(received), i, j);
6523                     }
6524                 } else {
6525                     ok(hr == prop.expected, "GetPropertyBSTR returned 0x%08x, expected 0x%08x. On uri_tests[%d].str_props[%d].\n",
6526                             hr, prop.expected, i, j);
6527                     ok(!strcmp_aw(prop.value, received) || broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
6528                             "Expected %s but got %s on uri_tests[%d].str_props[%d].\n",
6529                             prop.value, wine_dbgstr_w(received), i, j);
6530                 }
6531
6532                 SysFreeString(received);
6533             }
6534         }
6535
6536         if(uri) IUri_Release(uri);
6537
6538         heap_free(uriW);
6539     }
6540 }
6541
6542 static void test_IUri_GetPropertyDWORD(void) {
6543     IUri *uri = NULL;
6544     HRESULT hr;
6545     DWORD i;
6546
6547     hr = pCreateUri(http_urlW, 0, 0, &uri);
6548     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
6549     if(SUCCEEDED(hr)) {
6550         DWORD received = 0xdeadbeef;
6551
6552         hr = IUri_GetPropertyDWORD(uri, Uri_PROPERTY_DWORD_START, NULL, 0);
6553         ok(hr == E_INVALIDARG, "Error: GetPropertyDWORD returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
6554
6555         hr = IUri_GetPropertyDWORD(uri, Uri_PROPERTY_ABSOLUTE_URI, &received, 0);
6556         ok(hr == E_INVALIDARG, "Error: GetPropertyDWORD returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
6557         ok(received == 0, "Error: Expected received=%d but instead received=%d.\n", 0, received);
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. Failed 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. Failed on uri_tests[%d].\n",
6575                     hr, test.create_expected, i);
6576         }
6577
6578         if(SUCCEEDED(hr)) {
6579             DWORD j;
6580
6581             /* Checks all the DWORD properties of the uri. */
6582             for(j = 0; j < sizeof(test.dword_props)/sizeof(test.dword_props[0]); ++j) {
6583                 DWORD received;
6584                 uri_dword_property prop = test.dword_props[j];
6585
6586                 hr = IUri_GetPropertyDWORD(uri, j+Uri_PROPERTY_DWORD_START, &received, 0);
6587                 if(prop.todo) {
6588                     todo_wine {
6589                         ok(hr == prop.expected, "GetPropertyDWORD returned 0x%08x, expected 0x%08x. On uri_tests[%d].dword_props[%d].\n",
6590                                 hr, prop.expected, i, j);
6591                     }
6592                     todo_wine {
6593                         ok(prop.value == received, "Expected %d but got %d on uri_tests[%d].dword_props[%d].\n",
6594                                 prop.value, received, i, j);
6595                     }
6596                 } else {
6597                     ok(hr == prop.expected, "GetPropertyDWORD returned 0x%08x, expected 0x%08x. On uri_tests[%d].dword_props[%d].\n",
6598                             hr, prop.expected, i, j);
6599                     ok(prop.value == received, "Expected %d but got %d on uri_tests[%d].dword_props[%d].\n",
6600                             prop.value, received, i, j);
6601                 }
6602             }
6603         }
6604
6605         if(uri) IUri_Release(uri);
6606
6607         heap_free(uriW);
6608     }
6609 }
6610
6611 /* Tests all the 'Get*' property functions which deal with strings. */
6612 static void test_IUri_GetStrProperties(void) {
6613     IUri *uri = NULL;
6614     HRESULT hr;
6615     DWORD i;
6616
6617     /* Make sure all the 'Get*' string property functions handle invalid args correctly. */
6618     hr = pCreateUri(http_urlW, 0, 0, &uri);
6619     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
6620     if(SUCCEEDED(hr)) {
6621         hr = IUri_GetAbsoluteUri(uri, NULL);
6622         ok(hr == E_POINTER, "Error: GetAbsoluteUri returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
6623
6624         hr = IUri_GetAuthority(uri, NULL);
6625         ok(hr == E_POINTER, "Error: GetAuthority returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
6626
6627         hr = IUri_GetDisplayUri(uri, NULL);
6628         ok(hr == E_POINTER, "Error: GetDisplayUri returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
6629
6630         hr = IUri_GetDomain(uri, NULL);
6631         ok(hr == E_POINTER, "Error: GetDomain returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
6632
6633         hr = IUri_GetExtension(uri, NULL);
6634         ok(hr == E_POINTER, "Error: GetExtension returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
6635
6636         hr = IUri_GetFragment(uri, NULL);
6637         ok(hr == E_POINTER, "Error: GetFragment returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
6638
6639         hr = IUri_GetHost(uri, NULL);
6640         ok(hr == E_POINTER, "Error: GetHost returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
6641
6642         hr = IUri_GetPassword(uri, NULL);
6643         ok(hr == E_POINTER, "Error: GetPassword returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
6644
6645         hr = IUri_GetPath(uri, NULL);
6646         ok(hr == E_POINTER, "Error: GetPath returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
6647
6648         hr = IUri_GetPathAndQuery(uri, NULL);
6649         ok(hr == E_POINTER, "Error: GetPathAndQuery returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
6650
6651         hr = IUri_GetQuery(uri, NULL);
6652         ok(hr == E_POINTER, "Error: GetQuery returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
6653
6654         hr = IUri_GetRawUri(uri, NULL);
6655         ok(hr == E_POINTER, "Error: GetRawUri returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
6656
6657         hr = IUri_GetSchemeName(uri, NULL);
6658         ok(hr == E_POINTER, "Error: GetSchemeName returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
6659
6660         hr = IUri_GetUserInfo(uri, NULL);
6661         ok(hr == E_POINTER, "Error: GetUserInfo returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
6662
6663         hr = IUri_GetUserName(uri, NULL);
6664         ok(hr == E_POINTER, "Error: GetUserName returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
6665     }
6666     if(uri) IUri_Release(uri);
6667
6668     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
6669         uri_properties test = uri_tests[i];
6670         LPWSTR uriW;
6671         uri = NULL;
6672
6673         uriW = a2w(test.uri);
6674         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
6675         if(test.create_todo) {
6676             todo_wine {
6677                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6678                         hr, test.create_expected, i);
6679             }
6680         } else {
6681             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6682                     hr, test.create_expected, i);
6683         }
6684
6685         if(SUCCEEDED(hr)) {
6686             uri_str_property prop;
6687             BSTR received = NULL;
6688
6689             /* GetAbsoluteUri() tests. */
6690             prop = test.str_props[Uri_PROPERTY_ABSOLUTE_URI];
6691             hr = IUri_GetAbsoluteUri(uri, &received);
6692             if(prop.todo) {
6693                 todo_wine {
6694                     ok(hr == prop.expected, "Error: GetAbsoluteUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6695                             hr, prop.expected, i);
6696                 }
6697                 todo_wine {
6698                     ok(!strcmp_aw(prop.value, received) || broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
6699                             "Error: Expected %s but got %s on uri_tests[%d].\n",
6700                             prop.value, wine_dbgstr_w(received), i);
6701                 }
6702             } else {
6703                 ok(hr == prop.expected, "Error: GetAbsoluteUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6704                         hr, prop.expected, i);
6705                 ok(!strcmp_aw(prop.value, received) || broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
6706                         "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             /* GetAuthority() tests. */
6713             prop = test.str_props[Uri_PROPERTY_AUTHORITY];
6714             hr = IUri_GetAuthority(uri, &received);
6715             if(prop.todo) {
6716                 todo_wine {
6717                     ok(hr == prop.expected, "Error: GetAuthority 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: GetAuthority 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             /* GetDisplayUri() tests. */
6734             prop = test.str_props[Uri_PROPERTY_DISPLAY_URI];
6735             hr = IUri_GetDisplayUri(uri, &received);
6736             if(prop.todo) {
6737                 todo_wine {
6738                     ok(hr == prop.expected, "Error: GetDisplayUri 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) || broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
6743                             "Error: Expected %s but got %s on uri_test[%d].\n",
6744                             prop.value, wine_dbgstr_w(received), i);
6745                 }
6746             } else {
6747                 ok(hr == prop.expected, "Error: GetDisplayUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6748                         hr, prop.expected, i);
6749                 ok(!strcmp_aw(prop.value, received) || broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
6750                         "Error: Expected %s but got %s on uri_tests[%d].\n",
6751                         prop.value, wine_dbgstr_w(received), i);
6752             }
6753             SysFreeString(received);
6754             received = NULL;
6755
6756             /* GetDomain() tests. */
6757             prop = test.str_props[Uri_PROPERTY_DOMAIN];
6758             hr = IUri_GetDomain(uri, &received);
6759             if(prop.todo) {
6760                 todo_wine {
6761                     ok(hr == prop.expected, "Error: GetDomain returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6762                             hr, prop.expected, i);
6763                 }
6764                 todo_wine {
6765                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6766                             prop.value, wine_dbgstr_w(received), i);
6767                 }
6768             } else {
6769                 ok(hr == prop.expected, "Error: GetDomain returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6770                         hr, prop.expected, i);
6771                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6772                         prop.value, wine_dbgstr_w(received), i);
6773             }
6774             SysFreeString(received);
6775             received = NULL;
6776
6777             /* GetExtension() tests. */
6778             prop = test.str_props[Uri_PROPERTY_EXTENSION];
6779             hr = IUri_GetExtension(uri, &received);
6780             if(prop.todo) {
6781                 todo_wine {
6782                     ok(hr == prop.expected, "Error: GetExtension returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6783                             hr, prop.expected, i);
6784                 }
6785                 todo_wine {
6786                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6787                             prop.value, wine_dbgstr_w(received), i);
6788                 }
6789             } else {
6790                 ok(hr == prop.expected, "Error: GetExtension returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6791                         hr, prop.expected, i);
6792                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6793                         prop.value, wine_dbgstr_w(received), i);
6794             }
6795             SysFreeString(received);
6796             received = NULL;
6797
6798             /* GetFragment() tests. */
6799             prop = test.str_props[Uri_PROPERTY_FRAGMENT];
6800             hr = IUri_GetFragment(uri, &received);
6801             if(prop.todo) {
6802                 todo_wine {
6803                     ok(hr == prop.expected, "Error: GetFragment returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6804                             hr, prop.expected, i);
6805                 }
6806                 todo_wine {
6807                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6808                             prop.value, wine_dbgstr_w(received), i);
6809                 }
6810             } else {
6811                 ok(hr == prop.expected, "Error: GetFragment returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6812                         hr, prop.expected, i);
6813                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6814                         prop.value, wine_dbgstr_w(received), i);
6815             }
6816             SysFreeString(received);
6817             received = NULL;
6818
6819             /* GetHost() tests. */
6820             prop = test.str_props[Uri_PROPERTY_HOST];
6821             hr = IUri_GetHost(uri, &received);
6822             if(prop.todo) {
6823                 todo_wine {
6824                     ok(hr == prop.expected, "Error: GetHost returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6825                             hr, prop.expected, i);
6826                 }
6827                 todo_wine {
6828                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6829                             prop.value, wine_dbgstr_w(received), i);
6830                 }
6831             } else {
6832                 ok(hr == prop.expected, "Error: GetHost returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6833                         hr, prop.expected, i);
6834                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6835                         prop.value, wine_dbgstr_w(received), i);
6836             }
6837             SysFreeString(received);
6838             received = NULL;
6839
6840             /* GetPassword() tests. */
6841             prop = test.str_props[Uri_PROPERTY_PASSWORD];
6842             hr = IUri_GetPassword(uri, &received);
6843             if(prop.todo) {
6844                 todo_wine {
6845                     ok(hr == prop.expected, "Error: GetPassword returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6846                             hr, prop.expected, i);
6847                 }
6848                 todo_wine {
6849                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6850                             prop.value, wine_dbgstr_w(received), i);
6851                 }
6852             } else {
6853                 ok(hr == prop.expected, "Error: GetPassword returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6854                         hr, prop.expected, i);
6855                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6856                         prop.value, wine_dbgstr_w(received), i);
6857             }
6858             SysFreeString(received);
6859             received = NULL;
6860
6861             /* GetPath() tests. */
6862             prop = test.str_props[Uri_PROPERTY_PATH];
6863             hr = IUri_GetPath(uri, &received);
6864             if(prop.todo) {
6865                 todo_wine {
6866                     ok(hr == prop.expected, "Error: GetPath returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6867                             hr, prop.expected, i);
6868                 }
6869                 todo_wine {
6870                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6871                             prop.value, wine_dbgstr_w(received), i);
6872                 }
6873             } else {
6874                 ok(hr == prop.expected, "Error: GetPath returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6875                         hr, prop.expected, i);
6876                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6877                         prop.value, wine_dbgstr_w(received), i);
6878             }
6879             SysFreeString(received);
6880             received = NULL;
6881
6882             /* GetPathAndQuery() tests. */
6883             prop = test.str_props[Uri_PROPERTY_PATH_AND_QUERY];
6884             hr = IUri_GetPathAndQuery(uri, &received);
6885             if(prop.todo) {
6886                 todo_wine {
6887                     ok(hr == prop.expected, "Error: GetPathAndQuery returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6888                             hr, prop.expected, i);
6889                 }
6890                 todo_wine {
6891                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6892                             prop.value, wine_dbgstr_w(received), i);
6893                 }
6894             } else {
6895                 ok(hr == prop.expected, "Error: GetPathAndQuery returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6896                         hr, prop.expected, i);
6897                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6898                         prop.value, wine_dbgstr_w(received), i);
6899             }
6900             SysFreeString(received);
6901             received = NULL;
6902
6903             /* GetQuery() tests. */
6904             prop = test.str_props[Uri_PROPERTY_QUERY];
6905             hr = IUri_GetQuery(uri, &received);
6906             if(prop.todo) {
6907                 todo_wine {
6908                     ok(hr == prop.expected, "Error: GetQuery returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6909                             hr, prop.expected, i);
6910                 }
6911                 todo_wine {
6912                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6913                             prop.value, wine_dbgstr_w(received), i);
6914                 }
6915             } else {
6916                 ok(hr == prop.expected, "Error: GetQuery returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6917                         hr, prop.expected, i);
6918                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6919                         prop.value, wine_dbgstr_w(received), i);
6920             }
6921             SysFreeString(received);
6922             received = NULL;
6923
6924             /* GetRawUri() tests. */
6925             prop = test.str_props[Uri_PROPERTY_RAW_URI];
6926             hr = IUri_GetRawUri(uri, &received);
6927             if(prop.todo) {
6928                 todo_wine {
6929                     ok(hr == prop.expected, "Error: GetRawUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6930                             hr, prop.expected, i);
6931                 }
6932                 todo_wine {
6933                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6934                             prop.value, wine_dbgstr_w(received), i);
6935                 }
6936             } else {
6937                 ok(hr == prop.expected, "Error: GetRawUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6938                         hr, prop.expected, i);
6939                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6940                         prop.value, wine_dbgstr_w(received), i);
6941             }
6942             SysFreeString(received);
6943             received = NULL;
6944
6945             /* GetSchemeName() tests. */
6946             prop = test.str_props[Uri_PROPERTY_SCHEME_NAME];
6947             hr = IUri_GetSchemeName(uri, &received);
6948             if(prop.todo) {
6949                 todo_wine {
6950                     ok(hr == prop.expected, "Error: GetSchemeName returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6951                             hr, prop.expected, i);
6952                 }
6953                 todo_wine {
6954                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6955                             prop.value, wine_dbgstr_w(received), i);
6956                 }
6957             } else {
6958                 ok(hr == prop.expected, "Error: GetSchemeName returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6959                         hr, prop.expected, i);
6960                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6961                         prop.value, wine_dbgstr_w(received), i);
6962             }
6963             SysFreeString(received);
6964             received = NULL;
6965
6966             /* GetUserInfo() tests. */
6967             prop = test.str_props[Uri_PROPERTY_USER_INFO];
6968             hr = IUri_GetUserInfo(uri, &received);
6969             if(prop.todo) {
6970                 todo_wine {
6971                     ok(hr == prop.expected, "Error: GetUserInfo returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6972                             hr, prop.expected, i);
6973                 }
6974                 todo_wine {
6975                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6976                             prop.value, wine_dbgstr_w(received), i);
6977                 }
6978             } else {
6979                 ok(hr == prop.expected, "Error: GetUserInfo returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6980                         hr, prop.expected, i);
6981                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6982                         prop.value, wine_dbgstr_w(received), i);
6983             }
6984             SysFreeString(received);
6985             received = NULL;
6986
6987             /* GetUserName() tests. */
6988             prop = test.str_props[Uri_PROPERTY_USER_NAME];
6989             hr = IUri_GetUserName(uri, &received);
6990             if(prop.todo) {
6991                 todo_wine {
6992                     ok(hr == prop.expected, "Error: GetUserName returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6993                             hr, prop.expected, i);
6994                 }
6995                 todo_wine {
6996                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6997                             prop.value, wine_dbgstr_w(received), i);
6998                 }
6999             } else {
7000                 ok(hr == prop.expected, "Error: GetUserName returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7001                         hr, prop.expected, i);
7002                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
7003                         prop.value, wine_dbgstr_w(received), i);
7004             }
7005             SysFreeString(received);
7006         }
7007
7008         if(uri) IUri_Release(uri);
7009
7010         heap_free(uriW);
7011     }
7012 }
7013
7014 static void test_IUri_GetDwordProperties(void) {
7015     IUri *uri = NULL;
7016     HRESULT hr;
7017     DWORD i;
7018
7019     /* Make sure all the 'Get*' dword property functions handle invalid args correctly. */
7020     hr = pCreateUri(http_urlW, 0, 0, &uri);
7021     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7022     if(SUCCEEDED(hr)) {
7023         hr = IUri_GetHostType(uri, NULL);
7024         ok(hr == E_INVALIDARG, "Error: GetHostType returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
7025
7026         hr = IUri_GetPort(uri, NULL);
7027         ok(hr == E_INVALIDARG, "Error: GetPort returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
7028
7029         hr = IUri_GetScheme(uri, NULL);
7030         ok(hr == E_INVALIDARG, "Error: GetScheme returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
7031
7032         hr = IUri_GetZone(uri, NULL);
7033         ok(hr == E_INVALIDARG, "Error: GetZone returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
7034     }
7035     if(uri) IUri_Release(uri);
7036
7037     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
7038         uri_properties test = uri_tests[i];
7039         LPWSTR uriW;
7040         uri = NULL;
7041
7042         uriW = a2w(test.uri);
7043         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
7044         if(test.create_todo) {
7045             todo_wine {
7046                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7047                         hr, test.create_expected, i);
7048             }
7049         } else {
7050             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7051                     hr, test.create_expected, i);
7052         }
7053
7054         if(SUCCEEDED(hr)) {
7055             uri_dword_property prop;
7056             DWORD received;
7057
7058             /* Assign an insane value so tests don't accidentally pass when
7059              * they shouldn't!
7060              */
7061             received = -9999999;
7062
7063             /* GetHostType() tests. */
7064             prop = test.dword_props[Uri_PROPERTY_HOST_TYPE-Uri_PROPERTY_DWORD_START];
7065             hr = IUri_GetHostType(uri, &received);
7066             if(prop.todo) {
7067                 todo_wine {
7068                     ok(hr == prop.expected, "Error: GetHostType returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7069                             hr, prop.expected, i);
7070                 }
7071                 todo_wine {
7072                     ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
7073                 }
7074             } else {
7075                 ok(hr == prop.expected, "Error: GetHostType returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7076                         hr, prop.expected, i);
7077                 ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
7078             }
7079             received = -9999999;
7080
7081             /* GetPort() tests. */
7082             prop = test.dword_props[Uri_PROPERTY_PORT-Uri_PROPERTY_DWORD_START];
7083             hr = IUri_GetPort(uri, &received);
7084             if(prop.todo) {
7085                 todo_wine {
7086                     ok(hr == prop.expected, "Error: GetPort returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7087                             hr, prop.expected, i);
7088                 }
7089                 todo_wine {
7090                     ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
7091                 }
7092             } else {
7093                 ok(hr == prop.expected, "Error: GetPort returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7094                         hr, prop.expected, i);
7095                 ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
7096             }
7097             received = -9999999;
7098
7099             /* GetScheme() tests. */
7100             prop = test.dword_props[Uri_PROPERTY_SCHEME-Uri_PROPERTY_DWORD_START];
7101             hr = IUri_GetScheme(uri, &received);
7102             if(prop.todo) {
7103                 todo_wine {
7104                     ok(hr == prop.expected, "Error: GetScheme returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7105                             hr, prop.expected, i);
7106                 }
7107                 todo_wine {
7108                     ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
7109                 }
7110             } else {
7111                 ok(hr == prop.expected, "Error: GetScheme returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7112                         hr, prop.expected, i);
7113                 ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
7114             }
7115             received = -9999999;
7116
7117             /* GetZone() tests. */
7118             prop = test.dword_props[Uri_PROPERTY_ZONE-Uri_PROPERTY_DWORD_START];
7119             hr = IUri_GetZone(uri, &received);
7120             if(prop.todo) {
7121                 todo_wine {
7122                     ok(hr == prop.expected, "Error: GetZone returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7123                             hr, prop.expected, i);
7124                 }
7125                 todo_wine {
7126                     ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
7127                 }
7128             } else {
7129                 ok(hr == prop.expected, "Error: GetZone returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7130                         hr, prop.expected, i);
7131                 ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
7132             }
7133         }
7134
7135         if(uri) IUri_Release(uri);
7136
7137         heap_free(uriW);
7138     }
7139 }
7140
7141 static void test_IUri_GetPropertyLength(void) {
7142     IUri *uri = NULL;
7143     HRESULT hr;
7144     DWORD i;
7145
7146     /* Make sure it handles invalid args correctly. */
7147     hr = pCreateUri(http_urlW, 0, 0, &uri);
7148     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7149     if(SUCCEEDED(hr)) {
7150         DWORD received = 0xdeadbeef;
7151
7152         hr = IUri_GetPropertyLength(uri, Uri_PROPERTY_STRING_START, NULL, 0);
7153         ok(hr == E_INVALIDARG, "Error: GetPropertyLength returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
7154
7155         hr = IUri_GetPropertyLength(uri, Uri_PROPERTY_DWORD_START, &received, 0);
7156         ok(hr == E_INVALIDARG, "Error: GetPropertyLength return 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
7157         ok(received == 0xdeadbeef, "Error: Expected 0xdeadbeef but got 0x%08x.\n", received);
7158     }
7159     if(uri) IUri_Release(uri);
7160
7161     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
7162         uri_properties test = uri_tests[i];
7163         LPWSTR uriW;
7164         uri = NULL;
7165
7166         uriW = a2w(test.uri);
7167         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
7168         if(test.create_todo) {
7169             todo_wine {
7170                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7171                         hr, test.create_expected, i);
7172             }
7173         } else {
7174             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_test[%d].\n",
7175                     hr, test.create_expected, i);
7176         }
7177
7178         if(SUCCEEDED(hr)) {
7179             DWORD j;
7180
7181             for(j = Uri_PROPERTY_STRING_START; j <= Uri_PROPERTY_STRING_LAST; ++j) {
7182                 DWORD expectedLen, brokenLen, receivedLen;
7183                 uri_str_property prop = test.str_props[j];
7184
7185                 expectedLen = lstrlen(prop.value);
7186                 brokenLen = lstrlen(prop.broken_value);
7187
7188                 /* This won't be necessary once GetPropertyLength is implemented. */
7189                 receivedLen = -1;
7190
7191                 hr = IUri_GetPropertyLength(uri, j, &receivedLen, 0);
7192                 if(prop.todo) {
7193                     todo_wine {
7194                         ok(hr == prop.expected, "Error: GetPropertyLength returned 0x%08x, expected 0x%08x on uri_tests[%d].str_props[%d].\n",
7195                                 hr, prop.expected, i, j);
7196                     }
7197                     todo_wine {
7198                         ok(receivedLen == expectedLen || broken(receivedLen == brokenLen),
7199                                 "Error: Expected a length of %d but got %d on uri_tests[%d].str_props[%d].\n",
7200                                 expectedLen, receivedLen, i, j);
7201                     }
7202                 } else {
7203                     ok(hr == prop.expected, "Error: GetPropertyLength returned 0x%08x, expected 0x%08x on uri_tests[%d].str_props[%d].\n",
7204                             hr, prop.expected, i, j);
7205                     ok(receivedLen == expectedLen || broken(receivedLen == brokenLen),
7206                             "Error: Expected a length of %d but got %d on uri_tests[%d].str_props[%d].\n",
7207                             expectedLen, receivedLen, i, j);
7208                 }
7209             }
7210         }
7211
7212         if(uri) IUri_Release(uri);
7213
7214         heap_free(uriW);
7215     }
7216 }
7217
7218 static DWORD compute_expected_props(uri_properties *test)
7219 {
7220     DWORD ret = 0, i;
7221
7222     for(i=Uri_PROPERTY_STRING_START; i <= Uri_PROPERTY_STRING_LAST; i++) {
7223         if(test->str_props[i-Uri_PROPERTY_STRING_START].expected == S_OK)
7224             ret |= 1<<i;
7225     }
7226
7227     for(i=Uri_PROPERTY_DWORD_START; i <= Uri_PROPERTY_DWORD_LAST; i++) {
7228         if(test->dword_props[i-Uri_PROPERTY_DWORD_START].expected == S_OK)
7229             ret |= 1<<i;
7230     }
7231
7232     return ret;
7233 }
7234
7235 static void test_IUri_GetProperties(void) {
7236     IUri *uri = NULL;
7237     HRESULT hr;
7238     DWORD i;
7239
7240     hr = pCreateUri(http_urlW, 0, 0, &uri);
7241     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7242     if(SUCCEEDED(hr)) {
7243         hr = IUri_GetProperties(uri, NULL);
7244         ok(hr == E_INVALIDARG, "Error: GetProperties returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
7245     }
7246     if(uri) IUri_Release(uri);
7247
7248     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
7249         uri_properties test = uri_tests[i];
7250         LPWSTR uriW;
7251         uri = NULL;
7252
7253         uriW = a2w(test.uri);
7254         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
7255         if(test.create_todo) {
7256             todo_wine {
7257                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, test.create_expected);
7258             }
7259         } else {
7260             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, test.create_expected);
7261         }
7262
7263         if(SUCCEEDED(hr)) {
7264             DWORD received = 0, expected_props;
7265             DWORD j;
7266
7267             hr = IUri_GetProperties(uri, &received);
7268             ok(hr == S_OK, "Error: GetProperties returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7269
7270             expected_props = compute_expected_props(&test);
7271
7272             for(j = 0; j <= Uri_PROPERTY_DWORD_LAST; ++j) {
7273                 /* (1 << j) converts a Uri_PROPERTY to its corresponding Uri_HAS_* flag mask. */
7274                 if(expected_props & (1 << j))
7275                     ok(received & (1 << j), "Error: Expected flag for property %d on uri_tests[%d].\n", j, i);
7276                 else
7277                     ok(!(received & (1 << j)), "Error: Received flag for property %d when not expected on uri_tests[%d].\n", j, i);
7278             }
7279         }
7280
7281         if(uri) IUri_Release(uri);
7282
7283         heap_free(uriW);
7284     }
7285 }
7286
7287 static void test_IUri_HasProperty(void) {
7288     IUri *uri = NULL;
7289     HRESULT hr;
7290     DWORD i;
7291
7292     hr = pCreateUri(http_urlW, 0, 0, &uri);
7293     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7294     if(SUCCEEDED(hr)) {
7295         hr = IUri_HasProperty(uri, Uri_PROPERTY_RAW_URI, NULL);
7296         ok(hr == E_INVALIDARG, "Error: HasProperty returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
7297     }
7298     if(uri) IUri_Release(uri);
7299
7300     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
7301         uri_properties test = uri_tests[i];
7302         LPWSTR uriW;
7303         uri = NULL;
7304
7305         uriW = a2w(test.uri);
7306
7307         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
7308         if(test.create_todo) {
7309             todo_wine {
7310                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, test.create_expected);
7311             }
7312         } else {
7313             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, test.create_expected);
7314         }
7315
7316         if(SUCCEEDED(hr)) {
7317             DWORD expected_props, j;
7318
7319             expected_props = compute_expected_props(&test);
7320
7321             for(j = 0; j <= Uri_PROPERTY_DWORD_LAST; ++j) {
7322                 /* Assign -1, then explicitly test for TRUE or FALSE later. */
7323                 BOOL received = -1;
7324
7325                 hr = IUri_HasProperty(uri, j, &received);
7326                 ok(hr == S_OK, "Error: HasProperty returned 0x%08x, expected 0x%08x for property %d on uri_tests[%d].\n",
7327                         hr, S_OK, j, i);
7328
7329                 if(expected_props & (1 << j)) {
7330                     ok(received == TRUE, "Error: Expected to have property %d on uri_tests[%d].\n", j, i);
7331                 } else {
7332                     ok(received == FALSE, "Error: Wasn't expecting to have property %d on uri_tests[%d].\n", j, i);
7333                 }
7334             }
7335         }
7336
7337         if(uri) IUri_Release(uri);
7338
7339         heap_free(uriW);
7340     }
7341 }
7342
7343 static void test_IUri_IsEqual(void) {
7344     IUri *uriA, *uriB;
7345     HRESULT hrA, hrB;
7346     DWORD i;
7347
7348     uriA = uriB = NULL;
7349
7350     /* Make sure IsEqual handles invalid args correctly. */
7351     hrA = pCreateUri(http_urlW, 0, 0, &uriA);
7352     hrB = pCreateUri(http_urlW, 0, 0, &uriB);
7353     ok(hrA == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hrA, S_OK);
7354     ok(hrB == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hrB, S_OK);
7355     if(SUCCEEDED(hrA) && SUCCEEDED(hrB)) {
7356         BOOL equal = -1;
7357         hrA = IUri_IsEqual(uriA, NULL, &equal);
7358         ok(hrA == S_OK, "Error: IsEqual returned 0x%08x, expected 0x%08x.\n", hrA, S_OK);
7359         ok(equal == FALSE, "Error: Expected equal to be FALSE, but was %d instead.\n", equal);
7360
7361         hrA = IUri_IsEqual(uriA, uriB, NULL);
7362         ok(hrA == E_POINTER, "Error: IsEqual returned 0x%08x, expected 0x%08x.\n", hrA, E_POINTER);
7363     }
7364     if(uriA) IUri_Release(uriA);
7365     if(uriB) IUri_Release(uriB);
7366
7367     for(i = 0; i < sizeof(equality_tests)/sizeof(equality_tests[0]); ++i) {
7368         uri_equality test = equality_tests[i];
7369         LPWSTR uriA_W, uriB_W;
7370
7371         uriA = uriB = NULL;
7372
7373         uriA_W = a2w(test.a);
7374         uriB_W = a2w(test.b);
7375
7376         hrA = pCreateUri(uriA_W, test.create_flags_a, 0, &uriA);
7377         if(test.create_todo_a) {
7378             todo_wine {
7379                 ok(hrA == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x on equality_tests[%d].a\n",
7380                         hrA, S_OK, i);
7381             }
7382         } else {
7383             ok(hrA == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x on equality_tests[%d].a\n",
7384                     hrA, S_OK, i);
7385         }
7386
7387         hrB = pCreateUri(uriB_W, test.create_flags_b, 0, &uriB);
7388         if(test.create_todo_b) {
7389             todo_wine {
7390                 ok(hrB == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x on equality_tests[%d].b\n",
7391                         hrB, S_OK, i);
7392             }
7393         } else {
7394             ok(hrB == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x on equality_tests[%d].b\n",
7395                     hrB, S_OK, i);
7396         }
7397
7398         if(SUCCEEDED(hrA) && SUCCEEDED(hrB)) {
7399             BOOL equal = -1;
7400
7401             hrA = IUri_IsEqual(uriA, uriB, &equal);
7402             if(test.todo) {
7403                 todo_wine {
7404                     ok(hrA == S_OK, "Error: IsEqual returned 0x%08x, expected 0x%08x on equality_tests[%d].\n",
7405                             hrA, S_OK, i);
7406                 }
7407                 todo_wine {
7408                     ok(equal == test.equal, "Error: Expected the comparison to be %d on equality_tests[%d].\n", test.equal, i);
7409                 }
7410             } else {
7411                 ok(hrA == S_OK, "Error: IsEqual returned 0x%08x, expected 0x%08x on equality_tests[%d].\n", hrA, S_OK, i);
7412                 ok(equal == test.equal, "Error: Expected the comparison to be %d on equality_tests[%d].\n", test.equal, i);
7413             }
7414         }
7415         if(uriA) IUri_Release(uriA);
7416         if(uriB) IUri_Release(uriB);
7417
7418         heap_free(uriA_W);
7419         heap_free(uriB_W);
7420     }
7421 }
7422
7423 static void test_CreateUriWithFragment_InvalidArgs(void) {
7424     HRESULT hr;
7425     IUri *uri = (void*) 0xdeadbeef;
7426     const WCHAR fragmentW[] = {'#','f','r','a','g','m','e','n','t',0};
7427
7428     hr = pCreateUriWithFragment(NULL, fragmentW, 0, 0, &uri);
7429     ok(hr == E_INVALIDARG, "Error: CreateUriWithFragment returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
7430     ok(uri == NULL, "Error: Expected uri to be NULL, but was %p instead.\n", uri);
7431
7432     hr = pCreateUriWithFragment(http_urlW, fragmentW, 0, 0, NULL);
7433     ok(hr == E_INVALIDARG, "Error: CreateUriWithFragment returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
7434
7435     /* Original URI can't already contain a fragment component. */
7436     uri = (void*) 0xdeadbeef;
7437     hr = pCreateUriWithFragment(http_url_fragW, fragmentW, 0, 0, &uri);
7438     ok(hr == E_INVALIDARG, "Error: CreateUriWithFragment returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
7439     ok(uri == NULL, "Error: Expected uri to be NULL, but was %p instead.\n", uri);
7440 }
7441
7442 /* CreateUriWithFragment has the same invalid flag combinations as CreateUri. */
7443 static void test_CreateUriWithFragment_InvalidFlags(void) {
7444     DWORD i;
7445
7446     for(i = 0; i < sizeof(invalid_flag_tests)/sizeof(invalid_flag_tests[0]); ++i) {
7447         HRESULT hr;
7448         IUri *uri = (void*) 0xdeadbeef;
7449
7450         hr = pCreateUriWithFragment(http_urlW, NULL, invalid_flag_tests[i].flags, 0, &uri);
7451         ok(hr == invalid_flag_tests[i].expected, "Error: CreateUriWithFragment returned 0x%08x, expected 0x%08x. flags=0x%08x.\n",
7452             hr, invalid_flag_tests[i].expected, invalid_flag_tests[i].flags);
7453         ok(uri == NULL, "Error: Expected uri to be NULL, but was %p instead.\n", uri);
7454     }
7455 }
7456
7457 static void test_CreateUriWithFragment(void) {
7458     DWORD i;
7459
7460     for(i = 0; i < sizeof(uri_fragment_tests)/sizeof(uri_fragment_tests[0]); ++i) {
7461         HRESULT hr;
7462         IUri *uri = NULL;
7463         LPWSTR uriW, fragW;
7464         uri_with_fragment test = uri_fragment_tests[i];
7465
7466         uriW = a2w(test.uri);
7467         fragW = a2w(test.fragment);
7468
7469         hr = pCreateUriWithFragment(uriW, fragW, test.create_flags, 0, &uri);
7470         if(test.expected_todo) {
7471             todo_wine {
7472                 ok(hr == test.create_expected,
7473                     "Error: CreateUriWithFragment returned 0x%08x, expected 0x%08x on uri_fragment_tests[%d].\n",
7474                     hr, test.create_expected, i);
7475             }
7476         } else
7477             ok(hr == test.create_expected,
7478                 "Error: CreateUriWithFragment returned 0x%08x, expected 0x%08x on uri_fragment_tests[%d].\n",
7479                 hr, test.create_expected, i);
7480
7481         if(SUCCEEDED(hr)) {
7482             BSTR received = NULL;
7483
7484             hr = IUri_GetAbsoluteUri(uri, &received);
7485             if(test.expected_todo) {
7486                 todo_wine {
7487                     ok(hr == S_OK,
7488                         "Error: GetAbsoluteUri returned 0x%08x, expected 0x%08x on uri_fragment_tests[%d].\n",
7489                         hr, S_OK, i);
7490                 }
7491                 todo_wine {
7492                     ok(!strcmp_aw(test.expected_uri, received),
7493                         "Error: Expected %s but got %s on uri_fragment_tests[%d].\n",
7494                         test.expected_uri, wine_dbgstr_w(received), i);
7495                 }
7496             } else {
7497                 ok(hr == S_OK, "Error: GetAbsoluteUri returned 0x%08x, expected 0x%08x on uri_fragment_tests[%d].\n",
7498                     hr, S_OK, i);
7499                 ok(!strcmp_aw(test.expected_uri, received), "Error: Expected %s but got %s on uri_fragment_tests[%d].\n",
7500                     test.expected_uri, wine_dbgstr_w(received), i);
7501             }
7502
7503             SysFreeString(received);
7504         }
7505
7506         if(uri) IUri_Release(uri);
7507         heap_free(uriW);
7508         heap_free(fragW);
7509     }
7510 }
7511
7512 static void test_CreateIUriBuilder(void) {
7513     HRESULT hr;
7514     IUriBuilder *builder = NULL;
7515     IUri *uri;
7516
7517     hr = pCreateIUriBuilder(NULL, 0, 0, NULL);
7518     ok(hr == E_POINTER, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x\n",
7519         hr, E_POINTER);
7520
7521     /* CreateIUriBuilder increases the ref count of the IUri it receives. */
7522     hr = pCreateUri(http_urlW, 0, 0, &uri);
7523     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7524     if(SUCCEEDED(hr)) {
7525         ULONG cur_count, orig_count;
7526
7527         orig_count = get_refcnt(uri);
7528         hr = pCreateIUriBuilder(uri, 0, 0, &builder);
7529         ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7530         ok(builder != NULL, "Error: Expecting builder not to be NULL\n");
7531
7532         cur_count = get_refcnt(uri);
7533         ok(cur_count == orig_count+1, "Error: Expected the ref count to be %u, but was %u instead.\n", orig_count+1, cur_count);
7534
7535         if(builder) IUriBuilder_Release(builder);
7536         cur_count = get_refcnt(uri);
7537         ok(cur_count == orig_count, "Error: Expected the ref count to be %u, but was %u instead.\n", orig_count, cur_count);
7538     }
7539     if(uri) IUri_Release(uri);
7540 }
7541
7542 static void test_IUriBuilder_CreateUri(IUriBuilder *builder, const uri_builder_test *test,
7543                                        DWORD test_index) {
7544     HRESULT hr;
7545     IUri *uri = NULL;
7546
7547     hr = IUriBuilder_CreateUri(builder, test->uri_flags, 0, 0, &uri);
7548     if(test->uri_todo) {
7549         todo_wine {
7550             ok(hr == test->uri_hres,
7551                 "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7552                 hr, test->uri_hres, test_index);
7553         }
7554     } else {
7555         ok(hr == test->uri_hres,
7556             "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7557             hr, test->uri_hres, test_index);
7558     }
7559
7560     if(SUCCEEDED(hr)) {
7561         DWORD i;
7562
7563         for(i = 0; i < sizeof(test->expected_str_props)/sizeof(test->expected_str_props[0]); ++i) {
7564             uri_builder_str_property prop = test->expected_str_props[i];
7565             BSTR received = NULL;
7566
7567             hr = IUri_GetPropertyBSTR(uri, i, &received, 0);
7568             if(prop.todo) {
7569                 todo_wine {
7570                     ok(hr == prop.result,
7571                         "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_str_props[%d].\n",
7572                         hr, prop.result, test_index, i);
7573                 }
7574             } else {
7575                 ok(hr == prop.result,
7576                     "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_str_props[%d].\n",
7577                     hr, prop.result, test_index, i);
7578             }
7579             if(SUCCEEDED(hr)) {
7580                 if(prop.todo) {
7581                     todo_wine {
7582                         ok(!strcmp_aw(prop.expected, received),
7583                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].expected_str_props[%d].\n",
7584                             prop.expected, wine_dbgstr_w(received), test_index, i);
7585                     }
7586                 } else {
7587                     ok(!strcmp_aw(prop.expected, received),
7588                         "Error: Expected %s but got %s instead on uri_builder_tests[%d].expected_str_props[%d].\n",
7589                         prop.expected, wine_dbgstr_w(received), test_index, i);
7590                 }
7591             }
7592             SysFreeString(received);
7593         }
7594
7595         for(i = 0; i < sizeof(test->expected_dword_props)/sizeof(test->expected_dword_props[0]); ++i) {
7596             uri_builder_dword_property prop = test->expected_dword_props[i];
7597             DWORD received = -2;
7598
7599             hr = IUri_GetPropertyDWORD(uri, i+Uri_PROPERTY_DWORD_START, &received, 0);
7600             if(prop.todo) {
7601                 todo_wine {
7602                     ok(hr == prop.result,
7603                         "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_dword_props[%d].\n",
7604                         hr, prop.result, test_index, i);
7605                 }
7606             } else {
7607                 ok(hr == prop.result,
7608                     "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_dword_props[%d].\n",
7609                     hr, prop.result, test_index, i);
7610             }
7611             if(SUCCEEDED(hr)) {
7612                 if(prop.todo) {
7613                     todo_wine {
7614                         ok(received == prop.expected,
7615                             "Error: Expected %d but got %d instead on uri_builder_tests[%d].expected_dword_props[%d].\n",
7616                             prop.expected, received, test_index, i);
7617                     }
7618                 } else {
7619                     ok(received == prop.expected,
7620                         "Error: Expected %d but got %d instead on uri_builder_tests[%d].expected_dword_props[%d].\n",
7621                         prop.expected, received, test_index, i);
7622                 }
7623             }
7624         }
7625     }
7626     if(uri) IUri_Release(uri);
7627 }
7628
7629 static void test_IUriBuilder_CreateUriSimple(IUriBuilder *builder, const uri_builder_test *test,
7630                                        DWORD test_index) {
7631     HRESULT hr;
7632     IUri *uri = NULL;
7633
7634     hr = IUriBuilder_CreateUriSimple(builder, test->uri_simple_encode_flags, 0, &uri);
7635     if(test->uri_simple_todo) {
7636         todo_wine {
7637             ok(hr == test->uri_simple_hres,
7638                 "Error: IUriBuilder_CreateUriSimple returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7639                 hr, test->uri_simple_hres, test_index);
7640         }
7641     } else {
7642         ok(hr == test->uri_simple_hres,
7643             "Error: IUriBuilder_CreateUriSimple returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7644             hr, test->uri_simple_hres, test_index);
7645     }
7646
7647     if(SUCCEEDED(hr)) {
7648         DWORD i;
7649
7650         for(i = 0; i < sizeof(test->expected_str_props)/sizeof(test->expected_str_props[0]); ++i) {
7651             uri_builder_str_property prop = test->expected_str_props[i];
7652             BSTR received = NULL;
7653
7654             hr = IUri_GetPropertyBSTR(uri, i, &received, 0);
7655             if(prop.todo) {
7656                 todo_wine {
7657                     ok(hr == prop.result,
7658                         "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_str_props[%d].\n",
7659                         hr, prop.result, test_index, i);
7660                 }
7661             } else {
7662                 ok(hr == prop.result,
7663                     "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_str_props[%d].\n",
7664                     hr, prop.result, test_index, i);
7665             }
7666             if(SUCCEEDED(hr)) {
7667                 if(prop.todo) {
7668                     todo_wine {
7669                         ok(!strcmp_aw(prop.expected, received),
7670                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].expected_str_props[%d].\n",
7671                             prop.expected, wine_dbgstr_w(received), test_index, i);
7672                     }
7673                 } else {
7674                     ok(!strcmp_aw(prop.expected, received),
7675                         "Error: Expected %s but got %s instead on uri_builder_tests[%d].expected_str_props[%d].\n",
7676                         prop.expected, wine_dbgstr_w(received), test_index, i);
7677                 }
7678             }
7679             SysFreeString(received);
7680         }
7681
7682         for(i = 0; i < sizeof(test->expected_dword_props)/sizeof(test->expected_dword_props[0]); ++i) {
7683             uri_builder_dword_property prop = test->expected_dword_props[i];
7684             DWORD received = -2;
7685
7686             hr = IUri_GetPropertyDWORD(uri, i+Uri_PROPERTY_DWORD_START, &received, 0);
7687             if(prop.todo) {
7688                 todo_wine {
7689                     ok(hr == prop.result,
7690                         "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_dword_props[%d].\n",
7691                         hr, prop.result, test_index, i);
7692                 }
7693             } else {
7694                 ok(hr == prop.result,
7695                     "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_dword_props[%d].\n",
7696                     hr, prop.result, test_index, i);
7697             }
7698             if(SUCCEEDED(hr)) {
7699                 if(prop.todo) {
7700                     todo_wine {
7701                         ok(received == prop.expected,
7702                             "Error: Expected %d but got %d instead on uri_builder_tests[%d].expected_dword_props[%d].\n",
7703                             prop.expected, received, test_index, i);
7704                     }
7705                 } else {
7706                     ok(received == prop.expected,
7707                         "Error: Expected %d but got %d instead on uri_builder_tests[%d].expected_dword_props[%d].\n",
7708                         prop.expected, received, test_index, i);
7709                 }
7710             }
7711         }
7712     }
7713     if(uri) IUri_Release(uri);
7714 }
7715
7716 static void test_IUriBuilder_CreateUriWithFlags(IUriBuilder *builder, const uri_builder_test *test,
7717                                                 DWORD test_index) {
7718     HRESULT hr;
7719     IUri *uri = NULL;
7720
7721     hr = IUriBuilder_CreateUriWithFlags(builder, test->uri_with_flags, test->uri_with_builder_flags,
7722                                         test->uri_with_encode_flags, 0, &uri);
7723     if(test->uri_with_todo) {
7724         todo_wine {
7725             ok(hr == test->uri_with_hres,
7726                 "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7727                 hr, test->uri_with_hres, test_index);
7728         }
7729     } else {
7730         ok(hr == test->uri_with_hres,
7731             "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7732             hr, test->uri_with_hres, test_index);
7733     }
7734
7735     if(SUCCEEDED(hr)) {
7736         DWORD i;
7737
7738         for(i = 0; i < sizeof(test->expected_str_props)/sizeof(test->expected_str_props[0]); ++i) {
7739             uri_builder_str_property prop = test->expected_str_props[i];
7740             BSTR received = NULL;
7741
7742             hr = IUri_GetPropertyBSTR(uri, i, &received, 0);
7743             if(prop.todo) {
7744                 todo_wine {
7745                     ok(hr == prop.result,
7746                         "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_str_props[%d].\n",
7747                         hr, prop.result, test_index, i);
7748                 }
7749             } else {
7750                 ok(hr == prop.result,
7751                     "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_str_props[%d].\n",
7752                     hr, prop.result, test_index, i);
7753             }
7754             if(SUCCEEDED(hr)) {
7755                 if(prop.todo) {
7756                     todo_wine {
7757                         ok(!strcmp_aw(prop.expected, received),
7758                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].expected_str_props[%d].\n",
7759                             prop.expected, wine_dbgstr_w(received), test_index, i);
7760                     }
7761                 } else {
7762                     ok(!strcmp_aw(prop.expected, received),
7763                         "Error: Expected %s but got %s instead on uri_builder_tests[%d].expected_str_props[%d].\n",
7764                         prop.expected, wine_dbgstr_w(received), test_index, i);
7765                 }
7766             }
7767             SysFreeString(received);
7768         }
7769
7770         for(i = 0; i < sizeof(test->expected_dword_props)/sizeof(test->expected_dword_props[0]); ++i) {
7771             uri_builder_dword_property prop = test->expected_dword_props[i];
7772             DWORD received = -2;
7773
7774             hr = IUri_GetPropertyDWORD(uri, i+Uri_PROPERTY_DWORD_START, &received, 0);
7775             if(prop.todo) {
7776                 todo_wine {
7777                     ok(hr == prop.result,
7778                         "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_dword_props[%d].\n",
7779                         hr, prop.result, test_index, i);
7780                 }
7781             } else {
7782                 ok(hr == prop.result,
7783                     "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_dword_props[%d].\n",
7784                     hr, prop.result, test_index, i);
7785             }
7786             if(SUCCEEDED(hr)) {
7787                 if(prop.todo) {
7788                     todo_wine {
7789                         ok(received == prop.expected,
7790                             "Error: Expected %d but got %d instead on uri_builder_tests[%d].expected_dword_props[%d].\n",
7791                             prop.expected, received, test_index, i);
7792                     }
7793                 } else {
7794                     ok(received == prop.expected,
7795                         "Error: Expected %d but got %d instead on uri_builder_tests[%d].expected_dword_props[%d].\n",
7796                         prop.expected, received, test_index, i);
7797                 }
7798             }
7799         }
7800     }
7801     if(uri) IUri_Release(uri);
7802 }
7803
7804 static void test_IUriBuilder_CreateInvalidArgs(void) {
7805     IUriBuilder *builder;
7806     HRESULT hr;
7807
7808     hr = pCreateIUriBuilder(NULL, 0, 0, &builder);
7809     ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7810     if(SUCCEEDED(hr)) {
7811         IUri *test = NULL, *uri = (void*) 0xdeadbeef;
7812
7813         /* Test what happens if the IUriBuilder doesn't have a IUri set. */
7814         hr = IUriBuilder_CreateUri(builder, 0, 0, 0, NULL);
7815         ok(hr == E_POINTER, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
7816
7817         uri = (void*) 0xdeadbeef;
7818         hr = IUriBuilder_CreateUri(builder, 0, Uri_HAS_USER_NAME, 0, &uri);
7819         ok(hr == E_NOTIMPL, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, E_NOTIMPL);
7820         ok(uri == NULL, "Error: expected uri to be NULL, but was %p instead.\n", uri);
7821
7822         hr = IUriBuilder_CreateUriSimple(builder, 0, 0, NULL);
7823         ok(hr == E_POINTER, "Error: IUriBuilder_CreateUriSimple returned 0x%08x, expected 0x%08x.\n",
7824             hr, E_POINTER);
7825
7826         uri = (void*) 0xdeadbeef;
7827         hr = IUriBuilder_CreateUriSimple(builder, Uri_HAS_USER_NAME, 0, &uri);
7828         ok(hr == E_NOTIMPL, "Error: IUriBuilder_CreateUriSimple returned 0x%08x, expected 0x%08x.\n",
7829             hr, E_NOTIMPL);
7830         ok(!uri, "Error: Expected uri to NULL, but was %p instead.\n", uri);
7831
7832         hr = IUriBuilder_CreateUriWithFlags(builder, 0, 0, 0, 0, NULL);
7833         ok(hr == E_POINTER, "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x.\n",
7834             hr, E_POINTER);
7835
7836         uri = (void*) 0xdeadbeef;
7837         hr = IUriBuilder_CreateUriWithFlags(builder, 0, 0, Uri_HAS_USER_NAME, 0, &uri);
7838         ok(hr == E_NOTIMPL, "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x.\n",
7839             hr, E_NOTIMPL);
7840         ok(!uri, "Error: Expected uri to be NULL, but was %p instead.\n", uri);
7841
7842         hr = pCreateUri(http_urlW, 0, 0, &test);
7843         ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7844         if(SUCCEEDED(hr)) {
7845             hr = IUriBuilder_SetIUri(builder, test);
7846             ok(hr == S_OK, "Error: IUriBuilder_SetIUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7847
7848             /* No longer returns E_NOTIMPL, since a IUri has been set and hasn't been modified. */
7849             uri = NULL;
7850             hr = IUriBuilder_CreateUri(builder, 0, Uri_HAS_USER_NAME, 0, &uri);
7851             ok(hr == S_OK, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7852             ok(uri != NULL, "Error: The uri was NULL.\n");
7853             if(uri) IUri_Release(uri);
7854
7855             uri = NULL;
7856             hr = IUriBuilder_CreateUriSimple(builder, Uri_HAS_USER_NAME, 0, &uri);
7857             ok(hr == S_OK, "Error: IUriBuilder_CreateUriSimple returned 0x%08x, expected 0x%08x.\n",
7858                 hr, S_OK);
7859             ok(uri != NULL, "Error: uri was NULL.\n");
7860             if(uri) IUri_Release(uri);
7861
7862             uri = NULL;
7863             hr = IUriBuilder_CreateUriWithFlags(builder, 0, 0, 0, 0, &uri);
7864             ok(hr == S_OK, "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x.\n",
7865                 hr, S_OK);
7866             ok(uri != NULL, "Error: uri was NULL.\n");
7867             if(uri) IUri_Release(uri);
7868
7869             hr = IUriBuilder_SetFragment(builder, NULL);
7870             ok(hr == S_OK, "Error: IUriBuilder_SetFragment returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7871
7872             /* The IUriBuilder is changed, so it returns E_NOTIMPL again. */
7873             uri = (void*) 0xdeadbeef;
7874             hr = IUriBuilder_CreateUri(builder, 0, Uri_HAS_USER_NAME, 0, &uri);
7875             ok(hr == E_NOTIMPL, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7876             ok(!uri, "Error: Expected uri to be NULL but was %p instead.\n", uri);
7877
7878             uri = (void*) 0xdeadbeef;
7879             hr = IUriBuilder_CreateUriSimple(builder, Uri_HAS_USER_NAME, 0, &uri);
7880             ok(hr == E_NOTIMPL, "Error: IUriBuilder_CreateUriSimple returned 0x%08x, expected 0x%08x.\n",
7881                 hr, S_OK);
7882             ok(!uri, "Error: Expected uri to be NULL, but was %p instead.\n", uri);
7883
7884             uri = (void*) 0xdeadbeef;
7885             hr = IUriBuilder_CreateUriWithFlags(builder, 0, 0, Uri_HAS_USER_NAME, 0, &uri);
7886             ok(hr == E_NOTIMPL, "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x.\n",
7887                 hr, E_NOTIMPL);
7888             ok(!uri, "Error: Expected uri to be NULL, but was %p instead.\n", uri);
7889         }
7890         if(test) IUri_Release(test);
7891     }
7892     if(builder) IUriBuilder_Release(builder);
7893 }
7894
7895 /* Tests invalid args to the "Get*" functions. */
7896 static void test_IUriBuilder_GetInvalidArgs(void) {
7897     IUriBuilder *builder = NULL;
7898     HRESULT hr;
7899
7900     hr = pCreateIUriBuilder(NULL, 0, 0, &builder);
7901     ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7902     if(SUCCEEDED(hr)) {
7903         LPCWSTR received = (void*) 0xdeadbeef;
7904         DWORD len = -1, port = -1;
7905         BOOL set = -1;
7906
7907         hr = IUriBuilder_GetFragment(builder, NULL, NULL);
7908         ok(hr == E_POINTER, "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x.\n",
7909             hr, E_POINTER);
7910         hr = IUriBuilder_GetFragment(builder, NULL, &received);
7911         ok(hr == E_POINTER, "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x.\n",
7912             hr, E_POINTER);
7913         ok(!received, "Error: Expected received to be NULL, but was %p instead.\n", received);
7914         hr = IUriBuilder_GetFragment(builder, &len, NULL);
7915         ok(hr == E_POINTER, "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x.\n",
7916             hr, E_POINTER);
7917         ok(!len, "Error: Expected len to be 0, but was %d instead.\n", len);
7918
7919         hr = IUriBuilder_GetHost(builder, NULL, NULL);
7920         ok(hr == E_POINTER, "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x.\n",
7921             hr, E_POINTER);
7922         received = (void*) 0xdeadbeef;
7923         hr = IUriBuilder_GetHost(builder, NULL, &received);
7924         ok(hr == E_POINTER, "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x.\n",
7925             hr, E_POINTER);
7926         ok(!received, "Error: Expected received to be NULL, but was %p instead.\n", received);
7927         len = -1;
7928         hr = IUriBuilder_GetHost(builder, &len, NULL);
7929         ok(hr == E_POINTER, "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x.\n",
7930             hr, E_POINTER);
7931         ok(!len, "Error: Expected len to be 0, but was %d instead.\n", len);
7932
7933         hr = IUriBuilder_GetPassword(builder, NULL, NULL);
7934         ok(hr == E_POINTER, "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x.\n",
7935             hr, E_POINTER);
7936         received = (void*) 0xdeadbeef;
7937         hr = IUriBuilder_GetPassword(builder, NULL, &received);
7938         ok(hr == E_POINTER, "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x.\n",
7939             hr, E_POINTER);
7940         ok(!received, "Error: Expected received to be NULL, but was %p instead.\n", received);
7941         len = -1;
7942         hr = IUriBuilder_GetPassword(builder, &len, NULL);
7943         ok(hr == E_POINTER, "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x.\n",
7944             hr, E_POINTER);
7945         ok(!len, "Error: Expected len to be 0, but was %d instead.\n", len);
7946
7947         hr = IUriBuilder_GetPath(builder, NULL, NULL);
7948         ok(hr == E_POINTER, "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x.\n",
7949             hr, E_POINTER);
7950         received = (void*) 0xdeadbeef;
7951         hr = IUriBuilder_GetPath(builder, NULL, &received);
7952         ok(hr == E_POINTER, "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x.\n",
7953             hr, E_POINTER);
7954         ok(!received, "Error: Expected received to be NULL, but was %p instead.\n", received);
7955         len = -1;
7956         hr = IUriBuilder_GetPath(builder, &len, NULL);
7957         ok(hr == E_POINTER, "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x.\n",
7958             hr, E_POINTER);
7959         ok(!len, "Error: Expected len to be 0, but was %d instead.\n", len);
7960
7961         hr = IUriBuilder_GetPort(builder, NULL, NULL);
7962         ok(hr == E_POINTER, "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x.\n",
7963             hr, E_POINTER);
7964         hr = IUriBuilder_GetPort(builder, NULL, &port);
7965         ok(hr == E_POINTER, "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x.\n",
7966             hr, E_POINTER);
7967         ok(!port, "Error: Expected port to be 0, but was %d instead.\n", port);
7968         hr = IUriBuilder_GetPort(builder, &set, NULL);
7969         ok(hr == E_POINTER, "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x.\n",
7970             hr, E_POINTER);
7971         ok(!set, "Error: Expected set to be FALSE, but was %d instead.\n", set);
7972
7973         hr = IUriBuilder_GetQuery(builder, NULL, NULL);
7974         ok(hr == E_POINTER, "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x.\n",
7975             hr, E_POINTER);
7976         received = (void*) 0xdeadbeef;
7977         hr = IUriBuilder_GetQuery(builder, NULL, &received);
7978         ok(hr == E_POINTER, "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x.\n",
7979             hr, E_POINTER);
7980         ok(!received, "Error: Expected received to be NULL, but was %p instead.\n", received);
7981         len = -1;
7982         hr = IUriBuilder_GetQuery(builder, &len, NULL);
7983         ok(hr == E_POINTER, "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x.\n",
7984             hr, E_POINTER);
7985         ok(!len, "Error: Expected len to be 0, but was %d instead.\n", len);
7986
7987         hr = IUriBuilder_GetSchemeName(builder, NULL, NULL);
7988         ok(hr == E_POINTER, "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x.\n",
7989             hr, E_POINTER);
7990         received = (void*) 0xdeadbeef;
7991         hr = IUriBuilder_GetSchemeName(builder, NULL, &received);
7992         ok(hr == E_POINTER, "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x.\n",
7993             hr, E_POINTER);
7994         ok(!received, "Error: Expected received to be NULL, but was %p instead.\n", received);
7995         len = -1;
7996         hr = IUriBuilder_GetSchemeName(builder, &len, NULL);
7997         ok(hr == E_POINTER, "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x.\n",
7998             hr, E_POINTER);
7999         ok(!len, "Error: Expected len to be 0, but was %d instead.\n", len);
8000
8001         hr = IUriBuilder_GetUserName(builder, NULL, NULL);
8002         ok(hr == E_POINTER, "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x.\n",
8003             hr, E_POINTER);
8004         received = (void*) 0xdeadbeef;
8005         hr = IUriBuilder_GetUserName(builder, NULL, &received);
8006         ok(hr == E_POINTER, "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x.\n",
8007             hr, E_POINTER);
8008         ok(!received, "Error: Expected received to be NULL, but was %p instead.\n", received);
8009         len = -1;
8010         hr = IUriBuilder_GetUserName(builder, &len, NULL);
8011         ok(hr == E_POINTER, "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x.\n",
8012             hr, E_POINTER);
8013         ok(!len, "Error: Expected len to be 0, but was %d instead.\n", len);
8014     }
8015     if(builder) IUriBuilder_Release(builder);
8016 }
8017
8018 static void test_IUriBuilder_GetFragment(IUriBuilder *builder, const uri_builder_test *test,
8019                                          DWORD test_index) {
8020     HRESULT hr;
8021     DWORD i;
8022     LPCWSTR received = NULL;
8023     DWORD len = -1;
8024     const uri_builder_property *prop = NULL;
8025
8026     /* Check if the property was set earlier. */
8027     for(i = 0; i < sizeof(test->properties)/sizeof(test->properties[0]); ++i) {
8028         if(test->properties[i].change && test->properties[i].property == Uri_PROPERTY_FRAGMENT)
8029             prop = &(test->properties[i]);
8030     }
8031
8032     if(prop) {
8033         /* Use expected_value unless it's NULL, then use value. */
8034         LPCSTR expected = prop->expected_value ? prop->expected_value : prop->value;
8035         hr = IUriBuilder_GetFragment(builder, &len, &received);
8036         if(prop->todo) {
8037             todo_wine {
8038                 ok(hr == (expected ? S_OK : S_FALSE),
8039                     "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8040                     hr, (expected ? S_OK : S_FALSE), test_index);
8041             }
8042             if(SUCCEEDED(hr)) {
8043                 todo_wine {
8044                     ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
8045                         expected, wine_dbgstr_w(received), test_index);
8046                 }
8047                 todo_wine {
8048                     ok(lstrlen(expected) == len,
8049                         "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8050                         lstrlen(expected), len, test_index);
8051                 }
8052             }
8053         } else {
8054             ok(hr == (expected ? S_OK : S_FALSE),
8055                 "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8056                 hr, (expected ? S_OK : S_FALSE), test_index);
8057             ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
8058                 expected, wine_dbgstr_w(received), test_index);
8059             ok(lstrlen(expected) == len,
8060                 "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8061                 lstrlen(expected), len, test_index);
8062         }
8063     } else {
8064         /* The property wasn't set earlier, so it should return whatever
8065          * the base IUri contains (if anything).
8066          */
8067         IUri *uri = NULL;
8068         hr = IUriBuilder_GetIUri(builder, &uri);
8069         ok(hr == S_OK,
8070             "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8071             hr, S_OK, test_index);
8072         if(SUCCEEDED(hr)) {
8073             if(!uri) {
8074                 received = (void*) 0xdeadbeef;
8075                 len = -1;
8076
8077                 hr = IUriBuilder_GetFragment(builder, &len, &received);
8078                 ok(hr == S_FALSE,
8079                     "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8080                     hr, S_FALSE, test_index);
8081                 if(SUCCEEDED(hr)) {
8082                     ok(!len, "Error: Expected len to be 0, but was %d instead on uri_builder_tests[%d].\n",
8083                         len, test_index);
8084                     ok(!received, "Error: Expected received to be NULL, but was %p instead on uri_builder_tests[%d].\n",
8085                         received, test_index);
8086                 }
8087             } else {
8088                 BOOL has_prop = FALSE;
8089                 BSTR expected = NULL;
8090
8091                 hr = IUri_GetFragment(uri, &expected);
8092                 ok(SUCCEEDED(hr),
8093                     "Error: Expected IUri_GetFragment to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
8094                     hr, test_index);
8095                 has_prop = hr == S_OK;
8096
8097                 hr = IUriBuilder_GetFragment(builder, &len, &received);
8098                 if(has_prop) {
8099                     ok(hr == S_OK,
8100                         "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8101                         hr, S_OK, test_index);
8102                     if(SUCCEEDED(hr)) {
8103                         ok(!lstrcmpW(expected, received),
8104                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].\n",
8105                             wine_dbgstr_w(expected), wine_dbgstr_w(received), test_index);
8106                         ok(lstrlenW(expected) == len,
8107                             "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8108                             lstrlenW(expected), len, test_index);
8109                     }
8110                 } else {
8111                     ok(hr == S_FALSE,
8112                         "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8113                         hr, S_FALSE, test_index);
8114                     if(SUCCEEDED(hr)) {
8115                         ok(!received, "Error: Expected received to be NULL on uri_builder_tests[%d].\n", test_index);
8116                         ok(!len, "Error: Expected the length to be 0, but was %d instead on uri_builder_tests[%d].\n",
8117                             len, test_index);
8118                     }
8119                 }
8120                 SysFreeString(expected);
8121             }
8122         }
8123         if(uri) IUri_Release(uri);
8124     }
8125 }
8126
8127 static void test_IUriBuilder_GetHost(IUriBuilder *builder, const uri_builder_test *test,
8128                                      DWORD test_index) {
8129     HRESULT hr;
8130     DWORD i;
8131     LPCWSTR received = NULL;
8132     DWORD len = -1;
8133     const uri_builder_property *prop = NULL;
8134
8135     /* Check if the property was set earlier. */
8136     for(i = 0; i < sizeof(test->properties)/sizeof(test->properties[0]); ++i) {
8137         if(test->properties[i].change && test->properties[i].property == Uri_PROPERTY_HOST)
8138             prop = &(test->properties[i]);
8139     }
8140
8141     if(prop) {
8142         /* Use expected_value unless it's NULL, then use value. */
8143         LPCSTR expected = prop->expected_value ? prop->expected_value : prop->value;
8144         hr = IUriBuilder_GetHost(builder, &len, &received);
8145         if(prop->todo) {
8146             todo_wine {
8147                 ok(hr == (expected ? S_OK : S_FALSE),
8148                     "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8149                     hr, (expected ? S_OK : S_FALSE), test_index);
8150             }
8151             if(SUCCEEDED(hr)) {
8152                 todo_wine {
8153                     ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
8154                         expected, wine_dbgstr_w(received), test_index);
8155                 }
8156                 todo_wine {
8157                     ok(lstrlen(expected) == len,
8158                         "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8159                         lstrlen(expected), len, test_index);
8160                 }
8161             }
8162         } else {
8163             ok(hr == (expected ? S_OK : S_FALSE),
8164                 "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8165                 hr, (expected ? S_OK : S_FALSE), test_index);
8166             ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
8167                 expected, wine_dbgstr_w(received), test_index);
8168             ok(lstrlen(expected) == len,
8169                 "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8170                 lstrlen(expected), len, test_index);
8171         }
8172     } else {
8173         /* The property wasn't set earlier, so it should return whatever
8174          * the base IUri contains (if anything).
8175          */
8176         IUri *uri = NULL;
8177         hr = IUriBuilder_GetIUri(builder, &uri);
8178         ok(hr == S_OK,
8179             "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8180             hr, S_OK, test_index);
8181         if(SUCCEEDED(hr)) {
8182             if(!uri) {
8183                 received = (void*) 0xdeadbeef;
8184                 len = -1;
8185
8186                 hr = IUriBuilder_GetHost(builder, &len, &received);
8187                 ok(hr == S_FALSE,
8188                     "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8189                     hr, S_FALSE, test_index);
8190                 if(SUCCEEDED(hr)) {
8191                     ok(!len, "Error: Expected len to be 0, but was %d instead on uri_builder_tests[%d].\n",
8192                         len, test_index);
8193                     ok(!received, "Error: Expected received to be NULL, but was %p instead on uri_builder_tests[%d].\n",
8194                         received, test_index);
8195                 }
8196             } else {
8197                 BOOL has_prop = FALSE;
8198                 BSTR expected = NULL;
8199
8200                 hr = IUri_GetHost(uri, &expected);
8201                 ok(SUCCEEDED(hr),
8202                     "Error: Expected IUri_GetHost to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
8203                     hr, test_index);
8204                 has_prop = hr == S_OK;
8205
8206                 hr = IUriBuilder_GetHost(builder, &len, &received);
8207                 if(has_prop) {
8208                     ok(hr == S_OK,
8209                         "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8210                         hr, S_OK, test_index);
8211                     if(SUCCEEDED(hr)) {
8212                         ok(!lstrcmpW(expected, received),
8213                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].\n",
8214                             wine_dbgstr_w(expected), wine_dbgstr_w(received), test_index);
8215                         ok(lstrlenW(expected) == len,
8216                             "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8217                             lstrlenW(expected), len, test_index);
8218                     }
8219                 } else {
8220                     ok(hr == S_FALSE,
8221                         "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8222                         hr, S_FALSE, test_index);
8223                     if(SUCCEEDED(hr)) {
8224                         ok(!received, "Error: Expected received to be NULL on uri_builder_tests[%d].\n", test_index);
8225                         ok(!len, "Error: Expected the length to be 0, but was %d instead on uri_builder_tests[%d].\n",
8226                             len, test_index);
8227                     }
8228                 }
8229                 SysFreeString(expected);
8230             }
8231         }
8232         if(uri) IUri_Release(uri);
8233     }
8234 }
8235
8236 static void test_IUriBuilder_GetPassword(IUriBuilder *builder, const uri_builder_test *test,
8237                                          DWORD test_index) {
8238     HRESULT hr;
8239     DWORD i;
8240     LPCWSTR received = NULL;
8241     DWORD len = -1;
8242     const uri_builder_property *prop = NULL;
8243
8244     /* Check if the property was set earlier. */
8245     for(i = 0; i < sizeof(test->properties)/sizeof(test->properties[0]); ++i) {
8246         if(test->properties[i].change && test->properties[i].property == Uri_PROPERTY_PASSWORD)
8247             prop = &(test->properties[i]);
8248     }
8249
8250     if(prop) {
8251         /* Use expected_value unless it's NULL, then use value. */
8252         LPCSTR expected = prop->expected_value ? prop->expected_value : prop->value;
8253         hr = IUriBuilder_GetPassword(builder, &len, &received);
8254         if(prop->todo) {
8255             todo_wine {
8256                 ok(hr == (expected ? S_OK : S_FALSE),
8257                     "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8258                     hr, (expected ? S_OK : S_FALSE), test_index);
8259             }
8260             if(SUCCEEDED(hr)) {
8261                 todo_wine {
8262                     ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
8263                         expected, wine_dbgstr_w(received), test_index);
8264                 }
8265                 todo_wine {
8266                     ok(lstrlen(expected) == len,
8267                         "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8268                         lstrlen(expected), len, test_index);
8269                 }
8270             }
8271         } else {
8272             ok(hr == (expected ? S_OK : S_FALSE),
8273                 "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8274                 hr, (expected ? S_OK : S_FALSE), test_index);
8275             ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
8276                 expected, wine_dbgstr_w(received), test_index);
8277             ok(lstrlen(expected) == len,
8278                 "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8279                 lstrlen(expected), len, test_index);
8280         }
8281     } else {
8282         /* The property wasn't set earlier, so it should return whatever
8283          * the base IUri contains (if anything).
8284          */
8285         IUri *uri = NULL;
8286         hr = IUriBuilder_GetIUri(builder, &uri);
8287         ok(hr == S_OK,
8288             "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8289             hr, S_OK, test_index);
8290         if(SUCCEEDED(hr)) {
8291             if(!uri) {
8292                 received = (void*) 0xdeadbeef;
8293                 len = -1;
8294
8295                 hr = IUriBuilder_GetPassword(builder, &len, &received);
8296                 ok(hr == S_FALSE,
8297                     "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8298                     hr, S_FALSE, test_index);
8299                 if(SUCCEEDED(hr)) {
8300                     ok(!len, "Error: Expected len to be 0, but was %d instead on uri_builder_tests[%d].\n",
8301                         len, test_index);
8302                     ok(!received, "Error: Expected received to be NULL, but was %p instead on uri_builder_tests[%d].\n",
8303                         received, test_index);
8304                 }
8305             } else {
8306                 BOOL has_prop = FALSE;
8307                 BSTR expected = NULL;
8308
8309                 hr = IUri_GetPassword(uri, &expected);
8310                 ok(SUCCEEDED(hr),
8311                     "Error: Expected IUri_GetPassword to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
8312                     hr, test_index);
8313                 has_prop = hr == S_OK;
8314
8315                 hr = IUriBuilder_GetPassword(builder, &len, &received);
8316                 if(has_prop) {
8317                     ok(hr == S_OK,
8318                         "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8319                         hr, S_OK, test_index);
8320                     if(SUCCEEDED(hr)) {
8321                         ok(!lstrcmpW(expected, received),
8322                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].\n",
8323                             wine_dbgstr_w(expected), wine_dbgstr_w(received), test_index);
8324                         ok(lstrlenW(expected) == len,
8325                             "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8326                             lstrlenW(expected), len, test_index);
8327                     }
8328                 } else {
8329                     ok(hr == S_FALSE,
8330                         "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8331                         hr, S_FALSE, test_index);
8332                     if(SUCCEEDED(hr)) {
8333                         ok(!received, "Error: Expected received to be NULL on uri_builder_tests[%d].\n", test_index);
8334                         ok(!len, "Error: Expected the length to be 0, but was %d instead on uri_builder_tests[%d].\n",
8335                             len, test_index);
8336                     }
8337                 }
8338                 SysFreeString(expected);
8339             }
8340         }
8341         if(uri) IUri_Release(uri);
8342     }
8343 }
8344
8345 static void test_IUriBuilder_GetPath(IUriBuilder *builder, const uri_builder_test *test,
8346                                      DWORD test_index) {
8347     HRESULT hr;
8348     DWORD i;
8349     LPCWSTR received = NULL;
8350     DWORD len = -1;
8351     const uri_builder_property *prop = NULL;
8352
8353     /* Check if the property was set earlier. */
8354     for(i = 0; i < sizeof(test->properties)/sizeof(test->properties[0]); ++i) {
8355         if(test->properties[i].change && test->properties[i].property == Uri_PROPERTY_PATH)
8356             prop = &(test->properties[i]);
8357     }
8358
8359     if(prop) {
8360         /* Use expected_value unless it's NULL, then use value. */
8361         LPCSTR expected = prop->expected_value ? prop->expected_value : prop->value;
8362         hr = IUriBuilder_GetPath(builder, &len, &received);
8363         if(prop->todo) {
8364             todo_wine {
8365                 ok(hr == (expected ? S_OK : S_FALSE),
8366                     "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8367                     hr, (expected ? S_OK : S_FALSE), test_index);
8368             }
8369             if(SUCCEEDED(hr)) {
8370                 todo_wine {
8371                     ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
8372                         expected, wine_dbgstr_w(received), test_index);
8373                 }
8374                 todo_wine {
8375                     ok(lstrlen(expected) == len,
8376                         "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8377                         lstrlen(expected), len, test_index);
8378                 }
8379             }
8380         } else {
8381             ok(hr == (expected ? S_OK : S_FALSE),
8382                 "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8383                 hr, (expected ? S_OK : S_FALSE), test_index);
8384             ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
8385                 expected, wine_dbgstr_w(received), test_index);
8386             ok(lstrlen(expected) == len,
8387                 "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8388                 lstrlen(expected), len, test_index);
8389         }
8390     } else {
8391         /* The property wasn't set earlier, so it should return whatever
8392          * the base IUri contains (if anything).
8393          */
8394         IUri *uri = NULL;
8395         hr = IUriBuilder_GetIUri(builder, &uri);
8396         ok(hr == S_OK,
8397             "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8398             hr, S_OK, test_index);
8399         if(SUCCEEDED(hr)) {
8400             if(!uri) {
8401                 received = (void*) 0xdeadbeef;
8402                 len = -1;
8403
8404                 hr = IUriBuilder_GetPath(builder, &len, &received);
8405                 ok(hr == S_FALSE,
8406                     "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8407                     hr, S_FALSE, test_index);
8408                 if(SUCCEEDED(hr)) {
8409                     ok(!len, "Error: Expected len to be 0, but was %d instead on uri_builder_tests[%d].\n",
8410                         len, test_index);
8411                     ok(!received, "Error: Expected received to be NULL, but was %p instead on uri_builder_tests[%d].\n",
8412                         received, test_index);
8413                 }
8414             } else {
8415                 BOOL has_prop = FALSE;
8416                 BSTR expected = NULL;
8417
8418                 hr = IUri_GetPath(uri, &expected);
8419                 ok(SUCCEEDED(hr),
8420                     "Error: Expected IUri_GetPath to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
8421                     hr, test_index);
8422                 has_prop = hr == S_OK;
8423
8424                 hr = IUriBuilder_GetPath(builder, &len, &received);
8425                 if(has_prop) {
8426                     ok(hr == S_OK,
8427                         "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8428                         hr, S_OK, test_index);
8429                     if(SUCCEEDED(hr)) {
8430                         ok(!lstrcmpW(expected, received),
8431                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].\n",
8432                             wine_dbgstr_w(expected), wine_dbgstr_w(received), test_index);
8433                         ok(lstrlenW(expected) == len,
8434                             "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8435                             lstrlenW(expected), len, test_index);
8436                     }
8437                 } else {
8438                     ok(hr == S_FALSE,
8439                         "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8440                         hr, S_FALSE, test_index);
8441                     if(SUCCEEDED(hr)) {
8442                         ok(!received, "Error: Expected received to be NULL on uri_builder_tests[%d].\n", test_index);
8443                         ok(!len, "Error: Expected the length to be 0, but was %d instead on uri_builder_tests[%d].\n",
8444                             len, test_index);
8445                     }
8446                 }
8447                 SysFreeString(expected);
8448             }
8449         }
8450         if(uri) IUri_Release(uri);
8451     }
8452 }
8453
8454 static void test_IUriBuilder_GetPort(IUriBuilder *builder, const uri_builder_test *test,
8455                                      DWORD test_index) {
8456     HRESULT hr;
8457     BOOL has_port = FALSE;
8458     DWORD received = -1;
8459
8460     if(test->port_prop.change) {
8461         DWORD expected = test->port_prop.value;
8462
8463         hr = IUriBuilder_GetPort(builder, &has_port, &received);
8464         if(test->port_prop.todo) {
8465             todo_wine {
8466                 ok(hr == S_OK,
8467                     "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8468                     hr, S_OK, test_index);
8469             }
8470             if(SUCCEEDED(hr)) {
8471                 todo_wine {
8472                     ok(has_port == test->port_prop.set,
8473                         "Error: Expected has_port to be %d but was %d instead on uri_builder_tests[%d].\n",
8474                         test->port_prop.set, has_port, test_index);
8475                 }
8476                 todo_wine {
8477                     ok(received == expected,
8478                         "Error: Expected received to be %d, but was %d instead on uri_builder_tests[%d].\n",
8479                         expected, received, test_index);
8480                 }
8481             }
8482         } else {
8483             ok(hr == S_OK,
8484                 "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8485                 hr, S_OK, test_index);
8486             ok(has_port == test->port_prop.set,
8487                 "Error: Expected has_port to be %d, but was %d instead on uri_builder_tests[%d].\n",
8488                 test->port_prop.set, has_port, test_index);
8489             ok(received == test->port_prop.value,
8490                 "Error: Expected port to be %d, but was %d instead on uri_builder_tests[%d].\n",
8491                 test->port_prop.value, received, test_index);
8492         }
8493     } else {
8494         IUri *uri = NULL;
8495
8496         hr = IUriBuilder_GetIUri(builder, &uri);
8497         ok(hr == S_OK,
8498             "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8499             hr, S_OK, test_index);
8500         if(SUCCEEDED(hr)) {
8501             if(!uri) {
8502                 hr = IUriBuilder_GetPort(builder, &has_port, &received);
8503                 ok(hr == S_OK,
8504                     "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8505                     hr, S_OK, test_index);
8506                 if(SUCCEEDED(hr)) {
8507                     ok(has_port == FALSE,
8508                         "Error: Expected has_port to be FALSE, but was %d instead on uri_builder_tests[%d].\n",
8509                         has_port, test_index);
8510                     ok(!received, "Error: Expected received to be 0, but was %d instead on uri_builder_tests[%d].\n",
8511                         received, test_index);
8512                 }
8513             } else {
8514                 DWORD expected;
8515
8516                 hr = IUri_GetPort(uri, &expected);
8517                 ok(SUCCEEDED(hr),
8518                     "Error: Expected IUri_Port to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
8519                     hr, test_index);
8520
8521                 hr = IUriBuilder_GetPort(builder, &has_port, &received);
8522                 ok(hr == S_OK,
8523                     "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8524                     hr, S_OK, test_index);
8525                 if(SUCCEEDED(hr)) {
8526                     ok(!has_port,
8527                         "Error: Expected has_port to be FALSE but was TRUE instead on uri_builder_tests[%d].\n",
8528                         test_index);
8529                     ok(received == expected,
8530                         "Error: Expected received to be %d, but was %d instead on uri_builder_tests[%d].\n",
8531                         expected, received, test_index);
8532                 }
8533             }
8534         }
8535         if(uri) IUri_Release(uri);
8536     }
8537 }
8538
8539 static void test_IUriBuilder_GetQuery(IUriBuilder *builder, const uri_builder_test *test,
8540                                       DWORD test_index) {
8541     HRESULT hr;
8542     DWORD i;
8543     LPCWSTR received = NULL;
8544     DWORD len = -1;
8545     const uri_builder_property *prop = NULL;
8546
8547     /* Check if the property was set earlier. */
8548     for(i = 0; i < sizeof(test->properties)/sizeof(test->properties[0]); ++i) {
8549         if(test->properties[i].change && test->properties[i].property == Uri_PROPERTY_QUERY)
8550             prop = &(test->properties[i]);
8551     }
8552
8553     if(prop) {
8554         /* Use expected_value unless it's NULL, then use value. */
8555         LPCSTR expected = prop->expected_value ? prop->expected_value : prop->value;
8556         hr = IUriBuilder_GetQuery(builder, &len, &received);
8557         if(prop->todo) {
8558             todo_wine {
8559                 ok(hr == (expected ? S_OK : S_FALSE),
8560                     "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8561                     hr, (expected ? S_OK : S_FALSE), test_index);
8562             }
8563             if(SUCCEEDED(hr)) {
8564                 todo_wine {
8565                     ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
8566                         expected, wine_dbgstr_w(received), test_index);
8567                 }
8568                 todo_wine {
8569                     ok(lstrlen(expected) == len,
8570                         "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8571                         lstrlen(expected), len, test_index);
8572                 }
8573             }
8574         } else {
8575             ok(hr == (expected ? S_OK : S_FALSE),
8576                 "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8577                 hr, (expected ? S_OK : S_FALSE), test_index);
8578             ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
8579                 expected, wine_dbgstr_w(received), test_index);
8580             ok(lstrlen(expected) == len,
8581                 "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8582                 lstrlen(expected), len, test_index);
8583         }
8584     } else {
8585         /* The property wasn't set earlier, so it should return whatever
8586          * the base IUri contains (if anything).
8587          */
8588         IUri *uri = NULL;
8589         hr = IUriBuilder_GetIUri(builder, &uri);
8590         ok(hr == S_OK,
8591             "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8592             hr, S_OK, test_index);
8593         if(SUCCEEDED(hr)) {
8594             if(!uri) {
8595                 received = (void*) 0xdeadbeef;
8596                 len = -1;
8597
8598                 hr = IUriBuilder_GetQuery(builder, &len, &received);
8599                 ok(hr == S_FALSE,
8600                     "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8601                     hr, S_FALSE, test_index);
8602                 if(SUCCEEDED(hr)) {
8603                     ok(!len, "Error: Expected len to be 0, but was %d instead on uri_builder_tests[%d].\n",
8604                         len, test_index);
8605                     ok(!received, "Error: Expected received to be NULL, but was %p instead on uri_builder_tests[%d].\n",
8606                         received, test_index);
8607                 }
8608             } else {
8609                 BOOL has_prop = FALSE;
8610                 BSTR expected = NULL;
8611
8612                 hr = IUri_GetQuery(uri, &expected);
8613                 ok(SUCCEEDED(hr),
8614                     "Error: Expected IUri_GetQuery to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
8615                     hr, test_index);
8616                 has_prop = hr == S_OK;
8617
8618                 hr = IUriBuilder_GetQuery(builder, &len, &received);
8619                 if(has_prop) {
8620                     ok(hr == S_OK,
8621                         "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8622                         hr, S_OK, test_index);
8623                     if(SUCCEEDED(hr)) {
8624                         ok(!lstrcmpW(expected, received),
8625                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].\n",
8626                             wine_dbgstr_w(expected), wine_dbgstr_w(received), test_index);
8627                         ok(lstrlenW(expected) == len,
8628                             "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8629                             lstrlenW(expected), len, test_index);
8630                     }
8631                 } else {
8632                     ok(hr == S_FALSE,
8633                         "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8634                         hr, S_FALSE, test_index);
8635                     if(SUCCEEDED(hr)) {
8636                         ok(!received, "Error: Expected received to be NULL on uri_builder_tests[%d].\n", test_index);
8637                         ok(!len, "Error: Expected the length to be 0, but was %d instead on uri_builder_tests[%d].\n",
8638                             len, test_index);
8639                     }
8640                 }
8641                 SysFreeString(expected);
8642             }
8643         }
8644         if(uri) IUri_Release(uri);
8645     }
8646 }
8647
8648 static void test_IUriBuilder_GetSchemeName(IUriBuilder *builder, const uri_builder_test *test,
8649                                            DWORD test_index) {
8650     HRESULT hr;
8651     DWORD i;
8652     LPCWSTR received = NULL;
8653     DWORD len = -1;
8654     const uri_builder_property *prop = NULL;
8655
8656     /* Check if the property was set earlier. */
8657     for(i = 0; i < sizeof(test->properties)/sizeof(test->properties[0]); ++i) {
8658         if(test->properties[i].change && test->properties[i].property == Uri_PROPERTY_SCHEME_NAME)
8659             prop = &(test->properties[i]);
8660     }
8661
8662     if(prop) {
8663         /* Use expected_value unless it's NULL, then use value. */
8664         LPCSTR expected = prop->expected_value ? prop->expected_value : prop->value;
8665         hr = IUriBuilder_GetSchemeName(builder, &len, &received);
8666         if(prop->todo) {
8667             todo_wine {
8668                 ok(hr == (expected ? S_OK : S_FALSE),
8669                     "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8670                     hr, (expected ? S_OK : S_FALSE), test_index);
8671             }
8672             if(SUCCEEDED(hr)) {
8673                 todo_wine {
8674                     ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
8675                         expected, wine_dbgstr_w(received), test_index);
8676                 }
8677                 todo_wine {
8678                     ok(lstrlen(expected) == len,
8679                         "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8680                         lstrlen(expected), len, test_index);
8681                 }
8682             }
8683         } else {
8684             ok(hr == (expected ? S_OK : S_FALSE),
8685                 "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8686                 hr, (expected ? S_OK : S_FALSE), test_index);
8687             ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
8688                 expected, wine_dbgstr_w(received), test_index);
8689             ok(lstrlen(expected) == len,
8690                 "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8691                 lstrlen(expected), len, test_index);
8692         }
8693     } else {
8694         /* The property wasn't set earlier, so it should return whatever
8695          * the base IUri contains (if anything).
8696          */
8697         IUri *uri = NULL;
8698         hr = IUriBuilder_GetIUri(builder, &uri);
8699         ok(hr == S_OK,
8700             "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8701             hr, S_OK, test_index);
8702         if(SUCCEEDED(hr)) {
8703             if(!uri) {
8704                 received = (void*) 0xdeadbeef;
8705                 len = -1;
8706
8707                 hr = IUriBuilder_GetSchemeName(builder, &len, &received);
8708                 ok(hr == S_FALSE,
8709                     "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8710                     hr, S_FALSE, test_index);
8711                 if(SUCCEEDED(hr)) {
8712                     ok(!len, "Error: Expected len to be 0, but was %d instead on uri_builder_tests[%d].\n",
8713                         len, test_index);
8714                     ok(!received, "Error: Expected received to be NULL, but was %p instead on uri_builder_tests[%d].\n",
8715                         received, test_index);
8716                 }
8717             } else {
8718                 BOOL has_prop = FALSE;
8719                 BSTR expected = NULL;
8720
8721                 hr = IUri_GetSchemeName(uri, &expected);
8722                 ok(SUCCEEDED(hr),
8723                     "Error: Expected IUri_GetSchemeName to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
8724                     hr, test_index);
8725                 has_prop = hr == S_OK;
8726
8727                 hr = IUriBuilder_GetSchemeName(builder, &len, &received);
8728                 if(has_prop) {
8729                     ok(hr == S_OK,
8730                         "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8731                         hr, S_OK, test_index);
8732                     if(SUCCEEDED(hr)) {
8733                         ok(!lstrcmpW(expected, received),
8734                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].\n",
8735                             wine_dbgstr_w(expected), wine_dbgstr_w(received), test_index);
8736                         ok(lstrlenW(expected) == len,
8737                             "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8738                             lstrlenW(expected), len, test_index);
8739                     }
8740                 } else {
8741                     ok(hr == S_FALSE,
8742                         "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8743                         hr, S_FALSE, test_index);
8744                     if(SUCCEEDED(hr)) {
8745                         ok(!received, "Error: Expected received to be NULL on uri_builder_tests[%d].\n", test_index);
8746                         ok(!len, "Error: Expected the length to be 0, but was %d instead on uri_builder_tests[%d].\n",
8747                             len, test_index);
8748                     }
8749                 }
8750                 SysFreeString(expected);
8751             }
8752         }
8753         if(uri) IUri_Release(uri);
8754     }
8755 }
8756
8757 static void test_IUriBuilder_GetUserName(IUriBuilder *builder, const uri_builder_test *test,
8758                                          DWORD test_index) {
8759     HRESULT hr;
8760     DWORD i;
8761     LPCWSTR received = NULL;
8762     DWORD len = -1;
8763     const uri_builder_property *prop = NULL;
8764
8765     /* Check if the property was set earlier. */
8766     for(i = 0; i < sizeof(test->properties)/sizeof(test->properties[0]); ++i) {
8767         if(test->properties[i].change && test->properties[i].property == Uri_PROPERTY_USER_NAME)
8768             prop = &(test->properties[i]);
8769     }
8770
8771     if(prop && prop->value && *prop->value) {
8772         /* Use expected_value unless it's NULL, then use value. */
8773         LPCSTR expected = prop->expected_value ? prop->expected_value : prop->value;
8774         hr = IUriBuilder_GetUserName(builder, &len, &received);
8775         if(prop->todo) {
8776             todo_wine {
8777                 ok(hr == (expected ? S_OK : S_FALSE),
8778                     "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8779                     hr, (expected ? S_OK : S_FALSE), test_index);
8780             }
8781             if(SUCCEEDED(hr)) {
8782                 todo_wine {
8783                     ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
8784                         expected, wine_dbgstr_w(received), test_index);
8785                 }
8786                 todo_wine {
8787                     ok(lstrlen(expected) == len,
8788                         "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8789                         lstrlen(expected), len, test_index);
8790                 }
8791             }
8792         } else {
8793             ok(hr == (expected ? S_OK : S_FALSE),
8794                 "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8795                 hr, (expected ? S_OK : S_FALSE), test_index);
8796             ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
8797                 expected, wine_dbgstr_w(received), test_index);
8798             ok(lstrlen(expected) == len,
8799                 "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8800                 lstrlen(expected), len, test_index);
8801         }
8802     } else {
8803         /* The property wasn't set earlier, so it should return whatever
8804          * the base IUri contains (if anything).
8805          */
8806         IUri *uri = NULL;
8807         hr = IUriBuilder_GetIUri(builder, &uri);
8808         ok(hr == S_OK,
8809             "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8810             hr, S_OK, test_index);
8811         if(SUCCEEDED(hr)) {
8812             if(!uri) {
8813                 received = (void*) 0xdeadbeef;
8814                 len = -1;
8815
8816                 hr = IUriBuilder_GetUserName(builder, &len, &received);
8817                 ok(hr == S_FALSE,
8818                     "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8819                     hr, S_FALSE, test_index);
8820                 if(SUCCEEDED(hr)) {
8821                     ok(!len, "Error: Expected len to be 0, but was %d instead on uri_builder_tests[%d].\n",
8822                         len, test_index);
8823                     ok(!received, "Error: Expected received to be NULL, but was %p instead on uri_builder_tests[%d].\n",
8824                         received, test_index);
8825                 }
8826             } else {
8827                 BSTR expected = NULL;
8828                 BOOL has_prop = FALSE;
8829
8830                 hr = IUri_GetUserName(uri, &expected);
8831                 ok(SUCCEEDED(hr),
8832                     "Error: Expected IUri_GetUserName to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
8833                     hr, test_index);
8834                 has_prop = hr == S_OK;
8835
8836                 hr = IUriBuilder_GetUserName(builder, &len, &received);
8837                 if(has_prop) {
8838                     ok(hr == S_OK,
8839                         "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8840                         hr, S_OK, test_index);
8841                     if(SUCCEEDED(hr)) {
8842                         ok(!lstrcmpW(expected, received),
8843                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].\n",
8844                             wine_dbgstr_w(expected), wine_dbgstr_w(received), test_index);
8845                         ok(lstrlenW(expected) == len,
8846                             "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8847                             lstrlenW(expected), len, test_index);
8848                     }
8849                 } else {
8850                     ok(hr == S_FALSE,
8851                         "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8852                         hr, S_FALSE, test_index);
8853                     if(SUCCEEDED(hr)) {
8854                         ok(!received, "Error: Expected received to be NULL on uri_builder_tests[%d].\n", test_index);
8855                         ok(!len, "Error: Expected the length to be 0, but was %d instead on uri_builder_tests[%d].\n",
8856                             len, test_index);
8857                     }
8858                 }
8859                 SysFreeString(expected);
8860             }
8861         }
8862         if(uri) IUri_Release(uri);
8863     }
8864 }
8865
8866 /* Tests IUriBuilder functions. */
8867 static void test_IUriBuilder(void) {
8868     HRESULT hr;
8869     IUriBuilder *builder;
8870     DWORD i;
8871
8872     for(i = 0; i < sizeof(uri_builder_tests)/sizeof(uri_builder_tests[0]); ++i) {
8873         IUri *uri = NULL;
8874         uri_builder_test test = uri_builder_tests[i];
8875         LPWSTR uriW = NULL;
8876
8877         if(test.uri) {
8878             uriW = a2w(test.uri);
8879             hr = pCreateUri(uriW, test.create_flags, 0, &uri);
8880             ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8881                 hr, S_OK, i);
8882             if(FAILED(hr)) continue;
8883         }
8884         hr = pCreateIUriBuilder(uri, 0, 0, &builder);
8885         if(test.create_builder_todo) {
8886             todo_wine {
8887                 ok(hr == test.create_builder_expected,
8888                     "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8889                     hr, test.create_builder_expected, i);
8890             }
8891         } else {
8892             ok(hr == test.create_builder_expected,
8893                 "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8894                 hr, test.create_builder_expected, i);
8895         }
8896         if(SUCCEEDED(hr)) {
8897             DWORD j;
8898             BOOL modified = FALSE, received = FALSE;
8899
8900             /* Perform all the string property changes. */
8901             for(j = 0; j < URI_BUILDER_STR_PROPERTY_COUNT; ++j) {
8902                 uri_builder_property prop = test.properties[j];
8903                 if(prop.change) {
8904                     change_property(builder, &prop, i);
8905                     if(prop.property != Uri_PROPERTY_SCHEME_NAME &&
8906                        prop.property != Uri_PROPERTY_HOST)
8907                         modified = TRUE;
8908                     else if(prop.value && *prop.value)
8909                         modified = TRUE;
8910                     else if(prop.value && !*prop.value && prop.property == Uri_PROPERTY_HOST)
8911                         /* Host name property can't be NULL, but it can be empty. */
8912                         modified = TRUE;
8913                 }
8914             }
8915
8916             if(test.port_prop.change) {
8917                 hr = IUriBuilder_SetPort(builder, test.port_prop.set, test.port_prop.value);
8918                 modified = TRUE;
8919                 if(test.port_prop.todo) {
8920                     todo_wine {
8921                         ok(hr == test.port_prop.expected,
8922                             "Error: IUriBuilder_SetPort returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8923                             hr, test.port_prop.expected, i);
8924                     }
8925                 } else {
8926                     ok(hr == test.port_prop.expected,
8927                         "Error: IUriBuilder_SetPort returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8928                         hr, test.port_prop.expected, i);
8929                 }
8930             }
8931
8932             hr = IUriBuilder_HasBeenModified(builder, &received);
8933             ok(hr == S_OK,
8934                 "Error IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8935                 hr, S_OK, i);
8936             if(SUCCEEDED(hr))
8937                 ok(received == modified,
8938                     "Error: Expected received to be %d but was %d instead on uri_builder_tests[%d].\n",
8939                     modified, received, i);
8940
8941             /* Test the "Get*" functions. */
8942             test_IUriBuilder_GetFragment(builder, &test, i);
8943             test_IUriBuilder_GetHost(builder, &test, i);
8944             test_IUriBuilder_GetPassword(builder, &test, i);
8945             test_IUriBuilder_GetPath(builder, &test, i);
8946             test_IUriBuilder_GetPort(builder, &test, i);
8947             test_IUriBuilder_GetQuery(builder, &test, i);
8948             test_IUriBuilder_GetSchemeName(builder, &test, i);
8949             test_IUriBuilder_GetUserName(builder, &test, i);
8950
8951             test_IUriBuilder_CreateUri(builder, &test, i);
8952             test_IUriBuilder_CreateUriSimple(builder, &test, i);
8953             test_IUriBuilder_CreateUriWithFlags(builder, &test, i);
8954         }
8955         if(builder) IUriBuilder_Release(builder);
8956         if(uri) IUri_Release(uri);
8957         heap_free(uriW);
8958     }
8959 }
8960
8961 static void test_IUriBuilder_HasBeenModified(void) {
8962     HRESULT hr;
8963     IUriBuilder *builder = NULL;
8964
8965     hr = pCreateIUriBuilder(NULL, 0, 0, &builder);
8966     ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8967     if(SUCCEEDED(hr)) {
8968         static const WCHAR hostW[] = {'g','o','o','g','l','e','.','c','o','m',0};
8969         IUri *uri = NULL;
8970         BOOL received;
8971
8972         hr = IUriBuilder_HasBeenModified(builder, NULL);
8973         ok(hr == E_POINTER, "Error: IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x.\n",
8974             hr, E_POINTER);
8975
8976         hr = IUriBuilder_SetHost(builder, hostW);
8977         ok(hr == S_OK, "Error: IUriBuilder_SetHost returned 0x%08x, expected 0x%08x.\n",
8978             hr, S_OK);
8979
8980         hr = IUriBuilder_HasBeenModified(builder, &received);
8981         ok(hr == S_OK, "Error: IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x.\n",
8982             hr, S_OK);
8983         if(SUCCEEDED(hr))
8984             ok(received == TRUE, "Error: Expected received to be TRUE.\n");
8985
8986         hr = pCreateUri(http_urlW, 0, 0, &uri);
8987         ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8988         if(SUCCEEDED(hr)) {
8989             LPCWSTR prop;
8990             DWORD len = -1;
8991
8992             hr = IUriBuilder_SetIUri(builder, uri);
8993             ok(hr == S_OK, "Error: IUriBuilder_SetIUri returned 0x%08x, expected 0x%08x.\n",
8994                 hr, S_OK);
8995
8996             hr = IUriBuilder_HasBeenModified(builder, &received);
8997             ok(hr == S_OK, "Error: IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x.\n",
8998                 hr, S_OK);
8999             if(SUCCEEDED(hr))
9000                 ok(received == FALSE, "Error: Expected received to be FALSE.\n");
9001
9002             /* Test what happens with you call SetIUri with the same IUri again. */
9003             hr = IUriBuilder_SetHost(builder, hostW);
9004             ok(hr == S_OK, "Error: IUriBuilder_SetHost returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9005
9006             hr = IUriBuilder_HasBeenModified(builder, &received);
9007             ok(hr == S_OK, "Error: IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x.\n",
9008                 hr, S_OK);
9009             if(SUCCEEDED(hr))
9010                 ok(received == TRUE, "Error: Expected received to be TRUE.\n");
9011
9012             hr = IUriBuilder_SetIUri(builder, uri);
9013             ok(hr == S_OK, "Error: IUriBuilder_SetIUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9014
9015             /* IUriBuilder already had 'uri' as it's IUri property and so Windows doesn't
9016              * reset any of the changes that were made to the IUriBuilder.
9017              */
9018             hr = IUriBuilder_HasBeenModified(builder, &received);
9019             ok(hr == S_OK, "Error: IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9020             if(SUCCEEDED(hr))
9021                 ok(received == TRUE, "Error: Expected received to be TRUE.\n");
9022
9023             hr = IUriBuilder_GetHost(builder, &len, &prop);
9024             ok(hr == S_OK, "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9025             if(SUCCEEDED(hr)) {
9026                 ok(!lstrcmpW(prop, hostW), "Error: Expected %s but got %s instead.\n",
9027                     wine_dbgstr_w(hostW), wine_dbgstr_w(prop));
9028                 ok(len == lstrlenW(hostW), "Error: Expected len to be %d, but was %d instead.\n",
9029                     lstrlenW(hostW), len);
9030             }
9031
9032             hr = IUriBuilder_SetIUri(builder, NULL);
9033             ok(hr == S_OK, "Error: IUriBuilder_SetIUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9034
9035             hr = IUriBuilder_SetHost(builder, hostW);
9036             ok(hr == S_OK, "Error: IUriBuilder_SetHost returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9037             hr = IUriBuilder_HasBeenModified(builder, &received);
9038             ok(hr == S_OK, "Error: IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x.\n",
9039                 hr, S_OK);
9040             if(SUCCEEDED(hr))
9041                 ok(received == TRUE, "Error: Expected received to be TRUE.\n");
9042
9043             hr = IUriBuilder_SetIUri(builder, NULL);
9044             ok(hr == S_OK, "Error: IUriBuilder_SetIUri returned 0x%08x, expected 0x%09x.\n", hr, S_OK);
9045
9046             hr = IUriBuilder_HasBeenModified(builder, &received);
9047             ok(hr == S_OK, "Error: IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x.\n",
9048                 hr, S_OK);
9049             if(SUCCEEDED(hr))
9050                 ok(received == TRUE, "Error: Expected received to be TRUE.\n");
9051
9052             hr = IUriBuilder_GetHost(builder, &len, &prop);
9053             ok(hr == S_OK, "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9054             if(SUCCEEDED(hr)) {
9055                 ok(!lstrcmpW(prop, hostW), "Error: Expected %s but got %s instead.\n",
9056                     wine_dbgstr_w(hostW), wine_dbgstr_w(prop));
9057                 ok(len == lstrlenW(hostW), "Error: Expected len to %d, but was %d instead.\n",
9058                     lstrlenW(hostW), len);
9059             }
9060         }
9061         if(uri) IUri_Release(uri);
9062     }
9063     if(builder) IUriBuilder_Release(builder);
9064 }
9065
9066 /* Test IUriBuilder {Get,Set}IUri functions. */
9067 static void test_IUriBuilder_IUriProperty(void) {
9068     IUriBuilder *builder = NULL;
9069     HRESULT hr;
9070
9071     hr = pCreateIUriBuilder(NULL, 0, 0, &builder);
9072     ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9073     if(SUCCEEDED(hr)) {
9074         IUri *uri = NULL;
9075
9076         hr = IUriBuilder_GetIUri(builder, NULL);
9077         ok(hr == E_POINTER, "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x.\n",
9078             hr, E_POINTER);
9079
9080         hr = pCreateUri(http_urlW, 0, 0, &uri);
9081         if(SUCCEEDED(hr)) {
9082             IUri *test = NULL;
9083             ULONG cur_count, orig_count;
9084
9085             /* IUriBuilder doesn't clone the IUri, it use the same IUri. */
9086             orig_count = get_refcnt(uri);
9087             hr = IUriBuilder_SetIUri(builder, uri);
9088             cur_count = get_refcnt(uri);
9089             if(SUCCEEDED(hr))
9090                 ok(cur_count == orig_count+1, "Error: Expected uri ref count to be %d, but was %d instead.\n",
9091                     orig_count+1, cur_count);
9092
9093             hr = IUriBuilder_SetIUri(builder, NULL);
9094             cur_count = get_refcnt(uri);
9095             if(SUCCEEDED(hr))
9096                 ok(cur_count == orig_count, "Error: Expected uri ref count to be %d, but was %d instead.\n",
9097                     orig_count, cur_count);
9098
9099             /* CreateUri* functions will return back the same IUri if nothing has changed. */
9100             hr = IUriBuilder_SetIUri(builder, uri);
9101             ok(hr == S_OK, "Error: IUriBuilder_SetIUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9102             orig_count = get_refcnt(uri);
9103
9104             hr = IUriBuilder_CreateUri(builder, 0, 0, 0, &test);
9105             ok(hr == S_OK, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9106             if(SUCCEEDED(hr)) {
9107                 cur_count = get_refcnt(uri);
9108                 ok(cur_count == orig_count+1, "Error: Expected uri ref count to be %d, but was %d instead.\n",
9109                     orig_count+1, cur_count);
9110                 ok(test == uri, "Error: Expected test to be %p, but was %p instead.\n",
9111                     uri, test);
9112             }
9113             if(test) IUri_Release(test);
9114
9115             test = NULL;
9116             hr = IUriBuilder_CreateUri(builder, -1, 0, 0, &test);
9117             ok(hr == S_OK, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9118             if(SUCCEEDED(hr)) {
9119                 cur_count = get_refcnt(uri);
9120                 ok(cur_count == orig_count+1, "Error: Expected uri ref count to be %d, but was %d instead.\n",
9121                     orig_count+1, cur_count);
9122                 ok(test == uri, "Error: Expected test to be %p, but was %p instead.\n", uri, test);
9123             }
9124             if(test) IUri_Release(test);
9125
9126             /* Doesn't return the same IUri, if the flag combination is different then the one that created
9127              * the base IUri.
9128              */
9129             test = NULL;
9130             hr = IUriBuilder_CreateUri(builder, Uri_CREATE_ALLOW_RELATIVE, 0, 0, &test);
9131             ok(hr == S_OK, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9132             if(SUCCEEDED(hr))
9133                 ok(test != uri, "Error: Wasn't expecting 'test' to be 'uri'\n");
9134
9135             if(test) IUri_Release(test);
9136
9137             /* Still returns the same IUri, even though the base one wasn't created with CREATE_CANONICALIZE
9138              * explicitly set (because it's a default flags).
9139              */
9140             test = NULL;
9141             hr = IUriBuilder_CreateUri(builder, Uri_CREATE_CANONICALIZE, 0, 0, &test);
9142             ok(hr == S_OK, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9143             if(SUCCEEDED(hr)) {
9144                 cur_count = get_refcnt(uri);
9145                 ok(cur_count == orig_count+1, "Error: Expected uri ref count to be %d, but was %d instead.\n",
9146                     orig_count+1, cur_count);
9147                 ok(test == uri, "Error: Expected 'test' to be %p, but was %p instead.\n", uri, test);
9148             }
9149             if(test) IUri_Release(test);
9150
9151             test = NULL;
9152             hr = IUriBuilder_CreateUriSimple(builder, 0, 0, &test);
9153             ok(hr == S_OK, "Error: IUriBuilder_CreateUriSimple returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9154             if(SUCCEEDED(hr)) {
9155                 cur_count = get_refcnt(uri);
9156                 ok(cur_count == orig_count+1, "Error: Expected uri ref count to be %d, but was %d instead.\n",
9157                     orig_count+1, cur_count);
9158                 ok(test == uri, "Error: Expected test to be %p, but was %p instead.\n", uri, test);
9159             }
9160             if(test) IUri_Release(test);
9161
9162             test = NULL;
9163             hr = IUriBuilder_CreateUriWithFlags(builder, 0, 0, 0, 0, &test);
9164             ok(hr == S_OK, "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x.\n",
9165                 hr, S_OK);
9166             if(SUCCEEDED(hr)) {
9167                 cur_count = get_refcnt(uri);
9168                 ok(cur_count == orig_count+1, "Error: Expected uri ref count to be %d, but was %d instead.\n",
9169                     orig_count+1, cur_count);
9170                 ok(test == uri, "Error: Expected test to be %p, but was %p instead.\n", uri, test);
9171             }
9172             if(test) IUri_Release(test);
9173
9174             /* Doesn't return the same IUri, if the flag combination is different then the one that created
9175              * the base IUri.
9176              */
9177             test = NULL;
9178             hr = IUriBuilder_CreateUriWithFlags(builder, Uri_CREATE_ALLOW_RELATIVE, 0, 0, 0, &test);
9179             ok(hr == S_OK, "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9180             if(SUCCEEDED(hr))
9181                 ok(test != uri, "Error: Wasn't expecting 'test' to be 'uri'\n");
9182
9183             if(test) IUri_Release(test);
9184
9185             /* Still returns the same IUri, even though the base one wasn't created with CREATE_CANONICALIZE
9186              * explicitly set (because it's a default flags).
9187              */
9188             test = NULL;
9189             hr = IUriBuilder_CreateUriWithFlags(builder, Uri_CREATE_CANONICALIZE, 0, 0, 0, &test);
9190             ok(hr == S_OK, "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9191             if(SUCCEEDED(hr)) {
9192                 cur_count = get_refcnt(uri);
9193                 ok(cur_count == orig_count+1, "Error: Expected uri ref count to be %d, but was %d instead.\n",
9194                     orig_count+1, cur_count);
9195                 ok(test == uri, "Error: Expected 'test' to be %p, but was %p instead.\n", uri, test);
9196             }
9197             if(test) IUri_Release(test);
9198         }
9199         if(uri) IUri_Release(uri);
9200     }
9201     if(builder) IUriBuilder_Release(builder);
9202 }
9203
9204 static void test_IUriBuilder_RemoveProperties(void) {
9205     IUriBuilder *builder = NULL;
9206     HRESULT hr;
9207     DWORD i;
9208
9209     hr = pCreateIUriBuilder(NULL, 0, 0, &builder);
9210     ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9211     if(SUCCEEDED(hr)) {
9212         /* Properties that can't be removed. */
9213         const DWORD invalid = Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_RAW_URI|Uri_HAS_HOST_TYPE|
9214                               Uri_HAS_SCHEME|Uri_HAS_ZONE;
9215
9216         for(i = Uri_PROPERTY_STRING_START; i <= Uri_PROPERTY_DWORD_LAST; ++i) {
9217             hr = IUriBuilder_RemoveProperties(builder, i << 1);
9218             if((i << 1) & invalid) {
9219                 ok(hr == E_INVALIDARG,
9220                     "Error: IUriBuilder_RemoveProperties returned 0x%08x, expected 0x%08x with prop=%d.\n",
9221                     hr, E_INVALIDARG, i);
9222             } else {
9223                 ok(hr == S_OK,
9224                     "Error: IUriBuilder_RemoveProperties returned 0x%08x, expected 0x%08x with prop=%d.\n",
9225                     hr, S_OK, i);
9226             }
9227         }
9228
9229         /* Also doesn't accept anything that's outside the range of the
9230          * Uri_HAS flags.
9231          */
9232         hr = IUriBuilder_RemoveProperties(builder, (Uri_PROPERTY_DWORD_LAST+1) << 1);
9233         ok(hr == E_INVALIDARG, "Error: IUriBuilder_RemoveProperties returned 0x%08x, expected 0x%08x.\n",
9234             hr, E_INVALIDARG);
9235     }
9236     if(builder) IUriBuilder_Release(builder);
9237
9238     for(i = 0; i < sizeof(uri_builder_remove_tests)/sizeof(uri_builder_remove_tests[0]); ++i) {
9239         uri_builder_remove_test test = uri_builder_remove_tests[i];
9240         IUri *uri = NULL;
9241         LPWSTR uriW;
9242
9243         uriW = a2w(test.uri);
9244         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
9245         if(SUCCEEDED(hr)) {
9246             builder = NULL;
9247
9248             hr = pCreateIUriBuilder(uri, 0, 0, &builder);
9249             if(test.create_builder_todo) {
9250                 todo_wine {
9251                     ok(hr == test.create_builder_expected,
9252                         "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x on test %d.\n",
9253                         hr, test.create_builder_expected, i);
9254                 }
9255             } else {
9256                 ok(hr == test.create_builder_expected,
9257                     "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x on test %d.\n",
9258                     hr, test.create_builder_expected, i);
9259             }
9260             if(SUCCEEDED(hr)) {
9261                 hr = IUriBuilder_RemoveProperties(builder, test.remove_properties);
9262                 if(test.remove_todo) {
9263                     todo_wine {
9264                         ok(hr == test.remove_expected,
9265                             "Error: IUriBuilder_RemoveProperties returned 0x%08x, expected 0x%08x on test %d.\n",
9266                             hr, test.remove_expected, i);
9267                     }
9268                 } else {
9269                     ok(hr == test.remove_expected,
9270                         "Error: IUriBuilder returned 0x%08x, expected 0x%08x on test %d.\n",
9271                         hr, test.remove_expected, i);
9272                 }
9273                 if(SUCCEEDED(hr)) {
9274                     IUri *result = NULL;
9275
9276                     hr = IUriBuilder_CreateUri(builder, test.expected_flags, 0, 0, &result);
9277                     if(test.expected_todo) {
9278                         todo_wine {
9279                             ok(hr == test.expected_hres,
9280                                 "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x on test %d.\n",
9281                                 hr, test.expected_hres, i);
9282                         }
9283                     } else {
9284                         ok(hr == test.expected_hres,
9285                             "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x on test %d.\n",
9286                             hr, test.expected_hres, i);
9287                     }
9288                     if(SUCCEEDED(hr)) {
9289                         BSTR received = NULL;
9290
9291                         hr = IUri_GetAbsoluteUri(result, &received);
9292                         ok(hr == S_OK, "Error: Expected S_OK, but got 0x%08x instead.\n", hr);
9293                         ok(!strcmp_aw(test.expected_uri, received),
9294                             "Error: Expected %s but got %s instead on test %d.\n",
9295                             test.expected_uri, wine_dbgstr_w(received), i);
9296                         SysFreeString(received);
9297                     }
9298                     if(result) IUri_Release(result);
9299                 }
9300             }
9301             if(builder) IUriBuilder_Release(builder);
9302         }
9303         if(uri) IUri_Release(uri);
9304         heap_free(uriW);
9305     }
9306 }
9307
9308 static void test_IUriBuilder_Misc(void) {
9309     HRESULT hr;
9310     IUri *uri;
9311
9312     hr = pCreateUri(http_urlW, 0, 0, &uri);
9313     if(SUCCEEDED(hr)) {
9314         IUriBuilder *builder;
9315
9316         hr = pCreateIUriBuilder(uri, 0, 0, &builder);
9317         ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9318         if(SUCCEEDED(hr)) {
9319             BOOL has = -1;
9320             DWORD port = -1;
9321
9322             hr = IUriBuilder_GetPort(builder, &has, &port);
9323             ok(hr == S_OK, "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9324             if(SUCCEEDED(hr)) {
9325                 /* 'has' will be set to FALSE, even though uri had a port. */
9326                 ok(has == FALSE, "Error: Expected 'has' to be FALSE, was %d instead.\n", has);
9327                 /* Still sets 'port' to 80. */
9328                 ok(port == 80, "Error: Expected the port to be 80, but, was %d instead.\n", port);
9329             }
9330         }
9331         if(builder) IUriBuilder_Release(builder);
9332     }
9333     if(uri) IUri_Release(uri);
9334 }
9335
9336 static void test_IUriBuilderFactory(void) {
9337     HRESULT hr;
9338     IUri *uri;
9339     IUriBuilderFactory *factory;
9340     IUriBuilder *builder;
9341
9342     hr = pCreateUri(http_urlW, 0, 0, &uri);
9343     ok(SUCCEEDED(hr), "Error: CreateUri returned 0x%08x.\n", hr);
9344     if(SUCCEEDED(hr)) {
9345         factory = NULL;
9346         hr = IUri_QueryInterface(uri, &IID_IUriBuilderFactory, (void**)&factory);
9347         ok(hr == S_OK, "Error: Expected S_OK, but got 0x%08x.\n", hr);
9348         ok(factory != NULL, "Error: Expected 'factory' to not be NULL.\n");
9349
9350         if(SUCCEEDED(hr)) {
9351             builder = (void*) 0xdeadbeef;
9352             hr = IUriBuilderFactory_CreateIUriBuilder(factory, 10, 0, &builder);
9353             ok(hr == E_INVALIDARG, "Error: CreateInitializedIUriBuilder returned 0x%08x, expected 0x%08x.\n",
9354                 hr, E_INVALIDARG);
9355             ok(!builder, "Error: Expected 'builder' to be NULL, but was %p.\n", builder);
9356
9357             builder = (void*) 0xdeadbeef;
9358             hr = IUriBuilderFactory_CreateIUriBuilder(factory, 0, 10, &builder);
9359             ok(hr == E_INVALIDARG, "Error: CreateInitializedIUriBuilder returned 0x%08x, expected 0x%08x.\n",
9360                 hr, E_INVALIDARG);
9361             ok(!builder, "Error: Expected 'builder' to be NULL, but was %p.\n", builder);
9362
9363             hr = IUriBuilderFactory_CreateIUriBuilder(factory, 0, 0, NULL);
9364             ok(hr == E_POINTER, "Error: CreateInitializedIUriBuilder returned 0x%08x, expected 0x%08x.\n",
9365                 hr, E_POINTER);
9366
9367             builder = NULL;
9368             hr = IUriBuilderFactory_CreateIUriBuilder(factory, 0, 0, &builder);
9369             ok(hr == S_OK, "Error: CreateInitializedIUriBuilder returned 0x%08x, expected 0x%08x.\n",
9370                 hr, S_OK);
9371             if(SUCCEEDED(hr)) {
9372                 IUri *tmp = (void*) 0xdeadbeef;
9373                 LPCWSTR result;
9374                 DWORD result_len;
9375
9376                 hr = IUriBuilder_GetIUri(builder, &tmp);
9377                 ok(hr == S_OK, "Error: GetIUri returned 0x%08x, expected 0x%08x.\n",
9378                     hr, S_OK);
9379                 ok(!tmp, "Error: Expected 'tmp' to be NULL, but was %p instead.\n", tmp);
9380
9381                 hr = IUriBuilder_GetHost(builder, &result_len, &result);
9382                 ok(hr == S_FALSE, "Error: GetHost returned 0x%08x, expected 0x%08x.\n",
9383                     hr, S_FALSE);
9384             }
9385             if(builder) IUriBuilder_Release(builder);
9386
9387             builder = (void*) 0xdeadbeef;
9388             hr = IUriBuilderFactory_CreateInitializedIUriBuilder(factory, 10, 0, &builder);
9389             ok(hr == E_INVALIDARG, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n",
9390                 hr, E_INVALIDARG);
9391             ok(!builder, "Error: Expected 'builder' to be NULL, but was %p.\n", builder);
9392
9393             builder = (void*) 0xdeadbeef;
9394             hr = IUriBuilderFactory_CreateInitializedIUriBuilder(factory, 0, 10, &builder);
9395             ok(hr == E_INVALIDARG, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n",
9396                 hr, E_INVALIDARG);
9397             ok(!builder, "Error: Expected 'builder' to be NULL, but was %p.\n", builder);
9398
9399             hr = IUriBuilderFactory_CreateInitializedIUriBuilder(factory, 0, 0, NULL);
9400             ok(hr == E_POINTER, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n",
9401                 hr, E_POINTER);
9402
9403             builder = NULL;
9404             hr = IUriBuilderFactory_CreateInitializedIUriBuilder(factory, 0, 0, &builder);
9405             ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n",
9406                 hr, S_OK);
9407             if(SUCCEEDED(hr)) {
9408                 IUri *tmp = NULL;
9409
9410                 hr = IUriBuilder_GetIUri(builder, &tmp);
9411                 ok(hr == S_OK, "Error: GetIUri return 0x%08x, expected 0x%08x.\n",
9412                     hr, S_OK);
9413                 ok(tmp == uri, "Error: Expected tmp to be %p, but was %p.\n", uri, tmp);
9414                 if(uri) IUri_Release(uri);
9415             }
9416             if(builder) IUriBuilder_Release(builder);
9417         }
9418         if(factory) IUriBuilderFactory_Release(factory);
9419     }
9420     if(uri) IUri_Release(uri);
9421 }
9422
9423 static void test_CoInternetCombineIUri(void) {
9424     HRESULT hr;
9425     IUri *base, *relative, *result;
9426     DWORD i;
9427
9428     base = NULL;
9429     hr = pCreateUri(http_urlW, 0, 0, &base);
9430     ok(SUCCEEDED(hr), "Error: Expected CreateUri to succeed, got 0x%08x.\n", hr);
9431     if(SUCCEEDED(hr)) {
9432         result = (void*) 0xdeadbeef;
9433         hr = pCoInternetCombineIUri(base, NULL, 0, &result, 0);
9434         ok(hr == E_INVALIDARG, "Error: CoInternetCombineIUri returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
9435         ok(!result, "Error: Expected 'result' to be NULL, was %p.\n", result);
9436     }
9437
9438     relative = NULL;
9439     hr = pCreateUri(http_urlW, 0, 0, &relative);
9440     ok(SUCCEEDED(hr), "Error: Expected CreateUri to succeed, got 0x%08x.\n", hr);
9441     if(SUCCEEDED(hr)) {
9442         result = (void*) 0xdeadbeef;
9443         hr = pCoInternetCombineIUri(NULL, relative, 0, &result, 0);
9444         ok(hr == E_INVALIDARG, "Error: CoInternetCombineIUri returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
9445         ok(!result, "Error: Expected 'result' to be NULL, was %p.\n", result);
9446     }
9447
9448     hr = pCoInternetCombineIUri(base, relative, 0, NULL, 0);
9449     ok(hr == E_INVALIDARG, "Error: CoInternetCombineIUri returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
9450
9451     if(base) IUri_Release(base);
9452     if(relative) IUri_Release(relative);
9453
9454     for(i = 0; i < sizeof(uri_combine_tests)/sizeof(uri_combine_tests[0]); ++i) {
9455         LPWSTR baseW = a2w(uri_combine_tests[i].base_uri);
9456
9457         hr = pCreateUri(baseW, uri_combine_tests[i].base_create_flags, 0, &base);
9458         ok(SUCCEEDED(hr), "Error: Expected CreateUri to succeed, got 0x%08x on uri_combine_tests[%d].\n", hr, i);
9459         if(SUCCEEDED(hr)) {
9460             LPWSTR relativeW = a2w(uri_combine_tests[i].relative_uri);
9461
9462             hr = pCreateUri(relativeW, uri_combine_tests[i].relative_create_flags, 0, &relative);
9463             ok(SUCCEEDED(hr), "Error: Expected CreateUri to succeed, got 0x%08x on uri_combine_tests[%d].\n", hr, i);
9464             if(SUCCEEDED(hr)) {
9465                 result = NULL;
9466
9467                 hr = pCoInternetCombineIUri(base, relative, uri_combine_tests[i].combine_flags, &result, 0);
9468                 if(uri_combine_tests[i].todo) {
9469                     todo_wine {
9470                         ok(hr == uri_combine_tests[i].expected,
9471                             "Error: CoInternetCombineIUri returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].\n",
9472                             hr, uri_combine_tests[i].expected, i);
9473                     }
9474                 } else {
9475                     ok(hr == uri_combine_tests[i].expected,
9476                         "Error: CoInternetCombineIUri returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].\n",
9477                         hr, uri_combine_tests[i]. expected, i);
9478                 }
9479                 if(SUCCEEDED(hr)) {
9480                     DWORD j;
9481
9482                     for(j = 0; j < sizeof(uri_combine_tests[i].str_props)/sizeof(uri_combine_tests[i].str_props[0]); ++j) {
9483                         uri_combine_str_property prop = uri_combine_tests[i].str_props[j];
9484                         BSTR received;
9485
9486                         hr = IUri_GetPropertyBSTR(result, j, &received, 0);
9487                         if(prop.todo) {
9488                             todo_wine {
9489                                 ok(hr == prop.expected,
9490                                     "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].str_props[%d].\n",
9491                                     hr, prop.expected, i, j);
9492                             }
9493                             todo_wine {
9494                                 ok(!strcmp_aw(prop.value, received) ||
9495                                    broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
9496                                     "Error: Expected %s but got %s instead on uri_combine_tests[%d].str_props[%d].\n",
9497                                     prop.value, wine_dbgstr_w(received), i, j);
9498                             }
9499                         } else {
9500                             ok(hr == prop.expected,
9501                                 "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].str_props[%d].\n",
9502                                 hr, prop.expected, i, j);
9503                             ok(!strcmp_aw(prop.value, received) ||
9504                                broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
9505                                 "Error: Expected %s but got %s instead on uri_combine_tests[%d].str_props[%d].\n",
9506                                 prop.value, wine_dbgstr_w(received), i, j);
9507                         }
9508                         SysFreeString(received);
9509                     }
9510
9511                     for(j = 0; j < sizeof(uri_combine_tests[i].dword_props)/sizeof(uri_combine_tests[i].dword_props[0]); ++j) {
9512                         uri_dword_property prop = uri_combine_tests[i].dword_props[j];
9513                         DWORD received;
9514
9515                         hr = IUri_GetPropertyDWORD(result, j+Uri_PROPERTY_DWORD_START, &received, 0);
9516                         if(prop.todo) {
9517                             todo_wine {
9518                                 ok(hr == prop.expected,
9519                                     "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].dword_props[%d].\n",
9520                                     hr, prop.expected, i, j);
9521                             }
9522                             todo_wine {
9523                                 ok(prop.value == received, "Error: Expected %d, but got %d instead on uri_combine_tests[%d].dword_props[%d].\n",
9524                                     prop.value, received, i, j);
9525                             }
9526                         } else {
9527                             ok(hr == prop.expected,
9528                                 "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].dword_props[%d].\n",
9529                                 hr, prop.expected, i, j);
9530                             ok(prop.value == received, "Error: Expected %d, but got %d instead on uri_combine_tests[%d].dword_props[%d].\n",
9531                                 prop.value, received, i, j);
9532                         }
9533                     }
9534                 }
9535                 if(result) IUri_Release(result);
9536             }
9537             if(relative) IUri_Release(relative);
9538             heap_free(relativeW);
9539         }
9540         if(base) IUri_Release(base);
9541         heap_free(baseW);
9542     }
9543 }
9544
9545 static HRESULT WINAPI InternetProtocolInfo_QueryInterface(IInternetProtocolInfo *iface,
9546                                                           REFIID riid, void **ppv)
9547 {
9548     ok(0, "unexpected call\n");
9549     return E_NOINTERFACE;
9550 }
9551
9552 static ULONG WINAPI InternetProtocolInfo_AddRef(IInternetProtocolInfo *iface)
9553 {
9554     return 2;
9555 }
9556
9557 static ULONG WINAPI InternetProtocolInfo_Release(IInternetProtocolInfo *iface)
9558 {
9559     return 1;
9560 }
9561
9562 static HRESULT WINAPI InternetProtocolInfo_ParseUrl(IInternetProtocolInfo *iface, LPCWSTR pwzUrl,
9563         PARSEACTION ParseAction, DWORD dwParseFlags, LPWSTR pwzResult, DWORD cchResult,
9564         DWORD *pcchResult, DWORD dwReserved)
9565 {
9566     CHECK_EXPECT(ParseUrl);
9567     ok(!lstrcmpW(pwzUrl, parse_urlW), "Error: Expected %s, but got %s instead.\n",
9568         wine_dbgstr_w(parse_urlW), wine_dbgstr_w(pwzUrl));
9569     ok(ParseAction == parse_action, "Error: Expected %d, but got %d.\n", parse_action, ParseAction);
9570     ok(dwParseFlags == parse_flags, "Error: Expected 0x%08x, but got 0x%08x.\n", parse_flags, dwParseFlags);
9571     ok(cchResult == 200, "Error: Got %d.\n", cchResult);
9572
9573     memcpy(pwzResult, parse_resultW, sizeof(parse_resultW));
9574     *pcchResult = lstrlenW(parse_resultW);
9575
9576     return S_OK;
9577 }
9578
9579 static HRESULT WINAPI InternetProtocolInfo_CombineUrl(IInternetProtocolInfo *iface,
9580         LPCWSTR pwzBaseUrl, LPCWSTR pwzRelativeUrl, DWORD dwCombineFlags,
9581         LPWSTR pwzResult, DWORD cchResult, DWORD *pcchResult, DWORD dwReserved)
9582 {
9583     CHECK_EXPECT(CombineUrl);
9584     ok(!lstrcmpW(pwzBaseUrl, combine_baseW), "Error: Expected %s, but got %s instead.\n",
9585         wine_dbgstr_w(combine_baseW), wine_dbgstr_w(pwzBaseUrl));
9586     ok(!lstrcmpW(pwzRelativeUrl, combine_relativeW), "Error: Expected %s, but got %s instead.\n",
9587         wine_dbgstr_w(combine_relativeW), wine_dbgstr_w(pwzRelativeUrl));
9588     ok(dwCombineFlags == (URL_DONT_SIMPLIFY|URL_FILE_USE_PATHURL|URL_DONT_UNESCAPE_EXTRA_INFO),
9589         "Error: Expected 0, but got 0x%08x.\n", dwCombineFlags);
9590     ok(cchResult == INTERNET_MAX_URL_LENGTH+1, "Error: Got %d.\n", cchResult);
9591
9592     memcpy(pwzResult, combine_resultW, sizeof(combine_resultW));
9593     *pcchResult = lstrlenW(combine_resultW);
9594
9595     return S_OK;
9596 }
9597
9598 static HRESULT WINAPI InternetProtocolInfo_CompareUrl(IInternetProtocolInfo *iface,
9599         LPCWSTR pwzUrl1, LPCWSTR pwzUrl2, DWORD dwCompareFlags)
9600 {
9601     ok(0, "unexpected call\n");
9602     return E_NOTIMPL;
9603 }
9604
9605 static HRESULT WINAPI InternetProtocolInfo_QueryInfo(IInternetProtocolInfo *iface,
9606         LPCWSTR pwzUrl, QUERYOPTION OueryOption, DWORD dwQueryFlags, LPVOID pBuffer,
9607         DWORD cbBuffer, DWORD *pcbBuf, DWORD dwReserved)
9608 {
9609     ok(0, "unexpected call\n");
9610     return E_NOTIMPL;
9611 }
9612
9613 static const IInternetProtocolInfoVtbl InternetProtocolInfoVtbl = {
9614     InternetProtocolInfo_QueryInterface,
9615     InternetProtocolInfo_AddRef,
9616     InternetProtocolInfo_Release,
9617     InternetProtocolInfo_ParseUrl,
9618     InternetProtocolInfo_CombineUrl,
9619     InternetProtocolInfo_CompareUrl,
9620     InternetProtocolInfo_QueryInfo
9621 };
9622
9623 static IInternetProtocolInfo protocol_info = { &InternetProtocolInfoVtbl };
9624
9625 static HRESULT WINAPI ClassFactory_QueryInterface(IClassFactory *iface, REFIID riid, void **ppv)
9626 {
9627     if(IsEqualGUID(&IID_IInternetProtocolInfo, riid)) {
9628         *ppv = &protocol_info;
9629         return S_OK;
9630     }
9631
9632     ok(0, "unexpected call\n");
9633     return E_NOINTERFACE;
9634 }
9635
9636 static ULONG WINAPI ClassFactory_AddRef(IClassFactory *iface)
9637 {
9638     return 2;
9639 }
9640
9641 static ULONG WINAPI ClassFactory_Release(IClassFactory *iface)
9642 {
9643     return 1;
9644 }
9645
9646 static HRESULT WINAPI ClassFactory_CreateInstance(IClassFactory *iface, IUnknown *pOuter,
9647                                         REFIID riid, void **ppv)
9648 {
9649     ok(0, "unexpected call\n");
9650     return E_NOTIMPL;
9651 }
9652
9653 static HRESULT WINAPI ClassFactory_LockServer(IClassFactory *iface, BOOL dolock)
9654 {
9655     ok(0, "unexpected call\n");
9656     return S_OK;
9657 }
9658
9659 static const IClassFactoryVtbl ClassFactoryVtbl = {
9660     ClassFactory_QueryInterface,
9661     ClassFactory_AddRef,
9662     ClassFactory_Release,
9663     ClassFactory_CreateInstance,
9664     ClassFactory_LockServer
9665 };
9666
9667 static IClassFactory protocol_cf = { &ClassFactoryVtbl };
9668
9669 static void register_protocols(void)
9670 {
9671     IInternetSession *session;
9672     HRESULT hres;
9673
9674     hres = pCoInternetGetSession(0, &session, 0);
9675     ok(hres == S_OK, "CoInternetGetSession failed: %08x\n", hres);
9676     if(FAILED(hres))
9677         return;
9678
9679     hres = IInternetSession_RegisterNameSpace(session, &protocol_cf, &IID_NULL,
9680             winetestW, 0, NULL, 0);
9681     ok(hres == S_OK, "RegisterNameSpace failed: %08x\n", hres);
9682
9683     IInternetSession_Release(session);
9684 }
9685
9686 static void unregister_protocols(void) {
9687     IInternetSession *session;
9688     HRESULT hr;
9689
9690     hr = pCoInternetGetSession(0, &session, 0);
9691     ok(hr == S_OK, "CoInternetGetSession failed: 0x%08x\n", hr);
9692     if(FAILED(hr))
9693         return;
9694
9695     hr = IInternetSession_UnregisterNameSpace(session, &protocol_cf, winetestW);
9696     ok(hr == S_OK, "UnregisterNameSpace failed: 0x%08x\n", hr);
9697
9698     IInternetSession_Release(session);
9699 }
9700
9701 static void test_CoInternetCombineIUri_Pluggable(void) {
9702     HRESULT hr;
9703     IUri *base = NULL;
9704
9705     hr = pCreateUri(combine_baseW, 0, 0, &base);
9706     ok(SUCCEEDED(hr), "Error: CreateUri returned 0x%08x.\n", hr);
9707     if(SUCCEEDED(hr)) {
9708         IUri *relative = NULL;
9709
9710         hr = pCreateUri(combine_relativeW, Uri_CREATE_ALLOW_RELATIVE, 0, &relative);
9711         ok(SUCCEEDED(hr), "Error: CreateUri returned 0x%08x.\n", hr);
9712         if(SUCCEEDED(hr)) {
9713             IUri *result = NULL;
9714
9715             SET_EXPECT(CombineUrl);
9716
9717             hr = pCoInternetCombineIUri(base, relative, URL_DONT_SIMPLIFY|URL_FILE_USE_PATHURL|URL_DONT_UNESCAPE_EXTRA_INFO,
9718                                         &result, 0);
9719             ok(hr == S_OK, "Error: CoInternetCombineIUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9720
9721             CHECK_CALLED(CombineUrl);
9722
9723             if(SUCCEEDED(hr)) {
9724                 BSTR received = NULL;
9725                 hr = IUri_GetAbsoluteUri(result, &received);
9726                 ok(hr == S_OK, "Error: Expected S_OK, but got 0x%08x instead.\n", hr);
9727                 if(SUCCEEDED(hr)) {
9728                     ok(!lstrcmpW(combine_resultW, received), "Error: Expected %s, but got %s.\n",
9729                         wine_dbgstr_w(combine_resultW), wine_dbgstr_w(received));
9730                 }
9731                 SysFreeString(received);
9732             }
9733             if(result) IUri_Release(result);
9734         }
9735         if(relative) IUri_Release(relative);
9736     }
9737     if(base) IUri_Release(base);
9738 }
9739
9740 static void test_CoInternetCombineUrlEx(void) {
9741     HRESULT hr;
9742     IUri *base, *result;
9743     DWORD i;
9744
9745     base = NULL;
9746     hr = pCreateUri(http_urlW, 0, 0, &base);
9747     ok(SUCCEEDED(hr), "Error: CreateUri returned 0x%08x.\n", hr);
9748     if(SUCCEEDED(hr)) {
9749         result = (void*) 0xdeadbeef;
9750         hr = pCoInternetCombineUrlEx(base, NULL, 0, &result, 0);
9751         ok(hr == E_UNEXPECTED, "Error: CoInternetCombineUrlEx returned 0x%08x, expected 0x%08x.\n",
9752             hr, E_UNEXPECTED);
9753         ok(!result, "Error: Expected 'result' to be NULL was %p instead.\n", result);
9754     }
9755
9756     result = (void*) 0xdeadbeef;
9757     hr = pCoInternetCombineUrlEx(NULL, http_urlW, 0, &result, 0);
9758     ok(hr == E_INVALIDARG, "Error: CoInternetCombineUrlEx returned 0x%08x, expected 0x%08x.\n",
9759         hr, E_INVALIDARG);
9760     ok(!result, "Error: Expected 'result' to be NULL, but was %p instead.\n", result);
9761
9762     result = (void*) 0xdeadbeef;
9763     hr = pCoInternetCombineUrlEx(NULL, NULL, 0, &result, 0);
9764     ok(hr == E_UNEXPECTED, "Error: CoInternetCombineUrlEx returned 0x%08x, expected 0x%08x.\n",
9765         hr, E_UNEXPECTED);
9766     ok(!result, "Error: Expected 'result' to be NULL, but was %p instead.\n", result);
9767
9768     hr = pCoInternetCombineUrlEx(base, http_urlW, 0, NULL, 0);
9769     ok(hr == E_POINTER, "Error: CoInternetCombineUrlEx returned 0x%08x, expected 0x%08x.\n",
9770         hr, E_POINTER);
9771     if(base) IUri_Release(base);
9772
9773     for(i = 0; i < sizeof(uri_combine_tests)/sizeof(uri_combine_tests[0]); ++i) {
9774         LPWSTR baseW = a2w(uri_combine_tests[i].base_uri);
9775
9776         hr = pCreateUri(baseW, uri_combine_tests[i].base_create_flags, 0, &base);
9777         ok(SUCCEEDED(hr), "Error: CreateUri returned 0x%08x on uri_combine_tests[%d].\n", hr, i);
9778         if(SUCCEEDED(hr)) {
9779             LPWSTR relativeW = a2w(uri_combine_tests[i].relative_uri);
9780
9781             hr = pCoInternetCombineUrlEx(base, relativeW, uri_combine_tests[i].combine_flags,
9782                                          &result, 0);
9783             if(uri_combine_tests[i].todo) {
9784                 todo_wine {
9785                     ok(hr == uri_combine_tests[i].expected,
9786                         "Error: CoInternetCombineUrlEx returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].\n",
9787                         hr, uri_combine_tests[i].expected, i);
9788                 }
9789             } else {
9790                 ok(hr == uri_combine_tests[i].expected,
9791                     "Error: CoInternetCombineUrlEx returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].\n",
9792                     hr, uri_combine_tests[i]. expected, i);
9793             }
9794             if(SUCCEEDED(hr)) {
9795                 DWORD j;
9796
9797                 for(j = 0; j < sizeof(uri_combine_tests[i].str_props)/sizeof(uri_combine_tests[i].str_props[0]); ++j) {
9798                     uri_combine_str_property prop = uri_combine_tests[i].str_props[j];
9799                     BSTR received;
9800                     LPCSTR value = (prop.value_ex) ? prop.value_ex : prop.value;
9801
9802                     hr = IUri_GetPropertyBSTR(result, j, &received, 0);
9803                     if(prop.todo) {
9804                         todo_wine {
9805                             ok(hr == prop.expected,
9806                                 "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].str_props[%d].\n",
9807                                 hr, prop.expected, i, j);
9808                         }
9809                         todo_wine {
9810                             ok(!strcmp_aw(value, received) ||
9811                                broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
9812                                 "Error: Expected %s but got %s instead on uri_combine_tests[%d].str_props[%d].\n",
9813                                 value, wine_dbgstr_w(received), i, j);
9814                         }
9815                     } else {
9816                         ok(hr == prop.expected,
9817                             "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].str_props[%d].\n",
9818                             hr, prop.expected, i, j);
9819                         ok(!strcmp_aw(value, received) ||
9820                            broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
9821                             "Error: Expected %s but got %s instead on uri_combine_tests[%d].str_props[%d].\n",
9822                             value, wine_dbgstr_w(received), i, j);
9823                     }
9824                     SysFreeString(received);
9825                 }
9826
9827                 for(j = 0; j < sizeof(uri_combine_tests[i].dword_props)/sizeof(uri_combine_tests[i].dword_props[0]); ++j) {
9828                     uri_dword_property prop = uri_combine_tests[i].dword_props[j];
9829                     DWORD received;
9830
9831                     hr = IUri_GetPropertyDWORD(result, j+Uri_PROPERTY_DWORD_START, &received, 0);
9832                     if(prop.todo) {
9833                         todo_wine {
9834                             ok(hr == prop.expected,
9835                                 "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].dword_props[%d].\n",
9836                                 hr, prop.expected, i, j);
9837                         }
9838                         todo_wine {
9839                             ok(prop.value == received, "Error: Expected %d, but got %d instead on uri_combine_tests[%d].dword_props[%d].\n",
9840                                 prop.value, received, i, j);
9841                         }
9842                     } else {
9843                         ok(hr == prop.expected,
9844                             "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].dword_props[%d].\n",
9845                             hr, prop.expected, i, j);
9846                         ok(prop.value == received, "Error: Expected %d, but got %d instead on uri_combine_tests[%d].dword_props[%d].\n",
9847                             prop.value, received, i, j);
9848                     }
9849                 }
9850             }
9851             if(result) IUri_Release(result);
9852             heap_free(relativeW);
9853         }
9854         if(base) IUri_Release(base);
9855         heap_free(baseW);
9856     }
9857 }
9858
9859 static void test_CoInternetCombineUrlEx_Pluggable(void) {
9860     HRESULT hr;
9861     IUri *base = NULL;
9862
9863     hr = pCreateUri(combine_baseW, 0, 0, &base);
9864     ok(SUCCEEDED(hr), "Error: CreateUri returned 0x%08x.\n", hr);
9865     if(SUCCEEDED(hr)) {
9866         IUri *result = NULL;
9867
9868         SET_EXPECT(CombineUrl);
9869
9870         hr = pCoInternetCombineUrlEx(base, combine_relativeW, URL_DONT_SIMPLIFY|URL_FILE_USE_PATHURL|URL_DONT_UNESCAPE_EXTRA_INFO,
9871                                      &result, 0);
9872         ok(hr == S_OK, "Error: CoInternetCombineUrlEx returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9873
9874         CHECK_CALLED(CombineUrl);
9875
9876         if(SUCCEEDED(hr)) {
9877             BSTR received = NULL;
9878             hr = IUri_GetAbsoluteUri(result, &received);
9879             ok(hr == S_OK, "Error: Expected S_OK, but got 0x%08x instead.\n", hr);
9880             if(SUCCEEDED(hr)) {
9881                 ok(!lstrcmpW(combine_resultW, received), "Error: Expected %s, but got %s.\n",
9882                     wine_dbgstr_w(combine_resultW), wine_dbgstr_w(received));
9883             }
9884             SysFreeString(received);
9885         }
9886         if(result) IUri_Release(result);
9887     }
9888     if(base) IUri_Release(base);
9889 }
9890
9891 static void test_CoInternetParseIUri_InvalidArgs(void) {
9892     HRESULT hr;
9893     IUri *uri = NULL;
9894     WCHAR tmp[3];
9895     DWORD result = -1;
9896
9897     hr = pCoInternetParseIUri(NULL, PARSE_CANONICALIZE, 0, tmp, 3, &result, 0);
9898     ok(hr == E_INVALIDARG, "Error: CoInternetParseIUri returned 0x%08x, expected 0x%08x.\n",
9899         hr, E_INVALIDARG);
9900     ok(!result, "Error: Expected 'result' to be 0, but was %d.\n", result);
9901
9902     hr = pCreateUri(http_urlW, 0, 0, &uri);
9903     ok(SUCCEEDED(hr), "Error: CreateUri returned 0x%08x.\n", hr);
9904     if(SUCCEEDED(hr)) {
9905         DWORD expected_len;
9906
9907         result = -1;
9908         hr = pCoInternetParseIUri(uri, PARSE_CANONICALIZE, 0, NULL, 0, &result, 0);
9909         ok(hr == E_INVALIDARG, "Error: CoInternetParseIUri returned 0x%08x, expected 0x%08x.\n",
9910             hr, E_INVALIDARG);
9911         ok(!result, "Error: Expected 'result' to be 0, but was %d.\n", result);
9912
9913         hr = pCoInternetParseIUri(uri, PARSE_CANONICALIZE, 0, tmp, 3, NULL, 0);
9914         ok(hr == E_POINTER, "Error: CoInternetParseIUri returned 0x%08x, expected 0x%08x.\n",
9915             hr, E_POINTER);
9916
9917         result = -1;
9918         hr = pCoInternetParseIUri(uri, PARSE_SECURITY_URL, 0, tmp, 3, &result, 0);
9919         ok(hr == E_FAIL, "Error: CoInternetParseIUri returned 0x%08x expected 0x%08x.\n",
9920             hr, E_FAIL);
9921         ok(!result, "Error: Expected 'result' to be 0, but was %d.\n", result);
9922
9923         result = -1;
9924         hr = pCoInternetParseIUri(uri, PARSE_MIME, 0, tmp, 3, &result, 0);
9925         ok(hr == E_FAIL, "Error: CoInternetParseIUri returned 0x%08x, expected 0x%08x.\n",
9926             hr, E_FAIL);
9927         ok(!result, "Error: Expected 'result' to be 0, but was %d.\n", result);
9928
9929         result = -1;
9930         hr = pCoInternetParseIUri(uri, PARSE_SERVER, 0, tmp, 3, &result, 0);
9931         ok(hr == E_FAIL, "Error: CoInternetParseIUri returned 0x%08x, expected 0x%08x.\n",
9932             hr, E_FAIL);
9933         ok(!result, "Error: Expected 'result' to be 0, but was %d.\n", result);
9934
9935         result = -1;
9936         hr = pCoInternetParseIUri(uri, PARSE_SECURITY_DOMAIN, 0, tmp, 3, &result, 0);
9937         ok(hr == E_FAIL, "Error: CoInternetParseIUri returned 0x%08x, expected 0x%08x.\n",
9938             hr, E_FAIL);
9939         ok(!result, "Error: Expected 'result' to be 0, but was %d.\n", result);
9940
9941         expected_len = lstrlenW(http_urlW);
9942         result = -1;
9943         hr = pCoInternetParseIUri(uri, PARSE_CANONICALIZE, 0, tmp, 3, &result, 0);
9944         ok(hr == STRSAFE_E_INSUFFICIENT_BUFFER,
9945             "Error: CoInternetParseIUri returned 0x%08x, expected 0x%08x.\n",
9946             hr, STRSAFE_E_INSUFFICIENT_BUFFER);
9947         ok(result == expected_len, "Error: Expected 'result' to be %d, but was %d instead.\n",
9948             expected_len, result);
9949     }
9950     if(uri) IUri_Release(uri);
9951 }
9952
9953 static void test_CoInternetParseIUri(void) {
9954     DWORD i;
9955
9956     for(i = 0; i < sizeof(uri_parse_tests)/sizeof(uri_parse_tests[0]); ++i) {
9957         HRESULT hr;
9958         IUri *uri;
9959         LPWSTR uriW;
9960         uri_parse_test test = uri_parse_tests[i];
9961
9962         uriW = a2w(test.uri);
9963         hr = pCreateUri(uriW, test.uri_flags, 0, &uri);
9964         ok(SUCCEEDED(hr), "Error: CreateUri returned 0x%08x on uri_parse_tests[%d].\n", hr, i);
9965         if(SUCCEEDED(hr)) {
9966             WCHAR result[INTERNET_MAX_URL_LENGTH+1];
9967             DWORD result_len = -1;
9968
9969             hr = pCoInternetParseIUri(uri, test.action, test.flags, result, INTERNET_MAX_URL_LENGTH+1, &result_len, 0);
9970             if(test.todo) {
9971                 todo_wine {
9972                     ok(hr == test.expected,
9973                         "Error: CoInternetParseIUri returned 0x%08x, expected 0x%08x on uri_parse_tests[%d].\n",
9974                         hr, test.expected, i);
9975                 }
9976             } else {
9977                 ok(hr == test.expected,
9978                     "Error: CoInternetParseIUri returned 0x%08x, expected 0x%08x on uri_parse_tests[%d].\n",
9979                     hr, test.expected, i);
9980             }
9981             if(SUCCEEDED(hr)) {
9982                 DWORD len = lstrlenA(test.property);
9983                 ok(!strcmp_aw(test.property, result),
9984                     "Error: Expected %s but got %s instead on uri_parse_tests[%d].\n",
9985                     test.property, wine_dbgstr_w(result), i);
9986                 ok(len == result_len,
9987                     "Error: Expected %d, but got %d instead on uri_parse_tests[%d].\n",
9988                     len, result_len, i);
9989             } else {
9990                 ok(!result_len,
9991                     "Error: Expected 'result_len' to be 0, but was %d on uri_parse_tests[%d].\n",
9992                     result_len, i);
9993             }
9994         }
9995         if(uri) IUri_Release(uri);
9996         heap_free(uriW);
9997     }
9998 }
9999
10000 static void test_CoInternetParseIUri_Pluggable(void) {
10001     HRESULT hr;
10002     IUri *uri = NULL;
10003
10004     hr = pCreateUri(parse_urlW, 0, 0, &uri);
10005     ok(SUCCEEDED(hr), "Error: Expected CreateUri to succeed, but got 0x%08x.\n", hr);
10006     if(SUCCEEDED(hr)) {
10007         WCHAR result[200];
10008         DWORD result_len;
10009
10010         SET_EXPECT(ParseUrl);
10011
10012         parse_action = PARSE_CANONICALIZE;
10013         parse_flags = URL_UNESCAPE|URL_ESCAPE_UNSAFE;
10014
10015         hr = pCoInternetParseIUri(uri, parse_action, parse_flags, result, 200, &result_len, 0);
10016         ok(hr == S_OK, "Error: CoInternetParseIUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
10017
10018         CHECK_CALLED(ParseUrl);
10019
10020         if(SUCCEEDED(hr)) {
10021             ok(result_len == lstrlenW(parse_resultW), "Error: Expected %d, but got %d.\n",
10022                 lstrlenW(parse_resultW), result_len);
10023             ok(!lstrcmpW(result, parse_resultW), "Error: Expected %s, but got %s.\n",
10024                 wine_dbgstr_w(parse_resultW), wine_dbgstr_w(result));
10025         }
10026     }
10027     if(uri) IUri_Release(uri);
10028 }
10029
10030 START_TEST(uri) {
10031     HMODULE hurlmon;
10032
10033     hurlmon = GetModuleHandle("urlmon.dll");
10034     pCoInternetGetSession = (void*) GetProcAddress(hurlmon, "CoInternetGetSession");
10035     pCreateUri = (void*) GetProcAddress(hurlmon, "CreateUri");
10036     pCreateUriWithFragment = (void*) GetProcAddress(hurlmon, "CreateUriWithFragment");
10037     pCreateIUriBuilder = (void*) GetProcAddress(hurlmon, "CreateIUriBuilder");
10038     pCoInternetCombineIUri = (void*) GetProcAddress(hurlmon, "CoInternetCombineIUri");
10039     pCoInternetCombineUrlEx = (void*) GetProcAddress(hurlmon, "CoInternetCombineUrlEx");
10040     pCoInternetParseIUri = (void*) GetProcAddress(hurlmon, "CoInternetParseIUri");
10041
10042     if(!pCreateUri) {
10043         win_skip("CreateUri is not present, skipping tests.\n");
10044         return;
10045     }
10046
10047     trace("test CreateUri invalid flags...\n");
10048     test_CreateUri_InvalidFlags();
10049
10050     trace("test CreateUri invalid args...\n");
10051     test_CreateUri_InvalidArgs();
10052
10053     trace("test CreateUri invalid URIs...\n");
10054     test_CreateUri_InvalidUri();
10055
10056     trace("test IUri_GetPropertyBSTR...\n");
10057     test_IUri_GetPropertyBSTR();
10058
10059     trace("test IUri_GetPropertyDWORD...\n");
10060     test_IUri_GetPropertyDWORD();
10061
10062     trace("test IUri_GetStrProperties...\n");
10063     test_IUri_GetStrProperties();
10064
10065     trace("test IUri_GetDwordProperties...\n");
10066     test_IUri_GetDwordProperties();
10067
10068     trace("test IUri_GetPropertyLength...\n");
10069     test_IUri_GetPropertyLength();
10070
10071     trace("test IUri_GetProperties...\n");
10072     test_IUri_GetProperties();
10073
10074     trace("test IUri_HasProperty...\n");
10075     test_IUri_HasProperty();
10076
10077     trace("test IUri_IsEqual...\n");
10078     test_IUri_IsEqual();
10079
10080     trace("test CreateUriWithFragment invalid args...\n");
10081     test_CreateUriWithFragment_InvalidArgs();
10082
10083     trace("test CreateUriWithFragment invalid flags...\n");
10084     test_CreateUriWithFragment_InvalidFlags();
10085
10086     trace("test CreateUriWithFragment...\n");
10087     test_CreateUriWithFragment();
10088
10089     trace("test CreateIUriBuilder...\n");
10090     test_CreateIUriBuilder();
10091
10092     trace("test IUriBuilder_CreateInvalidArgs...\n");
10093     test_IUriBuilder_CreateInvalidArgs();
10094
10095     trace("test IUriBuilder...\n");
10096     test_IUriBuilder();
10097
10098     trace("test IUriBuilder_GetInvalidArgs...\n");
10099     test_IUriBuilder_GetInvalidArgs();
10100
10101     trace("test IUriBuilder_HasBeenModified...\n");
10102     test_IUriBuilder_HasBeenModified();
10103
10104     trace("test IUriBuilder_IUriProperty...\n");
10105     test_IUriBuilder_IUriProperty();
10106
10107     trace("test IUriBuilder_RemoveProperties...\n");
10108     test_IUriBuilder_RemoveProperties();
10109
10110     trace("test IUriBuilder miscellaneous...\n");
10111     test_IUriBuilder_Misc();
10112
10113     trace("test IUriBuilderFactory...\n");
10114     test_IUriBuilderFactory();
10115
10116     trace("test CoInternetCombineIUri...\n");
10117     test_CoInternetCombineIUri();
10118
10119     trace("test CoInternetCombineUrlEx...\n");
10120     test_CoInternetCombineUrlEx();
10121
10122     trace("test CoInternetParseIUri Invalid Args...\n");
10123     test_CoInternetParseIUri_InvalidArgs();
10124
10125     trace("test CoInternetParseIUri...\n");
10126     test_CoInternetParseIUri();
10127
10128     register_protocols();
10129
10130     trace("test CoInternetCombineIUri pluggable...\n");
10131     test_CoInternetCombineIUri_Pluggable();
10132
10133     trace("test CoInternetCombineUrlEx Pluggable...\n");
10134     test_CoInternetCombineUrlEx_Pluggable();
10135
10136     trace("test CoInternetParseIUri pluggable...\n");
10137     test_CoInternetParseIUri_Pluggable();
10138
10139     unregister_protocols();
10140 }