mmdevapi/tests: Add tests for IAudioClient::GetCurrentPadding.
[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 };
6083
6084 typedef struct _uri_parse_test {
6085     const char  *uri;
6086     DWORD       uri_flags;
6087     PARSEACTION action;
6088     DWORD       flags;
6089     const char  *property;
6090     HRESULT     expected;
6091     BOOL        todo;
6092 } uri_parse_test;
6093
6094 static const uri_parse_test uri_parse_tests[] = {
6095     /* PARSE_CANONICALIZE tests. */
6096     {"zip://google.com/test<|>",0,PARSE_CANONICALIZE,0,"zip://google.com/test<|>",S_OK,FALSE},
6097     {"http://google.com/test<|>",0,PARSE_CANONICALIZE,0,"http://google.com/test%3C%7C%3E",S_OK,FALSE},
6098     {"http://google.com/%30%23%3F",0,PARSE_CANONICALIZE,URL_UNESCAPE,"http://google.com/0#?",S_OK,FALSE},
6099     {"test <|>",Uri_CREATE_ALLOW_RELATIVE,PARSE_CANONICALIZE,URL_ESCAPE_UNSAFE,"test %3C%7C%3E",S_OK,FALSE},
6100     {"test <|>",Uri_CREATE_ALLOW_RELATIVE,PARSE_CANONICALIZE,URL_ESCAPE_SPACES_ONLY,"test%20<|>",S_OK,FALSE},
6101     {"test%20<|>",Uri_CREATE_ALLOW_RELATIVE,PARSE_CANONICALIZE,URL_UNESCAPE|URL_ESCAPE_UNSAFE,"test%20%3C%7C%3E",S_OK,FALSE},
6102     {"http://google.com/%20",0,PARSE_CANONICALIZE,URL_ESCAPE_PERCENT,"http://google.com/%2520",S_OK,FALSE},
6103     {"http://google.com/test/../",Uri_CREATE_NO_CANONICALIZE,PARSE_CANONICALIZE,URL_DONT_SIMPLIFY,"http://google.com/test/../",S_OK,FALSE},
6104     {"http://google.com/test/../",Uri_CREATE_NO_CANONICALIZE,PARSE_CANONICALIZE,URL_NO_META,"http://google.com/test/../",S_OK,FALSE},
6105     {"http://google.com/test/../",Uri_CREATE_NO_CANONICALIZE,PARSE_CANONICALIZE,0,"http://google.com/",S_OK,FALSE},
6106     {"zip://google.com/test/../",Uri_CREATE_NO_CANONICALIZE,PARSE_CANONICALIZE,0,"zip://google.com/",S_OK,FALSE},
6107     {"file:///c:/test/../test",Uri_CREATE_NO_CANONICALIZE,PARSE_CANONICALIZE,URL_DONT_SIMPLIFY,"file:///c:/test/../test",S_OK,FALSE},
6108
6109     /* PARSE_FRIENDLY tests. */
6110     {"http://test@google.com/test#test",0,PARSE_FRIENDLY,0,"http://google.com/test#test",S_OK,FALSE},
6111     {"zip://test@google.com/test",0,PARSE_FRIENDLY,0,"zip://test@google.com/test",S_OK,FALSE},
6112
6113     /* PARSE_ROOTDOCUMENT tests. */
6114     {"http://google.com:200/test/test",0,PARSE_ROOTDOCUMENT,0,"http://google.com:200/",S_OK,FALSE},
6115     {"http://google.com",Uri_CREATE_NO_CANONICALIZE,PARSE_ROOTDOCUMENT,0,"http://google.com/",S_OK,FALSE},
6116     {"zip://google.com/",0,PARSE_ROOTDOCUMENT,0,"",S_OK,FALSE},
6117     {"file:///c:/testing/",0,PARSE_ROOTDOCUMENT,0,"",S_OK,FALSE},
6118     {"file://server/test",0,PARSE_ROOTDOCUMENT,0,"",S_OK,FALSE},
6119     {"zip:test/test",0,PARSE_ROOTDOCUMENT,0,"",S_OK,FALSE},
6120
6121     /* PARSE_DOCUMENT tests. */
6122     {"http://test@google.com/test?query#frag",0,PARSE_DOCUMENT,0,"http://test@google.com/test?query",S_OK,FALSE},
6123     {"http:testing#frag",0,PARSE_DOCUMENT,0,"",S_OK,FALSE},
6124     {"file:///c:/test#frag",0,PARSE_DOCUMENT,0,"",S_OK,FALSE},
6125     {"zip://google.com/#frag",0,PARSE_DOCUMENT,0,"",S_OK,FALSE},
6126     {"zip:test#frag",0,PARSE_DOCUMENT,0,"",S_OK,FALSE},
6127     {"testing#frag",Uri_CREATE_ALLOW_RELATIVE,PARSE_DOCUMENT,0,"",S_OK,FALSE},
6128
6129     /* PARSE_PATH_FROM_URL tests. */
6130     {"file:///c:/test.mp3",0,PARSE_PATH_FROM_URL,0,"c:\\test.mp3",S_OK,FALSE},
6131     {"file:///c:/t<|>est.mp3",0,PARSE_PATH_FROM_URL,0,"c:\\t<|>est.mp3",S_OK,FALSE},
6132     {"file:///c:/te%XX t/",0,PARSE_PATH_FROM_URL,0,"c:\\te%XX t\\",S_OK,FALSE},
6133     {"file://server/test",0,PARSE_PATH_FROM_URL,0,"\\\\server\\test",S_OK,FALSE},
6134     {"http://google.com/",0,PARSE_PATH_FROM_URL,0,"",E_INVALIDARG,FALSE},
6135
6136     /* PARSE_URL_FROM_PATH tests. */
6137     /* This function almost seems to useless (just returns the absolute uri). */
6138     {"test.com",Uri_CREATE_ALLOW_RELATIVE,PARSE_URL_FROM_PATH,0,"test.com",S_OK,FALSE},
6139     {"/test/test",Uri_CREATE_ALLOW_RELATIVE,PARSE_URL_FROM_PATH,0,"/test/test",S_OK,FALSE},
6140     {"file://c:\\test\\test",Uri_CREATE_FILE_USE_DOS_PATH,PARSE_URL_FROM_PATH,0,"file://c:\\test\\test",S_OK,FALSE},
6141     {"file:c:/test",0,PARSE_URL_FROM_PATH,0,"",S_OK,FALSE},
6142     {"http:google.com/",0,PARSE_URL_FROM_PATH,0,"",S_OK,FALSE},
6143
6144     /* PARSE_SCHEMA tests. */
6145     {"http://google.com/test",0,PARSE_SCHEMA,0,"http",S_OK,FALSE},
6146     {"test",Uri_CREATE_ALLOW_RELATIVE,PARSE_SCHEMA,0,"",S_OK,FALSE},
6147
6148     /* PARSE_SITE tests. */
6149     {"http://google.uk.com/",0,PARSE_SITE,0,"google.uk.com",S_OK,FALSE},
6150     {"http://google.com.com/",0,PARSE_SITE,0,"google.com.com",S_OK,FALSE},
6151     {"google.com",Uri_CREATE_ALLOW_RELATIVE,PARSE_SITE,0,"",S_OK,FALSE},
6152     {"file://server/test",0,PARSE_SITE,0,"server",S_OK,FALSE},
6153
6154     /* PARSE_DOMAIN tests. */
6155     {"http://google.com.uk/",0,PARSE_DOMAIN,0,"google.com.uk",S_OK,FALSE},
6156     {"http://google.com.com/",0,PARSE_DOMAIN,0,"com.com",S_OK,FALSE},
6157     {"test/test",Uri_CREATE_ALLOW_RELATIVE,PARSE_DOMAIN,0,"",S_OK,FALSE},
6158     {"file://server/test",0,PARSE_DOMAIN,0,"",S_OK,FALSE},
6159
6160     /* PARSE_LOCATION and PARSE_ANCHOR tests. */
6161     {"http://google.com/test#Test",0,PARSE_ANCHOR,0,"#Test",S_OK,FALSE},
6162     {"http://google.com/test#Test",0,PARSE_LOCATION,0,"#Test",S_OK,FALSE},
6163     {"test",Uri_CREATE_ALLOW_RELATIVE,PARSE_ANCHOR,0,"",S_OK,FALSE},
6164     {"test",Uri_CREATE_ALLOW_RELATIVE,PARSE_LOCATION,0,"",S_OK,FALSE}
6165 };
6166
6167 static inline LPWSTR a2w(LPCSTR str) {
6168     LPWSTR ret = NULL;
6169
6170     if(str) {
6171         DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
6172         ret = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
6173         MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len);
6174     }
6175
6176     return ret;
6177 }
6178
6179 static inline BOOL heap_free(void* mem) {
6180     return HeapFree(GetProcessHeap(), 0, mem);
6181 }
6182
6183 static inline DWORD strcmp_aw(LPCSTR strA, LPCWSTR strB) {
6184     LPWSTR strAW = a2w(strA);
6185     DWORD ret = lstrcmpW(strAW, strB);
6186     heap_free(strAW);
6187     return ret;
6188 }
6189
6190 static inline ULONG get_refcnt(IUri *uri) {
6191     IUri_AddRef(uri);
6192     return IUri_Release(uri);
6193 }
6194
6195 static void change_property(IUriBuilder *builder, const uri_builder_property *prop,
6196                             DWORD test_index) {
6197     HRESULT hr;
6198     LPWSTR valueW;
6199
6200     valueW = a2w(prop->value);
6201     switch(prop->property) {
6202     case Uri_PROPERTY_FRAGMENT:
6203         hr = IUriBuilder_SetFragment(builder, valueW);
6204         if(prop->todo) {
6205             todo_wine {
6206                 ok(hr == prop->expected,
6207                     "Error: IUriBuilder_SetFragment returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6208                     hr, prop->expected, test_index);
6209             }
6210         } else {
6211             ok(hr == prop->expected,
6212                 "Error: IUriBuilder_SetFragment returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6213                 hr, prop->expected, test_index);
6214         }
6215         break;
6216     case Uri_PROPERTY_HOST:
6217         hr = IUriBuilder_SetHost(builder, valueW);
6218         if(prop->todo) {
6219             todo_wine {
6220                 ok(hr == prop->expected,
6221                     "Error: IUriBuilder_SetHost returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6222                     hr, prop->expected, test_index);
6223             }
6224         } else {
6225             ok(hr == prop->expected,
6226                 "Error: IUriBuilder_SetHost returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6227                 hr, prop->expected, test_index);
6228         }
6229         break;
6230     case Uri_PROPERTY_PASSWORD:
6231         hr = IUriBuilder_SetPassword(builder, valueW);
6232         if(prop->todo) {
6233             todo_wine {
6234                 ok(hr == prop->expected,
6235                     "Error: IUriBuilder_SetPassword returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6236                     hr, prop->expected, test_index);
6237             }
6238         } else {
6239             ok(hr == prop->expected,
6240                 "Error: IUriBuilder_SetPassword returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6241                 hr, prop->expected, test_index);
6242         }
6243         break;
6244     case Uri_PROPERTY_PATH:
6245         hr = IUriBuilder_SetPath(builder, valueW);
6246         if(prop->todo) {
6247             todo_wine {
6248                 ok(hr == prop->expected,
6249                     "Error: IUriBuilder_SetPath returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6250                     hr, prop->expected, test_index);
6251             }
6252         } else {
6253             ok(hr == prop->expected,
6254                 "Error: IUriBuilder_SetPath returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6255                 hr, prop->expected, test_index);
6256         }
6257         break;
6258     case Uri_PROPERTY_QUERY:
6259         hr = IUriBuilder_SetQuery(builder, valueW);
6260         if(prop->todo) {
6261             todo_wine {
6262                 ok(hr == prop->expected,
6263                     "Error: IUriBuilder_SetQuery returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6264                     hr, prop->expected, test_index);
6265             }
6266         } else {
6267             ok(hr == prop->expected,
6268                 "Error: IUriBuilder_SetQuery returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6269                 hr, prop->expected, test_index);
6270         }
6271         break;
6272     case Uri_PROPERTY_SCHEME_NAME:
6273         hr = IUriBuilder_SetSchemeName(builder, valueW);
6274         if(prop->todo) {
6275             todo_wine {
6276                 ok(hr == prop->expected,
6277                     "Error: IUriBuilder_SetSchemeName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6278                     hr, prop->expected, test_index);
6279             }
6280         } else {
6281             ok(hr == prop->expected,
6282                 "Error: IUriBuilder_SetSchemeName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6283                 hr, prop->expected, test_index);
6284         }
6285         break;
6286     case Uri_PROPERTY_USER_NAME:
6287         hr = IUriBuilder_SetUserName(builder, valueW);
6288         if(prop->todo) {
6289             todo_wine {
6290                 ok(hr == prop->expected,
6291                     "Error: IUriBuilder_SetUserName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6292                     hr, prop->expected, test_index);
6293             }
6294         } else {
6295             ok(hr == prop->expected,
6296                 "Error: IUriBuilder_SetUserName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6297                 hr, prop->expected, test_index);
6298         }
6299         break;
6300     default:
6301         trace("Unsupported operation for %d on uri_builder_tests[%d].\n", prop->property, test_index);
6302     }
6303
6304     heap_free(valueW);
6305 }
6306
6307 /*
6308  * Simple tests to make sure the CreateUri function handles invalid flag combinations
6309  * correctly.
6310  */
6311 static void test_CreateUri_InvalidFlags(void) {
6312     DWORD i;
6313
6314     for(i = 0; i < sizeof(invalid_flag_tests)/sizeof(invalid_flag_tests[0]); ++i) {
6315         HRESULT hr;
6316         IUri *uri = (void*) 0xdeadbeef;
6317
6318         hr = pCreateUri(http_urlW, invalid_flag_tests[i].flags, 0, &uri);
6319         ok(hr == invalid_flag_tests[i].expected, "Error: CreateUri returned 0x%08x, expected 0x%08x, flags=0x%08x\n",
6320                 hr, invalid_flag_tests[i].expected, invalid_flag_tests[i].flags);
6321         ok(uri == NULL, "Error: expected the IUri to be NULL, but it was %p instead\n", uri);
6322     }
6323 }
6324
6325 static void test_CreateUri_InvalidArgs(void) {
6326     HRESULT hr;
6327     IUri *uri = (void*) 0xdeadbeef;
6328
6329     const WCHAR invalidW[] = {'i','n','v','a','l','i','d',0};
6330     static const WCHAR emptyW[] = {0};
6331
6332     hr = pCreateUri(http_urlW, 0, 0, NULL);
6333     ok(hr == E_INVALIDARG, "Error: CreateUri returned 0x%08x, expected 0x%08x\n", hr, E_INVALIDARG);
6334
6335     hr = pCreateUri(NULL, 0, 0, &uri);
6336     ok(hr == E_INVALIDARG, "Error: CreateUri returned 0x%08x, expected 0x%08x\n", hr, E_INVALIDARG);
6337     ok(uri == NULL, "Error: Expected the IUri to be NULL, but it was %p instead\n", uri);
6338
6339     uri = (void*) 0xdeadbeef;
6340     hr = pCreateUri(invalidW, 0, 0, &uri);
6341     ok(hr == E_INVALIDARG, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
6342     ok(uri == NULL, "Error: Expected the IUri to be NULL, but it was %p instead\n", uri);
6343
6344     uri = (void*) 0xdeadbeef;
6345     hr = pCreateUri(emptyW, 0, 0, &uri);
6346     ok(hr == E_INVALIDARG, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
6347     ok(uri == NULL, "Error: Expected the IUri to be NULL, but it was %p instead\n", uri);
6348 }
6349
6350 static void test_CreateUri_InvalidUri(void) {
6351     DWORD i;
6352
6353     for(i = 0; i < sizeof(invalid_uri_tests)/sizeof(invalid_uri_tests[0]); ++i) {
6354         invalid_uri test = invalid_uri_tests[i];
6355         IUri *uri = NULL;
6356         LPWSTR uriW;
6357         HRESULT hr;
6358
6359         uriW = a2w(test.uri);
6360         hr = pCreateUri(uriW, test.flags, 0, &uri);
6361         if(test.todo) {
6362             todo_wine {
6363                 ok(hr == E_INVALIDARG, "Error: CreateUri returned 0x%08x, expected 0x%08x on invalid_uri_tests[%d].\n",
6364                     hr, E_INVALIDARG, i);
6365             }
6366         } else {
6367             ok(hr == E_INVALIDARG, "Error: CreateUri returned 0x%08x, expected 0x%08x on invalid_uri_tests[%d].\n",
6368                 hr, E_INVALIDARG, i);
6369         }
6370         if(uri) IUri_Release(uri);
6371
6372         heap_free(uriW);
6373     }
6374 }
6375
6376 static void test_IUri_GetPropertyBSTR(void) {
6377     IUri *uri = NULL;
6378     HRESULT hr;
6379     DWORD i;
6380
6381     /* Make sure GetPropertyBSTR handles invalid args correctly. */
6382     hr = pCreateUri(http_urlW, 0, 0, &uri);
6383     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
6384     if(SUCCEEDED(hr)) {
6385         BSTR received = NULL;
6386
6387         hr = IUri_GetPropertyBSTR(uri, Uri_PROPERTY_RAW_URI, NULL, 0);
6388         ok(hr == E_POINTER, "Error: GetPropertyBSTR returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
6389
6390         /* Make sure it handles a invalid Uri_PROPERTY's correctly. */
6391         hr = IUri_GetPropertyBSTR(uri, Uri_PROPERTY_PORT, &received, 0);
6392         ok(hr == S_OK, "Error: GetPropertyBSTR returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
6393         ok(received != NULL, "Error: Expected the string not to be NULL.\n");
6394         ok(!SysStringLen(received), "Error: Expected the string to be of len=0 but it was %d instead.\n", SysStringLen(received));
6395         SysFreeString(received);
6396
6397         /* Make sure it handles the ZONE property correctly. */
6398         received = NULL;
6399         hr = IUri_GetPropertyBSTR(uri, Uri_PROPERTY_ZONE, &received, 0);
6400         ok(hr == S_FALSE, "Error: GetPropertyBSTR returned 0x%08x, expected 0x%08x.\n", hr, S_FALSE);
6401         ok(received != NULL, "Error: Expected the string not to be NULL.\n");
6402         ok(!SysStringLen(received), "Error: Expected the string to be of len=0 but it was %d instead.\n", SysStringLen(received));
6403         SysFreeString(received);
6404     }
6405     if(uri) IUri_Release(uri);
6406
6407     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
6408         uri_properties test = uri_tests[i];
6409         LPWSTR uriW;
6410         uri = NULL;
6411
6412         uriW = a2w(test.uri);
6413         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
6414         if(test.create_todo) {
6415             todo_wine {
6416                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x. Failed on uri_tests[%d].\n",
6417                         hr, test.create_expected, i);
6418             }
6419         } else {
6420             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x. Failed on uri_tests[%d].\n",
6421                     hr, test.create_expected, i);
6422         }
6423
6424         if(SUCCEEDED(hr)) {
6425             DWORD j;
6426
6427             /* Checks all the string properties of the uri. */
6428             for(j = Uri_PROPERTY_STRING_START; j <= Uri_PROPERTY_STRING_LAST; ++j) {
6429                 BSTR received = NULL;
6430                 uri_str_property prop = test.str_props[j];
6431
6432                 hr = IUri_GetPropertyBSTR(uri, j, &received, 0);
6433                 if(prop.todo) {
6434                     todo_wine {
6435                         ok(hr == prop.expected, "GetPropertyBSTR returned 0x%08x, expected 0x%08x. On uri_tests[%d].str_props[%d].\n",
6436                                 hr, prop.expected, i, j);
6437                     }
6438                     todo_wine {
6439                         ok(!strcmp_aw(prop.value, received) || broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
6440                                 "Expected %s but got %s on uri_tests[%d].str_props[%d].\n",
6441                                 prop.value, wine_dbgstr_w(received), i, j);
6442                     }
6443                 } else {
6444                     ok(hr == prop.expected, "GetPropertyBSTR returned 0x%08x, expected 0x%08x. On uri_tests[%d].str_props[%d].\n",
6445                             hr, prop.expected, i, j);
6446                     ok(!strcmp_aw(prop.value, received) || broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
6447                             "Expected %s but got %s on uri_tests[%d].str_props[%d].\n",
6448                             prop.value, wine_dbgstr_w(received), i, j);
6449                 }
6450
6451                 SysFreeString(received);
6452             }
6453         }
6454
6455         if(uri) IUri_Release(uri);
6456
6457         heap_free(uriW);
6458     }
6459 }
6460
6461 static void test_IUri_GetPropertyDWORD(void) {
6462     IUri *uri = NULL;
6463     HRESULT hr;
6464     DWORD i;
6465
6466     hr = pCreateUri(http_urlW, 0, 0, &uri);
6467     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
6468     if(SUCCEEDED(hr)) {
6469         DWORD received = 0xdeadbeef;
6470
6471         hr = IUri_GetPropertyDWORD(uri, Uri_PROPERTY_DWORD_START, NULL, 0);
6472         ok(hr == E_INVALIDARG, "Error: GetPropertyDWORD returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
6473
6474         hr = IUri_GetPropertyDWORD(uri, Uri_PROPERTY_ABSOLUTE_URI, &received, 0);
6475         ok(hr == E_INVALIDARG, "Error: GetPropertyDWORD returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
6476         ok(received == 0, "Error: Expected received=%d but instead received=%d.\n", 0, received);
6477     }
6478     if(uri) IUri_Release(uri);
6479
6480     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
6481         uri_properties test = uri_tests[i];
6482         LPWSTR uriW;
6483         uri = NULL;
6484
6485         uriW = a2w(test.uri);
6486         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
6487         if(test.create_todo) {
6488             todo_wine {
6489                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x. Failed on uri_tests[%d].\n",
6490                         hr, test.create_expected, i);
6491             }
6492         } else {
6493             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x. Failed on uri_tests[%d].\n",
6494                     hr, test.create_expected, i);
6495         }
6496
6497         if(SUCCEEDED(hr)) {
6498             DWORD j;
6499
6500             /* Checks all the DWORD properties of the uri. */
6501             for(j = 0; j < sizeof(test.dword_props)/sizeof(test.dword_props[0]); ++j) {
6502                 DWORD received;
6503                 uri_dword_property prop = test.dword_props[j];
6504
6505                 hr = IUri_GetPropertyDWORD(uri, j+Uri_PROPERTY_DWORD_START, &received, 0);
6506                 if(prop.todo) {
6507                     todo_wine {
6508                         ok(hr == prop.expected, "GetPropertyDWORD returned 0x%08x, expected 0x%08x. On uri_tests[%d].dword_props[%d].\n",
6509                                 hr, prop.expected, i, j);
6510                     }
6511                     todo_wine {
6512                         ok(prop.value == received, "Expected %d but got %d on uri_tests[%d].dword_props[%d].\n",
6513                                 prop.value, received, i, j);
6514                     }
6515                 } else {
6516                     ok(hr == prop.expected, "GetPropertyDWORD returned 0x%08x, expected 0x%08x. On uri_tests[%d].dword_props[%d].\n",
6517                             hr, prop.expected, i, j);
6518                     ok(prop.value == received, "Expected %d but got %d on uri_tests[%d].dword_props[%d].\n",
6519                             prop.value, received, i, j);
6520                 }
6521             }
6522         }
6523
6524         if(uri) IUri_Release(uri);
6525
6526         heap_free(uriW);
6527     }
6528 }
6529
6530 /* Tests all the 'Get*' property functions which deal with strings. */
6531 static void test_IUri_GetStrProperties(void) {
6532     IUri *uri = NULL;
6533     HRESULT hr;
6534     DWORD i;
6535
6536     /* Make sure all the 'Get*' string property functions handle invalid args correctly. */
6537     hr = pCreateUri(http_urlW, 0, 0, &uri);
6538     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
6539     if(SUCCEEDED(hr)) {
6540         hr = IUri_GetAbsoluteUri(uri, NULL);
6541         ok(hr == E_POINTER, "Error: GetAbsoluteUri returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
6542
6543         hr = IUri_GetAuthority(uri, NULL);
6544         ok(hr == E_POINTER, "Error: GetAuthority returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
6545
6546         hr = IUri_GetDisplayUri(uri, NULL);
6547         ok(hr == E_POINTER, "Error: GetDisplayUri returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
6548
6549         hr = IUri_GetDomain(uri, NULL);
6550         ok(hr == E_POINTER, "Error: GetDomain returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
6551
6552         hr = IUri_GetExtension(uri, NULL);
6553         ok(hr == E_POINTER, "Error: GetExtension returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
6554
6555         hr = IUri_GetFragment(uri, NULL);
6556         ok(hr == E_POINTER, "Error: GetFragment returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
6557
6558         hr = IUri_GetHost(uri, NULL);
6559         ok(hr == E_POINTER, "Error: GetHost returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
6560
6561         hr = IUri_GetPassword(uri, NULL);
6562         ok(hr == E_POINTER, "Error: GetPassword returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
6563
6564         hr = IUri_GetPath(uri, NULL);
6565         ok(hr == E_POINTER, "Error: GetPath returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
6566
6567         hr = IUri_GetPathAndQuery(uri, NULL);
6568         ok(hr == E_POINTER, "Error: GetPathAndQuery returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
6569
6570         hr = IUri_GetQuery(uri, NULL);
6571         ok(hr == E_POINTER, "Error: GetQuery returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
6572
6573         hr = IUri_GetRawUri(uri, NULL);
6574         ok(hr == E_POINTER, "Error: GetRawUri returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
6575
6576         hr = IUri_GetSchemeName(uri, NULL);
6577         ok(hr == E_POINTER, "Error: GetSchemeName returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
6578
6579         hr = IUri_GetUserInfo(uri, NULL);
6580         ok(hr == E_POINTER, "Error: GetUserInfo returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
6581
6582         hr = IUri_GetUserName(uri, NULL);
6583         ok(hr == E_POINTER, "Error: GetUserName returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
6584     }
6585     if(uri) IUri_Release(uri);
6586
6587     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
6588         uri_properties test = uri_tests[i];
6589         LPWSTR uriW;
6590         uri = NULL;
6591
6592         uriW = a2w(test.uri);
6593         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
6594         if(test.create_todo) {
6595             todo_wine {
6596                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6597                         hr, test.create_expected, i);
6598             }
6599         } else {
6600             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6601                     hr, test.create_expected, i);
6602         }
6603
6604         if(SUCCEEDED(hr)) {
6605             uri_str_property prop;
6606             BSTR received = NULL;
6607
6608             /* GetAbsoluteUri() tests. */
6609             prop = test.str_props[Uri_PROPERTY_ABSOLUTE_URI];
6610             hr = IUri_GetAbsoluteUri(uri, &received);
6611             if(prop.todo) {
6612                 todo_wine {
6613                     ok(hr == prop.expected, "Error: GetAbsoluteUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6614                             hr, prop.expected, i);
6615                 }
6616                 todo_wine {
6617                     ok(!strcmp_aw(prop.value, received) || broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
6618                             "Error: Expected %s but got %s on uri_tests[%d].\n",
6619                             prop.value, wine_dbgstr_w(received), i);
6620                 }
6621             } else {
6622                 ok(hr == prop.expected, "Error: GetAbsoluteUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6623                         hr, prop.expected, i);
6624                 ok(!strcmp_aw(prop.value, received) || broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
6625                         "Error: Expected %s but got %s on uri_tests[%d].\n",
6626                         prop.value, wine_dbgstr_w(received), i);
6627             }
6628             SysFreeString(received);
6629             received = NULL;
6630
6631             /* GetAuthority() tests. */
6632             prop = test.str_props[Uri_PROPERTY_AUTHORITY];
6633             hr = IUri_GetAuthority(uri, &received);
6634             if(prop.todo) {
6635                 todo_wine {
6636                     ok(hr == prop.expected, "Error: GetAuthority returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6637                             hr, prop.expected, i);
6638                 }
6639                 todo_wine {
6640                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6641                             prop.value, wine_dbgstr_w(received), i);
6642                 }
6643             } else {
6644                 ok(hr == prop.expected, "Error: GetAuthority returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6645                         hr, prop.expected, i);
6646                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6647                         prop.value, wine_dbgstr_w(received), i);
6648             }
6649             SysFreeString(received);
6650             received = NULL;
6651
6652             /* GetDisplayUri() tests. */
6653             prop = test.str_props[Uri_PROPERTY_DISPLAY_URI];
6654             hr = IUri_GetDisplayUri(uri, &received);
6655             if(prop.todo) {
6656                 todo_wine {
6657                     ok(hr == prop.expected, "Error: GetDisplayUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6658                             hr, prop.expected, i);
6659                 }
6660                 todo_wine {
6661                     ok(!strcmp_aw(prop.value, received) || broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
6662                             "Error: Expected %s but got %s on uri_test[%d].\n",
6663                             prop.value, wine_dbgstr_w(received), i);
6664                 }
6665             } else {
6666                 ok(hr == prop.expected, "Error: GetDisplayUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6667                         hr, prop.expected, i);
6668                 ok(!strcmp_aw(prop.value, received) || broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
6669                         "Error: Expected %s but got %s on uri_tests[%d].\n",
6670                         prop.value, wine_dbgstr_w(received), i);
6671             }
6672             SysFreeString(received);
6673             received = NULL;
6674
6675             /* GetDomain() tests. */
6676             prop = test.str_props[Uri_PROPERTY_DOMAIN];
6677             hr = IUri_GetDomain(uri, &received);
6678             if(prop.todo) {
6679                 todo_wine {
6680                     ok(hr == prop.expected, "Error: GetDomain returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6681                             hr, prop.expected, i);
6682                 }
6683                 todo_wine {
6684                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6685                             prop.value, wine_dbgstr_w(received), i);
6686                 }
6687             } else {
6688                 ok(hr == prop.expected, "Error: GetDomain returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6689                         hr, prop.expected, i);
6690                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6691                         prop.value, wine_dbgstr_w(received), i);
6692             }
6693             SysFreeString(received);
6694             received = NULL;
6695
6696             /* GetExtension() tests. */
6697             prop = test.str_props[Uri_PROPERTY_EXTENSION];
6698             hr = IUri_GetExtension(uri, &received);
6699             if(prop.todo) {
6700                 todo_wine {
6701                     ok(hr == prop.expected, "Error: GetExtension returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6702                             hr, prop.expected, i);
6703                 }
6704                 todo_wine {
6705                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6706                             prop.value, wine_dbgstr_w(received), i);
6707                 }
6708             } else {
6709                 ok(hr == prop.expected, "Error: GetExtension returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6710                         hr, prop.expected, i);
6711                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6712                         prop.value, wine_dbgstr_w(received), i);
6713             }
6714             SysFreeString(received);
6715             received = NULL;
6716
6717             /* GetFragment() tests. */
6718             prop = test.str_props[Uri_PROPERTY_FRAGMENT];
6719             hr = IUri_GetFragment(uri, &received);
6720             if(prop.todo) {
6721                 todo_wine {
6722                     ok(hr == prop.expected, "Error: GetFragment returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6723                             hr, prop.expected, i);
6724                 }
6725                 todo_wine {
6726                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6727                             prop.value, wine_dbgstr_w(received), i);
6728                 }
6729             } else {
6730                 ok(hr == prop.expected, "Error: GetFragment returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6731                         hr, prop.expected, i);
6732                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6733                         prop.value, wine_dbgstr_w(received), i);
6734             }
6735             SysFreeString(received);
6736             received = NULL;
6737
6738             /* GetHost() tests. */
6739             prop = test.str_props[Uri_PROPERTY_HOST];
6740             hr = IUri_GetHost(uri, &received);
6741             if(prop.todo) {
6742                 todo_wine {
6743                     ok(hr == prop.expected, "Error: GetHost returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6744                             hr, prop.expected, i);
6745                 }
6746                 todo_wine {
6747                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6748                             prop.value, wine_dbgstr_w(received), i);
6749                 }
6750             } else {
6751                 ok(hr == prop.expected, "Error: GetHost returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6752                         hr, prop.expected, i);
6753                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6754                         prop.value, wine_dbgstr_w(received), i);
6755             }
6756             SysFreeString(received);
6757             received = NULL;
6758
6759             /* GetPassword() tests. */
6760             prop = test.str_props[Uri_PROPERTY_PASSWORD];
6761             hr = IUri_GetPassword(uri, &received);
6762             if(prop.todo) {
6763                 todo_wine {
6764                     ok(hr == prop.expected, "Error: GetPassword returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6765                             hr, prop.expected, i);
6766                 }
6767                 todo_wine {
6768                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6769                             prop.value, wine_dbgstr_w(received), i);
6770                 }
6771             } else {
6772                 ok(hr == prop.expected, "Error: GetPassword returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6773                         hr, prop.expected, i);
6774                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6775                         prop.value, wine_dbgstr_w(received), i);
6776             }
6777             SysFreeString(received);
6778             received = NULL;
6779
6780             /* GetPath() tests. */
6781             prop = test.str_props[Uri_PROPERTY_PATH];
6782             hr = IUri_GetPath(uri, &received);
6783             if(prop.todo) {
6784                 todo_wine {
6785                     ok(hr == prop.expected, "Error: GetPath returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6786                             hr, prop.expected, i);
6787                 }
6788                 todo_wine {
6789                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6790                             prop.value, wine_dbgstr_w(received), i);
6791                 }
6792             } else {
6793                 ok(hr == prop.expected, "Error: GetPath returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6794                         hr, prop.expected, i);
6795                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6796                         prop.value, wine_dbgstr_w(received), i);
6797             }
6798             SysFreeString(received);
6799             received = NULL;
6800
6801             /* GetPathAndQuery() tests. */
6802             prop = test.str_props[Uri_PROPERTY_PATH_AND_QUERY];
6803             hr = IUri_GetPathAndQuery(uri, &received);
6804             if(prop.todo) {
6805                 todo_wine {
6806                     ok(hr == prop.expected, "Error: GetPathAndQuery returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6807                             hr, prop.expected, i);
6808                 }
6809                 todo_wine {
6810                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6811                             prop.value, wine_dbgstr_w(received), i);
6812                 }
6813             } else {
6814                 ok(hr == prop.expected, "Error: GetPathAndQuery returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6815                         hr, prop.expected, i);
6816                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6817                         prop.value, wine_dbgstr_w(received), i);
6818             }
6819             SysFreeString(received);
6820             received = NULL;
6821
6822             /* GetQuery() tests. */
6823             prop = test.str_props[Uri_PROPERTY_QUERY];
6824             hr = IUri_GetQuery(uri, &received);
6825             if(prop.todo) {
6826                 todo_wine {
6827                     ok(hr == prop.expected, "Error: GetQuery returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6828                             hr, prop.expected, i);
6829                 }
6830                 todo_wine {
6831                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6832                             prop.value, wine_dbgstr_w(received), i);
6833                 }
6834             } else {
6835                 ok(hr == prop.expected, "Error: GetQuery returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6836                         hr, prop.expected, i);
6837                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6838                         prop.value, wine_dbgstr_w(received), i);
6839             }
6840             SysFreeString(received);
6841             received = NULL;
6842
6843             /* GetRawUri() tests. */
6844             prop = test.str_props[Uri_PROPERTY_RAW_URI];
6845             hr = IUri_GetRawUri(uri, &received);
6846             if(prop.todo) {
6847                 todo_wine {
6848                     ok(hr == prop.expected, "Error: GetRawUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6849                             hr, prop.expected, i);
6850                 }
6851                 todo_wine {
6852                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6853                             prop.value, wine_dbgstr_w(received), i);
6854                 }
6855             } else {
6856                 ok(hr == prop.expected, "Error: GetRawUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6857                         hr, prop.expected, i);
6858                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6859                         prop.value, wine_dbgstr_w(received), i);
6860             }
6861             SysFreeString(received);
6862             received = NULL;
6863
6864             /* GetSchemeName() tests. */
6865             prop = test.str_props[Uri_PROPERTY_SCHEME_NAME];
6866             hr = IUri_GetSchemeName(uri, &received);
6867             if(prop.todo) {
6868                 todo_wine {
6869                     ok(hr == prop.expected, "Error: GetSchemeName returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6870                             hr, prop.expected, i);
6871                 }
6872                 todo_wine {
6873                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6874                             prop.value, wine_dbgstr_w(received), i);
6875                 }
6876             } else {
6877                 ok(hr == prop.expected, "Error: GetSchemeName returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6878                         hr, prop.expected, i);
6879                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6880                         prop.value, wine_dbgstr_w(received), i);
6881             }
6882             SysFreeString(received);
6883             received = NULL;
6884
6885             /* GetUserInfo() tests. */
6886             prop = test.str_props[Uri_PROPERTY_USER_INFO];
6887             hr = IUri_GetUserInfo(uri, &received);
6888             if(prop.todo) {
6889                 todo_wine {
6890                     ok(hr == prop.expected, "Error: GetUserInfo returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6891                             hr, prop.expected, i);
6892                 }
6893                 todo_wine {
6894                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6895                             prop.value, wine_dbgstr_w(received), i);
6896                 }
6897             } else {
6898                 ok(hr == prop.expected, "Error: GetUserInfo returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6899                         hr, prop.expected, i);
6900                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6901                         prop.value, wine_dbgstr_w(received), i);
6902             }
6903             SysFreeString(received);
6904             received = NULL;
6905
6906             /* GetUserName() tests. */
6907             prop = test.str_props[Uri_PROPERTY_USER_NAME];
6908             hr = IUri_GetUserName(uri, &received);
6909             if(prop.todo) {
6910                 todo_wine {
6911                     ok(hr == prop.expected, "Error: GetUserName returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6912                             hr, prop.expected, i);
6913                 }
6914                 todo_wine {
6915                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6916                             prop.value, wine_dbgstr_w(received), i);
6917                 }
6918             } else {
6919                 ok(hr == prop.expected, "Error: GetUserName returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6920                         hr, prop.expected, i);
6921                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6922                         prop.value, wine_dbgstr_w(received), i);
6923             }
6924             SysFreeString(received);
6925         }
6926
6927         if(uri) IUri_Release(uri);
6928
6929         heap_free(uriW);
6930     }
6931 }
6932
6933 static void test_IUri_GetDwordProperties(void) {
6934     IUri *uri = NULL;
6935     HRESULT hr;
6936     DWORD i;
6937
6938     /* Make sure all the 'Get*' dword property functions handle invalid args correctly. */
6939     hr = pCreateUri(http_urlW, 0, 0, &uri);
6940     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
6941     if(SUCCEEDED(hr)) {
6942         hr = IUri_GetHostType(uri, NULL);
6943         ok(hr == E_INVALIDARG, "Error: GetHostType returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
6944
6945         hr = IUri_GetPort(uri, NULL);
6946         ok(hr == E_INVALIDARG, "Error: GetPort returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
6947
6948         hr = IUri_GetScheme(uri, NULL);
6949         ok(hr == E_INVALIDARG, "Error: GetScheme returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
6950
6951         hr = IUri_GetZone(uri, NULL);
6952         ok(hr == E_INVALIDARG, "Error: GetZone returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
6953     }
6954     if(uri) IUri_Release(uri);
6955
6956     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
6957         uri_properties test = uri_tests[i];
6958         LPWSTR uriW;
6959         uri = NULL;
6960
6961         uriW = a2w(test.uri);
6962         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
6963         if(test.create_todo) {
6964             todo_wine {
6965                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6966                         hr, test.create_expected, i);
6967             }
6968         } else {
6969             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6970                     hr, test.create_expected, i);
6971         }
6972
6973         if(SUCCEEDED(hr)) {
6974             uri_dword_property prop;
6975             DWORD received;
6976
6977             /* Assign an insane value so tests don't accidentally pass when
6978              * they shouldn't!
6979              */
6980             received = -9999999;
6981
6982             /* GetHostType() tests. */
6983             prop = test.dword_props[Uri_PROPERTY_HOST_TYPE-Uri_PROPERTY_DWORD_START];
6984             hr = IUri_GetHostType(uri, &received);
6985             if(prop.todo) {
6986                 todo_wine {
6987                     ok(hr == prop.expected, "Error: GetHostType returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6988                             hr, prop.expected, i);
6989                 }
6990                 todo_wine {
6991                     ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
6992                 }
6993             } else {
6994                 ok(hr == prop.expected, "Error: GetHostType returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6995                         hr, prop.expected, i);
6996                 ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
6997             }
6998             received = -9999999;
6999
7000             /* GetPort() tests. */
7001             prop = test.dword_props[Uri_PROPERTY_PORT-Uri_PROPERTY_DWORD_START];
7002             hr = IUri_GetPort(uri, &received);
7003             if(prop.todo) {
7004                 todo_wine {
7005                     ok(hr == prop.expected, "Error: GetPort returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7006                             hr, prop.expected, i);
7007                 }
7008                 todo_wine {
7009                     ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
7010                 }
7011             } else {
7012                 ok(hr == prop.expected, "Error: GetPort returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7013                         hr, prop.expected, i);
7014                 ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
7015             }
7016             received = -9999999;
7017
7018             /* GetScheme() tests. */
7019             prop = test.dword_props[Uri_PROPERTY_SCHEME-Uri_PROPERTY_DWORD_START];
7020             hr = IUri_GetScheme(uri, &received);
7021             if(prop.todo) {
7022                 todo_wine {
7023                     ok(hr == prop.expected, "Error: GetScheme returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7024                             hr, prop.expected, i);
7025                 }
7026                 todo_wine {
7027                     ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
7028                 }
7029             } else {
7030                 ok(hr == prop.expected, "Error: GetScheme returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7031                         hr, prop.expected, i);
7032                 ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
7033             }
7034             received = -9999999;
7035
7036             /* GetZone() tests. */
7037             prop = test.dword_props[Uri_PROPERTY_ZONE-Uri_PROPERTY_DWORD_START];
7038             hr = IUri_GetZone(uri, &received);
7039             if(prop.todo) {
7040                 todo_wine {
7041                     ok(hr == prop.expected, "Error: GetZone returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7042                             hr, prop.expected, i);
7043                 }
7044                 todo_wine {
7045                     ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
7046                 }
7047             } else {
7048                 ok(hr == prop.expected, "Error: GetZone returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7049                         hr, prop.expected, i);
7050                 ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
7051             }
7052         }
7053
7054         if(uri) IUri_Release(uri);
7055
7056         heap_free(uriW);
7057     }
7058 }
7059
7060 static void test_IUri_GetPropertyLength(void) {
7061     IUri *uri = NULL;
7062     HRESULT hr;
7063     DWORD i;
7064
7065     /* Make sure it handles invalid args correctly. */
7066     hr = pCreateUri(http_urlW, 0, 0, &uri);
7067     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7068     if(SUCCEEDED(hr)) {
7069         DWORD received = 0xdeadbeef;
7070
7071         hr = IUri_GetPropertyLength(uri, Uri_PROPERTY_STRING_START, NULL, 0);
7072         ok(hr == E_INVALIDARG, "Error: GetPropertyLength returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
7073
7074         hr = IUri_GetPropertyLength(uri, Uri_PROPERTY_DWORD_START, &received, 0);
7075         ok(hr == E_INVALIDARG, "Error: GetPropertyLength return 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
7076         ok(received == 0xdeadbeef, "Error: Expected 0xdeadbeef but got 0x%08x.\n", received);
7077     }
7078     if(uri) IUri_Release(uri);
7079
7080     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
7081         uri_properties test = uri_tests[i];
7082         LPWSTR uriW;
7083         uri = NULL;
7084
7085         uriW = a2w(test.uri);
7086         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
7087         if(test.create_todo) {
7088             todo_wine {
7089                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7090                         hr, test.create_expected, i);
7091             }
7092         } else {
7093             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_test[%d].\n",
7094                     hr, test.create_expected, i);
7095         }
7096
7097         if(SUCCEEDED(hr)) {
7098             DWORD j;
7099
7100             for(j = Uri_PROPERTY_STRING_START; j <= Uri_PROPERTY_STRING_LAST; ++j) {
7101                 DWORD expectedLen, brokenLen, receivedLen;
7102                 uri_str_property prop = test.str_props[j];
7103
7104                 expectedLen = lstrlen(prop.value);
7105                 brokenLen = lstrlen(prop.broken_value);
7106
7107                 /* This won't be necessary once GetPropertyLength is implemented. */
7108                 receivedLen = -1;
7109
7110                 hr = IUri_GetPropertyLength(uri, j, &receivedLen, 0);
7111                 if(prop.todo) {
7112                     todo_wine {
7113                         ok(hr == prop.expected, "Error: GetPropertyLength returned 0x%08x, expected 0x%08x on uri_tests[%d].str_props[%d].\n",
7114                                 hr, prop.expected, i, j);
7115                     }
7116                     todo_wine {
7117                         ok(receivedLen == expectedLen || broken(receivedLen == brokenLen),
7118                                 "Error: Expected a length of %d but got %d on uri_tests[%d].str_props[%d].\n",
7119                                 expectedLen, receivedLen, i, j);
7120                     }
7121                 } else {
7122                     ok(hr == prop.expected, "Error: GetPropertyLength returned 0x%08x, expected 0x%08x on uri_tests[%d].str_props[%d].\n",
7123                             hr, prop.expected, i, j);
7124                     ok(receivedLen == expectedLen || broken(receivedLen == brokenLen),
7125                             "Error: Expected a length of %d but got %d on uri_tests[%d].str_props[%d].\n",
7126                             expectedLen, receivedLen, i, j);
7127                 }
7128             }
7129         }
7130
7131         if(uri) IUri_Release(uri);
7132
7133         heap_free(uriW);
7134     }
7135 }
7136
7137 static DWORD compute_expected_props(uri_properties *test)
7138 {
7139     DWORD ret = 0, i;
7140
7141     for(i=Uri_PROPERTY_STRING_START; i <= Uri_PROPERTY_STRING_LAST; i++) {
7142         if(test->str_props[i-Uri_PROPERTY_STRING_START].expected == S_OK)
7143             ret |= 1<<i;
7144     }
7145
7146     for(i=Uri_PROPERTY_DWORD_START; i <= Uri_PROPERTY_DWORD_LAST; i++) {
7147         if(test->dword_props[i-Uri_PROPERTY_DWORD_START].expected == S_OK)
7148             ret |= 1<<i;
7149     }
7150
7151     return ret;
7152 }
7153
7154 static void test_IUri_GetProperties(void) {
7155     IUri *uri = NULL;
7156     HRESULT hr;
7157     DWORD i;
7158
7159     hr = pCreateUri(http_urlW, 0, 0, &uri);
7160     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7161     if(SUCCEEDED(hr)) {
7162         hr = IUri_GetProperties(uri, NULL);
7163         ok(hr == E_INVALIDARG, "Error: GetProperties returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
7164     }
7165     if(uri) IUri_Release(uri);
7166
7167     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
7168         uri_properties test = uri_tests[i];
7169         LPWSTR uriW;
7170         uri = NULL;
7171
7172         uriW = a2w(test.uri);
7173         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
7174         if(test.create_todo) {
7175             todo_wine {
7176                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, test.create_expected);
7177             }
7178         } else {
7179             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, test.create_expected);
7180         }
7181
7182         if(SUCCEEDED(hr)) {
7183             DWORD received = 0, expected_props;
7184             DWORD j;
7185
7186             hr = IUri_GetProperties(uri, &received);
7187             ok(hr == S_OK, "Error: GetProperties returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7188
7189             expected_props = compute_expected_props(&test);
7190
7191             for(j = 0; j <= Uri_PROPERTY_DWORD_LAST; ++j) {
7192                 /* (1 << j) converts a Uri_PROPERTY to its corresponding Uri_HAS_* flag mask. */
7193                 if(expected_props & (1 << j))
7194                     ok(received & (1 << j), "Error: Expected flag for property %d on uri_tests[%d].\n", j, i);
7195                 else
7196                     ok(!(received & (1 << j)), "Error: Received flag for property %d when not expected on uri_tests[%d].\n", j, i);
7197             }
7198         }
7199
7200         if(uri) IUri_Release(uri);
7201
7202         heap_free(uriW);
7203     }
7204 }
7205
7206 static void test_IUri_HasProperty(void) {
7207     IUri *uri = NULL;
7208     HRESULT hr;
7209     DWORD i;
7210
7211     hr = pCreateUri(http_urlW, 0, 0, &uri);
7212     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7213     if(SUCCEEDED(hr)) {
7214         hr = IUri_HasProperty(uri, Uri_PROPERTY_RAW_URI, NULL);
7215         ok(hr == E_INVALIDARG, "Error: HasProperty returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
7216     }
7217     if(uri) IUri_Release(uri);
7218
7219     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
7220         uri_properties test = uri_tests[i];
7221         LPWSTR uriW;
7222         uri = NULL;
7223
7224         uriW = a2w(test.uri);
7225
7226         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
7227         if(test.create_todo) {
7228             todo_wine {
7229                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, test.create_expected);
7230             }
7231         } else {
7232             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, test.create_expected);
7233         }
7234
7235         if(SUCCEEDED(hr)) {
7236             DWORD expected_props, j;
7237
7238             expected_props = compute_expected_props(&test);
7239
7240             for(j = 0; j <= Uri_PROPERTY_DWORD_LAST; ++j) {
7241                 /* Assign -1, then explicitly test for TRUE or FALSE later. */
7242                 BOOL received = -1;
7243
7244                 hr = IUri_HasProperty(uri, j, &received);
7245                 ok(hr == S_OK, "Error: HasProperty returned 0x%08x, expected 0x%08x for property %d on uri_tests[%d].\n",
7246                         hr, S_OK, j, i);
7247
7248                 if(expected_props & (1 << j)) {
7249                     ok(received == TRUE, "Error: Expected to have property %d on uri_tests[%d].\n", j, i);
7250                 } else {
7251                     ok(received == FALSE, "Error: Wasn't expecting to have property %d on uri_tests[%d].\n", j, i);
7252                 }
7253             }
7254         }
7255
7256         if(uri) IUri_Release(uri);
7257
7258         heap_free(uriW);
7259     }
7260 }
7261
7262 static void test_IUri_IsEqual(void) {
7263     IUri *uriA, *uriB;
7264     HRESULT hrA, hrB;
7265     DWORD i;
7266
7267     uriA = uriB = NULL;
7268
7269     /* Make sure IsEqual handles invalid args correctly. */
7270     hrA = pCreateUri(http_urlW, 0, 0, &uriA);
7271     hrB = pCreateUri(http_urlW, 0, 0, &uriB);
7272     ok(hrA == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hrA, S_OK);
7273     ok(hrB == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hrB, S_OK);
7274     if(SUCCEEDED(hrA) && SUCCEEDED(hrB)) {
7275         BOOL equal = -1;
7276         hrA = IUri_IsEqual(uriA, NULL, &equal);
7277         ok(hrA == S_OK, "Error: IsEqual returned 0x%08x, expected 0x%08x.\n", hrA, S_OK);
7278         ok(equal == FALSE, "Error: Expected equal to be FALSE, but was %d instead.\n", equal);
7279
7280         hrA = IUri_IsEqual(uriA, uriB, NULL);
7281         ok(hrA == E_POINTER, "Error: IsEqual returned 0x%08x, expected 0x%08x.\n", hrA, E_POINTER);
7282     }
7283     if(uriA) IUri_Release(uriA);
7284     if(uriB) IUri_Release(uriB);
7285
7286     for(i = 0; i < sizeof(equality_tests)/sizeof(equality_tests[0]); ++i) {
7287         uri_equality test = equality_tests[i];
7288         LPWSTR uriA_W, uriB_W;
7289
7290         uriA = uriB = NULL;
7291
7292         uriA_W = a2w(test.a);
7293         uriB_W = a2w(test.b);
7294
7295         hrA = pCreateUri(uriA_W, test.create_flags_a, 0, &uriA);
7296         if(test.create_todo_a) {
7297             todo_wine {
7298                 ok(hrA == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x on equality_tests[%d].a\n",
7299                         hrA, S_OK, i);
7300             }
7301         } else {
7302             ok(hrA == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x on equality_tests[%d].a\n",
7303                     hrA, S_OK, i);
7304         }
7305
7306         hrB = pCreateUri(uriB_W, test.create_flags_b, 0, &uriB);
7307         if(test.create_todo_b) {
7308             todo_wine {
7309                 ok(hrB == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x on equality_tests[%d].b\n",
7310                         hrB, S_OK, i);
7311             }
7312         } else {
7313             ok(hrB == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x on equality_tests[%d].b\n",
7314                     hrB, S_OK, i);
7315         }
7316
7317         if(SUCCEEDED(hrA) && SUCCEEDED(hrB)) {
7318             BOOL equal = -1;
7319
7320             hrA = IUri_IsEqual(uriA, uriB, &equal);
7321             if(test.todo) {
7322                 todo_wine {
7323                     ok(hrA == S_OK, "Error: IsEqual returned 0x%08x, expected 0x%08x on equality_tests[%d].\n",
7324                             hrA, S_OK, i);
7325                 }
7326                 todo_wine {
7327                     ok(equal == test.equal, "Error: Expected the comparison to be %d on equality_tests[%d].\n", test.equal, i);
7328                 }
7329             } else {
7330                 ok(hrA == S_OK, "Error: IsEqual returned 0x%08x, expected 0x%08x on equality_tests[%d].\n", hrA, S_OK, i);
7331                 ok(equal == test.equal, "Error: Expected the comparison to be %d on equality_tests[%d].\n", test.equal, i);
7332             }
7333         }
7334         if(uriA) IUri_Release(uriA);
7335         if(uriB) IUri_Release(uriB);
7336
7337         heap_free(uriA_W);
7338         heap_free(uriB_W);
7339     }
7340 }
7341
7342 static void test_CreateUriWithFragment_InvalidArgs(void) {
7343     HRESULT hr;
7344     IUri *uri = (void*) 0xdeadbeef;
7345     const WCHAR fragmentW[] = {'#','f','r','a','g','m','e','n','t',0};
7346
7347     hr = pCreateUriWithFragment(NULL, fragmentW, 0, 0, &uri);
7348     ok(hr == E_INVALIDARG, "Error: CreateUriWithFragment returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
7349     ok(uri == NULL, "Error: Expected uri to be NULL, but was %p instead.\n", uri);
7350
7351     hr = pCreateUriWithFragment(http_urlW, fragmentW, 0, 0, NULL);
7352     ok(hr == E_INVALIDARG, "Error: CreateUriWithFragment returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
7353
7354     /* Original URI can't already contain a fragment component. */
7355     uri = (void*) 0xdeadbeef;
7356     hr = pCreateUriWithFragment(http_url_fragW, fragmentW, 0, 0, &uri);
7357     ok(hr == E_INVALIDARG, "Error: CreateUriWithFragment returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
7358     ok(uri == NULL, "Error: Expected uri to be NULL, but was %p instead.\n", uri);
7359 }
7360
7361 /* CreateUriWithFragment has the same invalid flag combinations as CreateUri. */
7362 static void test_CreateUriWithFragment_InvalidFlags(void) {
7363     DWORD i;
7364
7365     for(i = 0; i < sizeof(invalid_flag_tests)/sizeof(invalid_flag_tests[0]); ++i) {
7366         HRESULT hr;
7367         IUri *uri = (void*) 0xdeadbeef;
7368
7369         hr = pCreateUriWithFragment(http_urlW, NULL, invalid_flag_tests[i].flags, 0, &uri);
7370         ok(hr == invalid_flag_tests[i].expected, "Error: CreateUriWithFragment returned 0x%08x, expected 0x%08x. flags=0x%08x.\n",
7371             hr, invalid_flag_tests[i].expected, invalid_flag_tests[i].flags);
7372         ok(uri == NULL, "Error: Expected uri to be NULL, but was %p instead.\n", uri);
7373     }
7374 }
7375
7376 static void test_CreateUriWithFragment(void) {
7377     DWORD i;
7378
7379     for(i = 0; i < sizeof(uri_fragment_tests)/sizeof(uri_fragment_tests[0]); ++i) {
7380         HRESULT hr;
7381         IUri *uri = NULL;
7382         LPWSTR uriW, fragW;
7383         uri_with_fragment test = uri_fragment_tests[i];
7384
7385         uriW = a2w(test.uri);
7386         fragW = a2w(test.fragment);
7387
7388         hr = pCreateUriWithFragment(uriW, fragW, test.create_flags, 0, &uri);
7389         if(test.expected_todo) {
7390             todo_wine {
7391                 ok(hr == test.create_expected,
7392                     "Error: CreateUriWithFragment returned 0x%08x, expected 0x%08x on uri_fragment_tests[%d].\n",
7393                     hr, test.create_expected, i);
7394             }
7395         } else
7396             ok(hr == test.create_expected,
7397                 "Error: CreateUriWithFragment returned 0x%08x, expected 0x%08x on uri_fragment_tests[%d].\n",
7398                 hr, test.create_expected, i);
7399
7400         if(SUCCEEDED(hr)) {
7401             BSTR received = NULL;
7402
7403             hr = IUri_GetAbsoluteUri(uri, &received);
7404             if(test.expected_todo) {
7405                 todo_wine {
7406                     ok(hr == S_OK,
7407                         "Error: GetAbsoluteUri returned 0x%08x, expected 0x%08x on uri_fragment_tests[%d].\n",
7408                         hr, S_OK, i);
7409                 }
7410                 todo_wine {
7411                     ok(!strcmp_aw(test.expected_uri, received),
7412                         "Error: Expected %s but got %s on uri_fragment_tests[%d].\n",
7413                         test.expected_uri, wine_dbgstr_w(received), i);
7414                 }
7415             } else {
7416                 ok(hr == S_OK, "Error: GetAbsoluteUri returned 0x%08x, expected 0x%08x on uri_fragment_tests[%d].\n",
7417                     hr, S_OK, i);
7418                 ok(!strcmp_aw(test.expected_uri, received), "Error: Expected %s but got %s on uri_fragment_tests[%d].\n",
7419                     test.expected_uri, wine_dbgstr_w(received), i);
7420             }
7421
7422             SysFreeString(received);
7423         }
7424
7425         if(uri) IUri_Release(uri);
7426         heap_free(uriW);
7427         heap_free(fragW);
7428     }
7429 }
7430
7431 static void test_CreateIUriBuilder(void) {
7432     HRESULT hr;
7433     IUriBuilder *builder = NULL;
7434     IUri *uri;
7435
7436     hr = pCreateIUriBuilder(NULL, 0, 0, NULL);
7437     ok(hr == E_POINTER, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x\n",
7438         hr, E_POINTER);
7439
7440     /* CreateIUriBuilder increases the ref count of the IUri it receives. */
7441     hr = pCreateUri(http_urlW, 0, 0, &uri);
7442     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7443     if(SUCCEEDED(hr)) {
7444         ULONG cur_count, orig_count;
7445
7446         orig_count = get_refcnt(uri);
7447         hr = pCreateIUriBuilder(uri, 0, 0, &builder);
7448         ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7449         ok(builder != NULL, "Error: Expecting builder not to be NULL\n");
7450
7451         cur_count = get_refcnt(uri);
7452         ok(cur_count == orig_count+1, "Error: Expected the ref count to be %u, but was %u instead.\n", orig_count+1, cur_count);
7453
7454         if(builder) IUriBuilder_Release(builder);
7455         cur_count = get_refcnt(uri);
7456         ok(cur_count == orig_count, "Error: Expected the ref count to be %u, but was %u instead.\n", orig_count, cur_count);
7457     }
7458     if(uri) IUri_Release(uri);
7459 }
7460
7461 static void test_IUriBuilder_CreateUri(IUriBuilder *builder, const uri_builder_test *test,
7462                                        DWORD test_index) {
7463     HRESULT hr;
7464     IUri *uri = NULL;
7465
7466     hr = IUriBuilder_CreateUri(builder, test->uri_flags, 0, 0, &uri);
7467     if(test->uri_todo) {
7468         todo_wine {
7469             ok(hr == test->uri_hres,
7470                 "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7471                 hr, test->uri_hres, test_index);
7472         }
7473     } else {
7474         ok(hr == test->uri_hres,
7475             "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7476             hr, test->uri_hres, test_index);
7477     }
7478
7479     if(SUCCEEDED(hr)) {
7480         DWORD i;
7481
7482         for(i = 0; i < sizeof(test->expected_str_props)/sizeof(test->expected_str_props[0]); ++i) {
7483             uri_builder_str_property prop = test->expected_str_props[i];
7484             BSTR received = NULL;
7485
7486             hr = IUri_GetPropertyBSTR(uri, i, &received, 0);
7487             if(prop.todo) {
7488                 todo_wine {
7489                     ok(hr == prop.result,
7490                         "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_str_props[%d].\n",
7491                         hr, prop.result, test_index, i);
7492                 }
7493             } else {
7494                 ok(hr == prop.result,
7495                     "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_str_props[%d].\n",
7496                     hr, prop.result, test_index, i);
7497             }
7498             if(SUCCEEDED(hr)) {
7499                 if(prop.todo) {
7500                     todo_wine {
7501                         ok(!strcmp_aw(prop.expected, received),
7502                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].expected_str_props[%d].\n",
7503                             prop.expected, wine_dbgstr_w(received), test_index, i);
7504                     }
7505                 } else {
7506                     ok(!strcmp_aw(prop.expected, received),
7507                         "Error: Expected %s but got %s instead on uri_builder_tests[%d].expected_str_props[%d].\n",
7508                         prop.expected, wine_dbgstr_w(received), test_index, i);
7509                 }
7510             }
7511             SysFreeString(received);
7512         }
7513
7514         for(i = 0; i < sizeof(test->expected_dword_props)/sizeof(test->expected_dword_props[0]); ++i) {
7515             uri_builder_dword_property prop = test->expected_dword_props[i];
7516             DWORD received = -2;
7517
7518             hr = IUri_GetPropertyDWORD(uri, i+Uri_PROPERTY_DWORD_START, &received, 0);
7519             if(prop.todo) {
7520                 todo_wine {
7521                     ok(hr == prop.result,
7522                         "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_dword_props[%d].\n",
7523                         hr, prop.result, test_index, i);
7524                 }
7525             } else {
7526                 ok(hr == prop.result,
7527                     "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_dword_props[%d].\n",
7528                     hr, prop.result, test_index, i);
7529             }
7530             if(SUCCEEDED(hr)) {
7531                 if(prop.todo) {
7532                     todo_wine {
7533                         ok(received == prop.expected,
7534                             "Error: Expected %d but got %d instead on uri_builder_tests[%d].expected_dword_props[%d].\n",
7535                             prop.expected, received, test_index, i);
7536                     }
7537                 } else {
7538                     ok(received == prop.expected,
7539                         "Error: Expected %d but got %d instead on uri_builder_tests[%d].expected_dword_props[%d].\n",
7540                         prop.expected, received, test_index, i);
7541                 }
7542             }
7543         }
7544     }
7545     if(uri) IUri_Release(uri);
7546 }
7547
7548 static void test_IUriBuilder_CreateUriSimple(IUriBuilder *builder, const uri_builder_test *test,
7549                                        DWORD test_index) {
7550     HRESULT hr;
7551     IUri *uri = NULL;
7552
7553     hr = IUriBuilder_CreateUriSimple(builder, test->uri_simple_encode_flags, 0, &uri);
7554     if(test->uri_simple_todo) {
7555         todo_wine {
7556             ok(hr == test->uri_simple_hres,
7557                 "Error: IUriBuilder_CreateUriSimple returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7558                 hr, test->uri_simple_hres, test_index);
7559         }
7560     } else {
7561         ok(hr == test->uri_simple_hres,
7562             "Error: IUriBuilder_CreateUriSimple returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7563             hr, test->uri_simple_hres, test_index);
7564     }
7565
7566     if(SUCCEEDED(hr)) {
7567         DWORD i;
7568
7569         for(i = 0; i < sizeof(test->expected_str_props)/sizeof(test->expected_str_props[0]); ++i) {
7570             uri_builder_str_property prop = test->expected_str_props[i];
7571             BSTR received = NULL;
7572
7573             hr = IUri_GetPropertyBSTR(uri, i, &received, 0);
7574             if(prop.todo) {
7575                 todo_wine {
7576                     ok(hr == prop.result,
7577                         "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_str_props[%d].\n",
7578                         hr, prop.result, test_index, i);
7579                 }
7580             } else {
7581                 ok(hr == prop.result,
7582                     "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_str_props[%d].\n",
7583                     hr, prop.result, test_index, i);
7584             }
7585             if(SUCCEEDED(hr)) {
7586                 if(prop.todo) {
7587                     todo_wine {
7588                         ok(!strcmp_aw(prop.expected, received),
7589                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].expected_str_props[%d].\n",
7590                             prop.expected, wine_dbgstr_w(received), test_index, i);
7591                     }
7592                 } else {
7593                     ok(!strcmp_aw(prop.expected, received),
7594                         "Error: Expected %s but got %s instead on uri_builder_tests[%d].expected_str_props[%d].\n",
7595                         prop.expected, wine_dbgstr_w(received), test_index, i);
7596                 }
7597             }
7598             SysFreeString(received);
7599         }
7600
7601         for(i = 0; i < sizeof(test->expected_dword_props)/sizeof(test->expected_dword_props[0]); ++i) {
7602             uri_builder_dword_property prop = test->expected_dword_props[i];
7603             DWORD received = -2;
7604
7605             hr = IUri_GetPropertyDWORD(uri, i+Uri_PROPERTY_DWORD_START, &received, 0);
7606             if(prop.todo) {
7607                 todo_wine {
7608                     ok(hr == prop.result,
7609                         "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_dword_props[%d].\n",
7610                         hr, prop.result, test_index, i);
7611                 }
7612             } else {
7613                 ok(hr == prop.result,
7614                     "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_dword_props[%d].\n",
7615                     hr, prop.result, test_index, i);
7616             }
7617             if(SUCCEEDED(hr)) {
7618                 if(prop.todo) {
7619                     todo_wine {
7620                         ok(received == prop.expected,
7621                             "Error: Expected %d but got %d instead on uri_builder_tests[%d].expected_dword_props[%d].\n",
7622                             prop.expected, received, test_index, i);
7623                     }
7624                 } else {
7625                     ok(received == prop.expected,
7626                         "Error: Expected %d but got %d instead on uri_builder_tests[%d].expected_dword_props[%d].\n",
7627                         prop.expected, received, test_index, i);
7628                 }
7629             }
7630         }
7631     }
7632     if(uri) IUri_Release(uri);
7633 }
7634
7635 static void test_IUriBuilder_CreateUriWithFlags(IUriBuilder *builder, const uri_builder_test *test,
7636                                                 DWORD test_index) {
7637     HRESULT hr;
7638     IUri *uri = NULL;
7639
7640     hr = IUriBuilder_CreateUriWithFlags(builder, test->uri_with_flags, test->uri_with_builder_flags,
7641                                         test->uri_with_encode_flags, 0, &uri);
7642     if(test->uri_with_todo) {
7643         todo_wine {
7644             ok(hr == test->uri_with_hres,
7645                 "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7646                 hr, test->uri_with_hres, test_index);
7647         }
7648     } else {
7649         ok(hr == test->uri_with_hres,
7650             "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7651             hr, test->uri_with_hres, test_index);
7652     }
7653
7654     if(SUCCEEDED(hr)) {
7655         DWORD i;
7656
7657         for(i = 0; i < sizeof(test->expected_str_props)/sizeof(test->expected_str_props[0]); ++i) {
7658             uri_builder_str_property prop = test->expected_str_props[i];
7659             BSTR received = NULL;
7660
7661             hr = IUri_GetPropertyBSTR(uri, i, &received, 0);
7662             if(prop.todo) {
7663                 todo_wine {
7664                     ok(hr == prop.result,
7665                         "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_str_props[%d].\n",
7666                         hr, prop.result, test_index, i);
7667                 }
7668             } else {
7669                 ok(hr == prop.result,
7670                     "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_str_props[%d].\n",
7671                     hr, prop.result, test_index, i);
7672             }
7673             if(SUCCEEDED(hr)) {
7674                 if(prop.todo) {
7675                     todo_wine {
7676                         ok(!strcmp_aw(prop.expected, received),
7677                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].expected_str_props[%d].\n",
7678                             prop.expected, wine_dbgstr_w(received), test_index, i);
7679                     }
7680                 } else {
7681                     ok(!strcmp_aw(prop.expected, received),
7682                         "Error: Expected %s but got %s instead on uri_builder_tests[%d].expected_str_props[%d].\n",
7683                         prop.expected, wine_dbgstr_w(received), test_index, i);
7684                 }
7685             }
7686             SysFreeString(received);
7687         }
7688
7689         for(i = 0; i < sizeof(test->expected_dword_props)/sizeof(test->expected_dword_props[0]); ++i) {
7690             uri_builder_dword_property prop = test->expected_dword_props[i];
7691             DWORD received = -2;
7692
7693             hr = IUri_GetPropertyDWORD(uri, i+Uri_PROPERTY_DWORD_START, &received, 0);
7694             if(prop.todo) {
7695                 todo_wine {
7696                     ok(hr == prop.result,
7697                         "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_dword_props[%d].\n",
7698                         hr, prop.result, test_index, i);
7699                 }
7700             } else {
7701                 ok(hr == prop.result,
7702                     "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_dword_props[%d].\n",
7703                     hr, prop.result, test_index, i);
7704             }
7705             if(SUCCEEDED(hr)) {
7706                 if(prop.todo) {
7707                     todo_wine {
7708                         ok(received == prop.expected,
7709                             "Error: Expected %d but got %d instead on uri_builder_tests[%d].expected_dword_props[%d].\n",
7710                             prop.expected, received, test_index, i);
7711                     }
7712                 } else {
7713                     ok(received == prop.expected,
7714                         "Error: Expected %d but got %d instead on uri_builder_tests[%d].expected_dword_props[%d].\n",
7715                         prop.expected, received, test_index, i);
7716                 }
7717             }
7718         }
7719     }
7720     if(uri) IUri_Release(uri);
7721 }
7722
7723 static void test_IUriBuilder_CreateInvalidArgs(void) {
7724     IUriBuilder *builder;
7725     HRESULT hr;
7726
7727     hr = pCreateIUriBuilder(NULL, 0, 0, &builder);
7728     ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7729     if(SUCCEEDED(hr)) {
7730         IUri *test = NULL, *uri = (void*) 0xdeadbeef;
7731
7732         /* Test what happens if the IUriBuilder doesn't have a IUri set. */
7733         hr = IUriBuilder_CreateUri(builder, 0, 0, 0, NULL);
7734         ok(hr == E_POINTER, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
7735
7736         uri = (void*) 0xdeadbeef;
7737         hr = IUriBuilder_CreateUri(builder, 0, Uri_HAS_USER_NAME, 0, &uri);
7738         ok(hr == E_NOTIMPL, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, E_NOTIMPL);
7739         ok(uri == NULL, "Error: expected uri to be NULL, but was %p instead.\n", uri);
7740
7741         hr = IUriBuilder_CreateUriSimple(builder, 0, 0, NULL);
7742         ok(hr == E_POINTER, "Error: IUriBuilder_CreateUriSimple returned 0x%08x, expected 0x%08x.\n",
7743             hr, E_POINTER);
7744
7745         uri = (void*) 0xdeadbeef;
7746         hr = IUriBuilder_CreateUriSimple(builder, Uri_HAS_USER_NAME, 0, &uri);
7747         ok(hr == E_NOTIMPL, "Error: IUriBuilder_CreateUriSimple returned 0x%08x, expected 0x%08x.\n",
7748             hr, E_NOTIMPL);
7749         ok(!uri, "Error: Expected uri to NULL, but was %p instead.\n", uri);
7750
7751         hr = IUriBuilder_CreateUriWithFlags(builder, 0, 0, 0, 0, NULL);
7752         ok(hr == E_POINTER, "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x.\n",
7753             hr, E_POINTER);
7754
7755         uri = (void*) 0xdeadbeef;
7756         hr = IUriBuilder_CreateUriWithFlags(builder, 0, 0, Uri_HAS_USER_NAME, 0, &uri);
7757         ok(hr == E_NOTIMPL, "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x.\n",
7758             hr, E_NOTIMPL);
7759         ok(!uri, "Error: Expected uri to be NULL, but was %p instead.\n", uri);
7760
7761         hr = pCreateUri(http_urlW, 0, 0, &test);
7762         ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7763         if(SUCCEEDED(hr)) {
7764             hr = IUriBuilder_SetIUri(builder, test);
7765             ok(hr == S_OK, "Error: IUriBuilder_SetIUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7766
7767             /* No longer returns E_NOTIMPL, since a IUri has been set and hasn't been modified. */
7768             uri = NULL;
7769             hr = IUriBuilder_CreateUri(builder, 0, Uri_HAS_USER_NAME, 0, &uri);
7770             ok(hr == S_OK, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7771             ok(uri != NULL, "Error: The uri was NULL.\n");
7772             if(uri) IUri_Release(uri);
7773
7774             uri = NULL;
7775             hr = IUriBuilder_CreateUriSimple(builder, Uri_HAS_USER_NAME, 0, &uri);
7776             ok(hr == S_OK, "Error: IUriBuilder_CreateUriSimple returned 0x%08x, expected 0x%08x.\n",
7777                 hr, S_OK);
7778             ok(uri != NULL, "Error: uri was NULL.\n");
7779             if(uri) IUri_Release(uri);
7780
7781             uri = NULL;
7782             hr = IUriBuilder_CreateUriWithFlags(builder, 0, 0, 0, 0, &uri);
7783             ok(hr == S_OK, "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x.\n",
7784                 hr, S_OK);
7785             ok(uri != NULL, "Error: uri was NULL.\n");
7786             if(uri) IUri_Release(uri);
7787
7788             hr = IUriBuilder_SetFragment(builder, NULL);
7789             ok(hr == S_OK, "Error: IUriBuilder_SetFragment returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7790
7791             /* The IUriBuilder is changed, so it returns E_NOTIMPL again. */
7792             uri = (void*) 0xdeadbeef;
7793             hr = IUriBuilder_CreateUri(builder, 0, Uri_HAS_USER_NAME, 0, &uri);
7794             ok(hr == E_NOTIMPL, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7795             ok(!uri, "Error: Expected uri to be NULL but was %p instead.\n", uri);
7796
7797             uri = (void*) 0xdeadbeef;
7798             hr = IUriBuilder_CreateUriSimple(builder, Uri_HAS_USER_NAME, 0, &uri);
7799             ok(hr == E_NOTIMPL, "Error: IUriBuilder_CreateUriSimple returned 0x%08x, expected 0x%08x.\n",
7800                 hr, S_OK);
7801             ok(!uri, "Error: Expected uri to be NULL, but was %p instead.\n", uri);
7802
7803             uri = (void*) 0xdeadbeef;
7804             hr = IUriBuilder_CreateUriWithFlags(builder, 0, 0, Uri_HAS_USER_NAME, 0, &uri);
7805             ok(hr == E_NOTIMPL, "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x.\n",
7806                 hr, E_NOTIMPL);
7807             ok(!uri, "Error: Expected uri to be NULL, but was %p instead.\n", uri);
7808         }
7809         if(test) IUri_Release(test);
7810     }
7811     if(builder) IUriBuilder_Release(builder);
7812 }
7813
7814 /* Tests invalid args to the "Get*" functions. */
7815 static void test_IUriBuilder_GetInvalidArgs(void) {
7816     IUriBuilder *builder = NULL;
7817     HRESULT hr;
7818
7819     hr = pCreateIUriBuilder(NULL, 0, 0, &builder);
7820     ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7821     if(SUCCEEDED(hr)) {
7822         LPCWSTR received = (void*) 0xdeadbeef;
7823         DWORD len = -1, port = -1;
7824         BOOL set = -1;
7825
7826         hr = IUriBuilder_GetFragment(builder, NULL, NULL);
7827         ok(hr == E_POINTER, "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x.\n",
7828             hr, E_POINTER);
7829         hr = IUriBuilder_GetFragment(builder, NULL, &received);
7830         ok(hr == E_POINTER, "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x.\n",
7831             hr, E_POINTER);
7832         ok(!received, "Error: Expected received to be NULL, but was %p instead.\n", received);
7833         hr = IUriBuilder_GetFragment(builder, &len, NULL);
7834         ok(hr == E_POINTER, "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x.\n",
7835             hr, E_POINTER);
7836         ok(!len, "Error: Expected len to be 0, but was %d instead.\n", len);
7837
7838         hr = IUriBuilder_GetHost(builder, NULL, NULL);
7839         ok(hr == E_POINTER, "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x.\n",
7840             hr, E_POINTER);
7841         received = (void*) 0xdeadbeef;
7842         hr = IUriBuilder_GetHost(builder, NULL, &received);
7843         ok(hr == E_POINTER, "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x.\n",
7844             hr, E_POINTER);
7845         ok(!received, "Error: Expected received to be NULL, but was %p instead.\n", received);
7846         len = -1;
7847         hr = IUriBuilder_GetHost(builder, &len, NULL);
7848         ok(hr == E_POINTER, "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x.\n",
7849             hr, E_POINTER);
7850         ok(!len, "Error: Expected len to be 0, but was %d instead.\n", len);
7851
7852         hr = IUriBuilder_GetPassword(builder, NULL, NULL);
7853         ok(hr == E_POINTER, "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x.\n",
7854             hr, E_POINTER);
7855         received = (void*) 0xdeadbeef;
7856         hr = IUriBuilder_GetPassword(builder, NULL, &received);
7857         ok(hr == E_POINTER, "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x.\n",
7858             hr, E_POINTER);
7859         ok(!received, "Error: Expected received to be NULL, but was %p instead.\n", received);
7860         len = -1;
7861         hr = IUriBuilder_GetPassword(builder, &len, NULL);
7862         ok(hr == E_POINTER, "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x.\n",
7863             hr, E_POINTER);
7864         ok(!len, "Error: Expected len to be 0, but was %d instead.\n", len);
7865
7866         hr = IUriBuilder_GetPath(builder, NULL, NULL);
7867         ok(hr == E_POINTER, "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x.\n",
7868             hr, E_POINTER);
7869         received = (void*) 0xdeadbeef;
7870         hr = IUriBuilder_GetPath(builder, NULL, &received);
7871         ok(hr == E_POINTER, "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x.\n",
7872             hr, E_POINTER);
7873         ok(!received, "Error: Expected received to be NULL, but was %p instead.\n", received);
7874         len = -1;
7875         hr = IUriBuilder_GetPath(builder, &len, NULL);
7876         ok(hr == E_POINTER, "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x.\n",
7877             hr, E_POINTER);
7878         ok(!len, "Error: Expected len to be 0, but was %d instead.\n", len);
7879
7880         hr = IUriBuilder_GetPort(builder, NULL, NULL);
7881         ok(hr == E_POINTER, "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x.\n",
7882             hr, E_POINTER);
7883         hr = IUriBuilder_GetPort(builder, NULL, &port);
7884         ok(hr == E_POINTER, "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x.\n",
7885             hr, E_POINTER);
7886         ok(!port, "Error: Expected port to be 0, but was %d instead.\n", port);
7887         hr = IUriBuilder_GetPort(builder, &set, NULL);
7888         ok(hr == E_POINTER, "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x.\n",
7889             hr, E_POINTER);
7890         ok(!set, "Error: Expected set to be FALSE, but was %d instead.\n", set);
7891
7892         hr = IUriBuilder_GetQuery(builder, NULL, NULL);
7893         ok(hr == E_POINTER, "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x.\n",
7894             hr, E_POINTER);
7895         received = (void*) 0xdeadbeef;
7896         hr = IUriBuilder_GetQuery(builder, NULL, &received);
7897         ok(hr == E_POINTER, "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x.\n",
7898             hr, E_POINTER);
7899         ok(!received, "Error: Expected received to be NULL, but was %p instead.\n", received);
7900         len = -1;
7901         hr = IUriBuilder_GetQuery(builder, &len, NULL);
7902         ok(hr == E_POINTER, "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x.\n",
7903             hr, E_POINTER);
7904         ok(!len, "Error: Expected len to be 0, but was %d instead.\n", len);
7905
7906         hr = IUriBuilder_GetSchemeName(builder, NULL, NULL);
7907         ok(hr == E_POINTER, "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x.\n",
7908             hr, E_POINTER);
7909         received = (void*) 0xdeadbeef;
7910         hr = IUriBuilder_GetSchemeName(builder, NULL, &received);
7911         ok(hr == E_POINTER, "Error: IUriBuilder_GetSchemeName 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         len = -1;
7915         hr = IUriBuilder_GetSchemeName(builder, &len, NULL);
7916         ok(hr == E_POINTER, "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x.\n",
7917             hr, E_POINTER);
7918         ok(!len, "Error: Expected len to be 0, but was %d instead.\n", len);
7919
7920         hr = IUriBuilder_GetUserName(builder, NULL, NULL);
7921         ok(hr == E_POINTER, "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x.\n",
7922             hr, E_POINTER);
7923         received = (void*) 0xdeadbeef;
7924         hr = IUriBuilder_GetUserName(builder, NULL, &received);
7925         ok(hr == E_POINTER, "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x.\n",
7926             hr, E_POINTER);
7927         ok(!received, "Error: Expected received to be NULL, but was %p instead.\n", received);
7928         len = -1;
7929         hr = IUriBuilder_GetUserName(builder, &len, NULL);
7930         ok(hr == E_POINTER, "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x.\n",
7931             hr, E_POINTER);
7932         ok(!len, "Error: Expected len to be 0, but was %d instead.\n", len);
7933     }
7934     if(builder) IUriBuilder_Release(builder);
7935 }
7936
7937 static void test_IUriBuilder_GetFragment(IUriBuilder *builder, const uri_builder_test *test,
7938                                          DWORD test_index) {
7939     HRESULT hr;
7940     DWORD i;
7941     LPCWSTR received = NULL;
7942     DWORD len = -1;
7943     const uri_builder_property *prop = NULL;
7944
7945     /* Check if the property was set earlier. */
7946     for(i = 0; i < sizeof(test->properties)/sizeof(test->properties[0]); ++i) {
7947         if(test->properties[i].change && test->properties[i].property == Uri_PROPERTY_FRAGMENT)
7948             prop = &(test->properties[i]);
7949     }
7950
7951     if(prop) {
7952         /* Use expected_value unless it's NULL, then use value. */
7953         LPCSTR expected = prop->expected_value ? prop->expected_value : prop->value;
7954         hr = IUriBuilder_GetFragment(builder, &len, &received);
7955         if(prop->todo) {
7956             todo_wine {
7957                 ok(hr == (expected ? S_OK : S_FALSE),
7958                     "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7959                     hr, (expected ? S_OK : S_FALSE), test_index);
7960             }
7961             if(SUCCEEDED(hr)) {
7962                 todo_wine {
7963                     ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
7964                         expected, wine_dbgstr_w(received), test_index);
7965                 }
7966                 todo_wine {
7967                     ok(lstrlen(expected) == len,
7968                         "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
7969                         lstrlen(expected), len, test_index);
7970                 }
7971             }
7972         } else {
7973             ok(hr == (expected ? S_OK : S_FALSE),
7974                 "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7975                 hr, (expected ? S_OK : S_FALSE), test_index);
7976             ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
7977                 expected, wine_dbgstr_w(received), test_index);
7978             ok(lstrlen(expected) == len,
7979                 "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
7980                 lstrlen(expected), len, test_index);
7981         }
7982     } else {
7983         /* The property wasn't set earlier, so it should return whatever
7984          * the base IUri contains (if anything).
7985          */
7986         IUri *uri = NULL;
7987         hr = IUriBuilder_GetIUri(builder, &uri);
7988         ok(hr == S_OK,
7989             "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7990             hr, S_OK, test_index);
7991         if(SUCCEEDED(hr)) {
7992             if(!uri) {
7993                 received = (void*) 0xdeadbeef;
7994                 len = -1;
7995
7996                 hr = IUriBuilder_GetFragment(builder, &len, &received);
7997                 ok(hr == S_FALSE,
7998                     "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7999                     hr, S_FALSE, test_index);
8000                 if(SUCCEEDED(hr)) {
8001                     ok(!len, "Error: Expected len to be 0, but was %d instead on uri_builder_tests[%d].\n",
8002                         len, test_index);
8003                     ok(!received, "Error: Expected received to be NULL, but was %p instead on uri_builder_tests[%d].\n",
8004                         received, test_index);
8005                 }
8006             } else {
8007                 BOOL has_prop = FALSE;
8008                 BSTR expected = NULL;
8009
8010                 hr = IUri_GetFragment(uri, &expected);
8011                 ok(SUCCEEDED(hr),
8012                     "Error: Expected IUri_GetFragment to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
8013                     hr, test_index);
8014                 has_prop = hr == S_OK;
8015
8016                 hr = IUriBuilder_GetFragment(builder, &len, &received);
8017                 if(has_prop) {
8018                     ok(hr == S_OK,
8019                         "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8020                         hr, S_OK, test_index);
8021                     if(SUCCEEDED(hr)) {
8022                         ok(!lstrcmpW(expected, received),
8023                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].\n",
8024                             wine_dbgstr_w(expected), wine_dbgstr_w(received), test_index);
8025                         ok(lstrlenW(expected) == len,
8026                             "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8027                             lstrlenW(expected), len, test_index);
8028                     }
8029                 } else {
8030                     ok(hr == S_FALSE,
8031                         "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8032                         hr, S_FALSE, test_index);
8033                     if(SUCCEEDED(hr)) {
8034                         ok(!received, "Error: Expected received to be NULL on uri_builder_tests[%d].\n", test_index);
8035                         ok(!len, "Error: Expected the length to be 0, but was %d instead on uri_builder_tests[%d].\n",
8036                             len, test_index);
8037                     }
8038                 }
8039                 SysFreeString(expected);
8040             }
8041         }
8042         if(uri) IUri_Release(uri);
8043     }
8044 }
8045
8046 static void test_IUriBuilder_GetHost(IUriBuilder *builder, const uri_builder_test *test,
8047                                      DWORD test_index) {
8048     HRESULT hr;
8049     DWORD i;
8050     LPCWSTR received = NULL;
8051     DWORD len = -1;
8052     const uri_builder_property *prop = NULL;
8053
8054     /* Check if the property was set earlier. */
8055     for(i = 0; i < sizeof(test->properties)/sizeof(test->properties[0]); ++i) {
8056         if(test->properties[i].change && test->properties[i].property == Uri_PROPERTY_HOST)
8057             prop = &(test->properties[i]);
8058     }
8059
8060     if(prop) {
8061         /* Use expected_value unless it's NULL, then use value. */
8062         LPCSTR expected = prop->expected_value ? prop->expected_value : prop->value;
8063         hr = IUriBuilder_GetHost(builder, &len, &received);
8064         if(prop->todo) {
8065             todo_wine {
8066                 ok(hr == (expected ? S_OK : S_FALSE),
8067                     "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8068                     hr, (expected ? S_OK : S_FALSE), test_index);
8069             }
8070             if(SUCCEEDED(hr)) {
8071                 todo_wine {
8072                     ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
8073                         expected, wine_dbgstr_w(received), test_index);
8074                 }
8075                 todo_wine {
8076                     ok(lstrlen(expected) == len,
8077                         "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8078                         lstrlen(expected), len, test_index);
8079                 }
8080             }
8081         } else {
8082             ok(hr == (expected ? S_OK : S_FALSE),
8083                 "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8084                 hr, (expected ? S_OK : S_FALSE), test_index);
8085             ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
8086                 expected, wine_dbgstr_w(received), test_index);
8087             ok(lstrlen(expected) == len,
8088                 "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8089                 lstrlen(expected), len, test_index);
8090         }
8091     } else {
8092         /* The property wasn't set earlier, so it should return whatever
8093          * the base IUri contains (if anything).
8094          */
8095         IUri *uri = NULL;
8096         hr = IUriBuilder_GetIUri(builder, &uri);
8097         ok(hr == S_OK,
8098             "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8099             hr, S_OK, test_index);
8100         if(SUCCEEDED(hr)) {
8101             if(!uri) {
8102                 received = (void*) 0xdeadbeef;
8103                 len = -1;
8104
8105                 hr = IUriBuilder_GetHost(builder, &len, &received);
8106                 ok(hr == S_FALSE,
8107                     "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8108                     hr, S_FALSE, test_index);
8109                 if(SUCCEEDED(hr)) {
8110                     ok(!len, "Error: Expected len to be 0, but was %d instead on uri_builder_tests[%d].\n",
8111                         len, test_index);
8112                     ok(!received, "Error: Expected received to be NULL, but was %p instead on uri_builder_tests[%d].\n",
8113                         received, test_index);
8114                 }
8115             } else {
8116                 BOOL has_prop = FALSE;
8117                 BSTR expected = NULL;
8118
8119                 hr = IUri_GetHost(uri, &expected);
8120                 ok(SUCCEEDED(hr),
8121                     "Error: Expected IUri_GetHost to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
8122                     hr, test_index);
8123                 has_prop = hr == S_OK;
8124
8125                 hr = IUriBuilder_GetHost(builder, &len, &received);
8126                 if(has_prop) {
8127                     ok(hr == S_OK,
8128                         "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8129                         hr, S_OK, test_index);
8130                     if(SUCCEEDED(hr)) {
8131                         ok(!lstrcmpW(expected, received),
8132                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].\n",
8133                             wine_dbgstr_w(expected), wine_dbgstr_w(received), test_index);
8134                         ok(lstrlenW(expected) == len,
8135                             "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8136                             lstrlenW(expected), len, test_index);
8137                     }
8138                 } else {
8139                     ok(hr == S_FALSE,
8140                         "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8141                         hr, S_FALSE, test_index);
8142                     if(SUCCEEDED(hr)) {
8143                         ok(!received, "Error: Expected received to be NULL on uri_builder_tests[%d].\n", test_index);
8144                         ok(!len, "Error: Expected the length to be 0, but was %d instead on uri_builder_tests[%d].\n",
8145                             len, test_index);
8146                     }
8147                 }
8148                 SysFreeString(expected);
8149             }
8150         }
8151         if(uri) IUri_Release(uri);
8152     }
8153 }
8154
8155 static void test_IUriBuilder_GetPassword(IUriBuilder *builder, const uri_builder_test *test,
8156                                          DWORD test_index) {
8157     HRESULT hr;
8158     DWORD i;
8159     LPCWSTR received = NULL;
8160     DWORD len = -1;
8161     const uri_builder_property *prop = NULL;
8162
8163     /* Check if the property was set earlier. */
8164     for(i = 0; i < sizeof(test->properties)/sizeof(test->properties[0]); ++i) {
8165         if(test->properties[i].change && test->properties[i].property == Uri_PROPERTY_PASSWORD)
8166             prop = &(test->properties[i]);
8167     }
8168
8169     if(prop) {
8170         /* Use expected_value unless it's NULL, then use value. */
8171         LPCSTR expected = prop->expected_value ? prop->expected_value : prop->value;
8172         hr = IUriBuilder_GetPassword(builder, &len, &received);
8173         if(prop->todo) {
8174             todo_wine {
8175                 ok(hr == (expected ? S_OK : S_FALSE),
8176                     "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8177                     hr, (expected ? S_OK : S_FALSE), test_index);
8178             }
8179             if(SUCCEEDED(hr)) {
8180                 todo_wine {
8181                     ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
8182                         expected, wine_dbgstr_w(received), test_index);
8183                 }
8184                 todo_wine {
8185                     ok(lstrlen(expected) == len,
8186                         "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8187                         lstrlen(expected), len, test_index);
8188                 }
8189             }
8190         } else {
8191             ok(hr == (expected ? S_OK : S_FALSE),
8192                 "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8193                 hr, (expected ? S_OK : S_FALSE), test_index);
8194             ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
8195                 expected, wine_dbgstr_w(received), test_index);
8196             ok(lstrlen(expected) == len,
8197                 "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8198                 lstrlen(expected), len, test_index);
8199         }
8200     } else {
8201         /* The property wasn't set earlier, so it should return whatever
8202          * the base IUri contains (if anything).
8203          */
8204         IUri *uri = NULL;
8205         hr = IUriBuilder_GetIUri(builder, &uri);
8206         ok(hr == S_OK,
8207             "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8208             hr, S_OK, test_index);
8209         if(SUCCEEDED(hr)) {
8210             if(!uri) {
8211                 received = (void*) 0xdeadbeef;
8212                 len = -1;
8213
8214                 hr = IUriBuilder_GetPassword(builder, &len, &received);
8215                 ok(hr == S_FALSE,
8216                     "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8217                     hr, S_FALSE, test_index);
8218                 if(SUCCEEDED(hr)) {
8219                     ok(!len, "Error: Expected len to be 0, but was %d instead on uri_builder_tests[%d].\n",
8220                         len, test_index);
8221                     ok(!received, "Error: Expected received to be NULL, but was %p instead on uri_builder_tests[%d].\n",
8222                         received, test_index);
8223                 }
8224             } else {
8225                 BOOL has_prop = FALSE;
8226                 BSTR expected = NULL;
8227
8228                 hr = IUri_GetPassword(uri, &expected);
8229                 ok(SUCCEEDED(hr),
8230                     "Error: Expected IUri_GetPassword to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
8231                     hr, test_index);
8232                 has_prop = hr == S_OK;
8233
8234                 hr = IUriBuilder_GetPassword(builder, &len, &received);
8235                 if(has_prop) {
8236                     ok(hr == S_OK,
8237                         "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8238                         hr, S_OK, test_index);
8239                     if(SUCCEEDED(hr)) {
8240                         ok(!lstrcmpW(expected, received),
8241                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].\n",
8242                             wine_dbgstr_w(expected), wine_dbgstr_w(received), test_index);
8243                         ok(lstrlenW(expected) == len,
8244                             "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8245                             lstrlenW(expected), len, test_index);
8246                     }
8247                 } else {
8248                     ok(hr == S_FALSE,
8249                         "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8250                         hr, S_FALSE, test_index);
8251                     if(SUCCEEDED(hr)) {
8252                         ok(!received, "Error: Expected received to be NULL on uri_builder_tests[%d].\n", test_index);
8253                         ok(!len, "Error: Expected the length to be 0, but was %d instead on uri_builder_tests[%d].\n",
8254                             len, test_index);
8255                     }
8256                 }
8257                 SysFreeString(expected);
8258             }
8259         }
8260         if(uri) IUri_Release(uri);
8261     }
8262 }
8263
8264 static void test_IUriBuilder_GetPath(IUriBuilder *builder, const uri_builder_test *test,
8265                                      DWORD test_index) {
8266     HRESULT hr;
8267     DWORD i;
8268     LPCWSTR received = NULL;
8269     DWORD len = -1;
8270     const uri_builder_property *prop = NULL;
8271
8272     /* Check if the property was set earlier. */
8273     for(i = 0; i < sizeof(test->properties)/sizeof(test->properties[0]); ++i) {
8274         if(test->properties[i].change && test->properties[i].property == Uri_PROPERTY_PATH)
8275             prop = &(test->properties[i]);
8276     }
8277
8278     if(prop) {
8279         /* Use expected_value unless it's NULL, then use value. */
8280         LPCSTR expected = prop->expected_value ? prop->expected_value : prop->value;
8281         hr = IUriBuilder_GetPath(builder, &len, &received);
8282         if(prop->todo) {
8283             todo_wine {
8284                 ok(hr == (expected ? S_OK : S_FALSE),
8285                     "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8286                     hr, (expected ? S_OK : S_FALSE), test_index);
8287             }
8288             if(SUCCEEDED(hr)) {
8289                 todo_wine {
8290                     ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
8291                         expected, wine_dbgstr_w(received), test_index);
8292                 }
8293                 todo_wine {
8294                     ok(lstrlen(expected) == len,
8295                         "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8296                         lstrlen(expected), len, test_index);
8297                 }
8298             }
8299         } else {
8300             ok(hr == (expected ? S_OK : S_FALSE),
8301                 "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8302                 hr, (expected ? S_OK : S_FALSE), test_index);
8303             ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
8304                 expected, wine_dbgstr_w(received), test_index);
8305             ok(lstrlen(expected) == len,
8306                 "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8307                 lstrlen(expected), len, test_index);
8308         }
8309     } else {
8310         /* The property wasn't set earlier, so it should return whatever
8311          * the base IUri contains (if anything).
8312          */
8313         IUri *uri = NULL;
8314         hr = IUriBuilder_GetIUri(builder, &uri);
8315         ok(hr == S_OK,
8316             "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8317             hr, S_OK, test_index);
8318         if(SUCCEEDED(hr)) {
8319             if(!uri) {
8320                 received = (void*) 0xdeadbeef;
8321                 len = -1;
8322
8323                 hr = IUriBuilder_GetPath(builder, &len, &received);
8324                 ok(hr == S_FALSE,
8325                     "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8326                     hr, S_FALSE, test_index);
8327                 if(SUCCEEDED(hr)) {
8328                     ok(!len, "Error: Expected len to be 0, but was %d instead on uri_builder_tests[%d].\n",
8329                         len, test_index);
8330                     ok(!received, "Error: Expected received to be NULL, but was %p instead on uri_builder_tests[%d].\n",
8331                         received, test_index);
8332                 }
8333             } else {
8334                 BOOL has_prop = FALSE;
8335                 BSTR expected = NULL;
8336
8337                 hr = IUri_GetPath(uri, &expected);
8338                 ok(SUCCEEDED(hr),
8339                     "Error: Expected IUri_GetPath to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
8340                     hr, test_index);
8341                 has_prop = hr == S_OK;
8342
8343                 hr = IUriBuilder_GetPath(builder, &len, &received);
8344                 if(has_prop) {
8345                     ok(hr == S_OK,
8346                         "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8347                         hr, S_OK, test_index);
8348                     if(SUCCEEDED(hr)) {
8349                         ok(!lstrcmpW(expected, received),
8350                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].\n",
8351                             wine_dbgstr_w(expected), wine_dbgstr_w(received), test_index);
8352                         ok(lstrlenW(expected) == len,
8353                             "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8354                             lstrlenW(expected), len, test_index);
8355                     }
8356                 } else {
8357                     ok(hr == S_FALSE,
8358                         "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8359                         hr, S_FALSE, test_index);
8360                     if(SUCCEEDED(hr)) {
8361                         ok(!received, "Error: Expected received to be NULL on uri_builder_tests[%d].\n", test_index);
8362                         ok(!len, "Error: Expected the length to be 0, but was %d instead on uri_builder_tests[%d].\n",
8363                             len, test_index);
8364                     }
8365                 }
8366                 SysFreeString(expected);
8367             }
8368         }
8369         if(uri) IUri_Release(uri);
8370     }
8371 }
8372
8373 static void test_IUriBuilder_GetPort(IUriBuilder *builder, const uri_builder_test *test,
8374                                      DWORD test_index) {
8375     HRESULT hr;
8376     BOOL has_port = FALSE;
8377     DWORD received = -1;
8378
8379     if(test->port_prop.change) {
8380         DWORD expected = test->port_prop.value;
8381
8382         hr = IUriBuilder_GetPort(builder, &has_port, &received);
8383         if(test->port_prop.todo) {
8384             todo_wine {
8385                 ok(hr == S_OK,
8386                     "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8387                     hr, S_OK, test_index);
8388             }
8389             if(SUCCEEDED(hr)) {
8390                 todo_wine {
8391                     ok(has_port == test->port_prop.set,
8392                         "Error: Expected has_port to be %d but was %d instead on uri_builder_tests[%d].\n",
8393                         test->port_prop.set, has_port, test_index);
8394                 }
8395                 todo_wine {
8396                     ok(received == expected,
8397                         "Error: Expected received to be %d, but was %d instead on uri_builder_tests[%d].\n",
8398                         expected, received, test_index);
8399                 }
8400             }
8401         } else {
8402             ok(hr == S_OK,
8403                 "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8404                 hr, S_OK, test_index);
8405             ok(has_port == test->port_prop.set,
8406                 "Error: Expected has_port to be %d, but was %d instead on uri_builder_tests[%d].\n",
8407                 test->port_prop.set, has_port, test_index);
8408             ok(received == test->port_prop.value,
8409                 "Error: Expected port to be %d, but was %d instead on uri_builder_tests[%d].\n",
8410                 test->port_prop.value, received, test_index);
8411         }
8412     } else {
8413         IUri *uri = NULL;
8414
8415         hr = IUriBuilder_GetIUri(builder, &uri);
8416         ok(hr == S_OK,
8417             "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8418             hr, S_OK, test_index);
8419         if(SUCCEEDED(hr)) {
8420             if(!uri) {
8421                 hr = IUriBuilder_GetPort(builder, &has_port, &received);
8422                 ok(hr == S_OK,
8423                     "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8424                     hr, S_OK, test_index);
8425                 if(SUCCEEDED(hr)) {
8426                     ok(has_port == FALSE,
8427                         "Error: Expected has_port to be FALSE, but was %d instead on uri_builder_tests[%d].\n",
8428                         has_port, test_index);
8429                     ok(!received, "Error: Expected received to be 0, but was %d instead on uri_builder_tests[%d].\n",
8430                         received, test_index);
8431                 }
8432             } else {
8433                 DWORD expected;
8434
8435                 hr = IUri_GetPort(uri, &expected);
8436                 ok(SUCCEEDED(hr),
8437                     "Error: Expected IUri_Port to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
8438                     hr, test_index);
8439
8440                 hr = IUriBuilder_GetPort(builder, &has_port, &received);
8441                 ok(hr == S_OK,
8442                     "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8443                     hr, S_OK, test_index);
8444                 if(SUCCEEDED(hr)) {
8445                     ok(!has_port,
8446                         "Error: Expected has_port to be FALSE but was TRUE instead on uri_builder_tests[%d].\n",
8447                         test_index);
8448                     ok(received == expected,
8449                         "Error: Expected received to be %d, but was %d instead on uri_builder_tests[%d].\n",
8450                         expected, received, test_index);
8451                 }
8452             }
8453         }
8454         if(uri) IUri_Release(uri);
8455     }
8456 }
8457
8458 static void test_IUriBuilder_GetQuery(IUriBuilder *builder, const uri_builder_test *test,
8459                                       DWORD test_index) {
8460     HRESULT hr;
8461     DWORD i;
8462     LPCWSTR received = NULL;
8463     DWORD len = -1;
8464     const uri_builder_property *prop = NULL;
8465
8466     /* Check if the property was set earlier. */
8467     for(i = 0; i < sizeof(test->properties)/sizeof(test->properties[0]); ++i) {
8468         if(test->properties[i].change && test->properties[i].property == Uri_PROPERTY_QUERY)
8469             prop = &(test->properties[i]);
8470     }
8471
8472     if(prop) {
8473         /* Use expected_value unless it's NULL, then use value. */
8474         LPCSTR expected = prop->expected_value ? prop->expected_value : prop->value;
8475         hr = IUriBuilder_GetQuery(builder, &len, &received);
8476         if(prop->todo) {
8477             todo_wine {
8478                 ok(hr == (expected ? S_OK : S_FALSE),
8479                     "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8480                     hr, (expected ? S_OK : S_FALSE), test_index);
8481             }
8482             if(SUCCEEDED(hr)) {
8483                 todo_wine {
8484                     ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
8485                         expected, wine_dbgstr_w(received), test_index);
8486                 }
8487                 todo_wine {
8488                     ok(lstrlen(expected) == len,
8489                         "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8490                         lstrlen(expected), len, test_index);
8491                 }
8492             }
8493         } else {
8494             ok(hr == (expected ? S_OK : S_FALSE),
8495                 "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8496                 hr, (expected ? S_OK : S_FALSE), test_index);
8497             ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
8498                 expected, wine_dbgstr_w(received), test_index);
8499             ok(lstrlen(expected) == len,
8500                 "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8501                 lstrlen(expected), len, test_index);
8502         }
8503     } else {
8504         /* The property wasn't set earlier, so it should return whatever
8505          * the base IUri contains (if anything).
8506          */
8507         IUri *uri = NULL;
8508         hr = IUriBuilder_GetIUri(builder, &uri);
8509         ok(hr == S_OK,
8510             "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8511             hr, S_OK, test_index);
8512         if(SUCCEEDED(hr)) {
8513             if(!uri) {
8514                 received = (void*) 0xdeadbeef;
8515                 len = -1;
8516
8517                 hr = IUriBuilder_GetQuery(builder, &len, &received);
8518                 ok(hr == S_FALSE,
8519                     "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8520                     hr, S_FALSE, test_index);
8521                 if(SUCCEEDED(hr)) {
8522                     ok(!len, "Error: Expected len to be 0, but was %d instead on uri_builder_tests[%d].\n",
8523                         len, test_index);
8524                     ok(!received, "Error: Expected received to be NULL, but was %p instead on uri_builder_tests[%d].\n",
8525                         received, test_index);
8526                 }
8527             } else {
8528                 BOOL has_prop = FALSE;
8529                 BSTR expected = NULL;
8530
8531                 hr = IUri_GetQuery(uri, &expected);
8532                 ok(SUCCEEDED(hr),
8533                     "Error: Expected IUri_GetQuery to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
8534                     hr, test_index);
8535                 has_prop = hr == S_OK;
8536
8537                 hr = IUriBuilder_GetQuery(builder, &len, &received);
8538                 if(has_prop) {
8539                     ok(hr == S_OK,
8540                         "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8541                         hr, S_OK, test_index);
8542                     if(SUCCEEDED(hr)) {
8543                         ok(!lstrcmpW(expected, received),
8544                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].\n",
8545                             wine_dbgstr_w(expected), wine_dbgstr_w(received), test_index);
8546                         ok(lstrlenW(expected) == len,
8547                             "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8548                             lstrlenW(expected), len, test_index);
8549                     }
8550                 } else {
8551                     ok(hr == S_FALSE,
8552                         "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8553                         hr, S_FALSE, test_index);
8554                     if(SUCCEEDED(hr)) {
8555                         ok(!received, "Error: Expected received to be NULL on uri_builder_tests[%d].\n", test_index);
8556                         ok(!len, "Error: Expected the length to be 0, but was %d instead on uri_builder_tests[%d].\n",
8557                             len, test_index);
8558                     }
8559                 }
8560                 SysFreeString(expected);
8561             }
8562         }
8563         if(uri) IUri_Release(uri);
8564     }
8565 }
8566
8567 static void test_IUriBuilder_GetSchemeName(IUriBuilder *builder, const uri_builder_test *test,
8568                                            DWORD test_index) {
8569     HRESULT hr;
8570     DWORD i;
8571     LPCWSTR received = NULL;
8572     DWORD len = -1;
8573     const uri_builder_property *prop = NULL;
8574
8575     /* Check if the property was set earlier. */
8576     for(i = 0; i < sizeof(test->properties)/sizeof(test->properties[0]); ++i) {
8577         if(test->properties[i].change && test->properties[i].property == Uri_PROPERTY_SCHEME_NAME)
8578             prop = &(test->properties[i]);
8579     }
8580
8581     if(prop) {
8582         /* Use expected_value unless it's NULL, then use value. */
8583         LPCSTR expected = prop->expected_value ? prop->expected_value : prop->value;
8584         hr = IUriBuilder_GetSchemeName(builder, &len, &received);
8585         if(prop->todo) {
8586             todo_wine {
8587                 ok(hr == (expected ? S_OK : S_FALSE),
8588                     "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8589                     hr, (expected ? S_OK : S_FALSE), test_index);
8590             }
8591             if(SUCCEEDED(hr)) {
8592                 todo_wine {
8593                     ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
8594                         expected, wine_dbgstr_w(received), test_index);
8595                 }
8596                 todo_wine {
8597                     ok(lstrlen(expected) == len,
8598                         "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8599                         lstrlen(expected), len, test_index);
8600                 }
8601             }
8602         } else {
8603             ok(hr == (expected ? S_OK : S_FALSE),
8604                 "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8605                 hr, (expected ? S_OK : S_FALSE), test_index);
8606             ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
8607                 expected, wine_dbgstr_w(received), test_index);
8608             ok(lstrlen(expected) == len,
8609                 "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8610                 lstrlen(expected), len, test_index);
8611         }
8612     } else {
8613         /* The property wasn't set earlier, so it should return whatever
8614          * the base IUri contains (if anything).
8615          */
8616         IUri *uri = NULL;
8617         hr = IUriBuilder_GetIUri(builder, &uri);
8618         ok(hr == S_OK,
8619             "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8620             hr, S_OK, test_index);
8621         if(SUCCEEDED(hr)) {
8622             if(!uri) {
8623                 received = (void*) 0xdeadbeef;
8624                 len = -1;
8625
8626                 hr = IUriBuilder_GetSchemeName(builder, &len, &received);
8627                 ok(hr == S_FALSE,
8628                     "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8629                     hr, S_FALSE, test_index);
8630                 if(SUCCEEDED(hr)) {
8631                     ok(!len, "Error: Expected len to be 0, but was %d instead on uri_builder_tests[%d].\n",
8632                         len, test_index);
8633                     ok(!received, "Error: Expected received to be NULL, but was %p instead on uri_builder_tests[%d].\n",
8634                         received, test_index);
8635                 }
8636             } else {
8637                 BOOL has_prop = FALSE;
8638                 BSTR expected = NULL;
8639
8640                 hr = IUri_GetSchemeName(uri, &expected);
8641                 ok(SUCCEEDED(hr),
8642                     "Error: Expected IUri_GetSchemeName to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
8643                     hr, test_index);
8644                 has_prop = hr == S_OK;
8645
8646                 hr = IUriBuilder_GetSchemeName(builder, &len, &received);
8647                 if(has_prop) {
8648                     ok(hr == S_OK,
8649                         "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8650                         hr, S_OK, test_index);
8651                     if(SUCCEEDED(hr)) {
8652                         ok(!lstrcmpW(expected, received),
8653                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].\n",
8654                             wine_dbgstr_w(expected), wine_dbgstr_w(received), test_index);
8655                         ok(lstrlenW(expected) == len,
8656                             "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8657                             lstrlenW(expected), len, test_index);
8658                     }
8659                 } else {
8660                     ok(hr == S_FALSE,
8661                         "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8662                         hr, S_FALSE, test_index);
8663                     if(SUCCEEDED(hr)) {
8664                         ok(!received, "Error: Expected received to be NULL on uri_builder_tests[%d].\n", test_index);
8665                         ok(!len, "Error: Expected the length to be 0, but was %d instead on uri_builder_tests[%d].\n",
8666                             len, test_index);
8667                     }
8668                 }
8669                 SysFreeString(expected);
8670             }
8671         }
8672         if(uri) IUri_Release(uri);
8673     }
8674 }
8675
8676 static void test_IUriBuilder_GetUserName(IUriBuilder *builder, const uri_builder_test *test,
8677                                          DWORD test_index) {
8678     HRESULT hr;
8679     DWORD i;
8680     LPCWSTR received = NULL;
8681     DWORD len = -1;
8682     const uri_builder_property *prop = NULL;
8683
8684     /* Check if the property was set earlier. */
8685     for(i = 0; i < sizeof(test->properties)/sizeof(test->properties[0]); ++i) {
8686         if(test->properties[i].change && test->properties[i].property == Uri_PROPERTY_USER_NAME)
8687             prop = &(test->properties[i]);
8688     }
8689
8690     if(prop && prop->value && *prop->value) {
8691         /* Use expected_value unless it's NULL, then use value. */
8692         LPCSTR expected = prop->expected_value ? prop->expected_value : prop->value;
8693         hr = IUriBuilder_GetUserName(builder, &len, &received);
8694         if(prop->todo) {
8695             todo_wine {
8696                 ok(hr == (expected ? S_OK : S_FALSE),
8697                     "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8698                     hr, (expected ? S_OK : S_FALSE), test_index);
8699             }
8700             if(SUCCEEDED(hr)) {
8701                 todo_wine {
8702                     ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
8703                         expected, wine_dbgstr_w(received), test_index);
8704                 }
8705                 todo_wine {
8706                     ok(lstrlen(expected) == len,
8707                         "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8708                         lstrlen(expected), len, test_index);
8709                 }
8710             }
8711         } else {
8712             ok(hr == (expected ? S_OK : S_FALSE),
8713                 "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8714                 hr, (expected ? S_OK : S_FALSE), test_index);
8715             ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
8716                 expected, wine_dbgstr_w(received), test_index);
8717             ok(lstrlen(expected) == len,
8718                 "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8719                 lstrlen(expected), len, test_index);
8720         }
8721     } else {
8722         /* The property wasn't set earlier, so it should return whatever
8723          * the base IUri contains (if anything).
8724          */
8725         IUri *uri = NULL;
8726         hr = IUriBuilder_GetIUri(builder, &uri);
8727         ok(hr == S_OK,
8728             "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8729             hr, S_OK, test_index);
8730         if(SUCCEEDED(hr)) {
8731             if(!uri) {
8732                 received = (void*) 0xdeadbeef;
8733                 len = -1;
8734
8735                 hr = IUriBuilder_GetUserName(builder, &len, &received);
8736                 ok(hr == S_FALSE,
8737                     "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8738                     hr, S_FALSE, test_index);
8739                 if(SUCCEEDED(hr)) {
8740                     ok(!len, "Error: Expected len to be 0, but was %d instead on uri_builder_tests[%d].\n",
8741                         len, test_index);
8742                     ok(!received, "Error: Expected received to be NULL, but was %p instead on uri_builder_tests[%d].\n",
8743                         received, test_index);
8744                 }
8745             } else {
8746                 BSTR expected = NULL;
8747                 BOOL has_prop = FALSE;
8748
8749                 hr = IUri_GetUserName(uri, &expected);
8750                 ok(SUCCEEDED(hr),
8751                     "Error: Expected IUri_GetUserName to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
8752                     hr, test_index);
8753                 has_prop = hr == S_OK;
8754
8755                 hr = IUriBuilder_GetUserName(builder, &len, &received);
8756                 if(has_prop) {
8757                     ok(hr == S_OK,
8758                         "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8759                         hr, S_OK, test_index);
8760                     if(SUCCEEDED(hr)) {
8761                         ok(!lstrcmpW(expected, received),
8762                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].\n",
8763                             wine_dbgstr_w(expected), wine_dbgstr_w(received), test_index);
8764                         ok(lstrlenW(expected) == len,
8765                             "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8766                             lstrlenW(expected), len, test_index);
8767                     }
8768                 } else {
8769                     ok(hr == S_FALSE,
8770                         "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8771                         hr, S_FALSE, test_index);
8772                     if(SUCCEEDED(hr)) {
8773                         ok(!received, "Error: Expected received to be NULL on uri_builder_tests[%d].\n", test_index);
8774                         ok(!len, "Error: Expected the length to be 0, but was %d instead on uri_builder_tests[%d].\n",
8775                             len, test_index);
8776                     }
8777                 }
8778                 SysFreeString(expected);
8779             }
8780         }
8781         if(uri) IUri_Release(uri);
8782     }
8783 }
8784
8785 /* Tests IUriBuilder functions. */
8786 static void test_IUriBuilder(void) {
8787     HRESULT hr;
8788     IUriBuilder *builder;
8789     DWORD i;
8790
8791     for(i = 0; i < sizeof(uri_builder_tests)/sizeof(uri_builder_tests[0]); ++i) {
8792         IUri *uri = NULL;
8793         uri_builder_test test = uri_builder_tests[i];
8794         LPWSTR uriW = NULL;
8795
8796         if(test.uri) {
8797             uriW = a2w(test.uri);
8798             hr = pCreateUri(uriW, test.create_flags, 0, &uri);
8799             ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8800                 hr, S_OK, i);
8801             if(FAILED(hr)) continue;
8802         }
8803         hr = pCreateIUriBuilder(uri, 0, 0, &builder);
8804         if(test.create_builder_todo) {
8805             todo_wine {
8806                 ok(hr == test.create_builder_expected,
8807                     "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8808                     hr, test.create_builder_expected, i);
8809             }
8810         } else {
8811             ok(hr == test.create_builder_expected,
8812                 "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8813                 hr, test.create_builder_expected, i);
8814         }
8815         if(SUCCEEDED(hr)) {
8816             DWORD j;
8817             BOOL modified = FALSE, received = FALSE;
8818
8819             /* Perform all the string property changes. */
8820             for(j = 0; j < URI_BUILDER_STR_PROPERTY_COUNT; ++j) {
8821                 uri_builder_property prop = test.properties[j];
8822                 if(prop.change) {
8823                     change_property(builder, &prop, i);
8824                     if(prop.property != Uri_PROPERTY_SCHEME_NAME &&
8825                        prop.property != Uri_PROPERTY_HOST)
8826                         modified = TRUE;
8827                     else if(prop.value && *prop.value)
8828                         modified = TRUE;
8829                     else if(prop.value && !*prop.value && prop.property == Uri_PROPERTY_HOST)
8830                         /* Host name property can't be NULL, but it can be empty. */
8831                         modified = TRUE;
8832                 }
8833             }
8834
8835             if(test.port_prop.change) {
8836                 hr = IUriBuilder_SetPort(builder, test.port_prop.set, test.port_prop.value);
8837                 modified = TRUE;
8838                 if(test.port_prop.todo) {
8839                     todo_wine {
8840                         ok(hr == test.port_prop.expected,
8841                             "Error: IUriBuilder_SetPort returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8842                             hr, test.port_prop.expected, i);
8843                     }
8844                 } else {
8845                     ok(hr == test.port_prop.expected,
8846                         "Error: IUriBuilder_SetPort returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8847                         hr, test.port_prop.expected, i);
8848                 }
8849             }
8850
8851             hr = IUriBuilder_HasBeenModified(builder, &received);
8852             ok(hr == S_OK,
8853                 "Error IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8854                 hr, S_OK, i);
8855             if(SUCCEEDED(hr))
8856                 ok(received == modified,
8857                     "Error: Expected received to be %d but was %d instead on uri_builder_tests[%d].\n",
8858                     modified, received, i);
8859
8860             /* Test the "Get*" functions. */
8861             test_IUriBuilder_GetFragment(builder, &test, i);
8862             test_IUriBuilder_GetHost(builder, &test, i);
8863             test_IUriBuilder_GetPassword(builder, &test, i);
8864             test_IUriBuilder_GetPath(builder, &test, i);
8865             test_IUriBuilder_GetPort(builder, &test, i);
8866             test_IUriBuilder_GetQuery(builder, &test, i);
8867             test_IUriBuilder_GetSchemeName(builder, &test, i);
8868             test_IUriBuilder_GetUserName(builder, &test, i);
8869
8870             test_IUriBuilder_CreateUri(builder, &test, i);
8871             test_IUriBuilder_CreateUriSimple(builder, &test, i);
8872             test_IUriBuilder_CreateUriWithFlags(builder, &test, i);
8873         }
8874         if(builder) IUriBuilder_Release(builder);
8875         if(uri) IUri_Release(uri);
8876         heap_free(uriW);
8877     }
8878 }
8879
8880 static void test_IUriBuilder_HasBeenModified(void) {
8881     HRESULT hr;
8882     IUriBuilder *builder = NULL;
8883
8884     hr = pCreateIUriBuilder(NULL, 0, 0, &builder);
8885     ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8886     if(SUCCEEDED(hr)) {
8887         static const WCHAR hostW[] = {'g','o','o','g','l','e','.','c','o','m',0};
8888         IUri *uri = NULL;
8889         BOOL received;
8890
8891         hr = IUriBuilder_HasBeenModified(builder, NULL);
8892         ok(hr == E_POINTER, "Error: IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x.\n",
8893             hr, E_POINTER);
8894
8895         hr = IUriBuilder_SetHost(builder, hostW);
8896         ok(hr == S_OK, "Error: IUriBuilder_SetHost returned 0x%08x, expected 0x%08x.\n",
8897             hr, S_OK);
8898
8899         hr = IUriBuilder_HasBeenModified(builder, &received);
8900         ok(hr == S_OK, "Error: IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x.\n",
8901             hr, S_OK);
8902         if(SUCCEEDED(hr))
8903             ok(received == TRUE, "Error: Expected received to be TRUE.\n");
8904
8905         hr = pCreateUri(http_urlW, 0, 0, &uri);
8906         ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8907         if(SUCCEEDED(hr)) {
8908             LPCWSTR prop;
8909             DWORD len = -1;
8910
8911             hr = IUriBuilder_SetIUri(builder, uri);
8912             ok(hr == S_OK, "Error: IUriBuilder_SetIUri returned 0x%08x, expected 0x%08x.\n",
8913                 hr, S_OK);
8914
8915             hr = IUriBuilder_HasBeenModified(builder, &received);
8916             ok(hr == S_OK, "Error: IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x.\n",
8917                 hr, S_OK);
8918             if(SUCCEEDED(hr))
8919                 ok(received == FALSE, "Error: Expected received to be FALSE.\n");
8920
8921             /* Test what happens with you call SetIUri with the same IUri again. */
8922             hr = IUriBuilder_SetHost(builder, hostW);
8923             ok(hr == S_OK, "Error: IUriBuilder_SetHost returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8924
8925             hr = IUriBuilder_HasBeenModified(builder, &received);
8926             ok(hr == S_OK, "Error: IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x.\n",
8927                 hr, S_OK);
8928             if(SUCCEEDED(hr))
8929                 ok(received == TRUE, "Error: Expected received to be TRUE.\n");
8930
8931             hr = IUriBuilder_SetIUri(builder, uri);
8932             ok(hr == S_OK, "Error: IUriBuilder_SetIUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8933
8934             /* IUriBuilder already had 'uri' as it's IUri property and so Windows doesn't
8935              * reset any of the changes that were made to the IUriBuilder.
8936              */
8937             hr = IUriBuilder_HasBeenModified(builder, &received);
8938             ok(hr == S_OK, "Error: IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8939             if(SUCCEEDED(hr))
8940                 ok(received == TRUE, "Error: Expected received to be TRUE.\n");
8941
8942             hr = IUriBuilder_GetHost(builder, &len, &prop);
8943             ok(hr == S_OK, "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8944             if(SUCCEEDED(hr)) {
8945                 ok(!lstrcmpW(prop, hostW), "Error: Expected %s but got %s instead.\n",
8946                     wine_dbgstr_w(hostW), wine_dbgstr_w(prop));
8947                 ok(len == lstrlenW(hostW), "Error: Expected len to be %d, but was %d instead.\n",
8948                     lstrlenW(hostW), len);
8949             }
8950
8951             hr = IUriBuilder_SetIUri(builder, NULL);
8952             ok(hr == S_OK, "Error: IUriBuilder_SetIUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8953
8954             hr = IUriBuilder_SetHost(builder, hostW);
8955             ok(hr == S_OK, "Error: IUriBuilder_SetHost returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8956             hr = IUriBuilder_HasBeenModified(builder, &received);
8957             ok(hr == S_OK, "Error: IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x.\n",
8958                 hr, S_OK);
8959             if(SUCCEEDED(hr))
8960                 ok(received == TRUE, "Error: Expected received to be TRUE.\n");
8961
8962             hr = IUriBuilder_SetIUri(builder, NULL);
8963             ok(hr == S_OK, "Error: IUriBuilder_SetIUri returned 0x%08x, expected 0x%09x.\n", hr, S_OK);
8964
8965             hr = IUriBuilder_HasBeenModified(builder, &received);
8966             ok(hr == S_OK, "Error: IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x.\n",
8967                 hr, S_OK);
8968             if(SUCCEEDED(hr))
8969                 ok(received == TRUE, "Error: Expected received to be TRUE.\n");
8970
8971             hr = IUriBuilder_GetHost(builder, &len, &prop);
8972             ok(hr == S_OK, "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8973             if(SUCCEEDED(hr)) {
8974                 ok(!lstrcmpW(prop, hostW), "Error: Expected %s but got %s instead.\n",
8975                     wine_dbgstr_w(hostW), wine_dbgstr_w(prop));
8976                 ok(len == lstrlenW(hostW), "Error: Expected len to %d, but was %d instead.\n",
8977                     lstrlenW(hostW), len);
8978             }
8979         }
8980         if(uri) IUri_Release(uri);
8981     }
8982     if(builder) IUriBuilder_Release(builder);
8983 }
8984
8985 /* Test IUriBuilder {Get,Set}IUri functions. */
8986 static void test_IUriBuilder_IUriProperty(void) {
8987     IUriBuilder *builder = NULL;
8988     HRESULT hr;
8989
8990     hr = pCreateIUriBuilder(NULL, 0, 0, &builder);
8991     ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8992     if(SUCCEEDED(hr)) {
8993         IUri *uri = NULL;
8994
8995         hr = IUriBuilder_GetIUri(builder, NULL);
8996         ok(hr == E_POINTER, "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x.\n",
8997             hr, E_POINTER);
8998
8999         hr = pCreateUri(http_urlW, 0, 0, &uri);
9000         if(SUCCEEDED(hr)) {
9001             IUri *test = NULL;
9002             ULONG cur_count, orig_count;
9003
9004             /* IUriBuilder doesn't clone the IUri, it use the same IUri. */
9005             orig_count = get_refcnt(uri);
9006             hr = IUriBuilder_SetIUri(builder, uri);
9007             cur_count = get_refcnt(uri);
9008             if(SUCCEEDED(hr))
9009                 ok(cur_count == orig_count+1, "Error: Expected uri ref count to be %d, but was %d instead.\n",
9010                     orig_count+1, cur_count);
9011
9012             hr = IUriBuilder_SetIUri(builder, NULL);
9013             cur_count = get_refcnt(uri);
9014             if(SUCCEEDED(hr))
9015                 ok(cur_count == orig_count, "Error: Expected uri ref count to be %d, but was %d instead.\n",
9016                     orig_count, cur_count);
9017
9018             /* CreateUri* functions will return back the same IUri if nothing has changed. */
9019             hr = IUriBuilder_SetIUri(builder, uri);
9020             ok(hr == S_OK, "Error: IUriBuilder_SetIUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9021             orig_count = get_refcnt(uri);
9022
9023             hr = IUriBuilder_CreateUri(builder, 0, 0, 0, &test);
9024             ok(hr == S_OK, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9025             if(SUCCEEDED(hr)) {
9026                 cur_count = get_refcnt(uri);
9027                 ok(cur_count == orig_count+1, "Error: Expected uri ref count to be %d, but was %d instead.\n",
9028                     orig_count+1, cur_count);
9029                 ok(test == uri, "Error: Expected test to be %p, but was %p instead.\n",
9030                     uri, test);
9031             }
9032             if(test) IUri_Release(test);
9033
9034             test = NULL;
9035             hr = IUriBuilder_CreateUri(builder, -1, 0, 0, &test);
9036             ok(hr == S_OK, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9037             if(SUCCEEDED(hr)) {
9038                 cur_count = get_refcnt(uri);
9039                 ok(cur_count == orig_count+1, "Error: Expected uri ref count to be %d, but was %d instead.\n",
9040                     orig_count+1, cur_count);
9041                 ok(test == uri, "Error: Expected test to be %p, but was %p instead.\n", uri, test);
9042             }
9043             if(test) IUri_Release(test);
9044
9045             /* Doesn't return the same IUri, if the flag combination is different then the one that created
9046              * the base IUri.
9047              */
9048             test = NULL;
9049             hr = IUriBuilder_CreateUri(builder, Uri_CREATE_ALLOW_RELATIVE, 0, 0, &test);
9050             ok(hr == S_OK, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9051             if(SUCCEEDED(hr))
9052                 ok(test != uri, "Error: Wasn't expecting 'test' to be 'uri'\n");
9053
9054             if(test) IUri_Release(test);
9055
9056             /* Still returns the same IUri, even though the base one wasn't created with CREATE_CANONICALIZE
9057              * explicitly set (because it's a default flags).
9058              */
9059             test = NULL;
9060             hr = IUriBuilder_CreateUri(builder, Uri_CREATE_CANONICALIZE, 0, 0, &test);
9061             ok(hr == S_OK, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9062             if(SUCCEEDED(hr)) {
9063                 cur_count = get_refcnt(uri);
9064                 ok(cur_count == orig_count+1, "Error: Expected uri ref count to be %d, but was %d instead.\n",
9065                     orig_count+1, cur_count);
9066                 ok(test == uri, "Error: Expected 'test' to be %p, but was %p instead.\n", uri, test);
9067             }
9068             if(test) IUri_Release(test);
9069
9070             test = NULL;
9071             hr = IUriBuilder_CreateUriSimple(builder, 0, 0, &test);
9072             ok(hr == S_OK, "Error: IUriBuilder_CreateUriSimple returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9073             if(SUCCEEDED(hr)) {
9074                 cur_count = get_refcnt(uri);
9075                 ok(cur_count == orig_count+1, "Error: Expected uri ref count to be %d, but was %d instead.\n",
9076                     orig_count+1, cur_count);
9077                 ok(test == uri, "Error: Expected test to be %p, but was %p instead.\n", uri, test);
9078             }
9079             if(test) IUri_Release(test);
9080
9081             test = NULL;
9082             hr = IUriBuilder_CreateUriWithFlags(builder, 0, 0, 0, 0, &test);
9083             ok(hr == S_OK, "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x.\n",
9084                 hr, S_OK);
9085             if(SUCCEEDED(hr)) {
9086                 cur_count = get_refcnt(uri);
9087                 ok(cur_count == orig_count+1, "Error: Expected uri ref count to be %d, but was %d instead.\n",
9088                     orig_count+1, cur_count);
9089                 ok(test == uri, "Error: Expected test to be %p, but was %p instead.\n", uri, test);
9090             }
9091             if(test) IUri_Release(test);
9092
9093             /* Doesn't return the same IUri, if the flag combination is different then the one that created
9094              * the base IUri.
9095              */
9096             test = NULL;
9097             hr = IUriBuilder_CreateUriWithFlags(builder, Uri_CREATE_ALLOW_RELATIVE, 0, 0, 0, &test);
9098             ok(hr == S_OK, "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9099             if(SUCCEEDED(hr))
9100                 ok(test != uri, "Error: Wasn't expecting 'test' to be 'uri'\n");
9101
9102             if(test) IUri_Release(test);
9103
9104             /* Still returns the same IUri, even though the base one wasn't created with CREATE_CANONICALIZE
9105              * explicitly set (because it's a default flags).
9106              */
9107             test = NULL;
9108             hr = IUriBuilder_CreateUriWithFlags(builder, Uri_CREATE_CANONICALIZE, 0, 0, 0, &test);
9109             ok(hr == S_OK, "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9110             if(SUCCEEDED(hr)) {
9111                 cur_count = get_refcnt(uri);
9112                 ok(cur_count == orig_count+1, "Error: Expected uri ref count to be %d, but was %d instead.\n",
9113                     orig_count+1, cur_count);
9114                 ok(test == uri, "Error: Expected 'test' to be %p, but was %p instead.\n", uri, test);
9115             }
9116             if(test) IUri_Release(test);
9117         }
9118         if(uri) IUri_Release(uri);
9119     }
9120     if(builder) IUriBuilder_Release(builder);
9121 }
9122
9123 static void test_IUriBuilder_RemoveProperties(void) {
9124     IUriBuilder *builder = NULL;
9125     HRESULT hr;
9126     DWORD i;
9127
9128     hr = pCreateIUriBuilder(NULL, 0, 0, &builder);
9129     ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9130     if(SUCCEEDED(hr)) {
9131         /* Properties that can't be removed. */
9132         const DWORD invalid = Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_RAW_URI|Uri_HAS_HOST_TYPE|
9133                               Uri_HAS_SCHEME|Uri_HAS_ZONE;
9134
9135         for(i = Uri_PROPERTY_STRING_START; i <= Uri_PROPERTY_DWORD_LAST; ++i) {
9136             hr = IUriBuilder_RemoveProperties(builder, i << 1);
9137             if((i << 1) & invalid) {
9138                 ok(hr == E_INVALIDARG,
9139                     "Error: IUriBuilder_RemoveProperties returned 0x%08x, expected 0x%08x with prop=%d.\n",
9140                     hr, E_INVALIDARG, i);
9141             } else {
9142                 ok(hr == S_OK,
9143                     "Error: IUriBuilder_RemoveProperties returned 0x%08x, expected 0x%08x with prop=%d.\n",
9144                     hr, S_OK, i);
9145             }
9146         }
9147
9148         /* Also doesn't accept anything that's outside the range of the
9149          * Uri_HAS flags.
9150          */
9151         hr = IUriBuilder_RemoveProperties(builder, (Uri_PROPERTY_DWORD_LAST+1) << 1);
9152         ok(hr == E_INVALIDARG, "Error: IUriBuilder_RemoveProperties returned 0x%08x, expected 0x%08x.\n",
9153             hr, E_INVALIDARG);
9154     }
9155     if(builder) IUriBuilder_Release(builder);
9156
9157     for(i = 0; i < sizeof(uri_builder_remove_tests)/sizeof(uri_builder_remove_tests[0]); ++i) {
9158         uri_builder_remove_test test = uri_builder_remove_tests[i];
9159         IUri *uri = NULL;
9160         LPWSTR uriW;
9161
9162         uriW = a2w(test.uri);
9163         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
9164         if(SUCCEEDED(hr)) {
9165             builder = NULL;
9166
9167             hr = pCreateIUriBuilder(uri, 0, 0, &builder);
9168             if(test.create_builder_todo) {
9169                 todo_wine {
9170                     ok(hr == test.create_builder_expected,
9171                         "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x on test %d.\n",
9172                         hr, test.create_builder_expected, i);
9173                 }
9174             } else {
9175                 ok(hr == test.create_builder_expected,
9176                     "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x on test %d.\n",
9177                     hr, test.create_builder_expected, i);
9178             }
9179             if(SUCCEEDED(hr)) {
9180                 hr = IUriBuilder_RemoveProperties(builder, test.remove_properties);
9181                 if(test.remove_todo) {
9182                     todo_wine {
9183                         ok(hr == test.remove_expected,
9184                             "Error: IUriBuilder_RemoveProperties returned 0x%08x, expected 0x%08x on test %d.\n",
9185                             hr, test.remove_expected, i);
9186                     }
9187                 } else {
9188                     ok(hr == test.remove_expected,
9189                         "Error: IUriBuilder returned 0x%08x, expected 0x%08x on test %d.\n",
9190                         hr, test.remove_expected, i);
9191                 }
9192                 if(SUCCEEDED(hr)) {
9193                     IUri *result = NULL;
9194
9195                     hr = IUriBuilder_CreateUri(builder, test.expected_flags, 0, 0, &result);
9196                     if(test.expected_todo) {
9197                         todo_wine {
9198                             ok(hr == test.expected_hres,
9199                                 "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x on test %d.\n",
9200                                 hr, test.expected_hres, i);
9201                         }
9202                     } else {
9203                         ok(hr == test.expected_hres,
9204                             "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x on test %d.\n",
9205                             hr, test.expected_hres, i);
9206                     }
9207                     if(SUCCEEDED(hr)) {
9208                         BSTR received = NULL;
9209
9210                         hr = IUri_GetAbsoluteUri(result, &received);
9211                         ok(hr == S_OK, "Error: Expected S_OK, but got 0x%08x instead.\n", hr);
9212                         ok(!strcmp_aw(test.expected_uri, received),
9213                             "Error: Expected %s but got %s instead on test %d.\n",
9214                             test.expected_uri, wine_dbgstr_w(received), i);
9215                         SysFreeString(received);
9216                     }
9217                     if(result) IUri_Release(result);
9218                 }
9219             }
9220             if(builder) IUriBuilder_Release(builder);
9221         }
9222         if(uri) IUri_Release(uri);
9223         heap_free(uriW);
9224     }
9225 }
9226
9227 static void test_IUriBuilder_Misc(void) {
9228     HRESULT hr;
9229     IUri *uri;
9230
9231     hr = pCreateUri(http_urlW, 0, 0, &uri);
9232     if(SUCCEEDED(hr)) {
9233         IUriBuilder *builder;
9234
9235         hr = pCreateIUriBuilder(uri, 0, 0, &builder);
9236         ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9237         if(SUCCEEDED(hr)) {
9238             BOOL has = -1;
9239             DWORD port = -1;
9240
9241             hr = IUriBuilder_GetPort(builder, &has, &port);
9242             ok(hr == S_OK, "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9243             if(SUCCEEDED(hr)) {
9244                 /* 'has' will be set to FALSE, even though uri had a port. */
9245                 ok(has == FALSE, "Error: Expected 'has' to be FALSE, was %d instead.\n", has);
9246                 /* Still sets 'port' to 80. */
9247                 ok(port == 80, "Error: Expected the port to be 80, but, was %d instead.\n", port);
9248             }
9249         }
9250         if(builder) IUriBuilder_Release(builder);
9251     }
9252     if(uri) IUri_Release(uri);
9253 }
9254
9255 static void test_IUriBuilderFactory(void) {
9256     HRESULT hr;
9257     IUri *uri;
9258     IUriBuilderFactory *factory;
9259     IUriBuilder *builder;
9260
9261     hr = pCreateUri(http_urlW, 0, 0, &uri);
9262     ok(SUCCEEDED(hr), "Error: CreateUri returned 0x%08x.\n", hr);
9263     if(SUCCEEDED(hr)) {
9264         factory = NULL;
9265         hr = IUri_QueryInterface(uri, &IID_IUriBuilderFactory, (void**)&factory);
9266         ok(hr == S_OK, "Error: Expected S_OK, but got 0x%08x.\n", hr);
9267         ok(factory != NULL, "Error: Expected 'factory' to not be NULL.\n");
9268
9269         if(SUCCEEDED(hr)) {
9270             builder = (void*) 0xdeadbeef;
9271             hr = IUriBuilderFactory_CreateIUriBuilder(factory, 10, 0, &builder);
9272             ok(hr == E_INVALIDARG, "Error: CreateInitializedIUriBuilder returned 0x%08x, expected 0x%08x.\n",
9273                 hr, E_INVALIDARG);
9274             ok(!builder, "Error: Expected 'builder' to be NULL, but was %p.\n", builder);
9275
9276             builder = (void*) 0xdeadbeef;
9277             hr = IUriBuilderFactory_CreateIUriBuilder(factory, 0, 10, &builder);
9278             ok(hr == E_INVALIDARG, "Error: CreateInitializedIUriBuilder returned 0x%08x, expected 0x%08x.\n",
9279                 hr, E_INVALIDARG);
9280             ok(!builder, "Error: Expected 'builder' to be NULL, but was %p.\n", builder);
9281
9282             hr = IUriBuilderFactory_CreateIUriBuilder(factory, 0, 0, NULL);
9283             ok(hr == E_POINTER, "Error: CreateInitializedIUriBuilder returned 0x%08x, expected 0x%08x.\n",
9284                 hr, E_POINTER);
9285
9286             builder = NULL;
9287             hr = IUriBuilderFactory_CreateIUriBuilder(factory, 0, 0, &builder);
9288             ok(hr == S_OK, "Error: CreateInitializedIUriBuilder returned 0x%08x, expected 0x%08x.\n",
9289                 hr, S_OK);
9290             if(SUCCEEDED(hr)) {
9291                 IUri *tmp = (void*) 0xdeadbeef;
9292                 LPCWSTR result;
9293                 DWORD result_len;
9294
9295                 hr = IUriBuilder_GetIUri(builder, &tmp);
9296                 ok(hr == S_OK, "Error: GetIUri returned 0x%08x, expected 0x%08x.\n",
9297                     hr, S_OK);
9298                 ok(!tmp, "Error: Expected 'tmp' to be NULL, but was %p instead.\n", tmp);
9299
9300                 hr = IUriBuilder_GetHost(builder, &result_len, &result);
9301                 ok(hr == S_FALSE, "Error: GetHost returned 0x%08x, expected 0x%08x.\n",
9302                     hr, S_FALSE);
9303             }
9304             if(builder) IUriBuilder_Release(builder);
9305
9306             builder = (void*) 0xdeadbeef;
9307             hr = IUriBuilderFactory_CreateInitializedIUriBuilder(factory, 10, 0, &builder);
9308             ok(hr == E_INVALIDARG, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n",
9309                 hr, E_INVALIDARG);
9310             ok(!builder, "Error: Expected 'builder' to be NULL, but was %p.\n", builder);
9311
9312             builder = (void*) 0xdeadbeef;
9313             hr = IUriBuilderFactory_CreateInitializedIUriBuilder(factory, 0, 10, &builder);
9314             ok(hr == E_INVALIDARG, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n",
9315                 hr, E_INVALIDARG);
9316             ok(!builder, "Error: Expected 'builder' to be NULL, but was %p.\n", builder);
9317
9318             hr = IUriBuilderFactory_CreateInitializedIUriBuilder(factory, 0, 0, NULL);
9319             ok(hr == E_POINTER, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n",
9320                 hr, E_POINTER);
9321
9322             builder = NULL;
9323             hr = IUriBuilderFactory_CreateInitializedIUriBuilder(factory, 0, 0, &builder);
9324             ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n",
9325                 hr, S_OK);
9326             if(SUCCEEDED(hr)) {
9327                 IUri *tmp = NULL;
9328
9329                 hr = IUriBuilder_GetIUri(builder, &tmp);
9330                 ok(hr == S_OK, "Error: GetIUri return 0x%08x, expected 0x%08x.\n",
9331                     hr, S_OK);
9332                 ok(tmp == uri, "Error: Expected tmp to be %p, but was %p.\n", uri, tmp);
9333                 if(uri) IUri_Release(uri);
9334             }
9335             if(builder) IUriBuilder_Release(builder);
9336         }
9337         if(factory) IUriBuilderFactory_Release(factory);
9338     }
9339     if(uri) IUri_Release(uri);
9340 }
9341
9342 static void test_CoInternetCombineIUri(void) {
9343     HRESULT hr;
9344     IUri *base, *relative, *result;
9345     DWORD i;
9346
9347     base = NULL;
9348     hr = pCreateUri(http_urlW, 0, 0, &base);
9349     ok(SUCCEEDED(hr), "Error: Expected CreateUri to succeed, got 0x%08x.\n", hr);
9350     if(SUCCEEDED(hr)) {
9351         result = (void*) 0xdeadbeef;
9352         hr = pCoInternetCombineIUri(base, NULL, 0, &result, 0);
9353         ok(hr == E_INVALIDARG, "Error: CoInternetCombineIUri returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
9354         ok(!result, "Error: Expected 'result' to be NULL, was %p.\n", result);
9355     }
9356
9357     relative = NULL;
9358     hr = pCreateUri(http_urlW, 0, 0, &relative);
9359     ok(SUCCEEDED(hr), "Error: Expected CreateUri to succeed, got 0x%08x.\n", hr);
9360     if(SUCCEEDED(hr)) {
9361         result = (void*) 0xdeadbeef;
9362         hr = pCoInternetCombineIUri(NULL, relative, 0, &result, 0);
9363         ok(hr == E_INVALIDARG, "Error: CoInternetCombineIUri returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
9364         ok(!result, "Error: Expected 'result' to be NULL, was %p.\n", result);
9365     }
9366
9367     hr = pCoInternetCombineIUri(base, relative, 0, NULL, 0);
9368     ok(hr == E_INVALIDARG, "Error: CoInternetCombineIUri returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
9369
9370     if(base) IUri_Release(base);
9371     if(relative) IUri_Release(relative);
9372
9373     for(i = 0; i < sizeof(uri_combine_tests)/sizeof(uri_combine_tests[0]); ++i) {
9374         LPWSTR baseW = a2w(uri_combine_tests[i].base_uri);
9375
9376         hr = pCreateUri(baseW, uri_combine_tests[i].base_create_flags, 0, &base);
9377         ok(SUCCEEDED(hr), "Error: Expected CreateUri to succeed, got 0x%08x on uri_combine_tests[%d].\n", hr, i);
9378         if(SUCCEEDED(hr)) {
9379             LPWSTR relativeW = a2w(uri_combine_tests[i].relative_uri);
9380
9381             hr = pCreateUri(relativeW, uri_combine_tests[i].relative_create_flags, 0, &relative);
9382             ok(SUCCEEDED(hr), "Error: Expected CreateUri to succeed, got 0x%08x on uri_combine_tests[%d].\n", hr, i);
9383             if(SUCCEEDED(hr)) {
9384                 result = NULL;
9385
9386                 hr = pCoInternetCombineIUri(base, relative, uri_combine_tests[i].combine_flags, &result, 0);
9387                 if(uri_combine_tests[i].todo) {
9388                     todo_wine {
9389                         ok(hr == uri_combine_tests[i].expected,
9390                             "Error: CoInternetCombineIUri returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].\n",
9391                             hr, uri_combine_tests[i].expected, i);
9392                     }
9393                 } else {
9394                     ok(hr == uri_combine_tests[i].expected,
9395                         "Error: CoInternetCombineIUri returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].\n",
9396                         hr, uri_combine_tests[i]. expected, i);
9397                 }
9398                 if(SUCCEEDED(hr)) {
9399                     DWORD j;
9400
9401                     for(j = 0; j < sizeof(uri_combine_tests[i].str_props)/sizeof(uri_combine_tests[i].str_props[0]); ++j) {
9402                         uri_combine_str_property prop = uri_combine_tests[i].str_props[j];
9403                         BSTR received;
9404
9405                         hr = IUri_GetPropertyBSTR(result, j, &received, 0);
9406                         if(prop.todo) {
9407                             todo_wine {
9408                                 ok(hr == prop.expected,
9409                                     "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].str_props[%d].\n",
9410                                     hr, prop.expected, i, j);
9411                             }
9412                             todo_wine {
9413                                 ok(!strcmp_aw(prop.value, received) ||
9414                                    broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
9415                                     "Error: Expected %s but got %s instead on uri_combine_tests[%d].str_props[%d].\n",
9416                                     prop.value, wine_dbgstr_w(received), i, j);
9417                             }
9418                         } else {
9419                             ok(hr == prop.expected,
9420                                 "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].str_props[%d].\n",
9421                                 hr, prop.expected, i, j);
9422                             ok(!strcmp_aw(prop.value, received) ||
9423                                broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
9424                                 "Error: Expected %s but got %s instead on uri_combine_tests[%d].str_props[%d].\n",
9425                                 prop.value, wine_dbgstr_w(received), i, j);
9426                         }
9427                         SysFreeString(received);
9428                     }
9429
9430                     for(j = 0; j < sizeof(uri_combine_tests[i].dword_props)/sizeof(uri_combine_tests[i].dword_props[0]); ++j) {
9431                         uri_dword_property prop = uri_combine_tests[i].dword_props[j];
9432                         DWORD received;
9433
9434                         hr = IUri_GetPropertyDWORD(result, j+Uri_PROPERTY_DWORD_START, &received, 0);
9435                         if(prop.todo) {
9436                             todo_wine {
9437                                 ok(hr == prop.expected,
9438                                     "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].dword_props[%d].\n",
9439                                     hr, prop.expected, i, j);
9440                             }
9441                             todo_wine {
9442                                 ok(prop.value == received, "Error: Expected %d, but got %d instead on uri_combine_tests[%d].dword_props[%d].\n",
9443                                     prop.value, received, i, j);
9444                             }
9445                         } else {
9446                             ok(hr == prop.expected,
9447                                 "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].dword_props[%d].\n",
9448                                 hr, prop.expected, i, j);
9449                             ok(prop.value == received, "Error: Expected %d, but got %d instead on uri_combine_tests[%d].dword_props[%d].\n",
9450                                 prop.value, received, i, j);
9451                         }
9452                     }
9453                 }
9454                 if(result) IUri_Release(result);
9455             }
9456             if(relative) IUri_Release(relative);
9457             heap_free(relativeW);
9458         }
9459         if(base) IUri_Release(base);
9460         heap_free(baseW);
9461     }
9462 }
9463
9464 static HRESULT WINAPI InternetProtocolInfo_QueryInterface(IInternetProtocolInfo *iface,
9465                                                           REFIID riid, void **ppv)
9466 {
9467     ok(0, "unexpected call\n");
9468     return E_NOINTERFACE;
9469 }
9470
9471 static ULONG WINAPI InternetProtocolInfo_AddRef(IInternetProtocolInfo *iface)
9472 {
9473     return 2;
9474 }
9475
9476 static ULONG WINAPI InternetProtocolInfo_Release(IInternetProtocolInfo *iface)
9477 {
9478     return 1;
9479 }
9480
9481 static HRESULT WINAPI InternetProtocolInfo_ParseUrl(IInternetProtocolInfo *iface, LPCWSTR pwzUrl,
9482         PARSEACTION ParseAction, DWORD dwParseFlags, LPWSTR pwzResult, DWORD cchResult,
9483         DWORD *pcchResult, DWORD dwReserved)
9484 {
9485     CHECK_EXPECT(ParseUrl);
9486     ok(!lstrcmpW(pwzUrl, parse_urlW), "Error: Expected %s, but got %s instead.\n",
9487         wine_dbgstr_w(parse_urlW), wine_dbgstr_w(pwzUrl));
9488     ok(ParseAction == parse_action, "Error: Expected %d, but got %d.\n", parse_action, ParseAction);
9489     ok(dwParseFlags == parse_flags, "Error: Expected 0x%08x, but got 0x%08x.\n", parse_flags, dwParseFlags);
9490     ok(cchResult == 200, "Error: Got %d.\n", cchResult);
9491
9492     memcpy(pwzResult, parse_resultW, sizeof(parse_resultW));
9493     *pcchResult = lstrlenW(parse_resultW);
9494
9495     return S_OK;
9496 }
9497
9498 static HRESULT WINAPI InternetProtocolInfo_CombineUrl(IInternetProtocolInfo *iface,
9499         LPCWSTR pwzBaseUrl, LPCWSTR pwzRelativeUrl, DWORD dwCombineFlags,
9500         LPWSTR pwzResult, DWORD cchResult, DWORD *pcchResult, DWORD dwReserved)
9501 {
9502     CHECK_EXPECT(CombineUrl);
9503     ok(!lstrcmpW(pwzBaseUrl, combine_baseW), "Error: Expected %s, but got %s instead.\n",
9504         wine_dbgstr_w(combine_baseW), wine_dbgstr_w(pwzBaseUrl));
9505     ok(!lstrcmpW(pwzRelativeUrl, combine_relativeW), "Error: Expected %s, but got %s instead.\n",
9506         wine_dbgstr_w(combine_relativeW), wine_dbgstr_w(pwzRelativeUrl));
9507     ok(dwCombineFlags == (URL_DONT_SIMPLIFY|URL_FILE_USE_PATHURL|URL_DONT_UNESCAPE_EXTRA_INFO),
9508         "Error: Expected 0, but got 0x%08x.\n", dwCombineFlags);
9509     ok(cchResult == INTERNET_MAX_URL_LENGTH+1, "Error: Got %d.\n", cchResult);
9510
9511     memcpy(pwzResult, combine_resultW, sizeof(combine_resultW));
9512     *pcchResult = lstrlenW(combine_resultW);
9513
9514     return S_OK;
9515 }
9516
9517 static HRESULT WINAPI InternetProtocolInfo_CompareUrl(IInternetProtocolInfo *iface,
9518         LPCWSTR pwzUrl1, LPCWSTR pwzUrl2, DWORD dwCompareFlags)
9519 {
9520     ok(0, "unexpected call\n");
9521     return E_NOTIMPL;
9522 }
9523
9524 static HRESULT WINAPI InternetProtocolInfo_QueryInfo(IInternetProtocolInfo *iface,
9525         LPCWSTR pwzUrl, QUERYOPTION OueryOption, DWORD dwQueryFlags, LPVOID pBuffer,
9526         DWORD cbBuffer, DWORD *pcbBuf, DWORD dwReserved)
9527 {
9528     ok(0, "unexpected call\n");
9529     return E_NOTIMPL;
9530 }
9531
9532 static const IInternetProtocolInfoVtbl InternetProtocolInfoVtbl = {
9533     InternetProtocolInfo_QueryInterface,
9534     InternetProtocolInfo_AddRef,
9535     InternetProtocolInfo_Release,
9536     InternetProtocolInfo_ParseUrl,
9537     InternetProtocolInfo_CombineUrl,
9538     InternetProtocolInfo_CompareUrl,
9539     InternetProtocolInfo_QueryInfo
9540 };
9541
9542 static IInternetProtocolInfo protocol_info = { &InternetProtocolInfoVtbl };
9543
9544 static HRESULT WINAPI ClassFactory_QueryInterface(IClassFactory *iface, REFIID riid, void **ppv)
9545 {
9546     if(IsEqualGUID(&IID_IInternetProtocolInfo, riid)) {
9547         *ppv = &protocol_info;
9548         return S_OK;
9549     }
9550
9551     ok(0, "unexpected call\n");
9552     return E_NOINTERFACE;
9553 }
9554
9555 static ULONG WINAPI ClassFactory_AddRef(IClassFactory *iface)
9556 {
9557     return 2;
9558 }
9559
9560 static ULONG WINAPI ClassFactory_Release(IClassFactory *iface)
9561 {
9562     return 1;
9563 }
9564
9565 static HRESULT WINAPI ClassFactory_CreateInstance(IClassFactory *iface, IUnknown *pOuter,
9566                                         REFIID riid, void **ppv)
9567 {
9568     ok(0, "unexpected call\n");
9569     return E_NOTIMPL;
9570 }
9571
9572 static HRESULT WINAPI ClassFactory_LockServer(IClassFactory *iface, BOOL dolock)
9573 {
9574     ok(0, "unexpected call\n");
9575     return S_OK;
9576 }
9577
9578 static const IClassFactoryVtbl ClassFactoryVtbl = {
9579     ClassFactory_QueryInterface,
9580     ClassFactory_AddRef,
9581     ClassFactory_Release,
9582     ClassFactory_CreateInstance,
9583     ClassFactory_LockServer
9584 };
9585
9586 static IClassFactory protocol_cf = { &ClassFactoryVtbl };
9587
9588 static void register_protocols(void)
9589 {
9590     IInternetSession *session;
9591     HRESULT hres;
9592
9593     hres = pCoInternetGetSession(0, &session, 0);
9594     ok(hres == S_OK, "CoInternetGetSession failed: %08x\n", hres);
9595     if(FAILED(hres))
9596         return;
9597
9598     hres = IInternetSession_RegisterNameSpace(session, &protocol_cf, &IID_NULL,
9599             winetestW, 0, NULL, 0);
9600     ok(hres == S_OK, "RegisterNameSpace failed: %08x\n", hres);
9601
9602     IInternetSession_Release(session);
9603 }
9604
9605 static void unregister_protocols(void) {
9606     IInternetSession *session;
9607     HRESULT hr;
9608
9609     hr = pCoInternetGetSession(0, &session, 0);
9610     ok(hr == S_OK, "CoInternetGetSession failed: 0x%08x\n", hr);
9611     if(FAILED(hr))
9612         return;
9613
9614     hr = IInternetSession_UnregisterNameSpace(session, &protocol_cf, winetestW);
9615     ok(hr == S_OK, "UnregisterNameSpace failed: 0x%08x\n", hr);
9616
9617     IInternetSession_Release(session);
9618 }
9619
9620 static void test_CoInternetCombineIUri_Pluggable(void) {
9621     HRESULT hr;
9622     IUri *base = NULL;
9623
9624     hr = pCreateUri(combine_baseW, 0, 0, &base);
9625     ok(SUCCEEDED(hr), "Error: CreateUri returned 0x%08x.\n", hr);
9626     if(SUCCEEDED(hr)) {
9627         IUri *relative = NULL;
9628
9629         hr = pCreateUri(combine_relativeW, Uri_CREATE_ALLOW_RELATIVE, 0, &relative);
9630         ok(SUCCEEDED(hr), "Error: CreateUri returned 0x%08x.\n", hr);
9631         if(SUCCEEDED(hr)) {
9632             IUri *result = NULL;
9633
9634             SET_EXPECT(CombineUrl);
9635
9636             hr = pCoInternetCombineIUri(base, relative, URL_DONT_SIMPLIFY|URL_FILE_USE_PATHURL|URL_DONT_UNESCAPE_EXTRA_INFO,
9637                                         &result, 0);
9638             ok(hr == S_OK, "Error: CoInternetCombineIUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9639
9640             CHECK_CALLED(CombineUrl);
9641
9642             if(SUCCEEDED(hr)) {
9643                 BSTR received = NULL;
9644                 hr = IUri_GetAbsoluteUri(result, &received);
9645                 ok(hr == S_OK, "Error: Expected S_OK, but got 0x%08x instead.\n", hr);
9646                 if(SUCCEEDED(hr)) {
9647                     ok(!lstrcmpW(combine_resultW, received), "Error: Expected %s, but got %s.\n",
9648                         wine_dbgstr_w(combine_resultW), wine_dbgstr_w(received));
9649                 }
9650                 SysFreeString(received);
9651             }
9652             if(result) IUri_Release(result);
9653         }
9654         if(relative) IUri_Release(relative);
9655     }
9656     if(base) IUri_Release(base);
9657 }
9658
9659 static void test_CoInternetCombineUrlEx(void) {
9660     HRESULT hr;
9661     IUri *base, *result;
9662     DWORD i;
9663
9664     base = NULL;
9665     hr = pCreateUri(http_urlW, 0, 0, &base);
9666     ok(SUCCEEDED(hr), "Error: CreateUri returned 0x%08x.\n", hr);
9667     if(SUCCEEDED(hr)) {
9668         result = (void*) 0xdeadbeef;
9669         hr = pCoInternetCombineUrlEx(base, NULL, 0, &result, 0);
9670         ok(hr == E_UNEXPECTED, "Error: CoInternetCombineUrlEx returned 0x%08x, expected 0x%08x.\n",
9671             hr, E_UNEXPECTED);
9672         ok(!result, "Error: Expected 'result' to be NULL was %p instead.\n", result);
9673     }
9674
9675     result = (void*) 0xdeadbeef;
9676     hr = pCoInternetCombineUrlEx(NULL, http_urlW, 0, &result, 0);
9677     ok(hr == E_INVALIDARG, "Error: CoInternetCombineUrlEx returned 0x%08x, expected 0x%08x.\n",
9678         hr, E_INVALIDARG);
9679     ok(!result, "Error: Expected 'result' to be NULL, but was %p instead.\n", result);
9680
9681     result = (void*) 0xdeadbeef;
9682     hr = pCoInternetCombineUrlEx(NULL, NULL, 0, &result, 0);
9683     ok(hr == E_UNEXPECTED, "Error: CoInternetCombineUrlEx returned 0x%08x, expected 0x%08x.\n",
9684         hr, E_UNEXPECTED);
9685     ok(!result, "Error: Expected 'result' to be NULL, but was %p instead.\n", result);
9686
9687     hr = pCoInternetCombineUrlEx(base, http_urlW, 0, NULL, 0);
9688     ok(hr == E_POINTER, "Error: CoInternetCombineUrlEx returned 0x%08x, expected 0x%08x.\n",
9689         hr, E_POINTER);
9690     if(base) IUri_Release(base);
9691
9692     for(i = 0; i < sizeof(uri_combine_tests)/sizeof(uri_combine_tests[0]); ++i) {
9693         LPWSTR baseW = a2w(uri_combine_tests[i].base_uri);
9694
9695         hr = pCreateUri(baseW, uri_combine_tests[i].base_create_flags, 0, &base);
9696         ok(SUCCEEDED(hr), "Error: CreateUri returned 0x%08x on uri_combine_tests[%d].\n", hr, i);
9697         if(SUCCEEDED(hr)) {
9698             LPWSTR relativeW = a2w(uri_combine_tests[i].relative_uri);
9699
9700             hr = pCoInternetCombineUrlEx(base, relativeW, uri_combine_tests[i].combine_flags,
9701                                          &result, 0);
9702             if(uri_combine_tests[i].todo) {
9703                 todo_wine {
9704                     ok(hr == uri_combine_tests[i].expected,
9705                         "Error: CoInternetCombineUrlEx returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].\n",
9706                         hr, uri_combine_tests[i].expected, i);
9707                 }
9708             } else {
9709                 ok(hr == uri_combine_tests[i].expected,
9710                     "Error: CoInternetCombineUrlEx returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].\n",
9711                     hr, uri_combine_tests[i]. expected, i);
9712             }
9713             if(SUCCEEDED(hr)) {
9714                 DWORD j;
9715
9716                 for(j = 0; j < sizeof(uri_combine_tests[i].str_props)/sizeof(uri_combine_tests[i].str_props[0]); ++j) {
9717                     uri_combine_str_property prop = uri_combine_tests[i].str_props[j];
9718                     BSTR received;
9719                     LPCSTR value = (prop.value_ex) ? prop.value_ex : prop.value;
9720
9721                     hr = IUri_GetPropertyBSTR(result, j, &received, 0);
9722                     if(prop.todo) {
9723                         todo_wine {
9724                             ok(hr == prop.expected,
9725                                 "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].str_props[%d].\n",
9726                                 hr, prop.expected, i, j);
9727                         }
9728                         todo_wine {
9729                             ok(!strcmp_aw(value, received) ||
9730                                broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
9731                                 "Error: Expected %s but got %s instead on uri_combine_tests[%d].str_props[%d].\n",
9732                                 value, wine_dbgstr_w(received), i, j);
9733                         }
9734                     } else {
9735                         ok(hr == prop.expected,
9736                             "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].str_props[%d].\n",
9737                             hr, prop.expected, i, j);
9738                         ok(!strcmp_aw(value, received) ||
9739                            broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
9740                             "Error: Expected %s but got %s instead on uri_combine_tests[%d].str_props[%d].\n",
9741                             value, wine_dbgstr_w(received), i, j);
9742                     }
9743                     SysFreeString(received);
9744                 }
9745
9746                 for(j = 0; j < sizeof(uri_combine_tests[i].dword_props)/sizeof(uri_combine_tests[i].dword_props[0]); ++j) {
9747                     uri_dword_property prop = uri_combine_tests[i].dword_props[j];
9748                     DWORD received;
9749
9750                     hr = IUri_GetPropertyDWORD(result, j+Uri_PROPERTY_DWORD_START, &received, 0);
9751                     if(prop.todo) {
9752                         todo_wine {
9753                             ok(hr == prop.expected,
9754                                 "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].dword_props[%d].\n",
9755                                 hr, prop.expected, i, j);
9756                         }
9757                         todo_wine {
9758                             ok(prop.value == received, "Error: Expected %d, but got %d instead on uri_combine_tests[%d].dword_props[%d].\n",
9759                                 prop.value, received, i, j);
9760                         }
9761                     } else {
9762                         ok(hr == prop.expected,
9763                             "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].dword_props[%d].\n",
9764                             hr, prop.expected, i, j);
9765                         ok(prop.value == received, "Error: Expected %d, but got %d instead on uri_combine_tests[%d].dword_props[%d].\n",
9766                             prop.value, received, i, j);
9767                     }
9768                 }
9769             }
9770             if(result) IUri_Release(result);
9771             heap_free(relativeW);
9772         }
9773         if(base) IUri_Release(base);
9774         heap_free(baseW);
9775     }
9776 }
9777
9778 static void test_CoInternetCombineUrlEx_Pluggable(void) {
9779     HRESULT hr;
9780     IUri *base = NULL;
9781
9782     hr = pCreateUri(combine_baseW, 0, 0, &base);
9783     ok(SUCCEEDED(hr), "Error: CreateUri returned 0x%08x.\n", hr);
9784     if(SUCCEEDED(hr)) {
9785         IUri *result = NULL;
9786
9787         SET_EXPECT(CombineUrl);
9788
9789         hr = pCoInternetCombineUrlEx(base, combine_relativeW, URL_DONT_SIMPLIFY|URL_FILE_USE_PATHURL|URL_DONT_UNESCAPE_EXTRA_INFO,
9790                                      &result, 0);
9791         ok(hr == S_OK, "Error: CoInternetCombineUrlEx returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9792
9793         CHECK_CALLED(CombineUrl);
9794
9795         if(SUCCEEDED(hr)) {
9796             BSTR received = NULL;
9797             hr = IUri_GetAbsoluteUri(result, &received);
9798             ok(hr == S_OK, "Error: Expected S_OK, but got 0x%08x instead.\n", hr);
9799             if(SUCCEEDED(hr)) {
9800                 ok(!lstrcmpW(combine_resultW, received), "Error: Expected %s, but got %s.\n",
9801                     wine_dbgstr_w(combine_resultW), wine_dbgstr_w(received));
9802             }
9803             SysFreeString(received);
9804         }
9805         if(result) IUri_Release(result);
9806     }
9807     if(base) IUri_Release(base);
9808 }
9809
9810 static void test_CoInternetParseIUri_InvalidArgs(void) {
9811     HRESULT hr;
9812     IUri *uri = NULL;
9813     WCHAR tmp[3];
9814     DWORD result = -1;
9815
9816     hr = pCoInternetParseIUri(NULL, PARSE_CANONICALIZE, 0, tmp, 3, &result, 0);
9817     ok(hr == E_INVALIDARG, "Error: CoInternetParseIUri returned 0x%08x, expected 0x%08x.\n",
9818         hr, E_INVALIDARG);
9819     ok(!result, "Error: Expected 'result' to be 0, but was %d.\n", result);
9820
9821     hr = pCreateUri(http_urlW, 0, 0, &uri);
9822     ok(SUCCEEDED(hr), "Error: CreateUri returned 0x%08x.\n", hr);
9823     if(SUCCEEDED(hr)) {
9824         DWORD expected_len;
9825
9826         result = -1;
9827         hr = pCoInternetParseIUri(uri, PARSE_CANONICALIZE, 0, NULL, 0, &result, 0);
9828         ok(hr == E_INVALIDARG, "Error: CoInternetParseIUri returned 0x%08x, expected 0x%08x.\n",
9829             hr, E_INVALIDARG);
9830         ok(!result, "Error: Expected 'result' to be 0, but was %d.\n", result);
9831
9832         hr = pCoInternetParseIUri(uri, PARSE_CANONICALIZE, 0, tmp, 3, NULL, 0);
9833         ok(hr == E_POINTER, "Error: CoInternetParseIUri returned 0x%08x, expected 0x%08x.\n",
9834             hr, E_POINTER);
9835
9836         result = -1;
9837         hr = pCoInternetParseIUri(uri, PARSE_SECURITY_URL, 0, tmp, 3, &result, 0);
9838         ok(hr == E_FAIL, "Error: CoInternetParseIUri returned 0x%08x expected 0x%08x.\n",
9839             hr, E_FAIL);
9840         ok(!result, "Error: Expected 'result' to be 0, but was %d.\n", result);
9841
9842         result = -1;
9843         hr = pCoInternetParseIUri(uri, PARSE_MIME, 0, tmp, 3, &result, 0);
9844         ok(hr == E_FAIL, "Error: CoInternetParseIUri returned 0x%08x, expected 0x%08x.\n",
9845             hr, E_FAIL);
9846         ok(!result, "Error: Expected 'result' to be 0, but was %d.\n", result);
9847
9848         result = -1;
9849         hr = pCoInternetParseIUri(uri, PARSE_SERVER, 0, tmp, 3, &result, 0);
9850         ok(hr == E_FAIL, "Error: CoInternetParseIUri returned 0x%08x, expected 0x%08x.\n",
9851             hr, E_FAIL);
9852         ok(!result, "Error: Expected 'result' to be 0, but was %d.\n", result);
9853
9854         result = -1;
9855         hr = pCoInternetParseIUri(uri, PARSE_SECURITY_DOMAIN, 0, tmp, 3, &result, 0);
9856         ok(hr == E_FAIL, "Error: CoInternetParseIUri returned 0x%08x, expected 0x%08x.\n",
9857             hr, E_FAIL);
9858         ok(!result, "Error: Expected 'result' to be 0, but was %d.\n", result);
9859
9860         expected_len = lstrlenW(http_urlW);
9861         result = -1;
9862         hr = pCoInternetParseIUri(uri, PARSE_CANONICALIZE, 0, tmp, 3, &result, 0);
9863         ok(hr == STRSAFE_E_INSUFFICIENT_BUFFER,
9864             "Error: CoInternetParseIUri returned 0x%08x, expected 0x%08x.\n",
9865             hr, STRSAFE_E_INSUFFICIENT_BUFFER);
9866         ok(result == expected_len, "Error: Expected 'result' to be %d, but was %d instead.\n",
9867             expected_len, result);
9868     }
9869     if(uri) IUri_Release(uri);
9870 }
9871
9872 static void test_CoInternetParseIUri(void) {
9873     DWORD i;
9874
9875     for(i = 0; i < sizeof(uri_parse_tests)/sizeof(uri_parse_tests[0]); ++i) {
9876         HRESULT hr;
9877         IUri *uri;
9878         LPWSTR uriW;
9879         uri_parse_test test = uri_parse_tests[i];
9880
9881         uriW = a2w(test.uri);
9882         hr = pCreateUri(uriW, test.uri_flags, 0, &uri);
9883         ok(SUCCEEDED(hr), "Error: CreateUri returned 0x%08x on uri_parse_tests[%d].\n", hr, i);
9884         if(SUCCEEDED(hr)) {
9885             WCHAR result[INTERNET_MAX_URL_LENGTH+1];
9886             DWORD result_len = -1;
9887
9888             hr = pCoInternetParseIUri(uri, test.action, test.flags, result, INTERNET_MAX_URL_LENGTH+1, &result_len, 0);
9889             if(test.todo) {
9890                 todo_wine {
9891                     ok(hr == test.expected,
9892                         "Error: CoInternetParseIUri returned 0x%08x, expected 0x%08x on uri_parse_tests[%d].\n",
9893                         hr, test.expected, i);
9894                 }
9895             } else {
9896                 ok(hr == test.expected,
9897                     "Error: CoInternetParseIUri returned 0x%08x, expected 0x%08x on uri_parse_tests[%d].\n",
9898                     hr, test.expected, i);
9899             }
9900             if(SUCCEEDED(hr)) {
9901                 DWORD len = lstrlenA(test.property);
9902                 ok(!strcmp_aw(test.property, result),
9903                     "Error: Expected %s but got %s instead on uri_parse_tests[%d].\n",
9904                     test.property, wine_dbgstr_w(result), i);
9905                 ok(len == result_len,
9906                     "Error: Expected %d, but got %d instead on uri_parse_tests[%d].\n",
9907                     len, result_len, i);
9908             } else {
9909                 ok(!result_len,
9910                     "Error: Expected 'result_len' to be 0, but was %d on uri_parse_tests[%d].\n",
9911                     result_len, i);
9912             }
9913         }
9914         if(uri) IUri_Release(uri);
9915         heap_free(uriW);
9916     }
9917 }
9918
9919 static void test_CoInternetParseIUri_Pluggable(void) {
9920     HRESULT hr;
9921     IUri *uri = NULL;
9922
9923     hr = pCreateUri(parse_urlW, 0, 0, &uri);
9924     ok(SUCCEEDED(hr), "Error: Expected CreateUri to succeed, but got 0x%08x.\n", hr);
9925     if(SUCCEEDED(hr)) {
9926         WCHAR result[200];
9927         DWORD result_len;
9928
9929         SET_EXPECT(ParseUrl);
9930
9931         parse_action = PARSE_CANONICALIZE;
9932         parse_flags = URL_UNESCAPE|URL_ESCAPE_UNSAFE;
9933
9934         hr = pCoInternetParseIUri(uri, parse_action, parse_flags, result, 200, &result_len, 0);
9935         ok(hr == S_OK, "Error: CoInternetParseIUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9936
9937         CHECK_CALLED(ParseUrl);
9938
9939         if(SUCCEEDED(hr)) {
9940             ok(result_len == lstrlenW(parse_resultW), "Error: Expected %d, but got %d.\n",
9941                 lstrlenW(parse_resultW), result_len);
9942             ok(!lstrcmpW(result, parse_resultW), "Error: Expected %s, but got %s.\n",
9943                 wine_dbgstr_w(parse_resultW), wine_dbgstr_w(result));
9944         }
9945     }
9946     if(uri) IUri_Release(uri);
9947 }
9948
9949 START_TEST(uri) {
9950     HMODULE hurlmon;
9951
9952     hurlmon = GetModuleHandle("urlmon.dll");
9953     pCoInternetGetSession = (void*) GetProcAddress(hurlmon, "CoInternetGetSession");
9954     pCreateUri = (void*) GetProcAddress(hurlmon, "CreateUri");
9955     pCreateUriWithFragment = (void*) GetProcAddress(hurlmon, "CreateUriWithFragment");
9956     pCreateIUriBuilder = (void*) GetProcAddress(hurlmon, "CreateIUriBuilder");
9957     pCoInternetCombineIUri = (void*) GetProcAddress(hurlmon, "CoInternetCombineIUri");
9958     pCoInternetCombineUrlEx = (void*) GetProcAddress(hurlmon, "CoInternetCombineUrlEx");
9959     pCoInternetParseIUri = (void*) GetProcAddress(hurlmon, "CoInternetParseIUri");
9960
9961     if(!pCreateUri) {
9962         win_skip("CreateUri is not present, skipping tests.\n");
9963         return;
9964     }
9965
9966     trace("test CreateUri invalid flags...\n");
9967     test_CreateUri_InvalidFlags();
9968
9969     trace("test CreateUri invalid args...\n");
9970     test_CreateUri_InvalidArgs();
9971
9972     trace("test CreateUri invalid URIs...\n");
9973     test_CreateUri_InvalidUri();
9974
9975     trace("test IUri_GetPropertyBSTR...\n");
9976     test_IUri_GetPropertyBSTR();
9977
9978     trace("test IUri_GetPropertyDWORD...\n");
9979     test_IUri_GetPropertyDWORD();
9980
9981     trace("test IUri_GetStrProperties...\n");
9982     test_IUri_GetStrProperties();
9983
9984     trace("test IUri_GetDwordProperties...\n");
9985     test_IUri_GetDwordProperties();
9986
9987     trace("test IUri_GetPropertyLength...\n");
9988     test_IUri_GetPropertyLength();
9989
9990     trace("test IUri_GetProperties...\n");
9991     test_IUri_GetProperties();
9992
9993     trace("test IUri_HasProperty...\n");
9994     test_IUri_HasProperty();
9995
9996     trace("test IUri_IsEqual...\n");
9997     test_IUri_IsEqual();
9998
9999     trace("test CreateUriWithFragment invalid args...\n");
10000     test_CreateUriWithFragment_InvalidArgs();
10001
10002     trace("test CreateUriWithFragment invalid flags...\n");
10003     test_CreateUriWithFragment_InvalidFlags();
10004
10005     trace("test CreateUriWithFragment...\n");
10006     test_CreateUriWithFragment();
10007
10008     trace("test CreateIUriBuilder...\n");
10009     test_CreateIUriBuilder();
10010
10011     trace("test IUriBuilder_CreateInvalidArgs...\n");
10012     test_IUriBuilder_CreateInvalidArgs();
10013
10014     trace("test IUriBuilder...\n");
10015     test_IUriBuilder();
10016
10017     trace("test IUriBuilder_GetInvalidArgs...\n");
10018     test_IUriBuilder_GetInvalidArgs();
10019
10020     trace("test IUriBuilder_HasBeenModified...\n");
10021     test_IUriBuilder_HasBeenModified();
10022
10023     trace("test IUriBuilder_IUriProperty...\n");
10024     test_IUriBuilder_IUriProperty();
10025
10026     trace("test IUriBuilder_RemoveProperties...\n");
10027     test_IUriBuilder_RemoveProperties();
10028
10029     trace("test IUriBuilder miscellaneous...\n");
10030     test_IUriBuilder_Misc();
10031
10032     trace("test IUriBuilderFactory...\n");
10033     test_IUriBuilderFactory();
10034
10035     trace("test CoInternetCombineIUri...\n");
10036     test_CoInternetCombineIUri();
10037
10038     trace("test CoInternetCombineUrlEx...\n");
10039     test_CoInternetCombineUrlEx();
10040
10041     trace("test CoInternetParseIUri Invalid Args...\n");
10042     test_CoInternetParseIUri_InvalidArgs();
10043
10044     trace("test CoInternetParseIUri...\n");
10045     test_CoInternetParseIUri();
10046
10047     register_protocols();
10048
10049     trace("test CoInternetCombineIUri pluggable...\n");
10050     test_CoInternetCombineIUri_Pluggable();
10051
10052     trace("test CoInternetCombineUrlEx Pluggable...\n");
10053     test_CoInternetCombineUrlEx_Pluggable();
10054
10055     trace("test CoInternetParseIUri pluggable...\n");
10056     test_CoInternetParseIUri_Pluggable();
10057
10058     unregister_protocols();
10059 }