mshtml: Pass DispatchEx pointer instead of outer IUnknown to DispatchEx's vtbl functions.
[wine] / dlls / urlmon / tests / uri.c
1 /*
2  * UrlMon IUri tests
3  *
4  * Copyright 2010 Thomas Mullaly
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #include <wine/test.h>
22 #include <stdarg.h>
23 #include <stddef.h>
24
25 #define COBJMACROS
26 #define CONST_VTABLE
27
28 #include "windef.h"
29 #include "winbase.h"
30 #include "urlmon.h"
31 #include "shlwapi.h"
32 #include "wininet.h"
33 #include "strsafe.h"
34
35 #define URI_STR_PROPERTY_COUNT Uri_PROPERTY_STRING_LAST+1
36 #define URI_DWORD_PROPERTY_COUNT (Uri_PROPERTY_DWORD_LAST - Uri_PROPERTY_DWORD_START)+1
37 #define URI_BUILDER_STR_PROPERTY_COUNT 7
38
39 #define DEFINE_EXPECT(func) \
40     static BOOL expect_ ## func = FALSE, called_ ## func = FALSE
41
42 #define SET_EXPECT(func) \
43     expect_ ## func = TRUE
44
45 #define CHECK_EXPECT(func) \
46     do { \
47         ok(expect_ ##func, "unexpected call " #func "\n"); \
48         expect_ ## func = FALSE; \
49         called_ ## func = TRUE; \
50     }while(0)
51
52 #define CHECK_EXPECT2(func) \
53     do { \
54         ok(expect_ ##func, "unexpected call " #func "\n"); \
55         called_ ## func = TRUE; \
56     }while(0)
57
58 #define CHECK_CALLED(func) \
59     do { \
60         ok(called_ ## func, "expected " #func "\n"); \
61         expect_ ## func = called_ ## func = FALSE; \
62     }while(0)
63
64 DEFINE_EXPECT(CombineUrl);
65 DEFINE_EXPECT(ParseUrl);
66
67 static HRESULT (WINAPI *pCreateUri)(LPCWSTR, DWORD, DWORD_PTR, IUri**);
68 static HRESULT (WINAPI *pCreateUriWithFragment)(LPCWSTR, LPCWSTR, DWORD, DWORD_PTR, IUri**);
69 static HRESULT (WINAPI *pCreateIUriBuilder)(IUri*, DWORD, DWORD_PTR, IUriBuilder**);
70 static HRESULT (WINAPI *pCoInternetCombineIUri)(IUri*,IUri*,DWORD,IUri**,DWORD_PTR);
71 static HRESULT (WINAPI *pCoInternetGetSession)(DWORD,IInternetSession**,DWORD);
72 static HRESULT (WINAPI *pCoInternetCombineUrlEx)(IUri*,LPCWSTR,DWORD,IUri**,DWORD_PTR);
73 static HRESULT (WINAPI *pCoInternetParseIUri)(IUri*,PARSEACTION,DWORD,LPWSTR,DWORD,DWORD*,DWORD_PTR);
74
75 static const WCHAR http_urlW[] = { 'h','t','t','p',':','/','/','w','w','w','.','w','i','n','e','h','q',
76         '.','o','r','g','/',0};
77 static const WCHAR http_url_fragW[] = { 'h','t','t','p',':','/','/','w','w','w','.','w','i','n','e','h','q',
78         '.','o','r','g','/','#','F','r','a','g',0};
79
80 static const WCHAR combine_baseW[] = {'w','i','n','e','t','e','s','t',':','?','t',
81         'e','s','t','i','n','g',0};
82 static const WCHAR combine_relativeW[] = {'?','t','e','s','t',0};
83 static const WCHAR combine_resultW[] = {'z','i','p',':','t','e','s','t',0};
84
85 static const WCHAR winetestW[] = {'w','i','n','e','t','e','s','t',0};
86
87 static const WCHAR parse_urlW[] = {'w','i','n','e','t','e','s','t',':','t','e','s','t',0};
88 static const WCHAR parse_resultW[] = {'z','i','p',':','t','e','s','t',0};
89
90 static PARSEACTION parse_action;
91 static DWORD parse_flags;
92
93 typedef struct _uri_create_flag_test {
94     DWORD   flags;
95     HRESULT expected;
96 } uri_create_flag_test;
97
98 static const uri_create_flag_test invalid_flag_tests[] = {
99     /* Set of invalid flag combinations to test for. */
100     {Uri_CREATE_DECODE_EXTRA_INFO | Uri_CREATE_NO_DECODE_EXTRA_INFO, E_INVALIDARG},
101     {Uri_CREATE_CANONICALIZE | Uri_CREATE_NO_CANONICALIZE, E_INVALIDARG},
102     {Uri_CREATE_CRACK_UNKNOWN_SCHEMES | Uri_CREATE_NO_CRACK_UNKNOWN_SCHEMES, E_INVALIDARG},
103     {Uri_CREATE_PRE_PROCESS_HTML_URI | Uri_CREATE_NO_PRE_PROCESS_HTML_URI, E_INVALIDARG},
104     {Uri_CREATE_IE_SETTINGS | Uri_CREATE_NO_IE_SETTINGS, E_INVALIDARG}
105 };
106
107 typedef struct _uri_str_property {
108     const char* value;
109     HRESULT     expected;
110     BOOL        todo;
111     const char* broken_value;
112 } uri_str_property;
113
114 typedef struct _uri_dword_property {
115     DWORD   value;
116     HRESULT expected;
117     BOOL    todo;
118 } uri_dword_property;
119
120 typedef struct _uri_properties {
121     const char*         uri;
122     DWORD               create_flags;
123     HRESULT             create_expected;
124     BOOL                create_todo;
125
126     uri_str_property    str_props[URI_STR_PROPERTY_COUNT];
127     uri_dword_property  dword_props[URI_DWORD_PROPERTY_COUNT];
128 } uri_properties;
129
130 static const uri_properties uri_tests[] = {
131     {   "http://www.winehq.org/tests/../tests/../..", 0, S_OK, FALSE,
132         {
133             {"http://www.winehq.org/",S_OK,FALSE},                      /* ABSOLUTE_URI */
134             {"www.winehq.org",S_OK,FALSE},                              /* AUTHORITY */
135             {"http://www.winehq.org/",S_OK,FALSE},                      /* DISPLAY_URI */
136             {"winehq.org",S_OK,FALSE},                                  /* DOMAIN */
137             {"",S_FALSE,FALSE},                                         /* EXTENSION */
138             {"",S_FALSE,FALSE},                                         /* FRAGMENT */
139             {"www.winehq.org",S_OK,FALSE},                              /* HOST */
140             {"",S_FALSE,FALSE},                                         /* PASSWORD */
141             {"/",S_OK,FALSE},                                           /* PATH */
142             {"/",S_OK,FALSE},                                           /* PATH_AND_QUERY */
143             {"",S_FALSE,FALSE},                                         /* QUERY */
144             {"http://www.winehq.org/tests/../tests/../..",S_OK,FALSE},  /* RAW_URI */
145             {"http",S_OK,FALSE},                                        /* SCHEME_NAME */
146             {"",S_FALSE,FALSE},                                         /* USER_INFO */
147             {"",S_FALSE,FALSE}                                          /* USER_NAME */
148         },
149         {
150             {Uri_HOST_DNS,S_OK,FALSE},                                  /* HOST_TYPE */
151             {80,S_OK,FALSE},                                            /* PORT */
152             {URL_SCHEME_HTTP,S_OK,FALSE},                               /* SCHEME */
153             {URLZONE_INVALID,E_NOTIMPL,FALSE}                           /* ZONE */
154         }
155     },
156     {   "http://winehq.org/tests/.././tests", 0, S_OK, FALSE,
157         {
158             {"http://winehq.org/tests",S_OK,FALSE},
159             {"winehq.org",S_OK,FALSE},
160             {"http://winehq.org/tests",S_OK,FALSE},
161             {"winehq.org",S_OK,FALSE},
162             {"",S_FALSE,FALSE},
163             {"",S_FALSE,FALSE},
164             {"winehq.org",S_OK,FALSE},
165             {"",S_FALSE,FALSE},
166             {"/tests",S_OK,FALSE},
167             {"/tests",S_OK,FALSE},
168             {"",S_FALSE,FALSE},
169             {"http://winehq.org/tests/.././tests",S_OK,FALSE},
170             {"http",S_OK,FALSE},
171             {"",S_FALSE,FALSE},
172             {"",S_FALSE,FALSE}
173         },
174         {
175             {Uri_HOST_DNS,S_OK,FALSE},
176             {80,S_OK,FALSE},
177             {URL_SCHEME_HTTP,S_OK,FALSE},
178             {URLZONE_INVALID,E_NOTIMPL,FALSE}
179         }
180     },
181     {   "HtTp://www.winehq.org/tests/..?query=x&return=y", 0, S_OK, FALSE,
182         {
183             {"http://www.winehq.org/?query=x&return=y",S_OK,FALSE},
184             {"www.winehq.org",S_OK,FALSE},
185             {"http://www.winehq.org/?query=x&return=y",S_OK,FALSE},
186             {"winehq.org",S_OK,FALSE},
187             {"",S_FALSE,FALSE},
188             {"",S_FALSE,FALSE},
189             {"www.winehq.org",S_OK,FALSE},
190             {"",S_FALSE,FALSE},
191             {"/",S_OK,FALSE},
192             {"/?query=x&return=y",S_OK,FALSE},
193             {"?query=x&return=y",S_OK,FALSE},
194             {"HtTp://www.winehq.org/tests/..?query=x&return=y",S_OK,FALSE},
195             {"http",S_OK,FALSE},
196             {"",S_FALSE,FALSE},
197             {"",S_FALSE,FALSE}
198         },
199         {
200             {Uri_HOST_DNS,S_OK,FALSE},
201             {80,S_OK,FALSE},
202             {URL_SCHEME_HTTP,S_OK,FALSE},
203             {URLZONE_INVALID,E_NOTIMPL,FALSE},
204         }
205     },
206     {   "hTTp://us%45r%3Ainfo@examp%4CE.com:80/path/a/b/./c/../%2E%2E/Forbidden'<|> Characters", 0, S_OK, FALSE,
207         {
208             {"http://usEr%3Ainfo@example.com/path/a/Forbidden'%3C%7C%3E%20Characters",S_OK,FALSE},
209             {"usEr%3Ainfo@example.com",S_OK,FALSE},
210             {"http://example.com/path/a/Forbidden'%3C%7C%3E%20Characters",S_OK,FALSE},
211             {"example.com",S_OK,FALSE},
212             {"",S_FALSE,FALSE},
213             {"",S_FALSE,FALSE},
214             {"example.com",S_OK,FALSE},
215             {"",S_FALSE,FALSE},
216             {"/path/a/Forbidden'%3C%7C%3E%20Characters",S_OK,FALSE},
217             {"/path/a/Forbidden'%3C%7C%3E%20Characters",S_OK,FALSE},
218             {"",S_FALSE,FALSE},
219             {"hTTp://us%45r%3Ainfo@examp%4CE.com:80/path/a/b/./c/../%2E%2E/Forbidden'<|> Characters",S_OK,FALSE},
220             {"http",S_OK,FALSE},
221             {"usEr%3Ainfo",S_OK,FALSE},
222             {"usEr%3Ainfo",S_OK,FALSE}
223         },
224         {
225             {Uri_HOST_DNS,S_OK,FALSE},
226             {80,S_OK,FALSE},
227             {URL_SCHEME_HTTP,S_OK,FALSE},
228             {URLZONE_INVALID,E_NOTIMPL,FALSE},
229         }
230     },
231     {   "ftp://winepass:wine@ftp.winehq.org:9999/dir/foo bar.txt", 0, S_OK, FALSE,
232         {
233             {"ftp://winepass:wine@ftp.winehq.org:9999/dir/foo%20bar.txt",S_OK,FALSE},
234             {"winepass:wine@ftp.winehq.org:9999",S_OK,FALSE},
235             {"ftp://ftp.winehq.org:9999/dir/foo%20bar.txt",S_OK,FALSE},
236             {"winehq.org",S_OK,FALSE},
237             {".txt",S_OK,FALSE},
238             {"",S_FALSE,FALSE},
239             {"ftp.winehq.org",S_OK,FALSE},
240             {"wine",S_OK,FALSE},
241             {"/dir/foo%20bar.txt",S_OK,FALSE},
242             {"/dir/foo%20bar.txt",S_OK,FALSE},
243             {"",S_FALSE,FALSE},
244             {"ftp://winepass:wine@ftp.winehq.org:9999/dir/foo bar.txt",S_OK,FALSE},
245             {"ftp",S_OK,FALSE},
246             {"winepass:wine",S_OK,FALSE},
247             {"winepass",S_OK,FALSE}
248         },
249         {
250             {Uri_HOST_DNS,S_OK,FALSE},
251             {9999,S_OK,FALSE},
252             {URL_SCHEME_FTP,S_OK,FALSE},
253             {URLZONE_INVALID,E_NOTIMPL,FALSE}
254         }
255     },
256     {   "file://c:\\tests\\../tests/foo%20bar.mp3", 0, S_OK, FALSE,
257         {
258             {"file:///c:/tests/foo%2520bar.mp3",S_OK,FALSE},
259             {"",S_FALSE,FALSE},
260             {"file:///c:/tests/foo%2520bar.mp3",S_OK,FALSE},
261             {"",S_FALSE,FALSE},
262             {".mp3",S_OK,FALSE},
263             {"",S_FALSE,FALSE},
264             {"",S_FALSE,FALSE},
265             {"",S_FALSE,FALSE},
266             {"/c:/tests/foo%2520bar.mp3",S_OK,FALSE},
267             {"/c:/tests/foo%2520bar.mp3",S_OK,FALSE},
268             {"",S_FALSE,FALSE},
269             {"file://c:\\tests\\../tests/foo%20bar.mp3",S_OK,FALSE},
270             {"file",S_OK,FALSE},
271             {"",S_FALSE,FALSE},
272             {"",S_FALSE,FALSE}
273         },
274         {
275             {Uri_HOST_UNKNOWN,S_OK,FALSE},
276             {0,S_FALSE,FALSE},
277             {URL_SCHEME_FILE,S_OK,FALSE},
278             {URLZONE_INVALID,E_NOTIMPL,FALSE}
279         }
280     },
281     {   "FILE://localhost/test dir\\../tests/test%20file.README.txt", 0, S_OK, FALSE,
282         {
283             {"file:///tests/test%20file.README.txt",S_OK,FALSE},
284             {"",S_FALSE,FALSE},
285             {"file:///tests/test%20file.README.txt",S_OK,FALSE},
286             {"",S_FALSE,FALSE},
287             {".txt",S_OK,FALSE},
288             {"",S_FALSE,FALSE},
289             {"",S_FALSE,FALSE},
290             {"",S_FALSE,FALSE},
291             {"/tests/test%20file.README.txt",S_OK,FALSE},
292             {"/tests/test%20file.README.txt",S_OK,FALSE},
293             {"",S_FALSE,FALSE},
294             {"FILE://localhost/test dir\\../tests/test%20file.README.txt",S_OK,FALSE},
295             {"file",S_OK,FALSE},
296             {"",S_FALSE,FALSE},
297             {"",S_FALSE,FALSE}
298         },
299         {
300             {Uri_HOST_UNKNOWN,S_OK,FALSE},
301             {0,S_FALSE,FALSE},
302             {URL_SCHEME_FILE,S_OK,FALSE},
303             {URLZONE_INVALID,E_NOTIMPL,FALSE}
304         }
305     },
306     {   "urn:nothing:should:happen here", 0, S_OK, FALSE,
307         {
308             {"urn:nothing:should:happen here",S_OK,FALSE},
309             {"",S_FALSE,FALSE},
310             {"urn:nothing:should:happen here",S_OK,FALSE},
311             {"",S_FALSE,FALSE},
312             {"",S_FALSE,FALSE},
313             {"",S_FALSE,FALSE},
314             {"",S_FALSE,FALSE},
315             {"",S_FALSE,FALSE},
316             {"nothing:should:happen here",S_OK,FALSE},
317             {"nothing:should:happen here",S_OK,FALSE},
318             {"",S_FALSE,FALSE},
319             {"urn:nothing:should:happen here",S_OK,FALSE},
320             {"urn",S_OK,FALSE},
321             {"",S_FALSE,FALSE},
322             {"",S_FALSE,FALSE}
323         },
324         {
325             {Uri_HOST_UNKNOWN,S_OK,FALSE},
326             {0,S_FALSE,FALSE},
327             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
328             {URLZONE_INVALID,E_NOTIMPL,FALSE}
329         }
330     },
331     {   "http://127.0.0.1/tests/../test dir/./test.txt", 0, S_OK, FALSE,
332         {
333             {"http://127.0.0.1/test%20dir/test.txt",S_OK,FALSE},
334             {"127.0.0.1",S_OK,FALSE},
335             {"http://127.0.0.1/test%20dir/test.txt",S_OK,FALSE},
336             {"",S_FALSE,FALSE},
337             {".txt",S_OK,FALSE},
338             {"",S_FALSE,FALSE},
339             {"127.0.0.1",S_OK,FALSE},
340             {"",S_FALSE,FALSE},
341             {"/test%20dir/test.txt",S_OK,FALSE},
342             {"/test%20dir/test.txt",S_OK,FALSE},
343             {"",S_FALSE,FALSE},
344             {"http://127.0.0.1/tests/../test dir/./test.txt",S_OK,FALSE},
345             {"http",S_OK,FALSE},
346             {"",S_FALSE,FALSE},
347             {"",S_FALSE,FALSE}
348         },
349         {
350             {Uri_HOST_IPV4,S_OK,FALSE},
351             {80,S_OK,FALSE},
352             {URL_SCHEME_HTTP,S_OK,FALSE},
353             {URLZONE_INVALID,E_NOTIMPL,FALSE}
354         }
355     },
356     {   "http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]", 0, S_OK, FALSE,
357         {
358             {"http://[fedc:ba98:7654:3210:fedc:ba98:7654:3210]/",S_OK,FALSE},
359             {"[fedc:ba98:7654:3210:fedc:ba98:7654:3210]",S_OK,FALSE},
360             {"http://[fedc:ba98:7654:3210:fedc:ba98:7654:3210]/",S_OK,FALSE},
361             {"",S_FALSE,FALSE},
362             {"",S_FALSE,FALSE},
363             {"",S_FALSE,FALSE},
364             {"fedc:ba98:7654:3210:fedc:ba98:7654:3210",S_OK,FALSE},
365             {"",S_FALSE,FALSE},
366             {"/",S_OK,FALSE},
367             {"/",S_OK,FALSE},
368             {"",S_FALSE,FALSE},
369             {"http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]",S_OK,FALSE},
370             {"http",S_OK,FALSE},
371             {"",S_FALSE,FALSE},
372             {"",S_FALSE,FALSE}
373         },
374         {
375             {Uri_HOST_IPV6,S_OK,FALSE},
376             {80,S_OK,FALSE},
377             {URL_SCHEME_HTTP,S_OK,FALSE},
378             {URLZONE_INVALID,E_NOTIMPL,FALSE}
379         }
380     },
381     {   "ftp://[::13.1.68.3]", 0, S_OK, FALSE,
382         {
383             {"ftp://[::13.1.68.3]/",S_OK,FALSE},
384             {"[::13.1.68.3]",S_OK,FALSE},
385             {"ftp://[::13.1.68.3]/",S_OK,FALSE},
386             {"",S_FALSE,FALSE},
387             {"",S_FALSE,FALSE},
388             {"",S_FALSE,FALSE},
389             {"::13.1.68.3",S_OK,FALSE},
390             {"",S_FALSE,FALSE},
391             {"/",S_OK,FALSE},
392             {"/",S_OK,FALSE},
393             {"",S_FALSE,FALSE},
394             {"ftp://[::13.1.68.3]",S_OK,FALSE},
395             {"ftp",S_OK,FALSE},
396             {"",S_FALSE,FALSE},
397             {"",S_FALSE,FALSE}
398         },
399         {
400             {Uri_HOST_IPV6,S_OK,FALSE},
401             {21,S_OK,FALSE},
402             {URL_SCHEME_FTP,S_OK,FALSE},
403             {URLZONE_INVALID,E_NOTIMPL,FALSE}
404         }
405     },
406     {   "http://[FEDC:BA98:0:0:0:0:0:3210]", 0, S_OK, FALSE,
407         {
408             {"http://[fedc:ba98::3210]/",S_OK,FALSE},
409             {"[fedc:ba98::3210]",S_OK,FALSE},
410             {"http://[fedc:ba98::3210]/",S_OK,FALSE},
411             {"",S_FALSE,FALSE},
412             {"",S_FALSE,FALSE},
413             {"",S_FALSE,FALSE},
414             {"fedc:ba98::3210",S_OK,FALSE},
415             {"",S_FALSE,FALSE},
416             {"/",S_OK,FALSE},
417             {"/",S_OK,FALSE},
418             {"",S_FALSE,FALSE},
419             {"http://[FEDC:BA98:0:0:0:0:0:3210]",S_OK,FALSE},
420             {"http",S_OK,FALSE},
421             {"",S_FALSE,FALSE},
422             {"",S_FALSE,FALSE},
423         },
424         {
425             {Uri_HOST_IPV6,S_OK,FALSE},
426             {80,S_OK,FALSE},
427             {URL_SCHEME_HTTP,S_OK,FALSE},
428             {URLZONE_INVALID,E_NOTIMPL,FALSE}
429         }
430     },
431     {   "1234://www.winehq.org", 0, S_OK, FALSE,
432         {
433             {"1234://www.winehq.org/",S_OK,FALSE},
434             {"www.winehq.org",S_OK,FALSE},
435             {"1234://www.winehq.org/",S_OK,FALSE},
436             {"winehq.org",S_OK,FALSE},
437             {"",S_FALSE,FALSE},
438             {"",S_FALSE,FALSE},
439             {"www.winehq.org",S_OK,FALSE},
440             {"",S_FALSE,FALSE},
441             {"/",S_OK,FALSE},
442             {"/",S_OK,FALSE},
443             {"",S_FALSE,FALSE},
444             {"1234://www.winehq.org",S_OK,FALSE},
445             {"1234",S_OK,FALSE},
446             {"",S_FALSE,FALSE},
447             {"",S_FALSE,FALSE}
448         },
449         {
450             {Uri_HOST_DNS,S_OK,FALSE},
451             {0,S_FALSE,FALSE},
452             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
453             {URLZONE_INVALID,E_NOTIMPL,FALSE}
454         }
455     },
456     /* Test's to make sure the parser/canonicalizer handles implicit file schemes correctly. */
457     {   "C:/test/test.mp3", Uri_CREATE_ALLOW_IMPLICIT_FILE_SCHEME, S_OK, FALSE,
458         {
459             {"file:///C:/test/test.mp3",S_OK,FALSE},
460             {"",S_FALSE,FALSE},
461             {"file:///C:/test/test.mp3",S_OK,FALSE},
462             {"",S_FALSE,FALSE},
463             {".mp3",S_OK,FALSE},
464             {"",S_FALSE,FALSE},
465             {"",S_FALSE,FALSE},
466             {"",S_FALSE,FALSE},
467             {"/C:/test/test.mp3",S_OK,FALSE},
468             {"/C:/test/test.mp3",S_OK,FALSE},
469             {"",S_FALSE,FALSE},
470             {"C:/test/test.mp3",S_OK,FALSE},
471             {"file",S_OK,FALSE},
472             {"",S_FALSE,FALSE},
473             {"",S_FALSE,FALSE}
474         },
475         {
476             {Uri_HOST_UNKNOWN,S_OK,FALSE},
477             {0,S_FALSE,FALSE},
478             {URL_SCHEME_FILE,S_OK,FALSE},
479             {URLZONE_INVALID,E_NOTIMPL,FALSE}
480         }
481     },
482     /* Test's to make sure the parser/canonicalizer handles implicit file schemes correctly. */
483     {   "\\\\Server/test.mp3", Uri_CREATE_ALLOW_IMPLICIT_FILE_SCHEME, S_OK, FALSE,
484         {
485             {"file://server/test.mp3",S_OK,FALSE},
486             {"server",S_OK,FALSE},
487             {"file://server/test.mp3",S_OK,FALSE},
488             {"",S_FALSE,FALSE},
489             {".mp3",S_OK,FALSE},
490             {"",S_FALSE,FALSE},
491             {"server",S_OK,FALSE},
492             {"",S_FALSE,FALSE},
493             {"/test.mp3",S_OK,FALSE},
494             {"/test.mp3",S_OK,FALSE},
495             {"",S_FALSE,FALSE},
496             {"\\\\Server/test.mp3",S_OK,FALSE},
497             {"file",S_OK,FALSE},
498             {"",S_FALSE,FALSE},
499             {"",S_FALSE,FALSE}
500         },
501         {
502             {Uri_HOST_DNS,S_OK,FALSE},
503             {0,S_FALSE,FALSE},
504             {URL_SCHEME_FILE,S_OK,FALSE},
505             {URLZONE_INVALID,E_NOTIMPL,FALSE}
506         }
507     },
508     {   "www.winehq.org/test", Uri_CREATE_ALLOW_IMPLICIT_WILDCARD_SCHEME, S_OK, FALSE,
509         {
510             {"*:www.winehq.org/test",S_OK,FALSE},
511             {"www.winehq.org",S_OK,FALSE},
512             {"*:www.winehq.org/test",S_OK,FALSE},
513             {"winehq.org",S_OK,FALSE},
514             {"",S_FALSE,FALSE},
515             {"",S_FALSE,FALSE},
516             {"www.winehq.org",S_OK,FALSE},
517             {"",S_FALSE,FALSE},
518             {"/test",S_OK,FALSE},
519             {"/test",S_OK,FALSE},
520             {"",S_FALSE,FALSE},
521             {"www.winehq.org/test",S_OK,FALSE},
522             {"*",S_OK,FALSE},
523             {"",S_FALSE,FALSE},
524             {"",S_FALSE,FALSE}
525         },
526         {
527             {Uri_HOST_DNS,S_OK,FALSE},
528             {0,S_FALSE,FALSE},
529             {URL_SCHEME_WILDCARD,S_OK,FALSE},
530             {URLZONE_INVALID,E_NOTIMPL,FALSE}
531         }
532     },
533     /* Valid since the '*' is the only character in the scheme name. */
534     {   "*:www.winehq.org/test", 0, S_OK, FALSE,
535         {
536             {"*:www.winehq.org/test",S_OK,FALSE},
537             {"www.winehq.org",S_OK,FALSE},
538             {"*:www.winehq.org/test",S_OK,FALSE},
539             {"winehq.org",S_OK,FALSE},
540             {"",S_FALSE,FALSE},
541             {"",S_FALSE,FALSE},
542             {"www.winehq.org",S_OK,FALSE},
543             {"",S_FALSE,FALSE},
544             {"/test",S_OK,FALSE},
545             {"/test",S_OK,FALSE},
546             {"",S_FALSE,FALSE},
547             {"*:www.winehq.org/test",S_OK,FALSE},
548             {"*",S_OK,FALSE},
549             {"",S_FALSE,FALSE},
550             {"",S_FALSE,FALSE}
551         },
552         {
553             {Uri_HOST_DNS,S_OK,FALSE},
554             {0,S_FALSE,FALSE},
555             {URL_SCHEME_WILDCARD,S_OK,FALSE},
556             {URLZONE_INVALID,E_NOTIMPL,FALSE}
557         }
558     },
559     {   "/../some dir/test.ext", Uri_CREATE_ALLOW_RELATIVE, S_OK, FALSE,
560         {
561             {"/../some dir/test.ext",S_OK,FALSE},
562             {"",S_FALSE,FALSE},
563             {"/../some dir/test.ext",S_OK,FALSE},
564             {"",S_FALSE,FALSE},
565             {".ext",S_OK,FALSE},
566             {"",S_FALSE,FALSE},
567             {"",S_FALSE,FALSE},
568             {"",S_FALSE,FALSE},
569             {"/../some dir/test.ext",S_OK,FALSE},
570             {"/../some dir/test.ext",S_OK,FALSE},
571             {"",S_FALSE,FALSE},
572             {"/../some dir/test.ext",S_OK,FALSE},
573             {"",S_FALSE,FALSE},
574             {"",S_FALSE,FALSE},
575             {"",S_FALSE,FALSE}
576         },
577         {
578             {Uri_HOST_UNKNOWN,S_OK,FALSE},
579             {0,S_FALSE,FALSE},
580             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
581             {URLZONE_INVALID,E_NOTIMPL,FALSE}
582         }
583     },
584     {   "//implicit/wildcard/uri scheme", Uri_CREATE_ALLOW_RELATIVE|Uri_CREATE_ALLOW_IMPLICIT_WILDCARD_SCHEME, S_OK, FALSE,
585         {
586             {"*://implicit/wildcard/uri%20scheme",S_OK,FALSE},
587             {"",S_OK,FALSE},
588             {"*://implicit/wildcard/uri%20scheme",S_OK,FALSE},
589             {"",S_FALSE,FALSE},
590             {"",S_FALSE,FALSE},
591             {"",S_FALSE,FALSE},
592             {"",S_OK,FALSE},
593             {"",S_FALSE,FALSE},
594             {"//implicit/wildcard/uri%20scheme",S_OK,FALSE},
595             {"//implicit/wildcard/uri%20scheme",S_OK,FALSE},
596             {"",S_FALSE,FALSE},
597             {"//implicit/wildcard/uri scheme",S_OK,FALSE},
598             {"*",S_OK,FALSE},
599             {"",S_FALSE,FALSE},
600             {"",S_FALSE,FALSE},
601         },
602         {
603             {Uri_HOST_UNKNOWN,S_OK,FALSE},
604             {0,S_FALSE,FALSE},
605             {URL_SCHEME_WILDCARD,S_OK,FALSE},
606             {URLZONE_INVALID,E_NOTIMPL,FALSE}
607         }
608     },
609     /* URI is considered opaque since CREATE_NO_CRACK_UNKNOWN_SCHEMES is set and its an unknown scheme. */
610     {   "zip://google.com", Uri_CREATE_NO_CRACK_UNKNOWN_SCHEMES, S_OK, FALSE,
611         {
612             {"zip:/.//google.com",S_OK,FALSE},
613             {"",S_FALSE,FALSE},
614             {"zip:/.//google.com",S_OK,FALSE},
615             {"",S_FALSE,FALSE},
616             {".com",S_OK,FALSE},
617             {"",S_FALSE,FALSE},
618             {"",S_FALSE,FALSE},
619             {"",S_FALSE,FALSE},
620             {"/.//google.com",S_OK,FALSE},
621             {"/.//google.com",S_OK,FALSE},
622             {"",S_FALSE,FALSE},
623             {"zip://google.com",S_OK,FALSE},
624             {"zip",S_OK,FALSE},
625             {"",S_FALSE,FALSE},
626             {"",S_FALSE,FALSE}
627         },
628         {
629             {Uri_HOST_UNKNOWN,S_OK,FALSE},
630             {0,S_FALSE,FALSE},
631             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
632             {URLZONE_INVALID,E_NOTIMPL,FALSE}
633         }
634     },
635     /* Windows uses the first occurrence of ':' to delimit the userinfo. */
636     {   "ftp://user:pass:word@winehq.org/", 0, S_OK, FALSE,
637         {
638             {"ftp://user:pass:word@winehq.org/",S_OK,FALSE},
639             {"user:pass:word@winehq.org",S_OK,FALSE},
640             {"ftp://winehq.org/",S_OK,FALSE},
641             {"winehq.org",S_OK,FALSE},
642             {"",S_FALSE,FALSE},
643             {"",S_FALSE,FALSE},
644             {"winehq.org",S_OK,FALSE},
645             {"pass:word",S_OK,FALSE},
646             {"/",S_OK,FALSE},
647             {"/",S_OK,FALSE},
648             {"",S_FALSE,FALSE},
649             {"ftp://user:pass:word@winehq.org/",S_OK,FALSE},
650             {"ftp",S_OK,FALSE},
651             {"user:pass:word",S_OK,FALSE},
652             {"user",S_OK,FALSE}
653         },
654         {
655             {Uri_HOST_DNS,S_OK,FALSE},
656             {21,S_OK,FALSE},
657             {URL_SCHEME_FTP,S_OK,FALSE},
658             {URLZONE_INVALID,E_NOTIMPL,FALSE}
659         }
660     },
661     /* Make sure % encoded unreserved characters are decoded. */
662     {   "ftp://w%49%4Ee:PA%53%53@ftp.google.com/", 0, S_OK, FALSE,
663         {
664             {"ftp://wINe:PASS@ftp.google.com/",S_OK,FALSE},
665             {"wINe:PASS@ftp.google.com",S_OK,FALSE},
666             {"ftp://ftp.google.com/",S_OK,FALSE},
667             {"google.com",S_OK,FALSE},
668             {"",S_FALSE,FALSE},
669             {"",S_FALSE,FALSE},
670             {"ftp.google.com",S_OK,FALSE},
671             {"PASS",S_OK,FALSE},
672             {"/",S_OK,FALSE},
673             {"/",S_OK,FALSE},
674             {"",S_FALSE,FALSE},
675             {"ftp://w%49%4Ee:PA%53%53@ftp.google.com/",S_OK,FALSE},
676             {"ftp",S_OK,FALSE},
677             {"wINe:PASS",S_OK,FALSE},
678             {"wINe",S_OK,FALSE}
679         },
680         {
681             {Uri_HOST_DNS,S_OK,FALSE},
682             {21,S_OK,FALSE},
683             {URL_SCHEME_FTP,S_OK,FALSE},
684             {URLZONE_INVALID,E_NOTIMPL,FALSE}
685         }
686     },
687     /* Make sure % encoded characters which are NOT unreserved are NOT decoded. */
688     {   "ftp://w%5D%5Be:PA%7B%7D@ftp.google.com/", 0, S_OK, FALSE,
689         {
690             {"ftp://w%5D%5Be:PA%7B%7D@ftp.google.com/",S_OK,FALSE},
691             {"w%5D%5Be:PA%7B%7D@ftp.google.com",S_OK,FALSE},
692             {"ftp://ftp.google.com/",S_OK,FALSE},
693             {"google.com",S_OK,FALSE},
694             {"",S_FALSE,FALSE},
695             {"",S_FALSE,FALSE},
696             {"ftp.google.com",S_OK,FALSE},
697             {"PA%7B%7D",S_OK,FALSE},
698             {"/",S_OK,FALSE},
699             {"/",S_OK,FALSE},
700             {"",S_FALSE,FALSE},
701             {"ftp://w%5D%5Be:PA%7B%7D@ftp.google.com/",S_OK,FALSE},
702             {"ftp",S_OK,FALSE},
703             {"w%5D%5Be:PA%7B%7D",S_OK,FALSE},
704             {"w%5D%5Be",S_OK,FALSE}
705         },
706         {
707             {Uri_HOST_DNS,S_OK,FALSE},
708             {21,S_OK,FALSE},
709             {URL_SCHEME_FTP,S_OK,FALSE},
710             {URLZONE_INVALID,E_NOTIMPL,FALSE}
711         }
712     },
713     /* You're allowed to have an empty password portion in the userinfo section. */
714     {   "ftp://empty:@ftp.google.com/", 0, S_OK, FALSE,
715         {
716             {"ftp://empty:@ftp.google.com/",S_OK,FALSE},
717             {"empty:@ftp.google.com",S_OK,FALSE},
718             {"ftp://ftp.google.com/",S_OK,FALSE},
719             {"google.com",S_OK,FALSE},
720             {"",S_FALSE,FALSE},
721             {"",S_FALSE,FALSE},
722             {"ftp.google.com",S_OK,FALSE},
723             {"",S_OK,FALSE},
724             {"/",S_OK,FALSE},
725             {"/",S_OK,FALSE},
726             {"",S_FALSE,FALSE},
727             {"ftp://empty:@ftp.google.com/",S_OK,FALSE},
728             {"ftp",S_OK,FALSE},
729             {"empty:",S_OK,FALSE},
730             {"empty",S_OK,FALSE}
731         },
732         {
733             {Uri_HOST_DNS,S_OK,FALSE},
734             {21,S_OK,FALSE},
735             {URL_SCHEME_FTP,S_OK,FALSE},
736             {URLZONE_INVALID,E_NOTIMPL,FALSE}
737         }
738     },
739     /* Make sure forbidden characters in "userinfo" get encoded. */
740     {   "ftp://\" \"weird@ftp.google.com/", 0, S_OK, FALSE,
741         {
742             {"ftp://%22%20%22weird@ftp.google.com/",S_OK,FALSE},
743             {"%22%20%22weird@ftp.google.com",S_OK,FALSE},
744             {"ftp://ftp.google.com/",S_OK,FALSE},
745             {"google.com",S_OK,FALSE},
746             {"",S_FALSE,FALSE},
747             {"",S_FALSE,FALSE},
748             {"ftp.google.com",S_OK,FALSE},
749             {"",S_FALSE,FALSE},
750             {"/",S_OK,FALSE},
751             {"/",S_OK,FALSE},
752             {"",S_FALSE,FALSE},
753             {"ftp://\" \"weird@ftp.google.com/",S_OK,FALSE},
754             {"ftp",S_OK,FALSE},
755             {"%22%20%22weird",S_OK,FALSE},
756             {"%22%20%22weird",S_OK,FALSE}
757         },
758         {
759             {Uri_HOST_DNS,S_OK,FALSE},
760             {21,S_OK,FALSE},
761             {URL_SCHEME_FTP,S_OK,FALSE},
762             {URLZONE_INVALID,E_NOTIMPL,FALSE}
763         }
764     },
765     /* Make sure the forbidden characters don't get percent encoded. */
766     {   "ftp://\" \"weird@ftp.google.com/", Uri_CREATE_NO_ENCODE_FORBIDDEN_CHARACTERS, S_OK, FALSE,
767         {
768             {"ftp://\" \"weird@ftp.google.com/",S_OK,FALSE},
769             {"\" \"weird@ftp.google.com",S_OK,FALSE},
770             {"ftp://ftp.google.com/",S_OK,FALSE},
771             {"google.com",S_OK,FALSE},
772             {"",S_FALSE,FALSE},
773             {"",S_FALSE,FALSE},
774             {"ftp.google.com",S_OK,FALSE},
775             {"",S_FALSE,FALSE},
776             {"/",S_OK,FALSE},
777             {"/",S_OK,FALSE},
778             {"",S_FALSE,FALSE},
779             {"ftp://\" \"weird@ftp.google.com/",S_OK,FALSE},
780             {"ftp",S_OK,FALSE},
781             {"\" \"weird",S_OK,FALSE},
782             {"\" \"weird",S_OK,FALSE}
783         },
784         {
785             {Uri_HOST_DNS,S_OK,FALSE},
786             {21,S_OK,FALSE},
787             {URL_SCHEME_FTP,S_OK,FALSE},
788             {URLZONE_INVALID,E_NOTIMPL,FALSE}
789         }
790     },
791     /* Allowed to have invalid % encoded because its an unknown scheme type. */
792     {   "zip://%xy:word@winehq.org/", 0, S_OK, FALSE,
793         {
794             {"zip://%xy:word@winehq.org/",S_OK,FALSE},
795             {"%xy:word@winehq.org",S_OK,FALSE},
796             {"zip://%xy:word@winehq.org/",S_OK,FALSE},
797             {"winehq.org",S_OK,FALSE},
798             {"",S_FALSE,FALSE},
799             {"",S_FALSE,FALSE},
800             {"winehq.org",S_OK,FALSE},
801             {"word",S_OK,FALSE},
802             {"/",S_OK,FALSE},
803             {"/",S_OK,FALSE},
804             {"",S_FALSE,FALSE},
805             {"zip://%xy:word@winehq.org/",S_OK,FALSE},
806             {"zip",S_OK,FALSE},
807             {"%xy:word",S_OK,FALSE},
808             {"%xy",S_OK,FALSE}
809         },
810         {
811             {Uri_HOST_DNS,S_OK,FALSE},
812             {0,S_FALSE,FALSE},
813             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
814             {URLZONE_INVALID,E_NOTIMPL,FALSE}
815         }
816     },
817     /* Unreserved, percent encoded characters aren't decoded in the userinfo becuase the scheme
818      * isn't known.
819      */
820     {   "zip://%2E:%52%53ord@winehq.org/", 0, S_OK, FALSE,
821         {
822             {"zip://%2E:%52%53ord@winehq.org/",S_OK,FALSE},
823             {"%2E:%52%53ord@winehq.org",S_OK,FALSE},
824             {"zip://%2E:%52%53ord@winehq.org/",S_OK,FALSE},
825             {"winehq.org",S_OK,FALSE},
826             {"",S_FALSE,FALSE},
827             {"",S_FALSE,FALSE},
828             {"winehq.org",S_OK,FALSE},
829             {"%52%53ord",S_OK,FALSE},
830             {"/",S_OK,FALSE},
831             {"/",S_OK,FALSE},
832             {"",S_FALSE,FALSE},
833             {"zip://%2E:%52%53ord@winehq.org/",S_OK,FALSE},
834             {"zip",S_OK,FALSE},
835             {"%2E:%52%53ord",S_OK,FALSE},
836             {"%2E",S_OK,FALSE}
837         },
838         {
839             {Uri_HOST_DNS,S_OK,FALSE},
840             {0,S_FALSE,FALSE},
841             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
842             {URLZONE_INVALID,E_NOTIMPL,FALSE}
843         }
844     },
845     {   "ftp://[](),'test':word@winehq.org/", 0, S_OK, FALSE,
846         {
847             {"ftp://[](),'test':word@winehq.org/",S_OK,FALSE},
848             {"[](),'test':word@winehq.org",S_OK,FALSE},
849             {"ftp://winehq.org/",S_OK,FALSE},
850             {"winehq.org",S_OK,FALSE},
851             {"",S_FALSE,FALSE},
852             {"",S_FALSE,FALSE},
853             {"winehq.org",S_OK,FALSE},
854             {"word",S_OK,FALSE},
855             {"/",S_OK,FALSE},
856             {"/",S_OK,FALSE},
857             {"",S_FALSE,FALSE},
858             {"ftp://[](),'test':word@winehq.org/",S_OK,FALSE},
859             {"ftp",S_OK,FALSE},
860             {"[](),'test':word",S_OK,FALSE},
861             {"[](),'test'",S_OK,FALSE}
862         },
863         {
864             {Uri_HOST_DNS,S_OK,FALSE},
865             {21,S_OK,FALSE},
866             {URL_SCHEME_FTP,S_OK,FALSE},
867             {URLZONE_INVALID,E_NOTIMPL,FALSE}
868         }
869     },
870     {   "ftp://test?:word@winehq.org/", 0, S_OK, FALSE,
871         {
872             {"ftp://test/?:word@winehq.org/",S_OK,FALSE},
873             {"test",S_OK,FALSE},
874             {"ftp://test/?:word@winehq.org/",S_OK,FALSE},
875             {"",S_FALSE,FALSE},
876             {"",S_FALSE,FALSE},
877             {"",S_FALSE,FALSE},
878             {"test",S_OK,FALSE},
879             {"",S_FALSE,FALSE},
880             {"/",S_OK,FALSE},
881             {"/?:word@winehq.org/",S_OK,FALSE},
882             {"?:word@winehq.org/",S_OK,FALSE},
883             {"ftp://test?:word@winehq.org/",S_OK,FALSE},
884             {"ftp",S_OK,FALSE},
885             {"",S_FALSE,FALSE},
886             {"",S_FALSE,FALSE}
887         },
888         {
889             {Uri_HOST_DNS,S_OK,FALSE},
890             {21,S_OK,FALSE},
891             {URL_SCHEME_FTP,S_OK,FALSE},
892             {URLZONE_INVALID,E_NOTIMPL,FALSE}
893         }
894     },
895     {   "ftp://test#:word@winehq.org/", 0, S_OK, FALSE,
896         {
897             {"ftp://test/#:word@winehq.org/",S_OK,FALSE},
898             {"test",S_OK,FALSE},
899             {"ftp://test/#:word@winehq.org/",S_OK,FALSE},
900             {"",S_FALSE,FALSE},
901             {"",S_FALSE,FALSE},
902             {"#:word@winehq.org/",S_OK,FALSE},
903             {"test",S_OK,FALSE},
904             {"",S_FALSE,FALSE},
905             {"/",S_OK,FALSE},
906             {"/",S_OK,FALSE},
907             {"",S_FALSE,FALSE},
908             {"ftp://test#:word@winehq.org/",S_OK,FALSE},
909             {"ftp",S_OK,FALSE},
910             {"",S_FALSE,FALSE},
911             {"",S_FALSE,FALSE}
912         },
913         {
914             {Uri_HOST_DNS,S_OK,FALSE},
915             {21,S_OK,FALSE},
916             {URL_SCHEME_FTP,S_OK,FALSE},
917             {URLZONE_INVALID,E_NOTIMPL,FALSE}
918         }
919     },
920     /* Allowed to have a backslash in the userinfo since it's an unknown scheme. */
921     {   "zip://test\\:word@winehq.org/", 0, S_OK, FALSE,
922         {
923             {"zip://test\\:word@winehq.org/",S_OK,FALSE},
924             {"test\\:word@winehq.org",S_OK,FALSE},
925             {"zip://test\\:word@winehq.org/",S_OK,FALSE},
926             {"winehq.org",S_OK,FALSE},
927             {"",S_FALSE,FALSE},
928             {"",S_FALSE,FALSE},
929             {"winehq.org",S_OK,FALSE},
930             {"word",S_OK,FALSE},
931             {"/",S_OK,FALSE},
932             {"/",S_OK,FALSE},
933             {"",S_FALSE,FALSE},
934             {"zip://test\\:word@winehq.org/",S_OK,FALSE},
935             {"zip",S_OK,FALSE},
936             {"test\\:word",S_OK,FALSE},
937             {"test\\",S_OK,FALSE}
938         },
939         {
940             {Uri_HOST_DNS,S_OK,FALSE},
941             {0,S_FALSE,FALSE},
942             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
943             {URLZONE_INVALID,E_NOTIMPL,FALSE}
944         }
945     },
946     /* It normalizes IPv4 addresses correctly. */
947     {   "http://127.000.000.100/", 0, S_OK, FALSE,
948         {
949             {"http://127.0.0.100/",S_OK,FALSE},
950             {"127.0.0.100",S_OK,FALSE},
951             {"http://127.0.0.100/",S_OK,FALSE},
952             {"",S_FALSE,FALSE},
953             {"",S_FALSE,FALSE},
954             {"",S_FALSE,FALSE},
955             {"127.0.0.100",S_OK,FALSE},
956             {"",S_FALSE,FALSE},
957             {"/",S_OK,FALSE},
958             {"/",S_OK,FALSE},
959             {"",S_FALSE,FALSE},
960             {"http://127.000.000.100/",S_OK,FALSE},
961             {"http",S_OK,FALSE},
962             {"",S_FALSE,FALSE},
963             {"",S_FALSE,FALSE}
964         },
965         {
966             {Uri_HOST_IPV4,S_OK,FALSE},
967             {80,S_OK,FALSE},
968             {URL_SCHEME_HTTP,S_OK,FALSE},
969             {URLZONE_INVALID,E_NOTIMPL,FALSE}
970         }
971     },
972     /* Make sure it normalizes partial IPv4 addresses correctly. */
973     {   "http://127.0/", 0, S_OK, FALSE,
974         {
975             {"http://127.0.0.0/",S_OK,FALSE},
976             {"127.0.0.0",S_OK,FALSE},
977             {"http://127.0.0.0/",S_OK,FALSE},
978             {"",S_FALSE,FALSE},
979             {"",S_FALSE,FALSE},
980             {"",S_FALSE,FALSE},
981             {"127.0.0.0",S_OK,FALSE},
982             {"",S_FALSE,FALSE},
983             {"/",S_OK,FALSE},
984             {"/",S_OK,FALSE},
985             {"",S_FALSE,FALSE},
986             {"http://127.0/",S_OK,FALSE},
987             {"http",S_OK,FALSE},
988             {"",S_FALSE,FALSE},
989             {"",S_FALSE,FALSE}
990         },
991         {
992             {Uri_HOST_IPV4,S_OK,FALSE},
993             {80,S_OK,FALSE},
994             {URL_SCHEME_HTTP,S_OK,FALSE},
995             {URLZONE_INVALID,E_NOTIMPL,FALSE}
996         }
997     },
998     /* Make sure it converts implicit IPv4's correctly. */
999     {   "http://123456/", 0, S_OK, FALSE,
1000         {
1001             {"http://0.1.226.64/",S_OK,FALSE},
1002             {"0.1.226.64",S_OK,FALSE},
1003             {"http://0.1.226.64/",S_OK,FALSE},
1004             {"",S_FALSE,FALSE},
1005             {"",S_FALSE,FALSE},
1006             {"",S_FALSE,FALSE},
1007             {"0.1.226.64",S_OK,FALSE},
1008             {"",S_FALSE,FALSE},
1009             {"/",S_OK,FALSE},
1010             {"/",S_OK,FALSE},
1011             {"",S_FALSE,FALSE},
1012             {"http://123456/",S_OK,FALSE},
1013             {"http",S_OK,FALSE},
1014             {"",S_FALSE,FALSE},
1015             {"",S_FALSE,FALSE}
1016         },
1017         {
1018             {Uri_HOST_IPV4,S_OK,FALSE},
1019             {80,S_OK,FALSE},
1020             {URL_SCHEME_HTTP,S_OK,FALSE},
1021             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1022         }
1023     },
1024     /* UINT_MAX */
1025     {   "http://4294967295/", 0, S_OK, FALSE,
1026         {
1027             {"http://255.255.255.255/",S_OK,FALSE},
1028             {"255.255.255.255",S_OK,FALSE},
1029             {"http://255.255.255.255/",S_OK,FALSE},
1030             {"",S_FALSE,FALSE},
1031             {"",S_FALSE,FALSE},
1032             {"",S_FALSE,FALSE},
1033             {"255.255.255.255",S_OK,FALSE},
1034             {"",S_FALSE,FALSE},
1035             {"/",S_OK,FALSE},
1036             {"/",S_OK,FALSE},
1037             {"",S_FALSE,FALSE},
1038             {"http://4294967295/",S_OK,FALSE},
1039             {"http",S_OK,FALSE},
1040             {"",S_FALSE,FALSE},
1041             {"",S_FALSE,FALSE}
1042         },
1043         {
1044             {Uri_HOST_IPV4,S_OK,FALSE},
1045             {80,S_OK,FALSE},
1046             {URL_SCHEME_HTTP,S_OK,FALSE},
1047             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1048         }
1049     },
1050     /* UINT_MAX+1 */
1051     {   "http://4294967296/", 0, S_OK, FALSE,
1052         {
1053             {"http://4294967296/",S_OK,FALSE},
1054             {"4294967296",S_OK,FALSE},
1055             {"http://4294967296/",S_OK,FALSE},
1056             {"",S_FALSE,FALSE},
1057             {"",S_FALSE,FALSE},
1058             {"",S_FALSE,FALSE},
1059             {"4294967296",S_OK,FALSE},
1060             {"",S_FALSE,FALSE},
1061             {"/",S_OK,FALSE},
1062             {"/",S_OK,FALSE},
1063             {"",S_FALSE,FALSE},
1064             {"http://4294967296/",S_OK,FALSE},
1065             {"http",S_OK,FALSE},
1066             {"",S_FALSE,FALSE},
1067             {"",S_FALSE,FALSE}
1068         },
1069         {
1070             {Uri_HOST_DNS,S_OK,FALSE},
1071             {80,S_OK,FALSE},
1072             {URL_SCHEME_HTTP,S_OK,FALSE},
1073             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1074         }
1075     },
1076     /* Window's doesn't normalize IP address for unknown schemes. */
1077     {   "1234://4294967295/", 0, S_OK, FALSE,
1078         {
1079             {"1234://4294967295/",S_OK,FALSE},
1080             {"4294967295",S_OK,FALSE},
1081             {"1234://4294967295/",S_OK,FALSE},
1082             {"",S_FALSE,FALSE},
1083             {"",S_FALSE,FALSE},
1084             {"",S_FALSE,FALSE},
1085             {"4294967295",S_OK,FALSE},
1086             {"",S_FALSE,FALSE},
1087             {"/",S_OK,FALSE},
1088             {"/",S_OK,FALSE},
1089             {"",S_FALSE,FALSE},
1090             {"1234://4294967295/",S_OK,FALSE},
1091             {"1234",S_OK,FALSE},
1092             {"",S_FALSE,FALSE},
1093             {"",S_FALSE,FALSE}
1094         },
1095         {
1096             {Uri_HOST_IPV4,S_OK,FALSE},
1097             {0,S_FALSE,FALSE},
1098             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1099             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1100         }
1101     },
1102     /* Window's doesn't normalize IP address for unknown schemes. */
1103     {   "1234://127.001/", 0, S_OK, FALSE,
1104         {
1105             {"1234://127.001/",S_OK,FALSE},
1106             {"127.001",S_OK,FALSE},
1107             {"1234://127.001/",S_OK,FALSE},
1108             {"",S_FALSE,FALSE},
1109             {"",S_FALSE,FALSE},
1110             {"",S_FALSE,FALSE},
1111             {"127.001",S_OK,FALSE},
1112             {"",S_FALSE,FALSE},
1113             {"/",S_OK,FALSE},
1114             {"/",S_OK,FALSE},
1115             {"",S_FALSE,FALSE},
1116             {"1234://127.001/",S_OK,FALSE},
1117             {"1234",S_OK,FALSE},
1118             {"",S_FALSE,FALSE},
1119             {"",S_FALSE,FALSE}
1120         },
1121         {
1122             {Uri_HOST_IPV4,S_OK,FALSE},
1123             {0,S_FALSE,FALSE},
1124             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1125             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1126         }
1127     },
1128     {   "http://[FEDC:BA98::3210]", 0, S_OK, FALSE,
1129         {
1130             {"http://[fedc:ba98::3210]/",S_OK,FALSE},
1131             {"[fedc:ba98::3210]",S_OK,FALSE},
1132             {"http://[fedc:ba98::3210]/",S_OK,FALSE},
1133             {"",S_FALSE,FALSE},
1134             {"",S_FALSE,FALSE},
1135             {"",S_FALSE,FALSE},
1136             {"fedc:ba98::3210",S_OK,FALSE},
1137             {"",S_FALSE,FALSE},
1138             {"/",S_OK,FALSE},
1139             {"/",S_OK,FALSE},
1140             {"",S_FALSE,FALSE},
1141             {"http://[FEDC:BA98::3210]",S_OK,FALSE},
1142             {"http",S_OK,FALSE},
1143             {"",S_FALSE,FALSE},
1144             {"",S_FALSE,FALSE},
1145         },
1146         {
1147             {Uri_HOST_IPV6,S_OK,FALSE},
1148             {80,S_OK,FALSE},
1149             {URL_SCHEME_HTTP,S_OK,FALSE},
1150             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1151         }
1152     },
1153     {   "http://[::]", 0, S_OK, FALSE,
1154         {
1155             {"http://[::]/",S_OK,FALSE},
1156             {"[::]",S_OK,FALSE},
1157             {"http://[::]/",S_OK,FALSE},
1158             {"",S_FALSE,FALSE},
1159             {"",S_FALSE,FALSE},
1160             {"",S_FALSE,FALSE},
1161             {"::",S_OK,FALSE},
1162             {"",S_FALSE,FALSE},
1163             {"/",S_OK,FALSE},
1164             {"/",S_OK,FALSE},
1165             {"",S_FALSE,FALSE},
1166             {"http://[::]",S_OK,FALSE},
1167             {"http",S_OK,FALSE},
1168             {"",S_FALSE,FALSE},
1169             {"",S_FALSE,FALSE},
1170         },
1171         {
1172             {Uri_HOST_IPV6,S_OK,FALSE},
1173             {80,S_OK,FALSE},
1174             {URL_SCHEME_HTTP,S_OK,FALSE},
1175             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1176         }
1177     },
1178     {   "http://[FEDC:BA98::]", 0, S_OK, FALSE,
1179         {
1180             {"http://[fedc:ba98::]/",S_OK,FALSE},
1181             {"[fedc:ba98::]",S_OK,FALSE},
1182             {"http://[fedc:ba98::]/",S_OK,FALSE},
1183             {"",S_FALSE,FALSE},
1184             {"",S_FALSE,FALSE},
1185             {"",S_FALSE,FALSE},
1186             {"fedc:ba98::",S_OK,FALSE},
1187             {"",S_FALSE,FALSE},
1188             {"/",S_OK,FALSE},
1189             {"/",S_OK,FALSE},
1190             {"",S_FALSE,FALSE},
1191             {"http://[FEDC:BA98::]",S_OK,FALSE},
1192             {"http",S_OK,FALSE},
1193             {"",S_FALSE,FALSE},
1194             {"",S_FALSE,FALSE},
1195         },
1196         {
1197             {Uri_HOST_IPV6,S_OK,FALSE},
1198             {80,S_OK,FALSE},
1199             {URL_SCHEME_HTTP,S_OK,FALSE},
1200             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1201         }
1202     },
1203     /* Valid even with 2 byte elision because it doesn't appear the beginning or end. */
1204     {   "http://[1::3:4:5:6:7:8]", 0, S_OK, FALSE,
1205         {
1206             {"http://[1:0:3:4:5:6:7:8]/",S_OK,FALSE},
1207             {"[1:0:3:4:5:6:7:8]",S_OK,FALSE},
1208             {"http://[1:0:3:4:5:6:7:8]/",S_OK,FALSE},
1209             {"",S_FALSE,FALSE},
1210             {"",S_FALSE,FALSE},
1211             {"",S_FALSE,FALSE},
1212             {"1:0:3:4:5:6:7:8",S_OK,FALSE},
1213             {"",S_FALSE,FALSE},
1214             {"/",S_OK,FALSE},
1215             {"/",S_OK,FALSE},
1216             {"",S_FALSE,FALSE},
1217             {"http://[1::3:4:5:6:7:8]",S_OK,FALSE},
1218             {"http",S_OK,FALSE},
1219             {"",S_FALSE,FALSE},
1220             {"",S_FALSE,FALSE},
1221         },
1222         {
1223             {Uri_HOST_IPV6,S_OK,FALSE},
1224             {80,S_OK,FALSE},
1225             {URL_SCHEME_HTTP,S_OK,FALSE},
1226             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1227         }
1228     },
1229     {   "http://[v2.34]/", 0, S_OK, FALSE,
1230         {
1231             {"http://[v2.34]/",S_OK,FALSE},
1232             {"[v2.34]",S_OK,FALSE},
1233             {"http://[v2.34]/",S_OK,FALSE},
1234             {"",S_FALSE,FALSE},
1235             {"",S_FALSE,FALSE},
1236             {"",S_FALSE,FALSE},
1237             {"[v2.34]",S_OK,FALSE},
1238             {"",S_FALSE,FALSE},
1239             {"/",S_OK,FALSE},
1240             {"/",S_OK,FALSE},
1241             {"",S_FALSE,FALSE},
1242             {"http://[v2.34]/",S_OK,FALSE},
1243             {"http",S_OK,FALSE},
1244             {"",S_FALSE,FALSE},
1245             {"",S_FALSE,FALSE}
1246         },
1247         {
1248             {Uri_HOST_UNKNOWN,S_OK,FALSE},
1249             {80,S_OK,FALSE},
1250             {URL_SCHEME_HTTP,S_OK,FALSE},
1251             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1252         }
1253     },
1254     /* Windows ignores ':' if they appear after a '[' on a non-IPLiteral host. */
1255     {   "http://[xyz:12345.com/test", 0, S_OK, FALSE,
1256         {
1257             {"http://[xyz:12345.com/test",S_OK,FALSE},
1258             {"[xyz:12345.com",S_OK,FALSE},
1259             {"http://[xyz:12345.com/test",S_OK,FALSE},
1260             {"[xyz:12345.com",S_OK,FALSE},
1261             {"",S_FALSE,FALSE},
1262             {"",S_FALSE,FALSE},
1263             {"[xyz:12345.com",S_OK,FALSE},
1264             {"",S_FALSE,FALSE},
1265             {"/test",S_OK,FALSE},
1266             {"/test",S_OK,FALSE},
1267             {"",S_FALSE,FALSE},
1268             {"http://[xyz:12345.com/test",S_OK,FALSE},
1269             {"http",S_OK,FALSE},
1270             {"",S_FALSE,FALSE},
1271             {"",S_FALSE,FALSE}
1272         },
1273         {
1274             {Uri_HOST_DNS,S_OK,FALSE},
1275             {80,S_OK,FALSE},
1276             {URL_SCHEME_HTTP,S_OK,FALSE},
1277             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1278         }
1279     },
1280     /* Valid URI since the '[' and ']' don't appear at the beginning and end
1281      * of the host name (respectively).
1282      */
1283     {   "ftp://www.[works].com/", 0, S_OK, FALSE,
1284         {
1285             {"ftp://www.[works].com/",S_OK,FALSE},
1286             {"www.[works].com",S_OK,FALSE},
1287             {"ftp://www.[works].com/",S_OK,FALSE},
1288             {"[works].com",S_OK,FALSE},
1289             {"",S_FALSE,FALSE},
1290             {"",S_FALSE,FALSE},
1291             {"www.[works].com",S_OK,FALSE},
1292             {"",S_FALSE,FALSE},
1293             {"/",S_OK,FALSE},
1294             {"/",S_OK,FALSE},
1295             {"",S_FALSE,FALSE},
1296             {"ftp://www.[works].com/",S_OK,FALSE},
1297             {"ftp",S_OK,FALSE},
1298             {"",S_FALSE,FALSE},
1299             {"",S_FALSE,FALSE}
1300         },
1301         {
1302             {Uri_HOST_DNS,S_OK,FALSE},
1303             {21,S_OK,FALSE},
1304             {URL_SCHEME_FTP,S_OK,FALSE},
1305             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1306         }
1307     },
1308     /* Considers ':' a delimiter since it appears after the ']'. */
1309     {   "http://www.google.com]:12345/", 0, S_OK, FALSE,
1310         {
1311             {"http://www.google.com]:12345/",S_OK,FALSE},
1312             {"www.google.com]:12345",S_OK,FALSE},
1313             {"http://www.google.com]:12345/",S_OK,FALSE},
1314             {"google.com]",S_OK,FALSE},
1315             {"",S_FALSE,FALSE},
1316             {"",S_FALSE,FALSE},
1317             {"www.google.com]",S_OK,FALSE},
1318             {"",S_FALSE,FALSE},
1319             {"/",S_OK,FALSE},
1320             {"/",S_OK,FALSE},
1321             {"",S_FALSE,FALSE},
1322             {"http://www.google.com]:12345/",S_OK,FALSE},
1323             {"http",S_OK,FALSE},
1324             {"",S_FALSE,FALSE},
1325             {"",S_FALSE,FALSE}
1326         },
1327         {
1328             {Uri_HOST_DNS,S_OK,FALSE},
1329             {12345,S_OK,FALSE},
1330             {URL_SCHEME_HTTP,S_OK,FALSE},
1331             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1332         }
1333     },
1334     /* Unknown scheme types can have invalid % encoded data in the hostname. */
1335     {   "zip://w%XXw%GEw.google.com/", 0, S_OK, FALSE,
1336         {
1337             {"zip://w%XXw%GEw.google.com/",S_OK,FALSE},
1338             {"w%XXw%GEw.google.com",S_OK,FALSE},
1339             {"zip://w%XXw%GEw.google.com/",S_OK,FALSE},
1340             {"google.com",S_OK,FALSE},
1341             {"",S_FALSE,FALSE},
1342             {"",S_FALSE,FALSE},
1343             {"w%XXw%GEw.google.com",S_OK,FALSE},
1344             {"",S_FALSE,FALSE},
1345             {"/",S_OK,FALSE},
1346             {"/",S_OK,FALSE},
1347             {"",S_FALSE,FALSE},
1348             {"zip://w%XXw%GEw.google.com/",S_OK,FALSE},
1349             {"zip",S_OK,FALSE},
1350             {"",S_FALSE,FALSE},
1351             {"",S_FALSE,FALSE}
1352         },
1353         {
1354             {Uri_HOST_DNS,S_OK,FALSE},
1355             {0,S_FALSE,FALSE},
1356             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1357             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1358         }
1359     },
1360     /* Unknown scheme types hostname doesn't get lower cased. */
1361     {   "zip://GOOGLE.com/", 0, S_OK, FALSE,
1362         {
1363             {"zip://GOOGLE.com/",S_OK,FALSE},
1364             {"GOOGLE.com",S_OK,FALSE},
1365             {"zip://GOOGLE.com/",S_OK,FALSE},
1366             {"GOOGLE.com",S_OK,FALSE},
1367             {"",S_FALSE,FALSE},
1368             {"",S_FALSE,FALSE},
1369             {"GOOGLE.com",S_OK,FALSE},
1370             {"",S_FALSE,FALSE},
1371             {"/",S_OK,FALSE},
1372             {"/",S_OK,FALSE},
1373             {"",S_FALSE,FALSE},
1374             {"zip://GOOGLE.com/",S_OK,FALSE},
1375             {"zip",S_OK,FALSE},
1376             {"",S_FALSE,FALSE},
1377             {"",S_FALSE,FALSE}
1378         },
1379         {
1380             {Uri_HOST_DNS,S_OK,FALSE},
1381             {0,S_FALSE,FALSE},
1382             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1383             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1384         }
1385     },
1386     /* Hostname get's lower cased for known scheme types. */
1387     {   "http://WWW.GOOGLE.com/", 0, S_OK, FALSE,
1388         {
1389             {"http://www.google.com/",S_OK,FALSE},
1390             {"www.google.com",S_OK,FALSE},
1391             {"http://www.google.com/",S_OK,FALSE},
1392             {"google.com",S_OK,FALSE},
1393             {"",S_FALSE,FALSE},
1394             {"",S_FALSE,FALSE},
1395             {"www.google.com",S_OK,FALSE},
1396             {"",S_FALSE,FALSE},
1397             {"/",S_OK,FALSE},
1398             {"/",S_OK,FALSE},
1399             {"",S_FALSE,FALSE},
1400             {"http://WWW.GOOGLE.com/",S_OK,FALSE},
1401             {"http",S_OK,FALSE},
1402             {"",S_FALSE,FALSE},
1403             {"",S_FALSE,FALSE}
1404         },
1405         {
1406             {Uri_HOST_DNS,S_OK,FALSE},
1407             {80,S_OK,FALSE},
1408             {URL_SCHEME_HTTP,S_OK,FALSE},
1409             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1410         }
1411     },
1412     /* Characters that get % encoded in the hostname also have their percent
1413      * encoded forms lower cased.
1414      */
1415     {   "http://www.%7Cgoogle|.com/", 0, S_OK, FALSE,
1416         {
1417             {"http://www.%7cgoogle%7c.com/",S_OK,FALSE},
1418             {"www.%7cgoogle%7c.com",S_OK,FALSE},
1419             {"http://www.%7cgoogle%7c.com/",S_OK,FALSE},
1420             {"%7cgoogle%7c.com",S_OK,FALSE},
1421             {"",S_FALSE,FALSE},
1422             {"",S_FALSE,FALSE},
1423             {"www.%7cgoogle%7c.com",S_OK,FALSE},
1424             {"",S_FALSE,FALSE},
1425             {"/",S_OK,FALSE},
1426             {"/",S_OK,FALSE},
1427             {"",S_FALSE,FALSE},
1428             {"http://www.%7Cgoogle|.com/",S_OK,FALSE},
1429             {"http",S_OK,FALSE},
1430             {"",S_FALSE,FALSE},
1431             {"",S_FALSE,FALSE}
1432         },
1433         {
1434             {Uri_HOST_DNS,S_OK,FALSE},
1435             {80,S_OK,FALSE},
1436             {URL_SCHEME_HTTP,S_OK,FALSE},
1437             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1438         }
1439     },
1440     /* IPv4 addresses attached to IPv6 can be included in elisions. */
1441     {   "http://[1:2:3:4:5:6:0.0.0.0]", 0, S_OK, FALSE,
1442         {
1443             {"http://[1:2:3:4:5:6::]/",S_OK,FALSE},
1444             {"[1:2:3:4:5:6::]",S_OK,FALSE},
1445             {"http://[1:2:3:4:5:6::]/",S_OK,FALSE},
1446             {"",S_FALSE,FALSE},
1447             {"",S_FALSE,FALSE},
1448             {"",S_FALSE,FALSE},
1449             {"1:2:3:4:5:6::",S_OK,FALSE},
1450             {"",S_FALSE,FALSE},
1451             {"/",S_OK,FALSE},
1452             {"/",S_OK,FALSE},
1453             {"",S_FALSE,FALSE},
1454             {"http://[1:2:3:4:5:6:0.0.0.0]",S_OK,FALSE},
1455             {"http",S_OK,FALSE},
1456             {"",S_FALSE,FALSE},
1457             {"",S_FALSE,FALSE},
1458         },
1459         {
1460             {Uri_HOST_IPV6,S_OK,FALSE},
1461             {80,S_OK,FALSE},
1462             {URL_SCHEME_HTTP,S_OK,FALSE},
1463             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1464         }
1465     },
1466     /* IPv4 addresses get normalized. */
1467     {   "http://[::001.002.003.000]", 0, S_OK, FALSE,
1468         {
1469             {"http://[::1.2.3.0]/",S_OK,FALSE},
1470             {"[::1.2.3.0]",S_OK,FALSE},
1471             {"http://[::1.2.3.0]/",S_OK,FALSE},
1472             {"",S_FALSE,FALSE},
1473             {"",S_FALSE,FALSE},
1474             {"",S_FALSE,FALSE},
1475             {"::1.2.3.0",S_OK,FALSE},
1476             {"",S_FALSE,FALSE},
1477             {"/",S_OK,FALSE},
1478             {"/",S_OK,FALSE},
1479             {"",S_FALSE,FALSE},
1480             {"http://[::001.002.003.000]",S_OK,FALSE},
1481             {"http",S_OK,FALSE},
1482             {"",S_FALSE,FALSE},
1483             {"",S_FALSE,FALSE},
1484         },
1485         {
1486             {Uri_HOST_IPV6,S_OK,FALSE},
1487             {80,S_OK,FALSE},
1488             {URL_SCHEME_HTTP,S_OK,FALSE},
1489             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1490         }
1491     },
1492     /* Windows doesn't do anything to IPv6's in unknown schemes. */
1493     {   "zip://[0001:0:000:0004:0005:0006:001.002.003.000]", 0, S_OK, FALSE,
1494         {
1495             {"zip://[0001:0:000:0004:0005:0006:001.002.003.000]/",S_OK,FALSE},
1496             {"[0001:0:000:0004:0005:0006:001.002.003.000]",S_OK,FALSE},
1497             {"zip://[0001:0:000:0004:0005:0006:001.002.003.000]/",S_OK,FALSE},
1498             {"",S_FALSE,FALSE},
1499             {"",S_FALSE,FALSE},
1500             {"",S_FALSE,FALSE},
1501             {"0001:0:000:0004:0005:0006:001.002.003.000",S_OK,FALSE},
1502             {"",S_FALSE,FALSE},
1503             {"/",S_OK,FALSE},
1504             {"/",S_OK,FALSE},
1505             {"",S_FALSE,FALSE},
1506             {"zip://[0001:0:000:0004:0005:0006:001.002.003.000]",S_OK,FALSE},
1507             {"zip",S_OK,FALSE},
1508             {"",S_FALSE,FALSE},
1509             {"",S_FALSE,FALSE},
1510         },
1511         {
1512             {Uri_HOST_IPV6,S_OK,FALSE},
1513             {0,S_FALSE,FALSE},
1514             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1515             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1516         }
1517     },
1518     /* IPv4 address is converted into 2 h16 components. */
1519     {   "http://[ffff::192.222.111.32]", 0, S_OK, FALSE,
1520         {
1521             {"http://[ffff::c0de:6f20]/",S_OK,FALSE},
1522             {"[ffff::c0de:6f20]",S_OK,FALSE},
1523             {"http://[ffff::c0de:6f20]/",S_OK,FALSE},
1524             {"",S_FALSE,FALSE},
1525             {"",S_FALSE,FALSE},
1526             {"",S_FALSE,FALSE},
1527             {"ffff::c0de:6f20",S_OK,FALSE},
1528             {"",S_FALSE,FALSE},
1529             {"/",S_OK,FALSE},
1530             {"/",S_OK,FALSE},
1531             {"",S_FALSE,FALSE},
1532             {"http://[ffff::192.222.111.32]",S_OK,FALSE},
1533             {"http",S_OK,FALSE},
1534             {"",S_FALSE,FALSE},
1535             {"",S_FALSE,FALSE},
1536         },
1537         {
1538             {Uri_HOST_IPV6,S_OK,FALSE},
1539             {80,S_OK,FALSE},
1540             {URL_SCHEME_HTTP,S_OK,FALSE},
1541             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1542         }
1543     },
1544     /* Max value for a port. */
1545     {   "http://google.com:65535", 0, S_OK, FALSE,
1546         {
1547             {"http://google.com:65535/",S_OK,FALSE},
1548             {"google.com:65535",S_OK,FALSE},
1549             {"http://google.com:65535/",S_OK,FALSE},
1550             {"google.com",S_OK,FALSE},
1551             {"",S_FALSE,FALSE},
1552             {"",S_FALSE,FALSE},
1553             {"google.com",S_OK,FALSE},
1554             {"",S_FALSE,FALSE},
1555             {"/",S_OK,FALSE},
1556             {"/",S_OK,FALSE},
1557             {"",S_FALSE,FALSE},
1558             {"http://google.com:65535",S_OK,FALSE},
1559             {"http",S_OK,FALSE},
1560             {"",S_FALSE,FALSE},
1561             {"",S_FALSE,FALSE}
1562         },
1563         {
1564             {Uri_HOST_DNS,S_OK,FALSE},
1565             {65535,S_OK,FALSE},
1566             {URL_SCHEME_HTTP,S_OK,FALSE},
1567             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1568         }
1569     },
1570     {   "zip://google.com:65536", 0, S_OK, FALSE,
1571         {
1572             {"zip://google.com:65536/",S_OK,FALSE},
1573             {"google.com:65536",S_OK,FALSE},
1574             {"zip://google.com:65536/",S_OK,FALSE},
1575             {"google.com:65536",S_OK,FALSE},
1576             {"",S_FALSE,FALSE},
1577             {"",S_FALSE,FALSE},
1578             {"google.com:65536",S_OK,FALSE},
1579             {"",S_FALSE,FALSE},
1580             {"/",S_OK,FALSE},
1581             {"/",S_OK,FALSE},
1582             {"",S_FALSE,FALSE},
1583             {"zip://google.com:65536",S_OK,FALSE},
1584             {"zip",S_OK,FALSE},
1585             {"",S_FALSE,FALSE},
1586             {"",S_FALSE,FALSE}
1587         },
1588         {
1589             {Uri_HOST_DNS,S_OK,FALSE},
1590             {0,S_FALSE,FALSE},
1591             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1592             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1593         }
1594     },
1595     {   "zip://google.com:65536:25", 0, S_OK, FALSE,
1596         {
1597             {"zip://google.com:65536:25/",S_OK,FALSE},
1598             {"google.com:65536:25",S_OK,FALSE},
1599             {"zip://google.com:65536:25/",S_OK,FALSE},
1600             {"google.com:65536:25",S_OK,FALSE},
1601             {"",S_FALSE,FALSE},
1602             {"",S_FALSE,FALSE},
1603             {"google.com:65536:25",S_OK,FALSE},
1604             {"",S_FALSE,FALSE},
1605             {"/",S_OK,FALSE},
1606             {"/",S_OK,FALSE},
1607             {"",S_FALSE,FALSE},
1608             {"zip://google.com:65536:25",S_OK,FALSE},
1609             {"zip",S_OK,FALSE},
1610             {"",S_FALSE,FALSE},
1611             {"",S_FALSE,FALSE}
1612         },
1613         {
1614             {Uri_HOST_DNS,S_OK,FALSE},
1615             {0,S_FALSE,FALSE},
1616             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1617             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1618         }
1619     },
1620     {   "zip://[::ffff]:abcd", 0, S_OK, FALSE,
1621         {
1622             {"zip://[::ffff]:abcd/",S_OK,FALSE},
1623             {"[::ffff]:abcd",S_OK,FALSE},
1624             {"zip://[::ffff]:abcd/",S_OK,FALSE},
1625             {"",S_FALSE,FALSE},
1626             {"",S_FALSE,FALSE},
1627             {"",S_FALSE,FALSE},
1628             {"[::ffff]:abcd",S_OK,FALSE},
1629             {"",S_FALSE,FALSE},
1630             {"/",S_OK,FALSE},
1631             {"/",S_OK,FALSE},
1632             {"",S_FALSE,FALSE},
1633             {"zip://[::ffff]:abcd",S_OK,FALSE},
1634             {"zip",S_OK,FALSE},
1635             {"",S_FALSE,FALSE},
1636             {"",S_FALSE,FALSE}
1637         },
1638         {
1639             {Uri_HOST_DNS,S_OK,FALSE},
1640             {0,S_FALSE,FALSE},
1641             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1642             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1643         }
1644     },
1645     {   "zip://127.0.0.1:abcd", 0, S_OK, FALSE,
1646         {
1647             {"zip://127.0.0.1:abcd/",S_OK,FALSE},
1648             {"127.0.0.1:abcd",S_OK,FALSE},
1649             {"zip://127.0.0.1:abcd/",S_OK,FALSE},
1650             {"0.1:abcd",S_OK,FALSE},
1651             {"",S_FALSE,FALSE},
1652             {"",S_FALSE,FALSE},
1653             {"127.0.0.1:abcd",S_OK,FALSE},
1654             {"",S_FALSE,FALSE},
1655             {"/",S_OK,FALSE},
1656             {"/",S_OK,FALSE},
1657             {"",S_FALSE,FALSE},
1658             {"zip://127.0.0.1:abcd",S_OK,FALSE},
1659             {"zip",S_OK,FALSE},
1660             {"",S_FALSE,FALSE},
1661             {"",S_FALSE,FALSE}
1662         },
1663         {
1664             {Uri_HOST_DNS,S_OK,FALSE},
1665             {0,S_FALSE,FALSE},
1666             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1667             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1668         }
1669     },
1670     /* Port is just copied over. */
1671     {   "http://google.com:00035", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
1672         {
1673             {"http://google.com:00035",S_OK,FALSE},
1674             {"google.com:00035",S_OK,FALSE},
1675             {"http://google.com:00035",S_OK,FALSE,"http://google.com:35"},
1676             {"google.com",S_OK,FALSE},
1677             {"",S_FALSE,FALSE},
1678             {"",S_FALSE,FALSE},
1679             {"google.com",S_OK,FALSE},
1680             {"",S_FALSE,FALSE},
1681             {"",S_FALSE,FALSE},
1682             {"",S_FALSE,FALSE},
1683             {"",S_FALSE,FALSE},
1684             {"http://google.com:00035",S_OK,FALSE},
1685             {"http",S_OK,FALSE},
1686             {"",S_FALSE,FALSE},
1687             {"",S_FALSE,FALSE}
1688         },
1689         {
1690             {Uri_HOST_DNS,S_OK,FALSE},
1691             {35,S_OK,FALSE},
1692             {URL_SCHEME_HTTP,S_OK,FALSE},
1693             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1694         }
1695     },
1696     /* Default port is copied over. */
1697     {   "http://google.com:80", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
1698         {
1699             {"http://google.com:80",S_OK,FALSE},
1700             {"google.com:80",S_OK,FALSE},
1701             {"http://google.com:80",S_OK,FALSE},
1702             {"google.com",S_OK,FALSE},
1703             {"",S_FALSE,FALSE},
1704             {"",S_FALSE,FALSE},
1705             {"google.com",S_OK,FALSE},
1706             {"",S_FALSE,FALSE},
1707             {"",S_FALSE,FALSE},
1708             {"",S_FALSE,FALSE},
1709             {"",S_FALSE,FALSE},
1710             {"http://google.com:80",S_OK,FALSE},
1711             {"http",S_OK,FALSE},
1712             {"",S_FALSE,FALSE},
1713             {"",S_FALSE,FALSE}
1714         },
1715         {
1716             {Uri_HOST_DNS,S_OK,FALSE},
1717             {80,S_OK,FALSE},
1718             {URL_SCHEME_HTTP,S_OK,FALSE},
1719             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1720         }
1721     },
1722     {   "http://google.com.uk", 0, S_OK, FALSE,
1723         {
1724             {"http://google.com.uk/",S_OK,FALSE},
1725             {"google.com.uk",S_OK,FALSE},
1726             {"http://google.com.uk/",S_OK,FALSE},
1727             {"google.com.uk",S_OK,FALSE},
1728             {"",S_FALSE,FALSE},
1729             {"",S_FALSE,FALSE},
1730             {"google.com.uk",S_OK,FALSE},
1731             {"",S_FALSE,FALSE},
1732             {"/",S_OK,FALSE},
1733             {"/",S_OK,FALSE},
1734             {"",S_FALSE,FALSE},
1735             {"http://google.com.uk",S_OK,FALSE},
1736             {"http",S_OK,FALSE},
1737             {"",S_FALSE,FALSE},
1738             {"",S_FALSE,FALSE}
1739         },
1740         {
1741             {Uri_HOST_DNS,S_OK,FALSE},
1742             {80,S_OK,FALSE},
1743             {URL_SCHEME_HTTP,S_OK,FALSE},
1744             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1745         }
1746     },
1747     {   "http://google.com.com", 0, S_OK, FALSE,
1748         {
1749             {"http://google.com.com/",S_OK,FALSE},
1750             {"google.com.com",S_OK,FALSE},
1751             {"http://google.com.com/",S_OK,FALSE},
1752             {"com.com",S_OK,FALSE},
1753             {"",S_FALSE,FALSE},
1754             {"",S_FALSE,FALSE},
1755             {"google.com.com",S_OK,FALSE},
1756             {"",S_FALSE,FALSE},
1757             {"/",S_OK,FALSE},
1758             {"/",S_OK,FALSE},
1759             {"",S_FALSE,FALSE},
1760             {"http://google.com.com",S_OK,FALSE},
1761             {"http",S_OK,FALSE},
1762             {"",S_FALSE,FALSE},
1763             {"",S_FALSE,FALSE}
1764         },
1765         {
1766             {Uri_HOST_DNS,S_OK,FALSE},
1767             {80,S_OK,FALSE},
1768             {URL_SCHEME_HTTP,S_OK,FALSE},
1769             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1770         }
1771     },
1772     {   "http://google.uk.1", 0, S_OK, FALSE,
1773         {
1774             {"http://google.uk.1/",S_OK,FALSE},
1775             {"google.uk.1",S_OK,FALSE},
1776             {"http://google.uk.1/",S_OK,FALSE},
1777             {"google.uk.1",S_OK,FALSE},
1778             {"",S_FALSE,FALSE},
1779             {"",S_FALSE,FALSE},
1780             {"google.uk.1",S_OK,FALSE},
1781             {"",S_FALSE,FALSE},
1782             {"/",S_OK,FALSE},
1783             {"/",S_OK,FALSE},
1784             {"",S_FALSE,FALSE},
1785             {"http://google.uk.1",S_OK,FALSE},
1786             {"http",S_OK,FALSE},
1787             {"",S_FALSE,FALSE},
1788             {"",S_FALSE,FALSE}
1789         },
1790         {
1791             {Uri_HOST_DNS,S_OK,FALSE},
1792             {80,S_OK,FALSE},
1793             {URL_SCHEME_HTTP,S_OK,FALSE},
1794             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1795         }
1796     },
1797     /* Since foo isn't a recognized 3 character TLD its considered the domain name. */
1798     {   "http://google.foo.uk", 0, S_OK, FALSE,
1799         {
1800             {"http://google.foo.uk/",S_OK,FALSE},
1801             {"google.foo.uk",S_OK,FALSE},
1802             {"http://google.foo.uk/",S_OK,FALSE},
1803             {"foo.uk",S_OK,FALSE},
1804             {"",S_FALSE,FALSE},
1805             {"",S_FALSE,FALSE},
1806             {"google.foo.uk",S_OK,FALSE},
1807             {"",S_FALSE,FALSE},
1808             {"/",S_OK,FALSE},
1809             {"/",S_OK,FALSE},
1810             {"",S_FALSE,FALSE},
1811             {"http://google.foo.uk",S_OK,FALSE},
1812             {"http",S_OK,FALSE},
1813             {"",S_FALSE,FALSE},
1814             {"",S_FALSE,FALSE}
1815         },
1816         {
1817             {Uri_HOST_DNS,S_OK,FALSE},
1818             {80,S_OK,FALSE},
1819             {URL_SCHEME_HTTP,S_OK,FALSE},
1820             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1821         }
1822     },
1823     {   "http://.com", 0, S_OK, FALSE,
1824         {
1825             {"http://.com/",S_OK,FALSE},
1826             {".com",S_OK,FALSE},
1827             {"http://.com/",S_OK,FALSE},
1828             {".com",S_OK,FALSE},
1829             {"",S_FALSE,FALSE},
1830             {"",S_FALSE,FALSE},
1831             {".com",S_OK,FALSE},
1832             {"",S_FALSE,FALSE},
1833             {"/",S_OK,FALSE},
1834             {"/",S_OK,FALSE},
1835             {"",S_FALSE,FALSE},
1836             {"http://.com",S_OK,FALSE},
1837             {"http",S_OK,FALSE},
1838             {"",S_FALSE,FALSE},
1839             {"",S_FALSE,FALSE}
1840         },
1841         {
1842             {Uri_HOST_DNS,S_OK,FALSE},
1843             {80,S_OK,FALSE},
1844             {URL_SCHEME_HTTP,S_OK,FALSE},
1845             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1846         }
1847     },
1848     {   "http://.uk", 0, S_OK, FALSE,
1849         {
1850             {"http://.uk/",S_OK,FALSE},
1851             {".uk",S_OK,FALSE},
1852             {"http://.uk/",S_OK,FALSE},
1853             {"",S_FALSE,FALSE},
1854             {"",S_FALSE,FALSE},
1855             {"",S_FALSE,FALSE},
1856             {".uk",S_OK,FALSE},
1857             {"",S_FALSE,FALSE},
1858             {"/",S_OK,FALSE},
1859             {"/",S_OK,FALSE},
1860             {"",S_FALSE,FALSE},
1861             {"http://.uk",S_OK,FALSE},
1862             {"http",S_OK,FALSE},
1863             {"",S_FALSE,FALSE},
1864             {"",S_FALSE,FALSE}
1865         },
1866         {
1867             {Uri_HOST_DNS,S_OK,FALSE},
1868             {80,S_OK,FALSE},
1869             {URL_SCHEME_HTTP,S_OK,FALSE},
1870             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1871         }
1872     },
1873     {   "http://www.co.google.com.[]", 0, S_OK, FALSE,
1874         {
1875             {"http://www.co.google.com.[]/",S_OK,FALSE},
1876             {"www.co.google.com.[]",S_OK,FALSE},
1877             {"http://www.co.google.com.[]/",S_OK,FALSE},
1878             {"google.com.[]",S_OK,FALSE},
1879             {"",S_FALSE,FALSE},
1880             {"",S_FALSE,FALSE},
1881             {"www.co.google.com.[]",S_OK,FALSE},
1882             {"",S_FALSE,FALSE},
1883             {"/",S_OK,FALSE},
1884             {"/",S_OK,FALSE},
1885             {"",S_FALSE,FALSE},
1886             {"http://www.co.google.com.[]",S_OK,FALSE},
1887             {"http",S_OK,FALSE},
1888             {"",S_FALSE,FALSE},
1889             {"",S_FALSE,FALSE}
1890         },
1891         {
1892             {Uri_HOST_DNS,S_OK,FALSE},
1893             {80,S_OK,FALSE},
1894             {URL_SCHEME_HTTP,S_OK,FALSE},
1895             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1896         }
1897     },
1898     {   "http://co.uk", 0, S_OK, FALSE,
1899         {
1900             {"http://co.uk/",S_OK,FALSE},
1901             {"co.uk",S_OK,FALSE},
1902             {"http://co.uk/",S_OK,FALSE},
1903             {"",S_FALSE,FALSE},
1904             {"",S_FALSE,FALSE},
1905             {"",S_FALSE,FALSE},
1906             {"co.uk",S_OK,FALSE},
1907             {"",S_FALSE,FALSE},
1908             {"/",S_OK,FALSE},
1909             {"/",S_OK,FALSE},
1910             {"",S_FALSE,FALSE},
1911             {"http://co.uk",S_OK,FALSE},
1912             {"http",S_OK,FALSE},
1913             {"",S_FALSE,FALSE},
1914             {"",S_FALSE,FALSE}
1915         },
1916         {
1917             {Uri_HOST_DNS,S_OK,FALSE},
1918             {80,S_OK,FALSE},
1919             {URL_SCHEME_HTTP,S_OK,FALSE},
1920             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1921         }
1922     },
1923     {   "http://www.co.google.us.test", 0, S_OK, FALSE,
1924         {
1925             {"http://www.co.google.us.test/",S_OK,FALSE},
1926             {"www.co.google.us.test",S_OK,FALSE},
1927             {"http://www.co.google.us.test/",S_OK,FALSE},
1928             {"us.test",S_OK,FALSE},
1929             {"",S_FALSE,FALSE},
1930             {"",S_FALSE,FALSE},
1931             {"www.co.google.us.test",S_OK,FALSE},
1932             {"",S_FALSE,FALSE},
1933             {"/",S_OK,FALSE},
1934             {"/",S_OK,FALSE},
1935             {"",S_FALSE,FALSE},
1936             {"http://www.co.google.us.test",S_OK,FALSE},
1937             {"http",S_OK,FALSE},
1938             {"",S_FALSE,FALSE},
1939             {"",S_FALSE,FALSE}
1940         },
1941         {
1942             {Uri_HOST_DNS,S_OK,FALSE},
1943             {80,S_OK,FALSE},
1944             {URL_SCHEME_HTTP,S_OK,FALSE},
1945             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1946         }
1947     },
1948     {   "http://gov.uk", 0, S_OK, FALSE,
1949         {
1950             {"http://gov.uk/",S_OK,FALSE},
1951             {"gov.uk",S_OK,FALSE},
1952             {"http://gov.uk/",S_OK,FALSE},
1953             {"",S_FALSE,FALSE},
1954             {"",S_FALSE,FALSE},
1955             {"",S_FALSE,FALSE},
1956             {"gov.uk",S_OK,FALSE},
1957             {"",S_FALSE,FALSE},
1958             {"/",S_OK,FALSE},
1959             {"/",S_OK,FALSE},
1960             {"",S_FALSE,FALSE},
1961             {"http://gov.uk",S_OK,FALSE},
1962             {"http",S_OK,FALSE},
1963             {"",S_FALSE,FALSE},
1964             {"",S_FALSE,FALSE}
1965         },
1966         {
1967             {Uri_HOST_DNS,S_OK,FALSE},
1968             {80,S_OK,FALSE},
1969             {URL_SCHEME_HTTP,S_OK,FALSE},
1970             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1971         }
1972     },
1973     {   "zip://www.google.com\\test", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
1974         {
1975             {"zip://www.google.com\\test",S_OK,FALSE},
1976             {"www.google.com\\test",S_OK,FALSE},
1977             {"zip://www.google.com\\test",S_OK,FALSE},
1978             {"google.com\\test",S_OK,FALSE},
1979             {"",S_FALSE,FALSE},
1980             {"",S_FALSE,FALSE},
1981             {"www.google.com\\test",S_OK,FALSE},
1982             {"",S_FALSE,FALSE},
1983             {"",S_FALSE,FALSE},
1984             {"",S_FALSE,FALSE},
1985             {"",S_FALSE,FALSE},
1986             {"zip://www.google.com\\test",S_OK,FALSE},
1987             {"zip",S_OK,FALSE},
1988             {"",S_FALSE,FALSE},
1989             {"",S_FALSE,FALSE}
1990         },
1991         {
1992             {Uri_HOST_DNS,S_OK,FALSE},
1993             {0,S_FALSE,FALSE},
1994             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1995             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1996         }
1997     },
1998     {   "urn:excepts:bad:%XY:encoded", 0, S_OK, FALSE,
1999         {
2000             {"urn:excepts:bad:%XY:encoded",S_OK,FALSE},
2001             {"",S_FALSE,FALSE},
2002             {"urn:excepts:bad:%XY:encoded",S_OK,FALSE},
2003             {"",S_FALSE,FALSE},
2004             {"",S_FALSE,FALSE},
2005             {"",S_FALSE,FALSE},
2006             {"",S_FALSE,FALSE},
2007             {"",S_FALSE,FALSE},
2008             {"excepts:bad:%XY:encoded",S_OK,FALSE},
2009             {"excepts:bad:%XY:encoded",S_OK,FALSE},
2010             {"",S_FALSE,FALSE},
2011             {"urn:excepts:bad:%XY:encoded",S_OK,FALSE},
2012             {"urn",S_OK,FALSE},
2013             {"",S_FALSE,FALSE},
2014             {"",S_FALSE,FALSE}
2015         },
2016         {
2017             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2018             {0,S_FALSE,FALSE},
2019             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2020             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2021         }
2022     },
2023     /* Since the original URI doesn't contain an extra '/' before the path no % encoded values
2024      * are decoded and all '%' are encoded.
2025      */
2026     {   "file://C:/te%3Es%2Et/tes%t.mp3", 0, S_OK, FALSE,
2027         {
2028             {"file:///C:/te%253Es%252Et/tes%25t.mp3",S_OK,FALSE},
2029             {"",S_FALSE,FALSE},
2030             {"file:///C:/te%253Es%252Et/tes%25t.mp3",S_OK,FALSE},
2031             {"",S_FALSE,FALSE},
2032             {".mp3",S_OK,FALSE},
2033             {"",S_FALSE,FALSE},
2034             {"",S_FALSE,FALSE},
2035             {"",S_FALSE,FALSE},
2036             {"/C:/te%253Es%252Et/tes%25t.mp3",S_OK,FALSE},
2037             {"/C:/te%253Es%252Et/tes%25t.mp3",S_OK,FALSE},
2038             {"",S_FALSE,FALSE},
2039             {"file://C:/te%3Es%2Et/tes%t.mp3",S_OK,FALSE},
2040             {"file",S_OK,FALSE},
2041             {"",S_FALSE,FALSE},
2042             {"",S_FALSE,FALSE}
2043         },
2044         {
2045             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2046             {0,S_FALSE,FALSE},
2047             {URL_SCHEME_FILE,S_OK,FALSE},
2048             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2049         }
2050     },
2051     /* Since there's a '/' in front of the drive letter, any percent encoded, non-forbidden character
2052      * is decoded and only %'s in front of invalid hex digits are encoded.
2053      */
2054     {   "file:///C:/te%3Es%2Et/t%23es%t.mp3", 0, S_OK, FALSE,
2055         {
2056             {"file:///C:/te%3Es.t/t#es%25t.mp3",S_OK,FALSE},
2057             {"",S_FALSE,FALSE},
2058             {"file:///C:/te%3Es.t/t#es%25t.mp3",S_OK,FALSE},
2059             {"",S_FALSE,FALSE},
2060             {".mp3",S_OK,FALSE},
2061             {"",S_FALSE,FALSE},
2062             {"",S_FALSE,FALSE},
2063             {"",S_FALSE,FALSE},
2064             {"/C:/te%3Es.t/t#es%25t.mp3",S_OK,FALSE},
2065             {"/C:/te%3Es.t/t#es%25t.mp3",S_OK,FALSE},
2066             {"",S_FALSE,FALSE},
2067             {"file:///C:/te%3Es%2Et/t%23es%t.mp3",S_OK,FALSE},
2068             {"file",S_OK,FALSE},
2069             {"",S_FALSE,FALSE},
2070             {"",S_FALSE,FALSE}
2071         },
2072         {
2073             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2074             {0,S_FALSE,FALSE},
2075             {URL_SCHEME_FILE,S_OK,FALSE},
2076             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2077         }
2078     },
2079     /* Only unreserved percent encoded characters are decoded for known schemes that aren't file. */
2080     {   "http://[::001.002.003.000]/%3F%23%2E%54/test", 0, S_OK, FALSE,
2081         {
2082             {"http://[::1.2.3.0]/%3F%23.T/test",S_OK,FALSE},
2083             {"[::1.2.3.0]",S_OK,FALSE},
2084             {"http://[::1.2.3.0]/%3F%23.T/test",S_OK,FALSE},
2085             {"",S_FALSE,FALSE},
2086             {"",S_FALSE,FALSE},
2087             {"",S_FALSE,FALSE},
2088             {"::1.2.3.0",S_OK,FALSE},
2089             {"",S_FALSE,FALSE},
2090             {"/%3F%23.T/test",S_OK,FALSE},
2091             {"/%3F%23.T/test",S_OK,FALSE},
2092             {"",S_FALSE,FALSE},
2093             {"http://[::001.002.003.000]/%3F%23%2E%54/test",S_OK,FALSE},
2094             {"http",S_OK,FALSE},
2095             {"",S_FALSE,FALSE},
2096             {"",S_FALSE,FALSE},
2097         },
2098         {
2099             {Uri_HOST_IPV6,S_OK,FALSE},
2100             {80,S_OK,FALSE},
2101             {URL_SCHEME_HTTP,S_OK,FALSE},
2102             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2103         }
2104     },
2105     /* Forbidden characters are always encoded for file URIs. */
2106     {   "file:///C:/\"test\"/test.mp3", Uri_CREATE_NO_ENCODE_FORBIDDEN_CHARACTERS, S_OK, FALSE,
2107         {
2108             {"file:///C:/%22test%22/test.mp3",S_OK,FALSE},
2109             {"",S_FALSE,FALSE},
2110             {"file:///C:/%22test%22/test.mp3",S_OK,FALSE},
2111             {"",S_FALSE,FALSE},
2112             {".mp3",S_OK,FALSE},
2113             {"",S_FALSE,FALSE},
2114             {"",S_FALSE,FALSE},
2115             {"",S_FALSE,FALSE},
2116             {"/C:/%22test%22/test.mp3",S_OK,FALSE},
2117             {"/C:/%22test%22/test.mp3",S_OK,FALSE},
2118             {"",S_FALSE,FALSE},
2119             {"file:///C:/\"test\"/test.mp3",S_OK,FALSE},
2120             {"file",S_OK,FALSE},
2121             {"",S_FALSE,FALSE},
2122             {"",S_FALSE,FALSE}
2123         },
2124         {
2125             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2126             {0,S_FALSE,FALSE},
2127             {URL_SCHEME_FILE,S_OK,FALSE},
2128             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2129         }
2130     },
2131     /* Forbidden characters are never encoded for unknown scheme types. */
2132     {   "1234://4294967295/<|>\" test<|>", 0, S_OK, FALSE,
2133         {
2134             {"1234://4294967295/<|>\" test<|>",S_OK,FALSE},
2135             {"4294967295",S_OK,FALSE},
2136             {"1234://4294967295/<|>\" test<|>",S_OK,FALSE},
2137             {"",S_FALSE,FALSE},
2138             {"",S_FALSE,FALSE},
2139             {"",S_FALSE,FALSE},
2140             {"4294967295",S_OK,FALSE},
2141             {"",S_FALSE,FALSE},
2142             {"/<|>\" test<|>",S_OK,FALSE},
2143             {"/<|>\" test<|>",S_OK,FALSE},
2144             {"",S_FALSE,FALSE},
2145             {"1234://4294967295/<|>\" test<|>",S_OK,FALSE},
2146             {"1234",S_OK,FALSE},
2147             {"",S_FALSE,FALSE},
2148             {"",S_FALSE,FALSE}
2149         },
2150         {
2151             {Uri_HOST_IPV4,S_OK,FALSE},
2152             {0,S_FALSE,FALSE},
2153             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2154             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2155         }
2156     },
2157     /* Make sure forbidden characters are percent encoded. */
2158     {   "http://gov.uk/<|> test<|>", 0, S_OK, FALSE,
2159         {
2160             {"http://gov.uk/%3C%7C%3E%20test%3C%7C%3E",S_OK,FALSE},
2161             {"gov.uk",S_OK,FALSE},
2162             {"http://gov.uk/%3C%7C%3E%20test%3C%7C%3E",S_OK,FALSE},
2163             {"",S_FALSE,FALSE},
2164             {"",S_FALSE,FALSE},
2165             {"",S_FALSE,FALSE},
2166             {"gov.uk",S_OK,FALSE},
2167             {"",S_FALSE,FALSE},
2168             {"/%3C%7C%3E%20test%3C%7C%3E",S_OK,FALSE},
2169             {"/%3C%7C%3E%20test%3C%7C%3E",S_OK,FALSE},
2170             {"",S_FALSE,FALSE},
2171             {"http://gov.uk/<|> test<|>",S_OK,FALSE},
2172             {"http",S_OK,FALSE},
2173             {"",S_FALSE,FALSE},
2174             {"",S_FALSE,FALSE}
2175         },
2176         {
2177             {Uri_HOST_DNS,S_OK,FALSE},
2178             {80,S_OK,FALSE},
2179             {URL_SCHEME_HTTP,S_OK,FALSE},
2180             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2181         }
2182     },
2183     {   "http://gov.uk/test/../test2/././../test3/.././././", 0, S_OK, FALSE,
2184         {
2185             {"http://gov.uk/",S_OK,FALSE},
2186             {"gov.uk",S_OK,FALSE},
2187             {"http://gov.uk/",S_OK,FALSE},
2188             {"",S_FALSE,FALSE},
2189             {"",S_FALSE,FALSE},
2190             {"",S_FALSE,FALSE},
2191             {"gov.uk",S_OK,FALSE},
2192             {"",S_FALSE,FALSE},
2193             {"/",S_OK,FALSE},
2194             {"/",S_OK,FALSE},
2195             {"",S_FALSE,FALSE},
2196             {"http://gov.uk/test/../test2/././../test3/.././././",S_OK,FALSE},
2197             {"http",S_OK,FALSE},
2198             {"",S_FALSE,FALSE},
2199             {"",S_FALSE,FALSE}
2200         },
2201         {
2202             {Uri_HOST_DNS,S_OK,FALSE},
2203             {80,S_OK,FALSE},
2204             {URL_SCHEME_HTTP,S_OK,FALSE},
2205             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2206         }
2207     },
2208     {   "http://gov.uk/test/test2/../../..", 0, S_OK, FALSE,
2209         {
2210             {"http://gov.uk/",S_OK,FALSE},
2211             {"gov.uk",S_OK,FALSE},
2212             {"http://gov.uk/",S_OK,FALSE},
2213             {"",S_FALSE,FALSE},
2214             {"",S_FALSE,FALSE},
2215             {"",S_FALSE,FALSE},
2216             {"gov.uk",S_OK,FALSE},
2217             {"",S_FALSE,FALSE},
2218             {"/",S_OK,FALSE},
2219             {"/",S_OK,FALSE},
2220             {"",S_FALSE,FALSE},
2221             {"http://gov.uk/test/test2/../../..",S_OK,FALSE},
2222             {"http",S_OK,FALSE},
2223             {"",S_FALSE,FALSE},
2224             {"",S_FALSE,FALSE}
2225         },
2226         {
2227             {Uri_HOST_DNS,S_OK,FALSE},
2228             {80,S_OK,FALSE},
2229             {URL_SCHEME_HTTP,S_OK,FALSE},
2230             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2231         }
2232     },
2233     {   "http://gov.uk/test/test2/../../.", 0, S_OK, FALSE,
2234         {
2235             {"http://gov.uk/",S_OK,FALSE},
2236             {"gov.uk",S_OK,FALSE},
2237             {"http://gov.uk/",S_OK,FALSE},
2238             {"",S_FALSE,FALSE},
2239             {"",S_FALSE,FALSE},
2240             {"",S_FALSE,FALSE},
2241             {"gov.uk",S_OK,FALSE},
2242             {"",S_FALSE,FALSE},
2243             {"/",S_OK,FALSE},
2244             {"/",S_OK,FALSE},
2245             {"",S_FALSE,FALSE},
2246             {"http://gov.uk/test/test2/../../.",S_OK,FALSE},
2247             {"http",S_OK,FALSE},
2248             {"",S_FALSE,FALSE},
2249             {"",S_FALSE,FALSE}
2250         },
2251         {
2252             {Uri_HOST_DNS,S_OK,FALSE},
2253             {80,S_OK,FALSE},
2254             {URL_SCHEME_HTTP,S_OK,FALSE},
2255             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2256         }
2257     },
2258     {   "file://c:\\tests\\../tests\\./.\\..\\foo%20bar.mp3", 0, S_OK, FALSE,
2259         {
2260             {"file:///c:/foo%2520bar.mp3",S_OK,FALSE},
2261             {"",S_FALSE,FALSE},
2262             {"file:///c:/foo%2520bar.mp3",S_OK,FALSE},
2263             {"",S_FALSE,FALSE},
2264             {".mp3",S_OK,FALSE},
2265             {"",S_FALSE,FALSE},
2266             {"",S_FALSE,FALSE},
2267             {"",S_FALSE,FALSE},
2268             {"/c:/foo%2520bar.mp3",S_OK,FALSE},
2269             {"/c:/foo%2520bar.mp3",S_OK,FALSE},
2270             {"",S_FALSE,FALSE},
2271             {"file://c:\\tests\\../tests\\./.\\..\\foo%20bar.mp3",S_OK,FALSE},
2272             {"file",S_OK,FALSE},
2273             {"",S_FALSE,FALSE},
2274             {"",S_FALSE,FALSE}
2275         },
2276         {
2277             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2278             {0,S_FALSE,FALSE},
2279             {URL_SCHEME_FILE,S_OK,FALSE},
2280             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2281         }
2282     },
2283     /* Dot removal happens for unknown scheme types. */
2284     {   "zip://gov.uk/test/test2/../../.", 0, S_OK, FALSE,
2285         {
2286             {"zip://gov.uk/",S_OK,FALSE},
2287             {"gov.uk",S_OK,FALSE},
2288             {"zip://gov.uk/",S_OK,FALSE},
2289             {"",S_FALSE,FALSE},
2290             {"",S_FALSE,FALSE},
2291             {"",S_FALSE,FALSE},
2292             {"gov.uk",S_OK,FALSE},
2293             {"",S_FALSE,FALSE},
2294             {"/",S_OK,FALSE},
2295             {"/",S_OK,FALSE},
2296             {"",S_FALSE,FALSE},
2297             {"zip://gov.uk/test/test2/../../.",S_OK,FALSE},
2298             {"zip",S_OK,FALSE},
2299             {"",S_FALSE,FALSE},
2300             {"",S_FALSE,FALSE}
2301         },
2302         {
2303             {Uri_HOST_DNS,S_OK,FALSE},
2304             {0,S_FALSE,FALSE},
2305             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2306             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2307         }
2308     },
2309     /* Dot removal doesn't happen if NO_CANONICALIZE is set. */
2310     {   "http://gov.uk/test/test2/../../.", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
2311         {
2312             {"http://gov.uk/test/test2/../../.",S_OK,FALSE},
2313             {"gov.uk",S_OK,FALSE},
2314             {"http://gov.uk/test/test2/../../.",S_OK,FALSE},
2315             {"",S_FALSE,FALSE},
2316             {".",S_OK,FALSE},
2317             {"",S_FALSE,FALSE},
2318             {"gov.uk",S_OK,FALSE},
2319             {"",S_FALSE,FALSE},
2320             {"/test/test2/../../.",S_OK,FALSE},
2321             {"/test/test2/../../.",S_OK,FALSE},
2322             {"",S_FALSE,FALSE},
2323             {"http://gov.uk/test/test2/../../.",S_OK,FALSE},
2324             {"http",S_OK,FALSE},
2325             {"",S_FALSE,FALSE},
2326             {"",S_FALSE,FALSE}
2327         },
2328         {
2329             {Uri_HOST_DNS,S_OK,FALSE},
2330             {80,S_OK,FALSE},
2331             {URL_SCHEME_HTTP,S_OK,FALSE},
2332             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2333         }
2334     },
2335     /* Dot removal doesn't happen for wildcard scheme types. */
2336     {   "*:gov.uk/test/test2/../../.", 0, S_OK, FALSE,
2337         {
2338             {"*:gov.uk/test/test2/../../.",S_OK,FALSE},
2339             {"gov.uk",S_OK,FALSE},
2340             {"*:gov.uk/test/test2/../../.",S_OK,FALSE},
2341             {"",S_FALSE,FALSE},
2342             {".",S_OK,FALSE},
2343             {"",S_FALSE,FALSE},
2344             {"gov.uk",S_OK,FALSE},
2345             {"",S_FALSE,FALSE},
2346             {"/test/test2/../../.",S_OK,FALSE},
2347             {"/test/test2/../../.",S_OK,FALSE},
2348             {"",S_FALSE,FALSE},
2349             {"*:gov.uk/test/test2/../../.",S_OK,FALSE},
2350             {"*",S_OK,FALSE},
2351             {"",S_FALSE,FALSE},
2352             {"",S_FALSE,FALSE}
2353         },
2354         {
2355             {Uri_HOST_DNS,S_OK,FALSE},
2356             {0,S_FALSE,FALSE},
2357             {URL_SCHEME_WILDCARD,S_OK,FALSE},
2358             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2359         }
2360     },
2361     /* Forbidden characters are encoded for opaque known scheme types. */
2362     {   "mailto:\"acco<|>unt@example.com\"", 0, S_OK, FALSE,
2363         {
2364             {"mailto:%22acco%3C%7C%3Eunt@example.com%22",S_OK,FALSE},
2365             {"",S_FALSE,FALSE},
2366             {"mailto:%22acco%3C%7C%3Eunt@example.com%22",S_OK,FALSE},
2367             {"",S_FALSE,FALSE},
2368             {".com%22",S_OK,FALSE},
2369             {"",S_FALSE,FALSE},
2370             {"",S_FALSE,FALSE},
2371             {"",S_FALSE,FALSE},
2372             {"%22acco%3C%7C%3Eunt@example.com%22",S_OK,FALSE},
2373             {"%22acco%3C%7C%3Eunt@example.com%22",S_OK,FALSE},
2374             {"",S_FALSE,FALSE},
2375             {"mailto:\"acco<|>unt@example.com\"",S_OK,FALSE},
2376             {"mailto",S_OK,FALSE},
2377             {"",S_FALSE,FALSE},
2378             {"",S_FALSE,FALSE}
2379         },
2380         {
2381             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2382             {0,S_FALSE,FALSE},
2383             {URL_SCHEME_MAILTO,S_OK,FALSE},
2384             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2385         }
2386     },
2387     {   "news:test.tes<|>t.com", 0, S_OK, FALSE,
2388         {
2389             {"news:test.tes%3C%7C%3Et.com",S_OK,FALSE},
2390             {"",S_FALSE,FALSE},
2391             {"news:test.tes%3C%7C%3Et.com",S_OK,FALSE},
2392             {"",S_FALSE,FALSE},
2393             {".com",S_OK,FALSE},
2394             {"",S_FALSE,FALSE},
2395             {"",S_FALSE,FALSE},
2396             {"",S_FALSE,FALSE},
2397             {"test.tes%3C%7C%3Et.com",S_OK,FALSE},
2398             {"test.tes%3C%7C%3Et.com",S_OK,FALSE},
2399             {"",S_FALSE,FALSE},
2400             {"news:test.tes<|>t.com",S_OK,FALSE},
2401             {"news",S_OK,FALSE},
2402             {"",S_FALSE,FALSE},
2403             {"",S_FALSE,FALSE}
2404         },
2405         {
2406             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2407             {0,S_FALSE,FALSE},
2408             {URL_SCHEME_NEWS,S_OK,FALSE},
2409             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2410         }
2411     },
2412     /* Don't encode forbidden characters. */
2413     {   "news:test.tes<|>t.com", Uri_CREATE_NO_ENCODE_FORBIDDEN_CHARACTERS, S_OK, FALSE,
2414         {
2415             {"news:test.tes<|>t.com",S_OK,FALSE},
2416             {"",S_FALSE,FALSE},
2417             {"news:test.tes<|>t.com",S_OK,FALSE},
2418             {"",S_FALSE,FALSE},
2419             {".com",S_OK,FALSE},
2420             {"",S_FALSE,FALSE},
2421             {"",S_FALSE,FALSE},
2422             {"",S_FALSE,FALSE},
2423             {"test.tes<|>t.com",S_OK,FALSE},
2424             {"test.tes<|>t.com",S_OK,FALSE},
2425             {"",S_FALSE,FALSE},
2426             {"news:test.tes<|>t.com",S_OK,FALSE},
2427             {"news",S_OK,FALSE},
2428             {"",S_FALSE,FALSE},
2429             {"",S_FALSE,FALSE}
2430         },
2431         {
2432             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2433             {0,S_FALSE,FALSE},
2434             {URL_SCHEME_NEWS,S_OK,FALSE},
2435             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2436         }
2437     },
2438     /* Forbidden characters aren't encoded for unknown, opaque URIs. */
2439     {   "urn:test.tes<|>t.com", 0, S_OK, FALSE,
2440         {
2441             {"urn:test.tes<|>t.com",S_OK,FALSE},
2442             {"",S_FALSE,FALSE},
2443             {"urn:test.tes<|>t.com",S_OK,FALSE},
2444             {"",S_FALSE,FALSE},
2445             {".com",S_OK,FALSE},
2446             {"",S_FALSE,FALSE},
2447             {"",S_FALSE,FALSE},
2448             {"",S_FALSE,FALSE},
2449             {"test.tes<|>t.com",S_OK,FALSE},
2450             {"test.tes<|>t.com",S_OK,FALSE},
2451             {"",S_FALSE,FALSE},
2452             {"urn:test.tes<|>t.com",S_OK,FALSE},
2453             {"urn",S_OK,FALSE},
2454             {"",S_FALSE,FALSE},
2455             {"",S_FALSE,FALSE}
2456         },
2457         {
2458             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2459             {0,S_FALSE,FALSE},
2460             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2461             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2462         }
2463     },
2464     /* Percent encoded unreserved characters are decoded for known opaque URIs. */
2465     {   "news:test.%74%65%73%74.com", 0, S_OK, FALSE,
2466         {
2467             {"news:test.test.com",S_OK,FALSE},
2468             {"",S_FALSE,FALSE},
2469             {"news:test.test.com",S_OK,FALSE},
2470             {"",S_FALSE,FALSE},
2471             {".com",S_OK,FALSE},
2472             {"",S_FALSE,FALSE},
2473             {"",S_FALSE,FALSE},
2474             {"",S_FALSE,FALSE},
2475             {"test.test.com",S_OK,FALSE},
2476             {"test.test.com",S_OK,FALSE},
2477             {"",S_FALSE,FALSE},
2478             {"news:test.%74%65%73%74.com",S_OK,FALSE},
2479             {"news",S_OK,FALSE},
2480             {"",S_FALSE,FALSE},
2481             {"",S_FALSE,FALSE}
2482         },
2483         {
2484             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2485             {0,S_FALSE,FALSE},
2486             {URL_SCHEME_NEWS,S_OK,FALSE},
2487             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2488         }
2489     },
2490     /* Percent encoded characters are still decoded for known scheme types. */
2491     {   "news:test.%74%65%73%74.com", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
2492         {
2493             {"news:test.test.com",S_OK,FALSE},
2494             {"",S_FALSE,FALSE},
2495             {"news:test.test.com",S_OK,FALSE},
2496             {"",S_FALSE,FALSE},
2497             {".com",S_OK,FALSE},
2498             {"",S_FALSE,FALSE},
2499             {"",S_FALSE,FALSE},
2500             {"",S_FALSE,FALSE},
2501             {"test.test.com",S_OK,FALSE},
2502             {"test.test.com",S_OK,FALSE},
2503             {"",S_FALSE,FALSE},
2504             {"news:test.%74%65%73%74.com",S_OK,FALSE},
2505             {"news",S_OK,FALSE},
2506             {"",S_FALSE,FALSE},
2507             {"",S_FALSE,FALSE}
2508         },
2509         {
2510             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2511             {0,S_FALSE,FALSE},
2512             {URL_SCHEME_NEWS,S_OK,FALSE},
2513             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2514         }
2515     },
2516     /* Percent encoded characters aren't decoded for unknown scheme types. */
2517     {   "urn:test.%74%65%73%74.com", 0, S_OK, FALSE,
2518         {
2519             {"urn:test.%74%65%73%74.com",S_OK,FALSE},
2520             {"",S_FALSE,FALSE},
2521             {"urn:test.%74%65%73%74.com",S_OK,FALSE},
2522             {"",S_FALSE,FALSE},
2523             {".com",S_OK,FALSE},
2524             {"",S_FALSE,FALSE},
2525             {"",S_FALSE,FALSE},
2526             {"",S_FALSE,FALSE},
2527             {"test.%74%65%73%74.com",S_OK,FALSE},
2528             {"test.%74%65%73%74.com",S_OK,FALSE},
2529             {"",S_FALSE,FALSE},
2530             {"urn:test.%74%65%73%74.com",S_OK,FALSE},
2531             {"urn",S_OK,FALSE},
2532             {"",S_FALSE,FALSE},
2533             {"",S_FALSE,FALSE}
2534         },
2535         {
2536             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2537             {0,S_FALSE,FALSE},
2538             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2539             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2540         }
2541     },
2542     /* Unknown scheme types can have invalid % encoded data in query string. */
2543     {   "zip://www.winehq.org/tests/..?query=%xx&return=y", 0, S_OK, FALSE,
2544         {
2545             {"zip://www.winehq.org/?query=%xx&return=y",S_OK,FALSE},
2546             {"www.winehq.org",S_OK,FALSE},
2547             {"zip://www.winehq.org/?query=%xx&return=y",S_OK,FALSE},
2548             {"winehq.org",S_OK,FALSE},
2549             {"",S_FALSE,FALSE},
2550             {"",S_FALSE,FALSE},
2551             {"www.winehq.org",S_OK,FALSE},
2552             {"",S_FALSE,FALSE},
2553             {"/",S_OK,FALSE},
2554             {"/?query=%xx&return=y",S_OK,FALSE},
2555             {"?query=%xx&return=y",S_OK,FALSE},
2556             {"zip://www.winehq.org/tests/..?query=%xx&return=y",S_OK,FALSE},
2557             {"zip",S_OK,FALSE},
2558             {"",S_FALSE,FALSE},
2559             {"",S_FALSE,FALSE}
2560         },
2561         {
2562             {Uri_HOST_DNS,S_OK,FALSE},
2563             {0,S_FALSE,FALSE},
2564             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2565             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2566         }
2567     },
2568     /* Known scheme types can have invalid % encoded data with the right flags. */
2569     {   "http://www.winehq.org/tests/..?query=%xx&return=y", Uri_CREATE_NO_DECODE_EXTRA_INFO, S_OK, FALSE,
2570         {
2571             {"http://www.winehq.org/?query=%xx&return=y",S_OK,FALSE},
2572             {"www.winehq.org",S_OK,FALSE},
2573             {"http://www.winehq.org/?query=%xx&return=y",S_OK,FALSE},
2574             {"winehq.org",S_OK,FALSE},
2575             {"",S_FALSE,FALSE},
2576             {"",S_FALSE,FALSE},
2577             {"www.winehq.org",S_OK,FALSE},
2578             {"",S_FALSE,FALSE},
2579             {"/",S_OK,FALSE},
2580             {"/?query=%xx&return=y",S_OK,FALSE},
2581             {"?query=%xx&return=y",S_OK,FALSE},
2582             {"http://www.winehq.org/tests/..?query=%xx&return=y",S_OK,FALSE},
2583             {"http",S_OK,FALSE},
2584             {"",S_FALSE,FALSE},
2585             {"",S_FALSE,FALSE}
2586         },
2587         {
2588             {Uri_HOST_DNS,S_OK,FALSE},
2589             {80,S_OK,FALSE},
2590             {URL_SCHEME_HTTP,S_OK,FALSE},
2591             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2592         }
2593     },
2594     /* Forbidden characters in query aren't percent encoded for known scheme types with this flag. */
2595     {   "http://www.winehq.org/tests/..?query=<|>&return=y", Uri_CREATE_NO_DECODE_EXTRA_INFO, S_OK, FALSE,
2596         {
2597             {"http://www.winehq.org/?query=<|>&return=y",S_OK,FALSE},
2598             {"www.winehq.org",S_OK,FALSE},
2599             {"http://www.winehq.org/?query=<|>&return=y",S_OK,FALSE},
2600             {"winehq.org",S_OK,FALSE},
2601             {"",S_FALSE,FALSE},
2602             {"",S_FALSE,FALSE},
2603             {"www.winehq.org",S_OK,FALSE},
2604             {"",S_FALSE,FALSE},
2605             {"/",S_OK,FALSE},
2606             {"/?query=<|>&return=y",S_OK,FALSE},
2607             {"?query=<|>&return=y",S_OK,FALSE},
2608             {"http://www.winehq.org/tests/..?query=<|>&return=y",S_OK,FALSE},
2609             {"http",S_OK,FALSE},
2610             {"",S_FALSE,FALSE},
2611             {"",S_FALSE,FALSE}
2612         },
2613         {
2614             {Uri_HOST_DNS,S_OK,FALSE},
2615             {80,S_OK,FALSE},
2616             {URL_SCHEME_HTTP,S_OK,FALSE},
2617             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2618         }
2619     },
2620     /* Forbidden characters in query aren't percent encoded for known scheme types with this flag. */
2621     {   "http://www.winehq.org/tests/..?query=<|>&return=y", Uri_CREATE_NO_ENCODE_FORBIDDEN_CHARACTERS, S_OK, FALSE,
2622         {
2623             {"http://www.winehq.org/?query=<|>&return=y",S_OK,FALSE},
2624             {"www.winehq.org",S_OK,FALSE},
2625             {"http://www.winehq.org/?query=<|>&return=y",S_OK,FALSE},
2626             {"winehq.org",S_OK,FALSE},
2627             {"",S_FALSE,FALSE},
2628             {"",S_FALSE,FALSE},
2629             {"www.winehq.org",S_OK,FALSE},
2630             {"",S_FALSE,FALSE},
2631             {"/",S_OK,FALSE},
2632             {"/?query=<|>&return=y",S_OK,FALSE},
2633             {"?query=<|>&return=y",S_OK,FALSE},
2634             {"http://www.winehq.org/tests/..?query=<|>&return=y",S_OK,FALSE},
2635             {"http",S_OK,FALSE},
2636             {"",S_FALSE,FALSE},
2637             {"",S_FALSE,FALSE}
2638         },
2639         {
2640             {Uri_HOST_DNS,S_OK,FALSE},
2641             {80,S_OK,FALSE},
2642             {URL_SCHEME_HTTP,S_OK,FALSE},
2643             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2644         }
2645     },
2646     /* Forbidden characters are encoded for known scheme types. */
2647     {   "http://www.winehq.org/tests/..?query=<|>&return=y", 0, S_OK, FALSE,
2648         {
2649             {"http://www.winehq.org/?query=%3C%7C%3E&return=y",S_OK,FALSE},
2650             {"www.winehq.org",S_OK,FALSE},
2651             {"http://www.winehq.org/?query=%3C%7C%3E&return=y",S_OK,FALSE},
2652             {"winehq.org",S_OK,FALSE},
2653             {"",S_FALSE,FALSE},
2654             {"",S_FALSE,FALSE},
2655             {"www.winehq.org",S_OK,FALSE},
2656             {"",S_FALSE,FALSE},
2657             {"/",S_OK,FALSE},
2658             {"/?query=%3C%7C%3E&return=y",S_OK,FALSE},
2659             {"?query=%3C%7C%3E&return=y",S_OK,FALSE},
2660             {"http://www.winehq.org/tests/..?query=<|>&return=y",S_OK,FALSE},
2661             {"http",S_OK,FALSE},
2662             {"",S_FALSE,FALSE},
2663             {"",S_FALSE,FALSE}
2664         },
2665         {
2666             {Uri_HOST_DNS,S_OK,FALSE},
2667             {80,S_OK,FALSE},
2668             {URL_SCHEME_HTTP,S_OK,FALSE},
2669             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2670         }
2671     },
2672     /* Forbidden characters are not encoded for unknown scheme types. */
2673     {   "zip://www.winehq.org/tests/..?query=<|>&return=y", 0, S_OK, FALSE,
2674         {
2675             {"zip://www.winehq.org/?query=<|>&return=y",S_OK,FALSE},
2676             {"www.winehq.org",S_OK,FALSE},
2677             {"zip://www.winehq.org/?query=<|>&return=y",S_OK,FALSE},
2678             {"winehq.org",S_OK,FALSE},
2679             {"",S_FALSE,FALSE},
2680             {"",S_FALSE,FALSE},
2681             {"www.winehq.org",S_OK,FALSE},
2682             {"",S_FALSE,FALSE},
2683             {"/",S_OK,FALSE},
2684             {"/?query=<|>&return=y",S_OK,FALSE},
2685             {"?query=<|>&return=y",S_OK,FALSE},
2686             {"zip://www.winehq.org/tests/..?query=<|>&return=y",S_OK,FALSE},
2687             {"zip",S_OK,FALSE},
2688             {"",S_FALSE,FALSE},
2689             {"",S_FALSE,FALSE}
2690         },
2691         {
2692             {Uri_HOST_DNS,S_OK,FALSE},
2693             {0,S_FALSE,FALSE},
2694             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2695             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2696         }
2697     },
2698     /* Percent encoded, unreserved characters are decoded for known scheme types. */
2699     {   "http://www.winehq.org/tests/..?query=%30%31&return=y", 0, S_OK, FALSE,
2700         {
2701             {"http://www.winehq.org/?query=01&return=y",S_OK,FALSE},
2702             {"www.winehq.org",S_OK,FALSE},
2703             {"http://www.winehq.org/?query=01&return=y",S_OK,FALSE},
2704             {"winehq.org",S_OK,FALSE},
2705             {"",S_FALSE,FALSE},
2706             {"",S_FALSE,FALSE},
2707             {"www.winehq.org",S_OK,FALSE},
2708             {"",S_FALSE,FALSE},
2709             {"/",S_OK,FALSE},
2710             {"/?query=01&return=y",S_OK,FALSE},
2711             {"?query=01&return=y",S_OK,FALSE},
2712             {"http://www.winehq.org/tests/..?query=%30%31&return=y",S_OK,FALSE},
2713             {"http",S_OK,FALSE},
2714             {"",S_FALSE,FALSE},
2715             {"",S_FALSE,FALSE}
2716         },
2717         {
2718             {Uri_HOST_DNS,S_OK,FALSE},
2719             {80,S_OK,FALSE},
2720             {URL_SCHEME_HTTP,S_OK,FALSE},
2721             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2722         }
2723     },
2724     /* Percent encoded, unreserved characters aren't decoded for unknown scheme types. */
2725     {   "zip://www.winehq.org/tests/..?query=%30%31&return=y", 0, S_OK, FALSE,
2726         {
2727             {"zip://www.winehq.org/?query=%30%31&return=y",S_OK,FALSE},
2728             {"www.winehq.org",S_OK,FALSE},
2729             {"zip://www.winehq.org/?query=%30%31&return=y",S_OK,FALSE},
2730             {"winehq.org",S_OK,FALSE},
2731             {"",S_FALSE,FALSE},
2732             {"",S_FALSE,FALSE},
2733             {"www.winehq.org",S_OK,FALSE},
2734             {"",S_FALSE,FALSE},
2735             {"/",S_OK,FALSE},
2736             {"/?query=%30%31&return=y",S_OK,FALSE},
2737             {"?query=%30%31&return=y",S_OK,FALSE},
2738             {"zip://www.winehq.org/tests/..?query=%30%31&return=y",S_OK,FALSE},
2739             {"zip",S_OK,FALSE},
2740             {"",S_FALSE,FALSE},
2741             {"",S_FALSE,FALSE}
2742         },
2743         {
2744             {Uri_HOST_DNS,S_OK,FALSE},
2745             {0,S_FALSE,FALSE},
2746             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2747             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2748         }
2749     },
2750     /* Percent encoded characters aren't decoded when NO_DECODE_EXTRA_INFO is set. */
2751     {   "http://www.winehq.org/tests/..?query=%30%31&return=y", Uri_CREATE_NO_DECODE_EXTRA_INFO, S_OK, FALSE,
2752         {
2753             {"http://www.winehq.org/?query=%30%31&return=y",S_OK,FALSE},
2754             {"www.winehq.org",S_OK,FALSE},
2755             {"http://www.winehq.org/?query=%30%31&return=y",S_OK,FALSE},
2756             {"winehq.org",S_OK,FALSE},
2757             {"",S_FALSE,FALSE},
2758             {"",S_FALSE,FALSE},
2759             {"www.winehq.org",S_OK,FALSE},
2760             {"",S_FALSE,FALSE},
2761             {"/",S_OK,FALSE},
2762             {"/?query=%30%31&return=y",S_OK,FALSE},
2763             {"?query=%30%31&return=y",S_OK,FALSE},
2764             {"http://www.winehq.org/tests/..?query=%30%31&return=y",S_OK,FALSE},
2765             {"http",S_OK,FALSE},
2766             {"",S_FALSE,FALSE},
2767             {"",S_FALSE,FALSE}
2768         },
2769         {
2770             {Uri_HOST_DNS,S_OK,FALSE},
2771             {80,S_OK,FALSE},
2772             {URL_SCHEME_HTTP,S_OK,FALSE},
2773             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2774         }
2775     },
2776     {   "http://www.winehq.org?query=12&return=y", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
2777         {
2778             {"http://www.winehq.org?query=12&return=y",S_OK,FALSE},
2779             {"www.winehq.org",S_OK,FALSE},
2780             {"http://www.winehq.org?query=12&return=y",S_OK,FALSE},
2781             {"winehq.org",S_OK,FALSE},
2782             {"",S_FALSE,FALSE},
2783             {"",S_FALSE,FALSE},
2784             {"www.winehq.org",S_OK,FALSE},
2785             {"",S_FALSE,FALSE},
2786             {"",S_FALSE,FALSE},
2787             {"?query=12&return=y",S_OK,FALSE},
2788             {"?query=12&return=y",S_OK,FALSE},
2789             {"http://www.winehq.org?query=12&return=y",S_OK,FALSE},
2790             {"http",S_OK,FALSE},
2791             {"",S_FALSE,FALSE},
2792             {"",S_FALSE,FALSE}
2793         },
2794         {
2795             {Uri_HOST_DNS,S_OK,FALSE},
2796             {80,S_OK,FALSE},
2797             {URL_SCHEME_HTTP,S_OK,FALSE},
2798             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2799         }
2800     },
2801     /* Unknown scheme types can have invalid % encoded data in fragments. */
2802     {   "zip://www.winehq.org/tests/#Te%xx", 0, S_OK, FALSE,
2803         {
2804             {"zip://www.winehq.org/tests/#Te%xx",S_OK,FALSE},
2805             {"www.winehq.org",S_OK,FALSE},
2806             {"zip://www.winehq.org/tests/#Te%xx",S_OK,FALSE},
2807             {"winehq.org",S_OK,FALSE},
2808             {"",S_FALSE,FALSE},
2809             {"#Te%xx",S_OK,FALSE},
2810             {"www.winehq.org",S_OK,FALSE},
2811             {"",S_FALSE,FALSE},
2812             {"/tests/",S_OK,FALSE},
2813             {"/tests/",S_OK,FALSE},
2814             {"",S_FALSE,FALSE},
2815             {"zip://www.winehq.org/tests/#Te%xx",S_OK,FALSE},
2816             {"zip",S_OK,FALSE},
2817             {"",S_FALSE,FALSE},
2818             {"",S_FALSE,FALSE}
2819         },
2820         {
2821             {Uri_HOST_DNS,S_OK,FALSE},
2822             {0,S_FALSE,FALSE},
2823             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2824             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2825         }
2826     },
2827     /* Forbidden characters in fragment aren't encoded for unknown schemes. */
2828     {   "zip://www.winehq.org/tests/#Te<|>", 0, S_OK, FALSE,
2829         {
2830             {"zip://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
2831             {"www.winehq.org",S_OK,FALSE},
2832             {"zip://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
2833             {"winehq.org",S_OK,FALSE},
2834             {"",S_FALSE,FALSE},
2835             {"#Te<|>",S_OK,FALSE},
2836             {"www.winehq.org",S_OK,FALSE},
2837             {"",S_FALSE,FALSE},
2838             {"/tests/",S_OK,FALSE},
2839             {"/tests/",S_OK,FALSE},
2840             {"",S_FALSE,FALSE},
2841             {"zip://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
2842             {"zip",S_OK,FALSE},
2843             {"",S_FALSE,FALSE},
2844             {"",S_FALSE,FALSE}
2845         },
2846         {
2847             {Uri_HOST_DNS,S_OK,FALSE},
2848             {0,S_FALSE,FALSE},
2849             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2850             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2851         }
2852     },
2853     /* Forbidden characters in the fragment are percent encoded for known schemes. */
2854     {   "http://www.winehq.org/tests/#Te<|>", 0, S_OK, FALSE,
2855         {
2856             {"http://www.winehq.org/tests/#Te%3C%7C%3E",S_OK,FALSE},
2857             {"www.winehq.org",S_OK,FALSE},
2858             {"http://www.winehq.org/tests/#Te%3C%7C%3E",S_OK,FALSE},
2859             {"winehq.org",S_OK,FALSE},
2860             {"",S_FALSE,FALSE},
2861             {"#Te%3C%7C%3E",S_OK,FALSE},
2862             {"www.winehq.org",S_OK,FALSE},
2863             {"",S_FALSE,FALSE},
2864             {"/tests/",S_OK,FALSE},
2865             {"/tests/",S_OK,FALSE},
2866             {"",S_FALSE,FALSE},
2867             {"http://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
2868             {"http",S_OK,FALSE},
2869             {"",S_FALSE,FALSE},
2870             {"",S_FALSE,FALSE}
2871         },
2872         {
2873             {Uri_HOST_DNS,S_OK,FALSE},
2874             {80,S_OK,FALSE},
2875             {URL_SCHEME_HTTP,S_OK,FALSE},
2876             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2877         }
2878     },
2879     /* Forbidden characters aren't encoded in the fragment with this flag. */
2880     {   "http://www.winehq.org/tests/#Te<|>", Uri_CREATE_NO_DECODE_EXTRA_INFO, S_OK, FALSE,
2881         {
2882             {"http://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
2883             {"www.winehq.org",S_OK,FALSE},
2884             {"http://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
2885             {"winehq.org",S_OK,FALSE},
2886             {"",S_FALSE,FALSE},
2887             {"#Te<|>",S_OK,FALSE},
2888             {"www.winehq.org",S_OK,FALSE},
2889             {"",S_FALSE,FALSE},
2890             {"/tests/",S_OK,FALSE},
2891             {"/tests/",S_OK,FALSE},
2892             {"",S_FALSE,FALSE},
2893             {"http://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
2894             {"http",S_OK,FALSE},
2895             {"",S_FALSE,FALSE},
2896             {"",S_FALSE,FALSE}
2897         },
2898         {
2899             {Uri_HOST_DNS,S_OK,FALSE},
2900             {80,S_OK,FALSE},
2901             {URL_SCHEME_HTTP,S_OK,FALSE},
2902             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2903         }
2904     },
2905     /* Forbidden characters aren't encoded in the fragment with this flag. */
2906     {   "http://www.winehq.org/tests/#Te<|>", Uri_CREATE_NO_ENCODE_FORBIDDEN_CHARACTERS, S_OK, FALSE,
2907         {
2908             {"http://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
2909             {"www.winehq.org",S_OK,FALSE},
2910             {"http://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
2911             {"winehq.org",S_OK,FALSE},
2912             {"",S_FALSE,FALSE},
2913             {"#Te<|>",S_OK,FALSE},
2914             {"www.winehq.org",S_OK,FALSE},
2915             {"",S_FALSE,FALSE},
2916             {"/tests/",S_OK,FALSE},
2917             {"/tests/",S_OK,FALSE},
2918             {"",S_FALSE,FALSE},
2919             {"http://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
2920             {"http",S_OK,FALSE},
2921             {"",S_FALSE,FALSE},
2922             {"",S_FALSE,FALSE}
2923         },
2924         {
2925             {Uri_HOST_DNS,S_OK,FALSE},
2926             {80,S_OK,FALSE},
2927             {URL_SCHEME_HTTP,S_OK,FALSE},
2928             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2929         }
2930     },
2931     /* Percent encoded, unreserved characters aren't decoded for known scheme types. */
2932     {   "zip://www.winehq.org/tests/#Te%30%31%32", 0, S_OK, FALSE,
2933         {
2934             {"zip://www.winehq.org/tests/#Te%30%31%32",S_OK,FALSE},
2935             {"www.winehq.org",S_OK,FALSE},
2936             {"zip://www.winehq.org/tests/#Te%30%31%32",S_OK,FALSE},
2937             {"winehq.org",S_OK,FALSE},
2938             {"",S_FALSE,FALSE},
2939             {"#Te%30%31%32",S_OK,FALSE},
2940             {"www.winehq.org",S_OK,FALSE},
2941             {"",S_FALSE,FALSE},
2942             {"/tests/",S_OK,FALSE},
2943             {"/tests/",S_OK,FALSE},
2944             {"",S_FALSE,FALSE},
2945             {"zip://www.winehq.org/tests/#Te%30%31%32",S_OK,FALSE},
2946             {"zip",S_OK,FALSE},
2947             {"",S_FALSE,FALSE},
2948             {"",S_FALSE,FALSE}
2949         },
2950         {
2951             {Uri_HOST_DNS,S_OK,FALSE},
2952             {0,S_FALSE,FALSE},
2953             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2954             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2955         }
2956     },
2957     /* Percent encoded, unreserved characters are decoded for known schemes. */
2958     {   "http://www.winehq.org/tests/#Te%30%31%32", 0, S_OK, FALSE,
2959         {
2960             {"http://www.winehq.org/tests/#Te012",S_OK,FALSE},
2961             {"www.winehq.org",S_OK,FALSE},
2962             {"http://www.winehq.org/tests/#Te012",S_OK,FALSE},
2963             {"winehq.org",S_OK,FALSE},
2964             {"",S_FALSE,FALSE},
2965             {"#Te012",S_OK,FALSE},
2966             {"www.winehq.org",S_OK,FALSE},
2967             {"",S_FALSE,FALSE},
2968             {"/tests/",S_OK,FALSE},
2969             {"/tests/",S_OK,FALSE},
2970             {"",S_FALSE,FALSE},
2971             {"http://www.winehq.org/tests/#Te%30%31%32",S_OK,FALSE},
2972             {"http",S_OK,FALSE},
2973             {"",S_FALSE,FALSE},
2974             {"",S_FALSE,FALSE}
2975         },
2976         {
2977             {Uri_HOST_DNS,S_OK,FALSE},
2978             {80,S_OK,FALSE},
2979             {URL_SCHEME_HTTP,S_OK,FALSE},
2980             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2981         }
2982     },
2983     /* Percent encoded, unreserved characters are decoded even if NO_CANONICALIZE is set. */
2984     {   "http://www.winehq.org/tests/#Te%30%31%32", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
2985         {
2986             {"http://www.winehq.org/tests/#Te012",S_OK,FALSE},
2987             {"www.winehq.org",S_OK,FALSE},
2988             {"http://www.winehq.org/tests/#Te012",S_OK,FALSE},
2989             {"winehq.org",S_OK,FALSE},
2990             {"",S_FALSE,FALSE},
2991             {"#Te012",S_OK,FALSE},
2992             {"www.winehq.org",S_OK,FALSE},
2993             {"",S_FALSE,FALSE},
2994             {"/tests/",S_OK,FALSE},
2995             {"/tests/",S_OK,FALSE},
2996             {"",S_FALSE,FALSE},
2997             {"http://www.winehq.org/tests/#Te%30%31%32",S_OK,FALSE},
2998             {"http",S_OK,FALSE},
2999             {"",S_FALSE,FALSE},
3000             {"",S_FALSE,FALSE}
3001         },
3002         {
3003             {Uri_HOST_DNS,S_OK,FALSE},
3004             {80,S_OK,FALSE},
3005             {URL_SCHEME_HTTP,S_OK,FALSE},
3006             {URLZONE_INVALID,E_NOTIMPL,FALSE},
3007         }
3008     },
3009     /* Percent encoded, unreserved characters aren't decoded when NO_DECODE_EXTRA is set. */
3010     {   "http://www.winehq.org/tests/#Te%30%31%32", Uri_CREATE_NO_DECODE_EXTRA_INFO, S_OK, FALSE,
3011         {
3012             {"http://www.winehq.org/tests/#Te%30%31%32",S_OK,FALSE},
3013             {"www.winehq.org",S_OK,FALSE},
3014             {"http://www.winehq.org/tests/#Te%30%31%32",S_OK,FALSE},
3015             {"winehq.org",S_OK,FALSE},
3016             {"",S_FALSE,FALSE},
3017             {"#Te%30%31%32",S_OK,FALSE},
3018             {"www.winehq.org",S_OK,FALSE},
3019             {"",S_FALSE,FALSE},
3020             {"/tests/",S_OK,FALSE},
3021             {"/tests/",S_OK,FALSE},
3022             {"",S_FALSE,FALSE},
3023             {"http://www.winehq.org/tests/#Te%30%31%32",S_OK,FALSE},
3024             {"http",S_OK,FALSE},
3025             {"",S_FALSE,FALSE},
3026             {"",S_FALSE,FALSE}
3027         },
3028         {
3029             {Uri_HOST_DNS,S_OK,FALSE},
3030             {80,S_OK,FALSE},
3031             {URL_SCHEME_HTTP,S_OK,FALSE},
3032             {URLZONE_INVALID,E_NOTIMPL,FALSE},
3033         }
3034     },
3035     /* Leading/Trailing whitespace is removed. */
3036     {   "    http://google.com/     ", 0, S_OK, FALSE,
3037         {
3038             {"http://google.com/",S_OK,FALSE},
3039             {"google.com",S_OK,FALSE},
3040             {"http://google.com/",S_OK,FALSE},
3041             {"google.com",S_OK,FALSE},
3042             {"",S_FALSE,FALSE},
3043             {"",S_FALSE,FALSE},
3044             {"google.com",S_OK,FALSE},
3045             {"",S_FALSE,FALSE},
3046             {"/",S_OK,FALSE},
3047             {"/",S_OK,FALSE},
3048             {"",S_FALSE,FALSE},
3049             {"http://google.com/",S_OK,FALSE},
3050             {"http",S_OK,FALSE},
3051             {"",S_FALSE,FALSE},
3052             {"",S_FALSE,FALSE}
3053         },
3054         {
3055             {Uri_HOST_DNS,S_OK,FALSE},
3056             {80,S_OK,FALSE},
3057             {URL_SCHEME_HTTP,S_OK,FALSE},
3058             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3059         }
3060     },
3061     {   "\t\t\r\nhttp\n://g\noogle.co\rm/\n\n\n", 0, S_OK, FALSE,
3062         {
3063             {"http://google.com/",S_OK,FALSE},
3064             {"google.com",S_OK,FALSE},
3065             {"http://google.com/",S_OK,FALSE},
3066             {"google.com",S_OK,FALSE},
3067             {"",S_FALSE,FALSE},
3068             {"",S_FALSE,FALSE},
3069             {"google.com",S_OK,FALSE},
3070             {"",S_FALSE,FALSE},
3071             {"/",S_OK,FALSE},
3072             {"/",S_OK,FALSE},
3073             {"",S_FALSE,FALSE},
3074             {"http://google.com/",S_OK,FALSE},
3075             {"http",S_OK,FALSE},
3076             {"",S_FALSE,FALSE},
3077             {"",S_FALSE,FALSE}
3078         },
3079         {
3080             {Uri_HOST_DNS,S_OK,FALSE},
3081             {80,S_OK,FALSE},
3082             {URL_SCHEME_HTTP,S_OK,FALSE},
3083             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3084         }
3085     },
3086     {   "http://g\noogle.co\rm/\n\n\n", Uri_CREATE_NO_PRE_PROCESS_HTML_URI, S_OK, FALSE,
3087         {
3088             {"http://g%0aoogle.co%0dm/%0A%0A%0A",S_OK,FALSE},
3089             {"g%0aoogle.co%0dm",S_OK,FALSE},
3090             {"http://g%0aoogle.co%0dm/%0A%0A%0A",S_OK,FALSE},
3091             {"g%0aoogle.co%0dm",S_OK,FALSE},
3092             {"",S_FALSE,FALSE},
3093             {"",S_FALSE,FALSE},
3094             {"g%0aoogle.co%0dm",S_OK,FALSE},
3095             {"",S_FALSE,FALSE},
3096             {"/%0A%0A%0A",S_OK,FALSE},
3097             {"/%0A%0A%0A",S_OK,FALSE},
3098             {"",S_FALSE,FALSE},
3099             {"http://g\noogle.co\rm/\n\n\n",S_OK,FALSE},
3100             {"http",S_OK,FALSE},
3101             {"",S_FALSE,FALSE},
3102             {"",S_FALSE,FALSE}
3103         },
3104         {
3105             {Uri_HOST_DNS,S_OK,FALSE},
3106             {80,S_OK,FALSE},
3107             {URL_SCHEME_HTTP,S_OK,FALSE},
3108             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3109         }
3110     },
3111     {   "zip://g\noogle.co\rm/\n\n\n", Uri_CREATE_NO_PRE_PROCESS_HTML_URI, S_OK, FALSE,
3112         {
3113             {"zip://g\noogle.co\rm/\n\n\n",S_OK,FALSE},
3114             {"g\noogle.co\rm",S_OK,FALSE},
3115             {"zip://g\noogle.co\rm/\n\n\n",S_OK,FALSE},
3116             {"g\noogle.co\rm",S_OK,FALSE},
3117             {"",S_FALSE,FALSE},
3118             {"",S_FALSE,FALSE},
3119             {"g\noogle.co\rm",S_OK,FALSE},
3120             {"",S_FALSE,FALSE},
3121             {"/\n\n\n",S_OK,FALSE},
3122             {"/\n\n\n",S_OK,FALSE},
3123             {"",S_FALSE,FALSE},
3124             {"zip://g\noogle.co\rm/\n\n\n",S_OK,FALSE},
3125             {"zip",S_OK,FALSE},
3126             {"",S_FALSE,FALSE},
3127             {"",S_FALSE,FALSE}
3128         },
3129         {
3130             {Uri_HOST_DNS,S_OK,FALSE},
3131             {0,S_FALSE,FALSE},
3132             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
3133             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3134         }
3135     },
3136     /* Since file URLs are usually hierarchical, it returns an empty string
3137      * for the absolute URI property since it was declared as an opaque URI.
3138      */
3139     {   "file:index.html", 0, S_OK, FALSE,
3140         {
3141             {"",S_FALSE,FALSE},
3142             {"",S_FALSE,FALSE},
3143             {"file:index.html",S_OK,FALSE},
3144             {"",S_FALSE,FALSE},
3145             {".html",S_OK,FALSE},
3146             {"",S_FALSE,FALSE},
3147             {"",S_FALSE,FALSE},
3148             {"",S_FALSE,FALSE},
3149             {"index.html",S_OK,FALSE},
3150             {"index.html",S_OK,FALSE},
3151             {"",S_FALSE,FALSE},
3152             {"file:index.html",S_OK,FALSE},
3153             {"file",S_OK,FALSE},
3154             {"",S_FALSE,FALSE},
3155             {"",S_FALSE,FALSE}
3156         },
3157         {
3158             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3159             {0,S_FALSE,FALSE},
3160             {URL_SCHEME_FILE,S_OK,FALSE},
3161             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3162         }
3163     },
3164     /* Doesn't have an absolute since it's opaque, but gets it port set. */
3165     {   "http:test.com/index.html", 0, S_OK, FALSE,
3166         {
3167             {"",S_FALSE,FALSE},
3168             {"",S_FALSE,FALSE},
3169             {"http:test.com/index.html",S_OK,FALSE},
3170             {"",S_FALSE,FALSE},
3171             {".html",S_OK,FALSE},
3172             {"",S_FALSE,FALSE},
3173             {"",S_FALSE,FALSE},
3174             {"",S_FALSE,FALSE},
3175             {"test.com/index.html",S_OK,FALSE},
3176             {"test.com/index.html",S_OK,FALSE},
3177             {"",S_FALSE,FALSE},
3178             {"http:test.com/index.html",S_OK,FALSE},
3179             {"http",S_OK,FALSE},
3180             {"",S_FALSE,FALSE},
3181             {"",S_FALSE,FALSE}
3182         },
3183         {
3184             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3185             {80,S_OK,FALSE},
3186             {URL_SCHEME_HTTP,S_OK,FALSE},
3187             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3188         }
3189     },
3190     {   "ftp:test.com/index.html", 0, S_OK, FALSE,
3191         {
3192             {"",S_FALSE,FALSE},
3193             {"",S_FALSE,FALSE},
3194             {"ftp:test.com/index.html",S_OK,FALSE},
3195             {"",S_FALSE,FALSE},
3196             {".html",S_OK,FALSE},
3197             {"",S_FALSE,FALSE},
3198             {"",S_FALSE,FALSE},
3199             {"",S_FALSE,FALSE},
3200             {"test.com/index.html",S_OK,FALSE},
3201             {"test.com/index.html",S_OK,FALSE},
3202             {"",S_FALSE,FALSE},
3203             {"ftp:test.com/index.html",S_OK,FALSE},
3204             {"ftp",S_OK,FALSE},
3205             {"",S_FALSE,FALSE},
3206             {"",S_FALSE,FALSE}
3207         },
3208         {
3209             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3210             {21,S_OK,FALSE},
3211             {URL_SCHEME_FTP,S_OK,FALSE},
3212             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3213         }
3214     },
3215     {   "file://C|/test.mp3", 0, S_OK, FALSE,
3216         {
3217             {"file:///C:/test.mp3",S_OK,FALSE},
3218             {"",S_FALSE,FALSE},
3219             {"file:///C:/test.mp3",S_OK,FALSE},
3220             {"",S_FALSE,FALSE},
3221             {".mp3",S_OK,FALSE},
3222             {"",S_FALSE,FALSE},
3223             {"",S_FALSE,FALSE},
3224             {"",S_FALSE,FALSE},
3225             {"/C:/test.mp3",S_OK,FALSE},
3226             {"/C:/test.mp3",S_OK,FALSE},
3227             {"",S_FALSE,FALSE},
3228             {"file://C|/test.mp3",S_OK,FALSE},
3229             {"file",S_OK,FALSE},
3230             {"",S_FALSE,FALSE},
3231             {"",S_FALSE,FALSE}
3232         },
3233         {
3234             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3235             {0,S_FALSE,FALSE},
3236             {URL_SCHEME_FILE,S_OK,FALSE},
3237             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3238         }
3239     },
3240     {   "file:///C|/test.mp3", 0, S_OK, FALSE,
3241         {
3242             {"file:///C:/test.mp3",S_OK,FALSE},
3243             {"",S_FALSE,FALSE},
3244             {"file:///C:/test.mp3",S_OK,FALSE},
3245             {"",S_FALSE,FALSE},
3246             {".mp3",S_OK,FALSE},
3247             {"",S_FALSE,FALSE},
3248             {"",S_FALSE,FALSE},
3249             {"",S_FALSE,FALSE},
3250             {"/C:/test.mp3",S_OK,FALSE},
3251             {"/C:/test.mp3",S_OK,FALSE},
3252             {"",S_FALSE,FALSE},
3253             {"file:///C|/test.mp3",S_OK,FALSE},
3254             {"file",S_OK,FALSE},
3255             {"",S_FALSE,FALSE},
3256             {"",S_FALSE,FALSE}
3257         },
3258         {
3259             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3260             {0,S_FALSE,FALSE},
3261             {URL_SCHEME_FILE,S_OK,FALSE},
3262             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3263         }
3264     },
3265     /* Extra '/' isn't added before "c:" since USE_DOS_PATH is set and '/' are converted
3266      * to '\\'.
3267      */
3268     {   "file://c:/dir/index.html", Uri_CREATE_FILE_USE_DOS_PATH, S_OK, FALSE,
3269         {
3270             {"file://c:\\dir\\index.html",S_OK,FALSE},
3271             {"",S_FALSE,FALSE},
3272             {"file://c:\\dir\\index.html",S_OK,FALSE},
3273             {"",S_FALSE,FALSE},
3274             {".html",S_OK,FALSE},
3275             {"",S_FALSE,FALSE},
3276             {"",S_FALSE,FALSE},
3277             {"",S_FALSE,FALSE},
3278             {"c:\\dir\\index.html",S_OK,FALSE},
3279             {"c:\\dir\\index.html",S_OK,FALSE},
3280             {"",S_FALSE,FALSE},
3281             {"file://c:/dir/index.html",S_OK,FALSE},
3282             {"file",S_OK,FALSE},
3283             {"",S_FALSE,FALSE},
3284             {"",S_FALSE,FALSE}
3285         },
3286         {
3287             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3288             {0,S_FALSE,FALSE},
3289             {URL_SCHEME_FILE,S_OK,FALSE},
3290             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3291         }
3292     },
3293     /* Extra '/' after "file://" is removed. */
3294     {   "file:///c:/dir/index.html", Uri_CREATE_FILE_USE_DOS_PATH, S_OK, FALSE,
3295         {
3296             {"file://c:\\dir\\index.html",S_OK,FALSE},
3297             {"",S_FALSE,FALSE},
3298             {"file://c:\\dir\\index.html",S_OK,FALSE},
3299             {"",S_FALSE,FALSE},
3300             {".html",S_OK,FALSE},
3301             {"",S_FALSE,FALSE},
3302             {"",S_FALSE,FALSE},
3303             {"",S_FALSE,FALSE},
3304             {"c:\\dir\\index.html",S_OK,FALSE},
3305             {"c:\\dir\\index.html",S_OK,FALSE},
3306             {"",S_FALSE,FALSE},
3307             {"file:///c:/dir/index.html",S_OK,FALSE},
3308             {"file",S_OK,FALSE},
3309             {"",S_FALSE,FALSE},
3310             {"",S_FALSE,FALSE}
3311         },
3312         {
3313             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3314             {0,S_FALSE,FALSE},
3315             {URL_SCHEME_FILE,S_OK,FALSE},
3316             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3317         }
3318     },
3319     /* Allow more characters when Uri_CREATE_FILE_USE_DOS_PATH is specified */
3320     {   "file:///c:/dir\\%%61%20%5Fname/file%2A.html", Uri_CREATE_FILE_USE_DOS_PATH, S_OK, FALSE,
3321         {
3322             {"file://c:\\dir\\%a _name\\file*.html",S_OK,FALSE},
3323             {"",S_FALSE,FALSE},
3324             {"file://c:\\dir\\%a _name\\file*.html",S_OK,FALSE},
3325             {"",S_FALSE,FALSE},
3326             {".html",S_OK,FALSE},
3327             {"",S_FALSE,FALSE},
3328             {"",S_FALSE,FALSE},
3329             {"",S_FALSE,FALSE},
3330             {"c:\\dir\\%a _name\\file*.html",S_OK,FALSE},
3331             {"c:\\dir\\%a _name\\file*.html",S_OK,FALSE},
3332             {"",S_FALSE,FALSE},
3333             {"file:///c:/dir\\%%61%20%5Fname/file%2A.html",S_OK,FALSE},
3334             {"file",S_OK,FALSE},
3335             {"",S_FALSE,FALSE},
3336             {"",S_FALSE,FALSE}
3337         },
3338         {
3339             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3340             {0,S_FALSE,FALSE},
3341             {URL_SCHEME_FILE,S_OK,FALSE},
3342             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3343         }
3344     },
3345     {   "file://c|/dir\\index.html", Uri_CREATE_FILE_USE_DOS_PATH, S_OK, FALSE,
3346         {
3347             {"file://c:\\dir\\index.html",S_OK,FALSE},
3348             {"",S_FALSE,FALSE},
3349             {"file://c:\\dir\\index.html",S_OK,FALSE},
3350             {"",S_FALSE,FALSE},
3351             {".html",S_OK,FALSE},
3352             {"",S_FALSE,FALSE},
3353             {"",S_FALSE,FALSE},
3354             {"",S_FALSE,FALSE},
3355             {"c:\\dir\\index.html",S_OK,FALSE},
3356             {"c:\\dir\\index.html",S_OK,FALSE},
3357             {"",S_FALSE,FALSE},
3358             {"file://c|/dir\\index.html",S_OK,FALSE},
3359             {"file",S_OK,FALSE},
3360             {"",S_FALSE,FALSE},
3361             {"",S_FALSE,FALSE}
3362         },
3363         {
3364             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3365             {0,S_FALSE,FALSE},
3366             {URL_SCHEME_FILE,S_OK,FALSE},
3367             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3368         }
3369     },
3370     /* The backslashes after the scheme name are converted to forward slashes. */
3371     {   "file:\\\\c:\\dir\\index.html", Uri_CREATE_FILE_USE_DOS_PATH, S_OK, FALSE,
3372         {
3373             {"file://c:\\dir\\index.html",S_OK,FALSE},
3374             {"",S_FALSE,FALSE},
3375             {"file://c:\\dir\\index.html",S_OK,FALSE},
3376             {"",S_FALSE,FALSE},
3377             {".html",S_OK,FALSE},
3378             {"",S_FALSE,FALSE},
3379             {"",S_FALSE,FALSE},
3380             {"",S_FALSE,FALSE},
3381             {"c:\\dir\\index.html",S_OK,FALSE},
3382             {"c:\\dir\\index.html",S_OK,FALSE},
3383             {"",S_FALSE,FALSE},
3384             {"file:\\\\c:\\dir\\index.html",S_OK,FALSE},
3385             {"file",S_OK,FALSE},
3386             {"",S_FALSE,FALSE},
3387             {"",S_FALSE,FALSE}
3388         },
3389         {
3390             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3391             {0,S_FALSE,FALSE},
3392             {URL_SCHEME_FILE,S_OK,FALSE},
3393             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3394         }
3395     },
3396     {   "file:\\\\c:/dir/index.html", 0, S_OK, FALSE,
3397         {
3398             {"file:///c:/dir/index.html",S_OK,FALSE},
3399             {"",S_FALSE,FALSE},
3400             {"file:///c:/dir/index.html",S_OK,FALSE},
3401             {"",S_FALSE,FALSE},
3402             {".html",S_OK,FALSE},
3403             {"",S_FALSE,FALSE},
3404             {"",S_FALSE,FALSE},
3405             {"",S_FALSE,FALSE},
3406             {"/c:/dir/index.html",S_OK,FALSE},
3407             {"/c:/dir/index.html",S_OK,FALSE},
3408             {"",S_FALSE,FALSE},
3409             {"file:\\\\c:/dir/index.html",S_OK,FALSE},
3410             {"file",S_OK,FALSE},
3411             {"",S_FALSE,FALSE},
3412             {"",S_FALSE,FALSE}
3413         },
3414         {
3415             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3416             {0,S_FALSE,FALSE},
3417             {URL_SCHEME_FILE,S_OK,FALSE},
3418             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3419         }
3420     },
3421     {   "http:\\\\google.com", 0, S_OK, FALSE,
3422         {
3423             {"http://google.com/",S_OK,FALSE},
3424             {"google.com",S_OK,FALSE},
3425             {"http://google.com/",S_OK,FALSE},
3426             {"google.com",S_OK,FALSE},
3427             {"",S_FALSE,FALSE},
3428             {"",S_FALSE,FALSE},
3429             {"google.com",S_OK,FALSE},
3430             {"",S_FALSE,FALSE},
3431             {"/",S_OK,FALSE},
3432             {"/",S_OK,FALSE},
3433             {"",S_FALSE,FALSE},
3434             {"http:\\\\google.com",S_OK,FALSE},
3435             {"http",S_OK,FALSE},
3436             {"",S_FALSE,FALSE},
3437             {"",S_FALSE,FALSE}
3438         },
3439         {
3440             {Uri_HOST_DNS,S_OK,FALSE},
3441             {80,S_OK,FALSE},
3442             {URL_SCHEME_HTTP,S_OK,FALSE},
3443             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3444         }
3445     },
3446     /* the "\\\\" aren't converted to "//" for unknown scheme types and it's considered opaque. */
3447     {   "zip:\\\\google.com", 0, S_OK, FALSE,
3448         {
3449             {"zip:\\\\google.com",S_OK,FALSE},
3450             {"",S_FALSE,FALSE},
3451             {"zip:\\\\google.com",S_OK,FALSE},
3452             {"",S_FALSE,FALSE},
3453             {".com",S_OK,FALSE},
3454             {"",S_FALSE,FALSE},
3455             {"",S_FALSE,FALSE},
3456             {"",S_FALSE,FALSE},
3457             {"\\\\google.com",S_OK,FALSE},
3458             {"\\\\google.com",S_OK,FALSE},
3459             {"",S_FALSE,FALSE},
3460             {"zip:\\\\google.com",S_OK,FALSE},
3461             {"zip",S_OK,FALSE},
3462             {"",S_FALSE,FALSE},
3463             {"",S_FALSE,FALSE}
3464         },
3465         {
3466             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3467             {0,S_FALSE,FALSE},
3468             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
3469             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3470         }
3471     },
3472     /* Dot segments aren't removed. */
3473     {   "file://c:\\dir\\../..\\./index.html", Uri_CREATE_FILE_USE_DOS_PATH, S_OK, FALSE,
3474         {
3475             {"file://c:\\dir\\..\\..\\.\\index.html",S_OK,FALSE},
3476             {"",S_FALSE,FALSE},
3477             {"file://c:\\dir\\..\\..\\.\\index.html",S_OK,FALSE},
3478             {"",S_FALSE,FALSE},
3479             {".html",S_OK,FALSE},
3480             {"",S_FALSE,FALSE},
3481             {"",S_FALSE,FALSE},
3482             {"",S_FALSE,FALSE},
3483             {"c:\\dir\\..\\..\\.\\index.html",S_OK,FALSE},
3484             {"c:\\dir\\..\\..\\.\\index.html",S_OK,FALSE},
3485             {"",S_FALSE,FALSE},
3486             {"file://c:\\dir\\../..\\./index.html",S_OK,FALSE},
3487             {"file",S_OK,FALSE},
3488             {"",S_FALSE,FALSE},
3489             {"",S_FALSE,FALSE}
3490         },
3491         {
3492             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3493             {0,S_FALSE,FALSE},
3494             {URL_SCHEME_FILE,S_OK,FALSE},
3495             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3496         }
3497     },
3498     /* Forbidden characters aren't percent encoded. */
3499     {   "file://c:\\dir\\i^|ndex.html", Uri_CREATE_FILE_USE_DOS_PATH, S_OK, FALSE,
3500         {
3501             {"file://c:\\dir\\i^|ndex.html",S_OK,FALSE},
3502             {"",S_FALSE,FALSE},
3503             {"file://c:\\dir\\i^|ndex.html",S_OK,FALSE},
3504             {"",S_FALSE,FALSE},
3505             {".html",S_OK,FALSE},
3506             {"",S_FALSE,FALSE},
3507             {"",S_FALSE,FALSE},
3508             {"",S_FALSE,FALSE},
3509             {"c:\\dir\\i^|ndex.html",S_OK,FALSE},
3510             {"c:\\dir\\i^|ndex.html",S_OK,FALSE},
3511             {"",S_FALSE,FALSE},
3512             {"file://c:\\dir\\i^|ndex.html",S_OK,FALSE},
3513             {"file",S_OK,FALSE},
3514             {"",S_FALSE,FALSE},
3515             {"",S_FALSE,FALSE}
3516         },
3517         {
3518             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3519             {0,S_FALSE,FALSE},
3520             {URL_SCHEME_FILE,S_OK,FALSE},
3521             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3522         }
3523     },
3524     /* The '\' are still converted to '/' even though it's an opaque file URI. */
3525     {   "file:c:\\dir\\../..\\index.html", 0, S_OK, FALSE,
3526         {
3527             {"",S_FALSE,FALSE},
3528             {"",S_FALSE,FALSE},
3529             {"file:c:/dir/../../index.html",S_OK,FALSE},
3530             {"",S_FALSE,FALSE},
3531             {".html",S_OK,FALSE},
3532             {"",S_FALSE,FALSE},
3533             {"",S_FALSE,FALSE},
3534             {"",S_FALSE,FALSE},
3535             {"c:/dir/../../index.html",S_OK,FALSE},
3536             {"c:/dir/../../index.html",S_OK,FALSE},
3537             {"",S_FALSE,FALSE},
3538             {"file:c:\\dir\\../..\\index.html",S_OK,FALSE},
3539             {"file",S_OK,FALSE},
3540             {"",S_FALSE,FALSE},
3541             {"",S_FALSE,FALSE}
3542         },
3543         {
3544             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3545             {0,S_FALSE,FALSE},
3546             {URL_SCHEME_FILE,S_OK,FALSE},
3547             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3548         }
3549     },
3550     /* '/' are still converted to '\' even though it's an opaque URI. */
3551     {   "file:c:/dir\\../..\\index.html", Uri_CREATE_FILE_USE_DOS_PATH, S_OK, FALSE,
3552         {
3553             {"",S_FALSE,FALSE},
3554             {"",S_FALSE,FALSE},
3555             {"file:c:\\dir\\..\\..\\index.html",S_OK,FALSE},
3556             {"",S_FALSE,FALSE},
3557             {".html",S_OK,FALSE},
3558             {"",S_FALSE,FALSE},
3559             {"",S_FALSE,FALSE},
3560             {"",S_FALSE,FALSE},
3561             {"c:\\dir\\..\\..\\index.html",S_OK,FALSE},
3562             {"c:\\dir\\..\\..\\index.html",S_OK,FALSE},
3563             {"",S_FALSE,FALSE},
3564             {"file:c:/dir\\../..\\index.html",S_OK,FALSE},
3565             {"file",S_OK,FALSE},
3566             {"",S_FALSE,FALSE},
3567             {"",S_FALSE,FALSE}
3568         },
3569         {
3570             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3571             {0,S_FALSE,FALSE},
3572             {URL_SCHEME_FILE,S_OK,FALSE},
3573             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3574         }
3575     },
3576     /* Forbidden characters aren't percent encoded. */
3577     {   "file:c:\\in^|dex.html", Uri_CREATE_FILE_USE_DOS_PATH, S_OK, FALSE,
3578         {
3579             {"",S_FALSE,FALSE},
3580             {"",S_FALSE,FALSE},
3581             {"file:c:\\in^|dex.html",S_OK,FALSE},
3582             {"",S_FALSE,FALSE},
3583             {".html",S_OK,FALSE},
3584             {"",S_FALSE,FALSE},
3585             {"",S_FALSE,FALSE},
3586             {"",S_FALSE,FALSE},
3587             {"c:\\in^|dex.html",S_OK,FALSE},
3588             {"c:\\in^|dex.html",S_OK,FALSE},
3589             {"",S_FALSE,FALSE},
3590             {"file:c:\\in^|dex.html",S_OK,FALSE},
3591             {"file",S_OK,FALSE},
3592             {"",S_FALSE,FALSE},
3593             {"",S_FALSE,FALSE}
3594         },
3595         {
3596             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3597             {0,S_FALSE,FALSE},
3598             {URL_SCHEME_FILE,S_OK,FALSE},
3599             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3600         }
3601     },
3602     /* Doesn't have a UserName since the ':' appears at the beginning of the
3603      * userinfo section.
3604      */
3605     {   "http://:password@gov.uk", 0, S_OK, FALSE,
3606         {
3607             {"http://:password@gov.uk/",S_OK,FALSE},
3608             {":password@gov.uk",S_OK,FALSE},
3609             {"http://gov.uk/",S_OK,FALSE},
3610             {"",S_FALSE,FALSE},
3611             {"",S_FALSE,FALSE},
3612             {"",S_FALSE,FALSE},
3613             {"gov.uk",S_OK,FALSE},
3614             {"password",S_OK,FALSE},
3615             {"/",S_OK,FALSE},
3616             {"/",S_OK,FALSE},
3617             {"",S_FALSE,FALSE},
3618             {"http://:password@gov.uk",S_OK,FALSE},
3619             {"http",S_OK,FALSE},
3620             {":password",S_OK,FALSE},
3621             {"",S_FALSE,FALSE}
3622         },
3623         {
3624             {Uri_HOST_DNS,S_OK,FALSE},
3625             {80,S_OK,FALSE},
3626             {URL_SCHEME_HTTP,S_OK,FALSE},
3627             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3628         }
3629     },
3630     /* Has a UserName since the userinfo section doesn't contain a password. */
3631     {   "http://@gov.uk", 0, S_OK, FALSE,
3632         {
3633             {"http://gov.uk/",S_OK,FALSE,"http://@gov.uk/"},
3634             {"@gov.uk",S_OK,FALSE},
3635             {"http://gov.uk/",S_OK,FALSE},
3636             {"",S_FALSE,FALSE},
3637             {"",S_FALSE,FALSE},
3638             {"",S_FALSE,FALSE},
3639             {"gov.uk",S_OK,FALSE},
3640             {"",S_FALSE,FALSE},
3641             {"/",S_OK,FALSE},
3642             {"/",S_OK,FALSE},
3643             {"",S_FALSE,FALSE},
3644             {"http://@gov.uk",S_OK,FALSE},
3645             {"http",S_OK,FALSE},
3646             {"",S_OK,FALSE},
3647             {"",S_OK,FALSE}
3648         },
3649         {
3650             {Uri_HOST_DNS,S_OK,FALSE},
3651             {80,S_OK,FALSE},
3652             {URL_SCHEME_HTTP,S_OK,FALSE},
3653             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3654         }
3655     },
3656     /* ":@" not included in the absolute URI. */
3657     {   "http://:@gov.uk", 0, S_OK, FALSE,
3658         {
3659             {"http://gov.uk/",S_OK,FALSE,"http://:@gov.uk/"},
3660             {":@gov.uk",S_OK,FALSE},
3661             {"http://gov.uk/",S_OK,FALSE},
3662             {"",S_FALSE,FALSE},
3663             {"",S_FALSE,FALSE},
3664             {"",S_FALSE,FALSE},
3665             {"gov.uk",S_OK,FALSE},
3666             {"",S_OK,FALSE},
3667             {"/",S_OK,FALSE},
3668             {"/",S_OK,FALSE},
3669             {"",S_FALSE,FALSE},
3670             {"http://:@gov.uk",S_OK,FALSE},
3671             {"http",S_OK,FALSE},
3672             {":",S_OK,FALSE},
3673             {"",S_FALSE,FALSE}
3674         },
3675         {
3676             {Uri_HOST_DNS,S_OK,FALSE},
3677             {80,S_OK,FALSE},
3678             {URL_SCHEME_HTTP,S_OK,FALSE},
3679             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3680         }
3681     },
3682     /* '@' is included because it's an unknown scheme type. */
3683     {   "zip://@gov.uk", 0, S_OK, FALSE,
3684         {
3685             {"zip://@gov.uk/",S_OK,FALSE},
3686             {"@gov.uk",S_OK,FALSE},
3687             {"zip://@gov.uk/",S_OK,FALSE},
3688             {"",S_FALSE,FALSE},
3689             {"",S_FALSE,FALSE},
3690             {"",S_FALSE,FALSE},
3691             {"gov.uk",S_OK,FALSE},
3692             {"",S_FALSE,FALSE},
3693             {"/",S_OK,FALSE},
3694             {"/",S_OK,FALSE},
3695             {"",S_FALSE,FALSE},
3696             {"zip://@gov.uk",S_OK,FALSE},
3697             {"zip",S_OK,FALSE},
3698             {"",S_OK,FALSE},
3699             {"",S_OK,FALSE}
3700         },
3701         {
3702             {Uri_HOST_DNS,S_OK,FALSE},
3703             {0,S_FALSE,FALSE},
3704             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
3705             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3706         }
3707     },
3708     /* ":@" are included because it's an unknown scheme type. */
3709     {   "zip://:@gov.uk", 0, S_OK, FALSE,
3710         {
3711             {"zip://:@gov.uk/",S_OK,FALSE},
3712             {":@gov.uk",S_OK,FALSE},
3713             {"zip://:@gov.uk/",S_OK,FALSE},
3714             {"",S_FALSE,FALSE},
3715             {"",S_FALSE,FALSE},
3716             {"",S_FALSE,FALSE},
3717             {"gov.uk",S_OK,FALSE},
3718             {"",S_OK,FALSE},
3719             {"/",S_OK,FALSE},
3720             {"/",S_OK,FALSE},
3721             {"",S_FALSE,FALSE},
3722             {"zip://:@gov.uk",S_OK,FALSE},
3723             {"zip",S_OK,FALSE},
3724             {":",S_OK,FALSE},
3725             {"",S_FALSE,FALSE}
3726         },
3727         {
3728             {Uri_HOST_DNS,S_OK,FALSE},
3729             {0,S_FALSE,FALSE},
3730             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
3731             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3732         }
3733     },
3734     {   "about:blank", 0, S_OK, FALSE,
3735         {
3736             {"about:blank",S_OK,FALSE},
3737             {"",S_FALSE,FALSE},
3738             {"about:blank",S_OK,FALSE},
3739             {"",S_FALSE,FALSE},
3740             {"",S_FALSE,FALSE},
3741             {"",S_FALSE,FALSE},
3742             {"",S_FALSE,FALSE},
3743             {"",S_FALSE,FALSE},
3744             {"blank",S_OK,FALSE},
3745             {"blank",S_OK,FALSE},
3746             {"",S_FALSE,FALSE},
3747             {"about:blank",S_OK,FALSE},
3748             {"about",S_OK,FALSE},
3749             {"",S_FALSE,FALSE},
3750             {"",S_FALSE,FALSE}
3751         },
3752         {
3753             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3754             {0,S_FALSE,FALSE},
3755             {URL_SCHEME_ABOUT,S_OK,FALSE},
3756             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3757         }
3758     },
3759     {   "mk:@MSITStore:C:\\Program Files/AutoCAD 2008\\Help/acad_acg.chm::/WSfacf1429558a55de1a7524c1004e616f8b-322b.htm",0,S_OK,FALSE,
3760         {
3761             {"mk:@MSITStore:C:\\Program%20Files/AutoCAD%202008\\Help/acad_acg.chm::/WSfacf1429558a55de1a7524c1004e616f8b-322b.htm",S_OK,FALSE},
3762             {"",S_FALSE,FALSE},
3763             {"mk:@MSITStore:C:\\Program%20Files/AutoCAD%202008\\Help/acad_acg.chm::/WSfacf1429558a55de1a7524c1004e616f8b-322b.htm",S_OK,FALSE},
3764             {"",S_FALSE,FALSE},
3765             {".htm",S_OK,FALSE},
3766             {"",S_FALSE,FALSE},
3767             {"",S_FALSE,FALSE},
3768             {"",S_FALSE,FALSE},
3769             {"@MSITStore:C:\\Program%20Files/AutoCAD%202008\\Help/acad_acg.chm::/WSfacf1429558a55de1a7524c1004e616f8b-322b.htm",S_OK,FALSE},
3770             {"@MSITStore:C:\\Program%20Files/AutoCAD%202008\\Help/acad_acg.chm::/WSfacf1429558a55de1a7524c1004e616f8b-322b.htm",S_OK,FALSE},
3771             {"",S_FALSE,FALSE},
3772             {"mk:@MSITStore:C:\\Program Files/AutoCAD 2008\\Help/acad_acg.chm::/WSfacf1429558a55de1a7524c1004e616f8b-322b.htm",S_OK,FALSE},
3773             {"mk",S_OK,FALSE},
3774             {"",S_FALSE,FALSE},
3775             {"",S_FALSE,FALSE}
3776         },
3777         {
3778             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3779             {0,S_FALSE,FALSE},
3780             {URL_SCHEME_MK,S_OK,FALSE},
3781             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3782         }
3783     },
3784     {   "mk:@MSITStore:Z:\\home\\test\\chm\\silqhelp.chm::/thesilqquickstartguide.htm",0,S_OK,FALSE,
3785         {
3786             {"mk:@MSITStore:Z:\\home\\test\\chm\\silqhelp.chm::/thesilqquickstartguide.htm",S_OK,FALSE},
3787             {"",S_FALSE,FALSE},
3788             {"mk:@MSITStore:Z:\\home\\test\\chm\\silqhelp.chm::/thesilqquickstartguide.htm",S_OK,FALSE},
3789             {"",S_FALSE,FALSE},
3790             {".htm",S_OK,FALSE},
3791             {"",S_FALSE,FALSE},
3792             {"",S_FALSE,FALSE},
3793             {"",S_FALSE,FALSE},
3794             {"@MSITStore:Z:\\home\\test\\chm\\silqhelp.chm::/thesilqquickstartguide.htm",S_OK,FALSE},
3795             {"@MSITStore:Z:\\home\\test\\chm\\silqhelp.chm::/thesilqquickstartguide.htm",S_OK,FALSE},
3796             {"",S_FALSE,FALSE},
3797             {"mk:@MSITStore:Z:\\home\\test\\chm\\silqhelp.chm::/thesilqquickstartguide.htm",S_OK,FALSE},
3798             {"mk",S_OK,FALSE},
3799             {"",S_FALSE,FALSE},
3800             {"",S_FALSE,FALSE}
3801         },
3802         {
3803             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3804             {0,S_FALSE,FALSE},
3805             {URL_SCHEME_MK,S_OK,FALSE},
3806             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3807         }
3808     },
3809     /* Two '\' are added to the URI when USE_DOS_PATH is set, and it's a UNC path. */
3810     {   "file://server/dir/index.html", Uri_CREATE_FILE_USE_DOS_PATH, S_OK, FALSE,
3811         {
3812             {"file://\\\\server\\dir\\index.html",S_OK,FALSE},
3813             {"server",S_OK,FALSE},
3814             {"file://\\\\server\\dir\\index.html",S_OK,FALSE},
3815             {"",S_FALSE,FALSE},
3816             {".html",S_OK,FALSE},
3817             {"",S_FALSE,FALSE},
3818             {"server",S_OK,FALSE},
3819             {"",S_FALSE,FALSE},
3820             {"\\dir\\index.html",S_OK,FALSE},
3821             {"\\dir\\index.html",S_OK,FALSE},
3822             {"",S_FALSE,FALSE},
3823             {"file://server/dir/index.html",S_OK,FALSE},
3824             {"file",S_OK,FALSE},
3825             {"",S_FALSE,FALSE},
3826             {"",S_FALSE,FALSE}
3827         },
3828         {
3829             {Uri_HOST_DNS,S_OK,FALSE},
3830             {0,S_FALSE,FALSE},
3831             {URL_SCHEME_FILE,S_OK,FALSE},
3832             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3833         }
3834     },
3835     /* When CreateUri generates an IUri, it still displays the default port in the
3836      * authority.
3837      */
3838     {   "http://google.com:80/", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
3839         {
3840             {"http://google.com:80/",S_OK,FALSE},
3841             {"google.com:80",S_OK,FALSE},
3842             {"http://google.com:80/",S_OK,FALSE},
3843             {"google.com",S_OK,FALSE},
3844             {"",S_FALSE,FALSE},
3845             {"",S_FALSE,FALSE},
3846             {"google.com",S_OK,FALSE},
3847             {"",S_FALSE,FALSE},
3848             {"/",S_OK,FALSE},
3849             {"/",S_OK,FALSE},
3850             {"",S_FALSE,FALSE},
3851             {"http://google.com:80/",S_OK,FALSE},
3852             {"http",S_OK,FALSE},
3853             {"",S_FALSE,FALSE},
3854             {"",S_FALSE,FALSE}
3855         },
3856         {
3857             {Uri_HOST_DNS,S_OK,FALSE},
3858             {80,S_OK,FALSE},
3859             {URL_SCHEME_HTTP,S_OK,FALSE},
3860             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3861         }
3862     },
3863     /* For res URIs the host is everything up until the first '/'. */
3864     {   "res://C:\\dir\\file.exe/DATA/test.html", 0, S_OK, FALSE,
3865         {
3866             {"res://C:\\dir\\file.exe/DATA/test.html",S_OK,FALSE},
3867             {"C:\\dir\\file.exe",S_OK,FALSE},
3868             {"res://C:\\dir\\file.exe/DATA/test.html",S_OK,FALSE},
3869             {"",S_FALSE,FALSE},
3870             {".html",S_OK,FALSE},
3871             {"",S_FALSE,FALSE},
3872             {"C:\\dir\\file.exe",S_OK,FALSE},
3873             {"",S_FALSE,FALSE},
3874             {"/DATA/test.html",S_OK,FALSE},
3875             {"/DATA/test.html",S_OK,FALSE},
3876             {"",S_FALSE,FALSE},
3877             {"res://C:\\dir\\file.exe/DATA/test.html",S_OK,FALSE},
3878             {"res",S_OK,FALSE},
3879             {"",S_FALSE,FALSE},
3880             {"",S_FALSE,FALSE}
3881         },
3882         {
3883             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3884             {0,S_FALSE,FALSE},
3885             {URL_SCHEME_RES,S_OK,FALSE},
3886             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3887         }
3888     },
3889     /* Res URI can contain a '|' in the host name. */
3890     {   "res://c:\\di|r\\file.exe/test", 0, S_OK, FALSE,
3891         {
3892             {"res://c:\\di|r\\file.exe/test",S_OK,FALSE},
3893             {"c:\\di|r\\file.exe",S_OK,FALSE},
3894             {"res://c:\\di|r\\file.exe/test",S_OK,FALSE},
3895             {"",S_FALSE,FALSE},
3896             {"",S_FALSE,FALSE},
3897             {"",S_FALSE,FALSE},
3898             {"c:\\di|r\\file.exe",S_OK,FALSE},
3899             {"",S_FALSE,FALSE},
3900             {"/test",S_OK,FALSE},
3901             {"/test",S_OK,FALSE},
3902             {"",S_FALSE,FALSE},
3903             {"res://c:\\di|r\\file.exe/test",S_OK,FALSE},
3904             {"res",S_OK,FALSE},
3905             {"",S_FALSE,FALSE},
3906             {"",S_FALSE,FALSE}
3907         },
3908         {
3909             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3910             {0,S_FALSE,FALSE},
3911             {URL_SCHEME_RES,S_OK,FALSE},
3912             {URLZONE_INVALID,E_NOTIMPL,FALSE},
3913         }
3914     },
3915     /* Res URIs can have invalid percent encoded values. */
3916     {   "res://c:\\dir%xx\\file.exe/test", 0, S_OK, FALSE,
3917         {
3918             {"res://c:\\dir%xx\\file.exe/test",S_OK,FALSE},
3919             {"c:\\dir%xx\\file.exe",S_OK,FALSE},
3920             {"res://c:\\dir%xx\\file.exe/test",S_OK,FALSE},
3921             {"",S_FALSE,FALSE},
3922             {"",S_FALSE,FALSE},
3923             {"",S_FALSE,FALSE},
3924             {"c:\\dir%xx\\file.exe",S_OK,FALSE},
3925             {"",S_FALSE,FALSE},
3926             {"/test",S_OK,FALSE},
3927             {"/test",S_OK,FALSE},
3928             {"",S_FALSE,FALSE},
3929             {"res://c:\\dir%xx\\file.exe/test",S_OK,FALSE},
3930             {"res",S_OK,FALSE},
3931             {"",S_FALSE,FALSE},
3932             {"",S_FALSE,FALSE}
3933         },
3934         {
3935             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3936             {0,S_FALSE,FALSE},
3937             {URL_SCHEME_RES,S_OK,FALSE},
3938             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3939         }
3940     },
3941     /* Res doesn't get forbidden characters percent encoded in it's path. */
3942     {   "res://c:\\test/tes<|>t", 0, S_OK, FALSE,
3943         {
3944             {"res://c:\\test/tes<|>t",S_OK,FALSE},
3945             {"c:\\test",S_OK,FALSE},
3946             {"res://c:\\test/tes<|>t",S_OK,FALSE},
3947             {"",S_FALSE,FALSE},
3948             {"",S_FALSE,FALSE},
3949             {"",S_FALSE,FALSE},
3950             {"c:\\test",S_OK,FALSE},
3951             {"",S_FALSE,FALSE},
3952             {"/tes<|>t",S_OK,FALSE},
3953             {"/tes<|>t",S_OK,FALSE},
3954             {"",S_FALSE,FALSE},
3955             {"res://c:\\test/tes<|>t",S_OK,FALSE},
3956             {"res",S_OK,FALSE},
3957             {"",S_FALSE,FALSE},
3958             {"",S_FALSE,FALSE}
3959         },
3960         {
3961             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3962             {0,S_FALSE,FALSE},
3963             {URL_SCHEME_RES,S_OK,FALSE},
3964             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3965         }
3966     }
3967 };
3968
3969 typedef struct _invalid_uri {
3970     const char* uri;
3971     DWORD       flags;
3972     BOOL        todo;
3973 } invalid_uri;
3974
3975 static const invalid_uri invalid_uri_tests[] = {
3976     /* Has to have a scheme name. */
3977     {"://www.winehq.org",0,FALSE},
3978     /* Window's doesn't like URI's which are implicitly file paths without the
3979      * ALLOW_IMPLICIT_FILE_SCHEME flag set.
3980      */
3981     {"C:/test/test.mp3",0,FALSE},
3982     {"\\\\Server/test/test.mp3",0,FALSE},
3983     {"C:/test/test.mp3",Uri_CREATE_ALLOW_IMPLICIT_WILDCARD_SCHEME,FALSE},
3984     {"\\\\Server/test/test.mp3",Uri_CREATE_ALLOW_RELATIVE,FALSE},
3985     /* Invalid schemes. */
3986     {"*abcd://not.valid.com",0,FALSE},
3987     {"*a*b*c*d://not.valid.com",0,FALSE},
3988     /* Not allowed to have invalid % encoded data. */
3989     {"ftp://google.co%XX/",0,FALSE},
3990     /* To many h16 components. */
3991     {"http://[1:2:3:4:5:6:7:8:9]",0,FALSE},
3992     /* Not enough room for IPv4 address. */
3993     {"http://[1:2:3:4:5:6:7:192.0.1.0]",0,FALSE},
3994     /* Not enough h16 components. */
3995     {"http://[1:2:3:4]",0,FALSE},
3996     /* Not enough components including IPv4. */
3997     {"http://[1:192.0.1.0]",0,FALSE},
3998     /* Not allowed to have partial IPv4 in IPv6. */
3999     {"http://[::192.0]",0,FALSE},
4000     /* Can't have elision of 1 h16 at beginning of address. */
4001     {"http://[::2:3:4:5:6:7:8]",0,FALSE},
4002     /* Can't have elision of 1 h16 at end of address. */
4003     {"http://[1:2:3:4:5:6:7::]",0,FALSE},
4004     /* Expects a valid IP Literal. */
4005     {"ftp://[not.valid.uri]/",0,FALSE},
4006     /* Expects valid port for a known scheme type. */
4007     {"ftp://www.winehq.org:123fgh",0,FALSE},
4008     /* Port exceeds USHORT_MAX for known scheme type. */
4009     {"ftp://www.winehq.org:65536",0,FALSE},
4010     /* Invalid port with IPv4 address. */
4011     {"http://www.winehq.org:1abcd",0,FALSE},
4012     /* Invalid port with IPv6 address. */
4013     {"http://[::ffff]:32xy",0,FALSE},
4014     /* Not allowed to have backslashes with NO_CANONICALIZE. */
4015     {"gopher://www.google.com\\test",Uri_CREATE_NO_CANONICALIZE,FALSE},
4016     /* Not allowed to have invalid % encoded data in opaque URI path. */
4017     {"news:test%XX",0,FALSE},
4018     {"mailto:wine@winehq%G8.com",0,FALSE},
4019     /* Known scheme types can't have invalid % encoded data in query string. */
4020     {"http://google.com/?query=te%xx",0,FALSE},
4021     /* Invalid % encoded data in fragment of know scheme type. */
4022     {"ftp://google.com/#Test%xx",0,FALSE},
4023     {"  http://google.com/",Uri_CREATE_NO_PRE_PROCESS_HTML_URI,FALSE},
4024     {"\n\nhttp://google.com/",Uri_CREATE_NO_PRE_PROCESS_HTML_URI,FALSE},
4025     {"file://c:\\test<test",Uri_CREATE_FILE_USE_DOS_PATH,FALSE},
4026     {"file://c:\\test>test",Uri_CREATE_FILE_USE_DOS_PATH,FALSE},
4027     {"file://c:\\test\"test",Uri_CREATE_FILE_USE_DOS_PATH,FALSE},
4028     {"file:c:\\test<test",Uri_CREATE_FILE_USE_DOS_PATH,FALSE},
4029     {"file:c:\\test>test",Uri_CREATE_FILE_USE_DOS_PATH,FALSE},
4030     {"file:c:\\test\"test",Uri_CREATE_FILE_USE_DOS_PATH,FALSE},
4031     /* res URIs aren't allowed to have forbidden dos path characters in the
4032      * hostname.
4033      */
4034     {"res://c:\\te<st\\test/test",0,FALSE},
4035     {"res://c:\\te>st\\test/test",0,FALSE},
4036     {"res://c:\\te\"st\\test/test",0,FALSE},
4037     {"res://c:\\test/te%xxst",0,FALSE}
4038 };
4039
4040 typedef struct _uri_equality {
4041     const char* a;
4042     DWORD       create_flags_a;
4043     BOOL        create_todo_a;
4044     const char* b;
4045     DWORD       create_flags_b;
4046     BOOL        create_todo_b;
4047     BOOL        equal;
4048     BOOL        todo;
4049 } uri_equality;
4050
4051 static const uri_equality equality_tests[] = {
4052     {
4053         "HTTP://www.winehq.org/test dir/./",0,FALSE,
4054         "http://www.winehq.org/test dir/../test dir/",0,FALSE,
4055         TRUE, FALSE
4056     },
4057     {
4058         /* http://www.winehq.org/test%20dir */
4059         "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,
4060         "http://www.winehq.org/test dir",0,FALSE,
4061         TRUE, FALSE
4062     },
4063     {
4064         "c:\\test.mp3",Uri_CREATE_ALLOW_IMPLICIT_FILE_SCHEME,FALSE,
4065         "file:///c:/test.mp3",0,FALSE,
4066         TRUE, FALSE
4067     },
4068     {
4069         "ftp://ftp.winehq.org/",0,FALSE,
4070         "ftp://ftp.winehq.org",0,FALSE,
4071         TRUE, FALSE
4072     },
4073     {
4074         "ftp://ftp.winehq.org/test/test2/../../testB/",0,FALSE,
4075         "ftp://ftp.winehq.org/t%45stB/",0,FALSE,
4076         FALSE, FALSE
4077     },
4078     {
4079         "http://google.com/TEST",0,FALSE,
4080         "http://google.com/test",0,FALSE,
4081         FALSE, FALSE
4082     },
4083     {
4084         "http://GOOGLE.com/",0,FALSE,
4085         "http://google.com/",0,FALSE,
4086         TRUE, FALSE
4087     },
4088     /* Performs case insensitive compare of host names (for known scheme types). */
4089     {
4090         "ftp://GOOGLE.com/",Uri_CREATE_NO_CANONICALIZE,FALSE,
4091         "ftp://google.com/",0,FALSE,
4092         TRUE, FALSE
4093     },
4094     {
4095         "zip://GOOGLE.com/",0,FALSE,
4096         "zip://google.com/",0,FALSE,
4097         FALSE, FALSE
4098     },
4099     {
4100         "file:///c:/TEST/TeST/",0,FALSE,
4101         "file:///c:/test/test/",0,FALSE,
4102         TRUE, FALSE
4103     },
4104     {
4105         "file:///server/TEST",0,FALSE,
4106         "file:///SERVER/TEST",0,FALSE,
4107         TRUE, FALSE
4108     },
4109     {
4110         "http://google.com",Uri_CREATE_NO_CANONICALIZE,FALSE,
4111         "http://google.com/",0,FALSE,
4112         TRUE, FALSE
4113     },
4114     {
4115         "ftp://google.com:21/",0,FALSE,
4116         "ftp://google.com/",0,FALSE,
4117         TRUE, FALSE
4118     },
4119     {
4120         "http://google.com:80/",Uri_CREATE_NO_CANONICALIZE,FALSE,
4121         "http://google.com/",0,FALSE,
4122         TRUE, FALSE
4123     },
4124     {
4125         "http://google.com:70/",0,FALSE,
4126         "http://google.com:71/",0,FALSE,
4127         FALSE, FALSE
4128     }
4129 };
4130
4131 typedef struct _uri_with_fragment {
4132     const char* uri;
4133     const char* fragment;
4134     DWORD       create_flags;
4135     HRESULT     create_expected;
4136     BOOL        create_todo;
4137
4138     const char* expected_uri;
4139     BOOL        expected_todo;
4140 } uri_with_fragment;
4141
4142 static const uri_with_fragment uri_fragment_tests[] = {
4143     {
4144         "http://google.com/","#fragment",0,S_OK,FALSE,
4145         "http://google.com/#fragment",FALSE
4146     },
4147     {
4148         "http://google.com/","fragment",0,S_OK,FALSE,
4149         "http://google.com/#fragment",FALSE
4150     },
4151     {
4152         "zip://test.com/","?test",0,S_OK,FALSE,
4153         "zip://test.com/#?test",FALSE
4154     },
4155     /* The fragment can be empty. */
4156     {
4157         "ftp://ftp.google.com/","",0,S_OK,FALSE,
4158         "ftp://ftp.google.com/#",FALSE
4159     }
4160 };
4161
4162 typedef struct _uri_builder_property {
4163     BOOL            change;
4164     const char      *value;
4165     const char      *expected_value;
4166     Uri_PROPERTY    property;
4167     HRESULT         expected;
4168     BOOL            todo;
4169 } uri_builder_property;
4170
4171 typedef struct _uri_builder_port {
4172     BOOL    change;
4173     BOOL    set;
4174     DWORD   value;
4175     HRESULT expected;
4176     BOOL    todo;
4177 } uri_builder_port;
4178
4179 typedef struct _uri_builder_str_property {
4180     const char* expected;
4181     HRESULT     result;
4182     BOOL        todo;
4183 } uri_builder_str_property;
4184
4185 typedef struct _uri_builder_dword_property {
4186     DWORD   expected;
4187     HRESULT result;
4188     BOOL    todo;
4189 } uri_builder_dword_property;
4190
4191 typedef struct _uri_builder_test {
4192     const char                  *uri;
4193     DWORD                       create_flags;
4194     HRESULT                     create_builder_expected;
4195     BOOL                        create_builder_todo;
4196
4197     uri_builder_property        properties[URI_BUILDER_STR_PROPERTY_COUNT];
4198
4199     uri_builder_port            port_prop;
4200
4201     DWORD                       uri_flags;
4202     HRESULT                     uri_hres;
4203     BOOL                        uri_todo;
4204
4205     DWORD                       uri_simple_encode_flags;
4206     HRESULT                     uri_simple_hres;
4207     BOOL                        uri_simple_todo;
4208
4209     DWORD                       uri_with_flags;
4210     DWORD                       uri_with_builder_flags;
4211     DWORD                       uri_with_encode_flags;
4212     HRESULT                     uri_with_hres;
4213     BOOL                        uri_with_todo;
4214
4215     uri_builder_str_property    expected_str_props[URI_STR_PROPERTY_COUNT];
4216     uri_builder_dword_property  expected_dword_props[URI_DWORD_PROPERTY_COUNT];
4217 } uri_builder_test;
4218
4219 static const uri_builder_test uri_builder_tests[] = {
4220     {   "http://google.com/",0,S_OK,FALSE,
4221         {
4222             {TRUE,"#fragment",NULL,Uri_PROPERTY_FRAGMENT,S_OK,FALSE},
4223             {TRUE,"password",NULL,Uri_PROPERTY_PASSWORD,S_OK,FALSE},
4224             {TRUE,"?query=x",NULL,Uri_PROPERTY_QUERY,S_OK,FALSE},
4225             {TRUE,"username",NULL,Uri_PROPERTY_USER_NAME,S_OK,FALSE}
4226         },
4227         {FALSE},
4228         0,S_OK,FALSE,
4229         0,S_OK,FALSE,
4230         0,0,0,S_OK,FALSE,
4231         {
4232             {"http://username:password@google.com/?query=x#fragment",S_OK},
4233             {"username:password@google.com",S_OK},
4234             {"http://google.com/?query=x#fragment",S_OK},
4235             {"google.com",S_OK},
4236             {"",S_FALSE},
4237             {"#fragment",S_OK},
4238             {"google.com",S_OK},
4239             {"password",S_OK},
4240             {"/",S_OK},
4241             {"/?query=x",S_OK},
4242             {"?query=x",S_OK},
4243             {"http://username:password@google.com/?query=x#fragment",S_OK},
4244             {"http",S_OK},
4245             {"username:password",S_OK},
4246             {"username",S_OK}
4247         },
4248         {
4249             {Uri_HOST_DNS,S_OK},
4250             {80,S_OK},
4251             {URL_SCHEME_HTTP,S_OK},
4252             {URLZONE_INVALID,E_NOTIMPL}
4253         }
4254     },
4255     {   "http://google.com/",0,S_OK,FALSE,
4256         {
4257             {TRUE,"test",NULL,Uri_PROPERTY_SCHEME_NAME,S_OK,FALSE}
4258         },
4259         {TRUE,TRUE,120,S_OK,FALSE},
4260         0,S_OK,FALSE,
4261         0,S_OK,FALSE,
4262         0,0,0,S_OK,FALSE,
4263         {
4264             {"test://google.com:120/",S_OK},
4265             {"google.com:120",S_OK},
4266             {"test://google.com:120/",S_OK},
4267             {"google.com",S_OK},
4268             {"",S_FALSE},
4269             {"",S_FALSE},
4270             {"google.com",S_OK},
4271             {"",S_FALSE},
4272             {"/",S_OK},
4273             {"/",S_OK},
4274             {"",S_FALSE},
4275             {"test://google.com:120/",S_OK},
4276             {"test",S_OK},
4277             {"",S_FALSE},
4278             {"",S_FALSE}
4279         },
4280         {
4281             {Uri_HOST_DNS,S_OK},
4282             {120,S_OK},
4283             {URL_SCHEME_UNKNOWN,S_OK},
4284             {URLZONE_INVALID,E_NOTIMPL}
4285         }
4286     },
4287     {   "/Test/test dir",Uri_CREATE_ALLOW_RELATIVE,S_OK,FALSE,
4288         {
4289             {TRUE,"http",NULL,Uri_PROPERTY_SCHEME_NAME,S_OK,FALSE},
4290             {TRUE,"::192.2.3.4",NULL,Uri_PROPERTY_HOST,S_OK,FALSE},
4291             {TRUE,NULL,NULL,Uri_PROPERTY_PATH,S_OK,FALSE}
4292         },
4293         {FALSE},
4294         0,S_OK,FALSE,
4295         0,S_OK,FALSE,
4296         0,0,0,S_OK,FALSE,
4297         {
4298             {"http://[::192.2.3.4]/",S_OK},
4299             {"[::192.2.3.4]",S_OK},
4300             {"http://[::192.2.3.4]/",S_OK},
4301             {"",S_FALSE},
4302             {"",S_FALSE},
4303             {"",S_FALSE},
4304             {"::192.2.3.4",S_OK},
4305             {"",S_FALSE},
4306             {"/",S_OK},
4307             {"/",S_OK},
4308             {"",S_FALSE},
4309             {"http://[::192.2.3.4]/",S_OK},
4310             {"http",S_OK},
4311             {"",S_FALSE},
4312             {"",S_FALSE}
4313         },
4314         {
4315             {Uri_HOST_IPV6,S_OK},
4316             {80,S_OK},
4317             {URL_SCHEME_HTTP,S_OK},
4318             {URLZONE_INVALID,E_NOTIMPL}
4319         }
4320     },
4321     {   "http://google.com/",0,S_OK,FALSE,
4322         {
4323             {TRUE,"Frag","#Frag",Uri_PROPERTY_FRAGMENT,S_OK,FALSE}
4324         },
4325         {FALSE},
4326         0,S_OK,FALSE,
4327         0,S_OK,FALSE,
4328         0,0,0,S_OK,FALSE,
4329         {
4330             {"http://google.com/#Frag",S_OK},
4331             {"google.com",S_OK},
4332             {"http://google.com/#Frag",S_OK},
4333             {"google.com",S_OK},
4334             {"",S_FALSE},
4335             {"#Frag",S_OK},
4336             {"google.com",S_OK},
4337             {"",S_FALSE},
4338             {"/",S_OK},
4339             {"/",S_OK},
4340             {"",S_FALSE},
4341             {"http://google.com/#Frag",S_OK},
4342             {"http",S_OK},
4343             {"",S_FALSE},
4344             {"",S_FALSE}
4345         },
4346         {
4347             {Uri_HOST_DNS,S_OK},
4348             {80,S_OK},
4349             {URL_SCHEME_HTTP,S_OK},
4350             {URLZONE_INVALID,E_NOTIMPL}
4351         }
4352     },
4353     {   "http://google.com/",0,S_OK,FALSE,
4354         {
4355             {TRUE,"","#",Uri_PROPERTY_FRAGMENT,S_OK,FALSE},
4356         },
4357         {FALSE},
4358         0,S_OK,FALSE,
4359         0,S_OK,FALSE,
4360         0,0,0,S_OK,FALSE,
4361         {
4362             {"http://google.com/#",S_OK},
4363             {"google.com",S_OK},
4364             {"http://google.com/#",S_OK},
4365             {"google.com",S_OK},
4366             {"",S_FALSE},
4367             {"#",S_OK},
4368             {"google.com",S_OK},
4369             {"",S_FALSE},
4370             {"/",S_OK},
4371             {"/",S_OK},
4372             {"",S_FALSE},
4373             {"http://google.com/#",S_OK},
4374             {"http",S_OK},
4375             {"",S_FALSE},
4376             {"",S_FALSE}
4377         },
4378         {
4379             {Uri_HOST_DNS,S_OK},
4380             {80,S_OK},
4381             {URL_SCHEME_HTTP,S_OK},
4382             {URLZONE_INVALID,E_NOTIMPL}
4383         }
4384     },
4385     {   "http://google.com/",0,S_OK,FALSE,
4386         {
4387             {TRUE,":password",NULL,Uri_PROPERTY_PASSWORD,S_OK,FALSE}
4388         },
4389         {FALSE},
4390         0,S_OK,FALSE,
4391         0,S_OK,FALSE,
4392         0,0,0,S_OK,FALSE,
4393         {
4394             {"http://::password@google.com/",S_OK},
4395             {"::password@google.com",S_OK},
4396             {"http://google.com/",S_OK},
4397             {"google.com",S_OK},
4398             {"",S_FALSE},
4399             {"",S_FALSE},
4400             {"google.com",S_OK},
4401             {":password",S_OK},
4402             {"/",S_OK},
4403             {"/",S_OK},
4404             {"",S_FALSE},
4405             {"http://::password@google.com/",S_OK},
4406             {"http",S_OK},
4407             {"::password",S_OK},
4408             {"",S_FALSE}
4409         },
4410         {
4411             {Uri_HOST_DNS,S_OK},
4412             {80,S_OK},
4413             {URL_SCHEME_HTTP,S_OK},
4414             {URLZONE_INVALID,E_NOTIMPL}
4415         }
4416     },
4417     {   "test/test",Uri_CREATE_ALLOW_RELATIVE,S_OK,FALSE,
4418         {
4419             {TRUE,"password",NULL,Uri_PROPERTY_PASSWORD,S_OK,FALSE}
4420         },
4421         {FALSE},
4422         Uri_CREATE_ALLOW_RELATIVE,S_OK,FALSE,
4423         0,S_OK,FALSE,
4424         Uri_CREATE_ALLOW_RELATIVE,0,0,S_OK,FALSE,
4425         {
4426             {":password@test/test",S_OK},
4427             {":password@",S_OK},
4428             {":password@test/test",S_OK},
4429             {"",S_FALSE},
4430             {"",S_FALSE},
4431             {"",S_FALSE},
4432             {"",S_FALSE},
4433             {"password",S_OK},
4434             {"test/test",S_OK},
4435             {"test/test",S_OK},
4436             {"",S_FALSE},
4437             {":password@test/test",S_OK},
4438             {"",S_FALSE},
4439             {":password",S_OK},
4440             {"",S_FALSE}
4441         },
4442         {
4443             {Uri_HOST_UNKNOWN,S_OK},
4444             {0,S_FALSE},
4445             {URL_SCHEME_UNKNOWN,S_OK},
4446             {URLZONE_INVALID,E_NOTIMPL}
4447         }
4448     },
4449     {   "http://google.com/",0,S_OK,FALSE,
4450         {
4451             {TRUE,"test/test",NULL,Uri_PROPERTY_PATH,S_OK,FALSE},
4452         },
4453         {FALSE},
4454         0,S_OK,FALSE,
4455         0,S_OK,FALSE,
4456         0,0,0,S_OK,FALSE,
4457         {
4458             {"http://google.com/test/test",S_OK},
4459             {"google.com",S_OK},
4460             {"http://google.com/test/test",S_OK},
4461             {"google.com",S_OK},
4462             {"",S_FALSE},
4463             {"",S_FALSE},
4464             {"google.com",S_OK},
4465             {"",S_FALSE},
4466             {"/test/test",S_OK},
4467             {"/test/test",S_OK},
4468             {"",S_FALSE},
4469             {"http://google.com/test/test",S_OK},
4470             {"http",S_OK},
4471             {"",S_FALSE},
4472             {"",S_FALSE}
4473         },
4474         {
4475             {Uri_HOST_DNS,S_OK},
4476             {80,S_OK},
4477             {URL_SCHEME_HTTP,S_OK},
4478             {URLZONE_INVALID,E_NOTIMPL}
4479         }
4480     },
4481     {   "zip:testing/test",0,S_OK,FALSE,
4482         {
4483             {TRUE,"test",NULL,Uri_PROPERTY_PATH,S_OK,FALSE},
4484         },
4485         {FALSE},
4486         0,S_OK,FALSE,
4487         0,S_OK,FALSE,
4488         0,0,0,S_OK,FALSE,
4489         {
4490             {"zip:test",S_OK},
4491             {"",S_FALSE},
4492             {"zip:test",S_OK},
4493             {"",S_FALSE},
4494             {"",S_FALSE},
4495             {"",S_FALSE},
4496             {"",S_FALSE},
4497             {"",S_FALSE},
4498             {"test",S_OK},
4499             {"test",S_OK},
4500             {"",S_FALSE},
4501             {"zip:test",S_OK},
4502             {"zip",S_OK},
4503             {"",S_FALSE},
4504             {"",S_FALSE}
4505         },
4506         {
4507             {Uri_HOST_UNKNOWN,S_OK},
4508             {0,S_FALSE},
4509             {URL_SCHEME_UNKNOWN,S_OK},
4510             {URLZONE_INVALID,E_NOTIMPL}
4511         }
4512     },
4513     {   "http://google.com/",0,S_OK,FALSE,
4514         {
4515             {FALSE},
4516         },
4517         /* 555 will be returned from GetPort even though FALSE was passed as the hasPort parameter. */
4518         {TRUE,FALSE,555,S_OK,FALSE},
4519         0,S_OK,FALSE,
4520         0,S_OK,FALSE,
4521         0,0,0,S_OK,FALSE,
4522         {
4523             {"http://google.com/",S_OK},
4524             {"google.com",S_OK},
4525             {"http://google.com/",S_OK},
4526             {"google.com",S_OK},
4527             {"",S_FALSE},
4528             {"",S_FALSE},
4529             {"google.com",S_OK},
4530             {"",S_FALSE},
4531             {"/",S_OK},
4532             {"/",S_OK},
4533             {"",S_FALSE},
4534             {"http://google.com/",S_OK},
4535             {"http",S_OK},
4536             {"",S_FALSE},
4537             {"",S_FALSE}
4538         },
4539         {
4540             {Uri_HOST_DNS,S_OK},
4541             /* Still returns 80, even though earlier the port was disabled. */
4542             {80,S_OK},
4543             {URL_SCHEME_HTTP,S_OK},
4544             {URLZONE_INVALID,E_NOTIMPL}
4545         }
4546     },
4547     {   "http://google.com/",0,S_OK,FALSE,
4548         {
4549             {FALSE},
4550         },
4551         /* Instead of getting "TRUE" back as the "hasPort" parameter in GetPort,
4552          * you'll get 122345 instead.
4553          */
4554         {TRUE,122345,222,S_OK,FALSE},
4555         0,S_OK,FALSE,
4556         0,S_OK,FALSE,
4557         0,0,0,S_OK,FALSE,
4558         {
4559             {"http://google.com:222/",S_OK},
4560             {"google.com:222",S_OK},
4561             {"http://google.com:222/",S_OK},
4562             {"google.com",S_OK},
4563             {"",S_FALSE},
4564             {"",S_FALSE},
4565             {"google.com",S_OK},
4566             {"",S_FALSE},
4567             {"/",S_OK},
4568             {"/",S_OK},
4569             {"",S_FALSE},
4570             {"http://google.com:222/",S_OK},
4571             {"http",S_OK},
4572             {"",S_FALSE},
4573             {"",S_FALSE}
4574         },
4575         {
4576             {Uri_HOST_DNS,S_OK},
4577             {222,S_OK},
4578             {URL_SCHEME_HTTP,S_OK},
4579             {URLZONE_INVALID,E_NOTIMPL}
4580         }
4581     },
4582     /* IUri's created with the IUriBuilder can have ports that exceed USHORT_MAX. */
4583     {   "http://google.com/",0,S_OK,FALSE,
4584         {
4585             {FALSE},
4586         },
4587         {TRUE,TRUE,999999,S_OK,FALSE},
4588         0,S_OK,FALSE,
4589         0,S_OK,FALSE,
4590         0,0,0,S_OK,FALSE,
4591         {
4592             {"http://google.com:999999/",S_OK},
4593             {"google.com:999999",S_OK},
4594             {"http://google.com:999999/",S_OK},
4595             {"google.com",S_OK},
4596             {"",S_FALSE},
4597             {"",S_FALSE},
4598             {"google.com",S_OK},
4599             {"",S_FALSE},
4600             {"/",S_OK},
4601             {"/",S_OK},
4602             {"",S_FALSE},
4603             {"http://google.com:999999/",S_OK},
4604             {"http",S_OK},
4605             {"",S_FALSE},
4606             {"",S_FALSE}
4607         },
4608         {
4609             {Uri_HOST_DNS,S_OK},
4610             {999999,S_OK},
4611             {URL_SCHEME_HTTP,S_OK},
4612             {URLZONE_INVALID,E_NOTIMPL}
4613         }
4614     },
4615     {   "http://google.com/",0,S_OK,FALSE,
4616         {
4617             {TRUE,"test","?test",Uri_PROPERTY_QUERY,S_OK,FALSE},
4618         },
4619
4620         {FALSE},
4621         0,S_OK,FALSE,
4622         0,S_OK,FALSE,
4623         0,0,0,S_OK,FALSE,
4624         {
4625             {"http://google.com/?test",S_OK},
4626             {"google.com",S_OK},
4627             {"http://google.com/?test",S_OK},
4628             {"google.com",S_OK},
4629             {"",S_FALSE},
4630             {"",S_FALSE},
4631             {"google.com",S_OK},
4632             {"",S_FALSE},
4633             {"/",S_OK},
4634             {"/?test",S_OK},
4635             {"?test",S_OK},
4636             {"http://google.com/?test",S_OK},
4637             {"http",S_OK},
4638             {"",S_FALSE},
4639             {"",S_FALSE}
4640         },
4641         {
4642             {Uri_HOST_DNS,S_OK},
4643             {80,S_OK},
4644             {URL_SCHEME_HTTP,S_OK},
4645             {URLZONE_INVALID,E_NOTIMPL}
4646         }
4647     },
4648     {   "http://:password@google.com/",0,S_OK,FALSE,
4649         {
4650             {FALSE},
4651         },
4652         {FALSE},
4653         0,S_OK,FALSE,
4654         0,S_OK,FALSE,
4655         0,0,0,S_OK,FALSE,
4656         {
4657             {"http://:password@google.com/",S_OK},
4658             {":password@google.com",S_OK},
4659             {"http://google.com/",S_OK},
4660             {"google.com",S_OK},
4661             {"",S_FALSE},
4662             {"",S_FALSE},
4663             {"google.com",S_OK},
4664             {"password",S_OK},
4665             {"/",S_OK},
4666             {"/",S_OK},
4667             {"",S_FALSE},
4668             {"http://:password@google.com/",S_OK},
4669             {"http",S_OK},
4670             {":password",S_OK},
4671             {"",S_FALSE}
4672         },
4673         {
4674             {Uri_HOST_DNS,S_OK},
4675             {80,S_OK},
4676             {URL_SCHEME_HTTP,S_OK},
4677             {URLZONE_INVALID,E_NOTIMPL}
4678         }
4679     },
4680     /* IUriBuilder doesn't need a base IUri to build a IUri. */
4681     {   NULL,0,S_OK,FALSE,
4682         {
4683             {TRUE,"http",NULL,Uri_PROPERTY_SCHEME_NAME,S_OK,FALSE},
4684             {TRUE,"google.com",NULL,Uri_PROPERTY_HOST,S_OK,FALSE}
4685         },
4686         {FALSE},
4687         0,S_OK,FALSE,
4688         0,S_OK,FALSE,
4689         0,0,0,S_OK,FALSE,
4690         {
4691             {"http://google.com/",S_OK},
4692             {"google.com",S_OK},
4693             {"http://google.com/",S_OK},
4694             {"google.com",S_OK},
4695             {"",S_FALSE},
4696             {"",S_FALSE},
4697             {"google.com",S_OK},
4698             {"",S_FALSE},
4699             {"/",S_OK},
4700             {"/",S_OK},
4701             {"",S_FALSE},
4702             {"http://google.com/",S_OK},
4703             {"http",S_OK},
4704             {"",S_FALSE},
4705             {"",S_FALSE}
4706         },
4707         {
4708             {Uri_HOST_DNS,S_OK},
4709             {80,S_OK},
4710             {URL_SCHEME_HTTP,S_OK},
4711             {URLZONE_INVALID,E_NOTIMPL}
4712         }
4713     },
4714     /* Can't set the scheme name to NULL. */
4715     {   "zip://google.com/",0,S_OK,FALSE,
4716         {
4717             {TRUE,NULL,"zip",Uri_PROPERTY_SCHEME_NAME,E_INVALIDARG,FALSE}
4718         },
4719         {FALSE},
4720         0,S_OK,FALSE,
4721         0,S_OK,FALSE,
4722         0,0,0,S_OK,FALSE,
4723         {
4724             {"zip://google.com/",S_OK},
4725             {"google.com",S_OK},
4726             {"zip://google.com/",S_OK},
4727             {"google.com",S_OK},
4728             {"",S_FALSE},
4729             {"",S_FALSE},
4730             {"google.com",S_OK},
4731             {"",S_FALSE},
4732             {"/",S_OK},
4733             {"/",S_OK},
4734             {"",S_FALSE},
4735             {"zip://google.com/",S_OK},
4736             {"zip",S_OK},
4737             {"",S_FALSE},
4738             {"",S_FALSE}
4739         },
4740         {
4741             {Uri_HOST_DNS,S_OK},
4742             {0,S_FALSE},
4743             {URL_SCHEME_UNKNOWN,S_OK},
4744             {URLZONE_INVALID,E_NOTIMPL}
4745         }
4746     },
4747     /* Can't set the scheme name to an empty string. */
4748     {   "zip://google.com/",0,S_OK,FALSE,
4749         {
4750             {TRUE,"","zip",Uri_PROPERTY_SCHEME_NAME,E_INVALIDARG,FALSE}
4751         },
4752         {FALSE},
4753         0,S_OK,FALSE,
4754         0,S_OK,FALSE,
4755         0,0,0,S_OK,FALSE,
4756         {
4757             {"zip://google.com/",S_OK},
4758             {"google.com",S_OK},
4759             {"zip://google.com/",S_OK},
4760             {"google.com",S_OK},
4761             {"",S_FALSE},
4762             {"",S_FALSE},
4763             {"google.com",S_OK},
4764             {"",S_FALSE},
4765             {"/",S_OK},
4766             {"/",S_OK},
4767             {"",S_FALSE},
4768             {"zip://google.com/",S_OK},
4769             {"zip",S_OK},
4770             {"",S_FALSE},
4771             {"",S_FALSE}
4772         },
4773         {
4774             {Uri_HOST_DNS,S_OK},
4775             {0,S_FALSE},
4776             {URL_SCHEME_UNKNOWN,S_OK},
4777             {URLZONE_INVALID,E_NOTIMPL}
4778         }
4779     },
4780     /* -1 to CreateUri makes it use the same flags as the base IUri was created with.
4781      * CreateUriSimple always uses the flags the base IUri was created with (if any).
4782      */
4783     {   "http://google.com/../../",Uri_CREATE_NO_CANONICALIZE,S_OK,FALSE,
4784         {{FALSE}},
4785         {FALSE},
4786         -1,S_OK,FALSE,
4787         0,S_OK,FALSE,
4788         0,UriBuilder_USE_ORIGINAL_FLAGS,0,S_OK,FALSE,
4789         {
4790             {"http://google.com/../../",S_OK},
4791             {"google.com",S_OK},
4792             {"http://google.com/../../",S_OK},
4793             {"google.com",S_OK},
4794             {"",S_FALSE},
4795             {"",S_FALSE},
4796             {"google.com",S_OK},
4797             {"",S_FALSE},
4798             {"/../../",S_OK},
4799             {"/../../",S_OK},
4800             {"",S_FALSE},
4801             {"http://google.com/../../",S_OK},
4802             {"http",S_OK},
4803             {"",S_FALSE},
4804             {"",S_FALSE}
4805         },
4806         {
4807             {Uri_HOST_DNS,S_OK},
4808             {80,S_OK},
4809             {URL_SCHEME_HTTP,S_OK},
4810             {URLZONE_INVALID,E_NOTIMPL}
4811         }
4812     },
4813     {   "http://google.com/",0,S_OK,FALSE,
4814         {
4815             {TRUE,"#Fr<|>g",NULL,Uri_PROPERTY_FRAGMENT,S_OK,FALSE}
4816         },
4817         {FALSE},
4818         -1,S_OK,FALSE,
4819         0,S_OK,FALSE,
4820         Uri_CREATE_NO_DECODE_EXTRA_INFO,UriBuilder_USE_ORIGINAL_FLAGS,0,S_OK,FALSE,
4821         {
4822             {"http://google.com/#Fr%3C%7C%3Eg",S_OK},
4823             {"google.com",S_OK},
4824             {"http://google.com/#Fr%3C%7C%3Eg",S_OK},
4825             {"google.com",S_OK},
4826             {"",S_FALSE},
4827             {"#Fr%3C%7C%3Eg",S_OK},
4828             {"google.com",S_OK},
4829             {"",S_FALSE},
4830             {"/",S_OK},
4831             {"/",S_OK},
4832             {"",S_FALSE},
4833             {"http://google.com/#Fr<|>g",S_OK},
4834             {"http",S_OK},
4835             {"",S_FALSE},
4836             {"",S_FALSE}
4837         },
4838         {
4839             {Uri_HOST_DNS,S_OK},
4840             {80,S_OK},
4841             {URL_SCHEME_HTTP,S_OK},
4842             {URLZONE_INVALID,E_NOTIMPL}
4843         }
4844     },
4845     {   "http://google.com/",0,S_OK,FALSE,
4846         {
4847             {TRUE,"#Fr<|>g",NULL,Uri_PROPERTY_FRAGMENT,S_OK,FALSE}
4848         },
4849         {FALSE},
4850         Uri_CREATE_CANONICALIZE|Uri_CREATE_NO_CANONICALIZE,E_INVALIDARG,FALSE,
4851         0,S_OK,FALSE,
4852         Uri_CREATE_CANONICALIZE|Uri_CREATE_NO_CANONICALIZE,UriBuilder_USE_ORIGINAL_FLAGS,0,S_OK,FALSE,
4853         {
4854             {"http://google.com/#Fr%3C%7C%3Eg",S_OK},
4855             {"google.com",S_OK},
4856             {"http://google.com/#Fr%3C%7C%3Eg",S_OK},
4857             {"google.com",S_OK},
4858             {"",S_FALSE},
4859             {"#Fr%3C%7C%3Eg",S_OK},
4860             {"google.com",S_OK},
4861             {"",S_FALSE},
4862             {"/",S_OK},
4863             {"/",S_OK},
4864             {"",S_FALSE},
4865             {"http://google.com/#Fr<|>g",S_OK},
4866             {"http",S_OK},
4867             {"",S_FALSE},
4868             {"",S_FALSE}
4869         },
4870         {
4871             {Uri_HOST_DNS,S_OK},
4872             {80,S_OK},
4873             {URL_SCHEME_HTTP,S_OK},
4874             {URLZONE_INVALID,E_NOTIMPL}
4875         }
4876     },
4877     {   NULL,0,S_OK,FALSE,
4878         {
4879             {TRUE,"/test/test/",NULL,Uri_PROPERTY_PATH,S_OK,FALSE},
4880             {TRUE,"#Fr<|>g",NULL,Uri_PROPERTY_FRAGMENT,S_OK,FALSE}
4881         },
4882         {FALSE},
4883         0,INET_E_INVALID_URL,FALSE,
4884         0,INET_E_INVALID_URL,FALSE,
4885         0,0,0,INET_E_INVALID_URL,FALSE
4886     },
4887     {   "http://google.com/",0,S_OK,FALSE,
4888         {
4889             {TRUE,"ht%xxtp",NULL,Uri_PROPERTY_SCHEME_NAME,S_OK,FALSE}
4890         },
4891         {FALSE},
4892         0,INET_E_INVALID_URL,FALSE,
4893         0,INET_E_INVALID_URL,FALSE,
4894         0,0,0,INET_E_INVALID_URL,FALSE
4895     },
4896     /* File scheme's can't have a username set. */
4897     {   "file://google.com/",0,S_OK,FALSE,
4898         {
4899             {TRUE,"username",NULL,Uri_PROPERTY_USER_NAME,S_OK,FALSE}
4900         },
4901         {FALSE},
4902         0,INET_E_INVALID_URL,FALSE,
4903         0,INET_E_INVALID_URL,FALSE,
4904         0,0,0,INET_E_INVALID_URL,FALSE
4905     },
4906     /* File schemes can't have a password set. */
4907     {   "file://google.com/",0,S_OK,FALSE,
4908         {
4909             {TRUE,"password",NULL,Uri_PROPERTY_PASSWORD,S_OK,FALSE}
4910         },
4911         {FALSE},
4912         0,INET_E_INVALID_URL,FALSE,
4913         0,INET_E_INVALID_URL,FALSE,
4914         0,0,0,INET_E_INVALID_URL,FALSE
4915     },
4916     /* UserName can't contain any character that is a delimeter for another
4917      * component that appears after it in a normal URI.
4918      */
4919     {   "http://google.com/",0,S_OK,FALSE,
4920         {
4921             {TRUE,"user:pass",NULL,Uri_PROPERTY_USER_NAME,S_OK,FALSE}
4922         },
4923         {FALSE},
4924         0,INET_E_INVALID_URL,FALSE,
4925         0,INET_E_INVALID_URL,FALSE,
4926         0,0,0,INET_E_INVALID_URL,FALSE
4927     },
4928     {   "http://google.com/",0,S_OK,FALSE,
4929         {
4930             {TRUE,"user@google.com",NULL,Uri_PROPERTY_USER_NAME,S_OK,FALSE}
4931         },
4932         {FALSE},
4933         0,INET_E_INVALID_URL,FALSE,
4934         0,INET_E_INVALID_URL,FALSE,
4935         0,0,0,INET_E_INVALID_URL,FALSE
4936     },
4937     {   "http://google.com/",0,S_OK,FALSE,
4938         {
4939             {TRUE,"user/path",NULL,Uri_PROPERTY_USER_NAME,S_OK,FALSE}
4940         },
4941         {FALSE},
4942         0,INET_E_INVALID_URL,FALSE,
4943         0,INET_E_INVALID_URL,FALSE,
4944         0,0,0,INET_E_INVALID_URL,FALSE
4945     },
4946     {   "http://google.com/",0,S_OK,FALSE,
4947         {
4948             {TRUE,"user?Query",NULL,Uri_PROPERTY_USER_NAME,S_OK,FALSE}
4949         },
4950         {FALSE},
4951         0,INET_E_INVALID_URL,FALSE,
4952         0,INET_E_INVALID_URL,FALSE,
4953         0,0,0,INET_E_INVALID_URL,FALSE
4954     },
4955     {   "http://google.com/",0,S_OK,FALSE,
4956         {
4957             {TRUE,"user#Frag",NULL,Uri_PROPERTY_USER_NAME,S_OK,FALSE}
4958         },
4959         {FALSE},
4960         0,INET_E_INVALID_URL,FALSE,
4961         0,INET_E_INVALID_URL,FALSE,
4962         0,0,0,INET_E_INVALID_URL,FALSE
4963     },
4964     {   "http://google.com/",0,S_OK,FALSE,
4965         {
4966             {TRUE,"pass@google.com",NULL,Uri_PROPERTY_PASSWORD,S_OK,FALSE}
4967         },
4968         {FALSE},
4969         0,INET_E_INVALID_URL,FALSE,
4970         0,INET_E_INVALID_URL,FALSE,
4971         0,0,0,INET_E_INVALID_URL,FALSE
4972     },
4973     {   "http://google.com/",0,S_OK,FALSE,
4974         {
4975             {TRUE,"pass/path",NULL,Uri_PROPERTY_PASSWORD,S_OK,FALSE}
4976         },
4977         {FALSE},
4978         0,INET_E_INVALID_URL,FALSE,
4979         0,INET_E_INVALID_URL,FALSE,
4980         0,0,0,INET_E_INVALID_URL,FALSE
4981     },
4982     {   "http://google.com/",0,S_OK,FALSE,
4983         {
4984             {TRUE,"pass?query",NULL,Uri_PROPERTY_PASSWORD,S_OK,FALSE}
4985         },
4986         {FALSE},
4987         0,INET_E_INVALID_URL,FALSE,
4988         0,INET_E_INVALID_URL,FALSE,
4989        0,0,0,INET_E_INVALID_URL,FALSE
4990     },
4991     {   "http://google.com/",0,S_OK,FALSE,
4992         {
4993             {TRUE,"pass#frag",NULL,Uri_PROPERTY_PASSWORD,S_OK,FALSE}
4994         },
4995         {FALSE},
4996         0,INET_E_INVALID_URL,FALSE,
4997         0,INET_E_INVALID_URL,FALSE,
4998         0,0,0,INET_E_INVALID_URL,FALSE
4999     },
5000     {   "http://google.com/",0,S_OK,FALSE,
5001         {
5002             {TRUE,"winehq.org/test",NULL,Uri_PROPERTY_HOST,S_OK,FALSE}
5003         },
5004         {FALSE},
5005         0,INET_E_INVALID_URL,FALSE,
5006         0,INET_E_INVALID_URL,FALSE,
5007         0,0,0,INET_E_INVALID_URL,FALSE
5008     },
5009     {   "http://google.com/",0,S_OK,FALSE,
5010         {
5011             {TRUE,"winehq.org?test",NULL,Uri_PROPERTY_HOST,S_OK,FALSE}
5012         },
5013         {FALSE},
5014         0,INET_E_INVALID_URL,FALSE,
5015         0,INET_E_INVALID_URL,FALSE,
5016         0,0,0,INET_E_INVALID_URL,FALSE
5017     },
5018     {   "http://google.com/",0,S_OK,FALSE,
5019         {
5020             {TRUE,"winehq.org#test",NULL,Uri_PROPERTY_HOST,S_OK,FALSE}
5021         },
5022         {FALSE},
5023         0,INET_E_INVALID_URL,FALSE,
5024         0,INET_E_INVALID_URL,FALSE,
5025         0,0,0,INET_E_INVALID_URL,FALSE
5026     },
5027     /* Hostname is allowed to contain a ':' (even for known scheme types). */
5028     {   "http://google.com/",0,S_OK,FALSE,
5029         {
5030             {TRUE,"winehq.org:test",NULL,Uri_PROPERTY_HOST,S_OK,FALSE},
5031         },
5032         {FALSE},
5033         0,S_OK,FALSE,
5034         0,S_OK,FALSE,
5035         0,0,0,S_OK,FALSE,
5036         {
5037             {"http://winehq.org:test/",S_OK},
5038             {"winehq.org:test",S_OK},
5039             {"http://winehq.org:test/",S_OK},
5040             {"winehq.org:test",S_OK},
5041             {"",S_FALSE},
5042             {"",S_FALSE},
5043             {"winehq.org:test",S_OK},
5044             {"",S_FALSE},
5045             {"/",S_OK},
5046             {"/",S_OK},
5047             {"",S_FALSE},
5048             {"http://winehq.org:test/",S_OK},
5049             {"http",S_OK},
5050             {"",S_FALSE},
5051             {"",S_FALSE}
5052         },
5053         {
5054             {Uri_HOST_DNS,S_OK},
5055             {80,S_OK},
5056             {URL_SCHEME_HTTP,S_OK},
5057             {URLZONE_INVALID,E_NOTIMPL}
5058         }
5059     },
5060     /* Can't set the host name to NULL. */
5061     {   "http://google.com/",0,S_OK,FALSE,
5062         {
5063             {TRUE,NULL,"google.com",Uri_PROPERTY_HOST,E_INVALIDARG,FALSE}
5064         },
5065         {FALSE},
5066         0,S_OK,FALSE,
5067         0,S_OK,FALSE,
5068         0,0,0,S_OK,FALSE,
5069         {
5070             {"http://google.com/",S_OK},
5071             {"google.com",S_OK},
5072             {"http://google.com/",S_OK},
5073             {"google.com",S_OK},
5074             {"",S_FALSE},
5075             {"",S_FALSE},
5076             {"google.com",S_OK},
5077             {"",S_FALSE},
5078             {"/",S_OK},
5079             {"/",S_OK},
5080             {"",S_FALSE},
5081             {"http://google.com/",S_OK},
5082             {"http",S_OK},
5083             {"",S_FALSE},
5084             {"",S_FALSE}
5085         },
5086         {
5087             {Uri_HOST_DNS,S_OK},
5088             {80,S_OK},
5089             {URL_SCHEME_HTTP,S_OK},
5090             {URLZONE_INVALID,E_NOTIMPL}
5091         }
5092     },
5093     /* Can set the host name to an empty string. */
5094     {   "http://google.com/",0,S_OK,FALSE,
5095         {
5096             {TRUE,"",NULL,Uri_PROPERTY_HOST,S_OK,FALSE}
5097         },
5098         {FALSE},
5099         0,S_OK,FALSE,
5100         0,S_OK,FALSE,
5101         0,0,0,S_OK,FALSE,
5102         {
5103             {"http:///",S_OK},
5104             {"",S_OK},
5105             {"http:///",S_OK},
5106             {"",S_FALSE},
5107             {"",S_FALSE},
5108             {"",S_FALSE},
5109             {"",S_OK},
5110             {"",S_FALSE},
5111             {"/",S_OK},
5112             {"/",S_OK},
5113             {"",S_FALSE},
5114             {"http:///",S_OK},
5115             {"http",S_OK},
5116             {"",S_FALSE},
5117             {"",S_FALSE}
5118         },
5119         {
5120             {Uri_HOST_UNKNOWN,S_OK},
5121             {80,S_OK},
5122             {URL_SCHEME_HTTP,S_OK},
5123             {URLZONE_INVALID,E_NOTIMPL}
5124         }
5125     },
5126     {   "http://google.com/",0,S_OK,FALSE,
5127         {
5128             {TRUE,"/path?query",NULL,Uri_PROPERTY_PATH,S_OK,FALSE}
5129         },
5130         {FALSE},
5131         0,INET_E_INVALID_URL,FALSE,
5132         0,INET_E_INVALID_URL,FALSE,
5133         0,0,0,INET_E_INVALID_URL,FALSE
5134     },
5135     {   "http://google.com/",0,S_OK,FALSE,
5136         {
5137             {TRUE,"/path#test",NULL,Uri_PROPERTY_PATH,S_OK,FALSE}
5138         },
5139         {FALSE},
5140         0,INET_E_INVALID_URL,FALSE,
5141         0,INET_E_INVALID_URL,FALSE,
5142         0,0,0,INET_E_INVALID_URL,FALSE
5143     },
5144     {   "http://google.com/",0,S_OK,FALSE,
5145         {
5146             {TRUE,"?path#test",NULL,Uri_PROPERTY_QUERY,S_OK,FALSE}
5147         },
5148         {FALSE},
5149         0,INET_E_INVALID_URL,FALSE,
5150         0,INET_E_INVALID_URL,FALSE,
5151         0,0,0,INET_E_INVALID_URL,FALSE
5152     }
5153 };
5154
5155 typedef struct _uri_builder_remove_test {
5156     const char  *uri;
5157     DWORD       create_flags;
5158     HRESULT     create_builder_expected;
5159     BOOL        create_builder_todo;
5160
5161     DWORD       remove_properties;
5162     HRESULT     remove_expected;
5163     BOOL        remove_todo;
5164
5165     const char  *expected_uri;
5166     DWORD       expected_flags;
5167     HRESULT     expected_hres;
5168     BOOL        expected_todo;
5169 } uri_builder_remove_test;
5170
5171 static const uri_builder_remove_test uri_builder_remove_tests[] = {
5172     {   "http://google.com/test?test=y#Frag",0,S_OK,FALSE,
5173         Uri_HAS_FRAGMENT|Uri_HAS_PATH|Uri_HAS_QUERY,S_OK,FALSE,
5174         "http://google.com/",0,S_OK,FALSE
5175     },
5176     {   "http://user:pass@winehq.org/",0,S_OK,FALSE,
5177         Uri_HAS_USER_NAME|Uri_HAS_PASSWORD,S_OK,FALSE,
5178         "http://winehq.org/",0,S_OK,FALSE
5179     },
5180     {   "zip://google.com?Test=x",0,S_OK,FALSE,
5181         Uri_HAS_HOST,S_OK,FALSE,
5182         "zip:/?Test=x",0,S_OK,FALSE
5183     },
5184     /* Doesn't remove the whole userinfo component. */
5185     {   "http://username:pass@google.com/",0,S_OK,FALSE,
5186         Uri_HAS_USER_INFO,S_OK,FALSE,
5187         "http://username:pass@google.com/",0,S_OK,FALSE
5188     },
5189     /* Doesn't remove the domain. */
5190     {   "http://google.com/",0,S_OK,FALSE,
5191         Uri_HAS_DOMAIN,S_OK,FALSE,
5192         "http://google.com/",0,S_OK,FALSE
5193     },
5194     {   "http://google.com:120/",0,S_OK,FALSE,
5195         Uri_HAS_AUTHORITY,S_OK,FALSE,
5196         "http://google.com:120/",0,S_OK,FALSE
5197     },
5198     {   "http://google.com/test.com/",0,S_OK,FALSE,
5199         Uri_HAS_EXTENSION,S_OK,FALSE,
5200         "http://google.com/test.com/",0,S_OK,FALSE
5201     },
5202     {   "http://google.com/?test=x",0,S_OK,FALSE,
5203         Uri_HAS_PATH_AND_QUERY,S_OK,FALSE,
5204         "http://google.com/?test=x",0,S_OK,FALSE
5205     },
5206     /* Can't remove the scheme name. */
5207     {   "http://google.com/?test=x",0,S_OK,FALSE,
5208         Uri_HAS_SCHEME_NAME|Uri_HAS_QUERY,E_INVALIDARG,FALSE,
5209         "http://google.com/?test=x",0,S_OK,FALSE
5210     }
5211 };
5212
5213 typedef struct _uri_combine_str_property {
5214     const char  *value;
5215     HRESULT     expected;
5216     BOOL        todo;
5217     const char  *broken_value;
5218     const char  *value_ex;
5219 } uri_combine_str_property;
5220
5221 typedef struct _uri_combine_test {
5222     const char  *base_uri;
5223     DWORD       base_create_flags;
5224     const char  *relative_uri;
5225     DWORD       relative_create_flags;
5226     DWORD       combine_flags;
5227     HRESULT     expected;
5228     BOOL        todo;
5229
5230     uri_combine_str_property    str_props[URI_STR_PROPERTY_COUNT];
5231     uri_dword_property          dword_props[URI_DWORD_PROPERTY_COUNT];
5232 } uri_combine_test;
5233
5234 static const uri_combine_test uri_combine_tests[] = {
5235     {   "http://google.com/fun/stuff",0,
5236         "../not/fun/stuff",Uri_CREATE_ALLOW_RELATIVE,
5237         0,S_OK,FALSE,
5238         {
5239             {"http://google.com/not/fun/stuff",S_OK},
5240             {"google.com",S_OK},
5241             {"http://google.com/not/fun/stuff",S_OK},
5242             {"google.com",S_OK},
5243             {"",S_FALSE},
5244             {"",S_FALSE},
5245             {"google.com",S_OK},
5246             {"",S_FALSE},
5247             {"/not/fun/stuff",S_OK},
5248             {"/not/fun/stuff",S_OK},
5249             {"",S_FALSE},
5250             {"http://google.com/not/fun/stuff",S_OK},
5251             {"http",S_OK},
5252             {"",S_FALSE},
5253             {"",S_FALSE}
5254         },
5255         {
5256             {Uri_HOST_DNS,S_OK},
5257             {80,S_OK},
5258             {URL_SCHEME_HTTP,S_OK},
5259             {URLZONE_INVALID,E_NOTIMPL}
5260         }
5261     },
5262     {   "http://google.com/test",0,
5263         "zip://test.com/cool",0,
5264         0,S_OK,FALSE,
5265         {
5266             {"zip://test.com/cool",S_OK},
5267             {"test.com",S_OK},
5268             {"zip://test.com/cool",S_OK},
5269             {"test.com",S_OK},
5270             {"",S_FALSE},
5271             {"",S_FALSE},
5272             {"test.com",S_OK},
5273             {"",S_FALSE},
5274             {"/cool",S_OK},
5275             {"/cool",S_OK},
5276             {"",S_FALSE},
5277             {"zip://test.com/cool",S_OK},
5278             {"zip",S_OK},
5279             {"",S_FALSE},
5280             {"",S_FALSE}
5281         },
5282         {
5283             {Uri_HOST_DNS,S_OK},
5284             {0,S_FALSE},
5285             {URL_SCHEME_UNKNOWN,S_OK},
5286             {URLZONE_INVALID,E_NOTIMPL}
5287         }
5288     },
5289     {   "http://google.com/use/base/path",0,
5290         "?relative",Uri_CREATE_ALLOW_RELATIVE,
5291         0,S_OK,FALSE,
5292         {
5293             {"http://google.com/use/base/path?relative",S_OK},
5294             {"google.com",S_OK},
5295             {"http://google.com/use/base/path?relative",S_OK},
5296             {"google.com",S_OK},
5297             {"",S_FALSE},
5298             {"",S_FALSE},
5299             {"google.com",S_OK},
5300             {"",S_FALSE},
5301             {"/use/base/path",S_OK},
5302             {"/use/base/path?relative",S_OK},
5303             {"?relative",S_OK},
5304             {"http://google.com/use/base/path?relative",S_OK},
5305             {"http",S_OK},
5306             {"",S_FALSE},
5307             {"",S_FALSE}
5308         },
5309         {
5310             {Uri_HOST_DNS,S_OK},
5311             {80,S_OK},
5312             {URL_SCHEME_HTTP,S_OK},
5313             {URLZONE_INVALID,E_NOTIMPL}
5314         }
5315     },
5316     {   "http://google.com/path",0,
5317         "/test/../test/.././testing",Uri_CREATE_ALLOW_RELATIVE,
5318         0,S_OK,FALSE,
5319         {
5320             {"http://google.com/testing",S_OK},
5321             {"google.com",S_OK},
5322             {"http://google.com/testing",S_OK},
5323             {"google.com",S_OK},
5324             {"",S_FALSE},
5325             {"",S_FALSE},
5326             {"google.com",S_OK},
5327             {"",S_FALSE},
5328             {"/testing",S_OK},
5329             {"/testing",S_OK},
5330             {"",S_FALSE},
5331             {"http://google.com/testing",S_OK},
5332             {"http",S_OK},
5333             {"",S_FALSE},
5334             {"",S_FALSE}
5335         },
5336         {
5337             {Uri_HOST_DNS,S_OK},
5338             {80,S_OK},
5339             {URL_SCHEME_HTTP,S_OK},
5340             {URLZONE_INVALID,E_NOTIMPL}
5341         }
5342     },
5343     {   "http://google.com/path",0,
5344         "/test/../test/.././testing",Uri_CREATE_ALLOW_RELATIVE,
5345         URL_DONT_SIMPLIFY,S_OK,FALSE,
5346         {
5347             {"http://google.com:80/test/../test/.././testing",S_OK},
5348             {"google.com",S_OK},
5349             {"http://google.com:80/test/../test/.././testing",S_OK},
5350             {"google.com",S_OK},
5351             {"",S_FALSE},
5352             {"",S_FALSE},
5353             {"google.com",S_OK},
5354             {"",S_FALSE},
5355             {"/test/../test/.././testing",S_OK},
5356             {"/test/../test/.././testing",S_OK},
5357             {"",S_FALSE},
5358             {"http://google.com:80/test/../test/.././testing",S_OK},
5359             {"http",S_OK},
5360             {"",S_FALSE},
5361             {"",S_FALSE}
5362         },
5363         {
5364             {Uri_HOST_DNS,S_OK},
5365             {80,S_OK},
5366             {URL_SCHEME_HTTP,S_OK},
5367             {URLZONE_INVALID,E_NOTIMPL}
5368         }
5369     },
5370     {   "http://winehq.org/test/abc",0,
5371         "testing/abc/../test",Uri_CREATE_ALLOW_RELATIVE,
5372         0,S_OK,FALSE,
5373         {
5374             {"http://winehq.org/test/testing/test",S_OK},
5375             {"winehq.org",S_OK},
5376             {"http://winehq.org/test/testing/test",S_OK},
5377             {"winehq.org",S_OK},
5378             {"",S_FALSE},
5379             {"",S_FALSE},
5380             {"winehq.org",S_OK},
5381             {"",S_FALSE},
5382             {"/test/testing/test",S_OK},
5383             {"/test/testing/test",S_OK},
5384             {"",S_FALSE},
5385             {"http://winehq.org/test/testing/test",S_OK},
5386             {"http",S_OK},
5387             {"",S_FALSE},
5388             {"",S_FALSE}
5389         },
5390         {
5391             {Uri_HOST_DNS,S_OK},
5392             {80,S_OK},
5393             {URL_SCHEME_HTTP,S_OK},
5394             {URLZONE_INVALID,E_NOTIMPL}
5395         }
5396     },
5397     {   "http://winehq.org/test/abc",0,
5398         "testing/abc/../test",Uri_CREATE_ALLOW_RELATIVE,
5399         URL_DONT_SIMPLIFY,S_OK,FALSE,
5400         {
5401             {"http://winehq.org:80/test/testing/abc/../test",S_OK},
5402             /* Default port is hidden in the authority. */
5403             {"winehq.org",S_OK},
5404             {"http://winehq.org:80/test/testing/abc/../test",S_OK},
5405             {"winehq.org",S_OK},
5406             {"",S_FALSE},
5407             {"",S_FALSE},
5408             {"winehq.org",S_OK},
5409             {"",S_FALSE},
5410             {"/test/testing/abc/../test",S_OK},
5411             {"/test/testing/abc/../test",S_OK},
5412             {"",S_FALSE},
5413             {"http://winehq.org:80/test/testing/abc/../test",S_OK},
5414             {"http",S_OK},
5415             {"",S_FALSE},
5416             {"",S_FALSE}
5417         },
5418         {
5419             {Uri_HOST_DNS,S_OK},
5420             {80,S_OK},
5421             {URL_SCHEME_HTTP,S_OK},
5422             {URLZONE_INVALID,E_NOTIMPL}
5423         }
5424     },
5425     {   "http://winehq.org/test?query",0,
5426         "testing",Uri_CREATE_ALLOW_RELATIVE,
5427         0,S_OK,FALSE,
5428         {
5429             {"http://winehq.org/testing",S_OK},
5430             {"winehq.org",S_OK},
5431             {"http://winehq.org/testing",S_OK},
5432             {"winehq.org",S_OK},
5433             {"",S_FALSE},
5434             {"",S_FALSE},
5435             {"winehq.org",S_OK},
5436             {"",S_FALSE},
5437             {"/testing",S_OK},
5438             {"/testing",S_OK},
5439             {"",S_FALSE},
5440             {"http://winehq.org/testing",S_OK},
5441             {"http",S_OK},
5442             {"",S_FALSE},
5443             {"",S_FALSE}
5444         },
5445         {
5446             {Uri_HOST_DNS,S_OK},
5447             {80,S_OK},
5448             {URL_SCHEME_HTTP,S_OK},
5449             {URLZONE_INVALID,E_NOTIMPL}
5450         }
5451     },
5452     {   "http://winehq.org/test#frag",0,
5453         "testing",Uri_CREATE_ALLOW_RELATIVE,
5454         0,S_OK,FALSE,
5455         {
5456             {"http://winehq.org/testing",S_OK},
5457             {"winehq.org",S_OK},
5458             {"http://winehq.org/testing",S_OK},
5459             {"winehq.org",S_OK},
5460             {"",S_FALSE},
5461             {"",S_FALSE},
5462             {"winehq.org",S_OK},
5463             {"",S_FALSE},
5464             {"/testing",S_OK},
5465             {"/testing",S_OK},
5466             {"",S_FALSE},
5467             {"http://winehq.org/testing",S_OK},
5468             {"http",S_OK},
5469             {"",S_FALSE},
5470             {"",S_FALSE}
5471         },
5472         {
5473             {Uri_HOST_DNS,S_OK},
5474             {80,S_OK},
5475             {URL_SCHEME_HTTP,S_OK},
5476             {URLZONE_INVALID,E_NOTIMPL}
5477         }
5478     },
5479     {   "testing?query#frag",Uri_CREATE_ALLOW_RELATIVE,
5480         "test",Uri_CREATE_ALLOW_RELATIVE,
5481         0,S_OK,FALSE,
5482         {
5483             {"test",S_OK},
5484             {"",S_FALSE},
5485             {"test",S_OK},
5486             {"",S_FALSE},
5487             {"",S_FALSE},
5488             {"",S_FALSE},
5489             {"",S_FALSE},
5490             {"",S_FALSE},
5491             {"test",S_OK},
5492             {"test",S_OK},
5493             {"",S_FALSE},
5494             {"test",S_OK},
5495             {"",S_FALSE},
5496             {"",S_FALSE},
5497             {"",S_FALSE}
5498         },
5499         {
5500             {Uri_HOST_UNKNOWN,S_OK},
5501             {0,S_FALSE},
5502             {URL_SCHEME_UNKNOWN,S_OK},
5503             {URLZONE_INVALID,E_NOTIMPL}
5504         }
5505     },
5506     {   "file:///c:/test/test",0,
5507         "/testing.mp3",Uri_CREATE_ALLOW_RELATIVE,
5508         URL_FILE_USE_PATHURL,S_OK,FALSE,
5509         {
5510             {"file://c:\\testing.mp3",S_OK},
5511             {"",S_FALSE},
5512             {"file://c:\\testing.mp3",S_OK},
5513             {"",S_FALSE},
5514             {".mp3",S_OK},
5515             {"",S_FALSE},
5516             {"",S_FALSE},
5517             {"",S_FALSE},
5518             {"c:\\testing.mp3",S_OK},
5519             {"c:\\testing.mp3",S_OK},
5520             {"",S_FALSE},
5521             {"file://c:\\testing.mp3",S_OK},
5522             {"file",S_OK},
5523             {"",S_FALSE},
5524             {"",S_FALSE}
5525         },
5526         {
5527             {Uri_HOST_UNKNOWN,S_OK},
5528             {0,S_FALSE},
5529             {URL_SCHEME_FILE,S_OK},
5530             {URLZONE_INVALID,E_NOTIMPL}
5531         }
5532     },
5533     {   "file:///c:/test/test",0,
5534         "/testing.mp3",Uri_CREATE_ALLOW_RELATIVE,
5535         0,S_OK,FALSE,
5536         {
5537             {"file:///c:/testing.mp3",S_OK},
5538             {"",S_FALSE},
5539             {"file:///c:/testing.mp3",S_OK},
5540             {"",S_FALSE},
5541             {".mp3",S_OK},
5542             {"",S_FALSE},
5543             {"",S_FALSE},
5544             {"",S_FALSE},
5545             {"/c:/testing.mp3",S_OK},
5546             {"/c:/testing.mp3",S_OK},
5547             {"",S_FALSE},
5548             {"file:///c:/testing.mp3",S_OK},
5549             {"file",S_OK},
5550             {"",S_FALSE},
5551             {"",S_FALSE}
5552         },
5553         {
5554             {Uri_HOST_UNKNOWN,S_OK},
5555             {0,S_FALSE},
5556             {URL_SCHEME_FILE,S_OK},
5557             {URLZONE_INVALID,E_NOTIMPL}
5558         }
5559     },
5560     {   "file://test.com/test/test",0,
5561         "/testing.mp3",Uri_CREATE_ALLOW_RELATIVE,
5562         URL_FILE_USE_PATHURL,S_OK,FALSE,
5563         {
5564             {"file://\\\\test.com\\testing.mp3",S_OK},
5565             {"test.com",S_OK},
5566             {"file://\\\\test.com\\testing.mp3",S_OK},
5567             {"test.com",S_OK},
5568             {".mp3",S_OK},
5569             {"",S_FALSE},
5570             {"test.com",S_OK},
5571             {"",S_FALSE},
5572             {"\\testing.mp3",S_OK},
5573             {"\\testing.mp3",S_OK},
5574             {"",S_FALSE},
5575             {"file://\\\\test.com\\testing.mp3",S_OK},
5576             {"file",S_OK},
5577             {"",S_FALSE},
5578             {"",S_FALSE}
5579         },
5580         {
5581             {Uri_HOST_DNS,S_OK},
5582             {0,S_FALSE},
5583             {URL_SCHEME_FILE,S_OK},
5584             {URLZONE_INVALID,E_NOTIMPL}
5585         }
5586     },
5587     /* URL_DONT_SIMPLIFY has no effect. */
5588     {   "http://google.com/test",0,
5589         "zip://test.com/cool/../cool/test",0,
5590         URL_DONT_SIMPLIFY,S_OK,FALSE,
5591         {
5592             {"zip://test.com/cool/test",S_OK,FALSE,NULL,"zip://test.com/cool/../cool/test"},
5593             {"test.com",S_OK},
5594             {"zip://test.com/cool/test",S_OK,FALSE,NULL,"zip://test.com/cool/../cool/test"},
5595             {"test.com",S_OK},
5596             {"",S_FALSE},
5597             {"",S_FALSE},
5598             {"test.com",S_OK},
5599             {"",S_FALSE},
5600             {"/cool/test",S_OK,FALSE,NULL,"/cool/../cool/test"},
5601             {"/cool/test",S_OK,FALSE,NULL,"/cool/../cool/test"},
5602             {"",S_FALSE},
5603             /* The resulting IUri has the same Raw URI as the relative URI (only IE 8).
5604              * On IE 7 it reduces the path in the Raw URI.
5605              */
5606             {"zip://test.com/cool/../cool/test",S_OK,FALSE,"zip://test.com/cool/test"},
5607             {"zip",S_OK},
5608             {"",S_FALSE},
5609             {"",S_FALSE}
5610         },
5611         {
5612             {Uri_HOST_DNS,S_OK},
5613             {0,S_FALSE},
5614             {URL_SCHEME_UNKNOWN,S_OK},
5615             {URLZONE_INVALID,E_NOTIMPL}
5616         }
5617     },
5618     /* FILE_USE_PATHURL has no effect in IE 8, in IE 7 the
5619      * resulting URI is converted into a dos path.
5620      */
5621     {   "http://google.com/test",0,
5622         "file:///c:/test/",0,
5623         URL_FILE_USE_PATHURL,S_OK,FALSE,
5624         {
5625             {"file:///c:/test/",S_OK,FALSE,"file://c:\\test\\"},
5626             {"",S_FALSE},
5627             {"file:///c:/test/",S_OK,FALSE,"file://c:\\test\\"},
5628             {"",S_FALSE},
5629             {"",S_FALSE},
5630             {"",S_FALSE},
5631             {"",S_FALSE},
5632             {"",S_FALSE},
5633             {"/c:/test/",S_OK,FALSE,"c:\\test\\"},
5634             {"/c:/test/",S_OK,FALSE,"c:\\test\\"},
5635             {"",S_FALSE},
5636             {"file:///c:/test/",S_OK,FALSE,"file://c:\\test\\"},
5637             {"file",S_OK},
5638             {"",S_FALSE},
5639             {"",S_FALSE}
5640         },
5641         {
5642             {Uri_HOST_UNKNOWN,S_OK},
5643             {0,S_FALSE},
5644             {URL_SCHEME_FILE,S_OK},
5645             {URLZONE_INVALID,E_NOTIMPL}
5646         }
5647     },
5648     {   "http://google.com/test",0,
5649         "http://test.com/test#%30test",0,
5650         URL_DONT_UNESCAPE_EXTRA_INFO,S_OK,FALSE,
5651         {
5652             {"http://test.com/test#0test",S_OK,FALSE,NULL,"http://test.com/test#%30test"},
5653             {"test.com",S_OK},
5654             {"http://test.com/test#0test",S_OK,FALSE,NULL,"http://test.com/test#%30test"},
5655             {"test.com",S_OK},
5656             {"",S_FALSE},
5657             {"#0test",S_OK,FALSE,NULL,"#%30test"},
5658             {"test.com",S_OK},
5659             {"",S_FALSE},
5660             {"/test",S_OK},
5661             {"/test",S_OK},
5662             {"",S_FALSE},
5663             /* IE 7 decodes the %30 to a 0 in the Raw URI. */
5664             {"http://test.com/test#%30test",S_OK,FALSE,"http://test.com/test#0test"},
5665             {"http",S_OK},
5666             {"",S_FALSE},
5667             {"",S_FALSE}
5668         },
5669         {
5670             {Uri_HOST_DNS,S_OK},
5671             {80,S_OK},
5672             {URL_SCHEME_HTTP,S_OK},
5673             {URLZONE_INVALID,E_NOTIMPL}
5674         }
5675     },
5676     /* Windows validates the path component from the relative Uri. */
5677     {   "http://google.com/test",0,
5678         "/Te%XXst",Uri_CREATE_ALLOW_RELATIVE,
5679         0,E_INVALIDARG,FALSE
5680     },
5681     /* Windows doesn't validate the query from the relative Uri. */
5682     {   "http://google.com/test",0,
5683         "?Tes%XXt",Uri_CREATE_ALLOW_RELATIVE,
5684         0,S_OK,FALSE,
5685         {
5686             {"http://google.com/test?Tes%XXt",S_OK},
5687             {"google.com",S_OK},
5688             {"http://google.com/test?Tes%XXt",S_OK},
5689             {"google.com",S_OK},
5690             {"",S_FALSE},
5691             {"",S_FALSE},
5692             {"google.com",S_OK},
5693             {"",S_FALSE},
5694             {"/test",S_OK},
5695             {"/test?Tes%XXt",S_OK},
5696             {"?Tes%XXt",S_OK},
5697             {"http://google.com/test?Tes%XXt",S_OK},
5698             {"http",S_OK},
5699             {"",S_FALSE},
5700             {"",S_FALSE}
5701         },
5702         {
5703             {Uri_HOST_DNS,S_OK},
5704             {80,S_OK},
5705             {URL_SCHEME_HTTP,S_OK},
5706             {URLZONE_INVALID,E_NOTIMPL}
5707         }
5708     },
5709     /* Windows doesn't validate the fragment from the relative Uri. */
5710     {   "http://google.com/test",0,
5711         "#Tes%XXt",Uri_CREATE_ALLOW_RELATIVE,
5712         0,S_OK,FALSE,
5713         {
5714             {"http://google.com/test#Tes%XXt",S_OK},
5715             {"google.com",S_OK},
5716             {"http://google.com/test#Tes%XXt",S_OK},
5717             {"google.com",S_OK},
5718             {"",S_FALSE},
5719             {"#Tes%XXt",S_OK},
5720             {"google.com",S_OK},
5721             {"",S_FALSE},
5722             {"/test",S_OK},
5723             {"/test",S_OK},
5724             {"",S_FALSE},
5725             {"http://google.com/test#Tes%XXt",S_OK},
5726             {"http",S_OK},
5727             {"",S_FALSE},
5728             {"",S_FALSE}
5729         },
5730         {
5731             {Uri_HOST_DNS,S_OK},
5732             {80,S_OK},
5733             {URL_SCHEME_HTTP,S_OK},
5734             {URLZONE_INVALID,E_NOTIMPL}
5735         }
5736     },
5737     /* Creates an IUri which contains an invalid dos path char. */
5738     {   "file:///c:/test",0,
5739         "/test<ing",Uri_CREATE_ALLOW_RELATIVE,
5740         URL_FILE_USE_PATHURL,S_OK,FALSE,
5741         {
5742             {"file://c:\\test<ing",S_OK},
5743             {"",S_FALSE},
5744             {"file://c:\\test<ing",S_OK},
5745             {"",S_FALSE},
5746             {"",S_FALSE},
5747             {"",S_FALSE},
5748             {"",S_FALSE},
5749             {"",S_FALSE},
5750             {"c:\\test<ing",S_OK},
5751             {"c:\\test<ing",S_OK},
5752             {"",S_FALSE},
5753             {"file://c:\\test<ing",S_OK},
5754             {"file",S_OK},
5755             {"",S_FALSE},
5756             {"",S_FALSE}
5757         },
5758         {
5759             {Uri_HOST_UNKNOWN,S_OK},
5760             {0,S_FALSE},
5761             {URL_SCHEME_FILE,S_OK},
5762             {URLZONE_INVALID,E_NOTIMPL}
5763         }
5764     },
5765     /* Appends the path after the drive letter (if any). */
5766     {   "file:///c:/test",0,
5767         "/c:/testing",Uri_CREATE_ALLOW_RELATIVE,
5768         0,S_OK,FALSE,
5769         {
5770             {"file:///c:/c:/testing",S_OK},
5771             {"",S_FALSE},
5772             {"file:///c:/c:/testing",S_OK},
5773             {"",S_FALSE},
5774             {"",S_FALSE},
5775             {"",S_FALSE},
5776             {"",S_FALSE},
5777             {"",S_FALSE},
5778             {"/c:/c:/testing",S_OK},
5779             {"/c:/c:/testing",S_OK},
5780             {"",S_FALSE},
5781             {"file:///c:/c:/testing",S_OK},
5782             {"file",S_OK},
5783             {"",S_FALSE},
5784             {"",S_FALSE}
5785         },
5786         {
5787             {Uri_HOST_UNKNOWN,S_OK},
5788             {0,S_FALSE},
5789             {URL_SCHEME_FILE,S_OK},
5790             {URLZONE_INVALID,E_NOTIMPL}
5791         }
5792     },
5793     /* A '/' is added if the base URI doesn't have a path and the
5794      * relative URI doesn't contain a path (since the base URI is
5795      * hierarchical.
5796      */
5797     {   "http://google.com",Uri_CREATE_NO_CANONICALIZE,
5798         "?test",Uri_CREATE_ALLOW_RELATIVE,
5799         0,S_OK,FALSE,
5800         {
5801             {"http://google.com/?test",S_OK},
5802             {"google.com",S_OK},
5803             {"http://google.com/?test",S_OK},
5804             {"google.com",S_OK},
5805             {"",S_FALSE},
5806             {"",S_FALSE},
5807             {"google.com",S_OK},
5808             {"",S_FALSE},
5809             {"/",S_OK},
5810             {"/?test",S_OK},
5811             {"?test",S_OK},
5812             {"http://google.com/?test",S_OK},
5813             {"http",S_OK},
5814             {"",S_FALSE},
5815             {"",S_FALSE}
5816         },
5817         {
5818             {Uri_HOST_DNS,S_OK},
5819             {80,S_OK},
5820             {URL_SCHEME_HTTP,S_OK},
5821             {URLZONE_INVALID,E_NOTIMPL}
5822         }
5823     },
5824     {   "zip://google.com",Uri_CREATE_NO_CANONICALIZE,
5825         "?test",Uri_CREATE_ALLOW_RELATIVE,
5826         0,S_OK,FALSE,
5827         {
5828             {"zip://google.com/?test",S_OK},
5829             {"google.com",S_OK},
5830             {"zip://google.com/?test",S_OK},
5831             {"google.com",S_OK},
5832             {"",S_FALSE},
5833             {"",S_FALSE},
5834             {"google.com",S_OK},
5835             {"",S_FALSE},
5836             {"/",S_OK},
5837             {"/?test",S_OK},
5838             {"?test",S_OK},
5839             {"zip://google.com/?test",S_OK},
5840             {"zip",S_OK},
5841             {"",S_FALSE},
5842             {"",S_FALSE}
5843         },
5844         {
5845             {Uri_HOST_DNS,S_OK},
5846             {0,S_FALSE},
5847             {URL_SCHEME_UNKNOWN,S_OK},
5848             {URLZONE_INVALID,E_NOTIMPL}
5849         }
5850     },
5851     /* No path is appended since the base URI is opaque. */
5852     {   "zip:?testing",0,
5853         "?test",Uri_CREATE_ALLOW_RELATIVE,
5854         0,S_OK,FALSE,
5855         {
5856             {"zip:?test",S_OK},
5857             {"",S_FALSE},
5858             {"zip:?test",S_OK},
5859             {"",S_FALSE},
5860             {"",S_FALSE},
5861             {"",S_FALSE},
5862             {"",S_FALSE},
5863             {"",S_FALSE},
5864             {"",S_OK},
5865             {"?test",S_OK},
5866             {"?test",S_OK},
5867             {"zip:?test",S_OK},
5868             {"zip",S_OK},
5869             {"",S_FALSE},
5870             {"",S_FALSE}
5871         },
5872         {
5873             {Uri_HOST_UNKNOWN,S_OK},
5874             {0,S_FALSE},
5875             {URL_SCHEME_UNKNOWN,S_OK},
5876             {URLZONE_INVALID,E_NOTIMPL}
5877         }
5878     },
5879     {   "file:///c:/",0,
5880         "../testing/test",Uri_CREATE_ALLOW_RELATIVE,
5881         0,S_OK,FALSE,
5882         {
5883             {"file:///c:/testing/test",S_OK},
5884             {"",S_FALSE},
5885             {"file:///c:/testing/test",S_OK},
5886             {"",S_FALSE},
5887             {"",S_FALSE},
5888             {"",S_FALSE},
5889             {"",S_FALSE},
5890             {"",S_FALSE},
5891             {"/c:/testing/test",S_OK},
5892             {"/c:/testing/test",S_OK},
5893             {"",S_FALSE},
5894             {"file:///c:/testing/test",S_OK},
5895             {"file",S_OK},
5896             {"",S_FALSE},
5897             {"",S_FALSE}
5898         },
5899         {
5900             {Uri_HOST_UNKNOWN,S_OK},
5901             {0,S_FALSE},
5902             {URL_SCHEME_FILE,S_OK},
5903             {URLZONE_INVALID,E_NOTIMPL}
5904         }
5905     }
5906 };
5907
5908 typedef struct _uri_parse_test {
5909     const char  *uri;
5910     DWORD       uri_flags;
5911     PARSEACTION action;
5912     DWORD       flags;
5913     const char  *property;
5914     HRESULT     expected;
5915     BOOL        todo;
5916 } uri_parse_test;
5917
5918 static const uri_parse_test uri_parse_tests[] = {
5919     /* PARSE_CANONICALIZE tests. */
5920     {"zip://google.com/test<|>",0,PARSE_CANONICALIZE,0,"zip://google.com/test<|>",S_OK,FALSE},
5921     {"http://google.com/test<|>",0,PARSE_CANONICALIZE,0,"http://google.com/test%3C%7C%3E",S_OK,FALSE},
5922     {"http://google.com/%30%23%3F",0,PARSE_CANONICALIZE,URL_UNESCAPE,"http://google.com/0#?",S_OK,FALSE},
5923     {"test <|>",Uri_CREATE_ALLOW_RELATIVE,PARSE_CANONICALIZE,URL_ESCAPE_UNSAFE,"test %3C%7C%3E",S_OK,FALSE},
5924     {"test <|>",Uri_CREATE_ALLOW_RELATIVE,PARSE_CANONICALIZE,URL_ESCAPE_SPACES_ONLY,"test%20<|>",S_OK,FALSE},
5925     {"test%20<|>",Uri_CREATE_ALLOW_RELATIVE,PARSE_CANONICALIZE,URL_UNESCAPE|URL_ESCAPE_UNSAFE,"test%20%3C%7C%3E",S_OK,FALSE},
5926     {"http://google.com/%20",0,PARSE_CANONICALIZE,URL_ESCAPE_PERCENT,"http://google.com/%2520",S_OK,FALSE},
5927     {"http://google.com/test/../",Uri_CREATE_NO_CANONICALIZE,PARSE_CANONICALIZE,URL_DONT_SIMPLIFY,"http://google.com/test/../",S_OK,FALSE},
5928     {"http://google.com/test/../",Uri_CREATE_NO_CANONICALIZE,PARSE_CANONICALIZE,URL_NO_META,"http://google.com/test/../",S_OK,FALSE},
5929     {"http://google.com/test/../",Uri_CREATE_NO_CANONICALIZE,PARSE_CANONICALIZE,0,"http://google.com/",S_OK,FALSE},
5930     {"zip://google.com/test/../",Uri_CREATE_NO_CANONICALIZE,PARSE_CANONICALIZE,0,"zip://google.com/",S_OK,FALSE},
5931     {"file:///c:/test/../test",Uri_CREATE_NO_CANONICALIZE,PARSE_CANONICALIZE,URL_DONT_SIMPLIFY,"file:///c:/test/../test",S_OK,FALSE},
5932
5933     /* PARSE_FRIENDLY tests. */
5934     {"http://test@google.com/test#test",0,PARSE_FRIENDLY,0,"http://google.com/test#test",S_OK,FALSE},
5935     {"zip://test@google.com/test",0,PARSE_FRIENDLY,0,"zip://test@google.com/test",S_OK,FALSE},
5936
5937     /* PARSE_ROOTDOCUMENT tests. */
5938     {"http://google.com:200/test/test",0,PARSE_ROOTDOCUMENT,0,"http://google.com:200/",S_OK,FALSE},
5939     {"http://google.com",Uri_CREATE_NO_CANONICALIZE,PARSE_ROOTDOCUMENT,0,"http://google.com/",S_OK,FALSE},
5940     {"zip://google.com/",0,PARSE_ROOTDOCUMENT,0,"",S_OK,FALSE},
5941     {"file:///c:/testing/",0,PARSE_ROOTDOCUMENT,0,"",S_OK,FALSE},
5942     {"file://server/test",0,PARSE_ROOTDOCUMENT,0,"",S_OK,FALSE},
5943     {"zip:test/test",0,PARSE_ROOTDOCUMENT,0,"",S_OK,FALSE},
5944
5945     /* PARSE_DOCUMENT tests. */
5946     {"http://test@google.com/test?query#frag",0,PARSE_DOCUMENT,0,"http://test@google.com/test?query",S_OK,FALSE},
5947     {"http:testing#frag",0,PARSE_DOCUMENT,0,"",S_OK,FALSE},
5948     {"file:///c:/test#frag",0,PARSE_DOCUMENT,0,"",S_OK,FALSE},
5949     {"zip://google.com/#frag",0,PARSE_DOCUMENT,0,"",S_OK,FALSE},
5950     {"zip:test#frag",0,PARSE_DOCUMENT,0,"",S_OK,FALSE},
5951     {"testing#frag",Uri_CREATE_ALLOW_RELATIVE,PARSE_DOCUMENT,0,"",S_OK,FALSE},
5952
5953     /* PARSE_PATH_FROM_URL tests. */
5954     {"file:///c:/test.mp3",0,PARSE_PATH_FROM_URL,0,"c:\\test.mp3",S_OK,FALSE},
5955     {"file:///c:/t<|>est.mp3",0,PARSE_PATH_FROM_URL,0,"c:\\t<|>est.mp3",S_OK,FALSE},
5956     {"file:///c:/te%XX t/",0,PARSE_PATH_FROM_URL,0,"c:\\te%XX t\\",S_OK,FALSE},
5957     {"file://server/test",0,PARSE_PATH_FROM_URL,0,"\\\\server\\test",S_OK,FALSE},
5958     {"http://google.com/",0,PARSE_PATH_FROM_URL,0,"",E_INVALIDARG,FALSE},
5959
5960     /* PARSE_URL_FROM_PATH tests. */
5961     /* This function almost seems to useless (just returns the absolute uri). */
5962     {"test.com",Uri_CREATE_ALLOW_RELATIVE,PARSE_URL_FROM_PATH,0,"test.com",S_OK,FALSE},
5963     {"/test/test",Uri_CREATE_ALLOW_RELATIVE,PARSE_URL_FROM_PATH,0,"/test/test",S_OK,FALSE},
5964     {"file://c:\\test\\test",Uri_CREATE_FILE_USE_DOS_PATH,PARSE_URL_FROM_PATH,0,"file://c:\\test\\test",S_OK,FALSE},
5965     {"file:c:/test",0,PARSE_URL_FROM_PATH,0,"",S_OK,FALSE},
5966     {"http:google.com/",0,PARSE_URL_FROM_PATH,0,"",S_OK,FALSE},
5967
5968     /* PARSE_SCHEMA tests. */
5969     {"http://google.com/test",0,PARSE_SCHEMA,0,"http",S_OK,FALSE},
5970     {"test",Uri_CREATE_ALLOW_RELATIVE,PARSE_SCHEMA,0,"",S_OK,FALSE},
5971
5972     /* PARSE_SITE tests. */
5973     {"http://google.uk.com/",0,PARSE_SITE,0,"google.uk.com",S_OK,FALSE},
5974     {"http://google.com.com/",0,PARSE_SITE,0,"google.com.com",S_OK,FALSE},
5975     {"google.com",Uri_CREATE_ALLOW_RELATIVE,PARSE_SITE,0,"",S_OK,FALSE},
5976     {"file://server/test",0,PARSE_SITE,0,"server",S_OK,FALSE},
5977
5978     /* PARSE_DOMAIN tests. */
5979     {"http://google.com.uk/",0,PARSE_DOMAIN,0,"google.com.uk",S_OK,FALSE},
5980     {"http://google.com.com/",0,PARSE_DOMAIN,0,"com.com",S_OK,FALSE},
5981     {"test/test",Uri_CREATE_ALLOW_RELATIVE,PARSE_DOMAIN,0,"",S_OK,FALSE},
5982     {"file://server/test",0,PARSE_DOMAIN,0,"",S_OK,FALSE},
5983
5984     /* PARSE_LOCATION and PARSE_ANCHOR tests. */
5985     {"http://google.com/test#Test",0,PARSE_ANCHOR,0,"#Test",S_OK,FALSE},
5986     {"http://google.com/test#Test",0,PARSE_LOCATION,0,"#Test",S_OK,FALSE},
5987     {"test",Uri_CREATE_ALLOW_RELATIVE,PARSE_ANCHOR,0,"",S_OK,FALSE},
5988     {"test",Uri_CREATE_ALLOW_RELATIVE,PARSE_LOCATION,0,"",S_OK,FALSE}
5989 };
5990
5991 static inline LPWSTR a2w(LPCSTR str) {
5992     LPWSTR ret = NULL;
5993
5994     if(str) {
5995         DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
5996         ret = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
5997         MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len);
5998     }
5999
6000     return ret;
6001 }
6002
6003 static inline BOOL heap_free(void* mem) {
6004     return HeapFree(GetProcessHeap(), 0, mem);
6005 }
6006
6007 static inline DWORD strcmp_aw(LPCSTR strA, LPCWSTR strB) {
6008     LPWSTR strAW = a2w(strA);
6009     DWORD ret = lstrcmpW(strAW, strB);
6010     heap_free(strAW);
6011     return ret;
6012 }
6013
6014 static inline ULONG get_refcnt(IUri *uri) {
6015     IUri_AddRef(uri);
6016     return IUri_Release(uri);
6017 }
6018
6019 static void change_property(IUriBuilder *builder, const uri_builder_property *prop,
6020                             DWORD test_index) {
6021     HRESULT hr;
6022     LPWSTR valueW;
6023
6024     valueW = a2w(prop->value);
6025     switch(prop->property) {
6026     case Uri_PROPERTY_FRAGMENT:
6027         hr = IUriBuilder_SetFragment(builder, valueW);
6028         if(prop->todo) {
6029             todo_wine {
6030                 ok(hr == prop->expected,
6031                     "Error: IUriBuilder_SetFragment returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6032                     hr, prop->expected, test_index);
6033             }
6034         } else {
6035             ok(hr == prop->expected,
6036                 "Error: IUriBuilder_SetFragment returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6037                 hr, prop->expected, test_index);
6038         }
6039         break;
6040     case Uri_PROPERTY_HOST:
6041         hr = IUriBuilder_SetHost(builder, valueW);
6042         if(prop->todo) {
6043             todo_wine {
6044                 ok(hr == prop->expected,
6045                     "Error: IUriBuilder_SetHost returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6046                     hr, prop->expected, test_index);
6047             }
6048         } else {
6049             ok(hr == prop->expected,
6050                 "Error: IUriBuilder_SetHost returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6051                 hr, prop->expected, test_index);
6052         }
6053         break;
6054     case Uri_PROPERTY_PASSWORD:
6055         hr = IUriBuilder_SetPassword(builder, valueW);
6056         if(prop->todo) {
6057             todo_wine {
6058                 ok(hr == prop->expected,
6059                     "Error: IUriBuilder_SetPassword returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6060                     hr, prop->expected, test_index);
6061             }
6062         } else {
6063             ok(hr == prop->expected,
6064                 "Error: IUriBuilder_SetPassword returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6065                 hr, prop->expected, test_index);
6066         }
6067         break;
6068     case Uri_PROPERTY_PATH:
6069         hr = IUriBuilder_SetPath(builder, valueW);
6070         if(prop->todo) {
6071             todo_wine {
6072                 ok(hr == prop->expected,
6073                     "Error: IUriBuilder_SetPath returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6074                     hr, prop->expected, test_index);
6075             }
6076         } else {
6077             ok(hr == prop->expected,
6078                 "Error: IUriBuilder_SetPath returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6079                 hr, prop->expected, test_index);
6080         }
6081         break;
6082     case Uri_PROPERTY_QUERY:
6083         hr = IUriBuilder_SetQuery(builder, valueW);
6084         if(prop->todo) {
6085             todo_wine {
6086                 ok(hr == prop->expected,
6087                     "Error: IUriBuilder_SetQuery returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6088                     hr, prop->expected, test_index);
6089             }
6090         } else {
6091             ok(hr == prop->expected,
6092                 "Error: IUriBuilder_SetQuery returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6093                 hr, prop->expected, test_index);
6094         }
6095         break;
6096     case Uri_PROPERTY_SCHEME_NAME:
6097         hr = IUriBuilder_SetSchemeName(builder, valueW);
6098         if(prop->todo) {
6099             todo_wine {
6100                 ok(hr == prop->expected,
6101                     "Error: IUriBuilder_SetSchemeName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6102                     hr, prop->expected, test_index);
6103             }
6104         } else {
6105             ok(hr == prop->expected,
6106                 "Error: IUriBuilder_SetSchemeName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6107                 hr, prop->expected, test_index);
6108         }
6109         break;
6110     case Uri_PROPERTY_USER_NAME:
6111         hr = IUriBuilder_SetUserName(builder, valueW);
6112         if(prop->todo) {
6113             todo_wine {
6114                 ok(hr == prop->expected,
6115                     "Error: IUriBuilder_SetUserName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6116                     hr, prop->expected, test_index);
6117             }
6118         } else {
6119             ok(hr == prop->expected,
6120                 "Error: IUriBuilder_SetUserName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6121                 hr, prop->expected, test_index);
6122         }
6123         break;
6124     default:
6125         trace("Unsupported operation for %d on uri_builder_tests[%d].\n", prop->property, test_index);
6126     }
6127
6128     heap_free(valueW);
6129 }
6130
6131 /*
6132  * Simple tests to make sure the CreateUri function handles invalid flag combinations
6133  * correctly.
6134  */
6135 static void test_CreateUri_InvalidFlags(void) {
6136     DWORD i;
6137
6138     for(i = 0; i < sizeof(invalid_flag_tests)/sizeof(invalid_flag_tests[0]); ++i) {
6139         HRESULT hr;
6140         IUri *uri = (void*) 0xdeadbeef;
6141
6142         hr = pCreateUri(http_urlW, invalid_flag_tests[i].flags, 0, &uri);
6143         ok(hr == invalid_flag_tests[i].expected, "Error: CreateUri returned 0x%08x, expected 0x%08x, flags=0x%08x\n",
6144                 hr, invalid_flag_tests[i].expected, invalid_flag_tests[i].flags);
6145         ok(uri == NULL, "Error: expected the IUri to be NULL, but it was %p instead\n", uri);
6146     }
6147 }
6148
6149 static void test_CreateUri_InvalidArgs(void) {
6150     HRESULT hr;
6151     IUri *uri = (void*) 0xdeadbeef;
6152
6153     const WCHAR invalidW[] = {'i','n','v','a','l','i','d',0};
6154     static const WCHAR emptyW[] = {0};
6155
6156     hr = pCreateUri(http_urlW, 0, 0, NULL);
6157     ok(hr == E_INVALIDARG, "Error: CreateUri returned 0x%08x, expected 0x%08x\n", hr, E_INVALIDARG);
6158
6159     hr = pCreateUri(NULL, 0, 0, &uri);
6160     ok(hr == E_INVALIDARG, "Error: CreateUri returned 0x%08x, expected 0x%08x\n", hr, E_INVALIDARG);
6161     ok(uri == NULL, "Error: Expected the IUri to be NULL, but it was %p instead\n", uri);
6162
6163     uri = (void*) 0xdeadbeef;
6164     hr = pCreateUri(invalidW, 0, 0, &uri);
6165     ok(hr == E_INVALIDARG, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
6166     ok(uri == NULL, "Error: Expected the IUri to be NULL, but it was %p instead\n", uri);
6167
6168     uri = (void*) 0xdeadbeef;
6169     hr = pCreateUri(emptyW, 0, 0, &uri);
6170     ok(hr == E_INVALIDARG, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
6171     ok(uri == NULL, "Error: Expected the IUri to be NULL, but it was %p instead\n", uri);
6172 }
6173
6174 static void test_CreateUri_InvalidUri(void) {
6175     DWORD i;
6176
6177     for(i = 0; i < sizeof(invalid_uri_tests)/sizeof(invalid_uri_tests[0]); ++i) {
6178         invalid_uri test = invalid_uri_tests[i];
6179         IUri *uri = NULL;
6180         LPWSTR uriW;
6181         HRESULT hr;
6182
6183         uriW = a2w(test.uri);
6184         hr = pCreateUri(uriW, test.flags, 0, &uri);
6185         if(test.todo) {
6186             todo_wine {
6187                 ok(hr == E_INVALIDARG, "Error: CreateUri returned 0x%08x, expected 0x%08x on invalid_uri_tests[%d].\n",
6188                     hr, E_INVALIDARG, i);
6189             }
6190         } else {
6191             ok(hr == E_INVALIDARG, "Error: CreateUri returned 0x%08x, expected 0x%08x on invalid_uri_tests[%d].\n",
6192                 hr, E_INVALIDARG, i);
6193         }
6194         if(uri) IUri_Release(uri);
6195
6196         heap_free(uriW);
6197     }
6198 }
6199
6200 static void test_IUri_GetPropertyBSTR(void) {
6201     IUri *uri = NULL;
6202     HRESULT hr;
6203     DWORD i;
6204
6205     /* Make sure GetPropertyBSTR handles invalid args correctly. */
6206     hr = pCreateUri(http_urlW, 0, 0, &uri);
6207     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
6208     if(SUCCEEDED(hr)) {
6209         BSTR received = NULL;
6210
6211         hr = IUri_GetPropertyBSTR(uri, Uri_PROPERTY_RAW_URI, NULL, 0);
6212         ok(hr == E_POINTER, "Error: GetPropertyBSTR returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
6213
6214         /* Make sure it handles a invalid Uri_PROPERTY's correctly. */
6215         hr = IUri_GetPropertyBSTR(uri, Uri_PROPERTY_PORT, &received, 0);
6216         ok(hr == S_OK, "Error: GetPropertyBSTR returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
6217         ok(received != NULL, "Error: Expected the string not to be NULL.\n");
6218         ok(!SysStringLen(received), "Error: Expected the string to be of len=0 but it was %d instead.\n", SysStringLen(received));
6219         SysFreeString(received);
6220
6221         /* Make sure it handles the ZONE property correctly. */
6222         received = NULL;
6223         hr = IUri_GetPropertyBSTR(uri, Uri_PROPERTY_ZONE, &received, 0);
6224         ok(hr == S_FALSE, "Error: GetPropertyBSTR returned 0x%08x, expected 0x%08x.\n", hr, S_FALSE);
6225         ok(received != NULL, "Error: Expected the string not to be NULL.\n");
6226         ok(!SysStringLen(received), "Error: Expected the string to be of len=0 but it was %d instead.\n", SysStringLen(received));
6227         SysFreeString(received);
6228     }
6229     if(uri) IUri_Release(uri);
6230
6231     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
6232         uri_properties test = uri_tests[i];
6233         LPWSTR uriW;
6234         uri = NULL;
6235
6236         uriW = a2w(test.uri);
6237         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
6238         if(test.create_todo) {
6239             todo_wine {
6240                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x. Failed on uri_tests[%d].\n",
6241                         hr, test.create_expected, i);
6242             }
6243         } else {
6244             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x. Failed on uri_tests[%d].\n",
6245                     hr, test.create_expected, i);
6246         }
6247
6248         if(SUCCEEDED(hr)) {
6249             DWORD j;
6250
6251             /* Checks all the string properties of the uri. */
6252             for(j = Uri_PROPERTY_STRING_START; j <= Uri_PROPERTY_STRING_LAST; ++j) {
6253                 BSTR received = NULL;
6254                 uri_str_property prop = test.str_props[j];
6255
6256                 hr = IUri_GetPropertyBSTR(uri, j, &received, 0);
6257                 if(prop.todo) {
6258                     todo_wine {
6259                         ok(hr == prop.expected, "GetPropertyBSTR returned 0x%08x, expected 0x%08x. On uri_tests[%d].str_props[%d].\n",
6260                                 hr, prop.expected, i, j);
6261                     }
6262                     todo_wine {
6263                         ok(!strcmp_aw(prop.value, received) || broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
6264                                 "Expected %s but got %s on uri_tests[%d].str_props[%d].\n",
6265                                 prop.value, wine_dbgstr_w(received), i, j);
6266                     }
6267                 } else {
6268                     ok(hr == prop.expected, "GetPropertyBSTR returned 0x%08x, expected 0x%08x. On uri_tests[%d].str_props[%d].\n",
6269                             hr, prop.expected, i, j);
6270                     ok(!strcmp_aw(prop.value, received) || broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
6271                             "Expected %s but got %s on uri_tests[%d].str_props[%d].\n",
6272                             prop.value, wine_dbgstr_w(received), i, j);
6273                 }
6274
6275                 SysFreeString(received);
6276             }
6277         }
6278
6279         if(uri) IUri_Release(uri);
6280
6281         heap_free(uriW);
6282     }
6283 }
6284
6285 static void test_IUri_GetPropertyDWORD(void) {
6286     IUri *uri = NULL;
6287     HRESULT hr;
6288     DWORD i;
6289
6290     hr = pCreateUri(http_urlW, 0, 0, &uri);
6291     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
6292     if(SUCCEEDED(hr)) {
6293         DWORD received = 0xdeadbeef;
6294
6295         hr = IUri_GetPropertyDWORD(uri, Uri_PROPERTY_DWORD_START, NULL, 0);
6296         ok(hr == E_INVALIDARG, "Error: GetPropertyDWORD returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
6297
6298         hr = IUri_GetPropertyDWORD(uri, Uri_PROPERTY_ABSOLUTE_URI, &received, 0);
6299         ok(hr == E_INVALIDARG, "Error: GetPropertyDWORD returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
6300         ok(received == 0, "Error: Expected received=%d but instead received=%d.\n", 0, received);
6301     }
6302     if(uri) IUri_Release(uri);
6303
6304     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
6305         uri_properties test = uri_tests[i];
6306         LPWSTR uriW;
6307         uri = NULL;
6308
6309         uriW = a2w(test.uri);
6310         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
6311         if(test.create_todo) {
6312             todo_wine {
6313                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x. Failed on uri_tests[%d].\n",
6314                         hr, test.create_expected, i);
6315             }
6316         } else {
6317             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x. Failed on uri_tests[%d].\n",
6318                     hr, test.create_expected, i);
6319         }
6320
6321         if(SUCCEEDED(hr)) {
6322             DWORD j;
6323
6324             /* Checks all the DWORD properties of the uri. */
6325             for(j = 0; j < sizeof(test.dword_props)/sizeof(test.dword_props[0]); ++j) {
6326                 DWORD received;
6327                 uri_dword_property prop = test.dword_props[j];
6328
6329                 hr = IUri_GetPropertyDWORD(uri, j+Uri_PROPERTY_DWORD_START, &received, 0);
6330                 if(prop.todo) {
6331                     todo_wine {
6332                         ok(hr == prop.expected, "GetPropertyDWORD returned 0x%08x, expected 0x%08x. On uri_tests[%d].dword_props[%d].\n",
6333                                 hr, prop.expected, i, j);
6334                     }
6335                     todo_wine {
6336                         ok(prop.value == received, "Expected %d but got %d on uri_tests[%d].dword_props[%d].\n",
6337                                 prop.value, received, i, j);
6338                     }
6339                 } else {
6340                     ok(hr == prop.expected, "GetPropertyDWORD returned 0x%08x, expected 0x%08x. On uri_tests[%d].dword_props[%d].\n",
6341                             hr, prop.expected, i, j);
6342                     ok(prop.value == received, "Expected %d but got %d on uri_tests[%d].dword_props[%d].\n",
6343                             prop.value, received, i, j);
6344                 }
6345             }
6346         }
6347
6348         if(uri) IUri_Release(uri);
6349
6350         heap_free(uriW);
6351     }
6352 }
6353
6354 /* Tests all the 'Get*' property functions which deal with strings. */
6355 static void test_IUri_GetStrProperties(void) {
6356     IUri *uri = NULL;
6357     HRESULT hr;
6358     DWORD i;
6359
6360     /* Make sure all the 'Get*' string property functions handle invalid args correctly. */
6361     hr = pCreateUri(http_urlW, 0, 0, &uri);
6362     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
6363     if(SUCCEEDED(hr)) {
6364         hr = IUri_GetAbsoluteUri(uri, NULL);
6365         ok(hr == E_POINTER, "Error: GetAbsoluteUri returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
6366
6367         hr = IUri_GetAuthority(uri, NULL);
6368         ok(hr == E_POINTER, "Error: GetAuthority returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
6369
6370         hr = IUri_GetDisplayUri(uri, NULL);
6371         ok(hr == E_POINTER, "Error: GetDisplayUri returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
6372
6373         hr = IUri_GetDomain(uri, NULL);
6374         ok(hr == E_POINTER, "Error: GetDomain returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
6375
6376         hr = IUri_GetExtension(uri, NULL);
6377         ok(hr == E_POINTER, "Error: GetExtension returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
6378
6379         hr = IUri_GetFragment(uri, NULL);
6380         ok(hr == E_POINTER, "Error: GetFragment returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
6381
6382         hr = IUri_GetHost(uri, NULL);
6383         ok(hr == E_POINTER, "Error: GetHost returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
6384
6385         hr = IUri_GetPassword(uri, NULL);
6386         ok(hr == E_POINTER, "Error: GetPassword returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
6387
6388         hr = IUri_GetPath(uri, NULL);
6389         ok(hr == E_POINTER, "Error: GetPath returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
6390
6391         hr = IUri_GetPathAndQuery(uri, NULL);
6392         ok(hr == E_POINTER, "Error: GetPathAndQuery returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
6393
6394         hr = IUri_GetQuery(uri, NULL);
6395         ok(hr == E_POINTER, "Error: GetQuery returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
6396
6397         hr = IUri_GetRawUri(uri, NULL);
6398         ok(hr == E_POINTER, "Error: GetRawUri returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
6399
6400         hr = IUri_GetSchemeName(uri, NULL);
6401         ok(hr == E_POINTER, "Error: GetSchemeName returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
6402
6403         hr = IUri_GetUserInfo(uri, NULL);
6404         ok(hr == E_POINTER, "Error: GetUserInfo returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
6405
6406         hr = IUri_GetUserName(uri, NULL);
6407         ok(hr == E_POINTER, "Error: GetUserName returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
6408     }
6409     if(uri) IUri_Release(uri);
6410
6411     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
6412         uri_properties test = uri_tests[i];
6413         LPWSTR uriW;
6414         uri = NULL;
6415
6416         uriW = a2w(test.uri);
6417         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
6418         if(test.create_todo) {
6419             todo_wine {
6420                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6421                         hr, test.create_expected, i);
6422             }
6423         } else {
6424             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6425                     hr, test.create_expected, i);
6426         }
6427
6428         if(SUCCEEDED(hr)) {
6429             uri_str_property prop;
6430             BSTR received = NULL;
6431
6432             /* GetAbsoluteUri() tests. */
6433             prop = test.str_props[Uri_PROPERTY_ABSOLUTE_URI];
6434             hr = IUri_GetAbsoluteUri(uri, &received);
6435             if(prop.todo) {
6436                 todo_wine {
6437                     ok(hr == prop.expected, "Error: GetAbsoluteUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6438                             hr, prop.expected, i);
6439                 }
6440                 todo_wine {
6441                     ok(!strcmp_aw(prop.value, received) || broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
6442                             "Error: Expected %s but got %s on uri_tests[%d].\n",
6443                             prop.value, wine_dbgstr_w(received), i);
6444                 }
6445             } else {
6446                 ok(hr == prop.expected, "Error: GetAbsoluteUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6447                         hr, prop.expected, i);
6448                 ok(!strcmp_aw(prop.value, received) || broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
6449                         "Error: Expected %s but got %s on uri_tests[%d].\n",
6450                         prop.value, wine_dbgstr_w(received), i);
6451             }
6452             SysFreeString(received);
6453             received = NULL;
6454
6455             /* GetAuthority() tests. */
6456             prop = test.str_props[Uri_PROPERTY_AUTHORITY];
6457             hr = IUri_GetAuthority(uri, &received);
6458             if(prop.todo) {
6459                 todo_wine {
6460                     ok(hr == prop.expected, "Error: GetAuthority returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6461                             hr, prop.expected, i);
6462                 }
6463                 todo_wine {
6464                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6465                             prop.value, wine_dbgstr_w(received), i);
6466                 }
6467             } else {
6468                 ok(hr == prop.expected, "Error: GetAuthority returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6469                         hr, prop.expected, i);
6470                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6471                         prop.value, wine_dbgstr_w(received), i);
6472             }
6473             SysFreeString(received);
6474             received = NULL;
6475
6476             /* GetDisplayUri() tests. */
6477             prop = test.str_props[Uri_PROPERTY_DISPLAY_URI];
6478             hr = IUri_GetDisplayUri(uri, &received);
6479             if(prop.todo) {
6480                 todo_wine {
6481                     ok(hr == prop.expected, "Error: GetDisplayUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6482                             hr, prop.expected, i);
6483                 }
6484                 todo_wine {
6485                     ok(!strcmp_aw(prop.value, received) || broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
6486                             "Error: Expected %s but got %s on uri_test[%d].\n",
6487                             prop.value, wine_dbgstr_w(received), i);
6488                 }
6489             } else {
6490                 ok(hr == prop.expected, "Error: GetDisplayUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6491                         hr, prop.expected, i);
6492                 ok(!strcmp_aw(prop.value, received) || broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
6493                         "Error: Expected %s but got %s on uri_tests[%d].\n",
6494                         prop.value, wine_dbgstr_w(received), i);
6495             }
6496             SysFreeString(received);
6497             received = NULL;
6498
6499             /* GetDomain() tests. */
6500             prop = test.str_props[Uri_PROPERTY_DOMAIN];
6501             hr = IUri_GetDomain(uri, &received);
6502             if(prop.todo) {
6503                 todo_wine {
6504                     ok(hr == prop.expected, "Error: GetDomain returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6505                             hr, prop.expected, i);
6506                 }
6507                 todo_wine {
6508                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6509                             prop.value, wine_dbgstr_w(received), i);
6510                 }
6511             } else {
6512                 ok(hr == prop.expected, "Error: GetDomain returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6513                         hr, prop.expected, i);
6514                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6515                         prop.value, wine_dbgstr_w(received), i);
6516             }
6517             SysFreeString(received);
6518             received = NULL;
6519
6520             /* GetExtension() tests. */
6521             prop = test.str_props[Uri_PROPERTY_EXTENSION];
6522             hr = IUri_GetExtension(uri, &received);
6523             if(prop.todo) {
6524                 todo_wine {
6525                     ok(hr == prop.expected, "Error: GetExtension returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6526                             hr, prop.expected, i);
6527                 }
6528                 todo_wine {
6529                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6530                             prop.value, wine_dbgstr_w(received), i);
6531                 }
6532             } else {
6533                 ok(hr == prop.expected, "Error: GetExtension returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6534                         hr, prop.expected, i);
6535                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6536                         prop.value, wine_dbgstr_w(received), i);
6537             }
6538             SysFreeString(received);
6539             received = NULL;
6540
6541             /* GetFragment() tests. */
6542             prop = test.str_props[Uri_PROPERTY_FRAGMENT];
6543             hr = IUri_GetFragment(uri, &received);
6544             if(prop.todo) {
6545                 todo_wine {
6546                     ok(hr == prop.expected, "Error: GetFragment returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6547                             hr, prop.expected, i);
6548                 }
6549                 todo_wine {
6550                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6551                             prop.value, wine_dbgstr_w(received), i);
6552                 }
6553             } else {
6554                 ok(hr == prop.expected, "Error: GetFragment returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6555                         hr, prop.expected, i);
6556                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6557                         prop.value, wine_dbgstr_w(received), i);
6558             }
6559             SysFreeString(received);
6560             received = NULL;
6561
6562             /* GetHost() tests. */
6563             prop = test.str_props[Uri_PROPERTY_HOST];
6564             hr = IUri_GetHost(uri, &received);
6565             if(prop.todo) {
6566                 todo_wine {
6567                     ok(hr == prop.expected, "Error: GetHost returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6568                             hr, prop.expected, i);
6569                 }
6570                 todo_wine {
6571                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6572                             prop.value, wine_dbgstr_w(received), i);
6573                 }
6574             } else {
6575                 ok(hr == prop.expected, "Error: GetHost returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6576                         hr, prop.expected, i);
6577                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6578                         prop.value, wine_dbgstr_w(received), i);
6579             }
6580             SysFreeString(received);
6581             received = NULL;
6582
6583             /* GetPassword() tests. */
6584             prop = test.str_props[Uri_PROPERTY_PASSWORD];
6585             hr = IUri_GetPassword(uri, &received);
6586             if(prop.todo) {
6587                 todo_wine {
6588                     ok(hr == prop.expected, "Error: GetPassword returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6589                             hr, prop.expected, i);
6590                 }
6591                 todo_wine {
6592                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6593                             prop.value, wine_dbgstr_w(received), i);
6594                 }
6595             } else {
6596                 ok(hr == prop.expected, "Error: GetPassword returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6597                         hr, prop.expected, i);
6598                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6599                         prop.value, wine_dbgstr_w(received), i);
6600             }
6601             SysFreeString(received);
6602             received = NULL;
6603
6604             /* GetPath() tests. */
6605             prop = test.str_props[Uri_PROPERTY_PATH];
6606             hr = IUri_GetPath(uri, &received);
6607             if(prop.todo) {
6608                 todo_wine {
6609                     ok(hr == prop.expected, "Error: GetPath returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6610                             hr, prop.expected, i);
6611                 }
6612                 todo_wine {
6613                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6614                             prop.value, wine_dbgstr_w(received), i);
6615                 }
6616             } else {
6617                 ok(hr == prop.expected, "Error: GetPath returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6618                         hr, prop.expected, i);
6619                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6620                         prop.value, wine_dbgstr_w(received), i);
6621             }
6622             SysFreeString(received);
6623             received = NULL;
6624
6625             /* GetPathAndQuery() tests. */
6626             prop = test.str_props[Uri_PROPERTY_PATH_AND_QUERY];
6627             hr = IUri_GetPathAndQuery(uri, &received);
6628             if(prop.todo) {
6629                 todo_wine {
6630                     ok(hr == prop.expected, "Error: GetPathAndQuery returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6631                             hr, prop.expected, i);
6632                 }
6633                 todo_wine {
6634                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6635                             prop.value, wine_dbgstr_w(received), i);
6636                 }
6637             } else {
6638                 ok(hr == prop.expected, "Error: GetPathAndQuery returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6639                         hr, prop.expected, i);
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             SysFreeString(received);
6644             received = NULL;
6645
6646             /* GetQuery() tests. */
6647             prop = test.str_props[Uri_PROPERTY_QUERY];
6648             hr = IUri_GetQuery(uri, &received);
6649             if(prop.todo) {
6650                 todo_wine {
6651                     ok(hr == prop.expected, "Error: GetQuery returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6652                             hr, prop.expected, i);
6653                 }
6654                 todo_wine {
6655                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6656                             prop.value, wine_dbgstr_w(received), i);
6657                 }
6658             } else {
6659                 ok(hr == prop.expected, "Error: GetQuery returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6660                         hr, prop.expected, i);
6661                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6662                         prop.value, wine_dbgstr_w(received), i);
6663             }
6664             SysFreeString(received);
6665             received = NULL;
6666
6667             /* GetRawUri() tests. */
6668             prop = test.str_props[Uri_PROPERTY_RAW_URI];
6669             hr = IUri_GetRawUri(uri, &received);
6670             if(prop.todo) {
6671                 todo_wine {
6672                     ok(hr == prop.expected, "Error: GetRawUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6673                             hr, prop.expected, i);
6674                 }
6675                 todo_wine {
6676                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6677                             prop.value, wine_dbgstr_w(received), i);
6678                 }
6679             } else {
6680                 ok(hr == prop.expected, "Error: GetRawUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6681                         hr, prop.expected, i);
6682                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6683                         prop.value, wine_dbgstr_w(received), i);
6684             }
6685             SysFreeString(received);
6686             received = NULL;
6687
6688             /* GetSchemeName() tests. */
6689             prop = test.str_props[Uri_PROPERTY_SCHEME_NAME];
6690             hr = IUri_GetSchemeName(uri, &received);
6691             if(prop.todo) {
6692                 todo_wine {
6693                     ok(hr == prop.expected, "Error: GetSchemeName returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6694                             hr, prop.expected, i);
6695                 }
6696                 todo_wine {
6697                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6698                             prop.value, wine_dbgstr_w(received), i);
6699                 }
6700             } else {
6701                 ok(hr == prop.expected, "Error: GetSchemeName returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6702                         hr, prop.expected, i);
6703                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6704                         prop.value, wine_dbgstr_w(received), i);
6705             }
6706             SysFreeString(received);
6707             received = NULL;
6708
6709             /* GetUserInfo() tests. */
6710             prop = test.str_props[Uri_PROPERTY_USER_INFO];
6711             hr = IUri_GetUserInfo(uri, &received);
6712             if(prop.todo) {
6713                 todo_wine {
6714                     ok(hr == prop.expected, "Error: GetUserInfo returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6715                             hr, prop.expected, i);
6716                 }
6717                 todo_wine {
6718                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6719                             prop.value, wine_dbgstr_w(received), i);
6720                 }
6721             } else {
6722                 ok(hr == prop.expected, "Error: GetUserInfo returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6723                         hr, prop.expected, i);
6724                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6725                         prop.value, wine_dbgstr_w(received), i);
6726             }
6727             SysFreeString(received);
6728             received = NULL;
6729
6730             /* GetUserName() tests. */
6731             prop = test.str_props[Uri_PROPERTY_USER_NAME];
6732             hr = IUri_GetUserName(uri, &received);
6733             if(prop.todo) {
6734                 todo_wine {
6735                     ok(hr == prop.expected, "Error: GetUserName returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6736                             hr, prop.expected, i);
6737                 }
6738                 todo_wine {
6739                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6740                             prop.value, wine_dbgstr_w(received), i);
6741                 }
6742             } else {
6743                 ok(hr == prop.expected, "Error: GetUserName returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6744                         hr, prop.expected, i);
6745                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
6746                         prop.value, wine_dbgstr_w(received), i);
6747             }
6748             SysFreeString(received);
6749         }
6750
6751         if(uri) IUri_Release(uri);
6752
6753         heap_free(uriW);
6754     }
6755 }
6756
6757 static void test_IUri_GetDwordProperties(void) {
6758     IUri *uri = NULL;
6759     HRESULT hr;
6760     DWORD i;
6761
6762     /* Make sure all the 'Get*' dword property functions handle invalid args correctly. */
6763     hr = pCreateUri(http_urlW, 0, 0, &uri);
6764     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
6765     if(SUCCEEDED(hr)) {
6766         hr = IUri_GetHostType(uri, NULL);
6767         ok(hr == E_INVALIDARG, "Error: GetHostType returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
6768
6769         hr = IUri_GetPort(uri, NULL);
6770         ok(hr == E_INVALIDARG, "Error: GetPort returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
6771
6772         hr = IUri_GetScheme(uri, NULL);
6773         ok(hr == E_INVALIDARG, "Error: GetScheme returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
6774
6775         hr = IUri_GetZone(uri, NULL);
6776         ok(hr == E_INVALIDARG, "Error: GetZone returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
6777     }
6778     if(uri) IUri_Release(uri);
6779
6780     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
6781         uri_properties test = uri_tests[i];
6782         LPWSTR uriW;
6783         uri = NULL;
6784
6785         uriW = a2w(test.uri);
6786         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
6787         if(test.create_todo) {
6788             todo_wine {
6789                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6790                         hr, test.create_expected, i);
6791             }
6792         } else {
6793             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6794                     hr, test.create_expected, i);
6795         }
6796
6797         if(SUCCEEDED(hr)) {
6798             uri_dword_property prop;
6799             DWORD received;
6800
6801             /* Assign an insane value so tests don't accidentally pass when
6802              * they shouldn't!
6803              */
6804             received = -9999999;
6805
6806             /* GetHostType() tests. */
6807             prop = test.dword_props[Uri_PROPERTY_HOST_TYPE-Uri_PROPERTY_DWORD_START];
6808             hr = IUri_GetHostType(uri, &received);
6809             if(prop.todo) {
6810                 todo_wine {
6811                     ok(hr == prop.expected, "Error: GetHostType returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6812                             hr, prop.expected, i);
6813                 }
6814                 todo_wine {
6815                     ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
6816                 }
6817             } else {
6818                 ok(hr == prop.expected, "Error: GetHostType returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6819                         hr, prop.expected, i);
6820                 ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
6821             }
6822             received = -9999999;
6823
6824             /* GetPort() tests. */
6825             prop = test.dword_props[Uri_PROPERTY_PORT-Uri_PROPERTY_DWORD_START];
6826             hr = IUri_GetPort(uri, &received);
6827             if(prop.todo) {
6828                 todo_wine {
6829                     ok(hr == prop.expected, "Error: GetPort returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6830                             hr, prop.expected, i);
6831                 }
6832                 todo_wine {
6833                     ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
6834                 }
6835             } else {
6836                 ok(hr == prop.expected, "Error: GetPort returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6837                         hr, prop.expected, i);
6838                 ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
6839             }
6840             received = -9999999;
6841
6842             /* GetScheme() tests. */
6843             prop = test.dword_props[Uri_PROPERTY_SCHEME-Uri_PROPERTY_DWORD_START];
6844             hr = IUri_GetScheme(uri, &received);
6845             if(prop.todo) {
6846                 todo_wine {
6847                     ok(hr == prop.expected, "Error: GetScheme returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6848                             hr, prop.expected, i);
6849                 }
6850                 todo_wine {
6851                     ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
6852                 }
6853             } else {
6854                 ok(hr == prop.expected, "Error: GetScheme returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6855                         hr, prop.expected, i);
6856                 ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
6857             }
6858             received = -9999999;
6859
6860             /* GetZone() tests. */
6861             prop = test.dword_props[Uri_PROPERTY_ZONE-Uri_PROPERTY_DWORD_START];
6862             hr = IUri_GetZone(uri, &received);
6863             if(prop.todo) {
6864                 todo_wine {
6865                     ok(hr == prop.expected, "Error: GetZone returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6866                             hr, prop.expected, i);
6867                 }
6868                 todo_wine {
6869                     ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
6870                 }
6871             } else {
6872                 ok(hr == prop.expected, "Error: GetZone returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6873                         hr, prop.expected, i);
6874                 ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
6875             }
6876         }
6877
6878         if(uri) IUri_Release(uri);
6879
6880         heap_free(uriW);
6881     }
6882 }
6883
6884 static void test_IUri_GetPropertyLength(void) {
6885     IUri *uri = NULL;
6886     HRESULT hr;
6887     DWORD i;
6888
6889     /* Make sure it handles invalid args correctly. */
6890     hr = pCreateUri(http_urlW, 0, 0, &uri);
6891     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
6892     if(SUCCEEDED(hr)) {
6893         DWORD received = 0xdeadbeef;
6894
6895         hr = IUri_GetPropertyLength(uri, Uri_PROPERTY_STRING_START, NULL, 0);
6896         ok(hr == E_INVALIDARG, "Error: GetPropertyLength returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
6897
6898         hr = IUri_GetPropertyLength(uri, Uri_PROPERTY_DWORD_START, &received, 0);
6899         ok(hr == E_INVALIDARG, "Error: GetPropertyLength return 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
6900         ok(received == 0xdeadbeef, "Error: Expected 0xdeadbeef but got 0x%08x.\n", received);
6901     }
6902     if(uri) IUri_Release(uri);
6903
6904     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
6905         uri_properties test = uri_tests[i];
6906         LPWSTR uriW;
6907         uri = NULL;
6908
6909         uriW = a2w(test.uri);
6910         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
6911         if(test.create_todo) {
6912             todo_wine {
6913                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
6914                         hr, test.create_expected, i);
6915             }
6916         } else {
6917             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_test[%d].\n",
6918                     hr, test.create_expected, i);
6919         }
6920
6921         if(SUCCEEDED(hr)) {
6922             DWORD j;
6923
6924             for(j = Uri_PROPERTY_STRING_START; j <= Uri_PROPERTY_STRING_LAST; ++j) {
6925                 DWORD expectedLen, brokenLen, receivedLen;
6926                 uri_str_property prop = test.str_props[j];
6927
6928                 expectedLen = lstrlen(prop.value);
6929                 brokenLen = lstrlen(prop.broken_value);
6930
6931                 /* This won't be necessary once GetPropertyLength is implemented. */
6932                 receivedLen = -1;
6933
6934                 hr = IUri_GetPropertyLength(uri, j, &receivedLen, 0);
6935                 if(prop.todo) {
6936                     todo_wine {
6937                         ok(hr == prop.expected, "Error: GetPropertyLength returned 0x%08x, expected 0x%08x on uri_tests[%d].str_props[%d].\n",
6938                                 hr, prop.expected, i, j);
6939                     }
6940                     todo_wine {
6941                         ok(receivedLen == expectedLen || broken(receivedLen == brokenLen),
6942                                 "Error: Expected a length of %d but got %d on uri_tests[%d].str_props[%d].\n",
6943                                 expectedLen, receivedLen, i, j);
6944                     }
6945                 } else {
6946                     ok(hr == prop.expected, "Error: GetPropertyLength returned 0x%08x, expected 0x%08x on uri_tests[%d].str_props[%d].\n",
6947                             hr, prop.expected, i, j);
6948                     ok(receivedLen == expectedLen || broken(receivedLen == brokenLen),
6949                             "Error: Expected a length of %d but got %d on uri_tests[%d].str_props[%d].\n",
6950                             expectedLen, receivedLen, i, j);
6951                 }
6952             }
6953         }
6954
6955         if(uri) IUri_Release(uri);
6956
6957         heap_free(uriW);
6958     }
6959 }
6960
6961 static DWORD compute_expected_props(uri_properties *test)
6962 {
6963     DWORD ret = 0, i;
6964
6965     for(i=Uri_PROPERTY_STRING_START; i <= Uri_PROPERTY_STRING_LAST; i++) {
6966         if(test->str_props[i-Uri_PROPERTY_STRING_START].expected == S_OK)
6967             ret |= 1<<i;
6968     }
6969
6970     for(i=Uri_PROPERTY_DWORD_START; i <= Uri_PROPERTY_DWORD_LAST; i++) {
6971         if(test->dword_props[i-Uri_PROPERTY_DWORD_START].expected == S_OK)
6972             ret |= 1<<i;
6973     }
6974
6975     return ret;
6976 }
6977
6978 static void test_IUri_GetProperties(void) {
6979     IUri *uri = NULL;
6980     HRESULT hr;
6981     DWORD i;
6982
6983     hr = pCreateUri(http_urlW, 0, 0, &uri);
6984     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
6985     if(SUCCEEDED(hr)) {
6986         hr = IUri_GetProperties(uri, NULL);
6987         ok(hr == E_INVALIDARG, "Error: GetProperties returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
6988     }
6989     if(uri) IUri_Release(uri);
6990
6991     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
6992         uri_properties test = uri_tests[i];
6993         LPWSTR uriW;
6994         uri = NULL;
6995
6996         uriW = a2w(test.uri);
6997         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
6998         if(test.create_todo) {
6999             todo_wine {
7000                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, test.create_expected);
7001             }
7002         } else {
7003             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, test.create_expected);
7004         }
7005
7006         if(SUCCEEDED(hr)) {
7007             DWORD received = 0, expected_props;
7008             DWORD j;
7009
7010             hr = IUri_GetProperties(uri, &received);
7011             ok(hr == S_OK, "Error: GetProperties returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7012
7013             expected_props = compute_expected_props(&test);
7014
7015             for(j = 0; j <= Uri_PROPERTY_DWORD_LAST; ++j) {
7016                 /* (1 << j) converts a Uri_PROPERTY to its corresponding Uri_HAS_* flag mask. */
7017                 if(expected_props & (1 << j))
7018                     ok(received & (1 << j), "Error: Expected flag for property %d on uri_tests[%d].\n", j, i);
7019                 else
7020                     ok(!(received & (1 << j)), "Error: Received flag for property %d when not expected on uri_tests[%d].\n", j, i);
7021             }
7022         }
7023
7024         if(uri) IUri_Release(uri);
7025
7026         heap_free(uriW);
7027     }
7028 }
7029
7030 static void test_IUri_HasProperty(void) {
7031     IUri *uri = NULL;
7032     HRESULT hr;
7033     DWORD i;
7034
7035     hr = pCreateUri(http_urlW, 0, 0, &uri);
7036     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7037     if(SUCCEEDED(hr)) {
7038         hr = IUri_HasProperty(uri, Uri_PROPERTY_RAW_URI, NULL);
7039         ok(hr == E_INVALIDARG, "Error: HasProperty returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
7040     }
7041     if(uri) IUri_Release(uri);
7042
7043     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
7044         uri_properties test = uri_tests[i];
7045         LPWSTR uriW;
7046         uri = NULL;
7047
7048         uriW = a2w(test.uri);
7049
7050         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
7051         if(test.create_todo) {
7052             todo_wine {
7053                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, test.create_expected);
7054             }
7055         } else {
7056             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, test.create_expected);
7057         }
7058
7059         if(SUCCEEDED(hr)) {
7060             DWORD expected_props, j;
7061
7062             expected_props = compute_expected_props(&test);
7063
7064             for(j = 0; j <= Uri_PROPERTY_DWORD_LAST; ++j) {
7065                 /* Assign -1, then explicitly test for TRUE or FALSE later. */
7066                 BOOL received = -1;
7067
7068                 hr = IUri_HasProperty(uri, j, &received);
7069                 ok(hr == S_OK, "Error: HasProperty returned 0x%08x, expected 0x%08x for property %d on uri_tests[%d].\n",
7070                         hr, S_OK, j, i);
7071
7072                 if(expected_props & (1 << j)) {
7073                     ok(received == TRUE, "Error: Expected to have property %d on uri_tests[%d].\n", j, i);
7074                 } else {
7075                     ok(received == FALSE, "Error: Wasn't expecting to have property %d on uri_tests[%d].\n", j, i);
7076                 }
7077             }
7078         }
7079
7080         if(uri) IUri_Release(uri);
7081
7082         heap_free(uriW);
7083     }
7084 }
7085
7086 static void test_IUri_IsEqual(void) {
7087     IUri *uriA, *uriB;
7088     HRESULT hrA, hrB;
7089     DWORD i;
7090
7091     uriA = uriB = NULL;
7092
7093     /* Make sure IsEqual handles invalid args correctly. */
7094     hrA = pCreateUri(http_urlW, 0, 0, &uriA);
7095     hrB = pCreateUri(http_urlW, 0, 0, &uriB);
7096     ok(hrA == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hrA, S_OK);
7097     ok(hrB == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hrB, S_OK);
7098     if(SUCCEEDED(hrA) && SUCCEEDED(hrB)) {
7099         BOOL equal = -1;
7100         hrA = IUri_IsEqual(uriA, NULL, &equal);
7101         ok(hrA == S_OK, "Error: IsEqual returned 0x%08x, expected 0x%08x.\n", hrA, S_OK);
7102         ok(equal == FALSE, "Error: Expected equal to be FALSE, but was %d instead.\n", equal);
7103
7104         hrA = IUri_IsEqual(uriA, uriB, NULL);
7105         ok(hrA == E_POINTER, "Error: IsEqual returned 0x%08x, expected 0x%08x.\n", hrA, E_POINTER);
7106     }
7107     if(uriA) IUri_Release(uriA);
7108     if(uriB) IUri_Release(uriB);
7109
7110     for(i = 0; i < sizeof(equality_tests)/sizeof(equality_tests[0]); ++i) {
7111         uri_equality test = equality_tests[i];
7112         LPWSTR uriA_W, uriB_W;
7113
7114         uriA = uriB = NULL;
7115
7116         uriA_W = a2w(test.a);
7117         uriB_W = a2w(test.b);
7118
7119         hrA = pCreateUri(uriA_W, test.create_flags_a, 0, &uriA);
7120         if(test.create_todo_a) {
7121             todo_wine {
7122                 ok(hrA == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x on equality_tests[%d].a\n",
7123                         hrA, S_OK, i);
7124             }
7125         } else {
7126             ok(hrA == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x on equality_tests[%d].a\n",
7127                     hrA, S_OK, i);
7128         }
7129
7130         hrB = pCreateUri(uriB_W, test.create_flags_b, 0, &uriB);
7131         if(test.create_todo_b) {
7132             todo_wine {
7133                 ok(hrB == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x on equality_tests[%d].b\n",
7134                         hrB, S_OK, i);
7135             }
7136         } else {
7137             ok(hrB == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x on equality_tests[%d].b\n",
7138                     hrB, S_OK, i);
7139         }
7140
7141         if(SUCCEEDED(hrA) && SUCCEEDED(hrB)) {
7142             BOOL equal = -1;
7143
7144             hrA = IUri_IsEqual(uriA, uriB, &equal);
7145             if(test.todo) {
7146                 todo_wine {
7147                     ok(hrA == S_OK, "Error: IsEqual returned 0x%08x, expected 0x%08x on equality_tests[%d].\n",
7148                             hrA, S_OK, i);
7149                 }
7150                 todo_wine {
7151                     ok(equal == test.equal, "Error: Expected the comparison to be %d on equality_tests[%d].\n", test.equal, i);
7152                 }
7153             } else {
7154                 ok(hrA == S_OK, "Error: IsEqual returned 0x%08x, expected 0x%08x on equality_tests[%d].\n", hrA, S_OK, i);
7155                 ok(equal == test.equal, "Error: Expected the comparison to be %d on equality_tests[%d].\n", test.equal, i);
7156             }
7157         }
7158         if(uriA) IUri_Release(uriA);
7159         if(uriB) IUri_Release(uriB);
7160
7161         heap_free(uriA_W);
7162         heap_free(uriB_W);
7163     }
7164 }
7165
7166 static void test_CreateUriWithFragment_InvalidArgs(void) {
7167     HRESULT hr;
7168     IUri *uri = (void*) 0xdeadbeef;
7169     const WCHAR fragmentW[] = {'#','f','r','a','g','m','e','n','t',0};
7170
7171     hr = pCreateUriWithFragment(NULL, fragmentW, 0, 0, &uri);
7172     ok(hr == E_INVALIDARG, "Error: CreateUriWithFragment returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
7173     ok(uri == NULL, "Error: Expected uri to be NULL, but was %p instead.\n", uri);
7174
7175     hr = pCreateUriWithFragment(http_urlW, fragmentW, 0, 0, NULL);
7176     ok(hr == E_INVALIDARG, "Error: CreateUriWithFragment returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
7177
7178     /* Original URI can't already contain a fragment component. */
7179     uri = (void*) 0xdeadbeef;
7180     hr = pCreateUriWithFragment(http_url_fragW, fragmentW, 0, 0, &uri);
7181     ok(hr == E_INVALIDARG, "Error: CreateUriWithFragment returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
7182     ok(uri == NULL, "Error: Expected uri to be NULL, but was %p instead.\n", uri);
7183 }
7184
7185 /* CreateUriWithFragment has the same invalid flag combinations as CreateUri. */
7186 static void test_CreateUriWithFragment_InvalidFlags(void) {
7187     DWORD i;
7188
7189     for(i = 0; i < sizeof(invalid_flag_tests)/sizeof(invalid_flag_tests[0]); ++i) {
7190         HRESULT hr;
7191         IUri *uri = (void*) 0xdeadbeef;
7192
7193         hr = pCreateUriWithFragment(http_urlW, NULL, invalid_flag_tests[i].flags, 0, &uri);
7194         ok(hr == invalid_flag_tests[i].expected, "Error: CreateUriWithFragment returned 0x%08x, expected 0x%08x. flags=0x%08x.\n",
7195             hr, invalid_flag_tests[i].expected, invalid_flag_tests[i].flags);
7196         ok(uri == NULL, "Error: Expected uri to be NULL, but was %p instead.\n", uri);
7197     }
7198 }
7199
7200 static void test_CreateUriWithFragment(void) {
7201     DWORD i;
7202
7203     for(i = 0; i < sizeof(uri_fragment_tests)/sizeof(uri_fragment_tests[0]); ++i) {
7204         HRESULT hr;
7205         IUri *uri = NULL;
7206         LPWSTR uriW, fragW;
7207         uri_with_fragment test = uri_fragment_tests[i];
7208
7209         uriW = a2w(test.uri);
7210         fragW = a2w(test.fragment);
7211
7212         hr = pCreateUriWithFragment(uriW, fragW, test.create_flags, 0, &uri);
7213         if(test.expected_todo) {
7214             todo_wine {
7215                 ok(hr == test.create_expected,
7216                     "Error: CreateUriWithFragment returned 0x%08x, expected 0x%08x on uri_fragment_tests[%d].\n",
7217                     hr, test.create_expected, i);
7218             }
7219         } else
7220             ok(hr == test.create_expected,
7221                 "Error: CreateUriWithFragment returned 0x%08x, expected 0x%08x on uri_fragment_tests[%d].\n",
7222                 hr, test.create_expected, i);
7223
7224         if(SUCCEEDED(hr)) {
7225             BSTR received = NULL;
7226
7227             hr = IUri_GetAbsoluteUri(uri, &received);
7228             if(test.expected_todo) {
7229                 todo_wine {
7230                     ok(hr == S_OK,
7231                         "Error: GetAbsoluteUri returned 0x%08x, expected 0x%08x on uri_fragment_tests[%d].\n",
7232                         hr, S_OK, i);
7233                 }
7234                 todo_wine {
7235                     ok(!strcmp_aw(test.expected_uri, received),
7236                         "Error: Expected %s but got %s on uri_fragment_tests[%d].\n",
7237                         test.expected_uri, wine_dbgstr_w(received), i);
7238                 }
7239             } else {
7240                 ok(hr == S_OK, "Error: GetAbsoluteUri returned 0x%08x, expected 0x%08x on uri_fragment_tests[%d].\n",
7241                     hr, S_OK, i);
7242                 ok(!strcmp_aw(test.expected_uri, received), "Error: Expected %s but got %s on uri_fragment_tests[%d].\n",
7243                     test.expected_uri, wine_dbgstr_w(received), i);
7244             }
7245
7246             SysFreeString(received);
7247         }
7248
7249         if(uri) IUri_Release(uri);
7250         heap_free(uriW);
7251     }
7252 }
7253
7254 static void test_CreateIUriBuilder(void) {
7255     HRESULT hr;
7256     IUriBuilder *builder = NULL;
7257     IUri *uri;
7258
7259     hr = pCreateIUriBuilder(NULL, 0, 0, NULL);
7260     ok(hr == E_POINTER, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x\n",
7261         hr, E_POINTER);
7262
7263     /* CreateIUriBuilder increases the ref count of the IUri it receives. */
7264     hr = pCreateUri(http_urlW, 0, 0, &uri);
7265     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7266     if(SUCCEEDED(hr)) {
7267         ULONG cur_count, orig_count;
7268
7269         orig_count = get_refcnt(uri);
7270         hr = pCreateIUriBuilder(uri, 0, 0, &builder);
7271         ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7272         ok(builder != NULL, "Error: Expecting builder not to be NULL\n");
7273
7274         cur_count = get_refcnt(uri);
7275         ok(cur_count == orig_count+1, "Error: Expected the ref count to be %u, but was %u instead.\n", orig_count+1, cur_count);
7276
7277         if(builder) IUriBuilder_Release(builder);
7278         cur_count = get_refcnt(uri);
7279         ok(cur_count == orig_count, "Error: Expected the ref count to be %u, but was %u instead.\n", orig_count, cur_count);
7280     }
7281     if(uri) IUri_Release(uri);
7282 }
7283
7284 static void test_IUriBuilder_CreateUri(IUriBuilder *builder, const uri_builder_test *test,
7285                                        DWORD test_index) {
7286     HRESULT hr;
7287     IUri *uri = NULL;
7288
7289     hr = IUriBuilder_CreateUri(builder, test->uri_flags, 0, 0, &uri);
7290     if(test->uri_todo) {
7291         todo_wine {
7292             ok(hr == test->uri_hres,
7293                 "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7294                 hr, test->uri_hres, test_index);
7295         }
7296     } else {
7297         ok(hr == test->uri_hres,
7298             "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7299             hr, test->uri_hres, test_index);
7300     }
7301
7302     if(SUCCEEDED(hr)) {
7303         DWORD i;
7304
7305         for(i = 0; i < sizeof(test->expected_str_props)/sizeof(test->expected_str_props[0]); ++i) {
7306             uri_builder_str_property prop = test->expected_str_props[i];
7307             BSTR received = NULL;
7308
7309             hr = IUri_GetPropertyBSTR(uri, i, &received, 0);
7310             if(prop.todo) {
7311                 todo_wine {
7312                     ok(hr == prop.result,
7313                         "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_str_props[%d].\n",
7314                         hr, prop.result, test_index, i);
7315                 }
7316             } else {
7317                 ok(hr == prop.result,
7318                     "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_str_props[%d].\n",
7319                     hr, prop.result, test_index, i);
7320             }
7321             if(SUCCEEDED(hr)) {
7322                 if(prop.todo) {
7323                     todo_wine {
7324                         ok(!strcmp_aw(prop.expected, received),
7325                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].expected_str_props[%d].\n",
7326                             prop.expected, wine_dbgstr_w(received), test_index, i);
7327                     }
7328                 } else {
7329                     ok(!strcmp_aw(prop.expected, received),
7330                         "Error: Expected %s but got %s instead on uri_builder_tests[%d].expected_str_props[%d].\n",
7331                         prop.expected, wine_dbgstr_w(received), test_index, i);
7332                 }
7333             }
7334             SysFreeString(received);
7335         }
7336
7337         for(i = 0; i < sizeof(test->expected_dword_props)/sizeof(test->expected_dword_props[0]); ++i) {
7338             uri_builder_dword_property prop = test->expected_dword_props[i];
7339             DWORD received = -2;
7340
7341             hr = IUri_GetPropertyDWORD(uri, i+Uri_PROPERTY_DWORD_START, &received, 0);
7342             if(prop.todo) {
7343                 todo_wine {
7344                     ok(hr == prop.result,
7345                         "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_dword_props[%d].\n",
7346                         hr, prop.result, test_index, i);
7347                 }
7348             } else {
7349                 ok(hr == prop.result,
7350                     "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_dword_props[%d].\n",
7351                     hr, prop.result, test_index, i);
7352             }
7353             if(SUCCEEDED(hr)) {
7354                 if(prop.todo) {
7355                     todo_wine {
7356                         ok(received == prop.expected,
7357                             "Error: Expected %d but got %d instead on uri_builder_tests[%d].expected_dword_props[%d].\n",
7358                             prop.expected, received, test_index, i);
7359                     }
7360                 } else {
7361                     ok(received == prop.expected,
7362                         "Error: Expected %d but got %d instead on uri_builder_tests[%d].expected_dword_props[%d].\n",
7363                         prop.expected, received, test_index, i);
7364                 }
7365             }
7366         }
7367     }
7368     if(uri) IUri_Release(uri);
7369 }
7370
7371 static void test_IUriBuilder_CreateUriSimple(IUriBuilder *builder, const uri_builder_test *test,
7372                                        DWORD test_index) {
7373     HRESULT hr;
7374     IUri *uri = NULL;
7375
7376     hr = IUriBuilder_CreateUriSimple(builder, test->uri_simple_encode_flags, 0, &uri);
7377     if(test->uri_simple_todo) {
7378         todo_wine {
7379             ok(hr == test->uri_simple_hres,
7380                 "Error: IUriBuilder_CreateUriSimple returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7381                 hr, test->uri_simple_hres, test_index);
7382         }
7383     } else {
7384         ok(hr == test->uri_simple_hres,
7385             "Error: IUriBuilder_CreateUriSimple returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7386             hr, test->uri_simple_hres, test_index);
7387     }
7388
7389     if(SUCCEEDED(hr)) {
7390         DWORD i;
7391
7392         for(i = 0; i < sizeof(test->expected_str_props)/sizeof(test->expected_str_props[0]); ++i) {
7393             uri_builder_str_property prop = test->expected_str_props[i];
7394             BSTR received = NULL;
7395
7396             hr = IUri_GetPropertyBSTR(uri, i, &received, 0);
7397             if(prop.todo) {
7398                 todo_wine {
7399                     ok(hr == prop.result,
7400                         "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_str_props[%d].\n",
7401                         hr, prop.result, test_index, i);
7402                 }
7403             } else {
7404                 ok(hr == prop.result,
7405                     "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_str_props[%d].\n",
7406                     hr, prop.result, test_index, i);
7407             }
7408             if(SUCCEEDED(hr)) {
7409                 if(prop.todo) {
7410                     todo_wine {
7411                         ok(!strcmp_aw(prop.expected, received),
7412                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].expected_str_props[%d].\n",
7413                             prop.expected, wine_dbgstr_w(received), test_index, i);
7414                     }
7415                 } else {
7416                     ok(!strcmp_aw(prop.expected, received),
7417                         "Error: Expected %s but got %s instead on uri_builder_tests[%d].expected_str_props[%d].\n",
7418                         prop.expected, wine_dbgstr_w(received), test_index, i);
7419                 }
7420             }
7421             SysFreeString(received);
7422         }
7423
7424         for(i = 0; i < sizeof(test->expected_dword_props)/sizeof(test->expected_dword_props[0]); ++i) {
7425             uri_builder_dword_property prop = test->expected_dword_props[i];
7426             DWORD received = -2;
7427
7428             hr = IUri_GetPropertyDWORD(uri, i+Uri_PROPERTY_DWORD_START, &received, 0);
7429             if(prop.todo) {
7430                 todo_wine {
7431                     ok(hr == prop.result,
7432                         "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_dword_props[%d].\n",
7433                         hr, prop.result, test_index, i);
7434                 }
7435             } else {
7436                 ok(hr == prop.result,
7437                     "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_dword_props[%d].\n",
7438                     hr, prop.result, test_index, i);
7439             }
7440             if(SUCCEEDED(hr)) {
7441                 if(prop.todo) {
7442                     todo_wine {
7443                         ok(received == prop.expected,
7444                             "Error: Expected %d but got %d instead on uri_builder_tests[%d].expected_dword_props[%d].\n",
7445                             prop.expected, received, test_index, i);
7446                     }
7447                 } else {
7448                     ok(received == prop.expected,
7449                         "Error: Expected %d but got %d instead on uri_builder_tests[%d].expected_dword_props[%d].\n",
7450                         prop.expected, received, test_index, i);
7451                 }
7452             }
7453         }
7454     }
7455     if(uri) IUri_Release(uri);
7456 }
7457
7458 static void test_IUriBuilder_CreateUriWithFlags(IUriBuilder *builder, const uri_builder_test *test,
7459                                                 DWORD test_index) {
7460     HRESULT hr;
7461     IUri *uri = NULL;
7462
7463     hr = IUriBuilder_CreateUriWithFlags(builder, test->uri_with_flags, test->uri_with_builder_flags,
7464                                         test->uri_with_encode_flags, 0, &uri);
7465     if(test->uri_with_todo) {
7466         todo_wine {
7467             ok(hr == test->uri_with_hres,
7468                 "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7469                 hr, test->uri_with_hres, test_index);
7470         }
7471     } else {
7472         ok(hr == test->uri_with_hres,
7473             "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7474             hr, test->uri_with_hres, test_index);
7475     }
7476
7477     if(SUCCEEDED(hr)) {
7478         DWORD i;
7479
7480         for(i = 0; i < sizeof(test->expected_str_props)/sizeof(test->expected_str_props[0]); ++i) {
7481             uri_builder_str_property prop = test->expected_str_props[i];
7482             BSTR received = NULL;
7483
7484             hr = IUri_GetPropertyBSTR(uri, i, &received, 0);
7485             if(prop.todo) {
7486                 todo_wine {
7487                     ok(hr == prop.result,
7488                         "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_str_props[%d].\n",
7489                         hr, prop.result, test_index, i);
7490                 }
7491             } else {
7492                 ok(hr == prop.result,
7493                     "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_str_props[%d].\n",
7494                     hr, prop.result, test_index, i);
7495             }
7496             if(SUCCEEDED(hr)) {
7497                 if(prop.todo) {
7498                     todo_wine {
7499                         ok(!strcmp_aw(prop.expected, received),
7500                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].expected_str_props[%d].\n",
7501                             prop.expected, wine_dbgstr_w(received), test_index, i);
7502                     }
7503                 } else {
7504                     ok(!strcmp_aw(prop.expected, received),
7505                         "Error: Expected %s but got %s instead on uri_builder_tests[%d].expected_str_props[%d].\n",
7506                         prop.expected, wine_dbgstr_w(received), test_index, i);
7507                 }
7508             }
7509             SysFreeString(received);
7510         }
7511
7512         for(i = 0; i < sizeof(test->expected_dword_props)/sizeof(test->expected_dword_props[0]); ++i) {
7513             uri_builder_dword_property prop = test->expected_dword_props[i];
7514             DWORD received = -2;
7515
7516             hr = IUri_GetPropertyDWORD(uri, i+Uri_PROPERTY_DWORD_START, &received, 0);
7517             if(prop.todo) {
7518                 todo_wine {
7519                     ok(hr == prop.result,
7520                         "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_dword_props[%d].\n",
7521                         hr, prop.result, test_index, i);
7522                 }
7523             } else {
7524                 ok(hr == prop.result,
7525                     "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_dword_props[%d].\n",
7526                     hr, prop.result, test_index, i);
7527             }
7528             if(SUCCEEDED(hr)) {
7529                 if(prop.todo) {
7530                     todo_wine {
7531                         ok(received == prop.expected,
7532                             "Error: Expected %d but got %d instead on uri_builder_tests[%d].expected_dword_props[%d].\n",
7533                             prop.expected, received, test_index, i);
7534                     }
7535                 } else {
7536                     ok(received == prop.expected,
7537                         "Error: Expected %d but got %d instead on uri_builder_tests[%d].expected_dword_props[%d].\n",
7538                         prop.expected, received, test_index, i);
7539                 }
7540             }
7541         }
7542     }
7543     if(uri) IUri_Release(uri);
7544 }
7545
7546 static void test_IUriBuilder_CreateInvalidArgs(void) {
7547     IUriBuilder *builder;
7548     HRESULT hr;
7549
7550     hr = pCreateIUriBuilder(NULL, 0, 0, &builder);
7551     ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7552     if(SUCCEEDED(hr)) {
7553         IUri *test = NULL, *uri = (void*) 0xdeadbeef;
7554
7555         /* Test what happens if the IUriBuilder doesn't have a IUri set. */
7556         hr = IUriBuilder_CreateUri(builder, 0, 0, 0, NULL);
7557         ok(hr == E_POINTER, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
7558
7559         uri = (void*) 0xdeadbeef;
7560         hr = IUriBuilder_CreateUri(builder, 0, Uri_HAS_USER_NAME, 0, &uri);
7561         ok(hr == E_NOTIMPL, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, E_NOTIMPL);
7562         ok(uri == NULL, "Error: expected uri to be NULL, but was %p instead.\n", uri);
7563
7564         hr = IUriBuilder_CreateUriSimple(builder, 0, 0, NULL);
7565         ok(hr == E_POINTER, "Error: IUriBuilder_CreateUriSimple returned 0x%08x, expected 0x%08x.\n",
7566             hr, E_POINTER);
7567
7568         uri = (void*) 0xdeadbeef;
7569         hr = IUriBuilder_CreateUriSimple(builder, Uri_HAS_USER_NAME, 0, &uri);
7570         ok(hr == E_NOTIMPL, "Error: IUriBuilder_CreateUriSimple returned 0x%08x, expected 0x%08x.\n",
7571             hr, E_NOTIMPL);
7572         ok(!uri, "Error: Expected uri to NULL, but was %p instead.\n", uri);
7573
7574         hr = IUriBuilder_CreateUriWithFlags(builder, 0, 0, 0, 0, NULL);
7575         ok(hr == E_POINTER, "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x.\n",
7576             hr, E_POINTER);
7577
7578         uri = (void*) 0xdeadbeef;
7579         hr = IUriBuilder_CreateUriWithFlags(builder, 0, 0, Uri_HAS_USER_NAME, 0, &uri);
7580         ok(hr == E_NOTIMPL, "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x.\n",
7581             hr, E_NOTIMPL);
7582         ok(!uri, "Error: Expected uri to be NULL, but was %p instead.\n", uri);
7583
7584         hr = pCreateUri(http_urlW, 0, 0, &test);
7585         ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7586         if(SUCCEEDED(hr)) {
7587             hr = IUriBuilder_SetIUri(builder, test);
7588             ok(hr == S_OK, "Error: IUriBuilder_SetIUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7589
7590             /* No longer returns E_NOTIMPL, since a IUri has been set and hasn't been modified. */
7591             uri = NULL;
7592             hr = IUriBuilder_CreateUri(builder, 0, Uri_HAS_USER_NAME, 0, &uri);
7593             ok(hr == S_OK, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7594             ok(uri != NULL, "Error: The uri was NULL.\n");
7595             if(uri) IUri_Release(uri);
7596
7597             uri = NULL;
7598             hr = IUriBuilder_CreateUriSimple(builder, Uri_HAS_USER_NAME, 0, &uri);
7599             ok(hr == S_OK, "Error: IUriBuilder_CreateUriSimple returned 0x%08x, expected 0x%08x.\n",
7600                 hr, S_OK);
7601             ok(uri != NULL, "Error: uri was NULL.\n");
7602             if(uri) IUri_Release(uri);
7603
7604             uri = NULL;
7605             hr = IUriBuilder_CreateUriWithFlags(builder, 0, 0, 0, 0, &uri);
7606             ok(hr == S_OK, "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x.\n",
7607                 hr, S_OK);
7608             ok(uri != NULL, "Error: uri was NULL.\n");
7609             if(uri) IUri_Release(uri);
7610
7611             hr = IUriBuilder_SetFragment(builder, NULL);
7612             ok(hr == S_OK, "Error: IUriBuilder_SetFragment returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7613
7614             /* The IUriBuilder is changed, so it returns E_NOTIMPL again. */
7615             uri = (void*) 0xdeadbeef;
7616             hr = IUriBuilder_CreateUri(builder, 0, Uri_HAS_USER_NAME, 0, &uri);
7617             ok(hr == E_NOTIMPL, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7618             ok(!uri, "Error: Expected uri to be NULL but was %p instead.\n", uri);
7619
7620             uri = (void*) 0xdeadbeef;
7621             hr = IUriBuilder_CreateUriSimple(builder, Uri_HAS_USER_NAME, 0, &uri);
7622             ok(hr == E_NOTIMPL, "Error: IUriBuilder_CreateUriSimple returned 0x%08x, expected 0x%08x.\n",
7623                 hr, S_OK);
7624             ok(!uri, "Error: Expected uri to be NULL, but was %p instead.\n", uri);
7625
7626             uri = (void*) 0xdeadbeef;
7627             hr = IUriBuilder_CreateUriWithFlags(builder, 0, 0, Uri_HAS_USER_NAME, 0, &uri);
7628             ok(hr == E_NOTIMPL, "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x.\n",
7629                 hr, E_NOTIMPL);
7630             ok(!uri, "Error: Expected uri to be NULL, but was %p instead.\n", uri);
7631         }
7632         if(test) IUri_Release(test);
7633     }
7634     if(builder) IUriBuilder_Release(builder);
7635 }
7636
7637 /* Tests invalid args to the "Get*" functions. */
7638 static void test_IUriBuilder_GetInvalidArgs(void) {
7639     IUriBuilder *builder = NULL;
7640     HRESULT hr;
7641
7642     hr = pCreateIUriBuilder(NULL, 0, 0, &builder);
7643     ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7644     if(SUCCEEDED(hr)) {
7645         LPCWSTR received = (void*) 0xdeadbeef;
7646         DWORD len = -1, port = -1;
7647         BOOL set = -1;
7648
7649         hr = IUriBuilder_GetFragment(builder, NULL, NULL);
7650         ok(hr == E_POINTER, "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x.\n",
7651             hr, E_POINTER);
7652         hr = IUriBuilder_GetFragment(builder, NULL, &received);
7653         ok(hr == E_POINTER, "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x.\n",
7654             hr, E_POINTER);
7655         ok(!received, "Error: Expected received to be NULL, but was %p instead.\n", received);
7656         hr = IUriBuilder_GetFragment(builder, &len, NULL);
7657         ok(hr == E_POINTER, "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x.\n",
7658             hr, E_POINTER);
7659         ok(!len, "Error: Expected len to be 0, but was %d instead.\n", len);
7660
7661         hr = IUriBuilder_GetHost(builder, NULL, NULL);
7662         ok(hr == E_POINTER, "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x.\n",
7663             hr, E_POINTER);
7664         received = (void*) 0xdeadbeef;
7665         hr = IUriBuilder_GetHost(builder, NULL, &received);
7666         ok(hr == E_POINTER, "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x.\n",
7667             hr, E_POINTER);
7668         ok(!received, "Error: Expected received to be NULL, but was %p instead.\n", received);
7669         len = -1;
7670         hr = IUriBuilder_GetHost(builder, &len, NULL);
7671         ok(hr == E_POINTER, "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x.\n",
7672             hr, E_POINTER);
7673         ok(!len, "Error: Expected len to be 0, but was %d instead.\n", len);
7674
7675         hr = IUriBuilder_GetPassword(builder, NULL, NULL);
7676         ok(hr == E_POINTER, "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x.\n",
7677             hr, E_POINTER);
7678         received = (void*) 0xdeadbeef;
7679         hr = IUriBuilder_GetPassword(builder, NULL, &received);
7680         ok(hr == E_POINTER, "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x.\n",
7681             hr, E_POINTER);
7682         ok(!received, "Error: Expected received to be NULL, but was %p instead.\n", received);
7683         len = -1;
7684         hr = IUriBuilder_GetPassword(builder, &len, NULL);
7685         ok(hr == E_POINTER, "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x.\n",
7686             hr, E_POINTER);
7687         ok(!len, "Error: Expected len to be 0, but was %d instead.\n", len);
7688
7689         hr = IUriBuilder_GetPath(builder, NULL, NULL);
7690         ok(hr == E_POINTER, "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x.\n",
7691             hr, E_POINTER);
7692         received = (void*) 0xdeadbeef;
7693         hr = IUriBuilder_GetPath(builder, NULL, &received);
7694         ok(hr == E_POINTER, "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x.\n",
7695             hr, E_POINTER);
7696         ok(!received, "Error: Expected received to be NULL, but was %p instead.\n", received);
7697         len = -1;
7698         hr = IUriBuilder_GetPath(builder, &len, NULL);
7699         ok(hr == E_POINTER, "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x.\n",
7700             hr, E_POINTER);
7701         ok(!len, "Error: Expected len to be 0, but was %d instead.\n", len);
7702
7703         hr = IUriBuilder_GetPort(builder, NULL, NULL);
7704         ok(hr == E_POINTER, "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x.\n",
7705             hr, E_POINTER);
7706         hr = IUriBuilder_GetPort(builder, NULL, &port);
7707         ok(hr == E_POINTER, "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x.\n",
7708             hr, E_POINTER);
7709         ok(!port, "Error: Expected port to be 0, but was %d instead.\n", port);
7710         hr = IUriBuilder_GetPort(builder, &set, NULL);
7711         ok(hr == E_POINTER, "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x.\n",
7712             hr, E_POINTER);
7713         ok(!set, "Error: Expected set to be FALSE, but was %d instead.\n", set);
7714
7715         hr = IUriBuilder_GetQuery(builder, NULL, NULL);
7716         ok(hr == E_POINTER, "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x.\n",
7717             hr, E_POINTER);
7718         received = (void*) 0xdeadbeef;
7719         hr = IUriBuilder_GetQuery(builder, NULL, &received);
7720         ok(hr == E_POINTER, "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x.\n",
7721             hr, E_POINTER);
7722         ok(!received, "Error: Expected received to be NULL, but was %p instead.\n", received);
7723         len = -1;
7724         hr = IUriBuilder_GetQuery(builder, &len, NULL);
7725         ok(hr == E_POINTER, "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x.\n",
7726             hr, E_POINTER);
7727         ok(!len, "Error: Expected len to be 0, but was %d instead.\n", len);
7728
7729         hr = IUriBuilder_GetSchemeName(builder, NULL, NULL);
7730         ok(hr == E_POINTER, "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x.\n",
7731             hr, E_POINTER);
7732         received = (void*) 0xdeadbeef;
7733         hr = IUriBuilder_GetSchemeName(builder, NULL, &received);
7734         ok(hr == E_POINTER, "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x.\n",
7735             hr, E_POINTER);
7736         ok(!received, "Error: Expected received to be NULL, but was %p instead.\n", received);
7737         len = -1;
7738         hr = IUriBuilder_GetSchemeName(builder, &len, NULL);
7739         ok(hr == E_POINTER, "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x.\n",
7740             hr, E_POINTER);
7741         ok(!len, "Error: Expected len to be 0, but was %d instead.\n", len);
7742
7743         hr = IUriBuilder_GetUserName(builder, NULL, NULL);
7744         ok(hr == E_POINTER, "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x.\n",
7745             hr, E_POINTER);
7746         received = (void*) 0xdeadbeef;
7747         hr = IUriBuilder_GetUserName(builder, NULL, &received);
7748         ok(hr == E_POINTER, "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x.\n",
7749             hr, E_POINTER);
7750         ok(!received, "Error: Expected received to be NULL, but was %p instead.\n", received);
7751         len = -1;
7752         hr = IUriBuilder_GetUserName(builder, &len, NULL);
7753         ok(hr == E_POINTER, "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x.\n",
7754             hr, E_POINTER);
7755         ok(!len, "Error: Expected len to be 0, but was %d instead.\n", len);
7756     }
7757     if(builder) IUriBuilder_Release(builder);
7758 }
7759
7760 static void test_IUriBuilder_GetFragment(IUriBuilder *builder, const uri_builder_test *test,
7761                                          DWORD test_index) {
7762     HRESULT hr;
7763     DWORD i;
7764     LPCWSTR received = NULL;
7765     DWORD len = -1;
7766     const uri_builder_property *prop = NULL;
7767
7768     /* Check if the property was set earlier. */
7769     for(i = 0; i < sizeof(test->properties)/sizeof(test->properties[0]); ++i) {
7770         if(test->properties[i].change && test->properties[i].property == Uri_PROPERTY_FRAGMENT)
7771             prop = &(test->properties[i]);
7772     }
7773
7774     if(prop) {
7775         /* Use expected_value unless it's NULL, then use value. */
7776         LPCSTR expected = prop->expected_value ? prop->expected_value : prop->value;
7777         hr = IUriBuilder_GetFragment(builder, &len, &received);
7778         if(prop->todo) {
7779             todo_wine {
7780                 ok(hr == (expected ? S_OK : S_FALSE),
7781                     "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7782                     hr, (expected ? S_OK : S_FALSE), test_index);
7783             }
7784             if(SUCCEEDED(hr)) {
7785                 todo_wine {
7786                     ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
7787                         expected, wine_dbgstr_w(received), test_index);
7788                 }
7789                 todo_wine {
7790                     ok(lstrlen(expected) == len,
7791                         "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
7792                         lstrlen(expected), len, test_index);
7793                 }
7794             }
7795         } else {
7796             ok(hr == (expected ? S_OK : S_FALSE),
7797                 "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7798                 hr, (expected ? S_OK : S_FALSE), test_index);
7799             ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
7800                 expected, wine_dbgstr_w(received), test_index);
7801             ok(lstrlen(expected) == len,
7802                 "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
7803                 lstrlen(expected), len, test_index);
7804         }
7805     } else {
7806         /* The property wasn't set earlier, so it should return whatever
7807          * the base IUri contains (if anything).
7808          */
7809         IUri *uri = NULL;
7810         hr = IUriBuilder_GetIUri(builder, &uri);
7811         ok(hr == S_OK,
7812             "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7813             hr, S_OK, test_index);
7814         if(SUCCEEDED(hr)) {
7815             if(!uri) {
7816                 received = (void*) 0xdeadbeef;
7817                 len = -1;
7818
7819                 hr = IUriBuilder_GetFragment(builder, &len, &received);
7820                 ok(hr == S_FALSE,
7821                     "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7822                     hr, S_FALSE, test_index);
7823                 if(SUCCEEDED(hr)) {
7824                     ok(!len, "Error: Expected len to be 0, but was %d instead on uri_builder_tests[%d].\n",
7825                         len, test_index);
7826                     ok(!received, "Error: Expected received to be NULL, but was %p instead on uri_builder_tests[%d].\n",
7827                         received, test_index);
7828                 }
7829             } else {
7830                 BOOL has_prop = FALSE;
7831                 BSTR expected = NULL;
7832
7833                 hr = IUri_GetFragment(uri, &expected);
7834                 ok(SUCCEEDED(hr),
7835                     "Error: Expected IUri_GetFragment to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
7836                     hr, test_index);
7837                 has_prop = hr == S_OK;
7838
7839                 hr = IUriBuilder_GetFragment(builder, &len, &received);
7840                 if(has_prop) {
7841                     ok(hr == S_OK,
7842                         "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7843                         hr, S_OK, test_index);
7844                     if(SUCCEEDED(hr)) {
7845                         ok(!lstrcmpW(expected, received),
7846                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].\n",
7847                             wine_dbgstr_w(expected), wine_dbgstr_w(received), test_index);
7848                         ok(lstrlenW(expected) == len,
7849                             "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
7850                             lstrlenW(expected), len, test_index);
7851                     }
7852                 } else {
7853                     ok(hr == S_FALSE,
7854                         "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7855                         hr, S_FALSE, test_index);
7856                     if(SUCCEEDED(hr)) {
7857                         ok(!received, "Error: Expected received to be NULL on uri_builder_tests[%d].\n", test_index);
7858                         ok(!len, "Error: Expected the length to be 0, but was %d instead on uri_builder_tests[%d].\n",
7859                             len, test_index);
7860                     }
7861                 }
7862                 SysFreeString(expected);
7863             }
7864         }
7865         if(uri) IUri_Release(uri);
7866     }
7867 }
7868
7869 static void test_IUriBuilder_GetHost(IUriBuilder *builder, const uri_builder_test *test,
7870                                      DWORD test_index) {
7871     HRESULT hr;
7872     DWORD i;
7873     LPCWSTR received = NULL;
7874     DWORD len = -1;
7875     const uri_builder_property *prop = NULL;
7876
7877     /* Check if the property was set earlier. */
7878     for(i = 0; i < sizeof(test->properties)/sizeof(test->properties[0]); ++i) {
7879         if(test->properties[i].change && test->properties[i].property == Uri_PROPERTY_HOST)
7880             prop = &(test->properties[i]);
7881     }
7882
7883     if(prop) {
7884         /* Use expected_value unless it's NULL, then use value. */
7885         LPCSTR expected = prop->expected_value ? prop->expected_value : prop->value;
7886         hr = IUriBuilder_GetHost(builder, &len, &received);
7887         if(prop->todo) {
7888             todo_wine {
7889                 ok(hr == (expected ? S_OK : S_FALSE),
7890                     "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7891                     hr, (expected ? S_OK : S_FALSE), test_index);
7892             }
7893             if(SUCCEEDED(hr)) {
7894                 todo_wine {
7895                     ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
7896                         expected, wine_dbgstr_w(received), test_index);
7897                 }
7898                 todo_wine {
7899                     ok(lstrlen(expected) == len,
7900                         "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
7901                         lstrlen(expected), len, test_index);
7902                 }
7903             }
7904         } else {
7905             ok(hr == (expected ? S_OK : S_FALSE),
7906                 "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7907                 hr, (expected ? S_OK : S_FALSE), test_index);
7908             ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
7909                 expected, wine_dbgstr_w(received), test_index);
7910             ok(lstrlen(expected) == len,
7911                 "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
7912                 lstrlen(expected), len, test_index);
7913         }
7914     } else {
7915         /* The property wasn't set earlier, so it should return whatever
7916          * the base IUri contains (if anything).
7917          */
7918         IUri *uri = NULL;
7919         hr = IUriBuilder_GetIUri(builder, &uri);
7920         ok(hr == S_OK,
7921             "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7922             hr, S_OK, test_index);
7923         if(SUCCEEDED(hr)) {
7924             if(!uri) {
7925                 received = (void*) 0xdeadbeef;
7926                 len = -1;
7927
7928                 hr = IUriBuilder_GetHost(builder, &len, &received);
7929                 ok(hr == S_FALSE,
7930                     "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7931                     hr, S_FALSE, test_index);
7932                 if(SUCCEEDED(hr)) {
7933                     ok(!len, "Error: Expected len to be 0, but was %d instead on uri_builder_tests[%d].\n",
7934                         len, test_index);
7935                     ok(!received, "Error: Expected received to be NULL, but was %p instead on uri_builder_tests[%d].\n",
7936                         received, test_index);
7937                 }
7938             } else {
7939                 BOOL has_prop = FALSE;
7940                 BSTR expected = NULL;
7941
7942                 hr = IUri_GetHost(uri, &expected);
7943                 ok(SUCCEEDED(hr),
7944                     "Error: Expected IUri_GetHost to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
7945                     hr, test_index);
7946                 has_prop = hr == S_OK;
7947
7948                 hr = IUriBuilder_GetHost(builder, &len, &received);
7949                 if(has_prop) {
7950                     ok(hr == S_OK,
7951                         "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7952                         hr, S_OK, test_index);
7953                     if(SUCCEEDED(hr)) {
7954                         ok(!lstrcmpW(expected, received),
7955                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].\n",
7956                             wine_dbgstr_w(expected), wine_dbgstr_w(received), test_index);
7957                         ok(lstrlenW(expected) == len,
7958                             "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
7959                             lstrlenW(expected), len, test_index);
7960                     }
7961                 } else {
7962                     ok(hr == S_FALSE,
7963                         "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7964                         hr, S_FALSE, test_index);
7965                     if(SUCCEEDED(hr)) {
7966                         ok(!received, "Error: Expected received to be NULL on uri_builder_tests[%d].\n", test_index);
7967                         ok(!len, "Error: Expected the length to be 0, but was %d instead on uri_builder_tests[%d].\n",
7968                             len, test_index);
7969                     }
7970                 }
7971                 SysFreeString(expected);
7972             }
7973         }
7974         if(uri) IUri_Release(uri);
7975     }
7976 }
7977
7978 static void test_IUriBuilder_GetPassword(IUriBuilder *builder, const uri_builder_test *test,
7979                                          DWORD test_index) {
7980     HRESULT hr;
7981     DWORD i;
7982     LPCWSTR received = NULL;
7983     DWORD len = -1;
7984     const uri_builder_property *prop = NULL;
7985
7986     /* Check if the property was set earlier. */
7987     for(i = 0; i < sizeof(test->properties)/sizeof(test->properties[0]); ++i) {
7988         if(test->properties[i].change && test->properties[i].property == Uri_PROPERTY_PASSWORD)
7989             prop = &(test->properties[i]);
7990     }
7991
7992     if(prop) {
7993         /* Use expected_value unless it's NULL, then use value. */
7994         LPCSTR expected = prop->expected_value ? prop->expected_value : prop->value;
7995         hr = IUriBuilder_GetPassword(builder, &len, &received);
7996         if(prop->todo) {
7997             todo_wine {
7998                 ok(hr == (expected ? S_OK : S_FALSE),
7999                     "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8000                     hr, (expected ? S_OK : S_FALSE), test_index);
8001             }
8002             if(SUCCEEDED(hr)) {
8003                 todo_wine {
8004                     ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
8005                         expected, wine_dbgstr_w(received), test_index);
8006                 }
8007                 todo_wine {
8008                     ok(lstrlen(expected) == len,
8009                         "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8010                         lstrlen(expected), len, test_index);
8011                 }
8012             }
8013         } else {
8014             ok(hr == (expected ? S_OK : S_FALSE),
8015                 "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8016                 hr, (expected ? S_OK : S_FALSE), test_index);
8017             ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
8018                 expected, wine_dbgstr_w(received), test_index);
8019             ok(lstrlen(expected) == len,
8020                 "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8021                 lstrlen(expected), len, test_index);
8022         }
8023     } else {
8024         /* The property wasn't set earlier, so it should return whatever
8025          * the base IUri contains (if anything).
8026          */
8027         IUri *uri = NULL;
8028         hr = IUriBuilder_GetIUri(builder, &uri);
8029         ok(hr == S_OK,
8030             "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8031             hr, S_OK, test_index);
8032         if(SUCCEEDED(hr)) {
8033             if(!uri) {
8034                 received = (void*) 0xdeadbeef;
8035                 len = -1;
8036
8037                 hr = IUriBuilder_GetPassword(builder, &len, &received);
8038                 ok(hr == S_FALSE,
8039                     "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8040                     hr, S_FALSE, test_index);
8041                 if(SUCCEEDED(hr)) {
8042                     ok(!len, "Error: Expected len to be 0, but was %d instead on uri_builder_tests[%d].\n",
8043                         len, test_index);
8044                     ok(!received, "Error: Expected received to be NULL, but was %p instead on uri_builder_tests[%d].\n",
8045                         received, test_index);
8046                 }
8047             } else {
8048                 BOOL has_prop = FALSE;
8049                 BSTR expected = NULL;
8050
8051                 hr = IUri_GetPassword(uri, &expected);
8052                 ok(SUCCEEDED(hr),
8053                     "Error: Expected IUri_GetPassword to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
8054                     hr, test_index);
8055                 has_prop = hr == S_OK;
8056
8057                 hr = IUriBuilder_GetPassword(builder, &len, &received);
8058                 if(has_prop) {
8059                     ok(hr == S_OK,
8060                         "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8061                         hr, S_OK, test_index);
8062                     if(SUCCEEDED(hr)) {
8063                         ok(!lstrcmpW(expected, received),
8064                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].\n",
8065                             wine_dbgstr_w(expected), wine_dbgstr_w(received), test_index);
8066                         ok(lstrlenW(expected) == len,
8067                             "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8068                             lstrlenW(expected), len, test_index);
8069                     }
8070                 } else {
8071                     ok(hr == S_FALSE,
8072                         "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8073                         hr, S_FALSE, test_index);
8074                     if(SUCCEEDED(hr)) {
8075                         ok(!received, "Error: Expected received to be NULL on uri_builder_tests[%d].\n", test_index);
8076                         ok(!len, "Error: Expected the length to be 0, but was %d instead on uri_builder_tests[%d].\n",
8077                             len, test_index);
8078                     }
8079                 }
8080                 SysFreeString(expected);
8081             }
8082         }
8083         if(uri) IUri_Release(uri);
8084     }
8085 }
8086
8087 static void test_IUriBuilder_GetPath(IUriBuilder *builder, const uri_builder_test *test,
8088                                      DWORD test_index) {
8089     HRESULT hr;
8090     DWORD i;
8091     LPCWSTR received = NULL;
8092     DWORD len = -1;
8093     const uri_builder_property *prop = NULL;
8094
8095     /* Check if the property was set earlier. */
8096     for(i = 0; i < sizeof(test->properties)/sizeof(test->properties[0]); ++i) {
8097         if(test->properties[i].change && test->properties[i].property == Uri_PROPERTY_PATH)
8098             prop = &(test->properties[i]);
8099     }
8100
8101     if(prop) {
8102         /* Use expected_value unless it's NULL, then use value. */
8103         LPCSTR expected = prop->expected_value ? prop->expected_value : prop->value;
8104         hr = IUriBuilder_GetPath(builder, &len, &received);
8105         if(prop->todo) {
8106             todo_wine {
8107                 ok(hr == (expected ? S_OK : S_FALSE),
8108                     "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8109                     hr, (expected ? S_OK : S_FALSE), test_index);
8110             }
8111             if(SUCCEEDED(hr)) {
8112                 todo_wine {
8113                     ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
8114                         expected, wine_dbgstr_w(received), test_index);
8115                 }
8116                 todo_wine {
8117                     ok(lstrlen(expected) == len,
8118                         "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8119                         lstrlen(expected), len, test_index);
8120                 }
8121             }
8122         } else {
8123             ok(hr == (expected ? S_OK : S_FALSE),
8124                 "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8125                 hr, (expected ? S_OK : S_FALSE), test_index);
8126             ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
8127                 expected, wine_dbgstr_w(received), test_index);
8128             ok(lstrlen(expected) == len,
8129                 "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8130                 lstrlen(expected), len, test_index);
8131         }
8132     } else {
8133         /* The property wasn't set earlier, so it should return whatever
8134          * the base IUri contains (if anything).
8135          */
8136         IUri *uri = NULL;
8137         hr = IUriBuilder_GetIUri(builder, &uri);
8138         ok(hr == S_OK,
8139             "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8140             hr, S_OK, test_index);
8141         if(SUCCEEDED(hr)) {
8142             if(!uri) {
8143                 received = (void*) 0xdeadbeef;
8144                 len = -1;
8145
8146                 hr = IUriBuilder_GetPath(builder, &len, &received);
8147                 ok(hr == S_FALSE,
8148                     "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8149                     hr, S_FALSE, test_index);
8150                 if(SUCCEEDED(hr)) {
8151                     ok(!len, "Error: Expected len to be 0, but was %d instead on uri_builder_tests[%d].\n",
8152                         len, test_index);
8153                     ok(!received, "Error: Expected received to be NULL, but was %p instead on uri_builder_tests[%d].\n",
8154                         received, test_index);
8155                 }
8156             } else {
8157                 BOOL has_prop = FALSE;
8158                 BSTR expected = NULL;
8159
8160                 hr = IUri_GetPath(uri, &expected);
8161                 ok(SUCCEEDED(hr),
8162                     "Error: Expected IUri_GetPath to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
8163                     hr, test_index);
8164                 has_prop = hr == S_OK;
8165
8166                 hr = IUriBuilder_GetPath(builder, &len, &received);
8167                 if(has_prop) {
8168                     ok(hr == S_OK,
8169                         "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8170                         hr, S_OK, test_index);
8171                     if(SUCCEEDED(hr)) {
8172                         ok(!lstrcmpW(expected, received),
8173                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].\n",
8174                             wine_dbgstr_w(expected), wine_dbgstr_w(received), test_index);
8175                         ok(lstrlenW(expected) == len,
8176                             "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8177                             lstrlenW(expected), len, test_index);
8178                     }
8179                 } else {
8180                     ok(hr == S_FALSE,
8181                         "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8182                         hr, S_FALSE, test_index);
8183                     if(SUCCEEDED(hr)) {
8184                         ok(!received, "Error: Expected received to be NULL on uri_builder_tests[%d].\n", test_index);
8185                         ok(!len, "Error: Expected the length to be 0, but was %d instead on uri_builder_tests[%d].\n",
8186                             len, test_index);
8187                     }
8188                 }
8189                 SysFreeString(expected);
8190             }
8191         }
8192         if(uri) IUri_Release(uri);
8193     }
8194 }
8195
8196 static void test_IUriBuilder_GetPort(IUriBuilder *builder, const uri_builder_test *test,
8197                                      DWORD test_index) {
8198     HRESULT hr;
8199     BOOL has_port = FALSE;
8200     DWORD received = -1;
8201
8202     if(test->port_prop.change) {
8203         DWORD expected = test->port_prop.value;
8204
8205         hr = IUriBuilder_GetPort(builder, &has_port, &received);
8206         if(test->port_prop.todo) {
8207             todo_wine {
8208                 ok(hr == S_OK,
8209                     "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8210                     hr, S_OK, test_index);
8211             }
8212             if(SUCCEEDED(hr)) {
8213                 todo_wine {
8214                     ok(has_port == test->port_prop.set,
8215                         "Error: Expected has_port to be %d but was %d instead on uri_builder_tests[%d].\n",
8216                         test->port_prop.set, has_port, test_index);
8217                 }
8218                 todo_wine {
8219                     ok(received == expected,
8220                         "Error: Expected received to be %d, but was %d instead on uri_builder_tests[%d].\n",
8221                         expected, received, test_index);
8222                 }
8223             }
8224         } else {
8225             ok(hr == S_OK,
8226                 "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8227                 hr, S_OK, test_index);
8228             ok(has_port == test->port_prop.set,
8229                 "Error: Expected has_port to be %d, but was %d instead on uri_builder_tests[%d].\n",
8230                 test->port_prop.set, has_port, test_index);
8231             ok(received == test->port_prop.value,
8232                 "Error: Expected port to be %d, but was %d instead on uri_builder_tests[%d].\n",
8233                 test->port_prop.value, received, test_index);
8234         }
8235     } else {
8236         IUri *uri = NULL;
8237
8238         hr = IUriBuilder_GetIUri(builder, &uri);
8239         ok(hr == S_OK,
8240             "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8241             hr, S_OK, test_index);
8242         if(SUCCEEDED(hr)) {
8243             if(!uri) {
8244                 hr = IUriBuilder_GetPort(builder, &has_port, &received);
8245                 ok(hr == S_OK,
8246                     "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8247                     hr, S_OK, test_index);
8248                 if(SUCCEEDED(hr)) {
8249                     ok(has_port == FALSE,
8250                         "Error: Expected has_port to be FALSE, but was %d instead on uri_builder_tests[%d].\n",
8251                         has_port, test_index);
8252                     ok(!received, "Error: Expected received to be 0, but was %d instead on uri_builder_tests[%d].\n",
8253                         received, test_index);
8254                 }
8255             } else {
8256                 DWORD expected;
8257
8258                 hr = IUri_GetPort(uri, &expected);
8259                 ok(SUCCEEDED(hr),
8260                     "Error: Expected IUri_Port to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
8261                     hr, test_index);
8262
8263                 hr = IUriBuilder_GetPort(builder, &has_port, &received);
8264                 ok(hr == S_OK,
8265                     "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8266                     hr, S_OK, test_index);
8267                 if(SUCCEEDED(hr)) {
8268                     ok(!has_port,
8269                         "Error: Expected has_port to be FALSE but was TRUE instead on uri_builder_tests[%d].\n",
8270                         test_index);
8271                     ok(received == expected,
8272                         "Error: Expected received to be %d, but was %d instead on uri_builder_tests[%d].\n",
8273                         expected, received, test_index);
8274                 }
8275             }
8276         }
8277         if(uri) IUri_Release(uri);
8278     }
8279 }
8280
8281 static void test_IUriBuilder_GetQuery(IUriBuilder *builder, const uri_builder_test *test,
8282                                       DWORD test_index) {
8283     HRESULT hr;
8284     DWORD i;
8285     LPCWSTR received = NULL;
8286     DWORD len = -1;
8287     const uri_builder_property *prop = NULL;
8288
8289     /* Check if the property was set earlier. */
8290     for(i = 0; i < sizeof(test->properties)/sizeof(test->properties[0]); ++i) {
8291         if(test->properties[i].change && test->properties[i].property == Uri_PROPERTY_QUERY)
8292             prop = &(test->properties[i]);
8293     }
8294
8295     if(prop) {
8296         /* Use expected_value unless it's NULL, then use value. */
8297         LPCSTR expected = prop->expected_value ? prop->expected_value : prop->value;
8298         hr = IUriBuilder_GetQuery(builder, &len, &received);
8299         if(prop->todo) {
8300             todo_wine {
8301                 ok(hr == (expected ? S_OK : S_FALSE),
8302                     "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8303                     hr, (expected ? S_OK : S_FALSE), test_index);
8304             }
8305             if(SUCCEEDED(hr)) {
8306                 todo_wine {
8307                     ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
8308                         expected, wine_dbgstr_w(received), test_index);
8309                 }
8310                 todo_wine {
8311                     ok(lstrlen(expected) == len,
8312                         "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8313                         lstrlen(expected), len, test_index);
8314                 }
8315             }
8316         } else {
8317             ok(hr == (expected ? S_OK : S_FALSE),
8318                 "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8319                 hr, (expected ? S_OK : S_FALSE), test_index);
8320             ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
8321                 expected, wine_dbgstr_w(received), test_index);
8322             ok(lstrlen(expected) == len,
8323                 "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8324                 lstrlen(expected), len, test_index);
8325         }
8326     } else {
8327         /* The property wasn't set earlier, so it should return whatever
8328          * the base IUri contains (if anything).
8329          */
8330         IUri *uri = NULL;
8331         hr = IUriBuilder_GetIUri(builder, &uri);
8332         ok(hr == S_OK,
8333             "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8334             hr, S_OK, test_index);
8335         if(SUCCEEDED(hr)) {
8336             if(!uri) {
8337                 received = (void*) 0xdeadbeef;
8338                 len = -1;
8339
8340                 hr = IUriBuilder_GetQuery(builder, &len, &received);
8341                 ok(hr == S_FALSE,
8342                     "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8343                     hr, S_FALSE, test_index);
8344                 if(SUCCEEDED(hr)) {
8345                     ok(!len, "Error: Expected len to be 0, but was %d instead on uri_builder_tests[%d].\n",
8346                         len, test_index);
8347                     ok(!received, "Error: Expected received to be NULL, but was %p instead on uri_builder_tests[%d].\n",
8348                         received, test_index);
8349                 }
8350             } else {
8351                 BOOL has_prop = FALSE;
8352                 BSTR expected = NULL;
8353
8354                 hr = IUri_GetQuery(uri, &expected);
8355                 ok(SUCCEEDED(hr),
8356                     "Error: Expected IUri_GetQuery to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
8357                     hr, test_index);
8358                 has_prop = hr == S_OK;
8359
8360                 hr = IUriBuilder_GetQuery(builder, &len, &received);
8361                 if(has_prop) {
8362                     ok(hr == S_OK,
8363                         "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8364                         hr, S_OK, test_index);
8365                     if(SUCCEEDED(hr)) {
8366                         ok(!lstrcmpW(expected, received),
8367                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].\n",
8368                             wine_dbgstr_w(expected), wine_dbgstr_w(received), test_index);
8369                         ok(lstrlenW(expected) == len,
8370                             "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8371                             lstrlenW(expected), len, test_index);
8372                     }
8373                 } else {
8374                     ok(hr == S_FALSE,
8375                         "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8376                         hr, S_FALSE, test_index);
8377                     if(SUCCEEDED(hr)) {
8378                         ok(!received, "Error: Expected received to be NULL on uri_builder_tests[%d].\n", test_index);
8379                         ok(!len, "Error: Expected the length to be 0, but was %d instead on uri_builder_tests[%d].\n",
8380                             len, test_index);
8381                     }
8382                 }
8383                 SysFreeString(expected);
8384             }
8385         }
8386         if(uri) IUri_Release(uri);
8387     }
8388 }
8389
8390 static void test_IUriBuilder_GetSchemeName(IUriBuilder *builder, const uri_builder_test *test,
8391                                            DWORD test_index) {
8392     HRESULT hr;
8393     DWORD i;
8394     LPCWSTR received = NULL;
8395     DWORD len = -1;
8396     const uri_builder_property *prop = NULL;
8397
8398     /* Check if the property was set earlier. */
8399     for(i = 0; i < sizeof(test->properties)/sizeof(test->properties[0]); ++i) {
8400         if(test->properties[i].change && test->properties[i].property == Uri_PROPERTY_SCHEME_NAME)
8401             prop = &(test->properties[i]);
8402     }
8403
8404     if(prop) {
8405         /* Use expected_value unless it's NULL, then use value. */
8406         LPCSTR expected = prop->expected_value ? prop->expected_value : prop->value;
8407         hr = IUriBuilder_GetSchemeName(builder, &len, &received);
8408         if(prop->todo) {
8409             todo_wine {
8410                 ok(hr == (expected ? S_OK : S_FALSE),
8411                     "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8412                     hr, (expected ? S_OK : S_FALSE), test_index);
8413             }
8414             if(SUCCEEDED(hr)) {
8415                 todo_wine {
8416                     ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
8417                         expected, wine_dbgstr_w(received), test_index);
8418                 }
8419                 todo_wine {
8420                     ok(lstrlen(expected) == len,
8421                         "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8422                         lstrlen(expected), len, test_index);
8423                 }
8424             }
8425         } else {
8426             ok(hr == (expected ? S_OK : S_FALSE),
8427                 "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8428                 hr, (expected ? S_OK : S_FALSE), test_index);
8429             ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
8430                 expected, wine_dbgstr_w(received), test_index);
8431             ok(lstrlen(expected) == len,
8432                 "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8433                 lstrlen(expected), len, test_index);
8434         }
8435     } else {
8436         /* The property wasn't set earlier, so it should return whatever
8437          * the base IUri contains (if anything).
8438          */
8439         IUri *uri = NULL;
8440         hr = IUriBuilder_GetIUri(builder, &uri);
8441         ok(hr == S_OK,
8442             "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8443             hr, S_OK, test_index);
8444         if(SUCCEEDED(hr)) {
8445             if(!uri) {
8446                 received = (void*) 0xdeadbeef;
8447                 len = -1;
8448
8449                 hr = IUriBuilder_GetSchemeName(builder, &len, &received);
8450                 ok(hr == S_FALSE,
8451                     "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8452                     hr, S_FALSE, test_index);
8453                 if(SUCCEEDED(hr)) {
8454                     ok(!len, "Error: Expected len to be 0, but was %d instead on uri_builder_tests[%d].\n",
8455                         len, test_index);
8456                     ok(!received, "Error: Expected received to be NULL, but was %p instead on uri_builder_tests[%d].\n",
8457                         received, test_index);
8458                 }
8459             } else {
8460                 BOOL has_prop = FALSE;
8461                 BSTR expected = NULL;
8462
8463                 hr = IUri_GetSchemeName(uri, &expected);
8464                 ok(SUCCEEDED(hr),
8465                     "Error: Expected IUri_GetSchemeName to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
8466                     hr, test_index);
8467                 has_prop = hr == S_OK;
8468
8469                 hr = IUriBuilder_GetSchemeName(builder, &len, &received);
8470                 if(has_prop) {
8471                     ok(hr == S_OK,
8472                         "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8473                         hr, S_OK, test_index);
8474                     if(SUCCEEDED(hr)) {
8475                         ok(!lstrcmpW(expected, received),
8476                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].\n",
8477                             wine_dbgstr_w(expected), wine_dbgstr_w(received), test_index);
8478                         ok(lstrlenW(expected) == len,
8479                             "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8480                             lstrlenW(expected), len, test_index);
8481                     }
8482                 } else {
8483                     ok(hr == S_FALSE,
8484                         "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8485                         hr, S_FALSE, test_index);
8486                     if(SUCCEEDED(hr)) {
8487                         ok(!received, "Error: Expected received to be NULL on uri_builder_tests[%d].\n", test_index);
8488                         ok(!len, "Error: Expected the length to be 0, but was %d instead on uri_builder_tests[%d].\n",
8489                             len, test_index);
8490                     }
8491                 }
8492                 SysFreeString(expected);
8493             }
8494         }
8495         if(uri) IUri_Release(uri);
8496     }
8497 }
8498
8499 static void test_IUriBuilder_GetUserName(IUriBuilder *builder, const uri_builder_test *test,
8500                                          DWORD test_index) {
8501     HRESULT hr;
8502     DWORD i;
8503     LPCWSTR received = NULL;
8504     DWORD len = -1;
8505     const uri_builder_property *prop = NULL;
8506
8507     /* Check if the property was set earlier. */
8508     for(i = 0; i < sizeof(test->properties)/sizeof(test->properties[0]); ++i) {
8509         if(test->properties[i].change && test->properties[i].property == Uri_PROPERTY_USER_NAME)
8510             prop = &(test->properties[i]);
8511     }
8512
8513     if(prop && prop->value && *prop->value) {
8514         /* Use expected_value unless it's NULL, then use value. */
8515         LPCSTR expected = prop->expected_value ? prop->expected_value : prop->value;
8516         hr = IUriBuilder_GetUserName(builder, &len, &received);
8517         if(prop->todo) {
8518             todo_wine {
8519                 ok(hr == (expected ? S_OK : S_FALSE),
8520                     "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8521                     hr, (expected ? S_OK : S_FALSE), test_index);
8522             }
8523             if(SUCCEEDED(hr)) {
8524                 todo_wine {
8525                     ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
8526                         expected, wine_dbgstr_w(received), test_index);
8527                 }
8528                 todo_wine {
8529                     ok(lstrlen(expected) == len,
8530                         "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8531                         lstrlen(expected), len, test_index);
8532                 }
8533             }
8534         } else {
8535             ok(hr == (expected ? S_OK : S_FALSE),
8536                 "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8537                 hr, (expected ? S_OK : S_FALSE), test_index);
8538             ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
8539                 expected, wine_dbgstr_w(received), test_index);
8540             ok(lstrlen(expected) == len,
8541                 "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8542                 lstrlen(expected), len, test_index);
8543         }
8544     } else {
8545         /* The property wasn't set earlier, so it should return whatever
8546          * the base IUri contains (if anything).
8547          */
8548         IUri *uri = NULL;
8549         hr = IUriBuilder_GetIUri(builder, &uri);
8550         ok(hr == S_OK,
8551             "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8552             hr, S_OK, test_index);
8553         if(SUCCEEDED(hr)) {
8554             if(!uri) {
8555                 received = (void*) 0xdeadbeef;
8556                 len = -1;
8557
8558                 hr = IUriBuilder_GetUserName(builder, &len, &received);
8559                 ok(hr == S_FALSE,
8560                     "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8561                     hr, S_FALSE, test_index);
8562                 if(SUCCEEDED(hr)) {
8563                     ok(!len, "Error: Expected len to be 0, but was %d instead on uri_builder_tests[%d].\n",
8564                         len, test_index);
8565                     ok(!received, "Error: Expected received to be NULL, but was %p instead on uri_builder_tests[%d].\n",
8566                         received, test_index);
8567                 }
8568             } else {
8569                 BSTR expected = NULL;
8570                 BOOL has_prop = FALSE;
8571
8572                 hr = IUri_GetUserName(uri, &expected);
8573                 ok(SUCCEEDED(hr),
8574                     "Error: Expected IUri_GetUserName to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
8575                     hr, test_index);
8576                 has_prop = hr == S_OK;
8577
8578                 hr = IUriBuilder_GetUserName(builder, &len, &received);
8579                 if(has_prop) {
8580                     ok(hr == S_OK,
8581                         "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8582                         hr, S_OK, test_index);
8583                     if(SUCCEEDED(hr)) {
8584                         ok(!lstrcmpW(expected, received),
8585                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].\n",
8586                             wine_dbgstr_w(expected), wine_dbgstr_w(received), test_index);
8587                         ok(lstrlenW(expected) == len,
8588                             "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8589                             lstrlenW(expected), len, test_index);
8590                     }
8591                 } else {
8592                     ok(hr == S_FALSE,
8593                         "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8594                         hr, S_FALSE, test_index);
8595                     if(SUCCEEDED(hr)) {
8596                         ok(!received, "Error: Expected received to be NULL on uri_builder_tests[%d].\n", test_index);
8597                         ok(!len, "Error: Expected the length to be 0, but was %d instead on uri_builder_tests[%d].\n",
8598                             len, test_index);
8599                     }
8600                 }
8601                 SysFreeString(expected);
8602             }
8603         }
8604         if(uri) IUri_Release(uri);
8605     }
8606 }
8607
8608 /* Tests IUriBuilder functions. */
8609 static void test_IUriBuilder(void) {
8610     HRESULT hr;
8611     IUriBuilder *builder;
8612     DWORD i;
8613
8614     for(i = 0; i < sizeof(uri_builder_tests)/sizeof(uri_builder_tests[0]); ++i) {
8615         IUri *uri = NULL;
8616         uri_builder_test test = uri_builder_tests[i];
8617         LPWSTR uriW = NULL;
8618
8619         if(test.uri) {
8620             uriW = a2w(test.uri);
8621             hr = pCreateUri(uriW, test.create_flags, 0, &uri);
8622             ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8623                 hr, S_OK, i);
8624             if(FAILED(hr)) continue;
8625         }
8626         hr = pCreateIUriBuilder(uri, 0, 0, &builder);
8627         if(test.create_builder_todo) {
8628             todo_wine {
8629                 ok(hr == test.create_builder_expected,
8630                     "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8631                     hr, test.create_builder_expected, i);
8632             }
8633         } else {
8634             ok(hr == test.create_builder_expected,
8635                 "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8636                 hr, test.create_builder_expected, i);
8637         }
8638         if(SUCCEEDED(hr)) {
8639             DWORD j;
8640             BOOL modified = FALSE, received = FALSE;
8641
8642             /* Perform all the string property changes. */
8643             for(j = 0; j < URI_BUILDER_STR_PROPERTY_COUNT; ++j) {
8644                 uri_builder_property prop = test.properties[j];
8645                 if(prop.change) {
8646                     change_property(builder, &prop, i);
8647                     if(prop.property != Uri_PROPERTY_SCHEME_NAME &&
8648                        prop.property != Uri_PROPERTY_HOST)
8649                         modified = TRUE;
8650                     else if(prop.value && *prop.value)
8651                         modified = TRUE;
8652                     else if(prop.value && !*prop.value && prop.property == Uri_PROPERTY_HOST)
8653                         /* Host name property can't be NULL, but it can be empty. */
8654                         modified = TRUE;
8655                 }
8656             }
8657
8658             if(test.port_prop.change) {
8659                 hr = IUriBuilder_SetPort(builder, test.port_prop.set, test.port_prop.value);
8660                 modified = TRUE;
8661                 if(test.port_prop.todo) {
8662                     todo_wine {
8663                         ok(hr == test.port_prop.expected,
8664                             "Error: IUriBuilder_SetPort returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8665                             hr, test.port_prop.expected, i);
8666                     }
8667                 } else {
8668                     ok(hr == test.port_prop.expected,
8669                         "Error: IUriBuilder_SetPort returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8670                         hr, test.port_prop.expected, i);
8671                 }
8672             }
8673
8674             hr = IUriBuilder_HasBeenModified(builder, &received);
8675             ok(hr == S_OK,
8676                 "Error IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8677                 hr, S_OK, i);
8678             if(SUCCEEDED(hr))
8679                 ok(received == modified,
8680                     "Error: Expected received to be %d but was %d instead on uri_builder_tests[%d].\n",
8681                     modified, received, i);
8682
8683             /* Test the "Get*" functions. */
8684             test_IUriBuilder_GetFragment(builder, &test, i);
8685             test_IUriBuilder_GetHost(builder, &test, i);
8686             test_IUriBuilder_GetPassword(builder, &test, i);
8687             test_IUriBuilder_GetPath(builder, &test, i);
8688             test_IUriBuilder_GetPort(builder, &test, i);
8689             test_IUriBuilder_GetQuery(builder, &test, i);
8690             test_IUriBuilder_GetSchemeName(builder, &test, i);
8691             test_IUriBuilder_GetUserName(builder, &test, i);
8692
8693             test_IUriBuilder_CreateUri(builder, &test, i);
8694             test_IUriBuilder_CreateUriSimple(builder, &test, i);
8695             test_IUriBuilder_CreateUriWithFlags(builder, &test, i);
8696         }
8697         if(builder) IUriBuilder_Release(builder);
8698         if(uri) IUri_Release(uri);
8699         heap_free(uriW);
8700     }
8701 }
8702
8703 static void test_IUriBuilder_HasBeenModified(void) {
8704     HRESULT hr;
8705     IUriBuilder *builder = NULL;
8706
8707     hr = pCreateIUriBuilder(NULL, 0, 0, &builder);
8708     ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8709     if(SUCCEEDED(hr)) {
8710         static const WCHAR hostW[] = {'g','o','o','g','l','e','.','c','o','m',0};
8711         IUri *uri = NULL;
8712         BOOL received;
8713
8714         hr = IUriBuilder_HasBeenModified(builder, NULL);
8715         ok(hr == E_POINTER, "Error: IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x.\n",
8716             hr, E_POINTER);
8717
8718         hr = IUriBuilder_SetHost(builder, hostW);
8719         ok(hr == S_OK, "Error: IUriBuilder_SetHost returned 0x%08x, expected 0x%08x.\n",
8720             hr, S_OK);
8721
8722         hr = IUriBuilder_HasBeenModified(builder, &received);
8723         ok(hr == S_OK, "Error: IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x.\n",
8724             hr, S_OK);
8725         if(SUCCEEDED(hr))
8726             ok(received == TRUE, "Error: Expected received to be TRUE.\n");
8727
8728         hr = pCreateUri(http_urlW, 0, 0, &uri);
8729         ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8730         if(SUCCEEDED(hr)) {
8731             LPCWSTR prop;
8732             DWORD len = -1;
8733
8734             hr = IUriBuilder_SetIUri(builder, uri);
8735             ok(hr == S_OK, "Error: IUriBuilder_SetIUri returned 0x%08x, expected 0x%08x.\n",
8736                 hr, S_OK);
8737
8738             hr = IUriBuilder_HasBeenModified(builder, &received);
8739             ok(hr == S_OK, "Error: IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x.\n",
8740                 hr, S_OK);
8741             if(SUCCEEDED(hr))
8742                 ok(received == FALSE, "Error: Expected received to be FALSE.\n");
8743
8744             /* Test what happens with you call SetIUri with the same IUri again. */
8745             hr = IUriBuilder_SetHost(builder, hostW);
8746             ok(hr == S_OK, "Error: IUriBuilder_SetHost returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8747
8748             hr = IUriBuilder_HasBeenModified(builder, &received);
8749             ok(hr == S_OK, "Error: IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x.\n",
8750                 hr, S_OK);
8751             if(SUCCEEDED(hr))
8752                 ok(received == TRUE, "Error: Expected received to be TRUE.\n");
8753
8754             hr = IUriBuilder_SetIUri(builder, uri);
8755             ok(hr == S_OK, "Error: IUriBuilder_SetIUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8756
8757             /* IUriBuilder already had 'uri' as it's IUri property and so Windows doesn't
8758              * reset any of the changes that were made to the IUriBuilder.
8759              */
8760             hr = IUriBuilder_HasBeenModified(builder, &received);
8761             ok(hr == S_OK, "Error: IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8762             if(SUCCEEDED(hr))
8763                 ok(received == TRUE, "Error: Expected received to be TRUE.\n");
8764
8765             hr = IUriBuilder_GetHost(builder, &len, &prop);
8766             ok(hr == S_OK, "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8767             if(SUCCEEDED(hr)) {
8768                 ok(!lstrcmpW(prop, hostW), "Error: Expected %s but got %s instead.\n",
8769                     wine_dbgstr_w(hostW), wine_dbgstr_w(prop));
8770                 ok(len == lstrlenW(hostW), "Error: Expected len to be %d, but was %d instead.\n",
8771                     lstrlenW(hostW), len);
8772             }
8773
8774             hr = IUriBuilder_SetIUri(builder, NULL);
8775             ok(hr == S_OK, "Error: IUriBuilder_SetIUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8776
8777             hr = IUriBuilder_SetHost(builder, hostW);
8778             ok(hr == S_OK, "Error: IUriBuilder_SetHost returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8779             hr = IUriBuilder_HasBeenModified(builder, &received);
8780             ok(hr == S_OK, "Error: IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x.\n",
8781                 hr, S_OK);
8782             if(SUCCEEDED(hr))
8783                 ok(received == TRUE, "Error: Expected received to be TRUE.\n");
8784
8785             hr = IUriBuilder_SetIUri(builder, NULL);
8786             ok(hr == S_OK, "Error: IUriBuilder_SetIUri returned 0x%08x, expected 0x%09x.\n", hr, S_OK);
8787
8788             hr = IUriBuilder_HasBeenModified(builder, &received);
8789             ok(hr == S_OK, "Error: IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x.\n",
8790                 hr, S_OK);
8791             if(SUCCEEDED(hr))
8792                 ok(received == TRUE, "Error: Expected received to be TRUE.\n");
8793
8794             hr = IUriBuilder_GetHost(builder, &len, &prop);
8795             ok(hr == S_OK, "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8796             if(SUCCEEDED(hr)) {
8797                 ok(!lstrcmpW(prop, hostW), "Error: Expected %s but got %s instead.\n",
8798                     wine_dbgstr_w(hostW), wine_dbgstr_w(prop));
8799                 ok(len == lstrlenW(hostW), "Error: Expected len to %d, but was %d instead.\n",
8800                     lstrlenW(hostW), len);
8801             }
8802         }
8803         if(uri) IUri_Release(uri);
8804     }
8805     if(builder) IUriBuilder_Release(builder);
8806 }
8807
8808 /* Test IUriBuilder {Get,Set}IUri functions. */
8809 static void test_IUriBuilder_IUriProperty(void) {
8810     IUriBuilder *builder = NULL;
8811     HRESULT hr;
8812
8813     hr = pCreateIUriBuilder(NULL, 0, 0, &builder);
8814     ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8815     if(SUCCEEDED(hr)) {
8816         IUri *uri = NULL;
8817
8818         hr = IUriBuilder_GetIUri(builder, NULL);
8819         ok(hr == E_POINTER, "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x.\n",
8820             hr, E_POINTER);
8821
8822         hr = pCreateUri(http_urlW, 0, 0, &uri);
8823         if(SUCCEEDED(hr)) {
8824             IUri *test = NULL;
8825             ULONG cur_count, orig_count;
8826
8827             /* IUriBuilder doesn't clone the IUri, it use the same IUri. */
8828             orig_count = get_refcnt(uri);
8829             hr = IUriBuilder_SetIUri(builder, uri);
8830             cur_count = get_refcnt(uri);
8831             if(SUCCEEDED(hr))
8832                 ok(cur_count == orig_count+1, "Error: Expected uri ref count to be %d, but was %d instead.\n",
8833                     orig_count+1, cur_count);
8834
8835             hr = IUriBuilder_SetIUri(builder, NULL);
8836             cur_count = get_refcnt(uri);
8837             if(SUCCEEDED(hr))
8838                 ok(cur_count == orig_count, "Error: Expected uri ref count to be %d, but was %d instead.\n",
8839                     orig_count, cur_count);
8840
8841             /* CreateUri* functions will return back the same IUri if nothing has changed. */
8842             hr = IUriBuilder_SetIUri(builder, uri);
8843             ok(hr == S_OK, "Error: IUriBuilder_SetIUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8844             orig_count = get_refcnt(uri);
8845
8846             hr = IUriBuilder_CreateUri(builder, 0, 0, 0, &test);
8847             ok(hr == S_OK, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8848             if(SUCCEEDED(hr)) {
8849                 cur_count = get_refcnt(uri);
8850                 ok(cur_count == orig_count+1, "Error: Expected uri ref count to be %d, but was %d instead.\n",
8851                     orig_count+1, cur_count);
8852                 ok(test == uri, "Error: Expected test to be %p, but was %p instead.\n",
8853                     uri, test);
8854             }
8855             if(test) IUri_Release(test);
8856
8857             test = NULL;
8858             hr = IUriBuilder_CreateUri(builder, -1, 0, 0, &test);
8859             ok(hr == S_OK, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8860             if(SUCCEEDED(hr)) {
8861                 cur_count = get_refcnt(uri);
8862                 ok(cur_count == orig_count+1, "Error: Expected uri ref count to be %d, but was %d instead.\n",
8863                     orig_count+1, cur_count);
8864                 ok(test == uri, "Error: Expected test to be %p, but was %p instead.\n", uri, test);
8865             }
8866             if(test) IUri_Release(test);
8867
8868             /* Doesn't return the same IUri, if the flag combination is different then the one that created
8869              * the base IUri.
8870              */
8871             test = NULL;
8872             hr = IUriBuilder_CreateUri(builder, Uri_CREATE_ALLOW_RELATIVE, 0, 0, &test);
8873             ok(hr == S_OK, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8874             if(SUCCEEDED(hr))
8875                 ok(test != uri, "Error: Wasn't expecting 'test' to be 'uri'\n");
8876
8877             if(test) IUri_Release(test);
8878
8879             /* Still returns the same IUri, even though the base one wasn't created with CREATE_CANONICALIZE
8880              * explicitly set (because it's a default flags).
8881              */
8882             test = NULL;
8883             hr = IUriBuilder_CreateUri(builder, Uri_CREATE_CANONICALIZE, 0, 0, &test);
8884             ok(hr == S_OK, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8885             if(SUCCEEDED(hr)) {
8886                 cur_count = get_refcnt(uri);
8887                 ok(cur_count == orig_count+1, "Error: Expected uri ref count to be %d, but was %d instead.\n",
8888                     orig_count+1, cur_count);
8889                 ok(test == uri, "Error: Expected 'test' to be %p, but was %p instead.\n", uri, test);
8890             }
8891             if(test) IUri_Release(test);
8892
8893             test = NULL;
8894             hr = IUriBuilder_CreateUriSimple(builder, 0, 0, &test);
8895             ok(hr == S_OK, "Error: IUriBuilder_CreateUriSimple returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8896             if(SUCCEEDED(hr)) {
8897                 cur_count = get_refcnt(uri);
8898                 ok(cur_count == orig_count+1, "Error: Expected uri ref count to be %d, but was %d instead.\n",
8899                     orig_count+1, cur_count);
8900                 ok(test == uri, "Error: Expected test to be %p, but was %p instead.\n", uri, test);
8901             }
8902             if(test) IUri_Release(test);
8903
8904             test = NULL;
8905             hr = IUriBuilder_CreateUriWithFlags(builder, 0, 0, 0, 0, &test);
8906             ok(hr == S_OK, "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x.\n",
8907                 hr, S_OK);
8908             if(SUCCEEDED(hr)) {
8909                 cur_count = get_refcnt(uri);
8910                 ok(cur_count == orig_count+1, "Error: Expected uri ref count to be %d, but was %d instead.\n",
8911                     orig_count+1, cur_count);
8912                 ok(test == uri, "Error: Expected test to be %p, but was %p instead.\n", uri, test);
8913             }
8914             if(test) IUri_Release(test);
8915
8916             /* Doesn't return the same IUri, if the flag combination is different then the one that created
8917              * the base IUri.
8918              */
8919             test = NULL;
8920             hr = IUriBuilder_CreateUriWithFlags(builder, Uri_CREATE_ALLOW_RELATIVE, 0, 0, 0, &test);
8921             ok(hr == S_OK, "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8922             if(SUCCEEDED(hr))
8923                 ok(test != uri, "Error: Wasn't expecting 'test' to be 'uri'\n");
8924
8925             if(test) IUri_Release(test);
8926
8927             /* Still returns the same IUri, even though the base one wasn't created with CREATE_CANONICALIZE
8928              * explicitly set (because it's a default flags).
8929              */
8930             test = NULL;
8931             hr = IUriBuilder_CreateUriWithFlags(builder, Uri_CREATE_CANONICALIZE, 0, 0, 0, &test);
8932             ok(hr == S_OK, "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8933             if(SUCCEEDED(hr)) {
8934                 cur_count = get_refcnt(uri);
8935                 ok(cur_count == orig_count+1, "Error: Expected uri ref count to be %d, but was %d instead.\n",
8936                     orig_count+1, cur_count);
8937                 ok(test == uri, "Error: Expected 'test' to be %p, but was %p instead.\n", uri, test);
8938             }
8939             if(test) IUri_Release(test);
8940         }
8941         if(uri) IUri_Release(uri);
8942     }
8943     if(builder) IUriBuilder_Release(builder);
8944 }
8945
8946 static void test_IUriBuilder_RemoveProperties(void) {
8947     IUriBuilder *builder = NULL;
8948     HRESULT hr;
8949     DWORD i;
8950
8951     hr = pCreateIUriBuilder(NULL, 0, 0, &builder);
8952     ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8953     if(SUCCEEDED(hr)) {
8954         /* Properties that can't be removed. */
8955         const DWORD invalid = Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_RAW_URI|Uri_HAS_HOST_TYPE|
8956                               Uri_HAS_SCHEME|Uri_HAS_ZONE;
8957
8958         for(i = Uri_PROPERTY_STRING_START; i <= Uri_PROPERTY_DWORD_LAST; ++i) {
8959             hr = IUriBuilder_RemoveProperties(builder, i << 1);
8960             if((i << 1) & invalid) {
8961                 ok(hr == E_INVALIDARG,
8962                     "Error: IUriBuilder_RemoveProperties returned 0x%08x, expected 0x%08x with prop=%d.\n",
8963                     hr, E_INVALIDARG, i);
8964             } else {
8965                 ok(hr == S_OK,
8966                     "Error: IUriBuilder_RemoveProperties returned 0x%08x, expected 0x%08x with prop=%d.\n",
8967                     hr, S_OK, i);
8968             }
8969         }
8970
8971         /* Also doesn't accept anything that's outside the range of the
8972          * Uri_HAS flags.
8973          */
8974         hr = IUriBuilder_RemoveProperties(builder, (Uri_PROPERTY_DWORD_LAST+1) << 1);
8975         ok(hr == E_INVALIDARG, "Error: IUriBuilder_RemoveProperties returned 0x%08x, expected 0x%08x.\n",
8976             hr, E_INVALIDARG);
8977     }
8978     if(builder) IUriBuilder_Release(builder);
8979
8980     for(i = 0; i < sizeof(uri_builder_remove_tests)/sizeof(uri_builder_remove_tests[0]); ++i) {
8981         uri_builder_remove_test test = uri_builder_remove_tests[i];
8982         IUri *uri = NULL;
8983         LPWSTR uriW;
8984
8985         uriW = a2w(test.uri);
8986         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
8987         if(SUCCEEDED(hr)) {
8988             builder = NULL;
8989
8990             hr = pCreateIUriBuilder(uri, 0, 0, &builder);
8991             if(test.create_builder_todo) {
8992                 todo_wine {
8993                     ok(hr == test.create_builder_expected,
8994                         "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x on test %d.\n",
8995                         hr, test.create_builder_expected, i);
8996                 }
8997             } else {
8998                 ok(hr == test.create_builder_expected,
8999                     "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x on test %d.\n",
9000                     hr, test.create_builder_expected, i);
9001             }
9002             if(SUCCEEDED(hr)) {
9003                 hr = IUriBuilder_RemoveProperties(builder, test.remove_properties);
9004                 if(test.remove_todo) {
9005                     todo_wine {
9006                         ok(hr == test.remove_expected,
9007                             "Error: IUriBuilder_RemoveProperties returned 0x%08x, expected 0x%08x on test %d.\n",
9008                             hr, test.remove_expected, i);
9009                     }
9010                 } else {
9011                     ok(hr == test.remove_expected,
9012                         "Error: IUriBuilder returned 0x%08x, expected 0x%08x on test %d.\n",
9013                         hr, test.remove_expected, i);
9014                 }
9015                 if(SUCCEEDED(hr)) {
9016                     IUri *result = NULL;
9017
9018                     hr = IUriBuilder_CreateUri(builder, test.expected_flags, 0, 0, &result);
9019                     if(test.expected_todo) {
9020                         todo_wine {
9021                             ok(hr == test.expected_hres,
9022                                 "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x on test %d.\n",
9023                                 hr, test.expected_hres, i);
9024                         }
9025                     } else {
9026                         ok(hr == test.expected_hres,
9027                             "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x on test %d.\n",
9028                             hr, test.expected_hres, i);
9029                     }
9030                     if(SUCCEEDED(hr)) {
9031                         BSTR received = NULL;
9032
9033                         hr = IUri_GetAbsoluteUri(result, &received);
9034                         ok(!strcmp_aw(test.expected_uri, received),
9035                             "Error: Expected %s but got %s instead on test %d.\n",
9036                             test.expected_uri, wine_dbgstr_w(received), i);
9037                         SysFreeString(received);
9038                     }
9039                     if(result) IUri_Release(result);
9040                 }
9041             }
9042             if(builder) IUriBuilder_Release(builder);
9043         }
9044         if(uri) IUri_Release(uri);
9045         heap_free(uriW);
9046     }
9047 }
9048
9049 static void test_IUriBuilder_Misc(void) {
9050     HRESULT hr;
9051     IUri *uri;
9052
9053     hr = pCreateUri(http_urlW, 0, 0, &uri);
9054     if(SUCCEEDED(hr)) {
9055         IUriBuilder *builder;
9056
9057         hr = pCreateIUriBuilder(uri, 0, 0, &builder);
9058         ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9059         if(SUCCEEDED(hr)) {
9060             BOOL has = -1;
9061             DWORD port = -1;
9062
9063             hr = IUriBuilder_GetPort(builder, &has, &port);
9064             ok(hr == S_OK, "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9065             if(SUCCEEDED(hr)) {
9066                 /* 'has' will be set to FALSE, even though uri had a port. */
9067                 ok(has == FALSE, "Error: Expected 'has' to be FALSE, was %d instead.\n", has);
9068                 /* Still sets 'port' to 80. */
9069                 ok(port == 80, "Error: Expected the port to be 80, but, was %d instead.\n", port);
9070             }
9071         }
9072         if(builder) IUriBuilder_Release(builder);
9073     }
9074     if(uri) IUri_Release(uri);
9075 }
9076
9077 static void test_IUriBuilderFactory(void) {
9078     HRESULT hr;
9079     IUri *uri;
9080     IUriBuilderFactory *factory;
9081     IUriBuilder *builder;
9082
9083     hr = pCreateUri(http_urlW, 0, 0, &uri);
9084     ok(SUCCEEDED(hr), "Error: CreateUri returned 0x%08x.\n", hr);
9085     if(SUCCEEDED(hr)) {
9086         factory = NULL;
9087         hr = IUri_QueryInterface(uri, &IID_IUriBuilderFactory, (void**)&factory);
9088         ok(hr == S_OK, "Error: Expected S_OK, but got 0x%08x.\n", hr);
9089         ok(factory != NULL, "Error: Expected 'factory' to not be NULL.\n");
9090
9091         if(SUCCEEDED(hr)) {
9092             builder = (void*) 0xdeadbeef;
9093             hr = IUriBuilderFactory_CreateInitializedIUriBuilder(factory, 10, 0, &builder);
9094             ok(hr == E_INVALIDARG, "Error: CreateInitializedIUriBuilder returned 0x%08x, expected 0x%08x.\n",
9095                 hr, E_INVALIDARG);
9096             ok(!builder, "Error: Expected 'builder' to be NULL, but was %p.\n", builder);
9097
9098             builder = (void*) 0xdeadbeef;
9099             hr = IUriBuilderFactory_CreateInitializedIUriBuilder(factory, 0, 10, &builder);
9100             ok(hr == E_INVALIDARG, "Error: CreateInitializedIUriBuilder returned 0x%08x, expected 0x%08x.\n",
9101                 hr, E_INVALIDARG);
9102             ok(!builder, "Error: Expected 'builder' to be NULL, but was %p.\n", builder);
9103
9104             hr = IUriBuilderFactory_CreateInitializedIUriBuilder(factory, 0, 0, NULL);
9105             ok(hr == E_POINTER, "Error: CreateInitializedIUriBuilder returned 0x%08x, expected 0x%08x.\n",
9106                 hr, E_POINTER);
9107
9108             builder = NULL;
9109             hr = IUriBuilderFactory_CreateInitializedIUriBuilder(factory, 0, 0, &builder);
9110             ok(hr == S_OK, "Error: CreateInitializedIUriBuilder returned 0x%08x, expected 0x%08x.\n",
9111                 hr, S_OK);
9112             if(SUCCEEDED(hr)) {
9113                 IUri *tmp = (void*) 0xdeadbeef;
9114                 LPCWSTR result;
9115                 DWORD result_len;
9116
9117                 /* Seems microsoft had a bit of mixup naming this function. It
9118                  * returns an uninitialized IUriBuilder.
9119                  */
9120                 hr = IUriBuilder_GetIUri(builder, &tmp);
9121                 ok(hr == S_OK, "Error: GetIUri returned 0x%08x, expected 0x%08x.\n",
9122                     hr, S_OK);
9123                 ok(!tmp, "Error: Expected 'tmp' to be NULL, but was %p instead.\n", tmp);
9124
9125                 hr = IUriBuilder_GetHost(builder, &result_len, &result);
9126                 ok(hr == S_FALSE, "Error: GetHost returned 0x%08x, expected 0x%08x.\n",
9127                     hr, S_FALSE);
9128             }
9129             if(builder) IUriBuilder_Release(builder);
9130
9131             builder = (void*) 0xdeadbeef;
9132             hr = IUriBuilderFactory_CreateIUriBuilder(factory, 10, 0, &builder);
9133             ok(hr == E_INVALIDARG, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n",
9134                 hr, E_INVALIDARG);
9135             ok(!builder, "Error: Expected 'builder' to be NULL, but was %p.\n", builder);
9136
9137             builder = (void*) 0xdeadbeef;
9138             hr = IUriBuilderFactory_CreateIUriBuilder(factory, 0, 10, &builder);
9139             ok(hr == E_INVALIDARG, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n",
9140                 hr, E_INVALIDARG);
9141             ok(!builder, "Error: Expected 'builder' to be NULL, but was %p.\n", builder);
9142
9143             hr = IUriBuilderFactory_CreateIUriBuilder(factory, 0, 0, NULL);
9144             ok(hr == E_POINTER, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n",
9145                 hr, E_POINTER);
9146
9147             builder = NULL;
9148             hr = IUriBuilderFactory_CreateIUriBuilder(factory, 0, 0, &builder);
9149             ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n",
9150                 hr, S_OK);
9151             if(SUCCEEDED(hr)) {
9152                 IUri *tmp = NULL;
9153
9154                 hr = IUriBuilder_GetIUri(builder, &tmp);
9155                 ok(hr == S_OK, "Error: GetIUri return 0x%08x, expected 0x%08x.\n",
9156                     hr, S_OK);
9157                 ok(tmp == uri, "Error: Expected tmp to be %p, but was %p.\n", uri, tmp);
9158                 if(uri) IUri_Release(uri);
9159             }
9160             if(builder) IUriBuilder_Release(builder);
9161         }
9162         if(factory) IUriBuilderFactory_Release(factory);
9163     }
9164     if(uri) IUri_Release(uri);
9165 }
9166
9167 static void test_CoInternetCombineIUri(void) {
9168     HRESULT hr;
9169     IUri *base, *relative, *result;
9170     DWORD i;
9171
9172     base = NULL;
9173     hr = pCreateUri(http_urlW, 0, 0, &base);
9174     ok(SUCCEEDED(hr), "Error: Expected CreateUri to succeed, got 0x%08x.\n", hr);
9175     if(SUCCEEDED(hr)) {
9176         result = (void*) 0xdeadbeef;
9177         hr = pCoInternetCombineIUri(base, NULL, 0, &result, 0);
9178         ok(hr == E_INVALIDARG, "Error: CoInternetCombineIUri returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
9179         ok(!result, "Error: Expected 'result' to be NULL, was %p.\n", result);
9180     }
9181
9182     relative = NULL;
9183     hr = pCreateUri(http_urlW, 0, 0, &relative);
9184     ok(SUCCEEDED(hr), "Error: Expected CreateUri to succeed, got 0x%08x.\n", hr);
9185     if(SUCCEEDED(hr)) {
9186         result = (void*) 0xdeadbeef;
9187         hr = pCoInternetCombineIUri(NULL, relative, 0, &result, 0);
9188         ok(hr == E_INVALIDARG, "Error: CoInternetCombineIUri returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
9189         ok(!result, "Error: Expected 'result' to be NULL, was %p.\n", result);
9190     }
9191
9192     hr = pCoInternetCombineIUri(base, relative, 0, NULL, 0);
9193     ok(hr == E_INVALIDARG, "Error: CoInternetCombineIUri returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
9194
9195     if(base) IUri_Release(base);
9196     if(relative) IUri_Release(relative);
9197
9198     for(i = 0; i < sizeof(uri_combine_tests)/sizeof(uri_combine_tests[0]); ++i) {
9199         LPWSTR baseW = a2w(uri_combine_tests[i].base_uri);
9200
9201         hr = pCreateUri(baseW, uri_combine_tests[i].base_create_flags, 0, &base);
9202         ok(SUCCEEDED(hr), "Error: Expected CreateUri to succeed, got 0x%08x on uri_combine_tests[%d].\n", hr, i);
9203         if(SUCCEEDED(hr)) {
9204             LPWSTR relativeW = a2w(uri_combine_tests[i].relative_uri);
9205
9206             hr = pCreateUri(relativeW, uri_combine_tests[i].relative_create_flags, 0, &relative);
9207             ok(SUCCEEDED(hr), "Error: Expected CreateUri to succeed, got 0x%08x on uri_combine_tests[%d].\n", hr, i);
9208             if(SUCCEEDED(hr)) {
9209                 result = NULL;
9210
9211                 hr = pCoInternetCombineIUri(base, relative, uri_combine_tests[i].combine_flags, &result, 0);
9212                 if(uri_combine_tests[i].todo) {
9213                     todo_wine {
9214                         ok(hr == uri_combine_tests[i].expected,
9215                             "Error: CoInternetCombineIUri returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].\n",
9216                             hr, uri_combine_tests[i].expected, i);
9217                     }
9218                 } else {
9219                     ok(hr == uri_combine_tests[i].expected,
9220                         "Error: CoInternetCombineIUri returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].\n",
9221                         hr, uri_combine_tests[i]. expected, i);
9222                 }
9223                 if(SUCCEEDED(hr)) {
9224                     DWORD j;
9225
9226                     for(j = 0; j < sizeof(uri_combine_tests[i].str_props)/sizeof(uri_combine_tests[i].str_props[0]); ++j) {
9227                         uri_combine_str_property prop = uri_combine_tests[i].str_props[j];
9228                         BSTR received;
9229
9230                         hr = IUri_GetPropertyBSTR(result, j, &received, 0);
9231                         if(prop.todo) {
9232                             todo_wine {
9233                                 ok(hr == prop.expected,
9234                                     "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].str_props[%d].\n",
9235                                     hr, prop.expected, i, j);
9236                             }
9237                             todo_wine {
9238                                 ok(!strcmp_aw(prop.value, received) ||
9239                                    broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
9240                                     "Error: Expected %s but got %s instead on uri_combine_tests[%d].str_props[%d].\n",
9241                                     prop.value, wine_dbgstr_w(received), i, j);
9242                             }
9243                         } else {
9244                             ok(hr == prop.expected,
9245                                 "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].str_props[%d].\n",
9246                                 hr, prop.expected, i, j);
9247                             ok(!strcmp_aw(prop.value, received) ||
9248                                broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
9249                                 "Error: Expected %s but got %s instead on uri_combine_tests[%d].str_props[%d].\n",
9250                                 prop.value, wine_dbgstr_w(received), i, j);
9251                         }
9252                         SysFreeString(received);
9253                     }
9254
9255                     for(j = 0; j < sizeof(uri_combine_tests[i].dword_props)/sizeof(uri_combine_tests[i].dword_props[0]); ++j) {
9256                         uri_dword_property prop = uri_combine_tests[i].dword_props[j];
9257                         DWORD received;
9258
9259                         hr = IUri_GetPropertyDWORD(result, j+Uri_PROPERTY_DWORD_START, &received, 0);
9260                         if(prop.todo) {
9261                             todo_wine {
9262                                 ok(hr == prop.expected,
9263                                     "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].dword_props[%d].\n",
9264                                     hr, prop.expected, i, j);
9265                             }
9266                             todo_wine {
9267                                 ok(prop.value == received, "Error: Expected %d, but got %d instead on uri_combine_tests[%d].dword_props[%d].\n",
9268                                     prop.value, received, i, j);
9269                             }
9270                         } else {
9271                             ok(hr == prop.expected,
9272                                 "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].dword_props[%d].\n",
9273                                 hr, prop.expected, i, j);
9274                             ok(prop.value == received, "Error: Expected %d, but got %d instead on uri_combine_tests[%d].dword_props[%d].\n",
9275                                 prop.value, received, i, j);
9276                         }
9277                     }
9278                 }
9279                 if(result) IUri_Release(result);
9280             }
9281             if(relative) IUri_Release(relative);
9282             heap_free(relativeW);
9283         }
9284         if(base) IUri_Release(base);
9285         heap_free(baseW);
9286     }
9287 }
9288
9289 static HRESULT WINAPI InternetProtocolInfo_QueryInterface(IInternetProtocolInfo *iface,
9290                                                           REFIID riid, void **ppv)
9291 {
9292     ok(0, "unexpected call\n");
9293     return E_NOINTERFACE;
9294 }
9295
9296 static ULONG WINAPI InternetProtocolInfo_AddRef(IInternetProtocolInfo *iface)
9297 {
9298     return 2;
9299 }
9300
9301 static ULONG WINAPI InternetProtocolInfo_Release(IInternetProtocolInfo *iface)
9302 {
9303     return 1;
9304 }
9305
9306 static HRESULT WINAPI InternetProtocolInfo_ParseUrl(IInternetProtocolInfo *iface, LPCWSTR pwzUrl,
9307         PARSEACTION ParseAction, DWORD dwParseFlags, LPWSTR pwzResult, DWORD cchResult,
9308         DWORD *pcchResult, DWORD dwReserved)
9309 {
9310     CHECK_EXPECT(ParseUrl);
9311     ok(!lstrcmpW(pwzUrl, parse_urlW), "Error: Expected %s, but got %s instead.\n",
9312         wine_dbgstr_w(parse_urlW), wine_dbgstr_w(pwzUrl));
9313     ok(ParseAction == parse_action, "Error: Expected %d, but got %d.\n", parse_action, ParseAction);
9314     ok(dwParseFlags == parse_flags, "Error: Expected 0x%08x, but got 0x%08x.\n", parse_flags, dwParseFlags);
9315     ok(cchResult == 200, "Error: Got %d.\n", cchResult);
9316
9317     memcpy(pwzResult, parse_resultW, sizeof(parse_resultW));
9318     *pcchResult = lstrlenW(parse_resultW);
9319
9320     return S_OK;
9321 }
9322
9323 static HRESULT WINAPI InternetProtocolInfo_CombineUrl(IInternetProtocolInfo *iface,
9324         LPCWSTR pwzBaseUrl, LPCWSTR pwzRelativeUrl, DWORD dwCombineFlags,
9325         LPWSTR pwzResult, DWORD cchResult, DWORD *pcchResult, DWORD dwReserved)
9326 {
9327     CHECK_EXPECT(CombineUrl);
9328     ok(!lstrcmpW(pwzBaseUrl, combine_baseW), "Error: Expected %s, but got %s instead.\n",
9329         wine_dbgstr_w(combine_baseW), wine_dbgstr_w(pwzBaseUrl));
9330     ok(!lstrcmpW(pwzRelativeUrl, combine_relativeW), "Error: Expected %s, but got %s instead.\n",
9331         wine_dbgstr_w(combine_relativeW), wine_dbgstr_w(pwzRelativeUrl));
9332     ok(dwCombineFlags == (URL_DONT_SIMPLIFY|URL_FILE_USE_PATHURL|URL_DONT_UNESCAPE_EXTRA_INFO),
9333         "Error: Expected 0, but got 0x%08x.\n", dwCombineFlags);
9334     ok(cchResult == INTERNET_MAX_URL_LENGTH+1, "Error: Got %d.\n", cchResult);
9335
9336     memcpy(pwzResult, combine_resultW, sizeof(combine_resultW));
9337     *pcchResult = lstrlenW(combine_resultW);
9338
9339     return S_OK;
9340 }
9341
9342 static HRESULT WINAPI InternetProtocolInfo_CompareUrl(IInternetProtocolInfo *iface,
9343         LPCWSTR pwzUrl1, LPCWSTR pwzUrl2, DWORD dwCompareFlags)
9344 {
9345     ok(0, "unexpected call\n");
9346     return E_NOTIMPL;
9347 }
9348
9349 static HRESULT WINAPI InternetProtocolInfo_QueryInfo(IInternetProtocolInfo *iface,
9350         LPCWSTR pwzUrl, QUERYOPTION OueryOption, DWORD dwQueryFlags, LPVOID pBuffer,
9351         DWORD cbBuffer, DWORD *pcbBuf, DWORD dwReserved)
9352 {
9353     ok(0, "unexpected call\n");
9354     return E_NOTIMPL;
9355 }
9356
9357 static const IInternetProtocolInfoVtbl InternetProtocolInfoVtbl = {
9358     InternetProtocolInfo_QueryInterface,
9359     InternetProtocolInfo_AddRef,
9360     InternetProtocolInfo_Release,
9361     InternetProtocolInfo_ParseUrl,
9362     InternetProtocolInfo_CombineUrl,
9363     InternetProtocolInfo_CompareUrl,
9364     InternetProtocolInfo_QueryInfo
9365 };
9366
9367 static IInternetProtocolInfo protocol_info = { &InternetProtocolInfoVtbl };
9368
9369 static HRESULT WINAPI ClassFactory_QueryInterface(IClassFactory *iface, REFIID riid, void **ppv)
9370 {
9371     if(IsEqualGUID(&IID_IInternetProtocolInfo, riid)) {
9372         *ppv = &protocol_info;
9373         return S_OK;
9374     }
9375
9376     ok(0, "unexpected call\n");
9377     return E_NOINTERFACE;
9378 }
9379
9380 static ULONG WINAPI ClassFactory_AddRef(IClassFactory *iface)
9381 {
9382     return 2;
9383 }
9384
9385 static ULONG WINAPI ClassFactory_Release(IClassFactory *iface)
9386 {
9387     return 1;
9388 }
9389
9390 static HRESULT WINAPI ClassFactory_CreateInstance(IClassFactory *iface, IUnknown *pOuter,
9391                                         REFIID riid, void **ppv)
9392 {
9393     ok(0, "unexpected call\n");
9394     return E_NOTIMPL;
9395 }
9396
9397 static HRESULT WINAPI ClassFactory_LockServer(IClassFactory *iface, BOOL dolock)
9398 {
9399     ok(0, "unexpected call\n");
9400     return S_OK;
9401 }
9402
9403 static const IClassFactoryVtbl ClassFactoryVtbl = {
9404     ClassFactory_QueryInterface,
9405     ClassFactory_AddRef,
9406     ClassFactory_Release,
9407     ClassFactory_CreateInstance,
9408     ClassFactory_LockServer
9409 };
9410
9411 static IClassFactory protocol_cf = { &ClassFactoryVtbl };
9412
9413 static void register_protocols(void)
9414 {
9415     IInternetSession *session;
9416     HRESULT hres;
9417
9418     hres = pCoInternetGetSession(0, &session, 0);
9419     ok(hres == S_OK, "CoInternetGetSession failed: %08x\n", hres);
9420     if(FAILED(hres))
9421         return;
9422
9423     hres = IInternetSession_RegisterNameSpace(session, &protocol_cf, &IID_NULL,
9424             winetestW, 0, NULL, 0);
9425     ok(hres == S_OK, "RegisterNameSpace failed: %08x\n", hres);
9426
9427     IInternetSession_Release(session);
9428 }
9429
9430 static void unregister_protocols(void) {
9431     IInternetSession *session;
9432     HRESULT hr;
9433
9434     hr = pCoInternetGetSession(0, &session, 0);
9435     ok(hr == S_OK, "CoInternetGetSession failed: 0x%08x\n", hr);
9436     if(FAILED(hr))
9437         return;
9438
9439     hr = IInternetSession_UnregisterNameSpace(session, &protocol_cf, winetestW);
9440     ok(hr == S_OK, "UnregisterNameSpace failed: 0x%08x\n", hr);
9441
9442     IInternetSession_Release(session);
9443 }
9444
9445 static void test_CoInternetCombineIUri_Pluggable(void) {
9446     HRESULT hr;
9447     IUri *base = NULL;
9448
9449     hr = pCreateUri(combine_baseW, 0, 0, &base);
9450     ok(SUCCEEDED(hr), "Error: CreateUri returned 0x%08x.\n", hr);
9451     if(SUCCEEDED(hr)) {
9452         IUri *relative = NULL;
9453
9454         hr = pCreateUri(combine_relativeW, Uri_CREATE_ALLOW_RELATIVE, 0, &relative);
9455         ok(SUCCEEDED(hr), "Error: CreateUri returned 0x%08x.\n", hr);
9456         if(SUCCEEDED(hr)) {
9457             IUri *result = NULL;
9458
9459             SET_EXPECT(CombineUrl);
9460
9461             hr = pCoInternetCombineIUri(base, relative, URL_DONT_SIMPLIFY|URL_FILE_USE_PATHURL|URL_DONT_UNESCAPE_EXTRA_INFO,
9462                                         &result, 0);
9463             ok(hr == S_OK, "Error: CoInternetCombineIUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9464
9465             CHECK_CALLED(CombineUrl);
9466
9467             if(SUCCEEDED(hr)) {
9468                 BSTR received = NULL;
9469                 hr = IUri_GetAbsoluteUri(result, &received);
9470                 ok(hr == S_OK, "Error: Expected S_OK, but got 0x%08x instead.\n", hr);
9471                 if(SUCCEEDED(hr)) {
9472                     ok(!lstrcmpW(combine_resultW, received), "Error: Expected %s, but got %s.\n",
9473                         wine_dbgstr_w(combine_resultW), wine_dbgstr_w(received));
9474                 }
9475                 SysFreeString(received);
9476             }
9477             if(result) IUri_Release(result);
9478         }
9479         if(relative) IUri_Release(relative);
9480     }
9481     if(base) IUri_Release(base);
9482 }
9483
9484 static void test_CoInternetCombineUrlEx(void) {
9485     HRESULT hr;
9486     IUri *base, *result;
9487     DWORD i;
9488
9489     base = NULL;
9490     hr = pCreateUri(http_urlW, 0, 0, &base);
9491     ok(SUCCEEDED(hr), "Error: CreateUri returned 0x%08x.\n", hr);
9492     if(SUCCEEDED(hr)) {
9493         result = (void*) 0xdeadbeef;
9494         hr = pCoInternetCombineUrlEx(base, NULL, 0, &result, 0);
9495         ok(hr == E_UNEXPECTED, "Error: CoInternetCombineUrlEx returned 0x%08x, expected 0x%08x.\n",
9496             hr, E_UNEXPECTED);
9497         ok(!result, "Error: Expected 'result' to be NULL was %p instead.\n", result);
9498     }
9499
9500     result = (void*) 0xdeadbeef;
9501     hr = pCoInternetCombineUrlEx(NULL, http_urlW, 0, &result, 0);
9502     ok(hr == E_INVALIDARG, "Error: CoInternetCombineUrlEx returned 0x%08x, expected 0x%08x.\n",
9503         hr, E_INVALIDARG);
9504     ok(!result, "Error: Expected 'result' to be NULL, but was %p instead.\n", result);
9505
9506     result = (void*) 0xdeadbeef;
9507     hr = pCoInternetCombineUrlEx(NULL, NULL, 0, &result, 0);
9508     ok(hr == E_UNEXPECTED, "Error: CoInternetCombineUrlEx returned 0x%08x, expected 0x%08x.\n",
9509         hr, E_UNEXPECTED);
9510     ok(!result, "Error: Expected 'result' to be NULL, but was %p instead.\n", result);
9511
9512     hr = pCoInternetCombineUrlEx(base, http_urlW, 0, NULL, 0);
9513     ok(hr == E_POINTER, "Error: CoInternetCombineUrlEx returned 0x%08x, expected 0x%08x.\n",
9514         hr, E_POINTER);
9515     if(base) IUri_Release(base);
9516
9517     for(i = 0; i < sizeof(uri_combine_tests)/sizeof(uri_combine_tests[0]); ++i) {
9518         LPWSTR baseW = a2w(uri_combine_tests[i].base_uri);
9519
9520         hr = pCreateUri(baseW, uri_combine_tests[i].base_create_flags, 0, &base);
9521         ok(SUCCEEDED(hr), "Error: CreateUri returned 0x%08x on uri_combine_tests[%d].\n", hr, i);
9522         if(SUCCEEDED(hr)) {
9523             LPWSTR relativeW = a2w(uri_combine_tests[i].relative_uri);
9524
9525             hr = pCoInternetCombineUrlEx(base, relativeW, uri_combine_tests[i].combine_flags,
9526                                          &result, 0);
9527             if(uri_combine_tests[i].todo) {
9528                 todo_wine {
9529                     ok(hr == uri_combine_tests[i].expected,
9530                         "Error: CoInternetCombineUrlEx returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].\n",
9531                         hr, uri_combine_tests[i].expected, i);
9532                 }
9533             } else {
9534                 ok(hr == uri_combine_tests[i].expected,
9535                     "Error: CoInternetCombineUrlEx returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].\n",
9536                     hr, uri_combine_tests[i]. expected, i);
9537             }
9538             if(SUCCEEDED(hr)) {
9539                 DWORD j;
9540
9541                 for(j = 0; j < sizeof(uri_combine_tests[i].str_props)/sizeof(uri_combine_tests[i].str_props[0]); ++j) {
9542                     uri_combine_str_property prop = uri_combine_tests[i].str_props[j];
9543                     BSTR received;
9544                     LPCSTR value = (prop.value_ex) ? prop.value_ex : prop.value;
9545
9546                     hr = IUri_GetPropertyBSTR(result, j, &received, 0);
9547                     if(prop.todo) {
9548                         todo_wine {
9549                             ok(hr == prop.expected,
9550                                 "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].str_props[%d].\n",
9551                                 hr, prop.expected, i, j);
9552                         }
9553                         todo_wine {
9554                             ok(!strcmp_aw(value, received) ||
9555                                broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
9556                                 "Error: Expected %s but got %s instead on uri_combine_tests[%d].str_props[%d].\n",
9557                                 value, wine_dbgstr_w(received), i, j);
9558                         }
9559                     } else {
9560                         ok(hr == prop.expected,
9561                             "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].str_props[%d].\n",
9562                             hr, prop.expected, i, j);
9563                         ok(!strcmp_aw(value, received) ||
9564                            broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
9565                             "Error: Expected %s but got %s instead on uri_combine_tests[%d].str_props[%d].\n",
9566                             value, wine_dbgstr_w(received), i, j);
9567                     }
9568                     SysFreeString(received);
9569                 }
9570
9571                 for(j = 0; j < sizeof(uri_combine_tests[i].dword_props)/sizeof(uri_combine_tests[i].dword_props[0]); ++j) {
9572                     uri_dword_property prop = uri_combine_tests[i].dword_props[j];
9573                     DWORD received;
9574
9575                     hr = IUri_GetPropertyDWORD(result, j+Uri_PROPERTY_DWORD_START, &received, 0);
9576                     if(prop.todo) {
9577                         todo_wine {
9578                             ok(hr == prop.expected,
9579                                 "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].dword_props[%d].\n",
9580                                 hr, prop.expected, i, j);
9581                         }
9582                         todo_wine {
9583                             ok(prop.value == received, "Error: Expected %d, but got %d instead on uri_combine_tests[%d].dword_props[%d].\n",
9584                                 prop.value, received, i, j);
9585                         }
9586                     } else {
9587                         ok(hr == prop.expected,
9588                             "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].dword_props[%d].\n",
9589                             hr, prop.expected, i, j);
9590                         ok(prop.value == received, "Error: Expected %d, but got %d instead on uri_combine_tests[%d].dword_props[%d].\n",
9591                             prop.value, received, i, j);
9592                     }
9593                 }
9594             }
9595             if(result) IUri_Release(result);
9596             heap_free(relativeW);
9597         }
9598         if(base) IUri_Release(base);
9599         heap_free(baseW);
9600     }
9601 }
9602
9603 static void test_CoInternetCombineUrlEx_Pluggable(void) {
9604     HRESULT hr;
9605     IUri *base = NULL;
9606
9607     hr = pCreateUri(combine_baseW, 0, 0, &base);
9608     ok(SUCCEEDED(hr), "Error: CreateUri returned 0x%08x.\n", hr);
9609     if(SUCCEEDED(hr)) {
9610         IUri *result = NULL;
9611
9612         SET_EXPECT(CombineUrl);
9613
9614         hr = pCoInternetCombineUrlEx(base, combine_relativeW, URL_DONT_SIMPLIFY|URL_FILE_USE_PATHURL|URL_DONT_UNESCAPE_EXTRA_INFO,
9615                                      &result, 0);
9616         ok(hr == S_OK, "Error: CoInternetCombineUrlEx returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9617
9618         CHECK_CALLED(CombineUrl);
9619
9620         if(SUCCEEDED(hr)) {
9621             BSTR received = NULL;
9622             hr = IUri_GetAbsoluteUri(result, &received);
9623             ok(hr == S_OK, "Error: Expected S_OK, but got 0x%08x instead.\n", hr);
9624             if(SUCCEEDED(hr)) {
9625                 ok(!lstrcmpW(combine_resultW, received), "Error: Expected %s, but got %s.\n",
9626                     wine_dbgstr_w(combine_resultW), wine_dbgstr_w(received));
9627             }
9628             SysFreeString(received);
9629         }
9630         if(result) IUri_Release(result);
9631     }
9632     if(base) IUri_Release(base);
9633 }
9634
9635 static void test_CoInternetParseIUri_InvalidArgs(void) {
9636     HRESULT hr;
9637     IUri *uri = NULL;
9638     WCHAR tmp[3];
9639     DWORD result = -1;
9640
9641     hr = pCoInternetParseIUri(NULL, PARSE_CANONICALIZE, 0, tmp, 3, &result, 0);
9642     ok(hr == E_INVALIDARG, "Error: CoInternetParseIUri returned 0x%08x, expected 0x%08x.\n",
9643         hr, E_INVALIDARG);
9644     ok(!result, "Error: Expected 'result' to be 0, but was %d.\n", result);
9645
9646     hr = pCreateUri(http_urlW, 0, 0, &uri);
9647     ok(SUCCEEDED(hr), "Error: CreateUri returned 0x%08x.\n", hr);
9648     if(SUCCEEDED(hr)) {
9649         DWORD expected_len;
9650
9651         result = -1;
9652         hr = pCoInternetParseIUri(uri, PARSE_CANONICALIZE, 0, NULL, 0, &result, 0);
9653         ok(hr == E_INVALIDARG, "Error: CoInternetParseIUri returned 0x%08x, expected 0x%08x.\n",
9654             hr, E_INVALIDARG);
9655         ok(!result, "Error: Expected 'result' to be 0, but was %d.\n", result);
9656
9657         hr = pCoInternetParseIUri(uri, PARSE_CANONICALIZE, 0, tmp, 3, NULL, 0);
9658         ok(hr == E_POINTER, "Error: CoInternetParseIUri returned 0x%08x, expected 0x%08x.\n",
9659             hr, E_POINTER);
9660
9661         result = -1;
9662         hr = pCoInternetParseIUri(uri, PARSE_SECURITY_URL, 0, tmp, 3, &result, 0);
9663         ok(hr == E_FAIL, "Error: CoInternetParseIUri returned 0x%08x expected 0x%08x.\n",
9664             hr, E_FAIL);
9665         ok(!result, "Error: Expected 'result' to be 0, but was %d.\n", result);
9666
9667         result = -1;
9668         hr = pCoInternetParseIUri(uri, PARSE_MIME, 0, tmp, 3, &result, 0);
9669         ok(hr == E_FAIL, "Error: CoInternetParseIUri returned 0x%08x, expected 0x%08x.\n",
9670             hr, E_FAIL);
9671         ok(!result, "Error: Expected 'result' to be 0, but was %d.\n", result);
9672
9673         result = -1;
9674         hr = pCoInternetParseIUri(uri, PARSE_SERVER, 0, tmp, 3, &result, 0);
9675         ok(hr == E_FAIL, "Error: CoInternetParseIUri returned 0x%08x, expected 0x%08x.\n",
9676             hr, E_FAIL);
9677         ok(!result, "Error: Expected 'result' to be 0, but was %d.\n", result);
9678
9679         result = -1;
9680         hr = pCoInternetParseIUri(uri, PARSE_SECURITY_DOMAIN, 0, tmp, 3, &result, 0);
9681         ok(hr == E_FAIL, "Error: CoInternetParseIUri returned 0x%08x, expected 0x%08x.\n",
9682             hr, E_FAIL);
9683         ok(!result, "Error: Expected 'result' to be 0, but was %d.\n", result);
9684
9685         expected_len = lstrlenW(http_urlW);
9686         result = -1;
9687         hr = pCoInternetParseIUri(uri, PARSE_CANONICALIZE, 0, tmp, 3, &result, 0);
9688         ok(hr == STRSAFE_E_INSUFFICIENT_BUFFER,
9689             "Error: CoInternetParseIUri returned 0x%08x, expected 0x%08x.\n",
9690             hr, STRSAFE_E_INSUFFICIENT_BUFFER);
9691         ok(result == expected_len, "Error: Expected 'result' to be %d, but was %d instead.\n",
9692             expected_len, result);
9693     }
9694     if(uri) IUri_Release(uri);
9695 }
9696
9697 static void test_CoInternetParseIUri(void) {
9698     DWORD i;
9699
9700     for(i = 0; i < sizeof(uri_parse_tests)/sizeof(uri_parse_tests[0]); ++i) {
9701         HRESULT hr;
9702         IUri *uri;
9703         LPWSTR uriW;
9704         uri_parse_test test = uri_parse_tests[i];
9705
9706         uriW = a2w(test.uri);
9707         hr = pCreateUri(uriW, test.uri_flags, 0, &uri);
9708         ok(SUCCEEDED(hr), "Error: CreateUri returned 0x%08x on uri_parse_tests[%d].\n", hr, i);
9709         if(SUCCEEDED(hr)) {
9710             WCHAR result[INTERNET_MAX_URL_LENGTH+1];
9711             DWORD result_len = -1;
9712
9713             hr = pCoInternetParseIUri(uri, test.action, test.flags, result, INTERNET_MAX_URL_LENGTH+1, &result_len, 0);
9714             if(test.todo) {
9715                 todo_wine {
9716                     ok(hr == test.expected,
9717                         "Error: CoInternetParseIUri returned 0x%08x, expected 0x%08x on uri_parse_tests[%d].\n",
9718                         hr, test.expected, i);
9719                 }
9720             } else {
9721                 ok(hr == test.expected,
9722                     "Error: CoInternetParseIUri returned 0x%08x, expected 0x%08x on uri_parse_tests[%d].\n",
9723                     hr, test.expected, i);
9724             }
9725             if(SUCCEEDED(hr)) {
9726                 DWORD len = lstrlenA(test.property);
9727                 ok(!strcmp_aw(test.property, result),
9728                     "Error: Expected %s but got %s instead on uri_parse_tests[%d].\n",
9729                     test.property, wine_dbgstr_w(result), i);
9730                 ok(len == result_len,
9731                     "Error: Expected %d, but got %d instead on uri_parse_tests[%d].\n",
9732                     len, result_len, i);
9733             } else {
9734                 ok(!result_len,
9735                     "Error: Expected 'result_len' to be 0, but was %d on uri_parse_tests[%d].\n",
9736                     result_len, i);
9737             }
9738         }
9739         if(uri) IUri_Release(uri);
9740         heap_free(uriW);
9741     }
9742 }
9743
9744 static void test_CoInternetParseIUri_Pluggable(void) {
9745     HRESULT hr;
9746     IUri *uri = NULL;
9747
9748     hr = pCreateUri(parse_urlW, 0, 0, &uri);
9749     ok(SUCCEEDED(hr), "Error: Expected CreateUri to succeed, but got 0x%08x.\n", hr);
9750     if(SUCCEEDED(hr)) {
9751         WCHAR result[200];
9752         DWORD result_len;
9753
9754         SET_EXPECT(ParseUrl);
9755
9756         parse_action = PARSE_CANONICALIZE;
9757         parse_flags = URL_UNESCAPE|URL_ESCAPE_UNSAFE;
9758
9759         hr = pCoInternetParseIUri(uri, parse_action, parse_flags, result, 200, &result_len, 0);
9760         ok(hr == S_OK, "Error: CoInternetParseIUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9761
9762         CHECK_CALLED(ParseUrl);
9763
9764         if(SUCCEEDED(hr)) {
9765             ok(result_len == lstrlenW(parse_resultW), "Error: Expected %d, but got %d.\n",
9766                 lstrlenW(parse_resultW), result_len);
9767             ok(!lstrcmpW(result, parse_resultW), "Error: Expected %s, but got %s.\n",
9768                 wine_dbgstr_w(parse_resultW), wine_dbgstr_w(result));
9769         }
9770     }
9771     if(uri) IUri_Release(uri);
9772 }
9773
9774 START_TEST(uri) {
9775     HMODULE hurlmon;
9776
9777     hurlmon = GetModuleHandle("urlmon.dll");
9778     pCoInternetGetSession = (void*) GetProcAddress(hurlmon, "CoInternetGetSession");
9779     pCreateUri = (void*) GetProcAddress(hurlmon, "CreateUri");
9780     pCreateUriWithFragment = (void*) GetProcAddress(hurlmon, "CreateUriWithFragment");
9781     pCreateIUriBuilder = (void*) GetProcAddress(hurlmon, "CreateIUriBuilder");
9782     pCoInternetCombineIUri = (void*) GetProcAddress(hurlmon, "CoInternetCombineIUri");
9783     pCoInternetCombineUrlEx = (void*) GetProcAddress(hurlmon, "CoInternetCombineUrlEx");
9784     pCoInternetParseIUri = (void*) GetProcAddress(hurlmon, "CoInternetParseIUri");
9785
9786     if(!pCreateUri) {
9787         win_skip("CreateUri is not present, skipping tests.\n");
9788         return;
9789     }
9790
9791     trace("test CreateUri invalid flags...\n");
9792     test_CreateUri_InvalidFlags();
9793
9794     trace("test CreateUri invalid args...\n");
9795     test_CreateUri_InvalidArgs();
9796
9797     trace("test CreateUri invalid URIs...\n");
9798     test_CreateUri_InvalidUri();
9799
9800     trace("test IUri_GetPropertyBSTR...\n");
9801     test_IUri_GetPropertyBSTR();
9802
9803     trace("test IUri_GetPropertyDWORD...\n");
9804     test_IUri_GetPropertyDWORD();
9805
9806     trace("test IUri_GetStrProperties...\n");
9807     test_IUri_GetStrProperties();
9808
9809     trace("test IUri_GetDwordProperties...\n");
9810     test_IUri_GetDwordProperties();
9811
9812     trace("test IUri_GetPropertyLength...\n");
9813     test_IUri_GetPropertyLength();
9814
9815     trace("test IUri_GetProperties...\n");
9816     test_IUri_GetProperties();
9817
9818     trace("test IUri_HasProperty...\n");
9819     test_IUri_HasProperty();
9820
9821     trace("test IUri_IsEqual...\n");
9822     test_IUri_IsEqual();
9823
9824     trace("test CreateUriWithFragment invalid args...\n");
9825     test_CreateUriWithFragment_InvalidArgs();
9826
9827     trace("test CreateUriWithFragment invalid flags...\n");
9828     test_CreateUriWithFragment_InvalidFlags();
9829
9830     trace("test CreateUriWithFragment...\n");
9831     test_CreateUriWithFragment();
9832
9833     trace("test CreateIUriBuilder...\n");
9834     test_CreateIUriBuilder();
9835
9836     trace("test IUriBuilder_CreateInvalidArgs...\n");
9837     test_IUriBuilder_CreateInvalidArgs();
9838
9839     trace("test IUriBuilder...\n");
9840     test_IUriBuilder();
9841
9842     trace("test IUriBuilder_GetInvalidArgs...\n");
9843     test_IUriBuilder_GetInvalidArgs();
9844
9845     trace("test IUriBuilder_HasBeenModified...\n");
9846     test_IUriBuilder_HasBeenModified();
9847
9848     trace("test IUriBuilder_IUriProperty...\n");
9849     test_IUriBuilder_IUriProperty();
9850
9851     trace("test IUriBuilder_RemoveProperties...\n");
9852     test_IUriBuilder_RemoveProperties();
9853
9854     trace("test IUriBuilder miscellaneous...\n");
9855     test_IUriBuilder_Misc();
9856
9857     trace("test IUriBuilderFactory...\n");
9858     test_IUriBuilderFactory();
9859
9860     trace("test CoInternetCombineIUri...\n");
9861     test_CoInternetCombineIUri();
9862
9863     trace("test CoInternetCombineUrlEx...\n");
9864     test_CoInternetCombineUrlEx();
9865
9866     trace("test CoInternetParseIUri Invalid Args...\n");
9867     test_CoInternetParseIUri_InvalidArgs();
9868
9869     trace("test CoInternetParseIUri...\n");
9870     test_CoInternetParseIUri();
9871
9872     register_protocols();
9873
9874     trace("test CoInternetCombineIUri pluggable...\n");
9875     test_CoInternetCombineIUri_Pluggable();
9876
9877     trace("test CoInternetCombineUrlEx Pluggable...\n");
9878     test_CoInternetCombineUrlEx_Pluggable();
9879
9880     trace("test CoInternetParseIUri pluggable...\n");
9881     test_CoInternetParseIUri_Pluggable();
9882
9883     unregister_protocols();
9884 }