Release 1.5.29.
[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 #define WIN32_LEAN_AND_MEAN
28
29 #include "windef.h"
30 #include "winbase.h"
31 #include "urlmon.h"
32 #include "shlwapi.h"
33 #include "wininet.h"
34 #include "strsafe.h"
35 #include "initguid.h"
36
37 DEFINE_GUID(CLSID_CUri, 0xDF2FCE13, 0x25EC, 0x45BB, 0x9D,0x4C, 0xCE,0xCD,0x47,0xC2,0x43,0x0C);
38
39 #define URI_STR_PROPERTY_COUNT Uri_PROPERTY_STRING_LAST+1
40 #define URI_DWORD_PROPERTY_COUNT (Uri_PROPERTY_DWORD_LAST - Uri_PROPERTY_DWORD_START)+1
41 #define URI_BUILDER_STR_PROPERTY_COUNT 7
42
43 #define DEFINE_EXPECT(func) \
44     static BOOL expect_ ## func = FALSE, called_ ## func = FALSE
45
46 #define SET_EXPECT(func) \
47     expect_ ## func = TRUE
48
49 #define CHECK_EXPECT(func) \
50     do { \
51         ok(expect_ ##func, "unexpected call " #func "\n"); \
52         expect_ ## func = FALSE; \
53         called_ ## func = TRUE; \
54     }while(0)
55
56 #define CHECK_EXPECT2(func) \
57     do { \
58         ok(expect_ ##func, "unexpected call " #func "\n"); \
59         called_ ## func = TRUE; \
60     }while(0)
61
62 #define CHECK_CALLED(func) \
63     do { \
64         ok(called_ ## func, "expected " #func "\n"); \
65         expect_ ## func = called_ ## func = FALSE; \
66     }while(0)
67
68 DEFINE_EXPECT(CombineUrl);
69 DEFINE_EXPECT(ParseUrl);
70
71 static HRESULT (WINAPI *pCreateUri)(LPCWSTR, DWORD, DWORD_PTR, IUri**);
72 static HRESULT (WINAPI *pCreateUriWithFragment)(LPCWSTR, LPCWSTR, DWORD, DWORD_PTR, IUri**);
73 static HRESULT (WINAPI *pCreateIUriBuilder)(IUri*, DWORD, DWORD_PTR, IUriBuilder**);
74 static HRESULT (WINAPI *pCoInternetCombineIUri)(IUri*,IUri*,DWORD,IUri**,DWORD_PTR);
75 static HRESULT (WINAPI *pCoInternetGetSession)(DWORD,IInternetSession**,DWORD);
76 static HRESULT (WINAPI *pCoInternetCombineUrlEx)(IUri*,LPCWSTR,DWORD,IUri**,DWORD_PTR);
77 static HRESULT (WINAPI *pCoInternetParseIUri)(IUri*,PARSEACTION,DWORD,LPWSTR,DWORD,DWORD*,DWORD_PTR);
78 static HRESULT (WINAPI *pCreateURLMonikerEx)(IMoniker*,LPCWSTR,IMoniker**,DWORD);
79 static HRESULT (WINAPI *pCreateURLMonikerEx2)(IMoniker*,IUri*,IMoniker**,DWORD);
80
81 static const WCHAR http_urlW[] = { 'h','t','t','p',':','/','/','w','w','w','.','w','i','n','e','h','q',
82         '.','o','r','g','/',0};
83 static const WCHAR http_url_fragW[] = { 'h','t','t','p',':','/','/','w','w','w','.','w','i','n','e','h','q',
84         '.','o','r','g','/','#','F','r','a','g',0};
85
86 static const WCHAR combine_baseW[] = {'w','i','n','e','t','e','s','t',':','?','t',
87         'e','s','t','i','n','g',0};
88 static const WCHAR combine_relativeW[] = {'?','t','e','s','t',0};
89 static const WCHAR combine_resultW[] = {'z','i','p',':','t','e','s','t',0};
90
91 static const WCHAR winetestW[] = {'w','i','n','e','t','e','s','t',0};
92
93 static const WCHAR parse_urlW[] = {'w','i','n','e','t','e','s','t',':','t','e','s','t',0};
94 static const WCHAR parse_resultW[] = {'z','i','p',':','t','e','s','t',0};
95
96 static PARSEACTION parse_action;
97 static DWORD parse_flags;
98
99 typedef struct _uri_create_flag_test {
100     DWORD   flags;
101     HRESULT expected;
102 } uri_create_flag_test;
103
104 static const uri_create_flag_test invalid_flag_tests[] = {
105     /* Set of invalid flag combinations to test for. */
106     {Uri_CREATE_DECODE_EXTRA_INFO | Uri_CREATE_NO_DECODE_EXTRA_INFO, E_INVALIDARG},
107     {Uri_CREATE_CANONICALIZE | Uri_CREATE_NO_CANONICALIZE, E_INVALIDARG},
108     {Uri_CREATE_CRACK_UNKNOWN_SCHEMES | Uri_CREATE_NO_CRACK_UNKNOWN_SCHEMES, E_INVALIDARG},
109     {Uri_CREATE_PRE_PROCESS_HTML_URI | Uri_CREATE_NO_PRE_PROCESS_HTML_URI, E_INVALIDARG},
110     {Uri_CREATE_IE_SETTINGS | Uri_CREATE_NO_IE_SETTINGS, E_INVALIDARG}
111 };
112
113 typedef struct _uri_str_property {
114     const char* value;
115     HRESULT     expected;
116     BOOL        todo;
117     const char* broken_value;
118 } uri_str_property;
119
120 typedef struct _uri_dword_property {
121     DWORD   value;
122     HRESULT expected;
123     BOOL    todo;
124     BOOL    broken_combine_hres;
125 } uri_dword_property;
126
127 typedef struct _uri_properties {
128     const char*         uri;
129     DWORD               create_flags;
130     HRESULT             create_expected;
131     BOOL                create_todo;
132
133     uri_str_property    str_props[URI_STR_PROPERTY_COUNT];
134     uri_dword_property  dword_props[URI_DWORD_PROPERTY_COUNT];
135 } uri_properties;
136
137 static const uri_properties uri_tests[] = {
138     {   "http://www.winehq.org/tests/../tests/../..", 0, S_OK, FALSE,
139         {
140             {"http://www.winehq.org/",S_OK,FALSE},                      /* ABSOLUTE_URI */
141             {"www.winehq.org",S_OK,FALSE},                              /* AUTHORITY */
142             {"http://www.winehq.org/",S_OK,FALSE},                      /* DISPLAY_URI */
143             {"winehq.org",S_OK,FALSE},                                  /* DOMAIN */
144             {"",S_FALSE,FALSE},                                         /* EXTENSION */
145             {"",S_FALSE,FALSE},                                         /* FRAGMENT */
146             {"www.winehq.org",S_OK,FALSE},                              /* HOST */
147             {"",S_FALSE,FALSE},                                         /* PASSWORD */
148             {"/",S_OK,FALSE},                                           /* PATH */
149             {"/",S_OK,FALSE},                                           /* PATH_AND_QUERY */
150             {"",S_FALSE,FALSE},                                         /* QUERY */
151             {"http://www.winehq.org/tests/../tests/../..",S_OK,FALSE},  /* RAW_URI */
152             {"http",S_OK,FALSE},                                        /* SCHEME_NAME */
153             {"",S_FALSE,FALSE},                                         /* USER_INFO */
154             {"",S_FALSE,FALSE}                                          /* USER_NAME */
155         },
156         {
157             {Uri_HOST_DNS,S_OK,FALSE},                                  /* HOST_TYPE */
158             {80,S_OK,FALSE},                                            /* PORT */
159             {URL_SCHEME_HTTP,S_OK,FALSE},                               /* SCHEME */
160             {URLZONE_INVALID,E_NOTIMPL,FALSE}                           /* ZONE */
161         }
162     },
163     {   "http://winehq.org/tests/.././tests", 0, S_OK, FALSE,
164         {
165             {"http://winehq.org/tests",S_OK,FALSE},
166             {"winehq.org",S_OK,FALSE},
167             {"http://winehq.org/tests",S_OK,FALSE},
168             {"winehq.org",S_OK,FALSE},
169             {"",S_FALSE,FALSE},
170             {"",S_FALSE,FALSE},
171             {"winehq.org",S_OK,FALSE},
172             {"",S_FALSE,FALSE},
173             {"/tests",S_OK,FALSE},
174             {"/tests",S_OK,FALSE},
175             {"",S_FALSE,FALSE},
176             {"http://winehq.org/tests/.././tests",S_OK,FALSE},
177             {"http",S_OK,FALSE},
178             {"",S_FALSE,FALSE},
179             {"",S_FALSE,FALSE}
180         },
181         {
182             {Uri_HOST_DNS,S_OK,FALSE},
183             {80,S_OK,FALSE},
184             {URL_SCHEME_HTTP,S_OK,FALSE},
185             {URLZONE_INVALID,E_NOTIMPL,FALSE}
186         }
187     },
188     {   "HtTp://www.winehq.org/tests/..?query=x&return=y", 0, S_OK, FALSE,
189         {
190             {"http://www.winehq.org/?query=x&return=y",S_OK,FALSE},
191             {"www.winehq.org",S_OK,FALSE},
192             {"http://www.winehq.org/?query=x&return=y",S_OK,FALSE},
193             {"winehq.org",S_OK,FALSE},
194             {"",S_FALSE,FALSE},
195             {"",S_FALSE,FALSE},
196             {"www.winehq.org",S_OK,FALSE},
197             {"",S_FALSE,FALSE},
198             {"/",S_OK,FALSE},
199             {"/?query=x&return=y",S_OK,FALSE},
200             {"?query=x&return=y",S_OK,FALSE},
201             {"HtTp://www.winehq.org/tests/..?query=x&return=y",S_OK,FALSE},
202             {"http",S_OK,FALSE},
203             {"",S_FALSE,FALSE},
204             {"",S_FALSE,FALSE}
205         },
206         {
207             {Uri_HOST_DNS,S_OK,FALSE},
208             {80,S_OK,FALSE},
209             {URL_SCHEME_HTTP,S_OK,FALSE},
210             {URLZONE_INVALID,E_NOTIMPL,FALSE},
211         }
212     },
213     {   "HtTpS://www.winehq.org/tests/..?query=x&return=y", 0, S_OK, FALSE,
214         {
215             {"https://www.winehq.org/?query=x&return=y",S_OK,FALSE},
216             {"www.winehq.org",S_OK,FALSE},
217             {"https://www.winehq.org/?query=x&return=y",S_OK,FALSE},
218             {"winehq.org",S_OK,FALSE},
219             {"",S_FALSE,FALSE},
220             {"",S_FALSE,FALSE},
221             {"www.winehq.org",S_OK,FALSE},
222             {"",S_FALSE,FALSE},
223             {"/",S_OK,FALSE},
224             {"/?query=x&return=y",S_OK,FALSE},
225             {"?query=x&return=y",S_OK,FALSE},
226             {"HtTpS://www.winehq.org/tests/..?query=x&return=y",S_OK,FALSE},
227             {"https",S_OK,FALSE},
228             {"",S_FALSE,FALSE},
229             {"",S_FALSE,FALSE}
230         },
231         {
232             {Uri_HOST_DNS,S_OK,FALSE},
233             {443,S_OK,FALSE},
234             {URL_SCHEME_HTTPS,S_OK,FALSE},
235             {URLZONE_INVALID,E_NOTIMPL,FALSE},
236         }
237     },
238     {   "hTTp://us%45r%3Ainfo@examp%4CE.com:80/path/a/b/./c/../%2E%2E/Forbidden'<|> Characters", 0, S_OK, FALSE,
239         {
240             {"http://usEr%3Ainfo@example.com/path/a/Forbidden'%3C%7C%3E%20Characters",S_OK,FALSE},
241             {"usEr%3Ainfo@example.com",S_OK,FALSE},
242             {"http://example.com/path/a/Forbidden'%3C%7C%3E%20Characters",S_OK,FALSE},
243             {"example.com",S_OK,FALSE},
244             {"",S_FALSE,FALSE},
245             {"",S_FALSE,FALSE},
246             {"example.com",S_OK,FALSE},
247             {"",S_FALSE,FALSE},
248             {"/path/a/Forbidden'%3C%7C%3E%20Characters",S_OK,FALSE},
249             {"/path/a/Forbidden'%3C%7C%3E%20Characters",S_OK,FALSE},
250             {"",S_FALSE,FALSE},
251             {"hTTp://us%45r%3Ainfo@examp%4CE.com:80/path/a/b/./c/../%2E%2E/Forbidden'<|> Characters",S_OK,FALSE},
252             {"http",S_OK,FALSE},
253             {"usEr%3Ainfo",S_OK,FALSE},
254             {"usEr%3Ainfo",S_OK,FALSE}
255         },
256         {
257             {Uri_HOST_DNS,S_OK,FALSE},
258             {80,S_OK,FALSE},
259             {URL_SCHEME_HTTP,S_OK,FALSE},
260             {URLZONE_INVALID,E_NOTIMPL,FALSE},
261         }
262     },
263     {   "ftp://winepass:wine@ftp.winehq.org:9999/dir/foo bar.txt", 0, S_OK, FALSE,
264         {
265             {"ftp://winepass:wine@ftp.winehq.org:9999/dir/foo%20bar.txt",S_OK,FALSE},
266             {"winepass:wine@ftp.winehq.org:9999",S_OK,FALSE},
267             {"ftp://ftp.winehq.org:9999/dir/foo%20bar.txt",S_OK,FALSE},
268             {"winehq.org",S_OK,FALSE},
269             {".txt",S_OK,FALSE},
270             {"",S_FALSE,FALSE},
271             {"ftp.winehq.org",S_OK,FALSE},
272             {"wine",S_OK,FALSE},
273             {"/dir/foo%20bar.txt",S_OK,FALSE},
274             {"/dir/foo%20bar.txt",S_OK,FALSE},
275             {"",S_FALSE,FALSE},
276             {"ftp://winepass:wine@ftp.winehq.org:9999/dir/foo bar.txt",S_OK,FALSE},
277             {"ftp",S_OK,FALSE},
278             {"winepass:wine",S_OK,FALSE},
279             {"winepass",S_OK,FALSE}
280         },
281         {
282             {Uri_HOST_DNS,S_OK,FALSE},
283             {9999,S_OK,FALSE},
284             {URL_SCHEME_FTP,S_OK,FALSE},
285             {URLZONE_INVALID,E_NOTIMPL,FALSE}
286         }
287     },
288     {   "file://c:\\tests\\../tests/foo%20bar.mp3", 0, S_OK, FALSE,
289         {
290             {"file:///c:/tests/foo%2520bar.mp3",S_OK,FALSE},
291             {"",S_FALSE,FALSE},
292             {"file:///c:/tests/foo%2520bar.mp3",S_OK,FALSE},
293             {"",S_FALSE,FALSE},
294             {".mp3",S_OK,FALSE},
295             {"",S_FALSE,FALSE},
296             {"",S_FALSE,FALSE},
297             {"",S_FALSE,FALSE},
298             {"/c:/tests/foo%2520bar.mp3",S_OK,FALSE},
299             {"/c:/tests/foo%2520bar.mp3",S_OK,FALSE},
300             {"",S_FALSE,FALSE},
301             {"file://c:\\tests\\../tests/foo%20bar.mp3",S_OK,FALSE},
302             {"file",S_OK,FALSE},
303             {"",S_FALSE,FALSE},
304             {"",S_FALSE,FALSE}
305         },
306         {
307             {Uri_HOST_UNKNOWN,S_OK,FALSE},
308             {0,S_FALSE,FALSE},
309             {URL_SCHEME_FILE,S_OK,FALSE},
310             {URLZONE_INVALID,E_NOTIMPL,FALSE}
311         }
312     },
313     {   "file://c:\\tests\\../tests/foo%20bar.mp3", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
314         {
315             {"file:///c:/tests/../tests/foo%2520bar.mp3",S_OK,FALSE},
316             {"",S_FALSE,FALSE},
317             {"file:///c:/tests/../tests/foo%2520bar.mp3",S_OK,FALSE},
318             {"",S_FALSE,FALSE},
319             {".mp3",S_OK,FALSE},
320             {"",S_FALSE,FALSE},
321             {"",S_FALSE,FALSE},
322             {"",S_FALSE,FALSE},
323             {"/c:/tests/../tests/foo%2520bar.mp3",S_OK,FALSE},
324             {"/c:/tests/../tests/foo%2520bar.mp3",S_OK,FALSE},
325             {"",S_FALSE,FALSE},
326             {"file://c:\\tests\\../tests/foo%20bar.mp3",S_OK,FALSE},
327             {"file",S_OK,FALSE},
328             {"",S_FALSE,FALSE},
329             {"",S_FALSE,FALSE}
330         },
331         {
332             {Uri_HOST_UNKNOWN,S_OK,FALSE},
333             {0,S_FALSE,FALSE},
334             {URL_SCHEME_FILE,S_OK,FALSE},
335             {URLZONE_INVALID,E_NOTIMPL,FALSE}
336         }
337     },
338     {   "FILE://localhost/test dir\\../tests/test%20file.README.txt", 0, S_OK, FALSE,
339         {
340             {"file:///tests/test%20file.README.txt",S_OK,FALSE},
341             {"",S_FALSE,FALSE},
342             {"file:///tests/test%20file.README.txt",S_OK,FALSE},
343             {"",S_FALSE,FALSE},
344             {".txt",S_OK,FALSE},
345             {"",S_FALSE,FALSE},
346             {"",S_FALSE,FALSE},
347             {"",S_FALSE,FALSE},
348             {"/tests/test%20file.README.txt",S_OK,FALSE},
349             {"/tests/test%20file.README.txt",S_OK,FALSE},
350             {"",S_FALSE,FALSE},
351             {"FILE://localhost/test dir\\../tests/test%20file.README.txt",S_OK,FALSE},
352             {"file",S_OK,FALSE},
353             {"",S_FALSE,FALSE},
354             {"",S_FALSE,FALSE}
355         },
356         {
357             {Uri_HOST_UNKNOWN,S_OK,FALSE},
358             {0,S_FALSE,FALSE},
359             {URL_SCHEME_FILE,S_OK,FALSE},
360             {URLZONE_INVALID,E_NOTIMPL,FALSE}
361         }
362     },
363     {   "file:///z:/test dir/README.txt", 0, S_OK, FALSE,
364         {
365             {"file:///z:/test%20dir/README.txt",S_OK},
366             {"",S_FALSE},
367             {"file:///z:/test%20dir/README.txt",S_OK},
368             {"",S_FALSE},
369             {".txt",S_OK},
370             {"",S_FALSE},
371             {"",S_FALSE},
372             {"",S_FALSE},
373             {"/z:/test%20dir/README.txt",S_OK},
374             {"/z:/test%20dir/README.txt",S_OK},
375             {"",S_FALSE},
376             {"file:///z:/test dir/README.txt",S_OK},
377             {"file",S_OK},
378             {"",S_FALSE},
379             {"",S_FALSE}
380         },
381         {
382             {Uri_HOST_UNKNOWN,S_OK,FALSE},
383             {0,S_FALSE,FALSE},
384             {URL_SCHEME_FILE,S_OK,FALSE},
385             {URLZONE_INVALID,E_NOTIMPL,FALSE}
386         }
387     },
388     {   "urn:nothing:should:happen here", 0, S_OK, FALSE,
389         {
390             {"urn:nothing:should:happen here",S_OK,FALSE},
391             {"",S_FALSE,FALSE},
392             {"urn:nothing:should:happen here",S_OK,FALSE},
393             {"",S_FALSE,FALSE},
394             {"",S_FALSE,FALSE},
395             {"",S_FALSE,FALSE},
396             {"",S_FALSE,FALSE},
397             {"",S_FALSE,FALSE},
398             {"nothing:should:happen here",S_OK,FALSE},
399             {"nothing:should:happen here",S_OK,FALSE},
400             {"",S_FALSE,FALSE},
401             {"urn:nothing:should:happen here",S_OK,FALSE},
402             {"urn",S_OK,FALSE},
403             {"",S_FALSE,FALSE},
404             {"",S_FALSE,FALSE}
405         },
406         {
407             {Uri_HOST_UNKNOWN,S_OK,FALSE},
408             {0,S_FALSE,FALSE},
409             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
410             {URLZONE_INVALID,E_NOTIMPL,FALSE}
411         }
412     },
413     {   "http://127.0.0.1/tests/../test dir/./test.txt", 0, S_OK, FALSE,
414         {
415             {"http://127.0.0.1/test%20dir/test.txt",S_OK,FALSE},
416             {"127.0.0.1",S_OK,FALSE},
417             {"http://127.0.0.1/test%20dir/test.txt",S_OK,FALSE},
418             {"",S_FALSE,FALSE},
419             {".txt",S_OK,FALSE},
420             {"",S_FALSE,FALSE},
421             {"127.0.0.1",S_OK,FALSE},
422             {"",S_FALSE,FALSE},
423             {"/test%20dir/test.txt",S_OK,FALSE},
424             {"/test%20dir/test.txt",S_OK,FALSE},
425             {"",S_FALSE,FALSE},
426             {"http://127.0.0.1/tests/../test dir/./test.txt",S_OK,FALSE},
427             {"http",S_OK,FALSE},
428             {"",S_FALSE,FALSE},
429             {"",S_FALSE,FALSE}
430         },
431         {
432             {Uri_HOST_IPV4,S_OK,FALSE},
433             {80,S_OK,FALSE},
434             {URL_SCHEME_HTTP,S_OK,FALSE},
435             {URLZONE_INVALID,E_NOTIMPL,FALSE}
436         }
437     },
438     {   "http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]", 0, S_OK, FALSE,
439         {
440             {"http://[fedc:ba98:7654:3210:fedc:ba98:7654:3210]/",S_OK,FALSE},
441             {"[fedc:ba98:7654:3210:fedc:ba98:7654:3210]",S_OK,FALSE},
442             {"http://[fedc:ba98:7654:3210:fedc:ba98:7654:3210]/",S_OK,FALSE},
443             {"",S_FALSE,FALSE},
444             {"",S_FALSE,FALSE},
445             {"",S_FALSE,FALSE},
446             {"fedc:ba98:7654:3210:fedc:ba98:7654:3210",S_OK,FALSE},
447             {"",S_FALSE,FALSE},
448             {"/",S_OK,FALSE},
449             {"/",S_OK,FALSE},
450             {"",S_FALSE,FALSE},
451             {"http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]",S_OK,FALSE},
452             {"http",S_OK,FALSE},
453             {"",S_FALSE,FALSE},
454             {"",S_FALSE,FALSE}
455         },
456         {
457             {Uri_HOST_IPV6,S_OK,FALSE},
458             {80,S_OK,FALSE},
459             {URL_SCHEME_HTTP,S_OK,FALSE},
460             {URLZONE_INVALID,E_NOTIMPL,FALSE}
461         }
462     },
463     {   "ftp://[::13.1.68.3]", 0, S_OK, FALSE,
464         {
465             {"ftp://[::13.1.68.3]/",S_OK,FALSE},
466             {"[::13.1.68.3]",S_OK,FALSE},
467             {"ftp://[::13.1.68.3]/",S_OK,FALSE},
468             {"",S_FALSE,FALSE},
469             {"",S_FALSE,FALSE},
470             {"",S_FALSE,FALSE},
471             {"::13.1.68.3",S_OK,FALSE},
472             {"",S_FALSE,FALSE},
473             {"/",S_OK,FALSE},
474             {"/",S_OK,FALSE},
475             {"",S_FALSE,FALSE},
476             {"ftp://[::13.1.68.3]",S_OK,FALSE},
477             {"ftp",S_OK,FALSE},
478             {"",S_FALSE,FALSE},
479             {"",S_FALSE,FALSE}
480         },
481         {
482             {Uri_HOST_IPV6,S_OK,FALSE},
483             {21,S_OK,FALSE},
484             {URL_SCHEME_FTP,S_OK,FALSE},
485             {URLZONE_INVALID,E_NOTIMPL,FALSE}
486         }
487     },
488     {   "http://[FEDC:BA98:0:0:0:0:0:3210]", 0, S_OK, FALSE,
489         {
490             {"http://[fedc:ba98::3210]/",S_OK,FALSE},
491             {"[fedc:ba98::3210]",S_OK,FALSE},
492             {"http://[fedc:ba98::3210]/",S_OK,FALSE},
493             {"",S_FALSE,FALSE},
494             {"",S_FALSE,FALSE},
495             {"",S_FALSE,FALSE},
496             {"fedc:ba98::3210",S_OK,FALSE},
497             {"",S_FALSE,FALSE},
498             {"/",S_OK,FALSE},
499             {"/",S_OK,FALSE},
500             {"",S_FALSE,FALSE},
501             {"http://[FEDC:BA98:0:0:0:0:0:3210]",S_OK,FALSE},
502             {"http",S_OK,FALSE},
503             {"",S_FALSE,FALSE},
504             {"",S_FALSE,FALSE},
505         },
506         {
507             {Uri_HOST_IPV6,S_OK,FALSE},
508             {80,S_OK,FALSE},
509             {URL_SCHEME_HTTP,S_OK,FALSE},
510             {URLZONE_INVALID,E_NOTIMPL,FALSE}
511         }
512     },
513     {   "1234://www.winehq.org", 0, S_OK, FALSE,
514         {
515             {"1234://www.winehq.org/",S_OK,FALSE},
516             {"www.winehq.org",S_OK,FALSE},
517             {"1234://www.winehq.org/",S_OK,FALSE},
518             {"winehq.org",S_OK,FALSE},
519             {"",S_FALSE,FALSE},
520             {"",S_FALSE,FALSE},
521             {"www.winehq.org",S_OK,FALSE},
522             {"",S_FALSE,FALSE},
523             {"/",S_OK,FALSE},
524             {"/",S_OK,FALSE},
525             {"",S_FALSE,FALSE},
526             {"1234://www.winehq.org",S_OK,FALSE},
527             {"1234",S_OK,FALSE},
528             {"",S_FALSE,FALSE},
529             {"",S_FALSE,FALSE}
530         },
531         {
532             {Uri_HOST_DNS,S_OK,FALSE},
533             {0,S_FALSE,FALSE},
534             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
535             {URLZONE_INVALID,E_NOTIMPL,FALSE}
536         }
537     },
538     /* Test's to make sure the parser/canonicalizer handles implicit file schemes correctly. */
539     {   "C:/test/test.mp3", Uri_CREATE_ALLOW_IMPLICIT_FILE_SCHEME, S_OK, FALSE,
540         {
541             {"file:///C:/test/test.mp3",S_OK,FALSE},
542             {"",S_FALSE,FALSE},
543             {"file:///C:/test/test.mp3",S_OK,FALSE},
544             {"",S_FALSE,FALSE},
545             {".mp3",S_OK,FALSE},
546             {"",S_FALSE,FALSE},
547             {"",S_FALSE,FALSE},
548             {"",S_FALSE,FALSE},
549             {"/C:/test/test.mp3",S_OK,FALSE},
550             {"/C:/test/test.mp3",S_OK,FALSE},
551             {"",S_FALSE,FALSE},
552             {"C:/test/test.mp3",S_OK,FALSE},
553             {"file",S_OK,FALSE},
554             {"",S_FALSE,FALSE},
555             {"",S_FALSE,FALSE}
556         },
557         {
558             {Uri_HOST_UNKNOWN,S_OK,FALSE},
559             {0,S_FALSE,FALSE},
560             {URL_SCHEME_FILE,S_OK,FALSE},
561             {URLZONE_INVALID,E_NOTIMPL,FALSE}
562         }
563     },
564     /* Test's to make sure the parser/canonicalizer handles implicit file schemes correctly. */
565     {   "\\\\Server/test.mp3", Uri_CREATE_ALLOW_IMPLICIT_FILE_SCHEME, S_OK, FALSE,
566         {
567             {"file://server/test.mp3",S_OK,FALSE},
568             {"server",S_OK,FALSE},
569             {"file://server/test.mp3",S_OK,FALSE},
570             {"",S_FALSE,FALSE},
571             {".mp3",S_OK,FALSE},
572             {"",S_FALSE,FALSE},
573             {"server",S_OK,FALSE},
574             {"",S_FALSE,FALSE},
575             {"/test.mp3",S_OK,FALSE},
576             {"/test.mp3",S_OK,FALSE},
577             {"",S_FALSE,FALSE},
578             {"\\\\Server/test.mp3",S_OK,FALSE},
579             {"file",S_OK,FALSE},
580             {"",S_FALSE,FALSE},
581             {"",S_FALSE,FALSE}
582         },
583         {
584             {Uri_HOST_DNS,S_OK,FALSE},
585             {0,S_FALSE,FALSE},
586             {URL_SCHEME_FILE,S_OK,FALSE},
587             {URLZONE_INVALID,E_NOTIMPL,FALSE}
588         }
589     },
590     {   "www.winehq.org/test", Uri_CREATE_ALLOW_IMPLICIT_WILDCARD_SCHEME, S_OK, FALSE,
591         {
592             {"*:www.winehq.org/test",S_OK,FALSE},
593             {"www.winehq.org",S_OK,FALSE},
594             {"*:www.winehq.org/test",S_OK,FALSE},
595             {"winehq.org",S_OK,FALSE},
596             {"",S_FALSE,FALSE},
597             {"",S_FALSE,FALSE},
598             {"www.winehq.org",S_OK,FALSE},
599             {"",S_FALSE,FALSE},
600             {"/test",S_OK,FALSE},
601             {"/test",S_OK,FALSE},
602             {"",S_FALSE,FALSE},
603             {"www.winehq.org/test",S_OK,FALSE},
604             {"*",S_OK,FALSE},
605             {"",S_FALSE,FALSE},
606             {"",S_FALSE,FALSE}
607         },
608         {
609             {Uri_HOST_DNS,S_OK,FALSE},
610             {0,S_FALSE,FALSE},
611             {URL_SCHEME_WILDCARD,S_OK,FALSE},
612             {URLZONE_INVALID,E_NOTIMPL,FALSE}
613         }
614     },
615     /* Valid since the '*' is the only character in the scheme name. */
616     {   "*:www.winehq.org/test", 0, S_OK, FALSE,
617         {
618             {"*:www.winehq.org/test",S_OK,FALSE},
619             {"www.winehq.org",S_OK,FALSE},
620             {"*:www.winehq.org/test",S_OK,FALSE},
621             {"winehq.org",S_OK,FALSE},
622             {"",S_FALSE,FALSE},
623             {"",S_FALSE,FALSE},
624             {"www.winehq.org",S_OK,FALSE},
625             {"",S_FALSE,FALSE},
626             {"/test",S_OK,FALSE},
627             {"/test",S_OK,FALSE},
628             {"",S_FALSE,FALSE},
629             {"*:www.winehq.org/test",S_OK,FALSE},
630             {"*",S_OK,FALSE},
631             {"",S_FALSE,FALSE},
632             {"",S_FALSE,FALSE}
633         },
634         {
635             {Uri_HOST_DNS,S_OK,FALSE},
636             {0,S_FALSE,FALSE},
637             {URL_SCHEME_WILDCARD,S_OK,FALSE},
638             {URLZONE_INVALID,E_NOTIMPL,FALSE}
639         }
640     },
641     {   "/../some dir/test.ext", Uri_CREATE_ALLOW_RELATIVE, S_OK, FALSE,
642         {
643             {"/../some dir/test.ext",S_OK,FALSE},
644             {"",S_FALSE,FALSE},
645             {"/../some dir/test.ext",S_OK,FALSE},
646             {"",S_FALSE,FALSE},
647             {".ext",S_OK,FALSE},
648             {"",S_FALSE,FALSE},
649             {"",S_FALSE,FALSE},
650             {"",S_FALSE,FALSE},
651             {"/../some dir/test.ext",S_OK,FALSE},
652             {"/../some dir/test.ext",S_OK,FALSE},
653             {"",S_FALSE,FALSE},
654             {"/../some dir/test.ext",S_OK,FALSE},
655             {"",S_FALSE,FALSE},
656             {"",S_FALSE,FALSE},
657             {"",S_FALSE,FALSE}
658         },
659         {
660             {Uri_HOST_UNKNOWN,S_OK,FALSE},
661             {0,S_FALSE,FALSE},
662             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
663             {URLZONE_INVALID,E_NOTIMPL,FALSE}
664         }
665     },
666     {   "//implicit/wildcard/uri scheme", Uri_CREATE_ALLOW_RELATIVE|Uri_CREATE_ALLOW_IMPLICIT_WILDCARD_SCHEME, S_OK, FALSE,
667         {
668             {"*://implicit/wildcard/uri%20scheme",S_OK,FALSE},
669             {"",S_OK,FALSE},
670             {"*://implicit/wildcard/uri%20scheme",S_OK,FALSE},
671             {"",S_FALSE,FALSE},
672             {"",S_FALSE,FALSE},
673             {"",S_FALSE,FALSE},
674             {"",S_OK,FALSE},
675             {"",S_FALSE,FALSE},
676             {"//implicit/wildcard/uri%20scheme",S_OK,FALSE},
677             {"//implicit/wildcard/uri%20scheme",S_OK,FALSE},
678             {"",S_FALSE,FALSE},
679             {"//implicit/wildcard/uri scheme",S_OK,FALSE},
680             {"*",S_OK,FALSE},
681             {"",S_FALSE,FALSE},
682             {"",S_FALSE,FALSE},
683         },
684         {
685             {Uri_HOST_UNKNOWN,S_OK,FALSE},
686             {0,S_FALSE,FALSE},
687             {URL_SCHEME_WILDCARD,S_OK,FALSE},
688             {URLZONE_INVALID,E_NOTIMPL,FALSE}
689         }
690     },
691     /* URI is considered opaque since CREATE_NO_CRACK_UNKNOWN_SCHEMES is set and its an unknown scheme. */
692     {   "zip://google.com", Uri_CREATE_NO_CRACK_UNKNOWN_SCHEMES, S_OK, FALSE,
693         {
694             {"zip:/.//google.com",S_OK,FALSE},
695             {"",S_FALSE,FALSE},
696             {"zip:/.//google.com",S_OK,FALSE},
697             {"",S_FALSE,FALSE},
698             {".com",S_OK,FALSE},
699             {"",S_FALSE,FALSE},
700             {"",S_FALSE,FALSE},
701             {"",S_FALSE,FALSE},
702             {"/.//google.com",S_OK,FALSE},
703             {"/.//google.com",S_OK,FALSE},
704             {"",S_FALSE,FALSE},
705             {"zip://google.com",S_OK,FALSE},
706             {"zip",S_OK,FALSE},
707             {"",S_FALSE,FALSE},
708             {"",S_FALSE,FALSE}
709         },
710         {
711             {Uri_HOST_UNKNOWN,S_OK,FALSE},
712             {0,S_FALSE,FALSE},
713             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
714             {URLZONE_INVALID,E_NOTIMPL,FALSE}
715         }
716     },
717     /* Windows uses the first occurrence of ':' to delimit the userinfo. */
718     {   "ftp://user:pass:word@winehq.org/", 0, S_OK, FALSE,
719         {
720             {"ftp://user:pass:word@winehq.org/",S_OK,FALSE},
721             {"user:pass:word@winehq.org",S_OK,FALSE},
722             {"ftp://winehq.org/",S_OK,FALSE},
723             {"winehq.org",S_OK,FALSE},
724             {"",S_FALSE,FALSE},
725             {"",S_FALSE,FALSE},
726             {"winehq.org",S_OK,FALSE},
727             {"pass:word",S_OK,FALSE},
728             {"/",S_OK,FALSE},
729             {"/",S_OK,FALSE},
730             {"",S_FALSE,FALSE},
731             {"ftp://user:pass:word@winehq.org/",S_OK,FALSE},
732             {"ftp",S_OK,FALSE},
733             {"user:pass:word",S_OK,FALSE},
734             {"user",S_OK,FALSE}
735         },
736         {
737             {Uri_HOST_DNS,S_OK,FALSE},
738             {21,S_OK,FALSE},
739             {URL_SCHEME_FTP,S_OK,FALSE},
740             {URLZONE_INVALID,E_NOTIMPL,FALSE}
741         }
742     },
743     /* Make sure % encoded unreserved characters are decoded. */
744     {   "ftp://w%49%4Ee:PA%53%53@ftp.google.com/", 0, S_OK, FALSE,
745         {
746             {"ftp://wINe:PASS@ftp.google.com/",S_OK,FALSE},
747             {"wINe:PASS@ftp.google.com",S_OK,FALSE},
748             {"ftp://ftp.google.com/",S_OK,FALSE},
749             {"google.com",S_OK,FALSE},
750             {"",S_FALSE,FALSE},
751             {"",S_FALSE,FALSE},
752             {"ftp.google.com",S_OK,FALSE},
753             {"PASS",S_OK,FALSE},
754             {"/",S_OK,FALSE},
755             {"/",S_OK,FALSE},
756             {"",S_FALSE,FALSE},
757             {"ftp://w%49%4Ee:PA%53%53@ftp.google.com/",S_OK,FALSE},
758             {"ftp",S_OK,FALSE},
759             {"wINe:PASS",S_OK,FALSE},
760             {"wINe",S_OK,FALSE}
761         },
762         {
763             {Uri_HOST_DNS,S_OK,FALSE},
764             {21,S_OK,FALSE},
765             {URL_SCHEME_FTP,S_OK,FALSE},
766             {URLZONE_INVALID,E_NOTIMPL,FALSE}
767         }
768     },
769     /* Make sure % encoded characters which are NOT unreserved are NOT decoded. */
770     {   "ftp://w%5D%5Be:PA%7B%7D@ftp.google.com/", 0, S_OK, FALSE,
771         {
772             {"ftp://w%5D%5Be:PA%7B%7D@ftp.google.com/",S_OK,FALSE},
773             {"w%5D%5Be:PA%7B%7D@ftp.google.com",S_OK,FALSE},
774             {"ftp://ftp.google.com/",S_OK,FALSE},
775             {"google.com",S_OK,FALSE},
776             {"",S_FALSE,FALSE},
777             {"",S_FALSE,FALSE},
778             {"ftp.google.com",S_OK,FALSE},
779             {"PA%7B%7D",S_OK,FALSE},
780             {"/",S_OK,FALSE},
781             {"/",S_OK,FALSE},
782             {"",S_FALSE,FALSE},
783             {"ftp://w%5D%5Be:PA%7B%7D@ftp.google.com/",S_OK,FALSE},
784             {"ftp",S_OK,FALSE},
785             {"w%5D%5Be:PA%7B%7D",S_OK,FALSE},
786             {"w%5D%5Be",S_OK,FALSE}
787         },
788         {
789             {Uri_HOST_DNS,S_OK,FALSE},
790             {21,S_OK,FALSE},
791             {URL_SCHEME_FTP,S_OK,FALSE},
792             {URLZONE_INVALID,E_NOTIMPL,FALSE}
793         }
794     },
795     /* You're allowed to have an empty password portion in the userinfo section. */
796     {   "ftp://empty:@ftp.google.com/", 0, S_OK, FALSE,
797         {
798             {"ftp://empty:@ftp.google.com/",S_OK,FALSE},
799             {"empty:@ftp.google.com",S_OK,FALSE},
800             {"ftp://ftp.google.com/",S_OK,FALSE},
801             {"google.com",S_OK,FALSE},
802             {"",S_FALSE,FALSE},
803             {"",S_FALSE,FALSE},
804             {"ftp.google.com",S_OK,FALSE},
805             {"",S_OK,FALSE},
806             {"/",S_OK,FALSE},
807             {"/",S_OK,FALSE},
808             {"",S_FALSE,FALSE},
809             {"ftp://empty:@ftp.google.com/",S_OK,FALSE},
810             {"ftp",S_OK,FALSE},
811             {"empty:",S_OK,FALSE},
812             {"empty",S_OK,FALSE}
813         },
814         {
815             {Uri_HOST_DNS,S_OK,FALSE},
816             {21,S_OK,FALSE},
817             {URL_SCHEME_FTP,S_OK,FALSE},
818             {URLZONE_INVALID,E_NOTIMPL,FALSE}
819         }
820     },
821     /* Make sure forbidden characters in "userinfo" get encoded. */
822     {   "ftp://\" \"weird@ftp.google.com/", 0, S_OK, FALSE,
823         {
824             {"ftp://%22%20%22weird@ftp.google.com/",S_OK,FALSE},
825             {"%22%20%22weird@ftp.google.com",S_OK,FALSE},
826             {"ftp://ftp.google.com/",S_OK,FALSE},
827             {"google.com",S_OK,FALSE},
828             {"",S_FALSE,FALSE},
829             {"",S_FALSE,FALSE},
830             {"ftp.google.com",S_OK,FALSE},
831             {"",S_FALSE,FALSE},
832             {"/",S_OK,FALSE},
833             {"/",S_OK,FALSE},
834             {"",S_FALSE,FALSE},
835             {"ftp://\" \"weird@ftp.google.com/",S_OK,FALSE},
836             {"ftp",S_OK,FALSE},
837             {"%22%20%22weird",S_OK,FALSE},
838             {"%22%20%22weird",S_OK,FALSE}
839         },
840         {
841             {Uri_HOST_DNS,S_OK,FALSE},
842             {21,S_OK,FALSE},
843             {URL_SCHEME_FTP,S_OK,FALSE},
844             {URLZONE_INVALID,E_NOTIMPL,FALSE}
845         }
846     },
847     /* Make sure the forbidden characters don't get percent encoded. */
848     {   "ftp://\" \"weird@ftp.google.com/", Uri_CREATE_NO_ENCODE_FORBIDDEN_CHARACTERS, S_OK, FALSE,
849         {
850             {"ftp://\" \"weird@ftp.google.com/",S_OK,FALSE},
851             {"\" \"weird@ftp.google.com",S_OK,FALSE},
852             {"ftp://ftp.google.com/",S_OK,FALSE},
853             {"google.com",S_OK,FALSE},
854             {"",S_FALSE,FALSE},
855             {"",S_FALSE,FALSE},
856             {"ftp.google.com",S_OK,FALSE},
857             {"",S_FALSE,FALSE},
858             {"/",S_OK,FALSE},
859             {"/",S_OK,FALSE},
860             {"",S_FALSE,FALSE},
861             {"ftp://\" \"weird@ftp.google.com/",S_OK,FALSE},
862             {"ftp",S_OK,FALSE},
863             {"\" \"weird",S_OK,FALSE},
864             {"\" \"weird",S_OK,FALSE}
865         },
866         {
867             {Uri_HOST_DNS,S_OK,FALSE},
868             {21,S_OK,FALSE},
869             {URL_SCHEME_FTP,S_OK,FALSE},
870             {URLZONE_INVALID,E_NOTIMPL,FALSE}
871         }
872     },
873     /* Make sure already percent encoded characters don't get unencoded. */
874     {   "ftp://\"%20\"weird@ftp.google.com/\"%20\"weird", Uri_CREATE_NO_ENCODE_FORBIDDEN_CHARACTERS, S_OK, FALSE,
875         {
876             {"ftp://\"%20\"weird@ftp.google.com/\"%20\"weird",S_OK,FALSE},
877             {"\"%20\"weird@ftp.google.com",S_OK,FALSE},
878             {"ftp://ftp.google.com/\"%20\"weird",S_OK,FALSE},
879             {"google.com",S_OK,FALSE},
880             {"",S_FALSE,FALSE},
881             {"",S_FALSE,FALSE},
882             {"ftp.google.com",S_OK,FALSE},
883             {"",S_FALSE,FALSE},
884             {"/\"%20\"weird",S_OK,FALSE},
885             {"/\"%20\"weird",S_OK,FALSE},
886             {"",S_FALSE,FALSE},
887             {"ftp://\"%20\"weird@ftp.google.com/\"%20\"weird",S_OK,FALSE},
888             {"ftp",S_OK,FALSE},
889             {"\"%20\"weird",S_OK,FALSE},
890             {"\"%20\"weird",S_OK,FALSE}
891         },
892         {
893             {Uri_HOST_DNS,S_OK,FALSE},
894             {21,S_OK,FALSE},
895             {URL_SCHEME_FTP,S_OK,FALSE},
896             {URLZONE_INVALID,E_NOTIMPL,FALSE}
897         }
898     },
899     /* Allowed to have invalid % encoded because its an unknown scheme type. */
900     {   "zip://%xy:word@winehq.org/", 0, S_OK, FALSE,
901         {
902             {"zip://%xy:word@winehq.org/",S_OK,FALSE},
903             {"%xy:word@winehq.org",S_OK,FALSE},
904             {"zip://%xy:word@winehq.org/",S_OK,FALSE},
905             {"winehq.org",S_OK,FALSE},
906             {"",S_FALSE,FALSE},
907             {"",S_FALSE,FALSE},
908             {"winehq.org",S_OK,FALSE},
909             {"word",S_OK,FALSE},
910             {"/",S_OK,FALSE},
911             {"/",S_OK,FALSE},
912             {"",S_FALSE,FALSE},
913             {"zip://%xy:word@winehq.org/",S_OK,FALSE},
914             {"zip",S_OK,FALSE},
915             {"%xy:word",S_OK,FALSE},
916             {"%xy",S_OK,FALSE}
917         },
918         {
919             {Uri_HOST_DNS,S_OK,FALSE},
920             {0,S_FALSE,FALSE},
921             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
922             {URLZONE_INVALID,E_NOTIMPL,FALSE}
923         }
924     },
925     /* Unreserved, percent encoded characters aren't decoded in the userinfo because the scheme
926      * isn't known.
927      */
928     {   "zip://%2E:%52%53ord@winehq.org/", 0, S_OK, FALSE,
929         {
930             {"zip://%2E:%52%53ord@winehq.org/",S_OK,FALSE},
931             {"%2E:%52%53ord@winehq.org",S_OK,FALSE},
932             {"zip://%2E:%52%53ord@winehq.org/",S_OK,FALSE},
933             {"winehq.org",S_OK,FALSE},
934             {"",S_FALSE,FALSE},
935             {"",S_FALSE,FALSE},
936             {"winehq.org",S_OK,FALSE},
937             {"%52%53ord",S_OK,FALSE},
938             {"/",S_OK,FALSE},
939             {"/",S_OK,FALSE},
940             {"",S_FALSE,FALSE},
941             {"zip://%2E:%52%53ord@winehq.org/",S_OK,FALSE},
942             {"zip",S_OK,FALSE},
943             {"%2E:%52%53ord",S_OK,FALSE},
944             {"%2E",S_OK,FALSE}
945         },
946         {
947             {Uri_HOST_DNS,S_OK,FALSE},
948             {0,S_FALSE,FALSE},
949             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
950             {URLZONE_INVALID,E_NOTIMPL,FALSE}
951         }
952     },
953     {   "ftp://[](),'test':word@winehq.org/", 0, S_OK, FALSE,
954         {
955             {"ftp://[](),'test':word@winehq.org/",S_OK,FALSE},
956             {"[](),'test':word@winehq.org",S_OK,FALSE},
957             {"ftp://winehq.org/",S_OK,FALSE},
958             {"winehq.org",S_OK,FALSE},
959             {"",S_FALSE,FALSE},
960             {"",S_FALSE,FALSE},
961             {"winehq.org",S_OK,FALSE},
962             {"word",S_OK,FALSE},
963             {"/",S_OK,FALSE},
964             {"/",S_OK,FALSE},
965             {"",S_FALSE,FALSE},
966             {"ftp://[](),'test':word@winehq.org/",S_OK,FALSE},
967             {"ftp",S_OK,FALSE},
968             {"[](),'test':word",S_OK,FALSE},
969             {"[](),'test'",S_OK,FALSE}
970         },
971         {
972             {Uri_HOST_DNS,S_OK,FALSE},
973             {21,S_OK,FALSE},
974             {URL_SCHEME_FTP,S_OK,FALSE},
975             {URLZONE_INVALID,E_NOTIMPL,FALSE}
976         }
977     },
978     {   "ftp://test?:word@winehq.org/", 0, S_OK, FALSE,
979         {
980             {"ftp://test/?:word@winehq.org/",S_OK,FALSE},
981             {"test",S_OK,FALSE},
982             {"ftp://test/?:word@winehq.org/",S_OK,FALSE},
983             {"",S_FALSE,FALSE},
984             {"",S_FALSE,FALSE},
985             {"",S_FALSE,FALSE},
986             {"test",S_OK,FALSE},
987             {"",S_FALSE,FALSE},
988             {"/",S_OK,FALSE},
989             {"/?:word@winehq.org/",S_OK,FALSE},
990             {"?:word@winehq.org/",S_OK,FALSE},
991             {"ftp://test?:word@winehq.org/",S_OK,FALSE},
992             {"ftp",S_OK,FALSE},
993             {"",S_FALSE,FALSE},
994             {"",S_FALSE,FALSE}
995         },
996         {
997             {Uri_HOST_DNS,S_OK,FALSE},
998             {21,S_OK,FALSE},
999             {URL_SCHEME_FTP,S_OK,FALSE},
1000             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1001         }
1002     },
1003     {   "ftp://test#:word@winehq.org/", 0, S_OK, FALSE,
1004         {
1005             {"ftp://test/#:word@winehq.org/",S_OK,FALSE},
1006             {"test",S_OK,FALSE},
1007             {"ftp://test/#:word@winehq.org/",S_OK,FALSE},
1008             {"",S_FALSE,FALSE},
1009             {"",S_FALSE,FALSE},
1010             {"#:word@winehq.org/",S_OK,FALSE},
1011             {"test",S_OK,FALSE},
1012             {"",S_FALSE,FALSE},
1013             {"/",S_OK,FALSE},
1014             {"/",S_OK,FALSE},
1015             {"",S_FALSE,FALSE},
1016             {"ftp://test#:word@winehq.org/",S_OK,FALSE},
1017             {"ftp",S_OK,FALSE},
1018             {"",S_FALSE,FALSE},
1019             {"",S_FALSE,FALSE}
1020         },
1021         {
1022             {Uri_HOST_DNS,S_OK,FALSE},
1023             {21,S_OK,FALSE},
1024             {URL_SCHEME_FTP,S_OK,FALSE},
1025             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1026         }
1027     },
1028     /* Allowed to have a backslash in the userinfo since it's an unknown scheme. */
1029     {   "zip://test\\:word@winehq.org/", 0, S_OK, FALSE,
1030         {
1031             {"zip://test\\:word@winehq.org/",S_OK,FALSE},
1032             {"test\\:word@winehq.org",S_OK,FALSE},
1033             {"zip://test\\:word@winehq.org/",S_OK,FALSE},
1034             {"winehq.org",S_OK,FALSE},
1035             {"",S_FALSE,FALSE},
1036             {"",S_FALSE,FALSE},
1037             {"winehq.org",S_OK,FALSE},
1038             {"word",S_OK,FALSE},
1039             {"/",S_OK,FALSE},
1040             {"/",S_OK,FALSE},
1041             {"",S_FALSE,FALSE},
1042             {"zip://test\\:word@winehq.org/",S_OK,FALSE},
1043             {"zip",S_OK,FALSE},
1044             {"test\\:word",S_OK,FALSE},
1045             {"test\\",S_OK,FALSE}
1046         },
1047         {
1048             {Uri_HOST_DNS,S_OK,FALSE},
1049             {0,S_FALSE,FALSE},
1050             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1051             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1052         }
1053     },
1054     /* It normalizes IPv4 addresses correctly. */
1055     {   "http://127.000.000.100/", 0, S_OK, FALSE,
1056         {
1057             {"http://127.0.0.100/",S_OK,FALSE},
1058             {"127.0.0.100",S_OK,FALSE},
1059             {"http://127.0.0.100/",S_OK,FALSE},
1060             {"",S_FALSE,FALSE},
1061             {"",S_FALSE,FALSE},
1062             {"",S_FALSE,FALSE},
1063             {"127.0.0.100",S_OK,FALSE},
1064             {"",S_FALSE,FALSE},
1065             {"/",S_OK,FALSE},
1066             {"/",S_OK,FALSE},
1067             {"",S_FALSE,FALSE},
1068             {"http://127.000.000.100/",S_OK,FALSE},
1069             {"http",S_OK,FALSE},
1070             {"",S_FALSE,FALSE},
1071             {"",S_FALSE,FALSE}
1072         },
1073         {
1074             {Uri_HOST_IPV4,S_OK,FALSE},
1075             {80,S_OK,FALSE},
1076             {URL_SCHEME_HTTP,S_OK,FALSE},
1077             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1078         }
1079     },
1080     {   "http://127.0.0.1:8000", 0, S_OK, FALSE,
1081         {
1082             {"http://127.0.0.1:8000/",S_OK},
1083             {"127.0.0.1:8000",S_OK},
1084             {"http://127.0.0.1:8000/",S_OK},
1085             {"",S_FALSE},
1086             {"",S_FALSE},
1087             {"",S_FALSE},
1088             {"127.0.0.1",S_OK},
1089             {"",S_FALSE},
1090             {"/",S_OK},
1091             {"/",S_OK},
1092             {"",S_FALSE},
1093             {"http://127.0.0.1:8000",S_OK},
1094             {"http",S_OK},
1095             {"",S_FALSE},
1096             {"",S_FALSE}
1097         },
1098         {
1099             {Uri_HOST_IPV4,S_OK,FALSE},
1100             {8000,S_OK,FALSE},
1101             {URL_SCHEME_HTTP,S_OK,FALSE},
1102             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1103         }
1104     },
1105     /* Make sure it normalizes partial IPv4 addresses correctly. */
1106     {   "http://127.0/", 0, S_OK, FALSE,
1107         {
1108             {"http://127.0.0.0/",S_OK,FALSE},
1109             {"127.0.0.0",S_OK,FALSE},
1110             {"http://127.0.0.0/",S_OK,FALSE},
1111             {"",S_FALSE,FALSE},
1112             {"",S_FALSE,FALSE},
1113             {"",S_FALSE,FALSE},
1114             {"127.0.0.0",S_OK,FALSE},
1115             {"",S_FALSE,FALSE},
1116             {"/",S_OK,FALSE},
1117             {"/",S_OK,FALSE},
1118             {"",S_FALSE,FALSE},
1119             {"http://127.0/",S_OK,FALSE},
1120             {"http",S_OK,FALSE},
1121             {"",S_FALSE,FALSE},
1122             {"",S_FALSE,FALSE}
1123         },
1124         {
1125             {Uri_HOST_IPV4,S_OK,FALSE},
1126             {80,S_OK,FALSE},
1127             {URL_SCHEME_HTTP,S_OK,FALSE},
1128             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1129         }
1130     },
1131     /* Make sure it converts implicit IPv4's correctly. */
1132     {   "http://123456/", 0, S_OK, FALSE,
1133         {
1134             {"http://0.1.226.64/",S_OK,FALSE},
1135             {"0.1.226.64",S_OK,FALSE},
1136             {"http://0.1.226.64/",S_OK,FALSE},
1137             {"",S_FALSE,FALSE},
1138             {"",S_FALSE,FALSE},
1139             {"",S_FALSE,FALSE},
1140             {"0.1.226.64",S_OK,FALSE},
1141             {"",S_FALSE,FALSE},
1142             {"/",S_OK,FALSE},
1143             {"/",S_OK,FALSE},
1144             {"",S_FALSE,FALSE},
1145             {"http://123456/",S_OK,FALSE},
1146             {"http",S_OK,FALSE},
1147             {"",S_FALSE,FALSE},
1148             {"",S_FALSE,FALSE}
1149         },
1150         {
1151             {Uri_HOST_IPV4,S_OK,FALSE},
1152             {80,S_OK,FALSE},
1153             {URL_SCHEME_HTTP,S_OK,FALSE},
1154             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1155         }
1156     },
1157     /* UINT_MAX */
1158     {   "http://4294967295/", 0, S_OK, FALSE,
1159         {
1160             {"http://255.255.255.255/",S_OK,FALSE},
1161             {"255.255.255.255",S_OK,FALSE},
1162             {"http://255.255.255.255/",S_OK,FALSE},
1163             {"",S_FALSE,FALSE},
1164             {"",S_FALSE,FALSE},
1165             {"",S_FALSE,FALSE},
1166             {"255.255.255.255",S_OK,FALSE},
1167             {"",S_FALSE,FALSE},
1168             {"/",S_OK,FALSE},
1169             {"/",S_OK,FALSE},
1170             {"",S_FALSE,FALSE},
1171             {"http://4294967295/",S_OK,FALSE},
1172             {"http",S_OK,FALSE},
1173             {"",S_FALSE,FALSE},
1174             {"",S_FALSE,FALSE}
1175         },
1176         {
1177             {Uri_HOST_IPV4,S_OK,FALSE},
1178             {80,S_OK,FALSE},
1179             {URL_SCHEME_HTTP,S_OK,FALSE},
1180             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1181         }
1182     },
1183     /* UINT_MAX+1 */
1184     {   "http://4294967296/", 0, S_OK, FALSE,
1185         {
1186             {"http://4294967296/",S_OK,FALSE},
1187             {"4294967296",S_OK,FALSE},
1188             {"http://4294967296/",S_OK,FALSE},
1189             {"",S_FALSE,FALSE},
1190             {"",S_FALSE,FALSE},
1191             {"",S_FALSE,FALSE},
1192             {"4294967296",S_OK,FALSE},
1193             {"",S_FALSE,FALSE},
1194             {"/",S_OK,FALSE},
1195             {"/",S_OK,FALSE},
1196             {"",S_FALSE,FALSE},
1197             {"http://4294967296/",S_OK,FALSE},
1198             {"http",S_OK,FALSE},
1199             {"",S_FALSE,FALSE},
1200             {"",S_FALSE,FALSE}
1201         },
1202         {
1203             {Uri_HOST_DNS,S_OK,FALSE},
1204             {80,S_OK,FALSE},
1205             {URL_SCHEME_HTTP,S_OK,FALSE},
1206             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1207         }
1208     },
1209     /* Window's doesn't normalize IP address for unknown schemes. */
1210     {   "1234://4294967295/", 0, S_OK, FALSE,
1211         {
1212             {"1234://4294967295/",S_OK,FALSE},
1213             {"4294967295",S_OK,FALSE},
1214             {"1234://4294967295/",S_OK,FALSE},
1215             {"",S_FALSE,FALSE},
1216             {"",S_FALSE,FALSE},
1217             {"",S_FALSE,FALSE},
1218             {"4294967295",S_OK,FALSE},
1219             {"",S_FALSE,FALSE},
1220             {"/",S_OK,FALSE},
1221             {"/",S_OK,FALSE},
1222             {"",S_FALSE,FALSE},
1223             {"1234://4294967295/",S_OK,FALSE},
1224             {"1234",S_OK,FALSE},
1225             {"",S_FALSE,FALSE},
1226             {"",S_FALSE,FALSE}
1227         },
1228         {
1229             {Uri_HOST_IPV4,S_OK,FALSE},
1230             {0,S_FALSE,FALSE},
1231             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1232             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1233         }
1234     },
1235     /* Window's doesn't normalize IP address for unknown schemes. */
1236     {   "1234://127.001/", 0, S_OK, FALSE,
1237         {
1238             {"1234://127.001/",S_OK,FALSE},
1239             {"127.001",S_OK,FALSE},
1240             {"1234://127.001/",S_OK,FALSE},
1241             {"",S_FALSE,FALSE},
1242             {"",S_FALSE,FALSE},
1243             {"",S_FALSE,FALSE},
1244             {"127.001",S_OK,FALSE},
1245             {"",S_FALSE,FALSE},
1246             {"/",S_OK,FALSE},
1247             {"/",S_OK,FALSE},
1248             {"",S_FALSE,FALSE},
1249             {"1234://127.001/",S_OK,FALSE},
1250             {"1234",S_OK,FALSE},
1251             {"",S_FALSE,FALSE},
1252             {"",S_FALSE,FALSE}
1253         },
1254         {
1255             {Uri_HOST_IPV4,S_OK,FALSE},
1256             {0,S_FALSE,FALSE},
1257             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1258             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1259         }
1260     },
1261     {   "http://[FEDC:BA98::3210]", 0, S_OK, FALSE,
1262         {
1263             {"http://[fedc:ba98::3210]/",S_OK,FALSE},
1264             {"[fedc:ba98::3210]",S_OK,FALSE},
1265             {"http://[fedc:ba98::3210]/",S_OK,FALSE},
1266             {"",S_FALSE,FALSE},
1267             {"",S_FALSE,FALSE},
1268             {"",S_FALSE,FALSE},
1269             {"fedc:ba98::3210",S_OK,FALSE},
1270             {"",S_FALSE,FALSE},
1271             {"/",S_OK,FALSE},
1272             {"/",S_OK,FALSE},
1273             {"",S_FALSE,FALSE},
1274             {"http://[FEDC:BA98::3210]",S_OK,FALSE},
1275             {"http",S_OK,FALSE},
1276             {"",S_FALSE,FALSE},
1277             {"",S_FALSE,FALSE},
1278         },
1279         {
1280             {Uri_HOST_IPV6,S_OK,FALSE},
1281             {80,S_OK,FALSE},
1282             {URL_SCHEME_HTTP,S_OK,FALSE},
1283             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1284         }
1285     },
1286     {   "http://[::]", 0, S_OK, FALSE,
1287         {
1288             {"http://[::]/",S_OK,FALSE},
1289             {"[::]",S_OK,FALSE},
1290             {"http://[::]/",S_OK,FALSE},
1291             {"",S_FALSE,FALSE},
1292             {"",S_FALSE,FALSE},
1293             {"",S_FALSE,FALSE},
1294             {"::",S_OK,FALSE},
1295             {"",S_FALSE,FALSE},
1296             {"/",S_OK,FALSE},
1297             {"/",S_OK,FALSE},
1298             {"",S_FALSE,FALSE},
1299             {"http://[::]",S_OK,FALSE},
1300             {"http",S_OK,FALSE},
1301             {"",S_FALSE,FALSE},
1302             {"",S_FALSE,FALSE},
1303         },
1304         {
1305             {Uri_HOST_IPV6,S_OK,FALSE},
1306             {80,S_OK,FALSE},
1307             {URL_SCHEME_HTTP,S_OK,FALSE},
1308             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1309         }
1310     },
1311     {   "http://[FEDC:BA98::]", 0, S_OK, FALSE,
1312         {
1313             {"http://[fedc:ba98::]/",S_OK,FALSE},
1314             {"[fedc:ba98::]",S_OK,FALSE},
1315             {"http://[fedc:ba98::]/",S_OK,FALSE},
1316             {"",S_FALSE,FALSE},
1317             {"",S_FALSE,FALSE},
1318             {"",S_FALSE,FALSE},
1319             {"fedc:ba98::",S_OK,FALSE},
1320             {"",S_FALSE,FALSE},
1321             {"/",S_OK,FALSE},
1322             {"/",S_OK,FALSE},
1323             {"",S_FALSE,FALSE},
1324             {"http://[FEDC:BA98::]",S_OK,FALSE},
1325             {"http",S_OK,FALSE},
1326             {"",S_FALSE,FALSE},
1327             {"",S_FALSE,FALSE},
1328         },
1329         {
1330             {Uri_HOST_IPV6,S_OK,FALSE},
1331             {80,S_OK,FALSE},
1332             {URL_SCHEME_HTTP,S_OK,FALSE},
1333             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1334         }
1335     },
1336     /* Valid even with 2 byte elision because it doesn't appear the beginning or end. */
1337     {   "http://[1::3:4:5:6:7:8]", 0, S_OK, FALSE,
1338         {
1339             {"http://[1:0:3:4:5:6:7:8]/",S_OK,FALSE},
1340             {"[1:0:3:4:5:6:7:8]",S_OK,FALSE},
1341             {"http://[1:0:3:4:5:6:7:8]/",S_OK,FALSE},
1342             {"",S_FALSE,FALSE},
1343             {"",S_FALSE,FALSE},
1344             {"",S_FALSE,FALSE},
1345             {"1:0:3:4:5:6:7:8",S_OK,FALSE},
1346             {"",S_FALSE,FALSE},
1347             {"/",S_OK,FALSE},
1348             {"/",S_OK,FALSE},
1349             {"",S_FALSE,FALSE},
1350             {"http://[1::3:4:5:6:7:8]",S_OK,FALSE},
1351             {"http",S_OK,FALSE},
1352             {"",S_FALSE,FALSE},
1353             {"",S_FALSE,FALSE},
1354         },
1355         {
1356             {Uri_HOST_IPV6,S_OK,FALSE},
1357             {80,S_OK,FALSE},
1358             {URL_SCHEME_HTTP,S_OK,FALSE},
1359             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1360         }
1361     },
1362     {   "http://[v2.34]/", 0, S_OK, FALSE,
1363         {
1364             {"http://[v2.34]/",S_OK,FALSE},
1365             {"[v2.34]",S_OK,FALSE},
1366             {"http://[v2.34]/",S_OK,FALSE},
1367             {"",S_FALSE,FALSE},
1368             {"",S_FALSE,FALSE},
1369             {"",S_FALSE,FALSE},
1370             {"[v2.34]",S_OK,FALSE},
1371             {"",S_FALSE,FALSE},
1372             {"/",S_OK,FALSE},
1373             {"/",S_OK,FALSE},
1374             {"",S_FALSE,FALSE},
1375             {"http://[v2.34]/",S_OK,FALSE},
1376             {"http",S_OK,FALSE},
1377             {"",S_FALSE,FALSE},
1378             {"",S_FALSE,FALSE}
1379         },
1380         {
1381             {Uri_HOST_UNKNOWN,S_OK,FALSE},
1382             {80,S_OK,FALSE},
1383             {URL_SCHEME_HTTP,S_OK,FALSE},
1384             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1385         }
1386     },
1387     /* Windows ignores ':' if they appear after a '[' on a non-IPLiteral host. */
1388     {   "http://[xyz:12345.com/test", 0, S_OK, FALSE,
1389         {
1390             {"http://[xyz:12345.com/test",S_OK,FALSE},
1391             {"[xyz:12345.com",S_OK,FALSE},
1392             {"http://[xyz:12345.com/test",S_OK,FALSE},
1393             {"[xyz:12345.com",S_OK,FALSE},
1394             {"",S_FALSE,FALSE},
1395             {"",S_FALSE,FALSE},
1396             {"[xyz:12345.com",S_OK,FALSE},
1397             {"",S_FALSE,FALSE},
1398             {"/test",S_OK,FALSE},
1399             {"/test",S_OK,FALSE},
1400             {"",S_FALSE,FALSE},
1401             {"http://[xyz:12345.com/test",S_OK,FALSE},
1402             {"http",S_OK,FALSE},
1403             {"",S_FALSE,FALSE},
1404             {"",S_FALSE,FALSE}
1405         },
1406         {
1407             {Uri_HOST_DNS,S_OK,FALSE},
1408             {80,S_OK,FALSE},
1409             {URL_SCHEME_HTTP,S_OK,FALSE},
1410             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1411         }
1412     },
1413     /* Valid URI since the '[' and ']' don't appear at the beginning and end
1414      * of the host name (respectively).
1415      */
1416     {   "ftp://www.[works].com/", 0, S_OK, FALSE,
1417         {
1418             {"ftp://www.[works].com/",S_OK,FALSE},
1419             {"www.[works].com",S_OK,FALSE},
1420             {"ftp://www.[works].com/",S_OK,FALSE},
1421             {"[works].com",S_OK,FALSE},
1422             {"",S_FALSE,FALSE},
1423             {"",S_FALSE,FALSE},
1424             {"www.[works].com",S_OK,FALSE},
1425             {"",S_FALSE,FALSE},
1426             {"/",S_OK,FALSE},
1427             {"/",S_OK,FALSE},
1428             {"",S_FALSE,FALSE},
1429             {"ftp://www.[works].com/",S_OK,FALSE},
1430             {"ftp",S_OK,FALSE},
1431             {"",S_FALSE,FALSE},
1432             {"",S_FALSE,FALSE}
1433         },
1434         {
1435             {Uri_HOST_DNS,S_OK,FALSE},
1436             {21,S_OK,FALSE},
1437             {URL_SCHEME_FTP,S_OK,FALSE},
1438             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1439         }
1440     },
1441     /* Considers ':' a delimiter since it appears after the ']'. */
1442     {   "http://www.google.com]:12345/", 0, S_OK, FALSE,
1443         {
1444             {"http://www.google.com]:12345/",S_OK,FALSE},
1445             {"www.google.com]:12345",S_OK,FALSE},
1446             {"http://www.google.com]:12345/",S_OK,FALSE},
1447             {"google.com]",S_OK,FALSE},
1448             {"",S_FALSE,FALSE},
1449             {"",S_FALSE,FALSE},
1450             {"www.google.com]",S_OK,FALSE},
1451             {"",S_FALSE,FALSE},
1452             {"/",S_OK,FALSE},
1453             {"/",S_OK,FALSE},
1454             {"",S_FALSE,FALSE},
1455             {"http://www.google.com]:12345/",S_OK,FALSE},
1456             {"http",S_OK,FALSE},
1457             {"",S_FALSE,FALSE},
1458             {"",S_FALSE,FALSE}
1459         },
1460         {
1461             {Uri_HOST_DNS,S_OK,FALSE},
1462             {12345,S_OK,FALSE},
1463             {URL_SCHEME_HTTP,S_OK,FALSE},
1464             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1465         }
1466     },
1467     /* Unknown scheme types can have invalid % encoded data in the hostname. */
1468     {   "zip://w%XXw%GEw.google.com/", 0, S_OK, FALSE,
1469         {
1470             {"zip://w%XXw%GEw.google.com/",S_OK,FALSE},
1471             {"w%XXw%GEw.google.com",S_OK,FALSE},
1472             {"zip://w%XXw%GEw.google.com/",S_OK,FALSE},
1473             {"google.com",S_OK,FALSE},
1474             {"",S_FALSE,FALSE},
1475             {"",S_FALSE,FALSE},
1476             {"w%XXw%GEw.google.com",S_OK,FALSE},
1477             {"",S_FALSE,FALSE},
1478             {"/",S_OK,FALSE},
1479             {"/",S_OK,FALSE},
1480             {"",S_FALSE,FALSE},
1481             {"zip://w%XXw%GEw.google.com/",S_OK,FALSE},
1482             {"zip",S_OK,FALSE},
1483             {"",S_FALSE,FALSE},
1484             {"",S_FALSE,FALSE}
1485         },
1486         {
1487             {Uri_HOST_DNS,S_OK,FALSE},
1488             {0,S_FALSE,FALSE},
1489             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1490             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1491         }
1492     },
1493     /* Unknown scheme types hostname doesn't get lower cased. */
1494     {   "zip://GOOGLE.com/", 0, S_OK, FALSE,
1495         {
1496             {"zip://GOOGLE.com/",S_OK,FALSE},
1497             {"GOOGLE.com",S_OK,FALSE},
1498             {"zip://GOOGLE.com/",S_OK,FALSE},
1499             {"GOOGLE.com",S_OK,FALSE},
1500             {"",S_FALSE,FALSE},
1501             {"",S_FALSE,FALSE},
1502             {"GOOGLE.com",S_OK,FALSE},
1503             {"",S_FALSE,FALSE},
1504             {"/",S_OK,FALSE},
1505             {"/",S_OK,FALSE},
1506             {"",S_FALSE,FALSE},
1507             {"zip://GOOGLE.com/",S_OK,FALSE},
1508             {"zip",S_OK,FALSE},
1509             {"",S_FALSE,FALSE},
1510             {"",S_FALSE,FALSE}
1511         },
1512         {
1513             {Uri_HOST_DNS,S_OK,FALSE},
1514             {0,S_FALSE,FALSE},
1515             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1516             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1517         }
1518     },
1519     /* Hostname gets lower-cased for known scheme types. */
1520     {   "http://WWW.GOOGLE.com/", 0, S_OK, FALSE,
1521         {
1522             {"http://www.google.com/",S_OK,FALSE},
1523             {"www.google.com",S_OK,FALSE},
1524             {"http://www.google.com/",S_OK,FALSE},
1525             {"google.com",S_OK,FALSE},
1526             {"",S_FALSE,FALSE},
1527             {"",S_FALSE,FALSE},
1528             {"www.google.com",S_OK,FALSE},
1529             {"",S_FALSE,FALSE},
1530             {"/",S_OK,FALSE},
1531             {"/",S_OK,FALSE},
1532             {"",S_FALSE,FALSE},
1533             {"http://WWW.GOOGLE.com/",S_OK,FALSE},
1534             {"http",S_OK,FALSE},
1535             {"",S_FALSE,FALSE},
1536             {"",S_FALSE,FALSE}
1537         },
1538         {
1539             {Uri_HOST_DNS,S_OK,FALSE},
1540             {80,S_OK,FALSE},
1541             {URL_SCHEME_HTTP,S_OK,FALSE},
1542             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1543         }
1544     },
1545     /* Characters that get % encoded in the hostname also have their percent
1546      * encoded forms lower cased.
1547      */
1548     {   "http://www.%7Cgoogle|.com/", 0, S_OK, FALSE,
1549         {
1550             {"http://www.%7cgoogle%7c.com/",S_OK,FALSE},
1551             {"www.%7cgoogle%7c.com",S_OK,FALSE},
1552             {"http://www.%7cgoogle%7c.com/",S_OK,FALSE},
1553             {"%7cgoogle%7c.com",S_OK,FALSE},
1554             {"",S_FALSE,FALSE},
1555             {"",S_FALSE,FALSE},
1556             {"www.%7cgoogle%7c.com",S_OK,FALSE},
1557             {"",S_FALSE,FALSE},
1558             {"/",S_OK,FALSE},
1559             {"/",S_OK,FALSE},
1560             {"",S_FALSE,FALSE},
1561             {"http://www.%7Cgoogle|.com/",S_OK,FALSE},
1562             {"http",S_OK,FALSE},
1563             {"",S_FALSE,FALSE},
1564             {"",S_FALSE,FALSE}
1565         },
1566         {
1567             {Uri_HOST_DNS,S_OK,FALSE},
1568             {80,S_OK,FALSE},
1569             {URL_SCHEME_HTTP,S_OK,FALSE},
1570             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1571         }
1572     },
1573     /* IPv4 addresses attached to IPv6 can be included in elisions. */
1574     {   "http://[1:2:3:4:5:6:0.0.0.0]", 0, S_OK, FALSE,
1575         {
1576             {"http://[1:2:3:4:5:6::]/",S_OK,FALSE},
1577             {"[1:2:3:4:5:6::]",S_OK,FALSE},
1578             {"http://[1:2:3:4:5:6::]/",S_OK,FALSE},
1579             {"",S_FALSE,FALSE},
1580             {"",S_FALSE,FALSE},
1581             {"",S_FALSE,FALSE},
1582             {"1:2:3:4:5:6::",S_OK,FALSE},
1583             {"",S_FALSE,FALSE},
1584             {"/",S_OK,FALSE},
1585             {"/",S_OK,FALSE},
1586             {"",S_FALSE,FALSE},
1587             {"http://[1:2:3:4:5:6:0.0.0.0]",S_OK,FALSE},
1588             {"http",S_OK,FALSE},
1589             {"",S_FALSE,FALSE},
1590             {"",S_FALSE,FALSE},
1591         },
1592         {
1593             {Uri_HOST_IPV6,S_OK,FALSE},
1594             {80,S_OK,FALSE},
1595             {URL_SCHEME_HTTP,S_OK,FALSE},
1596             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1597         }
1598     },
1599     /* IPv4 addresses get normalized. */
1600     {   "http://[::001.002.003.000]", 0, S_OK, FALSE,
1601         {
1602             {"http://[::1.2.3.0]/",S_OK,FALSE},
1603             {"[::1.2.3.0]",S_OK,FALSE},
1604             {"http://[::1.2.3.0]/",S_OK,FALSE},
1605             {"",S_FALSE,FALSE},
1606             {"",S_FALSE,FALSE},
1607             {"",S_FALSE,FALSE},
1608             {"::1.2.3.0",S_OK,FALSE},
1609             {"",S_FALSE,FALSE},
1610             {"/",S_OK,FALSE},
1611             {"/",S_OK,FALSE},
1612             {"",S_FALSE,FALSE},
1613             {"http://[::001.002.003.000]",S_OK,FALSE},
1614             {"http",S_OK,FALSE},
1615             {"",S_FALSE,FALSE},
1616             {"",S_FALSE,FALSE},
1617         },
1618         {
1619             {Uri_HOST_IPV6,S_OK,FALSE},
1620             {80,S_OK,FALSE},
1621             {URL_SCHEME_HTTP,S_OK,FALSE},
1622             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1623         }
1624     },
1625     /* Windows doesn't do anything to IPv6's in unknown schemes. */
1626     {   "zip://[0001:0:000:0004:0005:0006:001.002.003.000]", 0, S_OK, FALSE,
1627         {
1628             {"zip://[0001:0:000:0004:0005:0006:001.002.003.000]/",S_OK,FALSE},
1629             {"[0001:0:000:0004:0005:0006:001.002.003.000]",S_OK,FALSE},
1630             {"zip://[0001:0:000:0004:0005:0006:001.002.003.000]/",S_OK,FALSE},
1631             {"",S_FALSE,FALSE},
1632             {"",S_FALSE,FALSE},
1633             {"",S_FALSE,FALSE},
1634             {"0001:0:000:0004:0005:0006:001.002.003.000",S_OK,FALSE},
1635             {"",S_FALSE,FALSE},
1636             {"/",S_OK,FALSE},
1637             {"/",S_OK,FALSE},
1638             {"",S_FALSE,FALSE},
1639             {"zip://[0001:0:000:0004:0005:0006:001.002.003.000]",S_OK,FALSE},
1640             {"zip",S_OK,FALSE},
1641             {"",S_FALSE,FALSE},
1642             {"",S_FALSE,FALSE},
1643         },
1644         {
1645             {Uri_HOST_IPV6,S_OK,FALSE},
1646             {0,S_FALSE,FALSE},
1647             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1648             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1649         }
1650     },
1651     /* IPv4 address is converted into 2 h16 components. */
1652     {   "http://[ffff::192.222.111.32]", 0, S_OK, FALSE,
1653         {
1654             {"http://[ffff::c0de:6f20]/",S_OK,FALSE},
1655             {"[ffff::c0de:6f20]",S_OK,FALSE},
1656             {"http://[ffff::c0de:6f20]/",S_OK,FALSE},
1657             {"",S_FALSE,FALSE},
1658             {"",S_FALSE,FALSE},
1659             {"",S_FALSE,FALSE},
1660             {"ffff::c0de:6f20",S_OK,FALSE},
1661             {"",S_FALSE,FALSE},
1662             {"/",S_OK,FALSE},
1663             {"/",S_OK,FALSE},
1664             {"",S_FALSE,FALSE},
1665             {"http://[ffff::192.222.111.32]",S_OK,FALSE},
1666             {"http",S_OK,FALSE},
1667             {"",S_FALSE,FALSE},
1668             {"",S_FALSE,FALSE},
1669         },
1670         {
1671             {Uri_HOST_IPV6,S_OK,FALSE},
1672             {80,S_OK,FALSE},
1673             {URL_SCHEME_HTTP,S_OK,FALSE},
1674             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1675         }
1676     },
1677     /* Max value for a port. */
1678     {   "http://google.com:65535", 0, S_OK, FALSE,
1679         {
1680             {"http://google.com:65535/",S_OK,FALSE},
1681             {"google.com:65535",S_OK,FALSE},
1682             {"http://google.com:65535/",S_OK,FALSE},
1683             {"google.com",S_OK,FALSE},
1684             {"",S_FALSE,FALSE},
1685             {"",S_FALSE,FALSE},
1686             {"google.com",S_OK,FALSE},
1687             {"",S_FALSE,FALSE},
1688             {"/",S_OK,FALSE},
1689             {"/",S_OK,FALSE},
1690             {"",S_FALSE,FALSE},
1691             {"http://google.com:65535",S_OK,FALSE},
1692             {"http",S_OK,FALSE},
1693             {"",S_FALSE,FALSE},
1694             {"",S_FALSE,FALSE}
1695         },
1696         {
1697             {Uri_HOST_DNS,S_OK,FALSE},
1698             {65535,S_OK,FALSE},
1699             {URL_SCHEME_HTTP,S_OK,FALSE},
1700             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1701         }
1702     },
1703     {   "zip://google.com:65536", 0, S_OK, FALSE,
1704         {
1705             {"zip://google.com:65536/",S_OK,FALSE},
1706             {"google.com:65536",S_OK,FALSE},
1707             {"zip://google.com:65536/",S_OK,FALSE},
1708             {"google.com:65536",S_OK,FALSE},
1709             {"",S_FALSE,FALSE},
1710             {"",S_FALSE,FALSE},
1711             {"google.com:65536",S_OK,FALSE},
1712             {"",S_FALSE,FALSE},
1713             {"/",S_OK,FALSE},
1714             {"/",S_OK,FALSE},
1715             {"",S_FALSE,FALSE},
1716             {"zip://google.com:65536",S_OK,FALSE},
1717             {"zip",S_OK,FALSE},
1718             {"",S_FALSE,FALSE},
1719             {"",S_FALSE,FALSE}
1720         },
1721         {
1722             {Uri_HOST_DNS,S_OK,FALSE},
1723             {0,S_FALSE,FALSE},
1724             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1725             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1726         }
1727     },
1728     {   "zip://google.com:65536:25", 0, S_OK, FALSE,
1729         {
1730             {"zip://google.com:65536:25/",S_OK,FALSE},
1731             {"google.com:65536:25",S_OK,FALSE},
1732             {"zip://google.com:65536:25/",S_OK,FALSE},
1733             {"google.com:65536:25",S_OK,FALSE},
1734             {"",S_FALSE,FALSE},
1735             {"",S_FALSE,FALSE},
1736             {"google.com:65536:25",S_OK,FALSE},
1737             {"",S_FALSE,FALSE},
1738             {"/",S_OK,FALSE},
1739             {"/",S_OK,FALSE},
1740             {"",S_FALSE,FALSE},
1741             {"zip://google.com:65536:25",S_OK,FALSE},
1742             {"zip",S_OK,FALSE},
1743             {"",S_FALSE,FALSE},
1744             {"",S_FALSE,FALSE}
1745         },
1746         {
1747             {Uri_HOST_DNS,S_OK,FALSE},
1748             {0,S_FALSE,FALSE},
1749             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1750             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1751         }
1752     },
1753     {   "zip://[::ffff]:abcd", 0, S_OK, FALSE,
1754         {
1755             {"zip://[::ffff]:abcd/",S_OK,FALSE},
1756             {"[::ffff]:abcd",S_OK,FALSE},
1757             {"zip://[::ffff]:abcd/",S_OK,FALSE},
1758             {"",S_FALSE,FALSE},
1759             {"",S_FALSE,FALSE},
1760             {"",S_FALSE,FALSE},
1761             {"[::ffff]:abcd",S_OK,FALSE},
1762             {"",S_FALSE,FALSE},
1763             {"/",S_OK,FALSE},
1764             {"/",S_OK,FALSE},
1765             {"",S_FALSE,FALSE},
1766             {"zip://[::ffff]:abcd",S_OK,FALSE},
1767             {"zip",S_OK,FALSE},
1768             {"",S_FALSE,FALSE},
1769             {"",S_FALSE,FALSE}
1770         },
1771         {
1772             {Uri_HOST_DNS,S_OK,FALSE},
1773             {0,S_FALSE,FALSE},
1774             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1775             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1776         }
1777     },
1778     {   "zip://127.0.0.1:abcd", 0, S_OK, FALSE,
1779         {
1780             {"zip://127.0.0.1:abcd/",S_OK,FALSE},
1781             {"127.0.0.1:abcd",S_OK,FALSE},
1782             {"zip://127.0.0.1:abcd/",S_OK,FALSE},
1783             {"0.1:abcd",S_OK,FALSE},
1784             {"",S_FALSE,FALSE},
1785             {"",S_FALSE,FALSE},
1786             {"127.0.0.1:abcd",S_OK,FALSE},
1787             {"",S_FALSE,FALSE},
1788             {"/",S_OK,FALSE},
1789             {"/",S_OK,FALSE},
1790             {"",S_FALSE,FALSE},
1791             {"zip://127.0.0.1:abcd",S_OK,FALSE},
1792             {"zip",S_OK,FALSE},
1793             {"",S_FALSE,FALSE},
1794             {"",S_FALSE,FALSE}
1795         },
1796         {
1797             {Uri_HOST_DNS,S_OK,FALSE},
1798             {0,S_FALSE,FALSE},
1799             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1800             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1801         }
1802     },
1803     /* Port is just copied over. */
1804     {   "http://google.com:00035", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
1805         {
1806             {"http://google.com:00035",S_OK,FALSE},
1807             {"google.com:00035",S_OK,FALSE},
1808             {"http://google.com:00035",S_OK,FALSE,"http://google.com:35"},
1809             {"google.com",S_OK,FALSE},
1810             {"",S_FALSE,FALSE},
1811             {"",S_FALSE,FALSE},
1812             {"google.com",S_OK,FALSE},
1813             {"",S_FALSE,FALSE},
1814             {"",S_FALSE,FALSE},
1815             {"",S_FALSE,FALSE},
1816             {"",S_FALSE,FALSE},
1817             {"http://google.com:00035",S_OK,FALSE},
1818             {"http",S_OK,FALSE},
1819             {"",S_FALSE,FALSE},
1820             {"",S_FALSE,FALSE}
1821         },
1822         {
1823             {Uri_HOST_DNS,S_OK,FALSE},
1824             {35,S_OK,FALSE},
1825             {URL_SCHEME_HTTP,S_OK,FALSE},
1826             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1827         }
1828     },
1829     /* Default port is copied over. */
1830     {   "http://google.com:80", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
1831         {
1832             {"http://google.com:80",S_OK,FALSE},
1833             {"google.com:80",S_OK,FALSE},
1834             {"http://google.com:80",S_OK,FALSE},
1835             {"google.com",S_OK,FALSE},
1836             {"",S_FALSE,FALSE},
1837             {"",S_FALSE,FALSE},
1838             {"google.com",S_OK,FALSE},
1839             {"",S_FALSE,FALSE},
1840             {"",S_FALSE,FALSE},
1841             {"",S_FALSE,FALSE},
1842             {"",S_FALSE,FALSE},
1843             {"http://google.com:80",S_OK,FALSE},
1844             {"http",S_OK,FALSE},
1845             {"",S_FALSE,FALSE},
1846             {"",S_FALSE,FALSE}
1847         },
1848         {
1849             {Uri_HOST_DNS,S_OK,FALSE},
1850             {80,S_OK,FALSE},
1851             {URL_SCHEME_HTTP,S_OK,FALSE},
1852             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1853         }
1854     },
1855     {   "http://google.com.uk", 0, S_OK, FALSE,
1856         {
1857             {"http://google.com.uk/",S_OK,FALSE},
1858             {"google.com.uk",S_OK,FALSE},
1859             {"http://google.com.uk/",S_OK,FALSE},
1860             {"google.com.uk",S_OK,FALSE},
1861             {"",S_FALSE,FALSE},
1862             {"",S_FALSE,FALSE},
1863             {"google.com.uk",S_OK,FALSE},
1864             {"",S_FALSE,FALSE},
1865             {"/",S_OK,FALSE},
1866             {"/",S_OK,FALSE},
1867             {"",S_FALSE,FALSE},
1868             {"http://google.com.uk",S_OK,FALSE},
1869             {"http",S_OK,FALSE},
1870             {"",S_FALSE,FALSE},
1871             {"",S_FALSE,FALSE}
1872         },
1873         {
1874             {Uri_HOST_DNS,S_OK,FALSE},
1875             {80,S_OK,FALSE},
1876             {URL_SCHEME_HTTP,S_OK,FALSE},
1877             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1878         }
1879     },
1880     {   "http://google.com.com", 0, S_OK, FALSE,
1881         {
1882             {"http://google.com.com/",S_OK,FALSE},
1883             {"google.com.com",S_OK,FALSE},
1884             {"http://google.com.com/",S_OK,FALSE},
1885             {"com.com",S_OK,FALSE},
1886             {"",S_FALSE,FALSE},
1887             {"",S_FALSE,FALSE},
1888             {"google.com.com",S_OK,FALSE},
1889             {"",S_FALSE,FALSE},
1890             {"/",S_OK,FALSE},
1891             {"/",S_OK,FALSE},
1892             {"",S_FALSE,FALSE},
1893             {"http://google.com.com",S_OK,FALSE},
1894             {"http",S_OK,FALSE},
1895             {"",S_FALSE,FALSE},
1896             {"",S_FALSE,FALSE}
1897         },
1898         {
1899             {Uri_HOST_DNS,S_OK,FALSE},
1900             {80,S_OK,FALSE},
1901             {URL_SCHEME_HTTP,S_OK,FALSE},
1902             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1903         }
1904     },
1905     {   "http://google.uk.1", 0, S_OK, FALSE,
1906         {
1907             {"http://google.uk.1/",S_OK,FALSE},
1908             {"google.uk.1",S_OK,FALSE},
1909             {"http://google.uk.1/",S_OK,FALSE},
1910             {"google.uk.1",S_OK,FALSE},
1911             {"",S_FALSE,FALSE},
1912             {"",S_FALSE,FALSE},
1913             {"google.uk.1",S_OK,FALSE},
1914             {"",S_FALSE,FALSE},
1915             {"/",S_OK,FALSE},
1916             {"/",S_OK,FALSE},
1917             {"",S_FALSE,FALSE},
1918             {"http://google.uk.1",S_OK,FALSE},
1919             {"http",S_OK,FALSE},
1920             {"",S_FALSE,FALSE},
1921             {"",S_FALSE,FALSE}
1922         },
1923         {
1924             {Uri_HOST_DNS,S_OK,FALSE},
1925             {80,S_OK,FALSE},
1926             {URL_SCHEME_HTTP,S_OK,FALSE},
1927             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1928         }
1929     },
1930     /* Since foo isn't a recognized 3 character TLD its considered the domain name. */
1931     {   "http://google.foo.uk", 0, S_OK, FALSE,
1932         {
1933             {"http://google.foo.uk/",S_OK,FALSE},
1934             {"google.foo.uk",S_OK,FALSE},
1935             {"http://google.foo.uk/",S_OK,FALSE},
1936             {"foo.uk",S_OK,FALSE},
1937             {"",S_FALSE,FALSE},
1938             {"",S_FALSE,FALSE},
1939             {"google.foo.uk",S_OK,FALSE},
1940             {"",S_FALSE,FALSE},
1941             {"/",S_OK,FALSE},
1942             {"/",S_OK,FALSE},
1943             {"",S_FALSE,FALSE},
1944             {"http://google.foo.uk",S_OK,FALSE},
1945             {"http",S_OK,FALSE},
1946             {"",S_FALSE,FALSE},
1947             {"",S_FALSE,FALSE}
1948         },
1949         {
1950             {Uri_HOST_DNS,S_OK,FALSE},
1951             {80,S_OK,FALSE},
1952             {URL_SCHEME_HTTP,S_OK,FALSE},
1953             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1954         }
1955     },
1956     {   "http://.com", 0, S_OK, FALSE,
1957         {
1958             {"http://.com/",S_OK,FALSE},
1959             {".com",S_OK,FALSE},
1960             {"http://.com/",S_OK,FALSE},
1961             {".com",S_OK,FALSE},
1962             {"",S_FALSE,FALSE},
1963             {"",S_FALSE,FALSE},
1964             {".com",S_OK,FALSE},
1965             {"",S_FALSE,FALSE},
1966             {"/",S_OK,FALSE},
1967             {"/",S_OK,FALSE},
1968             {"",S_FALSE,FALSE},
1969             {"http://.com",S_OK,FALSE},
1970             {"http",S_OK,FALSE},
1971             {"",S_FALSE,FALSE},
1972             {"",S_FALSE,FALSE}
1973         },
1974         {
1975             {Uri_HOST_DNS,S_OK,FALSE},
1976             {80,S_OK,FALSE},
1977             {URL_SCHEME_HTTP,S_OK,FALSE},
1978             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1979         }
1980     },
1981     {   "http://.uk", 0, S_OK, FALSE,
1982         {
1983             {"http://.uk/",S_OK,FALSE},
1984             {".uk",S_OK,FALSE},
1985             {"http://.uk/",S_OK,FALSE},
1986             {"",S_FALSE,FALSE},
1987             {"",S_FALSE,FALSE},
1988             {"",S_FALSE,FALSE},
1989             {".uk",S_OK,FALSE},
1990             {"",S_FALSE,FALSE},
1991             {"/",S_OK,FALSE},
1992             {"/",S_OK,FALSE},
1993             {"",S_FALSE,FALSE},
1994             {"http://.uk",S_OK,FALSE},
1995             {"http",S_OK,FALSE},
1996             {"",S_FALSE,FALSE},
1997             {"",S_FALSE,FALSE}
1998         },
1999         {
2000             {Uri_HOST_DNS,S_OK,FALSE},
2001             {80,S_OK,FALSE},
2002             {URL_SCHEME_HTTP,S_OK,FALSE},
2003             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2004         }
2005     },
2006     {   "http://www.co.google.com.[]", 0, S_OK, FALSE,
2007         {
2008             {"http://www.co.google.com.[]/",S_OK,FALSE},
2009             {"www.co.google.com.[]",S_OK,FALSE},
2010             {"http://www.co.google.com.[]/",S_OK,FALSE},
2011             {"google.com.[]",S_OK,FALSE},
2012             {"",S_FALSE,FALSE},
2013             {"",S_FALSE,FALSE},
2014             {"www.co.google.com.[]",S_OK,FALSE},
2015             {"",S_FALSE,FALSE},
2016             {"/",S_OK,FALSE},
2017             {"/",S_OK,FALSE},
2018             {"",S_FALSE,FALSE},
2019             {"http://www.co.google.com.[]",S_OK,FALSE},
2020             {"http",S_OK,FALSE},
2021             {"",S_FALSE,FALSE},
2022             {"",S_FALSE,FALSE}
2023         },
2024         {
2025             {Uri_HOST_DNS,S_OK,FALSE},
2026             {80,S_OK,FALSE},
2027             {URL_SCHEME_HTTP,S_OK,FALSE},
2028             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2029         }
2030     },
2031     {   "http://co.uk", 0, S_OK, FALSE,
2032         {
2033             {"http://co.uk/",S_OK,FALSE},
2034             {"co.uk",S_OK,FALSE},
2035             {"http://co.uk/",S_OK,FALSE},
2036             {"",S_FALSE,FALSE},
2037             {"",S_FALSE,FALSE},
2038             {"",S_FALSE,FALSE},
2039             {"co.uk",S_OK,FALSE},
2040             {"",S_FALSE,FALSE},
2041             {"/",S_OK,FALSE},
2042             {"/",S_OK,FALSE},
2043             {"",S_FALSE,FALSE},
2044             {"http://co.uk",S_OK,FALSE},
2045             {"http",S_OK,FALSE},
2046             {"",S_FALSE,FALSE},
2047             {"",S_FALSE,FALSE}
2048         },
2049         {
2050             {Uri_HOST_DNS,S_OK,FALSE},
2051             {80,S_OK,FALSE},
2052             {URL_SCHEME_HTTP,S_OK,FALSE},
2053             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2054         }
2055     },
2056     {   "http://www.co.google.us.test", 0, S_OK, FALSE,
2057         {
2058             {"http://www.co.google.us.test/",S_OK,FALSE},
2059             {"www.co.google.us.test",S_OK,FALSE},
2060             {"http://www.co.google.us.test/",S_OK,FALSE},
2061             {"us.test",S_OK,FALSE},
2062             {"",S_FALSE,FALSE},
2063             {"",S_FALSE,FALSE},
2064             {"www.co.google.us.test",S_OK,FALSE},
2065             {"",S_FALSE,FALSE},
2066             {"/",S_OK,FALSE},
2067             {"/",S_OK,FALSE},
2068             {"",S_FALSE,FALSE},
2069             {"http://www.co.google.us.test",S_OK,FALSE},
2070             {"http",S_OK,FALSE},
2071             {"",S_FALSE,FALSE},
2072             {"",S_FALSE,FALSE}
2073         },
2074         {
2075             {Uri_HOST_DNS,S_OK,FALSE},
2076             {80,S_OK,FALSE},
2077             {URL_SCHEME_HTTP,S_OK,FALSE},
2078             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2079         }
2080     },
2081     {   "http://gov.uk", 0, S_OK, FALSE,
2082         {
2083             {"http://gov.uk/",S_OK,FALSE},
2084             {"gov.uk",S_OK,FALSE},
2085             {"http://gov.uk/",S_OK,FALSE},
2086             {"",S_FALSE,FALSE},
2087             {"",S_FALSE,FALSE},
2088             {"",S_FALSE,FALSE},
2089             {"gov.uk",S_OK,FALSE},
2090             {"",S_FALSE,FALSE},
2091             {"/",S_OK,FALSE},
2092             {"/",S_OK,FALSE},
2093             {"",S_FALSE,FALSE},
2094             {"http://gov.uk",S_OK,FALSE},
2095             {"http",S_OK,FALSE},
2096             {"",S_FALSE,FALSE},
2097             {"",S_FALSE,FALSE}
2098         },
2099         {
2100             {Uri_HOST_DNS,S_OK,FALSE},
2101             {80,S_OK,FALSE},
2102             {URL_SCHEME_HTTP,S_OK,FALSE},
2103             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2104         }
2105     },
2106     {   "zip://www.google.com\\test", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
2107         {
2108             {"zip://www.google.com\\test",S_OK,FALSE},
2109             {"www.google.com\\test",S_OK,FALSE},
2110             {"zip://www.google.com\\test",S_OK,FALSE},
2111             {"google.com\\test",S_OK,FALSE},
2112             {"",S_FALSE,FALSE},
2113             {"",S_FALSE,FALSE},
2114             {"www.google.com\\test",S_OK,FALSE},
2115             {"",S_FALSE,FALSE},
2116             {"",S_FALSE,FALSE},
2117             {"",S_FALSE,FALSE},
2118             {"",S_FALSE,FALSE},
2119             {"zip://www.google.com\\test",S_OK,FALSE},
2120             {"zip",S_OK,FALSE},
2121             {"",S_FALSE,FALSE},
2122             {"",S_FALSE,FALSE}
2123         },
2124         {
2125             {Uri_HOST_DNS,S_OK,FALSE},
2126             {0,S_FALSE,FALSE},
2127             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2128             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2129         }
2130     },
2131     {   "urn:excepts:bad:%XY:encoded", 0, S_OK, FALSE,
2132         {
2133             {"urn:excepts:bad:%XY:encoded",S_OK,FALSE},
2134             {"",S_FALSE,FALSE},
2135             {"urn:excepts:bad:%XY:encoded",S_OK,FALSE},
2136             {"",S_FALSE,FALSE},
2137             {"",S_FALSE,FALSE},
2138             {"",S_FALSE,FALSE},
2139             {"",S_FALSE,FALSE},
2140             {"",S_FALSE,FALSE},
2141             {"excepts:bad:%XY:encoded",S_OK,FALSE},
2142             {"excepts:bad:%XY:encoded",S_OK,FALSE},
2143             {"",S_FALSE,FALSE},
2144             {"urn:excepts:bad:%XY:encoded",S_OK,FALSE},
2145             {"urn",S_OK,FALSE},
2146             {"",S_FALSE,FALSE},
2147             {"",S_FALSE,FALSE}
2148         },
2149         {
2150             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2151             {0,S_FALSE,FALSE},
2152             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2153             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2154         }
2155     },
2156     /* Since the original URI doesn't contain an extra '/' before the path no % encoded values
2157      * are decoded and all '%' are encoded.
2158      */
2159     {   "file://C:/te%3Es%2Et/tes%t.mp3", 0, S_OK, FALSE,
2160         {
2161             {"file:///C:/te%253Es%252Et/tes%25t.mp3",S_OK,FALSE},
2162             {"",S_FALSE,FALSE},
2163             {"file:///C:/te%253Es%252Et/tes%25t.mp3",S_OK,FALSE},
2164             {"",S_FALSE,FALSE},
2165             {".mp3",S_OK,FALSE},
2166             {"",S_FALSE,FALSE},
2167             {"",S_FALSE,FALSE},
2168             {"",S_FALSE,FALSE},
2169             {"/C:/te%253Es%252Et/tes%25t.mp3",S_OK,FALSE},
2170             {"/C:/te%253Es%252Et/tes%25t.mp3",S_OK,FALSE},
2171             {"",S_FALSE,FALSE},
2172             {"file://C:/te%3Es%2Et/tes%t.mp3",S_OK,FALSE},
2173             {"file",S_OK,FALSE},
2174             {"",S_FALSE,FALSE},
2175             {"",S_FALSE,FALSE}
2176         },
2177         {
2178             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2179             {0,S_FALSE,FALSE},
2180             {URL_SCHEME_FILE,S_OK,FALSE},
2181             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2182         }
2183     },
2184     /* Since there's a '/' in front of the drive letter, any percent encoded, non-forbidden character
2185      * is decoded and only %'s in front of invalid hex digits are encoded.
2186      */
2187     {   "file:///C:/te%3Es%2Et/t%23es%t.mp3", 0, S_OK, FALSE,
2188         {
2189             {"file:///C:/te%3Es.t/t#es%25t.mp3",S_OK,FALSE},
2190             {"",S_FALSE,FALSE},
2191             {"file:///C:/te%3Es.t/t#es%25t.mp3",S_OK,FALSE},
2192             {"",S_FALSE,FALSE},
2193             {".mp3",S_OK,FALSE},
2194             {"",S_FALSE,FALSE},
2195             {"",S_FALSE,FALSE},
2196             {"",S_FALSE,FALSE},
2197             {"/C:/te%3Es.t/t#es%25t.mp3",S_OK,FALSE},
2198             {"/C:/te%3Es.t/t#es%25t.mp3",S_OK,FALSE},
2199             {"",S_FALSE,FALSE},
2200             {"file:///C:/te%3Es%2Et/t%23es%t.mp3",S_OK,FALSE},
2201             {"file",S_OK,FALSE},
2202             {"",S_FALSE,FALSE},
2203             {"",S_FALSE,FALSE}
2204         },
2205         {
2206             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2207             {0,S_FALSE,FALSE},
2208             {URL_SCHEME_FILE,S_OK,FALSE},
2209             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2210         }
2211     },
2212     /* Only unreserved percent encoded characters are decoded for known schemes that aren't file. */
2213     {   "http://[::001.002.003.000]/%3F%23%2E%54/test", 0, S_OK, FALSE,
2214         {
2215             {"http://[::1.2.3.0]/%3F%23.T/test",S_OK,FALSE},
2216             {"[::1.2.3.0]",S_OK,FALSE},
2217             {"http://[::1.2.3.0]/%3F%23.T/test",S_OK,FALSE},
2218             {"",S_FALSE,FALSE},
2219             {"",S_FALSE,FALSE},
2220             {"",S_FALSE,FALSE},
2221             {"::1.2.3.0",S_OK,FALSE},
2222             {"",S_FALSE,FALSE},
2223             {"/%3F%23.T/test",S_OK,FALSE},
2224             {"/%3F%23.T/test",S_OK,FALSE},
2225             {"",S_FALSE,FALSE},
2226             {"http://[::001.002.003.000]/%3F%23%2E%54/test",S_OK,FALSE},
2227             {"http",S_OK,FALSE},
2228             {"",S_FALSE,FALSE},
2229             {"",S_FALSE,FALSE},
2230         },
2231         {
2232             {Uri_HOST_IPV6,S_OK,FALSE},
2233             {80,S_OK,FALSE},
2234             {URL_SCHEME_HTTP,S_OK,FALSE},
2235             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2236         }
2237     },
2238     /* Forbidden characters are always encoded for file URIs. */
2239     {   "file:///C:/\"test\"/test.mp3", Uri_CREATE_NO_ENCODE_FORBIDDEN_CHARACTERS, S_OK, FALSE,
2240         {
2241             {"file:///C:/%22test%22/test.mp3",S_OK,FALSE},
2242             {"",S_FALSE,FALSE},
2243             {"file:///C:/%22test%22/test.mp3",S_OK,FALSE},
2244             {"",S_FALSE,FALSE},
2245             {".mp3",S_OK,FALSE},
2246             {"",S_FALSE,FALSE},
2247             {"",S_FALSE,FALSE},
2248             {"",S_FALSE,FALSE},
2249             {"/C:/%22test%22/test.mp3",S_OK,FALSE},
2250             {"/C:/%22test%22/test.mp3",S_OK,FALSE},
2251             {"",S_FALSE,FALSE},
2252             {"file:///C:/\"test\"/test.mp3",S_OK,FALSE},
2253             {"file",S_OK,FALSE},
2254             {"",S_FALSE,FALSE},
2255             {"",S_FALSE,FALSE}
2256         },
2257         {
2258             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2259             {0,S_FALSE,FALSE},
2260             {URL_SCHEME_FILE,S_OK,FALSE},
2261             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2262         }
2263     },
2264     /* Forbidden characters are never encoded for unknown scheme types. */
2265     {   "1234://4294967295/<|>\" test<|>", 0, S_OK, FALSE,
2266         {
2267             {"1234://4294967295/<|>\" test<|>",S_OK,FALSE},
2268             {"4294967295",S_OK,FALSE},
2269             {"1234://4294967295/<|>\" test<|>",S_OK,FALSE},
2270             {"",S_FALSE,FALSE},
2271             {"",S_FALSE,FALSE},
2272             {"",S_FALSE,FALSE},
2273             {"4294967295",S_OK,FALSE},
2274             {"",S_FALSE,FALSE},
2275             {"/<|>\" test<|>",S_OK,FALSE},
2276             {"/<|>\" test<|>",S_OK,FALSE},
2277             {"",S_FALSE,FALSE},
2278             {"1234://4294967295/<|>\" test<|>",S_OK,FALSE},
2279             {"1234",S_OK,FALSE},
2280             {"",S_FALSE,FALSE},
2281             {"",S_FALSE,FALSE}
2282         },
2283         {
2284             {Uri_HOST_IPV4,S_OK,FALSE},
2285             {0,S_FALSE,FALSE},
2286             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2287             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2288         }
2289     },
2290     /* Make sure forbidden characters are percent encoded. */
2291     {   "http://gov.uk/<|> test<|>", 0, S_OK, FALSE,
2292         {
2293             {"http://gov.uk/%3C%7C%3E%20test%3C%7C%3E",S_OK,FALSE},
2294             {"gov.uk",S_OK,FALSE},
2295             {"http://gov.uk/%3C%7C%3E%20test%3C%7C%3E",S_OK,FALSE},
2296             {"",S_FALSE,FALSE},
2297             {"",S_FALSE,FALSE},
2298             {"",S_FALSE,FALSE},
2299             {"gov.uk",S_OK,FALSE},
2300             {"",S_FALSE,FALSE},
2301             {"/%3C%7C%3E%20test%3C%7C%3E",S_OK,FALSE},
2302             {"/%3C%7C%3E%20test%3C%7C%3E",S_OK,FALSE},
2303             {"",S_FALSE,FALSE},
2304             {"http://gov.uk/<|> test<|>",S_OK,FALSE},
2305             {"http",S_OK,FALSE},
2306             {"",S_FALSE,FALSE},
2307             {"",S_FALSE,FALSE}
2308         },
2309         {
2310             {Uri_HOST_DNS,S_OK,FALSE},
2311             {80,S_OK,FALSE},
2312             {URL_SCHEME_HTTP,S_OK,FALSE},
2313             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2314         }
2315     },
2316     {   "http://gov.uk/test/../test2/././../test3/.././././", 0, S_OK, FALSE,
2317         {
2318             {"http://gov.uk/",S_OK,FALSE},
2319             {"gov.uk",S_OK,FALSE},
2320             {"http://gov.uk/",S_OK,FALSE},
2321             {"",S_FALSE,FALSE},
2322             {"",S_FALSE,FALSE},
2323             {"",S_FALSE,FALSE},
2324             {"gov.uk",S_OK,FALSE},
2325             {"",S_FALSE,FALSE},
2326             {"/",S_OK,FALSE},
2327             {"/",S_OK,FALSE},
2328             {"",S_FALSE,FALSE},
2329             {"http://gov.uk/test/../test2/././../test3/.././././",S_OK,FALSE},
2330             {"http",S_OK,FALSE},
2331             {"",S_FALSE,FALSE},
2332             {"",S_FALSE,FALSE}
2333         },
2334         {
2335             {Uri_HOST_DNS,S_OK,FALSE},
2336             {80,S_OK,FALSE},
2337             {URL_SCHEME_HTTP,S_OK,FALSE},
2338             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2339         }
2340     },
2341     {   "http://gov.uk/test/test2/../../..", 0, S_OK, FALSE,
2342         {
2343             {"http://gov.uk/",S_OK,FALSE},
2344             {"gov.uk",S_OK,FALSE},
2345             {"http://gov.uk/",S_OK,FALSE},
2346             {"",S_FALSE,FALSE},
2347             {"",S_FALSE,FALSE},
2348             {"",S_FALSE,FALSE},
2349             {"gov.uk",S_OK,FALSE},
2350             {"",S_FALSE,FALSE},
2351             {"/",S_OK,FALSE},
2352             {"/",S_OK,FALSE},
2353             {"",S_FALSE,FALSE},
2354             {"http://gov.uk/test/test2/../../..",S_OK,FALSE},
2355             {"http",S_OK,FALSE},
2356             {"",S_FALSE,FALSE},
2357             {"",S_FALSE,FALSE}
2358         },
2359         {
2360             {Uri_HOST_DNS,S_OK,FALSE},
2361             {80,S_OK,FALSE},
2362             {URL_SCHEME_HTTP,S_OK,FALSE},
2363             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2364         }
2365     },
2366     {   "http://gov.uk/test/test2/../../.", 0, S_OK, FALSE,
2367         {
2368             {"http://gov.uk/",S_OK,FALSE},
2369             {"gov.uk",S_OK,FALSE},
2370             {"http://gov.uk/",S_OK,FALSE},
2371             {"",S_FALSE,FALSE},
2372             {"",S_FALSE,FALSE},
2373             {"",S_FALSE,FALSE},
2374             {"gov.uk",S_OK,FALSE},
2375             {"",S_FALSE,FALSE},
2376             {"/",S_OK,FALSE},
2377             {"/",S_OK,FALSE},
2378             {"",S_FALSE,FALSE},
2379             {"http://gov.uk/test/test2/../../.",S_OK,FALSE},
2380             {"http",S_OK,FALSE},
2381             {"",S_FALSE,FALSE},
2382             {"",S_FALSE,FALSE}
2383         },
2384         {
2385             {Uri_HOST_DNS,S_OK,FALSE},
2386             {80,S_OK,FALSE},
2387             {URL_SCHEME_HTTP,S_OK,FALSE},
2388             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2389         }
2390     },
2391     {   "file://c:\\tests\\../tests\\./.\\..\\foo%20bar.mp3", 0, S_OK, FALSE,
2392         {
2393             {"file:///c:/foo%2520bar.mp3",S_OK,FALSE},
2394             {"",S_FALSE,FALSE},
2395             {"file:///c:/foo%2520bar.mp3",S_OK,FALSE},
2396             {"",S_FALSE,FALSE},
2397             {".mp3",S_OK,FALSE},
2398             {"",S_FALSE,FALSE},
2399             {"",S_FALSE,FALSE},
2400             {"",S_FALSE,FALSE},
2401             {"/c:/foo%2520bar.mp3",S_OK,FALSE},
2402             {"/c:/foo%2520bar.mp3",S_OK,FALSE},
2403             {"",S_FALSE,FALSE},
2404             {"file://c:\\tests\\../tests\\./.\\..\\foo%20bar.mp3",S_OK,FALSE},
2405             {"file",S_OK,FALSE},
2406             {"",S_FALSE,FALSE},
2407             {"",S_FALSE,FALSE}
2408         },
2409         {
2410             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2411             {0,S_FALSE,FALSE},
2412             {URL_SCHEME_FILE,S_OK,FALSE},
2413             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2414         }
2415     },
2416     /* Dot removal happens for unknown scheme types. */
2417     {   "zip://gov.uk/test/test2/../../.", 0, S_OK, FALSE,
2418         {
2419             {"zip://gov.uk/",S_OK,FALSE},
2420             {"gov.uk",S_OK,FALSE},
2421             {"zip://gov.uk/",S_OK,FALSE},
2422             {"",S_FALSE,FALSE},
2423             {"",S_FALSE,FALSE},
2424             {"",S_FALSE,FALSE},
2425             {"gov.uk",S_OK,FALSE},
2426             {"",S_FALSE,FALSE},
2427             {"/",S_OK,FALSE},
2428             {"/",S_OK,FALSE},
2429             {"",S_FALSE,FALSE},
2430             {"zip://gov.uk/test/test2/../../.",S_OK,FALSE},
2431             {"zip",S_OK,FALSE},
2432             {"",S_FALSE,FALSE},
2433             {"",S_FALSE,FALSE}
2434         },
2435         {
2436             {Uri_HOST_DNS,S_OK,FALSE},
2437             {0,S_FALSE,FALSE},
2438             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2439             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2440         }
2441     },
2442     /* Dot removal doesn't happen if NO_CANONICALIZE is set. */
2443     {   "http://gov.uk/test/test2/../../.", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
2444         {
2445             {"http://gov.uk/test/test2/../../.",S_OK,FALSE},
2446             {"gov.uk",S_OK,FALSE},
2447             {"http://gov.uk/test/test2/../../.",S_OK,FALSE},
2448             {"",S_FALSE,FALSE},
2449             {".",S_OK,FALSE},
2450             {"",S_FALSE,FALSE},
2451             {"gov.uk",S_OK,FALSE},
2452             {"",S_FALSE,FALSE},
2453             {"/test/test2/../../.",S_OK,FALSE},
2454             {"/test/test2/../../.",S_OK,FALSE},
2455             {"",S_FALSE,FALSE},
2456             {"http://gov.uk/test/test2/../../.",S_OK,FALSE},
2457             {"http",S_OK,FALSE},
2458             {"",S_FALSE,FALSE},
2459             {"",S_FALSE,FALSE}
2460         },
2461         {
2462             {Uri_HOST_DNS,S_OK,FALSE},
2463             {80,S_OK,FALSE},
2464             {URL_SCHEME_HTTP,S_OK,FALSE},
2465             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2466         }
2467     },
2468     /* Dot removal doesn't happen for wildcard scheme types. */
2469     {   "*:gov.uk/test/test2/../../.", 0, S_OK, FALSE,
2470         {
2471             {"*:gov.uk/test/test2/../../.",S_OK,FALSE},
2472             {"gov.uk",S_OK,FALSE},
2473             {"*:gov.uk/test/test2/../../.",S_OK,FALSE},
2474             {"",S_FALSE,FALSE},
2475             {".",S_OK,FALSE},
2476             {"",S_FALSE,FALSE},
2477             {"gov.uk",S_OK,FALSE},
2478             {"",S_FALSE,FALSE},
2479             {"/test/test2/../../.",S_OK,FALSE},
2480             {"/test/test2/../../.",S_OK,FALSE},
2481             {"",S_FALSE,FALSE},
2482             {"*:gov.uk/test/test2/../../.",S_OK,FALSE},
2483             {"*",S_OK,FALSE},
2484             {"",S_FALSE,FALSE},
2485             {"",S_FALSE,FALSE}
2486         },
2487         {
2488             {Uri_HOST_DNS,S_OK,FALSE},
2489             {0,S_FALSE,FALSE},
2490             {URL_SCHEME_WILDCARD,S_OK,FALSE},
2491             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2492         }
2493     },
2494     /* Forbidden characters are encoded for opaque known scheme types. */
2495     {   "mailto:\"acco<|>unt@example.com\"", 0, S_OK, FALSE,
2496         {
2497             {"mailto:%22acco%3C%7C%3Eunt@example.com%22",S_OK,FALSE},
2498             {"",S_FALSE,FALSE},
2499             {"mailto:%22acco%3C%7C%3Eunt@example.com%22",S_OK,FALSE},
2500             {"",S_FALSE,FALSE},
2501             {".com%22",S_OK,FALSE},
2502             {"",S_FALSE,FALSE},
2503             {"",S_FALSE,FALSE},
2504             {"",S_FALSE,FALSE},
2505             {"%22acco%3C%7C%3Eunt@example.com%22",S_OK,FALSE},
2506             {"%22acco%3C%7C%3Eunt@example.com%22",S_OK,FALSE},
2507             {"",S_FALSE,FALSE},
2508             {"mailto:\"acco<|>unt@example.com\"",S_OK,FALSE},
2509             {"mailto",S_OK,FALSE},
2510             {"",S_FALSE,FALSE},
2511             {"",S_FALSE,FALSE}
2512         },
2513         {
2514             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2515             {0,S_FALSE,FALSE},
2516             {URL_SCHEME_MAILTO,S_OK,FALSE},
2517             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2518         }
2519     },
2520     {   "news:test.tes<|>t.com", 0, S_OK, FALSE,
2521         {
2522             {"news:test.tes%3C%7C%3Et.com",S_OK,FALSE},
2523             {"",S_FALSE,FALSE},
2524             {"news:test.tes%3C%7C%3Et.com",S_OK,FALSE},
2525             {"",S_FALSE,FALSE},
2526             {".com",S_OK,FALSE},
2527             {"",S_FALSE,FALSE},
2528             {"",S_FALSE,FALSE},
2529             {"",S_FALSE,FALSE},
2530             {"test.tes%3C%7C%3Et.com",S_OK,FALSE},
2531             {"test.tes%3C%7C%3Et.com",S_OK,FALSE},
2532             {"",S_FALSE,FALSE},
2533             {"news:test.tes<|>t.com",S_OK,FALSE},
2534             {"news",S_OK,FALSE},
2535             {"",S_FALSE,FALSE},
2536             {"",S_FALSE,FALSE}
2537         },
2538         {
2539             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2540             {0,S_FALSE,FALSE},
2541             {URL_SCHEME_NEWS,S_OK,FALSE},
2542             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2543         }
2544     },
2545     /* Don't encode forbidden characters. */
2546     {   "news:test.tes<|>t.com", Uri_CREATE_NO_ENCODE_FORBIDDEN_CHARACTERS, S_OK, FALSE,
2547         {
2548             {"news:test.tes<|>t.com",S_OK,FALSE},
2549             {"",S_FALSE,FALSE},
2550             {"news:test.tes<|>t.com",S_OK,FALSE},
2551             {"",S_FALSE,FALSE},
2552             {".com",S_OK,FALSE},
2553             {"",S_FALSE,FALSE},
2554             {"",S_FALSE,FALSE},
2555             {"",S_FALSE,FALSE},
2556             {"test.tes<|>t.com",S_OK,FALSE},
2557             {"test.tes<|>t.com",S_OK,FALSE},
2558             {"",S_FALSE,FALSE},
2559             {"news:test.tes<|>t.com",S_OK,FALSE},
2560             {"news",S_OK,FALSE},
2561             {"",S_FALSE,FALSE},
2562             {"",S_FALSE,FALSE}
2563         },
2564         {
2565             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2566             {0,S_FALSE,FALSE},
2567             {URL_SCHEME_NEWS,S_OK,FALSE},
2568             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2569         }
2570     },
2571     /* Forbidden characters aren't encoded for unknown, opaque URIs. */
2572     {   "urn:test.tes<|>t.com", 0, S_OK, FALSE,
2573         {
2574             {"urn:test.tes<|>t.com",S_OK,FALSE},
2575             {"",S_FALSE,FALSE},
2576             {"urn:test.tes<|>t.com",S_OK,FALSE},
2577             {"",S_FALSE,FALSE},
2578             {".com",S_OK,FALSE},
2579             {"",S_FALSE,FALSE},
2580             {"",S_FALSE,FALSE},
2581             {"",S_FALSE,FALSE},
2582             {"test.tes<|>t.com",S_OK,FALSE},
2583             {"test.tes<|>t.com",S_OK,FALSE},
2584             {"",S_FALSE,FALSE},
2585             {"urn:test.tes<|>t.com",S_OK,FALSE},
2586             {"urn",S_OK,FALSE},
2587             {"",S_FALSE,FALSE},
2588             {"",S_FALSE,FALSE}
2589         },
2590         {
2591             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2592             {0,S_FALSE,FALSE},
2593             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2594             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2595         }
2596     },
2597     /* Percent encoded unreserved characters are decoded for known opaque URIs. */
2598     {   "news:test.%74%65%73%74.com", 0, S_OK, FALSE,
2599         {
2600             {"news:test.test.com",S_OK,FALSE},
2601             {"",S_FALSE,FALSE},
2602             {"news:test.test.com",S_OK,FALSE},
2603             {"",S_FALSE,FALSE},
2604             {".com",S_OK,FALSE},
2605             {"",S_FALSE,FALSE},
2606             {"",S_FALSE,FALSE},
2607             {"",S_FALSE,FALSE},
2608             {"test.test.com",S_OK,FALSE},
2609             {"test.test.com",S_OK,FALSE},
2610             {"",S_FALSE,FALSE},
2611             {"news:test.%74%65%73%74.com",S_OK,FALSE},
2612             {"news",S_OK,FALSE},
2613             {"",S_FALSE,FALSE},
2614             {"",S_FALSE,FALSE}
2615         },
2616         {
2617             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2618             {0,S_FALSE,FALSE},
2619             {URL_SCHEME_NEWS,S_OK,FALSE},
2620             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2621         }
2622     },
2623     /* Percent encoded characters are still decoded for known scheme types. */
2624     {   "news:test.%74%65%73%74.com", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
2625         {
2626             {"news:test.test.com",S_OK,FALSE},
2627             {"",S_FALSE,FALSE},
2628             {"news:test.test.com",S_OK,FALSE},
2629             {"",S_FALSE,FALSE},
2630             {".com",S_OK,FALSE},
2631             {"",S_FALSE,FALSE},
2632             {"",S_FALSE,FALSE},
2633             {"",S_FALSE,FALSE},
2634             {"test.test.com",S_OK,FALSE},
2635             {"test.test.com",S_OK,FALSE},
2636             {"",S_FALSE,FALSE},
2637             {"news:test.%74%65%73%74.com",S_OK,FALSE},
2638             {"news",S_OK,FALSE},
2639             {"",S_FALSE,FALSE},
2640             {"",S_FALSE,FALSE}
2641         },
2642         {
2643             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2644             {0,S_FALSE,FALSE},
2645             {URL_SCHEME_NEWS,S_OK,FALSE},
2646             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2647         }
2648     },
2649     /* Percent encoded characters aren't decoded for unknown scheme types. */
2650     {   "urn:test.%74%65%73%74.com", 0, S_OK, FALSE,
2651         {
2652             {"urn:test.%74%65%73%74.com",S_OK,FALSE},
2653             {"",S_FALSE,FALSE},
2654             {"urn:test.%74%65%73%74.com",S_OK,FALSE},
2655             {"",S_FALSE,FALSE},
2656             {".com",S_OK,FALSE},
2657             {"",S_FALSE,FALSE},
2658             {"",S_FALSE,FALSE},
2659             {"",S_FALSE,FALSE},
2660             {"test.%74%65%73%74.com",S_OK,FALSE},
2661             {"test.%74%65%73%74.com",S_OK,FALSE},
2662             {"",S_FALSE,FALSE},
2663             {"urn:test.%74%65%73%74.com",S_OK,FALSE},
2664             {"urn",S_OK,FALSE},
2665             {"",S_FALSE,FALSE},
2666             {"",S_FALSE,FALSE}
2667         },
2668         {
2669             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2670             {0,S_FALSE,FALSE},
2671             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2672             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2673         }
2674     },
2675     /* Unknown scheme types can have invalid % encoded data in query string. */
2676     {   "zip://www.winehq.org/tests/..?query=%xx&return=y", 0, S_OK, FALSE,
2677         {
2678             {"zip://www.winehq.org/?query=%xx&return=y",S_OK,FALSE},
2679             {"www.winehq.org",S_OK,FALSE},
2680             {"zip://www.winehq.org/?query=%xx&return=y",S_OK,FALSE},
2681             {"winehq.org",S_OK,FALSE},
2682             {"",S_FALSE,FALSE},
2683             {"",S_FALSE,FALSE},
2684             {"www.winehq.org",S_OK,FALSE},
2685             {"",S_FALSE,FALSE},
2686             {"/",S_OK,FALSE},
2687             {"/?query=%xx&return=y",S_OK,FALSE},
2688             {"?query=%xx&return=y",S_OK,FALSE},
2689             {"zip://www.winehq.org/tests/..?query=%xx&return=y",S_OK,FALSE},
2690             {"zip",S_OK,FALSE},
2691             {"",S_FALSE,FALSE},
2692             {"",S_FALSE,FALSE}
2693         },
2694         {
2695             {Uri_HOST_DNS,S_OK,FALSE},
2696             {0,S_FALSE,FALSE},
2697             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2698             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2699         }
2700     },
2701     /* Known scheme types can have invalid % encoded data with the right flags. */
2702     {   "http://www.winehq.org/tests/..?query=%xx&return=y", Uri_CREATE_NO_DECODE_EXTRA_INFO, S_OK, FALSE,
2703         {
2704             {"http://www.winehq.org/?query=%xx&return=y",S_OK,FALSE},
2705             {"www.winehq.org",S_OK,FALSE},
2706             {"http://www.winehq.org/?query=%xx&return=y",S_OK,FALSE},
2707             {"winehq.org",S_OK,FALSE},
2708             {"",S_FALSE,FALSE},
2709             {"",S_FALSE,FALSE},
2710             {"www.winehq.org",S_OK,FALSE},
2711             {"",S_FALSE,FALSE},
2712             {"/",S_OK,FALSE},
2713             {"/?query=%xx&return=y",S_OK,FALSE},
2714             {"?query=%xx&return=y",S_OK,FALSE},
2715             {"http://www.winehq.org/tests/..?query=%xx&return=y",S_OK,FALSE},
2716             {"http",S_OK,FALSE},
2717             {"",S_FALSE,FALSE},
2718             {"",S_FALSE,FALSE}
2719         },
2720         {
2721             {Uri_HOST_DNS,S_OK,FALSE},
2722             {80,S_OK,FALSE},
2723             {URL_SCHEME_HTTP,S_OK,FALSE},
2724             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2725         }
2726     },
2727     /* Forbidden characters in query aren't percent encoded for known scheme types with this flag. */
2728     {   "http://www.winehq.org/tests/..?query=<|>&return=y", Uri_CREATE_NO_DECODE_EXTRA_INFO, S_OK, FALSE,
2729         {
2730             {"http://www.winehq.org/?query=<|>&return=y",S_OK,FALSE},
2731             {"www.winehq.org",S_OK,FALSE},
2732             {"http://www.winehq.org/?query=<|>&return=y",S_OK,FALSE},
2733             {"winehq.org",S_OK,FALSE},
2734             {"",S_FALSE,FALSE},
2735             {"",S_FALSE,FALSE},
2736             {"www.winehq.org",S_OK,FALSE},
2737             {"",S_FALSE,FALSE},
2738             {"/",S_OK,FALSE},
2739             {"/?query=<|>&return=y",S_OK,FALSE},
2740             {"?query=<|>&return=y",S_OK,FALSE},
2741             {"http://www.winehq.org/tests/..?query=<|>&return=y",S_OK,FALSE},
2742             {"http",S_OK,FALSE},
2743             {"",S_FALSE,FALSE},
2744             {"",S_FALSE,FALSE}
2745         },
2746         {
2747             {Uri_HOST_DNS,S_OK,FALSE},
2748             {80,S_OK,FALSE},
2749             {URL_SCHEME_HTTP,S_OK,FALSE},
2750             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2751         }
2752     },
2753     /* Forbidden characters in query aren't percent encoded for known scheme types with this flag. */
2754     {   "http://www.winehq.org/tests/..?query=<|>&return=y", Uri_CREATE_NO_ENCODE_FORBIDDEN_CHARACTERS, S_OK, FALSE,
2755         {
2756             {"http://www.winehq.org/?query=<|>&return=y",S_OK,FALSE},
2757             {"www.winehq.org",S_OK,FALSE},
2758             {"http://www.winehq.org/?query=<|>&return=y",S_OK,FALSE},
2759             {"winehq.org",S_OK,FALSE},
2760             {"",S_FALSE,FALSE},
2761             {"",S_FALSE,FALSE},
2762             {"www.winehq.org",S_OK,FALSE},
2763             {"",S_FALSE,FALSE},
2764             {"/",S_OK,FALSE},
2765             {"/?query=<|>&return=y",S_OK,FALSE},
2766             {"?query=<|>&return=y",S_OK,FALSE},
2767             {"http://www.winehq.org/tests/..?query=<|>&return=y",S_OK,FALSE},
2768             {"http",S_OK,FALSE},
2769             {"",S_FALSE,FALSE},
2770             {"",S_FALSE,FALSE}
2771         },
2772         {
2773             {Uri_HOST_DNS,S_OK,FALSE},
2774             {80,S_OK,FALSE},
2775             {URL_SCHEME_HTTP,S_OK,FALSE},
2776             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2777         }
2778     },
2779     /* Forbidden characters are encoded for known scheme types. */
2780     {   "http://www.winehq.org/tests/..?query=<|>&return=y", 0, S_OK, FALSE,
2781         {
2782             {"http://www.winehq.org/?query=%3C%7C%3E&return=y",S_OK,FALSE},
2783             {"www.winehq.org",S_OK,FALSE},
2784             {"http://www.winehq.org/?query=%3C%7C%3E&return=y",S_OK,FALSE},
2785             {"winehq.org",S_OK,FALSE},
2786             {"",S_FALSE,FALSE},
2787             {"",S_FALSE,FALSE},
2788             {"www.winehq.org",S_OK,FALSE},
2789             {"",S_FALSE,FALSE},
2790             {"/",S_OK,FALSE},
2791             {"/?query=%3C%7C%3E&return=y",S_OK,FALSE},
2792             {"?query=%3C%7C%3E&return=y",S_OK,FALSE},
2793             {"http://www.winehq.org/tests/..?query=<|>&return=y",S_OK,FALSE},
2794             {"http",S_OK,FALSE},
2795             {"",S_FALSE,FALSE},
2796             {"",S_FALSE,FALSE}
2797         },
2798         {
2799             {Uri_HOST_DNS,S_OK,FALSE},
2800             {80,S_OK,FALSE},
2801             {URL_SCHEME_HTTP,S_OK,FALSE},
2802             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2803         }
2804     },
2805     /* Forbidden characters are not encoded for unknown scheme types. */
2806     {   "zip://www.winehq.org/tests/..?query=<|>&return=y", 0, S_OK, FALSE,
2807         {
2808             {"zip://www.winehq.org/?query=<|>&return=y",S_OK,FALSE},
2809             {"www.winehq.org",S_OK,FALSE},
2810             {"zip://www.winehq.org/?query=<|>&return=y",S_OK,FALSE},
2811             {"winehq.org",S_OK,FALSE},
2812             {"",S_FALSE,FALSE},
2813             {"",S_FALSE,FALSE},
2814             {"www.winehq.org",S_OK,FALSE},
2815             {"",S_FALSE,FALSE},
2816             {"/",S_OK,FALSE},
2817             {"/?query=<|>&return=y",S_OK,FALSE},
2818             {"?query=<|>&return=y",S_OK,FALSE},
2819             {"zip://www.winehq.org/tests/..?query=<|>&return=y",S_OK,FALSE},
2820             {"zip",S_OK,FALSE},
2821             {"",S_FALSE,FALSE},
2822             {"",S_FALSE,FALSE}
2823         },
2824         {
2825             {Uri_HOST_DNS,S_OK,FALSE},
2826             {0,S_FALSE,FALSE},
2827             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2828             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2829         }
2830     },
2831     /* Percent encoded, unreserved characters are decoded for known scheme types. */
2832     {   "http://www.winehq.org/tests/..?query=%30%31&return=y", 0, S_OK, FALSE,
2833         {
2834             {"http://www.winehq.org/?query=01&return=y",S_OK,FALSE},
2835             {"www.winehq.org",S_OK,FALSE},
2836             {"http://www.winehq.org/?query=01&return=y",S_OK,FALSE},
2837             {"winehq.org",S_OK,FALSE},
2838             {"",S_FALSE,FALSE},
2839             {"",S_FALSE,FALSE},
2840             {"www.winehq.org",S_OK,FALSE},
2841             {"",S_FALSE,FALSE},
2842             {"/",S_OK,FALSE},
2843             {"/?query=01&return=y",S_OK,FALSE},
2844             {"?query=01&return=y",S_OK,FALSE},
2845             {"http://www.winehq.org/tests/..?query=%30%31&return=y",S_OK,FALSE},
2846             {"http",S_OK,FALSE},
2847             {"",S_FALSE,FALSE},
2848             {"",S_FALSE,FALSE}
2849         },
2850         {
2851             {Uri_HOST_DNS,S_OK,FALSE},
2852             {80,S_OK,FALSE},
2853             {URL_SCHEME_HTTP,S_OK,FALSE},
2854             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2855         }
2856     },
2857     /* Percent encoded, unreserved characters aren't decoded for unknown scheme types. */
2858     {   "zip://www.winehq.org/tests/..?query=%30%31&return=y", 0, S_OK, FALSE,
2859         {
2860             {"zip://www.winehq.org/?query=%30%31&return=y",S_OK,FALSE},
2861             {"www.winehq.org",S_OK,FALSE},
2862             {"zip://www.winehq.org/?query=%30%31&return=y",S_OK,FALSE},
2863             {"winehq.org",S_OK,FALSE},
2864             {"",S_FALSE,FALSE},
2865             {"",S_FALSE,FALSE},
2866             {"www.winehq.org",S_OK,FALSE},
2867             {"",S_FALSE,FALSE},
2868             {"/",S_OK,FALSE},
2869             {"/?query=%30%31&return=y",S_OK,FALSE},
2870             {"?query=%30%31&return=y",S_OK,FALSE},
2871             {"zip://www.winehq.org/tests/..?query=%30%31&return=y",S_OK,FALSE},
2872             {"zip",S_OK,FALSE},
2873             {"",S_FALSE,FALSE},
2874             {"",S_FALSE,FALSE}
2875         },
2876         {
2877             {Uri_HOST_DNS,S_OK,FALSE},
2878             {0,S_FALSE,FALSE},
2879             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2880             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2881         }
2882     },
2883     /* Percent encoded characters aren't decoded when NO_DECODE_EXTRA_INFO is set. */
2884     {   "http://www.winehq.org/tests/..?query=%30%31&return=y", Uri_CREATE_NO_DECODE_EXTRA_INFO, S_OK, FALSE,
2885         {
2886             {"http://www.winehq.org/?query=%30%31&return=y",S_OK,FALSE},
2887             {"www.winehq.org",S_OK,FALSE},
2888             {"http://www.winehq.org/?query=%30%31&return=y",S_OK,FALSE},
2889             {"winehq.org",S_OK,FALSE},
2890             {"",S_FALSE,FALSE},
2891             {"",S_FALSE,FALSE},
2892             {"www.winehq.org",S_OK,FALSE},
2893             {"",S_FALSE,FALSE},
2894             {"/",S_OK,FALSE},
2895             {"/?query=%30%31&return=y",S_OK,FALSE},
2896             {"?query=%30%31&return=y",S_OK,FALSE},
2897             {"http://www.winehq.org/tests/..?query=%30%31&return=y",S_OK,FALSE},
2898             {"http",S_OK,FALSE},
2899             {"",S_FALSE,FALSE},
2900             {"",S_FALSE,FALSE}
2901         },
2902         {
2903             {Uri_HOST_DNS,S_OK,FALSE},
2904             {80,S_OK,FALSE},
2905             {URL_SCHEME_HTTP,S_OK,FALSE},
2906             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2907         }
2908     },
2909     {   "http://www.winehq.org?query=12&return=y", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
2910         {
2911             {"http://www.winehq.org?query=12&return=y",S_OK,FALSE},
2912             {"www.winehq.org",S_OK,FALSE},
2913             {"http://www.winehq.org?query=12&return=y",S_OK,FALSE},
2914             {"winehq.org",S_OK,FALSE},
2915             {"",S_FALSE,FALSE},
2916             {"",S_FALSE,FALSE},
2917             {"www.winehq.org",S_OK,FALSE},
2918             {"",S_FALSE,FALSE},
2919             {"",S_FALSE,FALSE},
2920             {"?query=12&return=y",S_OK,FALSE},
2921             {"?query=12&return=y",S_OK,FALSE},
2922             {"http://www.winehq.org?query=12&return=y",S_OK,FALSE},
2923             {"http",S_OK,FALSE},
2924             {"",S_FALSE,FALSE},
2925             {"",S_FALSE,FALSE}
2926         },
2927         {
2928             {Uri_HOST_DNS,S_OK,FALSE},
2929             {80,S_OK,FALSE},
2930             {URL_SCHEME_HTTP,S_OK,FALSE},
2931             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2932         }
2933     },
2934     /* Unknown scheme types can have invalid % encoded data in fragments. */
2935     {   "zip://www.winehq.org/tests/#Te%xx", 0, S_OK, FALSE,
2936         {
2937             {"zip://www.winehq.org/tests/#Te%xx",S_OK,FALSE},
2938             {"www.winehq.org",S_OK,FALSE},
2939             {"zip://www.winehq.org/tests/#Te%xx",S_OK,FALSE},
2940             {"winehq.org",S_OK,FALSE},
2941             {"",S_FALSE,FALSE},
2942             {"#Te%xx",S_OK,FALSE},
2943             {"www.winehq.org",S_OK,FALSE},
2944             {"",S_FALSE,FALSE},
2945             {"/tests/",S_OK,FALSE},
2946             {"/tests/",S_OK,FALSE},
2947             {"",S_FALSE,FALSE},
2948             {"zip://www.winehq.org/tests/#Te%xx",S_OK,FALSE},
2949             {"zip",S_OK,FALSE},
2950             {"",S_FALSE,FALSE},
2951             {"",S_FALSE,FALSE}
2952         },
2953         {
2954             {Uri_HOST_DNS,S_OK,FALSE},
2955             {0,S_FALSE,FALSE},
2956             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2957             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2958         }
2959     },
2960     /* Forbidden characters in fragment aren't encoded for unknown schemes. */
2961     {   "zip://www.winehq.org/tests/#Te<|>", 0, S_OK, FALSE,
2962         {
2963             {"zip://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
2964             {"www.winehq.org",S_OK,FALSE},
2965             {"zip://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
2966             {"winehq.org",S_OK,FALSE},
2967             {"",S_FALSE,FALSE},
2968             {"#Te<|>",S_OK,FALSE},
2969             {"www.winehq.org",S_OK,FALSE},
2970             {"",S_FALSE,FALSE},
2971             {"/tests/",S_OK,FALSE},
2972             {"/tests/",S_OK,FALSE},
2973             {"",S_FALSE,FALSE},
2974             {"zip://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
2975             {"zip",S_OK,FALSE},
2976             {"",S_FALSE,FALSE},
2977             {"",S_FALSE,FALSE}
2978         },
2979         {
2980             {Uri_HOST_DNS,S_OK,FALSE},
2981             {0,S_FALSE,FALSE},
2982             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2983             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2984         }
2985     },
2986     /* Forbidden characters in the fragment are percent encoded for known schemes. */
2987     {   "http://www.winehq.org/tests/#Te<|>", 0, S_OK, FALSE,
2988         {
2989             {"http://www.winehq.org/tests/#Te%3C%7C%3E",S_OK,FALSE},
2990             {"www.winehq.org",S_OK,FALSE},
2991             {"http://www.winehq.org/tests/#Te%3C%7C%3E",S_OK,FALSE},
2992             {"winehq.org",S_OK,FALSE},
2993             {"",S_FALSE,FALSE},
2994             {"#Te%3C%7C%3E",S_OK,FALSE},
2995             {"www.winehq.org",S_OK,FALSE},
2996             {"",S_FALSE,FALSE},
2997             {"/tests/",S_OK,FALSE},
2998             {"/tests/",S_OK,FALSE},
2999             {"",S_FALSE,FALSE},
3000             {"http://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
3001             {"http",S_OK,FALSE},
3002             {"",S_FALSE,FALSE},
3003             {"",S_FALSE,FALSE}
3004         },
3005         {
3006             {Uri_HOST_DNS,S_OK,FALSE},
3007             {80,S_OK,FALSE},
3008             {URL_SCHEME_HTTP,S_OK,FALSE},
3009             {URLZONE_INVALID,E_NOTIMPL,FALSE},
3010         }
3011     },
3012     /* Forbidden characters aren't encoded in the fragment with this flag. */
3013     {   "http://www.winehq.org/tests/#Te<|>", Uri_CREATE_NO_DECODE_EXTRA_INFO, S_OK, FALSE,
3014         {
3015             {"http://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
3016             {"www.winehq.org",S_OK,FALSE},
3017             {"http://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
3018             {"winehq.org",S_OK,FALSE},
3019             {"",S_FALSE,FALSE},
3020             {"#Te<|>",S_OK,FALSE},
3021             {"www.winehq.org",S_OK,FALSE},
3022             {"",S_FALSE,FALSE},
3023             {"/tests/",S_OK,FALSE},
3024             {"/tests/",S_OK,FALSE},
3025             {"",S_FALSE,FALSE},
3026             {"http://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
3027             {"http",S_OK,FALSE},
3028             {"",S_FALSE,FALSE},
3029             {"",S_FALSE,FALSE}
3030         },
3031         {
3032             {Uri_HOST_DNS,S_OK,FALSE},
3033             {80,S_OK,FALSE},
3034             {URL_SCHEME_HTTP,S_OK,FALSE},
3035             {URLZONE_INVALID,E_NOTIMPL,FALSE},
3036         }
3037     },
3038     /* Forbidden characters aren't encoded in the fragment with this flag. */
3039     {   "http://www.winehq.org/tests/#Te<|>", Uri_CREATE_NO_ENCODE_FORBIDDEN_CHARACTERS, S_OK, FALSE,
3040         {
3041             {"http://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
3042             {"www.winehq.org",S_OK,FALSE},
3043             {"http://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
3044             {"winehq.org",S_OK,FALSE},
3045             {"",S_FALSE,FALSE},
3046             {"#Te<|>",S_OK,FALSE},
3047             {"www.winehq.org",S_OK,FALSE},
3048             {"",S_FALSE,FALSE},
3049             {"/tests/",S_OK,FALSE},
3050             {"/tests/",S_OK,FALSE},
3051             {"",S_FALSE,FALSE},
3052             {"http://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
3053             {"http",S_OK,FALSE},
3054             {"",S_FALSE,FALSE},
3055             {"",S_FALSE,FALSE}
3056         },
3057         {
3058             {Uri_HOST_DNS,S_OK,FALSE},
3059             {80,S_OK,FALSE},
3060             {URL_SCHEME_HTTP,S_OK,FALSE},
3061             {URLZONE_INVALID,E_NOTIMPL,FALSE},
3062         }
3063     },
3064     /* Percent encoded, unreserved characters aren't decoded for known scheme types. */
3065     {   "zip://www.winehq.org/tests/#Te%30%31%32", 0, S_OK, FALSE,
3066         {
3067             {"zip://www.winehq.org/tests/#Te%30%31%32",S_OK,FALSE},
3068             {"www.winehq.org",S_OK,FALSE},
3069             {"zip://www.winehq.org/tests/#Te%30%31%32",S_OK,FALSE},
3070             {"winehq.org",S_OK,FALSE},
3071             {"",S_FALSE,FALSE},
3072             {"#Te%30%31%32",S_OK,FALSE},
3073             {"www.winehq.org",S_OK,FALSE},
3074             {"",S_FALSE,FALSE},
3075             {"/tests/",S_OK,FALSE},
3076             {"/tests/",S_OK,FALSE},
3077             {"",S_FALSE,FALSE},
3078             {"zip://www.winehq.org/tests/#Te%30%31%32",S_OK,FALSE},
3079             {"zip",S_OK,FALSE},
3080             {"",S_FALSE,FALSE},
3081             {"",S_FALSE,FALSE}
3082         },
3083         {
3084             {Uri_HOST_DNS,S_OK,FALSE},
3085             {0,S_FALSE,FALSE},
3086             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
3087             {URLZONE_INVALID,E_NOTIMPL,FALSE},
3088         }
3089     },
3090     /* Percent encoded, unreserved characters are decoded for known schemes. */
3091     {   "http://www.winehq.org/tests/#Te%30%31%32", 0, S_OK, FALSE,
3092         {
3093             {"http://www.winehq.org/tests/#Te012",S_OK,FALSE},
3094             {"www.winehq.org",S_OK,FALSE},
3095             {"http://www.winehq.org/tests/#Te012",S_OK,FALSE},
3096             {"winehq.org",S_OK,FALSE},
3097             {"",S_FALSE,FALSE},
3098             {"#Te012",S_OK,FALSE},
3099             {"www.winehq.org",S_OK,FALSE},
3100             {"",S_FALSE,FALSE},
3101             {"/tests/",S_OK,FALSE},
3102             {"/tests/",S_OK,FALSE},
3103             {"",S_FALSE,FALSE},
3104             {"http://www.winehq.org/tests/#Te%30%31%32",S_OK,FALSE},
3105             {"http",S_OK,FALSE},
3106             {"",S_FALSE,FALSE},
3107             {"",S_FALSE,FALSE}
3108         },
3109         {
3110             {Uri_HOST_DNS,S_OK,FALSE},
3111             {80,S_OK,FALSE},
3112             {URL_SCHEME_HTTP,S_OK,FALSE},
3113             {URLZONE_INVALID,E_NOTIMPL,FALSE},
3114         }
3115     },
3116     /* Percent encoded, unreserved characters are decoded even if NO_CANONICALIZE is set. */
3117     {   "http://www.winehq.org/tests/#Te%30%31%32", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
3118         {
3119             {"http://www.winehq.org/tests/#Te012",S_OK,FALSE},
3120             {"www.winehq.org",S_OK,FALSE},
3121             {"http://www.winehq.org/tests/#Te012",S_OK,FALSE},
3122             {"winehq.org",S_OK,FALSE},
3123             {"",S_FALSE,FALSE},
3124             {"#Te012",S_OK,FALSE},
3125             {"www.winehq.org",S_OK,FALSE},
3126             {"",S_FALSE,FALSE},
3127             {"/tests/",S_OK,FALSE},
3128             {"/tests/",S_OK,FALSE},
3129             {"",S_FALSE,FALSE},
3130             {"http://www.winehq.org/tests/#Te%30%31%32",S_OK,FALSE},
3131             {"http",S_OK,FALSE},
3132             {"",S_FALSE,FALSE},
3133             {"",S_FALSE,FALSE}
3134         },
3135         {
3136             {Uri_HOST_DNS,S_OK,FALSE},
3137             {80,S_OK,FALSE},
3138             {URL_SCHEME_HTTP,S_OK,FALSE},
3139             {URLZONE_INVALID,E_NOTIMPL,FALSE},
3140         }
3141     },
3142     /* Percent encoded, unreserved characters aren't decoded when NO_DECODE_EXTRA is set. */
3143     {   "http://www.winehq.org/tests/#Te%30%31%32", Uri_CREATE_NO_DECODE_EXTRA_INFO, S_OK, FALSE,
3144         {
3145             {"http://www.winehq.org/tests/#Te%30%31%32",S_OK,FALSE},
3146             {"www.winehq.org",S_OK,FALSE},
3147             {"http://www.winehq.org/tests/#Te%30%31%32",S_OK,FALSE},
3148             {"winehq.org",S_OK,FALSE},
3149             {"",S_FALSE,FALSE},
3150             {"#Te%30%31%32",S_OK,FALSE},
3151             {"www.winehq.org",S_OK,FALSE},
3152             {"",S_FALSE,FALSE},
3153             {"/tests/",S_OK,FALSE},
3154             {"/tests/",S_OK,FALSE},
3155             {"",S_FALSE,FALSE},
3156             {"http://www.winehq.org/tests/#Te%30%31%32",S_OK,FALSE},
3157             {"http",S_OK,FALSE},
3158             {"",S_FALSE,FALSE},
3159             {"",S_FALSE,FALSE}
3160         },
3161         {
3162             {Uri_HOST_DNS,S_OK,FALSE},
3163             {80,S_OK,FALSE},
3164             {URL_SCHEME_HTTP,S_OK,FALSE},
3165             {URLZONE_INVALID,E_NOTIMPL,FALSE},
3166         }
3167     },
3168     /* Leading/Trailing whitespace is removed. */
3169     {   "    http://google.com/     ", 0, S_OK, FALSE,
3170         {
3171             {"http://google.com/",S_OK,FALSE},
3172             {"google.com",S_OK,FALSE},
3173             {"http://google.com/",S_OK,FALSE},
3174             {"google.com",S_OK,FALSE},
3175             {"",S_FALSE,FALSE},
3176             {"",S_FALSE,FALSE},
3177             {"google.com",S_OK,FALSE},
3178             {"",S_FALSE,FALSE},
3179             {"/",S_OK,FALSE},
3180             {"/",S_OK,FALSE},
3181             {"",S_FALSE,FALSE},
3182             {"http://google.com/",S_OK,FALSE},
3183             {"http",S_OK,FALSE},
3184             {"",S_FALSE,FALSE},
3185             {"",S_FALSE,FALSE}
3186         },
3187         {
3188             {Uri_HOST_DNS,S_OK,FALSE},
3189             {80,S_OK,FALSE},
3190             {URL_SCHEME_HTTP,S_OK,FALSE},
3191             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3192         }
3193     },
3194     {   "\t\t\r\nhttp\n://g\noogle.co\rm/\n\n\n", 0, S_OK, FALSE,
3195         {
3196             {"http://google.com/",S_OK,FALSE},
3197             {"google.com",S_OK,FALSE},
3198             {"http://google.com/",S_OK,FALSE},
3199             {"google.com",S_OK,FALSE},
3200             {"",S_FALSE,FALSE},
3201             {"",S_FALSE,FALSE},
3202             {"google.com",S_OK,FALSE},
3203             {"",S_FALSE,FALSE},
3204             {"/",S_OK,FALSE},
3205             {"/",S_OK,FALSE},
3206             {"",S_FALSE,FALSE},
3207             {"http://google.com/",S_OK,FALSE},
3208             {"http",S_OK,FALSE},
3209             {"",S_FALSE,FALSE},
3210             {"",S_FALSE,FALSE}
3211         },
3212         {
3213             {Uri_HOST_DNS,S_OK,FALSE},
3214             {80,S_OK,FALSE},
3215             {URL_SCHEME_HTTP,S_OK,FALSE},
3216             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3217         }
3218     },
3219     {   "http://g\noogle.co\rm/\n\n\n", Uri_CREATE_NO_PRE_PROCESS_HTML_URI, S_OK, FALSE,
3220         {
3221             {"http://g%0aoogle.co%0dm/%0A%0A%0A",S_OK,FALSE},
3222             {"g%0aoogle.co%0dm",S_OK,FALSE},
3223             {"http://g%0aoogle.co%0dm/%0A%0A%0A",S_OK,FALSE},
3224             {"g%0aoogle.co%0dm",S_OK,FALSE},
3225             {"",S_FALSE,FALSE},
3226             {"",S_FALSE,FALSE},
3227             {"g%0aoogle.co%0dm",S_OK,FALSE},
3228             {"",S_FALSE,FALSE},
3229             {"/%0A%0A%0A",S_OK,FALSE},
3230             {"/%0A%0A%0A",S_OK,FALSE},
3231             {"",S_FALSE,FALSE},
3232             {"http://g\noogle.co\rm/\n\n\n",S_OK,FALSE},
3233             {"http",S_OK,FALSE},
3234             {"",S_FALSE,FALSE},
3235             {"",S_FALSE,FALSE}
3236         },
3237         {
3238             {Uri_HOST_DNS,S_OK,FALSE},
3239             {80,S_OK,FALSE},
3240             {URL_SCHEME_HTTP,S_OK,FALSE},
3241             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3242         }
3243     },
3244     {   "zip://g\noogle.co\rm/\n\n\n", Uri_CREATE_NO_PRE_PROCESS_HTML_URI, S_OK, FALSE,
3245         {
3246             {"zip://g\noogle.co\rm/\n\n\n",S_OK,FALSE},
3247             {"g\noogle.co\rm",S_OK,FALSE},
3248             {"zip://g\noogle.co\rm/\n\n\n",S_OK,FALSE},
3249             {"g\noogle.co\rm",S_OK,FALSE},
3250             {"",S_FALSE,FALSE},
3251             {"",S_FALSE,FALSE},
3252             {"g\noogle.co\rm",S_OK,FALSE},
3253             {"",S_FALSE,FALSE},
3254             {"/\n\n\n",S_OK,FALSE},
3255             {"/\n\n\n",S_OK,FALSE},
3256             {"",S_FALSE,FALSE},
3257             {"zip://g\noogle.co\rm/\n\n\n",S_OK,FALSE},
3258             {"zip",S_OK,FALSE},
3259             {"",S_FALSE,FALSE},
3260             {"",S_FALSE,FALSE}
3261         },
3262         {
3263             {Uri_HOST_DNS,S_OK,FALSE},
3264             {0,S_FALSE,FALSE},
3265             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
3266             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3267         }
3268     },
3269     /* Since file URLs are usually hierarchical, it returns an empty string
3270      * for the absolute URI property since it was declared as an opaque URI.
3271      */
3272     {   "file:index.html", 0, S_OK, FALSE,
3273         {
3274             {"",S_FALSE,FALSE},
3275             {"",S_FALSE,FALSE},
3276             {"file:index.html",S_OK,FALSE},
3277             {"",S_FALSE,FALSE},
3278             {".html",S_OK,FALSE},
3279             {"",S_FALSE,FALSE},
3280             {"",S_FALSE,FALSE},
3281             {"",S_FALSE,FALSE},
3282             {"index.html",S_OK,FALSE},
3283             {"index.html",S_OK,FALSE},
3284             {"",S_FALSE,FALSE},
3285             {"file:index.html",S_OK,FALSE},
3286             {"file",S_OK,FALSE},
3287             {"",S_FALSE,FALSE},
3288             {"",S_FALSE,FALSE}
3289         },
3290         {
3291             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3292             {0,S_FALSE,FALSE},
3293             {URL_SCHEME_FILE,S_OK,FALSE},
3294             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3295         }
3296     },
3297     /* Doesn't have an absolute since it's opaque, but gets it port set. */
3298     {   "http:test.com/index.html", 0, S_OK, FALSE,
3299         {
3300             {"",S_FALSE,FALSE},
3301             {"",S_FALSE,FALSE},
3302             {"http:test.com/index.html",S_OK,FALSE},
3303             {"",S_FALSE,FALSE},
3304             {".html",S_OK,FALSE},
3305             {"",S_FALSE,FALSE},
3306             {"",S_FALSE,FALSE},
3307             {"",S_FALSE,FALSE},
3308             {"test.com/index.html",S_OK,FALSE},
3309             {"test.com/index.html",S_OK,FALSE},
3310             {"",S_FALSE,FALSE},
3311             {"http:test.com/index.html",S_OK,FALSE},
3312             {"http",S_OK,FALSE},
3313             {"",S_FALSE,FALSE},
3314             {"",S_FALSE,FALSE}
3315         },
3316         {
3317             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3318             {80,S_OK,FALSE},
3319             {URL_SCHEME_HTTP,S_OK,FALSE},
3320             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3321         }
3322     },
3323     {   "ftp:test.com/index.html", 0, S_OK, FALSE,
3324         {
3325             {"",S_FALSE,FALSE},
3326             {"",S_FALSE,FALSE},
3327             {"ftp:test.com/index.html",S_OK,FALSE},
3328             {"",S_FALSE,FALSE},
3329             {".html",S_OK,FALSE},
3330             {"",S_FALSE,FALSE},
3331             {"",S_FALSE,FALSE},
3332             {"",S_FALSE,FALSE},
3333             {"test.com/index.html",S_OK,FALSE},
3334             {"test.com/index.html",S_OK,FALSE},
3335             {"",S_FALSE,FALSE},
3336             {"ftp:test.com/index.html",S_OK,FALSE},
3337             {"ftp",S_OK,FALSE},
3338             {"",S_FALSE,FALSE},
3339             {"",S_FALSE,FALSE}
3340         },
3341         {
3342             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3343             {21,S_OK,FALSE},
3344             {URL_SCHEME_FTP,S_OK,FALSE},
3345             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3346         }
3347     },
3348     {   "file://C|/test.mp3", 0, S_OK, FALSE,
3349         {
3350             {"file:///C:/test.mp3",S_OK,FALSE},
3351             {"",S_FALSE,FALSE},
3352             {"file:///C:/test.mp3",S_OK,FALSE},
3353             {"",S_FALSE,FALSE},
3354             {".mp3",S_OK,FALSE},
3355             {"",S_FALSE,FALSE},
3356             {"",S_FALSE,FALSE},
3357             {"",S_FALSE,FALSE},
3358             {"/C:/test.mp3",S_OK,FALSE},
3359             {"/C:/test.mp3",S_OK,FALSE},
3360             {"",S_FALSE,FALSE},
3361             {"file://C|/test.mp3",S_OK,FALSE},
3362             {"file",S_OK,FALSE},
3363             {"",S_FALSE,FALSE},
3364             {"",S_FALSE,FALSE}
3365         },
3366         {
3367             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3368             {0,S_FALSE,FALSE},
3369             {URL_SCHEME_FILE,S_OK,FALSE},
3370             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3371         }
3372     },
3373     {   "file:///C|/test.mp3", 0, S_OK, FALSE,
3374         {
3375             {"file:///C:/test.mp3",S_OK,FALSE},
3376             {"",S_FALSE,FALSE},
3377             {"file:///C:/test.mp3",S_OK,FALSE},
3378             {"",S_FALSE,FALSE},
3379             {".mp3",S_OK,FALSE},
3380             {"",S_FALSE,FALSE},
3381             {"",S_FALSE,FALSE},
3382             {"",S_FALSE,FALSE},
3383             {"/C:/test.mp3",S_OK,FALSE},
3384             {"/C:/test.mp3",S_OK,FALSE},
3385             {"",S_FALSE,FALSE},
3386             {"file:///C|/test.mp3",S_OK,FALSE},
3387             {"file",S_OK,FALSE},
3388             {"",S_FALSE,FALSE},
3389             {"",S_FALSE,FALSE}
3390         },
3391         {
3392             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3393             {0,S_FALSE,FALSE},
3394             {URL_SCHEME_FILE,S_OK,FALSE},
3395             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3396         }
3397     },
3398     /* Extra '/' isn't added before "c:" since USE_DOS_PATH is set and '/' are converted
3399      * to '\\'.
3400      */
3401     {   "file://c:/dir/index.html", Uri_CREATE_FILE_USE_DOS_PATH, S_OK, FALSE,
3402         {
3403             {"file://c:\\dir\\index.html",S_OK,FALSE},
3404             {"",S_FALSE,FALSE},
3405             {"file://c:\\dir\\index.html",S_OK,FALSE},
3406             {"",S_FALSE,FALSE},
3407             {".html",S_OK,FALSE},
3408             {"",S_FALSE,FALSE},
3409             {"",S_FALSE,FALSE},
3410             {"",S_FALSE,FALSE},
3411             {"c:\\dir\\index.html",S_OK,FALSE},
3412             {"c:\\dir\\index.html",S_OK,FALSE},
3413             {"",S_FALSE,FALSE},
3414             {"file://c:/dir/index.html",S_OK,FALSE},
3415             {"file",S_OK,FALSE},
3416             {"",S_FALSE,FALSE},
3417             {"",S_FALSE,FALSE}
3418         },
3419         {
3420             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3421             {0,S_FALSE,FALSE},
3422             {URL_SCHEME_FILE,S_OK,FALSE},
3423             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3424         }
3425     },
3426     /* Extra '/' after "file://" is removed. */
3427     {   "file:///c:/dir/index.html", Uri_CREATE_FILE_USE_DOS_PATH, S_OK, FALSE,
3428         {
3429             {"file://c:\\dir\\index.html",S_OK,FALSE},
3430             {"",S_FALSE,FALSE},
3431             {"file://c:\\dir\\index.html",S_OK,FALSE},
3432             {"",S_FALSE,FALSE},
3433             {".html",S_OK,FALSE},
3434             {"",S_FALSE,FALSE},
3435             {"",S_FALSE,FALSE},
3436             {"",S_FALSE,FALSE},
3437             {"c:\\dir\\index.html",S_OK,FALSE},
3438             {"c:\\dir\\index.html",S_OK,FALSE},
3439             {"",S_FALSE,FALSE},
3440             {"file:///c:/dir/index.html",S_OK,FALSE},
3441             {"file",S_OK,FALSE},
3442             {"",S_FALSE,FALSE},
3443             {"",S_FALSE,FALSE}
3444         },
3445         {
3446             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3447             {0,S_FALSE,FALSE},
3448             {URL_SCHEME_FILE,S_OK,FALSE},
3449             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3450         }
3451     },
3452     /* Allow more characters when Uri_CREATE_FILE_USE_DOS_PATH is specified */
3453     {   "file:///c:/dir\\%%61%20%5Fname/file%2A.html", Uri_CREATE_FILE_USE_DOS_PATH, S_OK, FALSE,
3454         {
3455             {"file://c:\\dir\\%a _name\\file*.html",S_OK,FALSE},
3456             {"",S_FALSE,FALSE},
3457             {"file://c:\\dir\\%a _name\\file*.html",S_OK,FALSE},
3458             {"",S_FALSE,FALSE},
3459             {".html",S_OK,FALSE},
3460             {"",S_FALSE,FALSE},
3461             {"",S_FALSE,FALSE},
3462             {"",S_FALSE,FALSE},
3463             {"c:\\dir\\%a _name\\file*.html",S_OK,FALSE},
3464             {"c:\\dir\\%a _name\\file*.html",S_OK,FALSE},
3465             {"",S_FALSE,FALSE},
3466             {"file:///c:/dir\\%%61%20%5Fname/file%2A.html",S_OK,FALSE},
3467             {"file",S_OK,FALSE},
3468             {"",S_FALSE,FALSE},
3469             {"",S_FALSE,FALSE}
3470         },
3471         {
3472             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3473             {0,S_FALSE,FALSE},
3474             {URL_SCHEME_FILE,S_OK,FALSE},
3475             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3476         }
3477     },
3478     {   "file://c|/dir\\index.html", Uri_CREATE_FILE_USE_DOS_PATH, S_OK, FALSE,
3479         {
3480             {"file://c:\\dir\\index.html",S_OK,FALSE},
3481             {"",S_FALSE,FALSE},
3482             {"file://c:\\dir\\index.html",S_OK,FALSE},
3483             {"",S_FALSE,FALSE},
3484             {".html",S_OK,FALSE},
3485             {"",S_FALSE,FALSE},
3486             {"",S_FALSE,FALSE},
3487             {"",S_FALSE,FALSE},
3488             {"c:\\dir\\index.html",S_OK,FALSE},
3489             {"c:\\dir\\index.html",S_OK,FALSE},
3490             {"",S_FALSE,FALSE},
3491             {"file://c|/dir\\index.html",S_OK,FALSE},
3492             {"file",S_OK,FALSE},
3493             {"",S_FALSE,FALSE},
3494             {"",S_FALSE,FALSE}
3495         },
3496         {
3497             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3498             {0,S_FALSE,FALSE},
3499             {URL_SCHEME_FILE,S_OK,FALSE},
3500             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3501         }
3502     },
3503     /* The backslashes after the scheme name are converted to forward slashes. */
3504     {   "file:\\\\c:\\dir\\index.html", Uri_CREATE_FILE_USE_DOS_PATH, S_OK, FALSE,
3505         {
3506             {"file://c:\\dir\\index.html",S_OK,FALSE},
3507             {"",S_FALSE,FALSE},
3508             {"file://c:\\dir\\index.html",S_OK,FALSE},
3509             {"",S_FALSE,FALSE},
3510             {".html",S_OK,FALSE},
3511             {"",S_FALSE,FALSE},
3512             {"",S_FALSE,FALSE},
3513             {"",S_FALSE,FALSE},
3514             {"c:\\dir\\index.html",S_OK,FALSE},
3515             {"c:\\dir\\index.html",S_OK,FALSE},
3516             {"",S_FALSE,FALSE},
3517             {"file:\\\\c:\\dir\\index.html",S_OK,FALSE},
3518             {"file",S_OK,FALSE},
3519             {"",S_FALSE,FALSE},
3520             {"",S_FALSE,FALSE}
3521         },
3522         {
3523             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3524             {0,S_FALSE,FALSE},
3525             {URL_SCHEME_FILE,S_OK,FALSE},
3526             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3527         }
3528     },
3529     {   "file:\\\\c:/dir/index.html", 0, S_OK, FALSE,
3530         {
3531             {"file:///c:/dir/index.html",S_OK,FALSE},
3532             {"",S_FALSE,FALSE},
3533             {"file:///c:/dir/index.html",S_OK,FALSE},
3534             {"",S_FALSE,FALSE},
3535             {".html",S_OK,FALSE},
3536             {"",S_FALSE,FALSE},
3537             {"",S_FALSE,FALSE},
3538             {"",S_FALSE,FALSE},
3539             {"/c:/dir/index.html",S_OK,FALSE},
3540             {"/c:/dir/index.html",S_OK,FALSE},
3541             {"",S_FALSE,FALSE},
3542             {"file:\\\\c:/dir/index.html",S_OK,FALSE},
3543             {"file",S_OK,FALSE},
3544             {"",S_FALSE,FALSE},
3545             {"",S_FALSE,FALSE}
3546         },
3547         {
3548             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3549             {0,S_FALSE,FALSE},
3550             {URL_SCHEME_FILE,S_OK,FALSE},
3551             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3552         }
3553     },
3554     {   "http:\\\\google.com", 0, S_OK, FALSE,
3555         {
3556             {"http://google.com/",S_OK,FALSE},
3557             {"google.com",S_OK,FALSE},
3558             {"http://google.com/",S_OK,FALSE},
3559             {"google.com",S_OK,FALSE},
3560             {"",S_FALSE,FALSE},
3561             {"",S_FALSE,FALSE},
3562             {"google.com",S_OK,FALSE},
3563             {"",S_FALSE,FALSE},
3564             {"/",S_OK,FALSE},
3565             {"/",S_OK,FALSE},
3566             {"",S_FALSE,FALSE},
3567             {"http:\\\\google.com",S_OK,FALSE},
3568             {"http",S_OK,FALSE},
3569             {"",S_FALSE,FALSE},
3570             {"",S_FALSE,FALSE}
3571         },
3572         {
3573             {Uri_HOST_DNS,S_OK,FALSE},
3574             {80,S_OK,FALSE},
3575             {URL_SCHEME_HTTP,S_OK,FALSE},
3576             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3577         }
3578     },
3579     /* the "\\\\" aren't converted to "//" for unknown scheme types and it's considered opaque. */
3580     {   "zip:\\\\google.com", 0, S_OK, FALSE,
3581         {
3582             {"zip:\\\\google.com",S_OK,FALSE},
3583             {"",S_FALSE,FALSE},
3584             {"zip:\\\\google.com",S_OK,FALSE},
3585             {"",S_FALSE,FALSE},
3586             {".com",S_OK,FALSE},
3587             {"",S_FALSE,FALSE},
3588             {"",S_FALSE,FALSE},
3589             {"",S_FALSE,FALSE},
3590             {"\\\\google.com",S_OK,FALSE},
3591             {"\\\\google.com",S_OK,FALSE},
3592             {"",S_FALSE,FALSE},
3593             {"zip:\\\\google.com",S_OK,FALSE},
3594             {"zip",S_OK,FALSE},
3595             {"",S_FALSE,FALSE},
3596             {"",S_FALSE,FALSE}
3597         },
3598         {
3599             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3600             {0,S_FALSE,FALSE},
3601             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
3602             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3603         }
3604     },
3605     /* Dot segments aren't removed. */
3606     {   "file://c:\\dir\\../..\\./index.html", Uri_CREATE_FILE_USE_DOS_PATH, S_OK, FALSE,
3607         {
3608             {"file://c:\\dir\\..\\..\\.\\index.html",S_OK,FALSE},
3609             {"",S_FALSE,FALSE},
3610             {"file://c:\\dir\\..\\..\\.\\index.html",S_OK,FALSE},
3611             {"",S_FALSE,FALSE},
3612             {".html",S_OK,FALSE},
3613             {"",S_FALSE,FALSE},
3614             {"",S_FALSE,FALSE},
3615             {"",S_FALSE,FALSE},
3616             {"c:\\dir\\..\\..\\.\\index.html",S_OK,FALSE},
3617             {"c:\\dir\\..\\..\\.\\index.html",S_OK,FALSE},
3618             {"",S_FALSE,FALSE},
3619             {"file://c:\\dir\\../..\\./index.html",S_OK,FALSE},
3620             {"file",S_OK,FALSE},
3621             {"",S_FALSE,FALSE},
3622             {"",S_FALSE,FALSE}
3623         },
3624         {
3625             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3626             {0,S_FALSE,FALSE},
3627             {URL_SCHEME_FILE,S_OK,FALSE},
3628             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3629         }
3630     },
3631     /* Forbidden characters aren't percent encoded. */
3632     {   "file://c:\\dir\\i^|ndex.html", Uri_CREATE_FILE_USE_DOS_PATH, S_OK, FALSE,
3633         {
3634             {"file://c:\\dir\\i^|ndex.html",S_OK,FALSE},
3635             {"",S_FALSE,FALSE},
3636             {"file://c:\\dir\\i^|ndex.html",S_OK,FALSE},
3637             {"",S_FALSE,FALSE},
3638             {".html",S_OK,FALSE},
3639             {"",S_FALSE,FALSE},
3640             {"",S_FALSE,FALSE},
3641             {"",S_FALSE,FALSE},
3642             {"c:\\dir\\i^|ndex.html",S_OK,FALSE},
3643             {"c:\\dir\\i^|ndex.html",S_OK,FALSE},
3644             {"",S_FALSE,FALSE},
3645             {"file://c:\\dir\\i^|ndex.html",S_OK,FALSE},
3646             {"file",S_OK,FALSE},
3647             {"",S_FALSE,FALSE},
3648             {"",S_FALSE,FALSE}
3649         },
3650         {
3651             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3652             {0,S_FALSE,FALSE},
3653             {URL_SCHEME_FILE,S_OK,FALSE},
3654             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3655         }
3656     },
3657     /* The '\' are still converted to '/' even though it's an opaque file URI. */
3658     {   "file:c:\\dir\\../..\\index.html", 0, S_OK, FALSE,
3659         {
3660             {"",S_FALSE,FALSE},
3661             {"",S_FALSE,FALSE},
3662             {"file:c:/dir/../../index.html",S_OK,FALSE},
3663             {"",S_FALSE,FALSE},
3664             {".html",S_OK,FALSE},
3665             {"",S_FALSE,FALSE},
3666             {"",S_FALSE,FALSE},
3667             {"",S_FALSE,FALSE},
3668             {"c:/dir/../../index.html",S_OK,FALSE},
3669             {"c:/dir/../../index.html",S_OK,FALSE},
3670             {"",S_FALSE,FALSE},
3671             {"file:c:\\dir\\../..\\index.html",S_OK,FALSE},
3672             {"file",S_OK,FALSE},
3673             {"",S_FALSE,FALSE},
3674             {"",S_FALSE,FALSE}
3675         },
3676         {
3677             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3678             {0,S_FALSE,FALSE},
3679             {URL_SCHEME_FILE,S_OK,FALSE},
3680             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3681         }
3682     },
3683     /* '/' are still converted to '\' even though it's an opaque URI. */
3684     {   "file:c:/dir\\../..\\index.html", Uri_CREATE_FILE_USE_DOS_PATH, S_OK, FALSE,
3685         {
3686             {"",S_FALSE,FALSE},
3687             {"",S_FALSE,FALSE},
3688             {"file:c:\\dir\\..\\..\\index.html",S_OK,FALSE},
3689             {"",S_FALSE,FALSE},
3690             {".html",S_OK,FALSE},
3691             {"",S_FALSE,FALSE},
3692             {"",S_FALSE,FALSE},
3693             {"",S_FALSE,FALSE},
3694             {"c:\\dir\\..\\..\\index.html",S_OK,FALSE},
3695             {"c:\\dir\\..\\..\\index.html",S_OK,FALSE},
3696             {"",S_FALSE,FALSE},
3697             {"file:c:/dir\\../..\\index.html",S_OK,FALSE},
3698             {"file",S_OK,FALSE},
3699             {"",S_FALSE,FALSE},
3700             {"",S_FALSE,FALSE}
3701         },
3702         {
3703             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3704             {0,S_FALSE,FALSE},
3705             {URL_SCHEME_FILE,S_OK,FALSE},
3706             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3707         }
3708     },
3709     /* Forbidden characters aren't percent encoded. */
3710     {   "file:c:\\in^|dex.html", Uri_CREATE_FILE_USE_DOS_PATH, S_OK, FALSE,
3711         {
3712             {"",S_FALSE,FALSE},
3713             {"",S_FALSE,FALSE},
3714             {"file:c:\\in^|dex.html",S_OK,FALSE},
3715             {"",S_FALSE,FALSE},
3716             {".html",S_OK,FALSE},
3717             {"",S_FALSE,FALSE},
3718             {"",S_FALSE,FALSE},
3719             {"",S_FALSE,FALSE},
3720             {"c:\\in^|dex.html",S_OK,FALSE},
3721             {"c:\\in^|dex.html",S_OK,FALSE},
3722             {"",S_FALSE,FALSE},
3723             {"file:c:\\in^|dex.html",S_OK,FALSE},
3724             {"file",S_OK,FALSE},
3725             {"",S_FALSE,FALSE},
3726             {"",S_FALSE,FALSE}
3727         },
3728         {
3729             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3730             {0,S_FALSE,FALSE},
3731             {URL_SCHEME_FILE,S_OK,FALSE},
3732             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3733         }
3734     },
3735     /* Doesn't have a UserName since the ':' appears at the beginning of the
3736      * userinfo section.
3737      */
3738     {   "http://:password@gov.uk", 0, S_OK, FALSE,
3739         {
3740             {"http://:password@gov.uk/",S_OK,FALSE},
3741             {":password@gov.uk",S_OK,FALSE},
3742             {"http://gov.uk/",S_OK,FALSE},
3743             {"",S_FALSE,FALSE},
3744             {"",S_FALSE,FALSE},
3745             {"",S_FALSE,FALSE},
3746             {"gov.uk",S_OK,FALSE},
3747             {"password",S_OK,FALSE},
3748             {"/",S_OK,FALSE},
3749             {"/",S_OK,FALSE},
3750             {"",S_FALSE,FALSE},
3751             {"http://:password@gov.uk",S_OK,FALSE},
3752             {"http",S_OK,FALSE},
3753             {":password",S_OK,FALSE},
3754             {"",S_FALSE,FALSE}
3755         },
3756         {
3757             {Uri_HOST_DNS,S_OK,FALSE},
3758             {80,S_OK,FALSE},
3759             {URL_SCHEME_HTTP,S_OK,FALSE},
3760             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3761         }
3762     },
3763     /* Has a UserName since the userinfo section doesn't contain a password. */
3764     {   "http://@gov.uk", 0, S_OK, FALSE,
3765         {
3766             {"http://gov.uk/",S_OK,FALSE,"http://@gov.uk/"},
3767             {"@gov.uk",S_OK,FALSE},
3768             {"http://gov.uk/",S_OK,FALSE},
3769             {"",S_FALSE,FALSE},
3770             {"",S_FALSE,FALSE},
3771             {"",S_FALSE,FALSE},
3772             {"gov.uk",S_OK,FALSE},
3773             {"",S_FALSE,FALSE},
3774             {"/",S_OK,FALSE},
3775             {"/",S_OK,FALSE},
3776             {"",S_FALSE,FALSE},
3777             {"http://@gov.uk",S_OK,FALSE},
3778             {"http",S_OK,FALSE},
3779             {"",S_OK,FALSE},
3780             {"",S_OK,FALSE}
3781         },
3782         {
3783             {Uri_HOST_DNS,S_OK,FALSE},
3784             {80,S_OK,FALSE},
3785             {URL_SCHEME_HTTP,S_OK,FALSE},
3786             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3787         }
3788     },
3789     /* ":@" not included in the absolute URI. */
3790     {   "http://:@gov.uk", 0, S_OK, FALSE,
3791         {
3792             {"http://gov.uk/",S_OK,FALSE,"http://:@gov.uk/"},
3793             {":@gov.uk",S_OK,FALSE},
3794             {"http://gov.uk/",S_OK,FALSE},
3795             {"",S_FALSE,FALSE},
3796             {"",S_FALSE,FALSE},
3797             {"",S_FALSE,FALSE},
3798             {"gov.uk",S_OK,FALSE},
3799             {"",S_OK,FALSE},
3800             {"/",S_OK,FALSE},
3801             {"/",S_OK,FALSE},
3802             {"",S_FALSE,FALSE},
3803             {"http://:@gov.uk",S_OK,FALSE},
3804             {"http",S_OK,FALSE},
3805             {":",S_OK,FALSE},
3806             {"",S_FALSE,FALSE}
3807         },
3808         {
3809             {Uri_HOST_DNS,S_OK,FALSE},
3810             {80,S_OK,FALSE},
3811             {URL_SCHEME_HTTP,S_OK,FALSE},
3812             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3813         }
3814     },
3815     /* '@' is included because it's an unknown scheme type. */
3816     {   "zip://@gov.uk", 0, S_OK, FALSE,
3817         {
3818             {"zip://@gov.uk/",S_OK,FALSE},
3819             {"@gov.uk",S_OK,FALSE},
3820             {"zip://@gov.uk/",S_OK,FALSE},
3821             {"",S_FALSE,FALSE},
3822             {"",S_FALSE,FALSE},
3823             {"",S_FALSE,FALSE},
3824             {"gov.uk",S_OK,FALSE},
3825             {"",S_FALSE,FALSE},
3826             {"/",S_OK,FALSE},
3827             {"/",S_OK,FALSE},
3828             {"",S_FALSE,FALSE},
3829             {"zip://@gov.uk",S_OK,FALSE},
3830             {"zip",S_OK,FALSE},
3831             {"",S_OK,FALSE},
3832             {"",S_OK,FALSE}
3833         },
3834         {
3835             {Uri_HOST_DNS,S_OK,FALSE},
3836             {0,S_FALSE,FALSE},
3837             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
3838             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3839         }
3840     },
3841     /* ":@" are included because it's an unknown scheme type. */
3842     {   "zip://:@gov.uk", 0, S_OK, FALSE,
3843         {
3844             {"zip://:@gov.uk/",S_OK,FALSE},
3845             {":@gov.uk",S_OK,FALSE},
3846             {"zip://:@gov.uk/",S_OK,FALSE},
3847             {"",S_FALSE,FALSE},
3848             {"",S_FALSE,FALSE},
3849             {"",S_FALSE,FALSE},
3850             {"gov.uk",S_OK,FALSE},
3851             {"",S_OK,FALSE},
3852             {"/",S_OK,FALSE},
3853             {"/",S_OK,FALSE},
3854             {"",S_FALSE,FALSE},
3855             {"zip://:@gov.uk",S_OK,FALSE},
3856             {"zip",S_OK,FALSE},
3857             {":",S_OK,FALSE},
3858             {"",S_FALSE,FALSE}
3859         },
3860         {
3861             {Uri_HOST_DNS,S_OK,FALSE},
3862             {0,S_FALSE,FALSE},
3863             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
3864             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3865         }
3866     },
3867     {   "about:blank", 0, S_OK, FALSE,
3868         {
3869             {"about:blank",S_OK,FALSE},
3870             {"",S_FALSE,FALSE},
3871             {"about:blank",S_OK,FALSE},
3872             {"",S_FALSE,FALSE},
3873             {"",S_FALSE,FALSE},
3874             {"",S_FALSE,FALSE},
3875             {"",S_FALSE,FALSE},
3876             {"",S_FALSE,FALSE},
3877             {"blank",S_OK,FALSE},
3878             {"blank",S_OK,FALSE},
3879             {"",S_FALSE,FALSE},
3880             {"about:blank",S_OK,FALSE},
3881             {"about",S_OK,FALSE},
3882             {"",S_FALSE,FALSE},
3883             {"",S_FALSE,FALSE}
3884         },
3885         {
3886             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3887             {0,S_FALSE,FALSE},
3888             {URL_SCHEME_ABOUT,S_OK,FALSE},
3889             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3890         }
3891     },
3892     {   "mk:@MSITStore:C:\\Program Files/AutoCAD 2008\\Help/acad_acg.chm::/WSfacf1429558a55de1a7524c1004e616f8b-322b.htm",0,S_OK,FALSE,
3893         {
3894             {"mk:@MSITStore:C:\\Program%20Files/AutoCAD%202008\\Help/acad_acg.chm::/WSfacf1429558a55de1a7524c1004e616f8b-322b.htm",S_OK,FALSE},
3895             {"",S_FALSE,FALSE},
3896             {"mk:@MSITStore:C:\\Program%20Files/AutoCAD%202008\\Help/acad_acg.chm::/WSfacf1429558a55de1a7524c1004e616f8b-322b.htm",S_OK,FALSE},
3897             {"",S_FALSE,FALSE},
3898             {".htm",S_OK,FALSE},
3899             {"",S_FALSE,FALSE},
3900             {"",S_FALSE,FALSE},
3901             {"",S_FALSE,FALSE},
3902             {"@MSITStore:C:\\Program%20Files/AutoCAD%202008\\Help/acad_acg.chm::/WSfacf1429558a55de1a7524c1004e616f8b-322b.htm",S_OK,FALSE},
3903             {"@MSITStore:C:\\Program%20Files/AutoCAD%202008\\Help/acad_acg.chm::/WSfacf1429558a55de1a7524c1004e616f8b-322b.htm",S_OK,FALSE},
3904             {"",S_FALSE,FALSE},
3905             {"mk:@MSITStore:C:\\Program Files/AutoCAD 2008\\Help/acad_acg.chm::/WSfacf1429558a55de1a7524c1004e616f8b-322b.htm",S_OK,FALSE},
3906             {"mk",S_OK,FALSE},
3907             {"",S_FALSE,FALSE},
3908             {"",S_FALSE,FALSE}
3909         },
3910         {
3911             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3912             {0,S_FALSE,FALSE},
3913             {URL_SCHEME_MK,S_OK,FALSE},
3914             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3915         }
3916     },
3917     {   "mk:@MSITStore:Z:\\home\\test\\chm\\silqhelp.chm::/thesilqquickstartguide.htm",0,S_OK,FALSE,
3918         {
3919             {"mk:@MSITStore:Z:\\home\\test\\chm\\silqhelp.chm::/thesilqquickstartguide.htm",S_OK,FALSE},
3920             {"",S_FALSE,FALSE},
3921             {"mk:@MSITStore:Z:\\home\\test\\chm\\silqhelp.chm::/thesilqquickstartguide.htm",S_OK,FALSE},
3922             {"",S_FALSE,FALSE},
3923             {".htm",S_OK,FALSE},
3924             {"",S_FALSE,FALSE},
3925             {"",S_FALSE,FALSE},
3926             {"",S_FALSE,FALSE},
3927             {"@MSITStore:Z:\\home\\test\\chm\\silqhelp.chm::/thesilqquickstartguide.htm",S_OK,FALSE},
3928             {"@MSITStore:Z:\\home\\test\\chm\\silqhelp.chm::/thesilqquickstartguide.htm",S_OK,FALSE},
3929             {"",S_FALSE,FALSE},
3930             {"mk:@MSITStore:Z:\\home\\test\\chm\\silqhelp.chm::/thesilqquickstartguide.htm",S_OK,FALSE},
3931             {"mk",S_OK,FALSE},
3932             {"",S_FALSE,FALSE},
3933             {"",S_FALSE,FALSE}
3934         },
3935         {
3936             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3937             {0,S_FALSE,FALSE},
3938             {URL_SCHEME_MK,S_OK,FALSE},
3939             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3940         }
3941     },
3942     /* Two '\' are added to the URI when USE_DOS_PATH is set, and it's a UNC path. */
3943     {   "file://server/dir/index.html", Uri_CREATE_FILE_USE_DOS_PATH, S_OK, FALSE,
3944         {
3945             {"file://\\\\server\\dir\\index.html",S_OK,FALSE},
3946             {"server",S_OK,FALSE},
3947             {"file://\\\\server\\dir\\index.html",S_OK,FALSE},
3948             {"",S_FALSE,FALSE},
3949             {".html",S_OK,FALSE},
3950             {"",S_FALSE,FALSE},
3951             {"server",S_OK,FALSE},
3952             {"",S_FALSE,FALSE},
3953             {"\\dir\\index.html",S_OK,FALSE},
3954             {"\\dir\\index.html",S_OK,FALSE},
3955             {"",S_FALSE,FALSE},
3956             {"file://server/dir/index.html",S_OK,FALSE},
3957             {"file",S_OK,FALSE},
3958             {"",S_FALSE,FALSE},
3959             {"",S_FALSE,FALSE}
3960         },
3961         {
3962             {Uri_HOST_DNS,S_OK,FALSE},
3963             {0,S_FALSE,FALSE},
3964             {URL_SCHEME_FILE,S_OK,FALSE},
3965             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3966         }
3967     },
3968     /* When CreateUri generates an IUri, it still displays the default port in the
3969      * authority.
3970      */
3971     {   "http://google.com:80/", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
3972         {
3973             {"http://google.com:80/",S_OK,FALSE},
3974             {"google.com:80",S_OK,FALSE},
3975             {"http://google.com:80/",S_OK,FALSE},
3976             {"google.com",S_OK,FALSE},
3977             {"",S_FALSE,FALSE},
3978             {"",S_FALSE,FALSE},
3979             {"google.com",S_OK,FALSE},
3980             {"",S_FALSE,FALSE},
3981             {"/",S_OK,FALSE},
3982             {"/",S_OK,FALSE},
3983             {"",S_FALSE,FALSE},
3984             {"http://google.com:80/",S_OK,FALSE},
3985             {"http",S_OK,FALSE},
3986             {"",S_FALSE,FALSE},
3987             {"",S_FALSE,FALSE}
3988         },
3989         {
3990             {Uri_HOST_DNS,S_OK,FALSE},
3991             {80,S_OK,FALSE},
3992             {URL_SCHEME_HTTP,S_OK,FALSE},
3993             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3994         }
3995     },
3996     /* For res URIs the host is everything up until the first '/'. */
3997     {   "res://C:\\dir\\file.exe/DATA/test.html", 0, S_OK, FALSE,
3998         {
3999             {"res://C:\\dir\\file.exe/DATA/test.html",S_OK,FALSE},
4000             {"C:\\dir\\file.exe",S_OK,FALSE},
4001             {"res://C:\\dir\\file.exe/DATA/test.html",S_OK,FALSE},
4002             {"",S_FALSE,FALSE},
4003             {".html",S_OK,FALSE},
4004             {"",S_FALSE,FALSE},
4005             {"C:\\dir\\file.exe",S_OK,FALSE},
4006             {"",S_FALSE,FALSE},
4007             {"/DATA/test.html",S_OK,FALSE},
4008             {"/DATA/test.html",S_OK,FALSE},
4009             {"",S_FALSE,FALSE},
4010             {"res://C:\\dir\\file.exe/DATA/test.html",S_OK,FALSE},
4011             {"res",S_OK,FALSE},
4012             {"",S_FALSE,FALSE},
4013             {"",S_FALSE,FALSE}
4014         },
4015         {
4016             {Uri_HOST_UNKNOWN,S_OK,FALSE},
4017             {0,S_FALSE,FALSE},
4018             {URL_SCHEME_RES,S_OK,FALSE},
4019             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4020         }
4021     },
4022     /* Res URI can contain a '|' in the host name. */
4023     {   "res://c:\\di|r\\file.exe/test", 0, S_OK, FALSE,
4024         {
4025             {"res://c:\\di|r\\file.exe/test",S_OK,FALSE},
4026             {"c:\\di|r\\file.exe",S_OK,FALSE},
4027             {"res://c:\\di|r\\file.exe/test",S_OK,FALSE},
4028             {"",S_FALSE,FALSE},
4029             {"",S_FALSE,FALSE},
4030             {"",S_FALSE,FALSE},
4031             {"c:\\di|r\\file.exe",S_OK,FALSE},
4032             {"",S_FALSE,FALSE},
4033             {"/test",S_OK,FALSE},
4034             {"/test",S_OK,FALSE},
4035             {"",S_FALSE,FALSE},
4036             {"res://c:\\di|r\\file.exe/test",S_OK,FALSE},
4037             {"res",S_OK,FALSE},
4038             {"",S_FALSE,FALSE},
4039             {"",S_FALSE,FALSE}
4040         },
4041         {
4042             {Uri_HOST_UNKNOWN,S_OK,FALSE},
4043             {0,S_FALSE,FALSE},
4044             {URL_SCHEME_RES,S_OK,FALSE},
4045             {URLZONE_INVALID,E_NOTIMPL,FALSE},
4046         }
4047     },
4048     /* Res URIs can have invalid percent encoded values. */
4049     {   "res://c:\\dir%xx\\file.exe/test", 0, S_OK, FALSE,
4050         {
4051             {"res://c:\\dir%xx\\file.exe/test",S_OK,FALSE},
4052             {"c:\\dir%xx\\file.exe",S_OK,FALSE},
4053             {"res://c:\\dir%xx\\file.exe/test",S_OK,FALSE},
4054             {"",S_FALSE,FALSE},
4055             {"",S_FALSE,FALSE},
4056             {"",S_FALSE,FALSE},
4057             {"c:\\dir%xx\\file.exe",S_OK,FALSE},
4058             {"",S_FALSE,FALSE},
4059             {"/test",S_OK,FALSE},
4060             {"/test",S_OK,FALSE},
4061             {"",S_FALSE,FALSE},
4062             {"res://c:\\dir%xx\\file.exe/test",S_OK,FALSE},
4063             {"res",S_OK,FALSE},
4064             {"",S_FALSE,FALSE},
4065             {"",S_FALSE,FALSE}
4066         },
4067         {
4068             {Uri_HOST_UNKNOWN,S_OK,FALSE},
4069             {0,S_FALSE,FALSE},
4070             {URL_SCHEME_RES,S_OK,FALSE},
4071             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4072         }
4073     },
4074     /* Res doesn't get forbidden characters percent encoded in it's path. */
4075     {   "res://c:\\test/tes<|>t", 0, S_OK, FALSE,
4076         {
4077             {"res://c:\\test/tes<|>t",S_OK,FALSE},
4078             {"c:\\test",S_OK,FALSE},
4079             {"res://c:\\test/tes<|>t",S_OK,FALSE},
4080             {"",S_FALSE,FALSE},
4081             {"",S_FALSE,FALSE},
4082             {"",S_FALSE,FALSE},
4083             {"c:\\test",S_OK,FALSE},
4084             {"",S_FALSE,FALSE},
4085             {"/tes<|>t",S_OK,FALSE},
4086             {"/tes<|>t",S_OK,FALSE},
4087             {"",S_FALSE,FALSE},
4088             {"res://c:\\test/tes<|>t",S_OK,FALSE},
4089             {"res",S_OK,FALSE},
4090             {"",S_FALSE,FALSE},
4091             {"",S_FALSE,FALSE}
4092         },
4093         {
4094             {Uri_HOST_UNKNOWN,S_OK,FALSE},
4095             {0,S_FALSE,FALSE},
4096             {URL_SCHEME_RES,S_OK,FALSE},
4097             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4098         }
4099     },
4100     {   "mk:@MSITStore:Z:\\dir\\test.chm::/html/../images/xxx.jpg", 0, S_OK, FALSE,
4101         {
4102             {"mk:@MSITStore:Z:\\dir\\test.chm::/images/xxx.jpg",S_OK,FALSE},
4103             {"",S_FALSE,FALSE},
4104             {"mk:@MSITStore:Z:\\dir\\test.chm::/images/xxx.jpg",S_OK,FALSE},
4105             {"",S_FALSE,FALSE},
4106             {".jpg",S_OK,FALSE},
4107             {"",S_FALSE,FALSE},
4108             {"",S_FALSE,FALSE},
4109             {"",S_FALSE,FALSE},
4110             {"@MSITStore:Z:\\dir\\test.chm::/images/xxx.jpg",S_OK,FALSE},
4111             {"@MSITStore:Z:\\dir\\test.chm::/images/xxx.jpg",S_OK,FALSE},
4112             {"",S_FALSE,FALSE},
4113             {"mk:@MSITStore:Z:\\dir\\test.chm::/html/../images/xxx.jpg",S_OK,FALSE},
4114             {"mk",S_OK,FALSE},
4115             {"",S_FALSE,FALSE},
4116             {"",S_FALSE,FALSE}
4117         },
4118         {
4119             {Uri_HOST_UNKNOWN,S_OK,FALSE},
4120             {0,S_FALSE,FALSE},
4121             {URL_SCHEME_MK,S_OK,FALSE},
4122             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4123         }
4124     },
4125     {   "mk:@MSITStore:Z:\\dir\\test.chm::/html/../images/xxx.jpg", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
4126         {
4127             {"mk:@MSITStore:Z:\\dir\\test.chm::/html/../images/xxx.jpg",S_OK,FALSE},
4128             {"",S_FALSE,FALSE},
4129             {"mk:@MSITStore:Z:\\dir\\test.chm::/html/../images/xxx.jpg",S_OK,FALSE},
4130             {"",S_FALSE,FALSE},
4131             {".jpg",S_OK,FALSE},
4132             {"",S_FALSE,FALSE},
4133             {"",S_FALSE,FALSE},
4134             {"",S_FALSE,FALSE},
4135             {"@MSITStore:Z:\\dir\\test.chm::/html/../images/xxx.jpg",S_OK,FALSE},
4136             {"@MSITStore:Z:\\dir\\test.chm::/html/../images/xxx.jpg",S_OK,FALSE},
4137             {"",S_FALSE,FALSE},
4138             {"mk:@MSITStore:Z:\\dir\\test.chm::/html/../images/xxx.jpg",S_OK,FALSE},
4139             {"mk",S_OK,FALSE},
4140             {"",S_FALSE,FALSE},
4141             {"",S_FALSE,FALSE}
4142         },
4143         {
4144             {Uri_HOST_UNKNOWN,S_OK,FALSE},
4145             {0,S_FALSE,FALSE},
4146             {URL_SCHEME_MK,S_OK,FALSE},
4147             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4148         }
4149     },
4150     {   "xx:@MSITStore:Z:\\dir\\test.chm::/html/../images/xxx.jpg", 0, S_OK, FALSE,
4151         {
4152             {"xx:@MSITStore:Z:\\dir\\test.chm::/html/../images/xxx.jpg",S_OK,FALSE},
4153             {"",S_FALSE,FALSE},
4154             {"xx:@MSITStore:Z:\\dir\\test.chm::/html/../images/xxx.jpg",S_OK,FALSE},
4155             {"",S_FALSE,FALSE},
4156             {".jpg",S_OK,FALSE},
4157             {"",S_FALSE,FALSE},
4158             {"",S_FALSE,FALSE},
4159             {"",S_FALSE,FALSE},
4160             {"@MSITStore:Z:\\dir\\test.chm::/html/../images/xxx.jpg",S_OK,FALSE},
4161             {"@MSITStore:Z:\\dir\\test.chm::/html/../images/xxx.jpg",S_OK,FALSE},
4162             {"",S_FALSE,FALSE},
4163             {"xx:@MSITStore:Z:\\dir\\test.chm::/html/../images/xxx.jpg",S_OK,FALSE},
4164             {"xx",S_OK,FALSE},
4165             {"",S_FALSE,FALSE},
4166             {"",S_FALSE,FALSE}
4167         },
4168         {
4169             {Uri_HOST_UNKNOWN,S_OK,FALSE},
4170             {0,S_FALSE,FALSE},
4171             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
4172             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4173         }
4174     },
4175     {   "mk:@MSITStore:Z:\\dir\\test.chm::/html/../../images/xxx.jpg", 0, S_OK, FALSE,
4176         {
4177             {"mk:@MSITStore:Z:\\dir\\images/xxx.jpg",S_OK,FALSE},
4178             {"",S_FALSE,FALSE},
4179             {"mk:@MSITStore:Z:\\dir\\images/xxx.jpg",S_OK,FALSE},
4180             {"",S_FALSE,FALSE},
4181             {".jpg",S_OK,FALSE},
4182             {"",S_FALSE,FALSE},
4183             {"",S_FALSE,FALSE},
4184             {"",S_FALSE,FALSE},
4185             {"@MSITStore:Z:\\dir\\images/xxx.jpg",S_OK,FALSE},
4186             {"@MSITStore:Z:\\dir\\images/xxx.jpg",S_OK,FALSE},
4187             {"",S_FALSE,FALSE},
4188             {"mk:@MSITStore:Z:\\dir\\test.chm::/html/../../images/xxx.jpg",S_OK,FALSE},
4189             {"mk",S_OK,FALSE},
4190             {"",S_FALSE,FALSE},
4191             {"",S_FALSE,FALSE}
4192         },
4193         {
4194             {Uri_HOST_UNKNOWN,S_OK,FALSE},
4195             {0,S_FALSE,FALSE},
4196             {URL_SCHEME_MK,S_OK,FALSE},
4197             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4198         }
4199     },
4200     {   "mk:@MSITStore:Z:\\dir\\dir2\\..\\test.chm::/html/../../images/xxx.jpg", 0, S_OK, FALSE,
4201         {
4202             {"mk:@MSITStore:Z:\\dir\\images/xxx.jpg",S_OK,FALSE},
4203             {"",S_FALSE,FALSE},
4204             {"mk:@MSITStore:Z:\\dir\\images/xxx.jpg",S_OK,FALSE},
4205             {"",S_FALSE,FALSE},
4206             {".jpg",S_OK,FALSE},
4207             {"",S_FALSE,FALSE},
4208             {"",S_FALSE,FALSE},
4209             {"",S_FALSE,FALSE},
4210             {"@MSITStore:Z:\\dir\\images/xxx.jpg",S_OK,FALSE},
4211             {"@MSITStore:Z:\\dir\\images/xxx.jpg",S_OK,FALSE},
4212             {"",S_FALSE,FALSE},
4213             {"mk:@MSITStore:Z:\\dir\\dir2\\..\\test.chm::/html/../../images/xxx.jpg",S_OK,FALSE},
4214             {"mk",S_OK,FALSE},
4215             {"",S_FALSE,FALSE},
4216             {"",S_FALSE,FALSE}
4217         },
4218         {
4219             {Uri_HOST_UNKNOWN,S_OK,FALSE},
4220             {0,S_FALSE,FALSE},
4221             {URL_SCHEME_MK,S_OK,FALSE},
4222             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4223         }
4224     },
4225     {   "mk:@MSITStore:Z:\\dir\\test.chm::/html/../../../../images/xxx.jpg", 0, S_OK, FALSE,
4226         {
4227             {"mk:images/xxx.jpg",S_OK,FALSE},
4228             {"",S_FALSE,FALSE},
4229             {"mk:images/xxx.jpg",S_OK,FALSE},
4230             {"",S_FALSE,FALSE},
4231             {".jpg",S_OK,FALSE},
4232             {"",S_FALSE,FALSE},
4233             {"",S_FALSE,FALSE},
4234             {"",S_FALSE,FALSE},
4235             {"images/xxx.jpg",S_OK,FALSE},
4236             {"images/xxx.jpg",S_OK,FALSE},
4237             {"",S_FALSE,FALSE},
4238             {"mk:@MSITStore:Z:\\dir\\test.chm::/html/../../../../images/xxx.jpg",S_OK,FALSE},
4239             {"mk",S_OK,FALSE},
4240             {"",S_FALSE,FALSE},
4241             {"",S_FALSE,FALSE}
4242         },
4243         {
4244             {Uri_HOST_UNKNOWN,S_OK,FALSE},
4245             {0,S_FALSE,FALSE},
4246             {URL_SCHEME_MK,S_OK,FALSE},
4247             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4248         }
4249     },
4250     {   "", Uri_CREATE_ALLOW_RELATIVE, S_OK, FALSE,
4251         {
4252             {"",S_OK,FALSE},
4253             {"",S_FALSE,FALSE},
4254             {"",S_OK,FALSE},
4255             {"",S_FALSE,FALSE},
4256             {"",S_FALSE,FALSE},
4257             {"",S_FALSE,FALSE},
4258             {"",S_FALSE,FALSE},
4259             {"",S_FALSE,FALSE},
4260             {"",S_OK,FALSE},
4261             {"",S_OK,FALSE},
4262             {"",S_FALSE,FALSE},
4263             {"",S_OK,FALSE},
4264             {"",S_FALSE,FALSE},
4265             {"",S_FALSE,FALSE},
4266             {"",S_FALSE,FALSE}
4267         },
4268         {
4269             {Uri_HOST_UNKNOWN,S_OK,FALSE},
4270             {0,S_FALSE,FALSE},
4271             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
4272             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4273         }
4274     },
4275     {   " \t ", Uri_CREATE_ALLOW_RELATIVE, S_OK, FALSE,
4276         {
4277             {"",S_OK,FALSE},
4278             {"",S_FALSE,FALSE},
4279             {"",S_OK,FALSE},
4280             {"",S_FALSE,FALSE},
4281             {"",S_FALSE,FALSE},
4282             {"",S_FALSE,FALSE},
4283             {"",S_FALSE,FALSE},
4284             {"",S_FALSE,FALSE},
4285             {"",S_OK,FALSE},
4286             {"",S_OK,FALSE},
4287             {"",S_FALSE,FALSE},
4288             {"",S_OK,FALSE},
4289             {"",S_FALSE,FALSE},
4290             {"",S_FALSE,FALSE},
4291             {"",S_FALSE,FALSE}
4292         },
4293         {
4294             {Uri_HOST_UNKNOWN,S_OK,FALSE},
4295             {0,S_FALSE,FALSE},
4296             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
4297             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4298         }
4299     },
4300     {   "javascript:void", 0, S_OK, FALSE,
4301         {
4302             {"javascript:void",S_OK},
4303             {"",S_FALSE},
4304             {"javascript:void",S_OK},
4305             {"",S_FALSE},
4306             {"",S_FALSE},
4307             {"",S_FALSE},
4308             {"",S_FALSE},
4309             {"",S_FALSE},
4310             {"void",S_OK},
4311             {"void",S_OK},
4312             {"",S_FALSE},
4313             {"javascript:void",S_OK},
4314             {"javascript",S_OK},
4315             {"",S_FALSE},
4316             {"",S_FALSE}
4317         },
4318         {
4319             {Uri_HOST_UNKNOWN,S_OK},
4320             {0,S_FALSE},
4321             {URL_SCHEME_JAVASCRIPT,S_OK},
4322             {URLZONE_INVALID,E_NOTIMPL}
4323         }
4324     },
4325     {   "javascript://undefined", 0, S_OK, FALSE,
4326         {
4327             {"javascript://undefined",S_OK},
4328             {"",S_FALSE},
4329             {"javascript://undefined",S_OK},
4330             {"",S_FALSE},
4331             {"",S_FALSE},
4332             {"",S_FALSE},
4333             {"",S_FALSE},
4334             {"",S_FALSE},
4335             {"//undefined",S_OK},
4336             {"//undefined",S_OK},
4337             {"",S_FALSE},
4338             {"javascript://undefined",S_OK},
4339             {"javascript",S_OK},
4340             {"",S_FALSE},
4341             {"",S_FALSE}
4342         },
4343         {
4344             {Uri_HOST_UNKNOWN,S_OK},
4345             {0,S_FALSE},
4346             {URL_SCHEME_JAVASCRIPT,S_OK},
4347             {URLZONE_INVALID,E_NOTIMPL}
4348         }
4349     },
4350     {   "JavaSCript:escape('/\\?#?')", 0, S_OK, FALSE,
4351         {
4352             {"javascript:escape('/\\?#?')",S_OK},
4353             {"",S_FALSE},
4354             {"javascript:escape('/\\?#?')",S_OK},
4355             {"",S_FALSE},
4356             {"",S_FALSE},
4357             {"",S_FALSE},
4358             {"",S_FALSE},
4359             {"",S_FALSE},
4360             {"escape('/\\?#?')",S_OK},
4361             {"escape('/\\?#?')",S_OK},
4362             {"",S_FALSE},
4363             {"JavaSCript:escape('/\\?#?')",S_OK},
4364             {"javascript",S_OK},
4365             {"",S_FALSE},
4366             {"",S_FALSE}
4367         },
4368         {
4369             {Uri_HOST_UNKNOWN,S_OK},
4370             {0,S_FALSE},
4371             {URL_SCHEME_JAVASCRIPT,S_OK},
4372             {URLZONE_INVALID,E_NOTIMPL}
4373         }
4374     },
4375     {   "*://google.com", 0, S_OK, FALSE,
4376         {
4377             {"*:google.com/",S_OK,FALSE},
4378             {"google.com",S_OK},
4379             {"*:google.com/",S_OK,FALSE},
4380             {"google.com",S_OK,FALSE},
4381             {"",S_FALSE,FALSE},
4382             {"",S_FALSE,FALSE},
4383             {"google.com",S_OK,FALSE},
4384             {"",S_FALSE,FALSE},
4385             {"/",S_OK,FALSE},
4386             {"/",S_OK,FALSE},
4387             {"",S_FALSE,FALSE},
4388             {"*://google.com",S_OK,FALSE},
4389             {"*",S_OK,FALSE},
4390             {"",S_FALSE,FALSE},
4391             {"",S_FALSE,FALSE}
4392         },
4393         {
4394             {Uri_HOST_DNS,S_OK,FALSE},
4395             {0,S_FALSE,FALSE},
4396             {URL_SCHEME_WILDCARD,S_OK,FALSE},
4397             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4398         }
4399     },
4400     {   "mk:@MSITSTORE:C:\\Some\\Bogus\\Path.chm::/subdir/file.txt",0,S_OK,FALSE,
4401         {
4402             {"mk:@MSITSTORE:C:\\Some\\Bogus\\Path.chm::/subdir/file.txt",S_OK},
4403             {"",S_FALSE},
4404             {"mk:@MSITSTORE:C:\\Some\\Bogus\\Path.chm::/subdir/file.txt",S_OK},
4405             {"",S_FALSE},
4406             {".txt",S_OK},
4407             {"",S_FALSE},
4408             {"",S_FALSE},
4409             {"",S_FALSE},
4410             {"@MSITSTORE:C:\\Some\\Bogus\\Path.chm::/subdir/file.txt",S_OK},
4411             {"@MSITSTORE:C:\\Some\\Bogus\\Path.chm::/subdir/file.txt",S_OK},
4412             {"",S_FALSE},
4413             {"mk:@MSITSTORE:C:\\Some\\Bogus\\Path.chm::/subdir/file.txt",S_OK},
4414             {"mk",S_OK},
4415             {"",S_FALSE},
4416             {"",S_FALSE}
4417         },
4418         {
4419             {Uri_HOST_UNKNOWN,S_OK},
4420             {0,S_FALSE},
4421             {URL_SCHEME_MK,S_OK},
4422             {URLZONE_INVALID,E_NOTIMPL}
4423         }
4424     },
4425     {   "gopher://test.winehq.org:151/file.txt",0,S_OK,FALSE,
4426         {
4427             {"gopher://test.winehq.org:151/file.txt",S_OK},
4428             {"test.winehq.org:151",S_OK},
4429             {"gopher://test.winehq.org:151/file.txt",S_OK},
4430             {"winehq.org",S_OK},
4431             {".txt",S_OK},
4432             {"",S_FALSE},
4433             {"test.winehq.org",S_OK},
4434             {"",S_FALSE},
4435             {"/file.txt",S_OK},
4436             {"/file.txt",S_OK},
4437             {"",S_FALSE},
4438             {"gopher://test.winehq.org:151/file.txt",S_OK},
4439             {"gopher",S_OK},
4440             {"",S_FALSE},
4441             {"",S_FALSE}
4442         },
4443         {
4444             {Uri_HOST_DNS,S_OK},
4445             {151,S_OK},
4446             {URL_SCHEME_GOPHER,S_OK},
4447             {URLZONE_INVALID,E_NOTIMPL}
4448         }
4449     },
4450     {   "//host.com/path/file.txt?query", Uri_CREATE_ALLOW_RELATIVE, S_OK, FALSE,
4451         {
4452             {"//host.com/path/file.txt?query",S_OK},
4453             {"host.com",S_OK},
4454             {"//host.com/path/file.txt?query",S_OK},
4455             {"host.com",S_OK},
4456             {".txt",S_OK},
4457             {"",S_FALSE},
4458             {"host.com",S_OK},
4459             {"",S_FALSE},
4460             {"/path/file.txt",S_OK},
4461             {"/path/file.txt?query",S_OK},
4462             {"?query",S_OK},
4463             {"//host.com/path/file.txt?query",S_OK},
4464             {"",S_FALSE},
4465             {"",S_FALSE},
4466             {"",S_FALSE},
4467         },
4468         {
4469             {Uri_HOST_DNS,S_OK},
4470             {0,S_FALSE},
4471             {URL_SCHEME_UNKNOWN,S_OK},
4472             {URLZONE_INVALID,E_NOTIMPL}
4473         }
4474     },
4475     {   "//host/path/file.txt?query", Uri_CREATE_ALLOW_RELATIVE, S_OK, FALSE,
4476         {
4477             {"//host/path/file.txt?query",S_OK},
4478             {"host",S_OK},
4479             {"//host/path/file.txt?query",S_OK},
4480             {"",S_FALSE},
4481             {".txt",S_OK},
4482             {"",S_FALSE},
4483             {"host",S_OK},
4484             {"",S_FALSE},
4485             {"/path/file.txt",S_OK},
4486             {"/path/file.txt?query",S_OK},
4487             {"?query",S_OK},
4488             {"//host/path/file.txt?query",S_OK},
4489             {"",S_FALSE},
4490             {"",S_FALSE},
4491             {"",S_FALSE},
4492         },
4493         {
4494             {Uri_HOST_DNS,S_OK},
4495             {0,S_FALSE},
4496             {URL_SCHEME_UNKNOWN,S_OK},
4497             {URLZONE_INVALID,E_NOTIMPL}
4498         }
4499     },
4500     {   "//host", Uri_CREATE_ALLOW_RELATIVE, S_OK, FALSE,
4501         {
4502             {"//host/",S_OK},
4503             {"host",S_OK},
4504             {"//host/",S_OK},
4505             {"",S_FALSE},
4506             {"",S_FALSE},
4507             {"",S_FALSE},
4508             {"host",S_OK},
4509             {"",S_FALSE},
4510             {"/",S_OK},
4511             {"/",S_OK},
4512             {"",S_FALSE},
4513             {"//host",S_OK},
4514             {"",S_FALSE},
4515             {"",S_FALSE},
4516             {"",S_FALSE},
4517         },
4518         {
4519             {Uri_HOST_DNS,S_OK},
4520             {0,S_FALSE},
4521             {URL_SCHEME_UNKNOWN,S_OK},
4522             {URLZONE_INVALID,E_NOTIMPL}
4523         }
4524     },
4525     {   "mailto://", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
4526         {
4527             {"mailto:",S_OK},
4528             {"",S_FALSE},
4529             {"mailto:",S_OK},
4530             {"",S_FALSE},
4531             {"",S_FALSE},
4532             {"",S_FALSE},
4533             {"",S_FALSE},
4534             {"",S_FALSE},
4535             {"",S_FALSE},
4536             {"",S_FALSE},
4537             {"",S_FALSE},
4538             {"mailto://",S_OK,FALSE,"mailto:"},
4539             {"mailto",S_OK},
4540             {"",S_FALSE},
4541             {"",S_FALSE}
4542         },
4543         {
4544             {Uri_HOST_UNKNOWN,S_OK},
4545             {0,S_FALSE},
4546             {URL_SCHEME_MAILTO,S_OK},
4547             {URLZONE_INVALID,E_NOTIMPL}
4548         }
4549     },
4550     {   "mailto://a@b.com", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
4551         {
4552             {"mailto:a@b.com",S_OK},
4553             {"",S_FALSE},
4554             {"mailto:a@b.com",S_OK},
4555             {"",S_FALSE},
4556             {".com",S_OK},
4557             {"",S_FALSE},
4558             {"",S_FALSE},
4559             {"",S_FALSE},
4560             {"a@b.com",S_OK},
4561             {"a@b.com",S_OK},
4562             {"",S_FALSE},
4563             {"mailto://a@b.com",S_OK,FALSE,"mailto:a@b.com"},
4564             {"mailto",S_OK},
4565             {"",S_FALSE},
4566             {"",S_FALSE}
4567         },
4568         {
4569             {Uri_HOST_UNKNOWN,S_OK},
4570             {0,S_FALSE},
4571             {URL_SCHEME_MAILTO,S_OK},
4572             {URLZONE_INVALID,E_NOTIMPL}
4573         }
4574      }
4575 };
4576
4577 typedef struct _invalid_uri {
4578     const char* uri;
4579     DWORD       flags;
4580     BOOL        todo;
4581 } invalid_uri;
4582
4583 static const invalid_uri invalid_uri_tests[] = {
4584     /* Has to have a scheme name. */
4585     {"://www.winehq.org",0,FALSE},
4586     /* Window's doesn't like URI's which are implicitly file paths without the
4587      * ALLOW_IMPLICIT_FILE_SCHEME flag set.
4588      */
4589     {"C:/test/test.mp3",0,FALSE},
4590     {"\\\\Server/test/test.mp3",0,FALSE},
4591     {"C:/test/test.mp3",Uri_CREATE_ALLOW_IMPLICIT_WILDCARD_SCHEME,FALSE},
4592     {"\\\\Server/test/test.mp3",Uri_CREATE_ALLOW_RELATIVE,FALSE},
4593     /* Invalid schemes. */
4594     {"*abcd://not.valid.com",0,FALSE},
4595     {"*a*b*c*d://not.valid.com",0,FALSE},
4596     /* Not allowed to have invalid % encoded data. */
4597     {"ftp://google.co%XX/",0,FALSE},
4598     /* To many h16 components. */
4599     {"http://[1:2:3:4:5:6:7:8:9]",0,FALSE},
4600     /* Not enough room for IPv4 address. */
4601     {"http://[1:2:3:4:5:6:7:192.0.1.0]",0,FALSE},
4602     /* Not enough h16 components. */
4603     {"http://[1:2:3:4]",0,FALSE},
4604     /* Not enough components including IPv4. */
4605     {"http://[1:192.0.1.0]",0,FALSE},
4606     /* Not allowed to have partial IPv4 in IPv6. */
4607     {"http://[::192.0]",0,FALSE},
4608     /* Can't have elision of 1 h16 at beginning of address. */
4609     {"http://[::2:3:4:5:6:7:8]",0,FALSE},
4610     /* Can't have elision of 1 h16 at end of address. */
4611     {"http://[1:2:3:4:5:6:7::]",0,FALSE},
4612     /* Expects a valid IP Literal. */
4613     {"ftp://[not.valid.uri]/",0,FALSE},
4614     /* Expects valid port for a known scheme type. */
4615     {"ftp://www.winehq.org:123fgh",0,FALSE},
4616     /* Port exceeds USHORT_MAX for known scheme type. */
4617     {"ftp://www.winehq.org:65536",0,FALSE},
4618     /* Invalid port with IPv4 address. */
4619     {"http://www.winehq.org:1abcd",0,FALSE},
4620     /* Invalid port with IPv6 address. */
4621     {"http://[::ffff]:32xy",0,FALSE},
4622     /* Not allowed to have backslashes with NO_CANONICALIZE. */
4623     {"gopher://www.google.com\\test",Uri_CREATE_NO_CANONICALIZE,FALSE},
4624     /* Not allowed to have invalid % encoded data in opaque URI path. */
4625     {"news:test%XX",0,FALSE},
4626     {"mailto:wine@winehq%G8.com",0,FALSE},
4627     /* Known scheme types can't have invalid % encoded data in query string. */
4628     {"http://google.com/?query=te%xx",0,FALSE},
4629     /* Invalid % encoded data in fragment of know scheme type. */
4630     {"ftp://google.com/#Test%xx",0,FALSE},
4631     {"  http://google.com/",Uri_CREATE_NO_PRE_PROCESS_HTML_URI,FALSE},
4632     {"\n\nhttp://google.com/",Uri_CREATE_NO_PRE_PROCESS_HTML_URI,FALSE},
4633     {"file://c:\\test<test",Uri_CREATE_FILE_USE_DOS_PATH,FALSE},
4634     {"file://c:\\test>test",Uri_CREATE_FILE_USE_DOS_PATH,FALSE},
4635     {"file://c:\\test\"test",Uri_CREATE_FILE_USE_DOS_PATH,FALSE},
4636     {"file:c:\\test<test",Uri_CREATE_FILE_USE_DOS_PATH,FALSE},
4637     {"file:c:\\test>test",Uri_CREATE_FILE_USE_DOS_PATH,FALSE},
4638     {"file:c:\\test\"test",Uri_CREATE_FILE_USE_DOS_PATH,FALSE},
4639     /* res URIs aren't allowed to have forbidden dos path characters in the
4640      * hostname.
4641      */
4642     {"res://c:\\te<st\\test/test",0,FALSE},
4643     {"res://c:\\te>st\\test/test",0,FALSE},
4644     {"res://c:\\te\"st\\test/test",0,FALSE},
4645     {"res://c:\\test/te%xxst",0,FALSE}
4646 };
4647
4648 typedef struct _uri_equality {
4649     const char* a;
4650     DWORD       create_flags_a;
4651     const char* b;
4652     DWORD       create_flags_b;
4653     BOOL        equal;
4654     BOOL        todo;
4655 } uri_equality;
4656
4657 static const uri_equality equality_tests[] = {
4658     {
4659         "HTTP://www.winehq.org/test dir/./",0,
4660         "http://www.winehq.org/test dir/../test dir/",0,
4661         TRUE
4662     },
4663     {
4664         /* http://www.winehq.org/test%20dir */
4665         "http://%77%77%77%2E%77%69%6E%65%68%71%2E%6F%72%67/%74%65%73%74%20%64%69%72",0,
4666         "http://www.winehq.org/test dir",0,
4667         TRUE
4668     },
4669     {
4670         "c:\\test.mp3",Uri_CREATE_ALLOW_IMPLICIT_FILE_SCHEME,
4671         "file:///c:/test.mp3",0,
4672         TRUE
4673     },
4674     {
4675         "ftp://ftp.winehq.org/",0,
4676         "ftp://ftp.winehq.org",0,
4677         TRUE
4678     },
4679     {
4680         "ftp://ftp.winehq.org/test/test2/../../testB/",0,
4681         "ftp://ftp.winehq.org/t%45stB/",0,
4682         FALSE
4683     },
4684     {
4685         "http://google.com/TEST",0,
4686         "http://google.com/test",0,
4687         FALSE
4688     },
4689     {
4690         "http://GOOGLE.com/",0,
4691         "http://google.com/",0,
4692         TRUE
4693     },
4694     /* Performs case insensitive compare of host names (for known scheme types). */
4695     {
4696         "ftp://GOOGLE.com/",Uri_CREATE_NO_CANONICALIZE,
4697         "ftp://google.com/",0,
4698         TRUE
4699     },
4700     {
4701         "zip://GOOGLE.com/",0,
4702         "zip://google.com/",0,
4703         FALSE
4704     },
4705     {
4706         "file:///c:/TEST/TeST/",0,
4707         "file:///c:/test/test/",0,
4708         TRUE
4709     },
4710     {
4711         "file:///server/TEST",0,
4712         "file:///SERVER/TEST",0,
4713         TRUE
4714     },
4715     {
4716         "http://google.com",Uri_CREATE_NO_CANONICALIZE,
4717         "http://google.com/",0,
4718         TRUE
4719     },
4720     {
4721         "ftp://google.com:21/",0,
4722         "ftp://google.com/",0,
4723         TRUE
4724     },
4725     {
4726         "http://google.com:80/",Uri_CREATE_NO_CANONICALIZE,
4727         "http://google.com/",0,
4728         TRUE
4729     },
4730     {
4731         "http://google.com:70/",0,
4732         "http://google.com:71/",0,
4733         FALSE
4734     },
4735     {
4736         "file:///c:/dir/file.txt", 0,
4737         "file:///c:/dir/file.txt", Uri_CREATE_FILE_USE_DOS_PATH,
4738         TRUE
4739     },
4740     {
4741         "file:///c:/dir/file.txt", 0,
4742         "file:///c:\\dir\\file.txt", Uri_CREATE_NO_CANONICALIZE,
4743         TRUE
4744     },
4745     {
4746         "file:///c:/dir/file.txt", 0,
4747         "file:///c:\\dir2\\..\\dir\\file.txt", Uri_CREATE_NO_CANONICALIZE,
4748         TRUE
4749     },
4750     {
4751         "file:///c:\\dir2\\..\\ dir\\file.txt", Uri_CREATE_NO_CANONICALIZE,
4752         "file:///c:/%20dir/file.txt", 0,
4753         TRUE
4754     },
4755     {
4756         "file:///c:/Dir/file.txt", 0,
4757         "file:///C:/dir/file.TXT", Uri_CREATE_FILE_USE_DOS_PATH,
4758         TRUE
4759     },
4760     {
4761         "file:///c:/dir/file.txt", 0,
4762         "file:///c:\\dir\\file.txt", Uri_CREATE_FILE_USE_DOS_PATH,
4763         TRUE
4764     },
4765     {
4766         "file:///c:/dir/file.txt#a", 0,
4767         "file:///c:\\dir\\file.txt#b", Uri_CREATE_FILE_USE_DOS_PATH,
4768         FALSE
4769     },
4770     /* Tests of an empty hash/fragment part */
4771     {
4772         "http://google.com/test",0,
4773         "http://google.com/test#",0,
4774         FALSE
4775     },
4776     {
4777         "ftp://ftp.winehq.org/",0,
4778         "ftp://ftp.winehq.org/#",0,
4779         FALSE
4780     },
4781     {
4782         "file:///c:/dir/file.txt#", 0,
4783         "file:///c:\\dir\\file.txt", Uri_CREATE_FILE_USE_DOS_PATH,
4784         FALSE
4785     }
4786 };
4787
4788 typedef struct _uri_with_fragment {
4789     const char* uri;
4790     const char* fragment;
4791     DWORD       create_flags;
4792     HRESULT     create_expected;
4793     BOOL        create_todo;
4794
4795     const char* expected_uri;
4796     BOOL        expected_todo;
4797 } uri_with_fragment;
4798
4799 static const uri_with_fragment uri_fragment_tests[] = {
4800     {
4801         "http://google.com/","#fragment",0,S_OK,FALSE,
4802         "http://google.com/#fragment",FALSE
4803     },
4804     {
4805         "http://google.com/","fragment",0,S_OK,FALSE,
4806         "http://google.com/#fragment",FALSE
4807     },
4808     {
4809         "zip://test.com/","?test",0,S_OK,FALSE,
4810         "zip://test.com/#?test",FALSE
4811     },
4812     /* The fragment can be empty. */
4813     {
4814         "ftp://ftp.google.com/","",0,S_OK,FALSE,
4815         "ftp://ftp.google.com/#",FALSE
4816     }
4817 };
4818
4819 typedef struct _uri_builder_property {
4820     BOOL            change;
4821     const char      *value;
4822     const char      *expected_value;
4823     Uri_PROPERTY    property;
4824     HRESULT         expected;
4825     BOOL            todo;
4826 } uri_builder_property;
4827
4828 typedef struct _uri_builder_port {
4829     BOOL    change;
4830     BOOL    set;
4831     DWORD   value;
4832     HRESULT expected;
4833     BOOL    todo;
4834 } uri_builder_port;
4835
4836 typedef struct _uri_builder_str_property {
4837     const char* expected;
4838     HRESULT     result;
4839     BOOL        todo;
4840 } uri_builder_str_property;
4841
4842 typedef struct _uri_builder_dword_property {
4843     DWORD   expected;
4844     HRESULT result;
4845     BOOL    todo;
4846 } uri_builder_dword_property;
4847
4848 typedef struct _uri_builder_test {
4849     const char                  *uri;
4850     DWORD                       create_flags;
4851     HRESULT                     create_builder_expected;
4852     BOOL                        create_builder_todo;
4853
4854     uri_builder_property        properties[URI_BUILDER_STR_PROPERTY_COUNT];
4855
4856     uri_builder_port            port_prop;
4857
4858     DWORD                       uri_flags;
4859     HRESULT                     uri_hres;
4860     BOOL                        uri_todo;
4861
4862     DWORD                       uri_simple_encode_flags;
4863     HRESULT                     uri_simple_hres;
4864     BOOL                        uri_simple_todo;
4865
4866     DWORD                       uri_with_flags;
4867     DWORD                       uri_with_builder_flags;
4868     DWORD                       uri_with_encode_flags;
4869     HRESULT                     uri_with_hres;
4870     BOOL                        uri_with_todo;
4871
4872     uri_builder_str_property    expected_str_props[URI_STR_PROPERTY_COUNT];
4873     uri_builder_dword_property  expected_dword_props[URI_DWORD_PROPERTY_COUNT];
4874 } uri_builder_test;
4875
4876 static const uri_builder_test uri_builder_tests[] = {
4877     {   "http://google.com/",0,S_OK,FALSE,
4878         {
4879             {TRUE,"#fragment",NULL,Uri_PROPERTY_FRAGMENT,S_OK,FALSE},
4880             {TRUE,"password",NULL,Uri_PROPERTY_PASSWORD,S_OK,FALSE},
4881             {TRUE,"?query=x",NULL,Uri_PROPERTY_QUERY,S_OK,FALSE},
4882             {TRUE,"username",NULL,Uri_PROPERTY_USER_NAME,S_OK,FALSE}
4883         },
4884         {FALSE},
4885         0,S_OK,FALSE,
4886         0,S_OK,FALSE,
4887         0,0,0,S_OK,FALSE,
4888         {
4889             {"http://username:password@google.com/?query=x#fragment",S_OK},
4890             {"username:password@google.com",S_OK},
4891             {"http://google.com/?query=x#fragment",S_OK},
4892             {"google.com",S_OK},
4893             {"",S_FALSE},
4894             {"#fragment",S_OK},
4895             {"google.com",S_OK},
4896             {"password",S_OK},
4897             {"/",S_OK},
4898             {"/?query=x",S_OK},
4899             {"?query=x",S_OK},
4900             {"http://username:password@google.com/?query=x#fragment",S_OK},
4901             {"http",S_OK},
4902             {"username:password",S_OK},
4903             {"username",S_OK}
4904         },
4905         {
4906             {Uri_HOST_DNS,S_OK},
4907             {80,S_OK},
4908             {URL_SCHEME_HTTP,S_OK},
4909             {URLZONE_INVALID,E_NOTIMPL}
4910         }
4911     },
4912     {   "http://google.com/",0,S_OK,FALSE,
4913         {
4914             {TRUE,"test",NULL,Uri_PROPERTY_SCHEME_NAME,S_OK,FALSE}
4915         },
4916         {TRUE,TRUE,120,S_OK,FALSE},
4917         0,S_OK,FALSE,
4918         0,S_OK,FALSE,
4919         0,0,0,S_OK,FALSE,
4920         {
4921             {"test://google.com:120/",S_OK},
4922             {"google.com:120",S_OK},
4923             {"test://google.com:120/",S_OK},
4924             {"google.com",S_OK},
4925             {"",S_FALSE},
4926             {"",S_FALSE},
4927             {"google.com",S_OK},
4928             {"",S_FALSE},
4929             {"/",S_OK},
4930             {"/",S_OK},
4931             {"",S_FALSE},
4932             {"test://google.com:120/",S_OK},
4933             {"test",S_OK},
4934             {"",S_FALSE},
4935             {"",S_FALSE}
4936         },
4937         {
4938             {Uri_HOST_DNS,S_OK},
4939             {120,S_OK},
4940             {URL_SCHEME_UNKNOWN,S_OK},
4941             {URLZONE_INVALID,E_NOTIMPL}
4942         }
4943     },
4944     {   "/Test/test dir",Uri_CREATE_ALLOW_RELATIVE,S_OK,FALSE,
4945         {
4946             {TRUE,"http",NULL,Uri_PROPERTY_SCHEME_NAME,S_OK,FALSE},
4947             {TRUE,"::192.2.3.4",NULL,Uri_PROPERTY_HOST,S_OK,FALSE},
4948             {TRUE,NULL,NULL,Uri_PROPERTY_PATH,S_OK,FALSE}
4949         },
4950         {FALSE},
4951         0,S_OK,FALSE,
4952         0,S_OK,FALSE,
4953         0,0,0,S_OK,FALSE,
4954         {
4955             {"http://[::192.2.3.4]/",S_OK},
4956             {"[::192.2.3.4]",S_OK},
4957             {"http://[::192.2.3.4]/",S_OK},
4958             {"",S_FALSE},
4959             {"",S_FALSE},
4960             {"",S_FALSE},
4961             {"::192.2.3.4",S_OK},
4962             {"",S_FALSE},
4963             {"/",S_OK},
4964             {"/",S_OK},
4965             {"",S_FALSE},
4966             {"http://[::192.2.3.4]/",S_OK},
4967             {"http",S_OK},
4968             {"",S_FALSE},
4969             {"",S_FALSE}
4970         },
4971         {
4972             {Uri_HOST_IPV6,S_OK},
4973             {80,S_OK},
4974             {URL_SCHEME_HTTP,S_OK},
4975             {URLZONE_INVALID,E_NOTIMPL}
4976         }
4977     },
4978     {   "http://google.com/",0,S_OK,FALSE,
4979         {
4980             {TRUE,"Frag","#Frag",Uri_PROPERTY_FRAGMENT,S_OK,FALSE}
4981         },
4982         {FALSE},
4983         0,S_OK,FALSE,
4984         0,S_OK,FALSE,
4985         0,0,0,S_OK,FALSE,
4986         {
4987             {"http://google.com/#Frag",S_OK},
4988             {"google.com",S_OK},
4989             {"http://google.com/#Frag",S_OK},
4990             {"google.com",S_OK},
4991             {"",S_FALSE},
4992             {"#Frag",S_OK},
4993             {"google.com",S_OK},
4994             {"",S_FALSE},
4995             {"/",S_OK},
4996             {"/",S_OK},
4997             {"",S_FALSE},
4998             {"http://google.com/#Frag",S_OK},
4999             {"http",S_OK},
5000             {"",S_FALSE},
5001             {"",S_FALSE}
5002         },
5003         {
5004             {Uri_HOST_DNS,S_OK},
5005             {80,S_OK},
5006             {URL_SCHEME_HTTP,S_OK},
5007             {URLZONE_INVALID,E_NOTIMPL}
5008         }
5009     },
5010     {   "http://google.com/",0,S_OK,FALSE,
5011         {
5012             {TRUE,"","#",Uri_PROPERTY_FRAGMENT,S_OK,FALSE},
5013         },
5014         {FALSE},
5015         0,S_OK,FALSE,
5016         0,S_OK,FALSE,
5017         0,0,0,S_OK,FALSE,
5018         {
5019             {"http://google.com/#",S_OK},
5020             {"google.com",S_OK},
5021             {"http://google.com/#",S_OK},
5022             {"google.com",S_OK},
5023             {"",S_FALSE},
5024             {"#",S_OK},
5025             {"google.com",S_OK},
5026             {"",S_FALSE},
5027             {"/",S_OK},
5028             {"/",S_OK},
5029             {"",S_FALSE},
5030             {"http://google.com/#",S_OK},
5031             {"http",S_OK},
5032             {"",S_FALSE},
5033             {"",S_FALSE}
5034         },
5035         {
5036             {Uri_HOST_DNS,S_OK},
5037             {80,S_OK},
5038             {URL_SCHEME_HTTP,S_OK},
5039             {URLZONE_INVALID,E_NOTIMPL}
5040         }
5041     },
5042     {   "http://google.com/",0,S_OK,FALSE,
5043         {
5044             {TRUE,":password",NULL,Uri_PROPERTY_PASSWORD,S_OK,FALSE}
5045         },
5046         {FALSE},
5047         0,S_OK,FALSE,
5048         0,S_OK,FALSE,
5049         0,0,0,S_OK,FALSE,
5050         {
5051             {"http://::password@google.com/",S_OK},
5052             {"::password@google.com",S_OK},
5053             {"http://google.com/",S_OK},
5054             {"google.com",S_OK},
5055             {"",S_FALSE},
5056             {"",S_FALSE},
5057             {"google.com",S_OK},
5058             {":password",S_OK},
5059             {"/",S_OK},
5060             {"/",S_OK},
5061             {"",S_FALSE},
5062             {"http://::password@google.com/",S_OK},
5063             {"http",S_OK},
5064             {"::password",S_OK},
5065             {"",S_FALSE}
5066         },
5067         {
5068             {Uri_HOST_DNS,S_OK},
5069             {80,S_OK},
5070             {URL_SCHEME_HTTP,S_OK},
5071             {URLZONE_INVALID,E_NOTIMPL}
5072         }
5073     },
5074     {   "test/test",Uri_CREATE_ALLOW_RELATIVE,S_OK,FALSE,
5075         {
5076             {TRUE,"password",NULL,Uri_PROPERTY_PASSWORD,S_OK,FALSE}
5077         },
5078         {FALSE},
5079         Uri_CREATE_ALLOW_RELATIVE,S_OK,FALSE,
5080         0,S_OK,FALSE,
5081         Uri_CREATE_ALLOW_RELATIVE,0,0,S_OK,FALSE,
5082         {
5083             {":password@test/test",S_OK},
5084             {":password@",S_OK},
5085             {":password@test/test",S_OK},
5086             {"",S_FALSE},
5087             {"",S_FALSE},
5088             {"",S_FALSE},
5089             {"",S_FALSE},
5090             {"password",S_OK},
5091             {"test/test",S_OK},
5092             {"test/test",S_OK},
5093             {"",S_FALSE},
5094             {":password@test/test",S_OK},
5095             {"",S_FALSE},
5096             {":password",S_OK},
5097             {"",S_FALSE}
5098         },
5099         {
5100             {Uri_HOST_UNKNOWN,S_OK},
5101             {0,S_FALSE},
5102             {URL_SCHEME_UNKNOWN,S_OK},
5103             {URLZONE_INVALID,E_NOTIMPL}
5104         }
5105     },
5106     {   "http://google.com/",0,S_OK,FALSE,
5107         {
5108             {TRUE,"test/test",NULL,Uri_PROPERTY_PATH,S_OK,FALSE},
5109         },
5110         {FALSE},
5111         0,S_OK,FALSE,
5112         0,S_OK,FALSE,
5113         0,0,0,S_OK,FALSE,
5114         {
5115             {"http://google.com/test/test",S_OK},
5116             {"google.com",S_OK},
5117             {"http://google.com/test/test",S_OK},
5118             {"google.com",S_OK},
5119             {"",S_FALSE},
5120             {"",S_FALSE},
5121             {"google.com",S_OK},
5122             {"",S_FALSE},
5123             {"/test/test",S_OK},
5124             {"/test/test",S_OK},
5125             {"",S_FALSE},
5126             {"http://google.com/test/test",S_OK},
5127             {"http",S_OK},
5128             {"",S_FALSE},
5129             {"",S_FALSE}
5130         },
5131         {
5132             {Uri_HOST_DNS,S_OK},
5133             {80,S_OK},
5134             {URL_SCHEME_HTTP,S_OK},
5135             {URLZONE_INVALID,E_NOTIMPL}
5136         }
5137     },
5138     {   "zip:testing/test",0,S_OK,FALSE,
5139         {
5140             {TRUE,"test",NULL,Uri_PROPERTY_PATH,S_OK,FALSE},
5141         },
5142         {FALSE},
5143         0,S_OK,FALSE,
5144         0,S_OK,FALSE,
5145         0,0,0,S_OK,FALSE,
5146         {
5147             {"zip:test",S_OK},
5148             {"",S_FALSE},
5149             {"zip:test",S_OK},
5150             {"",S_FALSE},
5151             {"",S_FALSE},
5152             {"",S_FALSE},
5153             {"",S_FALSE},
5154             {"",S_FALSE},
5155             {"test",S_OK},
5156             {"test",S_OK},
5157             {"",S_FALSE},
5158             {"zip:test",S_OK},
5159             {"zip",S_OK},
5160             {"",S_FALSE},
5161             {"",S_FALSE}
5162         },
5163         {
5164             {Uri_HOST_UNKNOWN,S_OK},
5165             {0,S_FALSE},
5166             {URL_SCHEME_UNKNOWN,S_OK},
5167             {URLZONE_INVALID,E_NOTIMPL}
5168         }
5169     },
5170     {   "http://google.com/",0,S_OK,FALSE,
5171         {
5172             {FALSE},
5173         },
5174         /* 555 will be returned from GetPort even though FALSE was passed as the hasPort parameter. */
5175         {TRUE,FALSE,555,S_OK,FALSE},
5176         0,S_OK,FALSE,
5177         0,S_OK,FALSE,
5178         0,0,0,S_OK,FALSE,
5179         {
5180             {"http://google.com/",S_OK},
5181             {"google.com",S_OK},
5182             {"http://google.com/",S_OK},
5183             {"google.com",S_OK},
5184             {"",S_FALSE},
5185             {"",S_FALSE},
5186             {"google.com",S_OK},
5187             {"",S_FALSE},
5188             {"/",S_OK},
5189             {"/",S_OK},
5190             {"",S_FALSE},
5191             {"http://google.com/",S_OK},
5192             {"http",S_OK},
5193             {"",S_FALSE},
5194             {"",S_FALSE}
5195         },
5196         {
5197             {Uri_HOST_DNS,S_OK},
5198             /* Still returns 80, even though earlier the port was disabled. */
5199             {80,S_OK},
5200             {URL_SCHEME_HTTP,S_OK},
5201             {URLZONE_INVALID,E_NOTIMPL}
5202         }
5203     },
5204     {   "http://google.com/",0,S_OK,FALSE,
5205         {
5206             {FALSE},
5207         },
5208         /* Instead of getting "TRUE" back as the "hasPort" parameter in GetPort,
5209          * you'll get 122345 instead.
5210          */
5211         {TRUE,122345,222,S_OK,FALSE},
5212         0,S_OK,FALSE,
5213         0,S_OK,FALSE,
5214         0,0,0,S_OK,FALSE,
5215         {
5216             {"http://google.com:222/",S_OK},
5217             {"google.com:222",S_OK},
5218             {"http://google.com:222/",S_OK},
5219             {"google.com",S_OK},
5220             {"",S_FALSE},
5221             {"",S_FALSE},
5222             {"google.com",S_OK},
5223             {"",S_FALSE},
5224             {"/",S_OK},
5225             {"/",S_OK},
5226             {"",S_FALSE},
5227             {"http://google.com:222/",S_OK},
5228             {"http",S_OK},
5229             {"",S_FALSE},
5230             {"",S_FALSE}
5231         },
5232         {
5233             {Uri_HOST_DNS,S_OK},
5234             {222,S_OK},
5235             {URL_SCHEME_HTTP,S_OK},
5236             {URLZONE_INVALID,E_NOTIMPL}
5237         }
5238     },
5239     /* IUri's created with the IUriBuilder can have ports that exceed USHORT_MAX. */
5240     {   "http://google.com/",0,S_OK,FALSE,
5241         {
5242             {FALSE},
5243         },
5244         {TRUE,TRUE,999999,S_OK,FALSE},
5245         0,S_OK,FALSE,
5246         0,S_OK,FALSE,
5247         0,0,0,S_OK,FALSE,
5248         {
5249             {"http://google.com:999999/",S_OK},
5250             {"google.com:999999",S_OK},
5251             {"http://google.com:999999/",S_OK},
5252             {"google.com",S_OK},
5253             {"",S_FALSE},
5254             {"",S_FALSE},
5255             {"google.com",S_OK},
5256             {"",S_FALSE},
5257             {"/",S_OK},
5258             {"/",S_OK},
5259             {"",S_FALSE},
5260             {"http://google.com:999999/",S_OK},
5261             {"http",S_OK},
5262             {"",S_FALSE},
5263             {"",S_FALSE}
5264         },
5265         {
5266             {Uri_HOST_DNS,S_OK},
5267             {999999,S_OK},
5268             {URL_SCHEME_HTTP,S_OK},
5269             {URLZONE_INVALID,E_NOTIMPL}
5270         }
5271     },
5272     {   "http://google.com/",0,S_OK,FALSE,
5273         {
5274             {TRUE,"test","?test",Uri_PROPERTY_QUERY,S_OK,FALSE},
5275         },
5276
5277         {FALSE},
5278         0,S_OK,FALSE,
5279         0,S_OK,FALSE,
5280         0,0,0,S_OK,FALSE,
5281         {
5282             {"http://google.com/?test",S_OK},
5283             {"google.com",S_OK},
5284             {"http://google.com/?test",S_OK},
5285             {"google.com",S_OK},
5286             {"",S_FALSE},
5287             {"",S_FALSE},
5288             {"google.com",S_OK},
5289             {"",S_FALSE},
5290             {"/",S_OK},
5291             {"/?test",S_OK},
5292             {"?test",S_OK},
5293             {"http://google.com/?test",S_OK},
5294             {"http",S_OK},
5295             {"",S_FALSE},
5296             {"",S_FALSE}
5297         },
5298         {
5299             {Uri_HOST_DNS,S_OK},
5300             {80,S_OK},
5301             {URL_SCHEME_HTTP,S_OK},
5302             {URLZONE_INVALID,E_NOTIMPL}
5303         }
5304     },
5305     {   "http://:password@google.com/",0,S_OK,FALSE,
5306         {
5307             {FALSE},
5308         },
5309         {FALSE},
5310         0,S_OK,FALSE,
5311         0,S_OK,FALSE,
5312         0,0,0,S_OK,FALSE,
5313         {
5314             {"http://:password@google.com/",S_OK},
5315             {":password@google.com",S_OK},
5316             {"http://google.com/",S_OK},
5317             {"google.com",S_OK},
5318             {"",S_FALSE},
5319             {"",S_FALSE},
5320             {"google.com",S_OK},
5321             {"password",S_OK},
5322             {"/",S_OK},
5323             {"/",S_OK},
5324             {"",S_FALSE},
5325             {"http://:password@google.com/",S_OK},
5326             {"http",S_OK},
5327             {":password",S_OK},
5328             {"",S_FALSE}
5329         },
5330         {
5331             {Uri_HOST_DNS,S_OK},
5332             {80,S_OK},
5333             {URL_SCHEME_HTTP,S_OK},
5334             {URLZONE_INVALID,E_NOTIMPL}
5335         }
5336     },
5337     /* IUriBuilder doesn't need a base IUri to build a IUri. */
5338     {   NULL,0,S_OK,FALSE,
5339         {
5340             {TRUE,"http",NULL,Uri_PROPERTY_SCHEME_NAME,S_OK,FALSE},
5341             {TRUE,"google.com",NULL,Uri_PROPERTY_HOST,S_OK,FALSE}
5342         },
5343         {FALSE},
5344         0,S_OK,FALSE,
5345         0,S_OK,FALSE,
5346         0,0,0,S_OK,FALSE,
5347         {
5348             {"http://google.com/",S_OK},
5349             {"google.com",S_OK},
5350             {"http://google.com/",S_OK},
5351             {"google.com",S_OK},
5352             {"",S_FALSE},
5353             {"",S_FALSE},
5354             {"google.com",S_OK},
5355             {"",S_FALSE},
5356             {"/",S_OK},
5357             {"/",S_OK},
5358             {"",S_FALSE},
5359             {"http://google.com/",S_OK},
5360             {"http",S_OK},
5361             {"",S_FALSE},
5362             {"",S_FALSE}
5363         },
5364         {
5365             {Uri_HOST_DNS,S_OK},
5366             {80,S_OK},
5367             {URL_SCHEME_HTTP,S_OK},
5368             {URLZONE_INVALID,E_NOTIMPL}
5369         }
5370     },
5371     /* Can't set the scheme name to NULL. */
5372     {   "zip://google.com/",0,S_OK,FALSE,
5373         {
5374             {TRUE,NULL,"zip",Uri_PROPERTY_SCHEME_NAME,E_INVALIDARG,FALSE}
5375         },
5376         {FALSE},
5377         0,S_OK,FALSE,
5378         0,S_OK,FALSE,
5379         0,0,0,S_OK,FALSE,
5380         {
5381             {"zip://google.com/",S_OK},
5382             {"google.com",S_OK},
5383             {"zip://google.com/",S_OK},
5384             {"google.com",S_OK},
5385             {"",S_FALSE},
5386             {"",S_FALSE},
5387             {"google.com",S_OK},
5388             {"",S_FALSE},
5389             {"/",S_OK},
5390             {"/",S_OK},
5391             {"",S_FALSE},
5392             {"zip://google.com/",S_OK},
5393             {"zip",S_OK},
5394             {"",S_FALSE},
5395             {"",S_FALSE}
5396         },
5397         {
5398             {Uri_HOST_DNS,S_OK},
5399             {0,S_FALSE},
5400             {URL_SCHEME_UNKNOWN,S_OK},
5401             {URLZONE_INVALID,E_NOTIMPL}
5402         }
5403     },
5404     /* Can't set the scheme name to an empty string. */
5405     {   "zip://google.com/",0,S_OK,FALSE,
5406         {
5407             {TRUE,"","zip",Uri_PROPERTY_SCHEME_NAME,E_INVALIDARG,FALSE}
5408         },
5409         {FALSE},
5410         0,S_OK,FALSE,
5411         0,S_OK,FALSE,
5412         0,0,0,S_OK,FALSE,
5413         {
5414             {"zip://google.com/",S_OK},
5415             {"google.com",S_OK},
5416             {"zip://google.com/",S_OK},
5417             {"google.com",S_OK},
5418             {"",S_FALSE},
5419             {"",S_FALSE},
5420             {"google.com",S_OK},
5421             {"",S_FALSE},
5422             {"/",S_OK},
5423             {"/",S_OK},
5424             {"",S_FALSE},
5425             {"zip://google.com/",S_OK},
5426             {"zip",S_OK},
5427             {"",S_FALSE},
5428             {"",S_FALSE}
5429         },
5430         {
5431             {Uri_HOST_DNS,S_OK},
5432             {0,S_FALSE},
5433             {URL_SCHEME_UNKNOWN,S_OK},
5434             {URLZONE_INVALID,E_NOTIMPL}
5435         }
5436     },
5437     /* -1 to CreateUri makes it use the same flags as the base IUri was created with.
5438      * CreateUriSimple always uses the flags the base IUri was created with (if any).
5439      */
5440     {   "http://google.com/../../",Uri_CREATE_NO_CANONICALIZE,S_OK,FALSE,
5441         {{FALSE}},
5442         {FALSE},
5443         -1,S_OK,FALSE,
5444         0,S_OK,FALSE,
5445         0,UriBuilder_USE_ORIGINAL_FLAGS,0,S_OK,FALSE,
5446         {
5447             {"http://google.com/../../",S_OK},
5448             {"google.com",S_OK},
5449             {"http://google.com/../../",S_OK},
5450             {"google.com",S_OK},
5451             {"",S_FALSE},
5452             {"",S_FALSE},
5453             {"google.com",S_OK},
5454             {"",S_FALSE},
5455             {"/../../",S_OK},
5456             {"/../../",S_OK},
5457             {"",S_FALSE},
5458             {"http://google.com/../../",S_OK},
5459             {"http",S_OK},
5460             {"",S_FALSE},
5461             {"",S_FALSE}
5462         },
5463         {
5464             {Uri_HOST_DNS,S_OK},
5465             {80,S_OK},
5466             {URL_SCHEME_HTTP,S_OK},
5467             {URLZONE_INVALID,E_NOTIMPL}
5468         }
5469     },
5470     {   "http://google.com/",0,S_OK,FALSE,
5471         {
5472             {TRUE,"#Fr<|>g",NULL,Uri_PROPERTY_FRAGMENT,S_OK,FALSE}
5473         },
5474         {FALSE},
5475         -1,S_OK,FALSE,
5476         0,S_OK,FALSE,
5477         Uri_CREATE_NO_DECODE_EXTRA_INFO,UriBuilder_USE_ORIGINAL_FLAGS,0,S_OK,FALSE,
5478         {
5479             {"http://google.com/#Fr%3C%7C%3Eg",S_OK},
5480             {"google.com",S_OK},
5481             {"http://google.com/#Fr%3C%7C%3Eg",S_OK},
5482             {"google.com",S_OK},
5483             {"",S_FALSE},
5484             {"#Fr%3C%7C%3Eg",S_OK},
5485             {"google.com",S_OK},
5486             {"",S_FALSE},
5487             {"/",S_OK},
5488             {"/",S_OK},
5489             {"",S_FALSE},
5490             {"http://google.com/#Fr<|>g",S_OK},
5491             {"http",S_OK},
5492             {"",S_FALSE},
5493             {"",S_FALSE}
5494         },
5495         {
5496             {Uri_HOST_DNS,S_OK},
5497             {80,S_OK},
5498             {URL_SCHEME_HTTP,S_OK},
5499             {URLZONE_INVALID,E_NOTIMPL}
5500         }
5501     },
5502     {   "http://google.com/",0,S_OK,FALSE,
5503         {
5504             {TRUE,"#Fr<|>g",NULL,Uri_PROPERTY_FRAGMENT,S_OK,FALSE}
5505         },
5506         {FALSE},
5507         Uri_CREATE_CANONICALIZE|Uri_CREATE_NO_CANONICALIZE,E_INVALIDARG,FALSE,
5508         0,S_OK,FALSE,
5509         Uri_CREATE_CANONICALIZE|Uri_CREATE_NO_CANONICALIZE,UriBuilder_USE_ORIGINAL_FLAGS,0,S_OK,FALSE,
5510         {
5511             {"http://google.com/#Fr%3C%7C%3Eg",S_OK},
5512             {"google.com",S_OK},
5513             {"http://google.com/#Fr%3C%7C%3Eg",S_OK},
5514             {"google.com",S_OK},
5515             {"",S_FALSE},
5516             {"#Fr%3C%7C%3Eg",S_OK},
5517             {"google.com",S_OK},
5518             {"",S_FALSE},
5519             {"/",S_OK},
5520             {"/",S_OK},
5521             {"",S_FALSE},
5522             {"http://google.com/#Fr<|>g",S_OK},
5523             {"http",S_OK},
5524             {"",S_FALSE},
5525             {"",S_FALSE}
5526         },
5527         {
5528             {Uri_HOST_DNS,S_OK},
5529             {80,S_OK},
5530             {URL_SCHEME_HTTP,S_OK},
5531             {URLZONE_INVALID,E_NOTIMPL}
5532         }
5533     },
5534     {   NULL,0,S_OK,FALSE,
5535         {
5536             {TRUE,"/test/test/",NULL,Uri_PROPERTY_PATH,S_OK,FALSE},
5537             {TRUE,"#Fr<|>g",NULL,Uri_PROPERTY_FRAGMENT,S_OK,FALSE}
5538         },
5539         {FALSE},
5540         0,INET_E_INVALID_URL,FALSE,
5541         0,INET_E_INVALID_URL,FALSE,
5542         0,0,0,INET_E_INVALID_URL,FALSE
5543     },
5544     {   "http://google.com/",0,S_OK,FALSE,
5545         {
5546             {TRUE,"ht%xxtp",NULL,Uri_PROPERTY_SCHEME_NAME,S_OK,FALSE}
5547         },
5548         {FALSE},
5549         0,INET_E_INVALID_URL,FALSE,
5550         0,INET_E_INVALID_URL,FALSE,
5551         0,0,0,INET_E_INVALID_URL,FALSE
5552     },
5553     /* File scheme's can't have a username set. */
5554     {   "file://google.com/",0,S_OK,FALSE,
5555         {
5556             {TRUE,"username",NULL,Uri_PROPERTY_USER_NAME,S_OK,FALSE}
5557         },
5558         {FALSE},
5559         0,INET_E_INVALID_URL,FALSE,
5560         0,INET_E_INVALID_URL,FALSE,
5561         0,0,0,INET_E_INVALID_URL,FALSE
5562     },
5563     /* File schemes can't have a password set. */
5564     {   "file://google.com/",0,S_OK,FALSE,
5565         {
5566             {TRUE,"password",NULL,Uri_PROPERTY_PASSWORD,S_OK,FALSE}
5567         },
5568         {FALSE},
5569         0,INET_E_INVALID_URL,FALSE,
5570         0,INET_E_INVALID_URL,FALSE,
5571         0,0,0,INET_E_INVALID_URL,FALSE
5572     },
5573     /* UserName can't contain any character that is a delimeter for another
5574      * component that appears after it in a normal URI.
5575      */
5576     {   "http://google.com/",0,S_OK,FALSE,
5577         {
5578             {TRUE,"user:pass",NULL,Uri_PROPERTY_USER_NAME,S_OK,FALSE}
5579         },
5580         {FALSE},
5581         0,INET_E_INVALID_URL,FALSE,
5582         0,INET_E_INVALID_URL,FALSE,
5583         0,0,0,INET_E_INVALID_URL,FALSE
5584     },
5585     {   "http://google.com/",0,S_OK,FALSE,
5586         {
5587             {TRUE,"user@google.com",NULL,Uri_PROPERTY_USER_NAME,S_OK,FALSE}
5588         },
5589         {FALSE},
5590         0,INET_E_INVALID_URL,FALSE,
5591         0,INET_E_INVALID_URL,FALSE,
5592         0,0,0,INET_E_INVALID_URL,FALSE
5593     },
5594     {   "http://google.com/",0,S_OK,FALSE,
5595         {
5596             {TRUE,"user/path",NULL,Uri_PROPERTY_USER_NAME,S_OK,FALSE}
5597         },
5598         {FALSE},
5599         0,INET_E_INVALID_URL,FALSE,
5600         0,INET_E_INVALID_URL,FALSE,
5601         0,0,0,INET_E_INVALID_URL,FALSE
5602     },
5603     {   "http://google.com/",0,S_OK,FALSE,
5604         {
5605             {TRUE,"user?Query",NULL,Uri_PROPERTY_USER_NAME,S_OK,FALSE}
5606         },
5607         {FALSE},
5608         0,INET_E_INVALID_URL,FALSE,
5609         0,INET_E_INVALID_URL,FALSE,
5610         0,0,0,INET_E_INVALID_URL,FALSE
5611     },
5612     {   "http://google.com/",0,S_OK,FALSE,
5613         {
5614             {TRUE,"user#Frag",NULL,Uri_PROPERTY_USER_NAME,S_OK,FALSE}
5615         },
5616         {FALSE},
5617         0,INET_E_INVALID_URL,FALSE,
5618         0,INET_E_INVALID_URL,FALSE,
5619         0,0,0,INET_E_INVALID_URL,FALSE
5620     },
5621     {   "http://google.com/",0,S_OK,FALSE,
5622         {
5623             {TRUE,"pass@google.com",NULL,Uri_PROPERTY_PASSWORD,S_OK,FALSE}
5624         },
5625         {FALSE},
5626         0,INET_E_INVALID_URL,FALSE,
5627         0,INET_E_INVALID_URL,FALSE,
5628         0,0,0,INET_E_INVALID_URL,FALSE
5629     },
5630     {   "http://google.com/",0,S_OK,FALSE,
5631         {
5632             {TRUE,"pass/path",NULL,Uri_PROPERTY_PASSWORD,S_OK,FALSE}
5633         },
5634         {FALSE},
5635         0,INET_E_INVALID_URL,FALSE,
5636         0,INET_E_INVALID_URL,FALSE,
5637         0,0,0,INET_E_INVALID_URL,FALSE
5638     },
5639     {   "http://google.com/",0,S_OK,FALSE,
5640         {
5641             {TRUE,"pass?query",NULL,Uri_PROPERTY_PASSWORD,S_OK,FALSE}
5642         },
5643         {FALSE},
5644         0,INET_E_INVALID_URL,FALSE,
5645         0,INET_E_INVALID_URL,FALSE,
5646        0,0,0,INET_E_INVALID_URL,FALSE
5647     },
5648     {   "http://google.com/",0,S_OK,FALSE,
5649         {
5650             {TRUE,"pass#frag",NULL,Uri_PROPERTY_PASSWORD,S_OK,FALSE}
5651         },
5652         {FALSE},
5653         0,INET_E_INVALID_URL,FALSE,
5654         0,INET_E_INVALID_URL,FALSE,
5655         0,0,0,INET_E_INVALID_URL,FALSE
5656     },
5657     {   "http://google.com/",0,S_OK,FALSE,
5658         {
5659             {TRUE,"winehq.org/test",NULL,Uri_PROPERTY_HOST,S_OK,FALSE}
5660         },
5661         {FALSE},
5662         0,INET_E_INVALID_URL,FALSE,
5663         0,INET_E_INVALID_URL,FALSE,
5664         0,0,0,INET_E_INVALID_URL,FALSE
5665     },
5666     {   "http://google.com/",0,S_OK,FALSE,
5667         {
5668             {TRUE,"winehq.org?test",NULL,Uri_PROPERTY_HOST,S_OK,FALSE}
5669         },
5670         {FALSE},
5671         0,INET_E_INVALID_URL,FALSE,
5672         0,INET_E_INVALID_URL,FALSE,
5673         0,0,0,INET_E_INVALID_URL,FALSE
5674     },
5675     {   "http://google.com/",0,S_OK,FALSE,
5676         {
5677             {TRUE,"winehq.org#test",NULL,Uri_PROPERTY_HOST,S_OK,FALSE}
5678         },
5679         {FALSE},
5680         0,INET_E_INVALID_URL,FALSE,
5681         0,INET_E_INVALID_URL,FALSE,
5682         0,0,0,INET_E_INVALID_URL,FALSE
5683     },
5684     /* Hostname is allowed to contain a ':' (even for known scheme types). */
5685     {   "http://google.com/",0,S_OK,FALSE,
5686         {
5687             {TRUE,"winehq.org:test",NULL,Uri_PROPERTY_HOST,S_OK,FALSE},
5688         },
5689         {FALSE},
5690         0,S_OK,FALSE,
5691         0,S_OK,FALSE,
5692         0,0,0,S_OK,FALSE,
5693         {
5694             {"http://winehq.org:test/",S_OK},
5695             {"winehq.org:test",S_OK},
5696             {"http://winehq.org:test/",S_OK},
5697             {"winehq.org:test",S_OK},
5698             {"",S_FALSE},
5699             {"",S_FALSE},
5700             {"winehq.org:test",S_OK},
5701             {"",S_FALSE},
5702             {"/",S_OK},
5703             {"/",S_OK},
5704             {"",S_FALSE},
5705             {"http://winehq.org:test/",S_OK},
5706             {"http",S_OK},
5707             {"",S_FALSE},
5708             {"",S_FALSE}
5709         },
5710         {
5711             {Uri_HOST_DNS,S_OK},
5712             {80,S_OK},
5713             {URL_SCHEME_HTTP,S_OK},
5714             {URLZONE_INVALID,E_NOTIMPL}
5715         }
5716     },
5717     /* Can't set the host name to NULL. */
5718     {   "http://google.com/",0,S_OK,FALSE,
5719         {
5720             {TRUE,NULL,"google.com",Uri_PROPERTY_HOST,E_INVALIDARG,FALSE}
5721         },
5722         {FALSE},
5723         0,S_OK,FALSE,
5724         0,S_OK,FALSE,
5725         0,0,0,S_OK,FALSE,
5726         {
5727             {"http://google.com/",S_OK},
5728             {"google.com",S_OK},
5729             {"http://google.com/",S_OK},
5730             {"google.com",S_OK},
5731             {"",S_FALSE},
5732             {"",S_FALSE},
5733             {"google.com",S_OK},
5734             {"",S_FALSE},
5735             {"/",S_OK},
5736             {"/",S_OK},
5737             {"",S_FALSE},
5738             {"http://google.com/",S_OK},
5739             {"http",S_OK},
5740             {"",S_FALSE},
5741             {"",S_FALSE}
5742         },
5743         {
5744             {Uri_HOST_DNS,S_OK},
5745             {80,S_OK},
5746             {URL_SCHEME_HTTP,S_OK},
5747             {URLZONE_INVALID,E_NOTIMPL}
5748         }
5749     },
5750     /* Can set the host name to an empty string. */
5751     {   "http://google.com/",0,S_OK,FALSE,
5752         {
5753             {TRUE,"",NULL,Uri_PROPERTY_HOST,S_OK,FALSE}
5754         },
5755         {FALSE},
5756         0,S_OK,FALSE,
5757         0,S_OK,FALSE,
5758         0,0,0,S_OK,FALSE,
5759         {
5760             {"http:///",S_OK},
5761             {"",S_OK},
5762             {"http:///",S_OK},
5763             {"",S_FALSE},
5764             {"",S_FALSE},
5765             {"",S_FALSE},
5766             {"",S_OK},
5767             {"",S_FALSE},
5768             {"/",S_OK},
5769             {"/",S_OK},
5770             {"",S_FALSE},
5771             {"http:///",S_OK},
5772             {"http",S_OK},
5773             {"",S_FALSE},
5774             {"",S_FALSE}
5775         },
5776         {
5777             {Uri_HOST_UNKNOWN,S_OK},
5778             {80,S_OK},
5779             {URL_SCHEME_HTTP,S_OK},
5780             {URLZONE_INVALID,E_NOTIMPL}
5781         }
5782     },
5783     {   "http://google.com/",0,S_OK,FALSE,
5784         {
5785             {TRUE,"/path?query",NULL,Uri_PROPERTY_PATH,S_OK,FALSE}
5786         },
5787         {FALSE},
5788         0,INET_E_INVALID_URL,FALSE,
5789         0,INET_E_INVALID_URL,FALSE,
5790         0,0,0,INET_E_INVALID_URL,FALSE
5791     },
5792     {   "http://google.com/",0,S_OK,FALSE,
5793         {
5794             {TRUE,"/path#test",NULL,Uri_PROPERTY_PATH,S_OK,FALSE}
5795         },
5796         {FALSE},
5797         0,INET_E_INVALID_URL,FALSE,
5798         0,INET_E_INVALID_URL,FALSE,
5799         0,0,0,INET_E_INVALID_URL,FALSE
5800     },
5801     {   "http://google.com/",0,S_OK,FALSE,
5802         {
5803             {TRUE,"?path#test",NULL,Uri_PROPERTY_QUERY,S_OK,FALSE}
5804         },
5805         {FALSE},
5806         0,INET_E_INVALID_URL,FALSE,
5807         0,INET_E_INVALID_URL,FALSE,
5808         0,0,0,INET_E_INVALID_URL,FALSE
5809     },
5810     {   "file:///c:/dir/file.html",0,S_OK,FALSE,
5811         {
5812             {TRUE,NULL,NULL,Uri_PROPERTY_FRAGMENT,S_OK},
5813         },
5814         {FALSE},
5815         0,S_OK,FALSE,
5816         0,S_OK,FALSE,
5817         0,0,0,S_OK,FALSE,
5818         {
5819             {"file:///c:/dir/file.html",S_OK},
5820             {"",S_FALSE},
5821             {"file:///c:/dir/file.html",S_OK},
5822             {"",S_FALSE},
5823             {".html",S_OK},
5824             {"",S_FALSE},
5825             {"",S_FALSE},
5826             {"",S_FALSE},
5827             {"/c:/dir/file.html",S_OK},
5828             {"/c:/dir/file.html",S_OK},
5829             {"",S_FALSE},
5830             {"file:///c:/dir/file.html",S_OK},
5831             {"file",S_OK},
5832             {"",S_FALSE},
5833             {"",S_FALSE}
5834         },
5835         {
5836             {Uri_HOST_UNKNOWN,S_OK},
5837             {0,S_FALSE},
5838             {URL_SCHEME_FILE,S_OK},
5839             {URLZONE_INVALID,E_NOTIMPL}
5840         }
5841     },
5842     {   "file:///c:/dir/file.html",0,S_OK,FALSE,
5843         {
5844             {TRUE,"#",NULL,Uri_PROPERTY_FRAGMENT,S_OK},
5845         },
5846         {FALSE},
5847         0,S_OK,FALSE,
5848         0,S_OK,FALSE,
5849         0,0,0,S_OK,FALSE,
5850         {
5851             {"file:///c:/dir/file.html#",S_OK},
5852             {"",S_FALSE},
5853             {"file:///c:/dir/file.html#",S_OK},
5854             {"",S_FALSE},
5855             {".html",S_OK},
5856             {"#",S_OK},
5857             {"",S_FALSE},
5858             {"",S_FALSE},
5859             {"/c:/dir/file.html",S_OK},
5860             {"/c:/dir/file.html",S_OK},
5861             {"",S_FALSE},
5862             {"file:///c:/dir/file.html#",S_OK},
5863             {"file",S_OK},
5864             {"",S_FALSE},
5865             {"",S_FALSE}
5866         },
5867         {
5868             {Uri_HOST_UNKNOWN,S_OK},
5869             {0,S_FALSE},
5870             {URL_SCHEME_FILE,S_OK},
5871             {URLZONE_INVALID,E_NOTIMPL}
5872         }
5873     }
5874 };
5875
5876 typedef struct _uri_builder_remove_test {
5877     const char  *uri;
5878     DWORD       create_flags;
5879     HRESULT     create_builder_expected;
5880     BOOL        create_builder_todo;
5881
5882     DWORD       remove_properties;
5883     HRESULT     remove_expected;
5884     BOOL        remove_todo;
5885
5886     const char  *expected_uri;
5887     DWORD       expected_flags;
5888     HRESULT     expected_hres;
5889     BOOL        expected_todo;
5890 } uri_builder_remove_test;
5891
5892 static const uri_builder_remove_test uri_builder_remove_tests[] = {
5893     {   "http://google.com/test?test=y#Frag",0,S_OK,FALSE,
5894         Uri_HAS_FRAGMENT|Uri_HAS_PATH|Uri_HAS_QUERY,S_OK,FALSE,
5895         "http://google.com/",0,S_OK,FALSE
5896     },
5897     {   "http://user:pass@winehq.org/",0,S_OK,FALSE,
5898         Uri_HAS_USER_NAME|Uri_HAS_PASSWORD,S_OK,FALSE,
5899         "http://winehq.org/",0,S_OK,FALSE
5900     },
5901     {   "zip://google.com?Test=x",0,S_OK,FALSE,
5902         Uri_HAS_HOST,S_OK,FALSE,
5903         "zip:/?Test=x",0,S_OK,FALSE
5904     },
5905     /* Doesn't remove the whole userinfo component. */
5906     {   "http://username:pass@google.com/",0,S_OK,FALSE,
5907         Uri_HAS_USER_INFO,S_OK,FALSE,
5908         "http://username:pass@google.com/",0,S_OK,FALSE
5909     },
5910     /* Doesn't remove the domain. */
5911     {   "http://google.com/",0,S_OK,FALSE,
5912         Uri_HAS_DOMAIN,S_OK,FALSE,
5913         "http://google.com/",0,S_OK,FALSE
5914     },
5915     {   "http://google.com:120/",0,S_OK,FALSE,
5916         Uri_HAS_AUTHORITY,S_OK,FALSE,
5917         "http://google.com:120/",0,S_OK,FALSE
5918     },
5919     {   "http://google.com/test.com/",0,S_OK,FALSE,
5920         Uri_HAS_EXTENSION,S_OK,FALSE,
5921         "http://google.com/test.com/",0,S_OK,FALSE
5922     },
5923     {   "http://google.com/?test=x",0,S_OK,FALSE,
5924         Uri_HAS_PATH_AND_QUERY,S_OK,FALSE,
5925         "http://google.com/?test=x",0,S_OK,FALSE
5926     },
5927     /* Can't remove the scheme name. */
5928     {   "http://google.com/?test=x",0,S_OK,FALSE,
5929         Uri_HAS_SCHEME_NAME|Uri_HAS_QUERY,E_INVALIDARG,FALSE,
5930         "http://google.com/?test=x",0,S_OK,FALSE
5931     }
5932 };
5933
5934 typedef struct _uri_combine_str_property {
5935     const char  *value;
5936     HRESULT     expected;
5937     BOOL        todo;
5938     const char  *broken_value;
5939     const char  *value_ex;
5940 } uri_combine_str_property;
5941
5942 typedef struct _uri_combine_test {
5943     const char  *base_uri;
5944     DWORD       base_create_flags;
5945     const char  *relative_uri;
5946     DWORD       relative_create_flags;
5947     DWORD       combine_flags;
5948     HRESULT     expected;
5949     BOOL        todo;
5950
5951     uri_combine_str_property    str_props[URI_STR_PROPERTY_COUNT];
5952     uri_dword_property          dword_props[URI_DWORD_PROPERTY_COUNT];
5953 } uri_combine_test;
5954
5955 static const uri_combine_test uri_combine_tests[] = {
5956     {   "http://google.com/fun/stuff",0,
5957         "../not/fun/stuff",Uri_CREATE_ALLOW_RELATIVE,
5958         0,S_OK,FALSE,
5959         {
5960             {"http://google.com/not/fun/stuff",S_OK},
5961             {"google.com",S_OK},
5962             {"http://google.com/not/fun/stuff",S_OK},
5963             {"google.com",S_OK},
5964             {"",S_FALSE},
5965             {"",S_FALSE},
5966             {"google.com",S_OK},
5967             {"",S_FALSE},
5968             {"/not/fun/stuff",S_OK},
5969             {"/not/fun/stuff",S_OK},
5970             {"",S_FALSE},
5971             {"http://google.com/not/fun/stuff",S_OK},
5972             {"http",S_OK},
5973             {"",S_FALSE},
5974             {"",S_FALSE}
5975         },
5976         {
5977             {Uri_HOST_DNS,S_OK},
5978             {80,S_OK},
5979             {URL_SCHEME_HTTP,S_OK},
5980             {URLZONE_INVALID,E_NOTIMPL}
5981         }
5982     },
5983     {   "http://google.com/test",0,
5984         "zip://test.com/cool",0,
5985         0,S_OK,FALSE,
5986         {
5987             {"zip://test.com/cool",S_OK},
5988             {"test.com",S_OK},
5989             {"zip://test.com/cool",S_OK},
5990             {"test.com",S_OK},
5991             {"",S_FALSE},
5992             {"",S_FALSE},
5993             {"test.com",S_OK},
5994             {"",S_FALSE},
5995             {"/cool",S_OK},
5996             {"/cool",S_OK},
5997             {"",S_FALSE},
5998             {"zip://test.com/cool",S_OK},
5999             {"zip",S_OK},
6000             {"",S_FALSE},
6001             {"",S_FALSE}
6002         },
6003         {
6004             {Uri_HOST_DNS,S_OK},
6005             {0,S_FALSE},
6006             {URL_SCHEME_UNKNOWN,S_OK},
6007             {URLZONE_INVALID,E_NOTIMPL}
6008         }
6009     },
6010     {   "http://google.com/use/base/path",0,
6011         "?relative",Uri_CREATE_ALLOW_RELATIVE,
6012         0,S_OK,FALSE,
6013         {
6014             {"http://google.com/use/base/path?relative",S_OK},
6015             {"google.com",S_OK},
6016             {"http://google.com/use/base/path?relative",S_OK},
6017             {"google.com",S_OK},
6018             {"",S_FALSE},
6019             {"",S_FALSE},
6020             {"google.com",S_OK},
6021             {"",S_FALSE},
6022             {"/use/base/path",S_OK},
6023             {"/use/base/path?relative",S_OK},
6024             {"?relative",S_OK},
6025             {"http://google.com/use/base/path?relative",S_OK},
6026             {"http",S_OK},
6027             {"",S_FALSE},
6028             {"",S_FALSE}
6029         },
6030         {
6031             {Uri_HOST_DNS,S_OK},
6032             {80,S_OK},
6033             {URL_SCHEME_HTTP,S_OK},
6034             {URLZONE_INVALID,E_NOTIMPL}
6035         }
6036     },
6037     {   "http://google.com/path",0,
6038         "/test/../test/.././testing",Uri_CREATE_ALLOW_RELATIVE,
6039         0,S_OK,FALSE,
6040         {
6041             {"http://google.com/testing",S_OK},
6042             {"google.com",S_OK},
6043             {"http://google.com/testing",S_OK},
6044             {"google.com",S_OK},
6045             {"",S_FALSE},
6046             {"",S_FALSE},
6047             {"google.com",S_OK},
6048             {"",S_FALSE},
6049             {"/testing",S_OK},
6050             {"/testing",S_OK},
6051             {"",S_FALSE},
6052             {"http://google.com/testing",S_OK},
6053             {"http",S_OK},
6054             {"",S_FALSE},
6055             {"",S_FALSE}
6056         },
6057         {
6058             {Uri_HOST_DNS,S_OK},
6059             {80,S_OK},
6060             {URL_SCHEME_HTTP,S_OK},
6061             {URLZONE_INVALID,E_NOTIMPL}
6062         }
6063     },
6064     {   "http://google.com/path",0,
6065         "/test/../test/.././testing",Uri_CREATE_ALLOW_RELATIVE,
6066         URL_DONT_SIMPLIFY,S_OK,FALSE,
6067         {
6068             {"http://google.com:80/test/../test/.././testing",S_OK},
6069             {"google.com",S_OK},
6070             {"http://google.com:80/test/../test/.././testing",S_OK},
6071             {"google.com",S_OK},
6072             {"",S_FALSE},
6073             {"",S_FALSE},
6074             {"google.com",S_OK},
6075             {"",S_FALSE},
6076             {"/test/../test/.././testing",S_OK},
6077             {"/test/../test/.././testing",S_OK},
6078             {"",S_FALSE},
6079             {"http://google.com:80/test/../test/.././testing",S_OK},
6080             {"http",S_OK},
6081             {"",S_FALSE},
6082             {"",S_FALSE}
6083         },
6084         {
6085             {Uri_HOST_DNS,S_OK},
6086             {80,S_OK},
6087             {URL_SCHEME_HTTP,S_OK},
6088             {URLZONE_INVALID,E_NOTIMPL}
6089         }
6090     },
6091     {   "http://winehq.org/test/abc",0,
6092         "testing/abc/../test",Uri_CREATE_ALLOW_RELATIVE,
6093         0,S_OK,FALSE,
6094         {
6095             {"http://winehq.org/test/testing/test",S_OK},
6096             {"winehq.org",S_OK},
6097             {"http://winehq.org/test/testing/test",S_OK},
6098             {"winehq.org",S_OK},
6099             {"",S_FALSE},
6100             {"",S_FALSE},
6101             {"winehq.org",S_OK},
6102             {"",S_FALSE},
6103             {"/test/testing/test",S_OK},
6104             {"/test/testing/test",S_OK},
6105             {"",S_FALSE},
6106             {"http://winehq.org/test/testing/test",S_OK},
6107             {"http",S_OK},
6108             {"",S_FALSE},
6109             {"",S_FALSE}
6110         },
6111         {
6112             {Uri_HOST_DNS,S_OK},
6113             {80,S_OK},
6114             {URL_SCHEME_HTTP,S_OK},
6115             {URLZONE_INVALID,E_NOTIMPL}
6116         }
6117     },
6118     {   "http://winehq.org/test/abc",0,
6119         "testing/abc/../test",Uri_CREATE_ALLOW_RELATIVE,
6120         URL_DONT_SIMPLIFY,S_OK,FALSE,
6121         {
6122             {"http://winehq.org:80/test/testing/abc/../test",S_OK},
6123             /* Default port is hidden in the authority. */
6124             {"winehq.org",S_OK},
6125             {"http://winehq.org:80/test/testing/abc/../test",S_OK},
6126             {"winehq.org",S_OK},
6127             {"",S_FALSE},
6128             {"",S_FALSE},
6129             {"winehq.org",S_OK},
6130             {"",S_FALSE},
6131             {"/test/testing/abc/../test",S_OK},
6132             {"/test/testing/abc/../test",S_OK},
6133             {"",S_FALSE},
6134             {"http://winehq.org:80/test/testing/abc/../test",S_OK},
6135             {"http",S_OK},
6136             {"",S_FALSE},
6137             {"",S_FALSE}
6138         },
6139         {
6140             {Uri_HOST_DNS,S_OK},
6141             {80,S_OK},
6142             {URL_SCHEME_HTTP,S_OK},
6143             {URLZONE_INVALID,E_NOTIMPL}
6144         }
6145     },
6146     {   "http://winehq.org/test?query",0,
6147         "testing",Uri_CREATE_ALLOW_RELATIVE,
6148         0,S_OK,FALSE,
6149         {
6150             {"http://winehq.org/testing",S_OK},
6151             {"winehq.org",S_OK},
6152             {"http://winehq.org/testing",S_OK},
6153             {"winehq.org",S_OK},
6154             {"",S_FALSE},
6155             {"",S_FALSE},
6156             {"winehq.org",S_OK},
6157             {"",S_FALSE},
6158             {"/testing",S_OK},
6159             {"/testing",S_OK},
6160             {"",S_FALSE},
6161             {"http://winehq.org/testing",S_OK},
6162             {"http",S_OK},
6163             {"",S_FALSE},
6164             {"",S_FALSE}
6165         },
6166         {
6167             {Uri_HOST_DNS,S_OK},
6168             {80,S_OK},
6169             {URL_SCHEME_HTTP,S_OK},
6170             {URLZONE_INVALID,E_NOTIMPL}
6171         }
6172     },
6173     {   "http://winehq.org/test#frag",0,
6174         "testing",Uri_CREATE_ALLOW_RELATIVE,
6175         0,S_OK,FALSE,
6176         {
6177             {"http://winehq.org/testing",S_OK},
6178             {"winehq.org",S_OK},
6179             {"http://winehq.org/testing",S_OK},
6180             {"winehq.org",S_OK},
6181             {"",S_FALSE},
6182             {"",S_FALSE},
6183             {"winehq.org",S_OK},
6184             {"",S_FALSE},
6185             {"/testing",S_OK},
6186             {"/testing",S_OK},
6187             {"",S_FALSE},
6188             {"http://winehq.org/testing",S_OK},
6189             {"http",S_OK},
6190             {"",S_FALSE},
6191             {"",S_FALSE}
6192         },
6193         {
6194             {Uri_HOST_DNS,S_OK},
6195             {80,S_OK},
6196             {URL_SCHEME_HTTP,S_OK},
6197             {URLZONE_INVALID,E_NOTIMPL}
6198         }
6199     },
6200     {   "testing?query#frag",Uri_CREATE_ALLOW_RELATIVE,
6201         "test",Uri_CREATE_ALLOW_RELATIVE,
6202         0,S_OK,FALSE,
6203         {
6204             {"test",S_OK},
6205             {"",S_FALSE},
6206             {"test",S_OK},
6207             {"",S_FALSE},
6208             {"",S_FALSE},
6209             {"",S_FALSE},
6210             {"",S_FALSE},
6211             {"",S_FALSE},
6212             {"test",S_OK},
6213             {"test",S_OK},
6214             {"",S_FALSE},
6215             {"test",S_OK},
6216             {"",S_FALSE},
6217             {"",S_FALSE},
6218             {"",S_FALSE}
6219         },
6220         {
6221             {Uri_HOST_UNKNOWN,S_OK},
6222             {0,S_FALSE},
6223             {URL_SCHEME_UNKNOWN,S_OK},
6224             {URLZONE_INVALID,E_NOTIMPL}
6225         }
6226     },
6227     {   "file:///c:/test/test",0,
6228         "/testing.mp3",Uri_CREATE_ALLOW_RELATIVE,
6229         URL_FILE_USE_PATHURL,S_OK,FALSE,
6230         {
6231             {"file://c:\\testing.mp3",S_OK},
6232             {"",S_FALSE},
6233             {"file://c:\\testing.mp3",S_OK},
6234             {"",S_FALSE},
6235             {".mp3",S_OK},
6236             {"",S_FALSE},
6237             {"",S_FALSE},
6238             {"",S_FALSE},
6239             {"c:\\testing.mp3",S_OK},
6240             {"c:\\testing.mp3",S_OK},
6241             {"",S_FALSE},
6242             {"file://c:\\testing.mp3",S_OK},
6243             {"file",S_OK},
6244             {"",S_FALSE},
6245             {"",S_FALSE}
6246         },
6247         {
6248             {Uri_HOST_UNKNOWN,S_OK},
6249             {0,S_FALSE},
6250             {URL_SCHEME_FILE,S_OK},
6251             {URLZONE_INVALID,E_NOTIMPL}
6252         }
6253     },
6254     {   "file:///c:/test/test",0,
6255         "/testing.mp3",Uri_CREATE_ALLOW_RELATIVE,
6256         0,S_OK,FALSE,
6257         {
6258             {"file:///c:/testing.mp3",S_OK},
6259             {"",S_FALSE},
6260             {"file:///c:/testing.mp3",S_OK},
6261             {"",S_FALSE},
6262             {".mp3",S_OK},
6263             {"",S_FALSE},
6264             {"",S_FALSE},
6265             {"",S_FALSE},
6266             {"/c:/testing.mp3",S_OK},
6267             {"/c:/testing.mp3",S_OK},
6268             {"",S_FALSE},
6269             {"file:///c:/testing.mp3",S_OK},
6270             {"file",S_OK},
6271             {"",S_FALSE},
6272             {"",S_FALSE}
6273         },
6274         {
6275             {Uri_HOST_UNKNOWN,S_OK},
6276             {0,S_FALSE},
6277             {URL_SCHEME_FILE,S_OK},
6278             {URLZONE_INVALID,E_NOTIMPL}
6279         }
6280     },
6281     {   "file://test.com/test/test",0,
6282         "/testing.mp3",Uri_CREATE_ALLOW_RELATIVE,
6283         URL_FILE_USE_PATHURL,S_OK,FALSE,
6284         {
6285             {"file://\\\\test.com\\testing.mp3",S_OK},
6286             {"test.com",S_OK},
6287             {"file://\\\\test.com\\testing.mp3",S_OK},
6288             {"test.com",S_OK},
6289             {".mp3",S_OK},
6290             {"",S_FALSE},
6291             {"test.com",S_OK},
6292             {"",S_FALSE},
6293             {"\\testing.mp3",S_OK},
6294             {"\\testing.mp3",S_OK},
6295             {"",S_FALSE},
6296             {"file://\\\\test.com\\testing.mp3",S_OK},
6297             {"file",S_OK},
6298             {"",S_FALSE},
6299             {"",S_FALSE}
6300         },
6301         {
6302             {Uri_HOST_DNS,S_OK},
6303             {0,S_FALSE},
6304             {URL_SCHEME_FILE,S_OK},
6305             {URLZONE_INVALID,E_NOTIMPL}
6306         }
6307     },
6308     /* URL_DONT_SIMPLIFY has no effect. */
6309     {   "http://google.com/test",0,
6310         "zip://test.com/cool/../cool/test",0,
6311         URL_DONT_SIMPLIFY,S_OK,FALSE,
6312         {
6313             {"zip://test.com/cool/test",S_OK,FALSE,NULL,"zip://test.com/cool/../cool/test"},
6314             {"test.com",S_OK},
6315             {"zip://test.com/cool/test",S_OK,FALSE,NULL,"zip://test.com/cool/../cool/test"},
6316             {"test.com",S_OK},
6317             {"",S_FALSE},
6318             {"",S_FALSE},
6319             {"test.com",S_OK},
6320             {"",S_FALSE},
6321             {"/cool/test",S_OK,FALSE,NULL,"/cool/../cool/test"},
6322             {"/cool/test",S_OK,FALSE,NULL,"/cool/../cool/test"},
6323             {"",S_FALSE},
6324             /* The resulting IUri has the same Raw URI as the relative URI (only IE 8).
6325              * On IE 7 it reduces the path in the Raw URI.
6326              */
6327             {"zip://test.com/cool/../cool/test",S_OK,FALSE,"zip://test.com/cool/test"},
6328             {"zip",S_OK},
6329             {"",S_FALSE},
6330             {"",S_FALSE}
6331         },
6332         {
6333             {Uri_HOST_DNS,S_OK},
6334             {0,S_FALSE},
6335             {URL_SCHEME_UNKNOWN,S_OK},
6336             {URLZONE_INVALID,E_NOTIMPL}
6337         }
6338     },
6339     /* FILE_USE_PATHURL has no effect in IE 8, in IE 7 the
6340      * resulting URI is converted into a dos path.
6341      */
6342     {   "http://google.com/test",0,
6343         "file:///c:/test/",0,
6344         URL_FILE_USE_PATHURL,S_OK,FALSE,
6345         {
6346             {"file:///c:/test/",S_OK,FALSE,"file://c:\\test\\"},
6347             {"",S_FALSE},
6348             {"file:///c:/test/",S_OK,FALSE,"file://c:\\test\\"},
6349             {"",S_FALSE},
6350             {"",S_FALSE},
6351             {"",S_FALSE},
6352             {"",S_FALSE},
6353             {"",S_FALSE},
6354             {"/c:/test/",S_OK,FALSE,"c:\\test\\"},
6355             {"/c:/test/",S_OK,FALSE,"c:\\test\\"},
6356             {"",S_FALSE},
6357             {"file:///c:/test/",S_OK,FALSE,"file://c:\\test\\"},
6358             {"file",S_OK},
6359             {"",S_FALSE},
6360             {"",S_FALSE}
6361         },
6362         {
6363             {Uri_HOST_UNKNOWN,S_OK},
6364             {0,S_FALSE},
6365             {URL_SCHEME_FILE,S_OK},
6366             {URLZONE_INVALID,E_NOTIMPL}
6367         }
6368     },
6369     {   "http://google.com/test",0,
6370         "http://test.com/test#%30test",0,
6371         URL_DONT_UNESCAPE_EXTRA_INFO,S_OK,FALSE,
6372         {
6373             {"http://test.com/test#0test",S_OK,FALSE,NULL,"http://test.com/test#%30test"},
6374             {"test.com",S_OK},
6375             {"http://test.com/test#0test",S_OK,FALSE,NULL,"http://test.com/test#%30test"},
6376             {"test.com",S_OK},
6377             {"",S_FALSE},
6378             {"#0test",S_OK,FALSE,NULL,"#%30test"},
6379             {"test.com",S_OK},
6380             {"",S_FALSE},
6381             {"/test",S_OK},
6382             {"/test",S_OK},
6383             {"",S_FALSE},
6384             /* IE 7 decodes the %30 to a 0 in the Raw URI. */
6385             {"http://test.com/test#%30test",S_OK,FALSE,"http://test.com/test#0test"},
6386             {"http",S_OK},
6387             {"",S_FALSE},
6388             {"",S_FALSE}
6389         },
6390         {
6391             {Uri_HOST_DNS,S_OK},
6392             {80,S_OK},
6393             {URL_SCHEME_HTTP,S_OK},
6394             {URLZONE_INVALID,E_NOTIMPL}
6395         }
6396     },
6397     /* Windows validates the path component from the relative Uri. */
6398     {   "http://google.com/test",0,
6399         "/Te%XXst",Uri_CREATE_ALLOW_RELATIVE,
6400         0,E_INVALIDARG,FALSE
6401     },
6402     /* Windows doesn't validate the query from the relative Uri. */
6403     {   "http://google.com/test",0,
6404         "?Tes%XXt",Uri_CREATE_ALLOW_RELATIVE,
6405         0,S_OK,FALSE,
6406         {
6407             {"http://google.com/test?Tes%XXt",S_OK},
6408             {"google.com",S_OK},
6409             {"http://google.com/test?Tes%XXt",S_OK},
6410             {"google.com",S_OK},
6411             {"",S_FALSE},
6412             {"",S_FALSE},
6413             {"google.com",S_OK},
6414             {"",S_FALSE},
6415             {"/test",S_OK},
6416             {"/test?Tes%XXt",S_OK},
6417             {"?Tes%XXt",S_OK},
6418             {"http://google.com/test?Tes%XXt",S_OK},
6419             {"http",S_OK},
6420             {"",S_FALSE},
6421             {"",S_FALSE}
6422         },
6423         {
6424             {Uri_HOST_DNS,S_OK},
6425             {80,S_OK},
6426             {URL_SCHEME_HTTP,S_OK},
6427             {URLZONE_INVALID,E_NOTIMPL}
6428         }
6429     },
6430     /* Windows doesn't validate the fragment from the relative Uri. */
6431     {   "http://google.com/test",0,
6432         "#Tes%XXt",Uri_CREATE_ALLOW_RELATIVE,
6433         0,S_OK,FALSE,
6434         {
6435             {"http://google.com/test#Tes%XXt",S_OK},
6436             {"google.com",S_OK},
6437             {"http://google.com/test#Tes%XXt",S_OK},
6438             {"google.com",S_OK},
6439             {"",S_FALSE},
6440             {"#Tes%XXt",S_OK},
6441             {"google.com",S_OK},
6442             {"",S_FALSE},
6443             {"/test",S_OK},
6444             {"/test",S_OK},
6445             {"",S_FALSE},
6446             {"http://google.com/test#Tes%XXt",S_OK},
6447             {"http",S_OK},
6448             {"",S_FALSE},
6449             {"",S_FALSE}
6450         },
6451         {
6452             {Uri_HOST_DNS,S_OK},
6453             {80,S_OK},
6454             {URL_SCHEME_HTTP,S_OK},
6455             {URLZONE_INVALID,E_NOTIMPL}
6456         }
6457     },
6458     /* Creates an IUri which contains an invalid dos path char. */
6459     {   "file:///c:/test",0,
6460         "/test<ing",Uri_CREATE_ALLOW_RELATIVE,
6461         URL_FILE_USE_PATHURL,S_OK,FALSE,
6462         {
6463             {"file://c:\\test<ing",S_OK},
6464             {"",S_FALSE},
6465             {"file://c:\\test<ing",S_OK},
6466             {"",S_FALSE},
6467             {"",S_FALSE},
6468             {"",S_FALSE},
6469             {"",S_FALSE},
6470             {"",S_FALSE},
6471             {"c:\\test<ing",S_OK},
6472             {"c:\\test<ing",S_OK},
6473             {"",S_FALSE},
6474             {"file://c:\\test<ing",S_OK},
6475             {"file",S_OK},
6476             {"",S_FALSE},
6477             {"",S_FALSE}
6478         },
6479         {
6480             {Uri_HOST_UNKNOWN,S_OK},
6481             {0,S_FALSE},
6482             {URL_SCHEME_FILE,S_OK},
6483             {URLZONE_INVALID,E_NOTIMPL}
6484         }
6485     },
6486     /* Appends the path after the drive letter (if any). */
6487     {   "file:///c:/test",0,
6488         "/c:/testing",Uri_CREATE_ALLOW_RELATIVE,
6489         0,S_OK,FALSE,
6490         {
6491             {"file:///c:/c:/testing",S_OK},
6492             {"",S_FALSE},
6493             {"file:///c:/c:/testing",S_OK},
6494             {"",S_FALSE},
6495             {"",S_FALSE},
6496             {"",S_FALSE},
6497             {"",S_FALSE},
6498             {"",S_FALSE},
6499             {"/c:/c:/testing",S_OK},
6500             {"/c:/c:/testing",S_OK},
6501             {"",S_FALSE},
6502             {"file:///c:/c:/testing",S_OK},
6503             {"file",S_OK},
6504             {"",S_FALSE},
6505             {"",S_FALSE}
6506         },
6507         {
6508             {Uri_HOST_UNKNOWN,S_OK},
6509             {0,S_FALSE},
6510             {URL_SCHEME_FILE,S_OK},
6511             {URLZONE_INVALID,E_NOTIMPL}
6512         }
6513     },
6514     /* A '/' is added if the base URI doesn't have a path and the
6515      * relative URI doesn't contain a path (since the base URI is
6516      * hierarchical.
6517      */
6518     {   "http://google.com",Uri_CREATE_NO_CANONICALIZE,
6519         "?test",Uri_CREATE_ALLOW_RELATIVE,
6520         0,S_OK,FALSE,
6521         {
6522             {"http://google.com/?test",S_OK},
6523             {"google.com",S_OK},
6524             {"http://google.com/?test",S_OK},
6525             {"google.com",S_OK},
6526             {"",S_FALSE},
6527             {"",S_FALSE},
6528             {"google.com",S_OK},
6529             {"",S_FALSE},
6530             {"/",S_OK},
6531             {"/?test",S_OK},
6532             {"?test",S_OK},
6533             {"http://google.com/?test",S_OK},
6534             {"http",S_OK},
6535             {"",S_FALSE},
6536             {"",S_FALSE}
6537         },
6538         {
6539             {Uri_HOST_DNS,S_OK},
6540             {80,S_OK},
6541             {URL_SCHEME_HTTP,S_OK},
6542             {URLZONE_INVALID,E_NOTIMPL}
6543         }
6544     },
6545     {   "zip://google.com",Uri_CREATE_NO_CANONICALIZE,
6546         "?test",Uri_CREATE_ALLOW_RELATIVE,
6547         0,S_OK,FALSE,
6548         {
6549             {"zip://google.com/?test",S_OK},
6550             {"google.com",S_OK},
6551             {"zip://google.com/?test",S_OK},
6552             {"google.com",S_OK},
6553             {"",S_FALSE},
6554             {"",S_FALSE},
6555             {"google.com",S_OK},
6556             {"",S_FALSE},
6557             {"/",S_OK},
6558             {"/?test",S_OK},
6559             {"?test",S_OK},
6560             {"zip://google.com/?test",S_OK},
6561             {"zip",S_OK},
6562             {"",S_FALSE},
6563             {"",S_FALSE}
6564         },
6565         {
6566             {Uri_HOST_DNS,S_OK},
6567             {0,S_FALSE},
6568             {URL_SCHEME_UNKNOWN,S_OK},
6569             {URLZONE_INVALID,E_NOTIMPL}
6570         }
6571     },
6572     /* No path is appended since the base URI is opaque. */
6573     {   "zip:?testing",0,
6574         "?test",Uri_CREATE_ALLOW_RELATIVE,
6575         0,S_OK,FALSE,
6576         {
6577             {"zip:?test",S_OK},
6578             {"",S_FALSE},
6579             {"zip:?test",S_OK},
6580             {"",S_FALSE},
6581             {"",S_FALSE},
6582             {"",S_FALSE},
6583             {"",S_FALSE},
6584             {"",S_FALSE},
6585             {"",S_OK},
6586             {"?test",S_OK},
6587             {"?test",S_OK},
6588             {"zip:?test",S_OK},
6589             {"zip",S_OK},
6590             {"",S_FALSE},
6591             {"",S_FALSE}
6592         },
6593         {
6594             {Uri_HOST_UNKNOWN,S_OK},
6595             {0,S_FALSE},
6596             {URL_SCHEME_UNKNOWN,S_OK},
6597             {URLZONE_INVALID,E_NOTIMPL}
6598         }
6599     },
6600     {   "file:///c:/",0,
6601         "../testing/test",Uri_CREATE_ALLOW_RELATIVE,
6602         0,S_OK,FALSE,
6603         {
6604             {"file:///c:/testing/test",S_OK},
6605             {"",S_FALSE},
6606             {"file:///c:/testing/test",S_OK},
6607             {"",S_FALSE},
6608             {"",S_FALSE},
6609             {"",S_FALSE},
6610             {"",S_FALSE},
6611             {"",S_FALSE},
6612             {"/c:/testing/test",S_OK},
6613             {"/c:/testing/test",S_OK},
6614             {"",S_FALSE},
6615             {"file:///c:/testing/test",S_OK},
6616             {"file",S_OK},
6617             {"",S_FALSE},
6618             {"",S_FALSE}
6619         },
6620         {
6621             {Uri_HOST_UNKNOWN,S_OK},
6622             {0,S_FALSE},
6623             {URL_SCHEME_FILE,S_OK},
6624             {URLZONE_INVALID,E_NOTIMPL}
6625         }
6626     },
6627     {   "http://winehq.org/dir/testfile",0,
6628         "test?querystring",Uri_CREATE_ALLOW_RELATIVE,
6629         0,S_OK,FALSE,
6630         {
6631             {"http://winehq.org/dir/test?querystring",S_OK},
6632             {"winehq.org",S_OK},
6633             {"http://winehq.org/dir/test?querystring",S_OK},
6634             {"winehq.org",S_OK},
6635             {"",S_FALSE},
6636             {"",S_FALSE},
6637             {"winehq.org",S_OK},
6638             {"",S_FALSE},
6639             {"/dir/test",S_OK},
6640             {"/dir/test?querystring",S_OK},
6641             {"?querystring",S_OK},
6642             {"http://winehq.org/dir/test?querystring",S_OK},
6643             {"http",S_OK},
6644             {"",S_FALSE},
6645             {"",S_FALSE}
6646         },
6647         {
6648             {Uri_HOST_DNS,S_OK},
6649             {80,S_OK},
6650             {URL_SCHEME_HTTP,S_OK},
6651             {URLZONE_INVALID,E_NOTIMPL}
6652         }
6653     },
6654     {   "http://winehq.org/dir/test",0,
6655         "test?querystring",Uri_CREATE_ALLOW_RELATIVE,
6656         0,S_OK,FALSE,
6657         {
6658             {"http://winehq.org/dir/test?querystring",S_OK},
6659             {"winehq.org",S_OK},
6660             {"http://winehq.org/dir/test?querystring",S_OK},
6661             {"winehq.org",S_OK},
6662             {"",S_FALSE},
6663             {"",S_FALSE},
6664             {"winehq.org",S_OK},
6665             {"",S_FALSE},
6666             {"/dir/test",S_OK},
6667             {"/dir/test?querystring",S_OK},
6668             {"?querystring",S_OK},
6669             {"http://winehq.org/dir/test?querystring",S_OK},
6670             {"http",S_OK},
6671             {"",S_FALSE},
6672             {"",S_FALSE}
6673         },
6674         {
6675             {Uri_HOST_DNS,S_OK},
6676             {80,S_OK},
6677             {URL_SCHEME_HTTP,S_OK},
6678             {URLZONE_INVALID,E_NOTIMPL}
6679         }
6680     },
6681     {   "http://winehq.org/dir/test?querystring",0,
6682         "#hash",Uri_CREATE_ALLOW_RELATIVE,
6683         0,S_OK,FALSE,
6684         {
6685             {"http://winehq.org/dir/test?querystring#hash",S_OK},
6686             {"winehq.org",S_OK},
6687             {"http://winehq.org/dir/test?querystring#hash",S_OK},
6688             {"winehq.org",S_OK},
6689             {"",S_FALSE},
6690             {"#hash",S_OK},
6691             {"winehq.org",S_OK},
6692             {"",S_FALSE},
6693             {"/dir/test",S_OK},
6694             {"/dir/test?querystring",S_OK},
6695             {"?querystring",S_OK},
6696             {"http://winehq.org/dir/test?querystring#hash",S_OK},
6697             {"http",S_OK},
6698             {"",S_FALSE},
6699             {"",S_FALSE}
6700         },
6701         {
6702             {Uri_HOST_DNS,S_OK},
6703             {80,S_OK},
6704             {URL_SCHEME_HTTP,S_OK},
6705             {URLZONE_INVALID,E_NOTIMPL}
6706         }
6707     },
6708     {   "mk:@MSITSTORE:C:\\Some\\Bogus\\Path.chm::/subdir\\file.txt",0,
6709         "relative/path.txt",Uri_CREATE_ALLOW_RELATIVE,
6710         0,S_OK,FALSE,
6711         {
6712             {"mk:@MSITSTORE:C:\\Some\\Bogus\\Path.chm::/subdir/relative/path.txt",S_OK},
6713             {"",S_FALSE},
6714             {"mk:@MSITSTORE:C:\\Some\\Bogus\\Path.chm::/subdir/relative/path.txt",S_OK},
6715             {"",S_FALSE},
6716             {".txt",S_OK},
6717             {"",S_FALSE},
6718             {"",S_FALSE},
6719             {"",S_FALSE},
6720             {"@MSITSTORE:C:\\Some\\Bogus\\Path.chm::/subdir/relative/path.txt",S_OK},
6721             {"@MSITSTORE:C:\\Some\\Bogus\\Path.chm::/subdir/relative/path.txt",S_OK},
6722             {"",S_FALSE},
6723             {"mk:@MSITSTORE:C:\\Some\\Bogus\\Path.chm::/subdir/relative/path.txt",S_OK},
6724             {"mk",S_OK},
6725             {"",S_FALSE},
6726             {"",S_FALSE}
6727         },
6728         {
6729             {Uri_HOST_UNKNOWN,S_OK},
6730             {0,S_FALSE},
6731             {URL_SCHEME_MK,S_OK},
6732             {URLZONE_INVALID,E_NOTIMPL}
6733         }
6734     },
6735     {   "mk:@MSITSTORE:C:\\Some\\Bogus\\Path.chm::\\subdir\\file.txt",0,
6736         "relative/path.txt",Uri_CREATE_ALLOW_RELATIVE,
6737         0,S_OK,FALSE,
6738         {
6739             {"mk:@MSITSTORE:C:\\Some\\Bogus\\Path.chm::/subdir/relative/path.txt",S_OK},
6740             {"",S_FALSE},
6741             {"mk:@MSITSTORE:C:\\Some\\Bogus\\Path.chm::/subdir/relative/path.txt",S_OK},
6742             {"",S_FALSE},
6743             {".txt",S_OK},
6744             {"",S_FALSE},
6745             {"",S_FALSE},
6746             {"",S_FALSE},
6747             {"@MSITSTORE:C:\\Some\\Bogus\\Path.chm::/subdir/relative/path.txt",S_OK},
6748             {"@MSITSTORE:C:\\Some\\Bogus\\Path.chm::/subdir/relative/path.txt",S_OK},
6749             {"",S_FALSE},
6750             {"mk:@MSITSTORE:C:\\Some\\Bogus\\Path.chm::/subdir/relative/path.txt",S_OK},
6751             {"mk",S_OK},
6752             {"",S_FALSE},
6753             {"",S_FALSE}
6754         },
6755         {
6756             {Uri_HOST_UNKNOWN,S_OK},
6757             {0,S_FALSE},
6758             {URL_SCHEME_MK,S_OK},
6759             {URLZONE_INVALID,E_NOTIMPL}
6760         }
6761     },
6762     {   "mk:@MSITSTORE:C:/Some\\Bogus/Path.chm::/subdir\\file.txt",0,
6763         "relative\\path.txt",Uri_CREATE_ALLOW_RELATIVE,
6764         0,S_OK,FALSE,
6765         {
6766             {"mk:@MSITSTORE:C:/Some\\Bogus/Path.chm::/subdir/relative/path.txt",S_OK},
6767             {"",S_FALSE},
6768             {"mk:@MSITSTORE:C:/Some\\Bogus/Path.chm::/subdir/relative/path.txt",S_OK},
6769             {"",S_FALSE},
6770             {".txt",S_OK},
6771             {"",S_FALSE},
6772             {"",S_FALSE},
6773             {"",S_FALSE},
6774             {"@MSITSTORE:C:/Some\\Bogus/Path.chm::/subdir/relative/path.txt",S_OK},
6775             {"@MSITSTORE:C:/Some\\Bogus/Path.chm::/subdir/relative/path.txt",S_OK},
6776             {"",S_FALSE},
6777             {"mk:@MSITSTORE:C:/Some\\Bogus/Path.chm::/subdir/relative/path.txt",S_OK},
6778             {"mk",S_OK},
6779             {"",S_FALSE},
6780             {"",S_FALSE}
6781         },
6782         {
6783             {Uri_HOST_UNKNOWN,S_OK},
6784             {0,S_FALSE},
6785             {URL_SCHEME_MK,S_OK},
6786             {URLZONE_INVALID,E_NOTIMPL}
6787         }
6788     },
6789     {   "mk:@MSITSTORE:C:\\dir\\file.chm::/subdir/file.txt",0,
6790         "/relative/path.txt",Uri_CREATE_ALLOW_RELATIVE,
6791         0,S_OK,FALSE,
6792         {
6793             {"mk:@MSITSTORE:C:\\dir\\file.chm::/relative/path.txt",S_OK},
6794             {"",S_FALSE},
6795             {"mk:@MSITSTORE:C:\\dir\\file.chm::/relative/path.txt",S_OK},
6796             {"",S_FALSE},
6797             {".txt",S_OK},
6798             {"",S_FALSE},
6799             {"",S_FALSE},
6800             {"",S_FALSE},
6801             {"@MSITSTORE:C:\\dir\\file.chm::/relative/path.txt",S_OK},
6802             {"@MSITSTORE:C:\\dir\\file.chm::/relative/path.txt",S_OK},
6803             {"",S_FALSE},
6804             {"mk:@MSITSTORE:C:\\dir\\file.chm::/relative/path.txt",S_OK},
6805             {"mk",S_OK},
6806             {"",S_FALSE},
6807             {"",S_FALSE}
6808         },
6809         {
6810             {Uri_HOST_UNKNOWN,S_OK},
6811             {0,S_FALSE},
6812             {URL_SCHEME_MK,S_OK},
6813             {URLZONE_INVALID,E_NOTIMPL}
6814         }
6815     },
6816     {   "mk:MSITSTORE:C:\\dir\\file.chm::/subdir/file.txt",0,
6817         "/relative/path.txt",Uri_CREATE_ALLOW_RELATIVE,
6818         0,S_OK,FALSE,
6819         {
6820             {"mk:MSITSTORE:C:\\dir\\file.chm::/relative/path.txt",S_OK},
6821             {"",S_FALSE},
6822             {"mk:MSITSTORE:C:\\dir\\file.chm::/relative/path.txt",S_OK},
6823             {"",S_FALSE},
6824             {".txt",S_OK},
6825             {"",S_FALSE},
6826             {"",S_FALSE},
6827             {"",S_FALSE},
6828             {"MSITSTORE:C:\\dir\\file.chm::/relative/path.txt",S_OK},
6829             {"MSITSTORE:C:\\dir\\file.chm::/relative/path.txt",S_OK},
6830             {"",S_FALSE},
6831             {"mk:MSITSTORE:C:\\dir\\file.chm::/relative/path.txt",S_OK},
6832             {"mk",S_OK},
6833             {"",S_FALSE},
6834             {"",S_FALSE}
6835         },
6836         {
6837             {Uri_HOST_UNKNOWN,S_OK},
6838             {0,S_FALSE},
6839             {URL_SCHEME_MK,S_OK},
6840             {URLZONE_INVALID,E_NOTIMPL}
6841         }
6842     },
6843     {   "mk:@MSITSTORE:C:\\dir\\file.chm::/subdir/../../file.txt",0,
6844         "/relative/path.txt",Uri_CREATE_ALLOW_RELATIVE,
6845         0,S_OK,FALSE,
6846         {
6847             {"mk:@MSITSTORE:/relative/path.txt",S_OK},
6848             {"",S_FALSE},
6849             {"mk:@MSITSTORE:/relative/path.txt",S_OK},
6850             {"",S_FALSE},
6851             {".txt",S_OK},
6852             {"",S_FALSE},
6853             {"",S_FALSE},
6854             {"",S_FALSE},
6855             {"@MSITSTORE:/relative/path.txt",S_OK},
6856             {"@MSITSTORE:/relative/path.txt",S_OK},
6857             {"",S_FALSE},
6858             {"mk:@MSITSTORE:/relative/path.txt",S_OK},
6859             {"mk",S_OK},
6860             {"",S_FALSE},
6861             {"",S_FALSE}
6862         },
6863         {
6864             {Uri_HOST_UNKNOWN,S_OK},
6865             {0,S_FALSE},
6866             {URL_SCHEME_MK,S_OK},
6867             {URLZONE_INVALID,E_NOTIMPL}
6868         }
6869     },
6870     {   "mk:@xxx:C:\\dir\\file.chm::/subdir/../../file.txt",0,
6871         "/relative/path.txt",Uri_CREATE_ALLOW_RELATIVE,
6872         0,S_OK,FALSE,
6873         {
6874             {"mk:@xxx:/relative/path.txt",S_OK},
6875             {"",S_FALSE},
6876             {"mk:@xxx:/relative/path.txt",S_OK},
6877             {"",S_FALSE},
6878             {".txt",S_OK},
6879             {"",S_FALSE},
6880             {"",S_FALSE},
6881             {"",S_FALSE},
6882             {"@xxx:/relative/path.txt",S_OK},
6883             {"@xxx:/relative/path.txt",S_OK},
6884             {"",S_FALSE},
6885             {"mk:@xxx:/relative/path.txt",S_OK},
6886             {"mk",S_OK},
6887             {"",S_FALSE},
6888             {"",S_FALSE}
6889         },
6890         {
6891             {Uri_HOST_UNKNOWN,S_OK},
6892             {0,S_FALSE},
6893             {URL_SCHEME_MK,S_OK},
6894             {URLZONE_INVALID,E_NOTIMPL}
6895         }
6896     },
6897     {   "mk:xxx:C:\\dir\\file.chm::/subdir/../../file.txt",0,
6898         "/relative/path.txt",Uri_CREATE_ALLOW_RELATIVE,
6899         0,S_OK,FALSE,
6900         {
6901             {"mk:/relative/path.txt",S_OK},
6902             {"",S_FALSE},
6903             {"mk:/relative/path.txt",S_OK},
6904             {"",S_FALSE},
6905             {".txt",S_OK},
6906             {"",S_FALSE},
6907             {"",S_FALSE},
6908             {"",S_FALSE},
6909             {"/relative/path.txt",S_OK},
6910             {"/relative/path.txt",S_OK},
6911             {"",S_FALSE},
6912             {"mk:/relative/path.txt",S_OK},
6913             {"mk",S_OK},
6914             {"",S_FALSE},
6915             {"",S_FALSE}
6916         },
6917         {
6918             {Uri_HOST_UNKNOWN,S_OK},
6919             {0,S_FALSE},
6920             {URL_SCHEME_MK,S_OK},
6921             {URLZONE_INVALID,E_NOTIMPL}
6922         }
6923     },
6924     {   "ml:@MSITSTORE:C:\\dir\\file.chm::/subdir/file.txt",0,
6925         "/relative/path.txt",Uri_CREATE_ALLOW_RELATIVE,
6926         0,S_OK,FALSE,
6927         {
6928             {"ml:/relative/path.txt",S_OK},
6929             {"",S_FALSE},
6930             {"ml:/relative/path.txt",S_OK},
6931             {"",S_FALSE},
6932             {".txt",S_OK},
6933             {"",S_FALSE},
6934             {"",S_FALSE},
6935             {"",S_FALSE},
6936             {"/relative/path.txt",S_OK},
6937             {"/relative/path.txt",S_OK},
6938             {"",S_FALSE},
6939             {"ml:/relative/path.txt",S_OK},
6940             {"ml",S_OK},
6941             {"",S_FALSE},
6942             {"",S_FALSE}
6943         },
6944         {
6945             {Uri_HOST_UNKNOWN,S_OK},
6946             {0,S_FALSE},
6947             {URL_SCHEME_UNKNOWN,S_OK},
6948             {URLZONE_INVALID,E_NOTIMPL}
6949         }
6950     },
6951     {   "http://winehq.org/dir/test?querystring",0,
6952         "//winehq.com/#hash",Uri_CREATE_ALLOW_RELATIVE,
6953         0,S_OK,FALSE,
6954         {
6955             {"http://winehq.com/#hash",S_OK},
6956             {"winehq.com",S_OK},
6957             {"http://winehq.com/#hash",S_OK},
6958             {"winehq.com",S_OK},
6959             {"",S_FALSE},
6960             {"#hash",S_OK},
6961             {"winehq.com",S_OK},
6962             {"",S_FALSE},
6963             {"/",S_OK},
6964             {"/",S_OK},
6965             {"",S_FALSE},
6966             {"http://winehq.com/#hash",S_OK},
6967             {"http",S_OK},
6968             {"",S_FALSE},
6969             {"",S_FALSE}
6970         },
6971         {
6972             {Uri_HOST_DNS,S_OK},
6973             {80,S_OK,FALSE,TRUE},
6974             {URL_SCHEME_HTTP,S_OK},
6975             {URLZONE_INVALID,E_NOTIMPL}
6976         }
6977     },
6978     {   "http://winehq.org/dir/test?querystring",0,
6979         "//winehq.com/dir2/../dir/file.txt?query#hash",Uri_CREATE_ALLOW_RELATIVE,
6980         0,S_OK,FALSE,
6981         {
6982             {"http://winehq.com/dir/file.txt?query#hash",S_OK},
6983             {"winehq.com",S_OK},
6984             {"http://winehq.com/dir/file.txt?query#hash",S_OK},
6985             {"winehq.com",S_OK},
6986             {".txt",S_OK},
6987             {"#hash",S_OK},
6988             {"winehq.com",S_OK},
6989             {"",S_FALSE},
6990             {"/dir/file.txt",S_OK},
6991             {"/dir/file.txt?query",S_OK},
6992             {"?query",S_OK},
6993             {"http://winehq.com/dir/file.txt?query#hash",S_OK},
6994             {"http",S_OK},
6995             {"",S_FALSE},
6996             {"",S_FALSE}
6997         },
6998         {
6999             {Uri_HOST_DNS,S_OK},
7000             {80,S_OK,FALSE,TRUE},
7001             {URL_SCHEME_HTTP,S_OK},
7002             {URLZONE_INVALID,E_NOTIMPL}
7003         }
7004     },
7005     {   "http://google.com/test",0,
7006         "c:\\test\\", Uri_CREATE_ALLOW_IMPLICIT_FILE_SCHEME,
7007         0,S_OK,FALSE,
7008         {
7009             {"file:///c:/test/",S_OK},
7010             {"",S_FALSE},
7011             {"file:///c:/test/",S_OK},
7012             {"",S_FALSE},
7013             {"",S_FALSE},
7014             {"",S_FALSE},
7015             {"",S_FALSE},
7016             {"",S_FALSE},
7017             {"/c:/test/",S_OK},
7018             {"/c:/test/",S_OK},
7019             {"",S_FALSE},
7020             {"c:\\test\\",S_OK,FALSE,"file:///c:/test/"},
7021             {"file",S_OK},
7022             {"",S_FALSE},
7023             {"",S_FALSE}
7024         },
7025         {
7026             {Uri_HOST_UNKNOWN,S_OK},
7027             {0,S_FALSE},
7028             {URL_SCHEME_FILE,S_OK},
7029             {URLZONE_INVALID,E_NOTIMPL}
7030         }
7031     },
7032     {   "http://google.com/test",0,
7033         "c:\\test\\", Uri_CREATE_ALLOW_IMPLICIT_FILE_SCHEME,
7034         0,S_OK,FALSE,
7035         {
7036             {"file:///c:/test/",S_OK},
7037             {"",S_FALSE},
7038             {"file:///c:/test/",S_OK},
7039             {"",S_FALSE},
7040             {"",S_FALSE},
7041             {"",S_FALSE},
7042             {"",S_FALSE},
7043             {"",S_FALSE},
7044             {"/c:/test/",S_OK},
7045             {"/c:/test/",S_OK},
7046             {"",S_FALSE},
7047             {"c:\\test\\",S_OK,FALSE,"file:///c:/test/"},
7048             {"file",S_OK},
7049             {"",S_FALSE},
7050             {"",S_FALSE}
7051         },
7052         {
7053             {Uri_HOST_UNKNOWN,S_OK},
7054             {0,S_FALSE},
7055             {URL_SCHEME_FILE,S_OK},
7056             {URLZONE_INVALID,E_NOTIMPL}
7057         }
7058     },
7059     {   "http://winehq.org",0,
7060         "mailto://",Uri_CREATE_NO_CANONICALIZE,
7061         0,S_OK,FALSE,
7062         {
7063             {"mailto:",S_OK},
7064             {"",S_FALSE},
7065             {"mailto:",S_OK},
7066             {"",S_FALSE},
7067             {"",S_FALSE},
7068             {"",S_FALSE},
7069             {"",S_FALSE},
7070             {"",S_FALSE},
7071             {"",S_FALSE},
7072             {"",S_FALSE},
7073             {"",S_FALSE},
7074             {"mailto://",S_OK,FALSE,"mailto:"},
7075             {"mailto",S_OK},
7076             {"",S_FALSE},
7077             {"",S_FALSE}
7078         },
7079         {
7080             {Uri_HOST_UNKNOWN,S_OK},
7081             {0,S_FALSE},
7082             {URL_SCHEME_MAILTO,S_OK},
7083             {URLZONE_INVALID,E_NOTIMPL}
7084         }
7085     },
7086     {   "http://winehq.org",0,
7087         "mailto://a@b.com",Uri_CREATE_NO_CANONICALIZE,
7088         0,S_OK,FALSE,
7089         {
7090             {"mailto:a@b.com",S_OK},
7091             {"",S_FALSE},
7092             {"mailto:a@b.com",S_OK},
7093             {"",S_FALSE},
7094             {".com",S_OK},
7095             {"",S_FALSE},
7096             {"",S_FALSE},
7097             {"",S_FALSE},
7098             {"a@b.com",S_OK},
7099             {"a@b.com",S_OK},
7100             {"",S_FALSE},
7101             {"mailto://a@b.com",S_OK,FALSE,"mailto:a@b.com"},
7102             {"mailto",S_OK},
7103             {"",S_FALSE},
7104             {"",S_FALSE}
7105         },
7106         {
7107             {Uri_HOST_UNKNOWN,S_OK},
7108             {0,S_FALSE},
7109             {URL_SCHEME_MAILTO,S_OK},
7110             {URLZONE_INVALID,E_NOTIMPL}
7111         }
7112     }
7113 };
7114
7115 typedef struct _uri_parse_test {
7116     const char  *uri;
7117     DWORD       uri_flags;
7118     PARSEACTION action;
7119     DWORD       flags;
7120     const char  *property;
7121     HRESULT     expected;
7122     BOOL        todo;
7123 } uri_parse_test;
7124
7125 static const uri_parse_test uri_parse_tests[] = {
7126     /* PARSE_CANONICALIZE tests. */
7127     {"zip://google.com/test<|>",0,PARSE_CANONICALIZE,0,"zip://google.com/test<|>",S_OK,FALSE},
7128     {"http://google.com/test<|>",0,PARSE_CANONICALIZE,0,"http://google.com/test%3C%7C%3E",S_OK,FALSE},
7129     {"http://google.com/%30%23%3F",0,PARSE_CANONICALIZE,URL_UNESCAPE,"http://google.com/0#?",S_OK,FALSE},
7130     {"test <|>",Uri_CREATE_ALLOW_RELATIVE,PARSE_CANONICALIZE,URL_ESCAPE_UNSAFE,"test %3C%7C%3E",S_OK,FALSE},
7131     {"test <|>",Uri_CREATE_ALLOW_RELATIVE,PARSE_CANONICALIZE,URL_ESCAPE_SPACES_ONLY,"test%20<|>",S_OK,FALSE},
7132     {"test%20<|>",Uri_CREATE_ALLOW_RELATIVE,PARSE_CANONICALIZE,URL_UNESCAPE|URL_ESCAPE_UNSAFE,"test%20%3C%7C%3E",S_OK,FALSE},
7133     {"http://google.com/%20",0,PARSE_CANONICALIZE,URL_ESCAPE_PERCENT,"http://google.com/%2520",S_OK,FALSE},
7134     {"http://google.com/test/../",Uri_CREATE_NO_CANONICALIZE,PARSE_CANONICALIZE,URL_DONT_SIMPLIFY,"http://google.com/test/../",S_OK,FALSE},
7135     {"http://google.com/test/../",Uri_CREATE_NO_CANONICALIZE,PARSE_CANONICALIZE,URL_NO_META,"http://google.com/test/../",S_OK,FALSE},
7136     {"http://google.com/test/../",Uri_CREATE_NO_CANONICALIZE,PARSE_CANONICALIZE,0,"http://google.com/",S_OK,FALSE},
7137     {"zip://google.com/test/../",Uri_CREATE_NO_CANONICALIZE,PARSE_CANONICALIZE,0,"zip://google.com/",S_OK,FALSE},
7138     {"file:///c:/test/../test",Uri_CREATE_NO_CANONICALIZE,PARSE_CANONICALIZE,URL_DONT_SIMPLIFY,"file:///c:/test/../test",S_OK,FALSE},
7139
7140     /* PARSE_FRIENDLY tests. */
7141     {"http://test@google.com/test#test",0,PARSE_FRIENDLY,0,"http://google.com/test#test",S_OK,FALSE},
7142     {"zip://test@google.com/test",0,PARSE_FRIENDLY,0,"zip://test@google.com/test",S_OK,FALSE},
7143
7144     /* PARSE_ROOTDOCUMENT tests. */
7145     {"http://google.com:200/test/test",0,PARSE_ROOTDOCUMENT,0,"http://google.com:200/",S_OK,FALSE},
7146     {"http://google.com",Uri_CREATE_NO_CANONICALIZE,PARSE_ROOTDOCUMENT,0,"http://google.com/",S_OK,FALSE},
7147     {"zip://google.com/",0,PARSE_ROOTDOCUMENT,0,"",S_OK,FALSE},
7148     {"file:///c:/testing/",0,PARSE_ROOTDOCUMENT,0,"",S_OK,FALSE},
7149     {"file://server/test",0,PARSE_ROOTDOCUMENT,0,"",S_OK,FALSE},
7150     {"zip:test/test",0,PARSE_ROOTDOCUMENT,0,"",S_OK,FALSE},
7151
7152     /* PARSE_DOCUMENT tests. */
7153     {"http://test@google.com/test?query#frag",0,PARSE_DOCUMENT,0,"http://test@google.com/test?query",S_OK,FALSE},
7154     {"http:testing#frag",0,PARSE_DOCUMENT,0,"",S_OK,FALSE},
7155     {"file:///c:/test#frag",0,PARSE_DOCUMENT,0,"",S_OK,FALSE},
7156     {"zip://google.com/#frag",0,PARSE_DOCUMENT,0,"",S_OK,FALSE},
7157     {"zip:test#frag",0,PARSE_DOCUMENT,0,"",S_OK,FALSE},
7158     {"testing#frag",Uri_CREATE_ALLOW_RELATIVE,PARSE_DOCUMENT,0,"",S_OK,FALSE},
7159
7160     /* PARSE_PATH_FROM_URL tests. */
7161     {"file:///c:/test.mp3",0,PARSE_PATH_FROM_URL,0,"c:\\test.mp3",S_OK,FALSE},
7162     {"file:///c:/t<|>est.mp3",0,PARSE_PATH_FROM_URL,0,"c:\\t<|>est.mp3",S_OK,FALSE},
7163     {"file:///c:/te%XX t/",0,PARSE_PATH_FROM_URL,0,"c:\\te%XX t\\",S_OK,FALSE},
7164     {"file://server/test",0,PARSE_PATH_FROM_URL,0,"\\\\server\\test",S_OK,FALSE},
7165     {"http://google.com/",0,PARSE_PATH_FROM_URL,0,"",E_INVALIDARG,FALSE},
7166
7167     /* PARSE_URL_FROM_PATH tests. */
7168     /* This function almost seems to useless (just returns the absolute uri). */
7169     {"test.com",Uri_CREATE_ALLOW_RELATIVE,PARSE_URL_FROM_PATH,0,"test.com",S_OK,FALSE},
7170     {"/test/test",Uri_CREATE_ALLOW_RELATIVE,PARSE_URL_FROM_PATH,0,"/test/test",S_OK,FALSE},
7171     {"file://c:\\test\\test",Uri_CREATE_FILE_USE_DOS_PATH,PARSE_URL_FROM_PATH,0,"file://c:\\test\\test",S_OK,FALSE},
7172     {"file:c:/test",0,PARSE_URL_FROM_PATH,0,"",S_OK,FALSE},
7173     {"http:google.com/",0,PARSE_URL_FROM_PATH,0,"",S_OK,FALSE},
7174
7175     /* PARSE_SCHEMA tests. */
7176     {"http://google.com/test",0,PARSE_SCHEMA,0,"http",S_OK,FALSE},
7177     {"test",Uri_CREATE_ALLOW_RELATIVE,PARSE_SCHEMA,0,"",S_OK,FALSE},
7178
7179     /* PARSE_SITE tests. */
7180     {"http://google.uk.com/",0,PARSE_SITE,0,"google.uk.com",S_OK,FALSE},
7181     {"http://google.com.com/",0,PARSE_SITE,0,"google.com.com",S_OK,FALSE},
7182     {"google.com",Uri_CREATE_ALLOW_RELATIVE,PARSE_SITE,0,"",S_OK,FALSE},
7183     {"file://server/test",0,PARSE_SITE,0,"server",S_OK,FALSE},
7184
7185     /* PARSE_DOMAIN tests. */
7186     {"http://google.com.uk/",0,PARSE_DOMAIN,0,"google.com.uk",S_OK,FALSE},
7187     {"http://google.com.com/",0,PARSE_DOMAIN,0,"com.com",S_OK,FALSE},
7188     {"test/test",Uri_CREATE_ALLOW_RELATIVE,PARSE_DOMAIN,0,"",S_OK,FALSE},
7189     {"file://server/test",0,PARSE_DOMAIN,0,"",S_OK,FALSE},
7190
7191     /* PARSE_LOCATION and PARSE_ANCHOR tests. */
7192     {"http://google.com/test#Test",0,PARSE_ANCHOR,0,"#Test",S_OK,FALSE},
7193     {"http://google.com/test#Test",0,PARSE_LOCATION,0,"#Test",S_OK,FALSE},
7194     {"test",Uri_CREATE_ALLOW_RELATIVE,PARSE_ANCHOR,0,"",S_OK,FALSE},
7195     {"test",Uri_CREATE_ALLOW_RELATIVE,PARSE_LOCATION,0,"",S_OK,FALSE}
7196 };
7197
7198 static inline LPWSTR a2w(LPCSTR str) {
7199     LPWSTR ret = NULL;
7200
7201     if(str) {
7202         DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
7203         ret = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
7204         MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len);
7205     }
7206
7207     return ret;
7208 }
7209
7210 static inline BOOL heap_free(void* mem) {
7211     return HeapFree(GetProcessHeap(), 0, mem);
7212 }
7213
7214 static inline DWORD strcmp_aw(LPCSTR strA, LPCWSTR strB) {
7215     LPWSTR strAW = a2w(strA);
7216     DWORD ret = lstrcmpW(strAW, strB);
7217     heap_free(strAW);
7218     return ret;
7219 }
7220
7221 static inline ULONG get_refcnt(IUri *uri) {
7222     IUri_AddRef(uri);
7223     return IUri_Release(uri);
7224 }
7225
7226 static void change_property(IUriBuilder *builder, const uri_builder_property *prop,
7227                             DWORD test_index) {
7228     HRESULT hr;
7229     LPWSTR valueW;
7230
7231     valueW = a2w(prop->value);
7232     switch(prop->property) {
7233     case Uri_PROPERTY_FRAGMENT:
7234         hr = IUriBuilder_SetFragment(builder, valueW);
7235         if(prop->todo) {
7236             todo_wine {
7237                 ok(hr == prop->expected,
7238                     "Error: IUriBuilder_SetFragment returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7239                     hr, prop->expected, test_index);
7240             }
7241         } else {
7242             ok(hr == prop->expected,
7243                 "Error: IUriBuilder_SetFragment returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7244                 hr, prop->expected, test_index);
7245         }
7246         break;
7247     case Uri_PROPERTY_HOST:
7248         hr = IUriBuilder_SetHost(builder, valueW);
7249         if(prop->todo) {
7250             todo_wine {
7251                 ok(hr == prop->expected,
7252                     "Error: IUriBuilder_SetHost returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7253                     hr, prop->expected, test_index);
7254             }
7255         } else {
7256             ok(hr == prop->expected,
7257                 "Error: IUriBuilder_SetHost returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7258                 hr, prop->expected, test_index);
7259         }
7260         break;
7261     case Uri_PROPERTY_PASSWORD:
7262         hr = IUriBuilder_SetPassword(builder, valueW);
7263         if(prop->todo) {
7264             todo_wine {
7265                 ok(hr == prop->expected,
7266                     "Error: IUriBuilder_SetPassword returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7267                     hr, prop->expected, test_index);
7268             }
7269         } else {
7270             ok(hr == prop->expected,
7271                 "Error: IUriBuilder_SetPassword returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7272                 hr, prop->expected, test_index);
7273         }
7274         break;
7275     case Uri_PROPERTY_PATH:
7276         hr = IUriBuilder_SetPath(builder, valueW);
7277         if(prop->todo) {
7278             todo_wine {
7279                 ok(hr == prop->expected,
7280                     "Error: IUriBuilder_SetPath returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7281                     hr, prop->expected, test_index);
7282             }
7283         } else {
7284             ok(hr == prop->expected,
7285                 "Error: IUriBuilder_SetPath returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7286                 hr, prop->expected, test_index);
7287         }
7288         break;
7289     case Uri_PROPERTY_QUERY:
7290         hr = IUriBuilder_SetQuery(builder, valueW);
7291         if(prop->todo) {
7292             todo_wine {
7293                 ok(hr == prop->expected,
7294                     "Error: IUriBuilder_SetQuery returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7295                     hr, prop->expected, test_index);
7296             }
7297         } else {
7298             ok(hr == prop->expected,
7299                 "Error: IUriBuilder_SetQuery returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7300                 hr, prop->expected, test_index);
7301         }
7302         break;
7303     case Uri_PROPERTY_SCHEME_NAME:
7304         hr = IUriBuilder_SetSchemeName(builder, valueW);
7305         if(prop->todo) {
7306             todo_wine {
7307                 ok(hr == prop->expected,
7308                     "Error: IUriBuilder_SetSchemeName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7309                     hr, prop->expected, test_index);
7310             }
7311         } else {
7312             ok(hr == prop->expected,
7313                 "Error: IUriBuilder_SetSchemeName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7314                 hr, prop->expected, test_index);
7315         }
7316         break;
7317     case Uri_PROPERTY_USER_NAME:
7318         hr = IUriBuilder_SetUserName(builder, valueW);
7319         if(prop->todo) {
7320             todo_wine {
7321                 ok(hr == prop->expected,
7322                     "Error: IUriBuilder_SetUserName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7323                     hr, prop->expected, test_index);
7324             }
7325         } else {
7326             ok(hr == prop->expected,
7327                 "Error: IUriBuilder_SetUserName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7328                 hr, prop->expected, test_index);
7329         }
7330         break;
7331     default:
7332         trace("Unsupported operation for %d on uri_builder_tests[%d].\n", prop->property, test_index);
7333     }
7334
7335     heap_free(valueW);
7336 }
7337
7338 /*
7339  * Simple tests to make sure the CreateUri function handles invalid flag combinations
7340  * correctly.
7341  */
7342 static void test_CreateUri_InvalidFlags(void) {
7343     DWORD i;
7344
7345     for(i = 0; i < sizeof(invalid_flag_tests)/sizeof(invalid_flag_tests[0]); ++i) {
7346         HRESULT hr;
7347         IUri *uri = (void*) 0xdeadbeef;
7348
7349         hr = pCreateUri(http_urlW, invalid_flag_tests[i].flags, 0, &uri);
7350         ok(hr == invalid_flag_tests[i].expected, "Error: CreateUri returned 0x%08x, expected 0x%08x, flags=0x%08x\n",
7351                 hr, invalid_flag_tests[i].expected, invalid_flag_tests[i].flags);
7352         ok(uri == NULL, "Error: expected the IUri to be NULL, but it was %p instead\n", uri);
7353     }
7354 }
7355
7356 static void test_CreateUri_InvalidArgs(void) {
7357     HRESULT hr;
7358     IUri *uri = (void*) 0xdeadbeef;
7359
7360     const WCHAR invalidW[] = {'i','n','v','a','l','i','d',0};
7361     static const WCHAR emptyW[] = {0};
7362
7363     hr = pCreateUri(http_urlW, 0, 0, NULL);
7364     ok(hr == E_INVALIDARG, "Error: CreateUri returned 0x%08x, expected 0x%08x\n", hr, E_INVALIDARG);
7365
7366     hr = pCreateUri(NULL, 0, 0, &uri);
7367     ok(hr == E_INVALIDARG, "Error: CreateUri returned 0x%08x, expected 0x%08x\n", hr, E_INVALIDARG);
7368     ok(uri == NULL, "Error: Expected the IUri to be NULL, but it was %p instead\n", uri);
7369
7370     uri = (void*) 0xdeadbeef;
7371     hr = pCreateUri(invalidW, 0, 0, &uri);
7372     ok(hr == E_INVALIDARG, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
7373     ok(uri == NULL, "Error: Expected the IUri to be NULL, but it was %p instead\n", uri);
7374
7375     uri = (void*) 0xdeadbeef;
7376     hr = pCreateUri(emptyW, 0, 0, &uri);
7377     ok(hr == E_INVALIDARG, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
7378     ok(uri == NULL, "Error: Expected the IUri to be NULL, but it was %p instead\n", uri);
7379 }
7380
7381 static void test_CreateUri_InvalidUri(void) {
7382     DWORD i;
7383
7384     for(i = 0; i < sizeof(invalid_uri_tests)/sizeof(invalid_uri_tests[0]); ++i) {
7385         invalid_uri test = invalid_uri_tests[i];
7386         IUri *uri = NULL;
7387         LPWSTR uriW;
7388         HRESULT hr;
7389
7390         uriW = a2w(test.uri);
7391         hr = pCreateUri(uriW, test.flags, 0, &uri);
7392         if(test.todo) {
7393             todo_wine {
7394                 ok(hr == E_INVALIDARG, "Error: CreateUri returned 0x%08x, expected 0x%08x on invalid_uri_tests[%d].\n",
7395                     hr, E_INVALIDARG, i);
7396             }
7397         } else {
7398             ok(hr == E_INVALIDARG, "Error: CreateUri returned 0x%08x, expected 0x%08x on invalid_uri_tests[%d].\n",
7399                 hr, E_INVALIDARG, i);
7400         }
7401         if(uri) IUri_Release(uri);
7402
7403         heap_free(uriW);
7404     }
7405 }
7406
7407 static void test_IUri_GetPropertyBSTR(void) {
7408     IUri *uri = NULL;
7409     HRESULT hr;
7410     DWORD i;
7411
7412     /* Make sure GetPropertyBSTR handles invalid args correctly. */
7413     hr = pCreateUri(http_urlW, 0, 0, &uri);
7414     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7415     if(SUCCEEDED(hr)) {
7416         BSTR received = NULL;
7417
7418         hr = IUri_GetPropertyBSTR(uri, Uri_PROPERTY_RAW_URI, NULL, 0);
7419         ok(hr == E_POINTER, "Error: GetPropertyBSTR returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
7420
7421         /* Make sure it handles a invalid Uri_PROPERTY's correctly. */
7422         hr = IUri_GetPropertyBSTR(uri, Uri_PROPERTY_PORT, &received, 0);
7423         ok(hr == S_OK, "Error: GetPropertyBSTR returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7424         ok(received != NULL, "Error: Expected the string not to be NULL.\n");
7425         ok(!SysStringLen(received), "Error: Expected the string to be of len=0 but it was %d instead.\n", SysStringLen(received));
7426         SysFreeString(received);
7427
7428         /* Make sure it handles the ZONE property correctly. */
7429         received = NULL;
7430         hr = IUri_GetPropertyBSTR(uri, Uri_PROPERTY_ZONE, &received, 0);
7431         ok(hr == S_FALSE, "Error: GetPropertyBSTR returned 0x%08x, expected 0x%08x.\n", hr, S_FALSE);
7432         ok(received != NULL, "Error: Expected the string not to be NULL.\n");
7433         ok(!SysStringLen(received), "Error: Expected the string to be of len=0 but it was %d instead.\n", SysStringLen(received));
7434         SysFreeString(received);
7435     }
7436     if(uri) IUri_Release(uri);
7437
7438     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
7439         uri_properties test = uri_tests[i];
7440         LPWSTR uriW;
7441         uri = NULL;
7442
7443         uriW = a2w(test.uri);
7444         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
7445         if(test.create_todo) {
7446             todo_wine {
7447                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x. Failed on uri_tests[%d].\n",
7448                         hr, test.create_expected, i);
7449             }
7450         } else {
7451             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x. Failed on uri_tests[%d].\n",
7452                     hr, test.create_expected, i);
7453         }
7454
7455         if(SUCCEEDED(hr)) {
7456             DWORD j;
7457
7458             /* Checks all the string properties of the uri. */
7459             for(j = Uri_PROPERTY_STRING_START; j <= Uri_PROPERTY_STRING_LAST; ++j) {
7460                 BSTR received = NULL;
7461                 uri_str_property prop = test.str_props[j];
7462
7463                 hr = IUri_GetPropertyBSTR(uri, j, &received, 0);
7464                 if(prop.todo) {
7465                     todo_wine {
7466                         ok(hr == prop.expected, "GetPropertyBSTR returned 0x%08x, expected 0x%08x. On uri_tests[%d].str_props[%d].\n",
7467                                 hr, prop.expected, i, j);
7468                     }
7469                     todo_wine {
7470                         ok(!strcmp_aw(prop.value, received) || broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
7471                                 "Expected %s but got %s on uri_tests[%d].str_props[%d].\n",
7472                                 prop.value, wine_dbgstr_w(received), i, j);
7473                     }
7474                 } else {
7475                     ok(hr == prop.expected, "GetPropertyBSTR returned 0x%08x, expected 0x%08x. On uri_tests[%d].str_props[%d].\n",
7476                             hr, prop.expected, i, j);
7477                     ok(!strcmp_aw(prop.value, received) || broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
7478                             "Expected %s but got %s on uri_tests[%d].str_props[%d].\n",
7479                             prop.value, wine_dbgstr_w(received), i, j);
7480                 }
7481
7482                 SysFreeString(received);
7483             }
7484         }
7485
7486         if(uri) IUri_Release(uri);
7487
7488         heap_free(uriW);
7489     }
7490 }
7491
7492 static void test_IUri_GetPropertyDWORD(void) {
7493     IUri *uri = NULL;
7494     HRESULT hr;
7495     DWORD i;
7496
7497     hr = pCreateUri(http_urlW, 0, 0, &uri);
7498     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7499     if(SUCCEEDED(hr)) {
7500         DWORD received = 0xdeadbeef;
7501
7502         hr = IUri_GetPropertyDWORD(uri, Uri_PROPERTY_DWORD_START, NULL, 0);
7503         ok(hr == E_INVALIDARG, "Error: GetPropertyDWORD returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
7504
7505         hr = IUri_GetPropertyDWORD(uri, Uri_PROPERTY_ABSOLUTE_URI, &received, 0);
7506         ok(hr == E_INVALIDARG, "Error: GetPropertyDWORD returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
7507         ok(received == 0, "Error: Expected received=%d but instead received=%d.\n", 0, received);
7508     }
7509     if(uri) IUri_Release(uri);
7510
7511     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
7512         uri_properties test = uri_tests[i];
7513         LPWSTR uriW;
7514         uri = NULL;
7515
7516         uriW = a2w(test.uri);
7517         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
7518         if(test.create_todo) {
7519             todo_wine {
7520                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x. Failed on uri_tests[%d].\n",
7521                         hr, test.create_expected, i);
7522             }
7523         } else {
7524             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x. Failed on uri_tests[%d].\n",
7525                     hr, test.create_expected, i);
7526         }
7527
7528         if(SUCCEEDED(hr)) {
7529             DWORD j;
7530
7531             /* Checks all the DWORD properties of the uri. */
7532             for(j = 0; j < sizeof(test.dword_props)/sizeof(test.dword_props[0]); ++j) {
7533                 DWORD received;
7534                 uri_dword_property prop = test.dword_props[j];
7535
7536                 hr = IUri_GetPropertyDWORD(uri, j+Uri_PROPERTY_DWORD_START, &received, 0);
7537                 if(prop.todo) {
7538                     todo_wine {
7539                         ok(hr == prop.expected, "GetPropertyDWORD returned 0x%08x, expected 0x%08x. On uri_tests[%d].dword_props[%d].\n",
7540                                 hr, prop.expected, i, j);
7541                     }
7542                     todo_wine {
7543                         ok(prop.value == received, "Expected %d but got %d on uri_tests[%d].dword_props[%d].\n",
7544                                 prop.value, received, i, j);
7545                     }
7546                 } else {
7547                     ok(hr == prop.expected, "GetPropertyDWORD returned 0x%08x, expected 0x%08x. On uri_tests[%d].dword_props[%d].\n",
7548                             hr, prop.expected, i, j);
7549                     ok(prop.value == received, "Expected %d but got %d on uri_tests[%d].dword_props[%d].\n",
7550                             prop.value, received, i, j);
7551                 }
7552             }
7553         }
7554
7555         if(uri) IUri_Release(uri);
7556
7557         heap_free(uriW);
7558     }
7559 }
7560
7561 /* Tests all the 'Get*' property functions which deal with strings. */
7562 static void test_IUri_GetStrProperties(void) {
7563     IUri *uri = NULL;
7564     HRESULT hr;
7565     DWORD i;
7566
7567     /* Make sure all the 'Get*' string property functions handle invalid args correctly. */
7568     hr = pCreateUri(http_urlW, 0, 0, &uri);
7569     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7570     if(SUCCEEDED(hr)) {
7571         hr = IUri_GetAbsoluteUri(uri, NULL);
7572         ok(hr == E_POINTER, "Error: GetAbsoluteUri returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
7573
7574         hr = IUri_GetAuthority(uri, NULL);
7575         ok(hr == E_POINTER, "Error: GetAuthority returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
7576
7577         hr = IUri_GetDisplayUri(uri, NULL);
7578         ok(hr == E_POINTER, "Error: GetDisplayUri returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
7579
7580         hr = IUri_GetDomain(uri, NULL);
7581         ok(hr == E_POINTER, "Error: GetDomain returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
7582
7583         hr = IUri_GetExtension(uri, NULL);
7584         ok(hr == E_POINTER, "Error: GetExtension returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
7585
7586         hr = IUri_GetFragment(uri, NULL);
7587         ok(hr == E_POINTER, "Error: GetFragment returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
7588
7589         hr = IUri_GetHost(uri, NULL);
7590         ok(hr == E_POINTER, "Error: GetHost returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
7591
7592         hr = IUri_GetPassword(uri, NULL);
7593         ok(hr == E_POINTER, "Error: GetPassword returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
7594
7595         hr = IUri_GetPath(uri, NULL);
7596         ok(hr == E_POINTER, "Error: GetPath returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
7597
7598         hr = IUri_GetPathAndQuery(uri, NULL);
7599         ok(hr == E_POINTER, "Error: GetPathAndQuery returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
7600
7601         hr = IUri_GetQuery(uri, NULL);
7602         ok(hr == E_POINTER, "Error: GetQuery returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
7603
7604         hr = IUri_GetRawUri(uri, NULL);
7605         ok(hr == E_POINTER, "Error: GetRawUri returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
7606
7607         hr = IUri_GetSchemeName(uri, NULL);
7608         ok(hr == E_POINTER, "Error: GetSchemeName returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
7609
7610         hr = IUri_GetUserInfo(uri, NULL);
7611         ok(hr == E_POINTER, "Error: GetUserInfo returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
7612
7613         hr = IUri_GetUserName(uri, NULL);
7614         ok(hr == E_POINTER, "Error: GetUserName returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
7615     }
7616     if(uri) IUri_Release(uri);
7617
7618     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
7619         uri_properties test = uri_tests[i];
7620         LPWSTR uriW;
7621         uri = NULL;
7622
7623         uriW = a2w(test.uri);
7624         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
7625         if(test.create_todo) {
7626             todo_wine {
7627                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7628                         hr, test.create_expected, i);
7629             }
7630         } else {
7631             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7632                     hr, test.create_expected, i);
7633         }
7634
7635         if(SUCCEEDED(hr)) {
7636             uri_str_property prop;
7637             BSTR received = NULL;
7638
7639             /* GetAbsoluteUri() tests. */
7640             prop = test.str_props[Uri_PROPERTY_ABSOLUTE_URI];
7641             hr = IUri_GetAbsoluteUri(uri, &received);
7642             if(prop.todo) {
7643                 todo_wine {
7644                     ok(hr == prop.expected, "Error: GetAbsoluteUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7645                             hr, prop.expected, i);
7646                 }
7647                 todo_wine {
7648                     ok(!strcmp_aw(prop.value, received) || broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
7649                             "Error: Expected %s but got %s on uri_tests[%d].\n",
7650                             prop.value, wine_dbgstr_w(received), i);
7651                 }
7652             } else {
7653                 ok(hr == prop.expected, "Error: GetAbsoluteUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7654                         hr, prop.expected, i);
7655                 ok(!strcmp_aw(prop.value, received) || broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
7656                         "Error: Expected %s but got %s on uri_tests[%d].\n",
7657                         prop.value, wine_dbgstr_w(received), i);
7658             }
7659             SysFreeString(received);
7660             received = NULL;
7661
7662             /* GetAuthority() tests. */
7663             prop = test.str_props[Uri_PROPERTY_AUTHORITY];
7664             hr = IUri_GetAuthority(uri, &received);
7665             if(prop.todo) {
7666                 todo_wine {
7667                     ok(hr == prop.expected, "Error: GetAuthority returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7668                             hr, prop.expected, i);
7669                 }
7670                 todo_wine {
7671                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
7672                             prop.value, wine_dbgstr_w(received), i);
7673                 }
7674             } else {
7675                 ok(hr == prop.expected, "Error: GetAuthority returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7676                         hr, prop.expected, i);
7677                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
7678                         prop.value, wine_dbgstr_w(received), i);
7679             }
7680             SysFreeString(received);
7681             received = NULL;
7682
7683             /* GetDisplayUri() tests. */
7684             prop = test.str_props[Uri_PROPERTY_DISPLAY_URI];
7685             hr = IUri_GetDisplayUri(uri, &received);
7686             if(prop.todo) {
7687                 todo_wine {
7688                     ok(hr == prop.expected, "Error: GetDisplayUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7689                             hr, prop.expected, i);
7690                 }
7691                 todo_wine {
7692                     ok(!strcmp_aw(prop.value, received) || broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
7693                             "Error: Expected %s but got %s on uri_test[%d].\n",
7694                             prop.value, wine_dbgstr_w(received), i);
7695                 }
7696             } else {
7697                 ok(hr == prop.expected, "Error: GetDisplayUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7698                         hr, prop.expected, i);
7699                 ok(!strcmp_aw(prop.value, received) || broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
7700                         "Error: Expected %s but got %s on uri_tests[%d].\n",
7701                         prop.value, wine_dbgstr_w(received), i);
7702             }
7703             SysFreeString(received);
7704             received = NULL;
7705
7706             /* GetDomain() tests. */
7707             prop = test.str_props[Uri_PROPERTY_DOMAIN];
7708             hr = IUri_GetDomain(uri, &received);
7709             if(prop.todo) {
7710                 todo_wine {
7711                     ok(hr == prop.expected, "Error: GetDomain returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7712                             hr, prop.expected, i);
7713                 }
7714                 todo_wine {
7715                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
7716                             prop.value, wine_dbgstr_w(received), i);
7717                 }
7718             } else {
7719                 ok(hr == prop.expected, "Error: GetDomain returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7720                         hr, prop.expected, i);
7721                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
7722                         prop.value, wine_dbgstr_w(received), i);
7723             }
7724             SysFreeString(received);
7725             received = NULL;
7726
7727             /* GetExtension() tests. */
7728             prop = test.str_props[Uri_PROPERTY_EXTENSION];
7729             hr = IUri_GetExtension(uri, &received);
7730             if(prop.todo) {
7731                 todo_wine {
7732                     ok(hr == prop.expected, "Error: GetExtension returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7733                             hr, prop.expected, i);
7734                 }
7735                 todo_wine {
7736                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
7737                             prop.value, wine_dbgstr_w(received), i);
7738                 }
7739             } else {
7740                 ok(hr == prop.expected, "Error: GetExtension returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7741                         hr, prop.expected, i);
7742                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
7743                         prop.value, wine_dbgstr_w(received), i);
7744             }
7745             SysFreeString(received);
7746             received = NULL;
7747
7748             /* GetFragment() tests. */
7749             prop = test.str_props[Uri_PROPERTY_FRAGMENT];
7750             hr = IUri_GetFragment(uri, &received);
7751             if(prop.todo) {
7752                 todo_wine {
7753                     ok(hr == prop.expected, "Error: GetFragment returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7754                             hr, prop.expected, i);
7755                 }
7756                 todo_wine {
7757                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
7758                             prop.value, wine_dbgstr_w(received), i);
7759                 }
7760             } else {
7761                 ok(hr == prop.expected, "Error: GetFragment returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7762                         hr, prop.expected, i);
7763                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
7764                         prop.value, wine_dbgstr_w(received), i);
7765             }
7766             SysFreeString(received);
7767             received = NULL;
7768
7769             /* GetHost() tests. */
7770             prop = test.str_props[Uri_PROPERTY_HOST];
7771             hr = IUri_GetHost(uri, &received);
7772             if(prop.todo) {
7773                 todo_wine {
7774                     ok(hr == prop.expected, "Error: GetHost returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7775                             hr, prop.expected, i);
7776                 }
7777                 todo_wine {
7778                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
7779                             prop.value, wine_dbgstr_w(received), i);
7780                 }
7781             } else {
7782                 ok(hr == prop.expected, "Error: GetHost returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7783                         hr, prop.expected, i);
7784                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
7785                         prop.value, wine_dbgstr_w(received), i);
7786             }
7787             SysFreeString(received);
7788             received = NULL;
7789
7790             /* GetPassword() tests. */
7791             prop = test.str_props[Uri_PROPERTY_PASSWORD];
7792             hr = IUri_GetPassword(uri, &received);
7793             if(prop.todo) {
7794                 todo_wine {
7795                     ok(hr == prop.expected, "Error: GetPassword returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7796                             hr, prop.expected, i);
7797                 }
7798                 todo_wine {
7799                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
7800                             prop.value, wine_dbgstr_w(received), i);
7801                 }
7802             } else {
7803                 ok(hr == prop.expected, "Error: GetPassword returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7804                         hr, prop.expected, i);
7805                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
7806                         prop.value, wine_dbgstr_w(received), i);
7807             }
7808             SysFreeString(received);
7809             received = NULL;
7810
7811             /* GetPath() tests. */
7812             prop = test.str_props[Uri_PROPERTY_PATH];
7813             hr = IUri_GetPath(uri, &received);
7814             if(prop.todo) {
7815                 todo_wine {
7816                     ok(hr == prop.expected, "Error: GetPath returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7817                             hr, prop.expected, i);
7818                 }
7819                 todo_wine {
7820                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
7821                             prop.value, wine_dbgstr_w(received), i);
7822                 }
7823             } else {
7824                 ok(hr == prop.expected, "Error: GetPath returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7825                         hr, prop.expected, i);
7826                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
7827                         prop.value, wine_dbgstr_w(received), i);
7828             }
7829             SysFreeString(received);
7830             received = NULL;
7831
7832             /* GetPathAndQuery() tests. */
7833             prop = test.str_props[Uri_PROPERTY_PATH_AND_QUERY];
7834             hr = IUri_GetPathAndQuery(uri, &received);
7835             if(prop.todo) {
7836                 todo_wine {
7837                     ok(hr == prop.expected, "Error: GetPathAndQuery returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7838                             hr, prop.expected, i);
7839                 }
7840                 todo_wine {
7841                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
7842                             prop.value, wine_dbgstr_w(received), i);
7843                 }
7844             } else {
7845                 ok(hr == prop.expected, "Error: GetPathAndQuery returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7846                         hr, prop.expected, i);
7847                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
7848                         prop.value, wine_dbgstr_w(received), i);
7849             }
7850             SysFreeString(received);
7851             received = NULL;
7852
7853             /* GetQuery() tests. */
7854             prop = test.str_props[Uri_PROPERTY_QUERY];
7855             hr = IUri_GetQuery(uri, &received);
7856             if(prop.todo) {
7857                 todo_wine {
7858                     ok(hr == prop.expected, "Error: GetQuery returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7859                             hr, prop.expected, i);
7860                 }
7861                 todo_wine {
7862                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
7863                             prop.value, wine_dbgstr_w(received), i);
7864                 }
7865             } else {
7866                 ok(hr == prop.expected, "Error: GetQuery returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7867                         hr, prop.expected, i);
7868                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
7869                         prop.value, wine_dbgstr_w(received), i);
7870             }
7871             SysFreeString(received);
7872             received = NULL;
7873
7874             /* GetRawUri() tests. */
7875             prop = test.str_props[Uri_PROPERTY_RAW_URI];
7876             hr = IUri_GetRawUri(uri, &received);
7877             if(prop.todo) {
7878                 todo_wine {
7879                     ok(hr == prop.expected, "Error: GetRawUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7880                             hr, prop.expected, i);
7881                 }
7882                 todo_wine {
7883                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
7884                             prop.value, wine_dbgstr_w(received), i);
7885                 }
7886             } else {
7887                 ok(hr == prop.expected, "Error: GetRawUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7888                         hr, prop.expected, i);
7889                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
7890                         prop.value, wine_dbgstr_w(received), i);
7891             }
7892             SysFreeString(received);
7893             received = NULL;
7894
7895             /* GetSchemeName() tests. */
7896             prop = test.str_props[Uri_PROPERTY_SCHEME_NAME];
7897             hr = IUri_GetSchemeName(uri, &received);
7898             if(prop.todo) {
7899                 todo_wine {
7900                     ok(hr == prop.expected, "Error: GetSchemeName returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7901                             hr, prop.expected, i);
7902                 }
7903                 todo_wine {
7904                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
7905                             prop.value, wine_dbgstr_w(received), i);
7906                 }
7907             } else {
7908                 ok(hr == prop.expected, "Error: GetSchemeName returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7909                         hr, prop.expected, i);
7910                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
7911                         prop.value, wine_dbgstr_w(received), i);
7912             }
7913             SysFreeString(received);
7914             received = NULL;
7915
7916             /* GetUserInfo() tests. */
7917             prop = test.str_props[Uri_PROPERTY_USER_INFO];
7918             hr = IUri_GetUserInfo(uri, &received);
7919             if(prop.todo) {
7920                 todo_wine {
7921                     ok(hr == prop.expected, "Error: GetUserInfo returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7922                             hr, prop.expected, i);
7923                 }
7924                 todo_wine {
7925                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
7926                             prop.value, wine_dbgstr_w(received), i);
7927                 }
7928             } else {
7929                 ok(hr == prop.expected, "Error: GetUserInfo returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7930                         hr, prop.expected, i);
7931                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
7932                         prop.value, wine_dbgstr_w(received), i);
7933             }
7934             SysFreeString(received);
7935             received = NULL;
7936
7937             /* GetUserName() tests. */
7938             prop = test.str_props[Uri_PROPERTY_USER_NAME];
7939             hr = IUri_GetUserName(uri, &received);
7940             if(prop.todo) {
7941                 todo_wine {
7942                     ok(hr == prop.expected, "Error: GetUserName returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7943                             hr, prop.expected, i);
7944                 }
7945                 todo_wine {
7946                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
7947                             prop.value, wine_dbgstr_w(received), i);
7948                 }
7949             } else {
7950                 ok(hr == prop.expected, "Error: GetUserName returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7951                         hr, prop.expected, i);
7952                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
7953                         prop.value, wine_dbgstr_w(received), i);
7954             }
7955             SysFreeString(received);
7956         }
7957
7958         if(uri) IUri_Release(uri);
7959
7960         heap_free(uriW);
7961     }
7962 }
7963
7964 static void test_IUri_GetDwordProperties(void) {
7965     IUri *uri = NULL;
7966     HRESULT hr;
7967     DWORD i;
7968
7969     /* Make sure all the 'Get*' dword property functions handle invalid args correctly. */
7970     hr = pCreateUri(http_urlW, 0, 0, &uri);
7971     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7972     if(SUCCEEDED(hr)) {
7973         hr = IUri_GetHostType(uri, NULL);
7974         ok(hr == E_INVALIDARG, "Error: GetHostType returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
7975
7976         hr = IUri_GetPort(uri, NULL);
7977         ok(hr == E_INVALIDARG, "Error: GetPort returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
7978
7979         hr = IUri_GetScheme(uri, NULL);
7980         ok(hr == E_INVALIDARG, "Error: GetScheme returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
7981
7982         hr = IUri_GetZone(uri, NULL);
7983         ok(hr == E_INVALIDARG, "Error: GetZone returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
7984     }
7985     if(uri) IUri_Release(uri);
7986
7987     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
7988         uri_properties test = uri_tests[i];
7989         LPWSTR uriW;
7990         uri = NULL;
7991
7992         uriW = a2w(test.uri);
7993         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
7994         if(test.create_todo) {
7995             todo_wine {
7996                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7997                         hr, test.create_expected, i);
7998             }
7999         } else {
8000             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
8001                     hr, test.create_expected, i);
8002         }
8003
8004         if(SUCCEEDED(hr)) {
8005             uri_dword_property prop;
8006             DWORD received;
8007
8008             /* Assign an insane value so tests don't accidentally pass when
8009              * they shouldn't!
8010              */
8011             received = -9999999;
8012
8013             /* GetHostType() tests. */
8014             prop = test.dword_props[Uri_PROPERTY_HOST_TYPE-Uri_PROPERTY_DWORD_START];
8015             hr = IUri_GetHostType(uri, &received);
8016             if(prop.todo) {
8017                 todo_wine {
8018                     ok(hr == prop.expected, "Error: GetHostType returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
8019                             hr, prop.expected, i);
8020                 }
8021                 todo_wine {
8022                     ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
8023                 }
8024             } else {
8025                 ok(hr == prop.expected, "Error: GetHostType returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
8026                         hr, prop.expected, i);
8027                 ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
8028             }
8029             received = -9999999;
8030
8031             /* GetPort() tests. */
8032             prop = test.dword_props[Uri_PROPERTY_PORT-Uri_PROPERTY_DWORD_START];
8033             hr = IUri_GetPort(uri, &received);
8034             if(prop.todo) {
8035                 todo_wine {
8036                     ok(hr == prop.expected, "Error: GetPort returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
8037                             hr, prop.expected, i);
8038                 }
8039                 todo_wine {
8040                     ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
8041                 }
8042             } else {
8043                 ok(hr == prop.expected, "Error: GetPort returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
8044                         hr, prop.expected, i);
8045                 ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
8046             }
8047             received = -9999999;
8048
8049             /* GetScheme() tests. */
8050             prop = test.dword_props[Uri_PROPERTY_SCHEME-Uri_PROPERTY_DWORD_START];
8051             hr = IUri_GetScheme(uri, &received);
8052             if(prop.todo) {
8053                 todo_wine {
8054                     ok(hr == prop.expected, "Error: GetScheme returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
8055                             hr, prop.expected, i);
8056                 }
8057                 todo_wine {
8058                     ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
8059                 }
8060             } else {
8061                 ok(hr == prop.expected, "Error: GetScheme returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
8062                         hr, prop.expected, i);
8063                 ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
8064             }
8065             received = -9999999;
8066
8067             /* GetZone() tests. */
8068             prop = test.dword_props[Uri_PROPERTY_ZONE-Uri_PROPERTY_DWORD_START];
8069             hr = IUri_GetZone(uri, &received);
8070             if(prop.todo) {
8071                 todo_wine {
8072                     ok(hr == prop.expected, "Error: GetZone returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
8073                             hr, prop.expected, i);
8074                 }
8075                 todo_wine {
8076                     ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
8077                 }
8078             } else {
8079                 ok(hr == prop.expected, "Error: GetZone returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
8080                         hr, prop.expected, i);
8081                 ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
8082             }
8083         }
8084
8085         if(uri) IUri_Release(uri);
8086
8087         heap_free(uriW);
8088     }
8089 }
8090
8091 static void test_IUri_GetPropertyLength(void) {
8092     IUri *uri = NULL;
8093     HRESULT hr;
8094     DWORD i;
8095
8096     /* Make sure it handles invalid args correctly. */
8097     hr = pCreateUri(http_urlW, 0, 0, &uri);
8098     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8099     if(SUCCEEDED(hr)) {
8100         DWORD received = 0xdeadbeef;
8101
8102         hr = IUri_GetPropertyLength(uri, Uri_PROPERTY_STRING_START, NULL, 0);
8103         ok(hr == E_INVALIDARG, "Error: GetPropertyLength returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
8104
8105         hr = IUri_GetPropertyLength(uri, Uri_PROPERTY_DWORD_START, &received, 0);
8106         ok(hr == E_INVALIDARG, "Error: GetPropertyLength return 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
8107         ok(received == 0xdeadbeef, "Error: Expected 0xdeadbeef but got 0x%08x.\n", received);
8108     }
8109     if(uri) IUri_Release(uri);
8110
8111     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
8112         uri_properties test = uri_tests[i];
8113         LPWSTR uriW;
8114         uri = NULL;
8115
8116         uriW = a2w(test.uri);
8117         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
8118         if(test.create_todo) {
8119             todo_wine {
8120                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
8121                         hr, test.create_expected, i);
8122             }
8123         } else {
8124             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_test[%d].\n",
8125                     hr, test.create_expected, i);
8126         }
8127
8128         if(SUCCEEDED(hr)) {
8129             DWORD j;
8130
8131             for(j = Uri_PROPERTY_STRING_START; j <= Uri_PROPERTY_STRING_LAST; ++j) {
8132                 DWORD expectedLen, brokenLen, receivedLen;
8133                 uri_str_property prop = test.str_props[j];
8134
8135                 expectedLen = lstrlen(prop.value);
8136                 brokenLen = lstrlen(prop.broken_value);
8137
8138                 /* This won't be necessary once GetPropertyLength is implemented. */
8139                 receivedLen = -1;
8140
8141                 hr = IUri_GetPropertyLength(uri, j, &receivedLen, 0);
8142                 if(prop.todo) {
8143                     todo_wine {
8144                         ok(hr == prop.expected, "Error: GetPropertyLength returned 0x%08x, expected 0x%08x on uri_tests[%d].str_props[%d].\n",
8145                                 hr, prop.expected, i, j);
8146                     }
8147                     todo_wine {
8148                         ok(receivedLen == expectedLen || broken(receivedLen == brokenLen),
8149                                 "Error: Expected a length of %d but got %d on uri_tests[%d].str_props[%d].\n",
8150                                 expectedLen, receivedLen, i, j);
8151                     }
8152                 } else {
8153                     ok(hr == prop.expected, "Error: GetPropertyLength returned 0x%08x, expected 0x%08x on uri_tests[%d].str_props[%d].\n",
8154                             hr, prop.expected, i, j);
8155                     ok(receivedLen == expectedLen || broken(receivedLen == brokenLen),
8156                             "Error: Expected a length of %d but got %d on uri_tests[%d].str_props[%d].\n",
8157                             expectedLen, receivedLen, i, j);
8158                 }
8159             }
8160         }
8161
8162         if(uri) IUri_Release(uri);
8163
8164         heap_free(uriW);
8165     }
8166 }
8167
8168 static DWORD compute_expected_props(uri_properties *test)
8169 {
8170     DWORD ret = 0, i;
8171
8172     for(i=Uri_PROPERTY_STRING_START; i <= Uri_PROPERTY_STRING_LAST; i++) {
8173         if(test->str_props[i-Uri_PROPERTY_STRING_START].expected == S_OK)
8174             ret |= 1<<i;
8175     }
8176
8177     for(i=Uri_PROPERTY_DWORD_START; i <= Uri_PROPERTY_DWORD_LAST; i++) {
8178         if(test->dword_props[i-Uri_PROPERTY_DWORD_START].expected == S_OK)
8179             ret |= 1<<i;
8180     }
8181
8182     return ret;
8183 }
8184
8185 static void test_IUri_GetProperties(void) {
8186     IUri *uri = NULL;
8187     HRESULT hr;
8188     DWORD i;
8189
8190     hr = pCreateUri(http_urlW, 0, 0, &uri);
8191     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8192     if(SUCCEEDED(hr)) {
8193         hr = IUri_GetProperties(uri, NULL);
8194         ok(hr == E_INVALIDARG, "Error: GetProperties returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
8195     }
8196     if(uri) IUri_Release(uri);
8197
8198     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
8199         uri_properties test = uri_tests[i];
8200         LPWSTR uriW;
8201         uri = NULL;
8202
8203         uriW = a2w(test.uri);
8204         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
8205         if(test.create_todo) {
8206             todo_wine {
8207                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, test.create_expected);
8208             }
8209         } else {
8210             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, test.create_expected);
8211         }
8212
8213         if(SUCCEEDED(hr)) {
8214             DWORD received = 0, expected_props;
8215             DWORD j;
8216
8217             hr = IUri_GetProperties(uri, &received);
8218             ok(hr == S_OK, "Error: GetProperties returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8219
8220             expected_props = compute_expected_props(&test);
8221
8222             for(j = 0; j <= Uri_PROPERTY_DWORD_LAST; ++j) {
8223                 /* (1 << j) converts a Uri_PROPERTY to its corresponding Uri_HAS_* flag mask. */
8224                 if(expected_props & (1 << j))
8225                     ok(received & (1 << j), "Error: Expected flag for property %d on uri_tests[%d].\n", j, i);
8226                 else
8227                     ok(!(received & (1 << j)), "Error: Received flag for property %d when not expected on uri_tests[%d].\n", j, i);
8228             }
8229         }
8230
8231         if(uri) IUri_Release(uri);
8232
8233         heap_free(uriW);
8234     }
8235 }
8236
8237 static void test_IUri_HasProperty(void) {
8238     IUri *uri = NULL;
8239     HRESULT hr;
8240     DWORD i;
8241
8242     hr = pCreateUri(http_urlW, 0, 0, &uri);
8243     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8244     if(SUCCEEDED(hr)) {
8245         hr = IUri_HasProperty(uri, Uri_PROPERTY_RAW_URI, NULL);
8246         ok(hr == E_INVALIDARG, "Error: HasProperty returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
8247     }
8248     if(uri) IUri_Release(uri);
8249
8250     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
8251         uri_properties test = uri_tests[i];
8252         LPWSTR uriW;
8253         uri = NULL;
8254
8255         uriW = a2w(test.uri);
8256
8257         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
8258         if(test.create_todo) {
8259             todo_wine {
8260                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, test.create_expected);
8261             }
8262         } else {
8263             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, test.create_expected);
8264         }
8265
8266         if(SUCCEEDED(hr)) {
8267             DWORD expected_props, j;
8268
8269             expected_props = compute_expected_props(&test);
8270
8271             for(j = 0; j <= Uri_PROPERTY_DWORD_LAST; ++j) {
8272                 /* Assign -1, then explicitly test for TRUE or FALSE later. */
8273                 BOOL received = -1;
8274
8275                 hr = IUri_HasProperty(uri, j, &received);
8276                 ok(hr == S_OK, "Error: HasProperty returned 0x%08x, expected 0x%08x for property %d on uri_tests[%d].\n",
8277                         hr, S_OK, j, i);
8278
8279                 if(expected_props & (1 << j)) {
8280                     ok(received == TRUE, "Error: Expected to have property %d on uri_tests[%d].\n", j, i);
8281                 } else {
8282                     ok(received == FALSE, "Error: Wasn't expecting to have property %d on uri_tests[%d].\n", j, i);
8283                 }
8284             }
8285         }
8286
8287         if(uri) IUri_Release(uri);
8288
8289         heap_free(uriW);
8290     }
8291 }
8292
8293 static void test_IUri_IsEqual(void) {
8294     IUri *uriA, *uriB;
8295     BOOL equal;
8296     HRESULT hres;
8297     DWORD i;
8298
8299     uriA = uriB = NULL;
8300
8301     /* Make sure IsEqual handles invalid args correctly. */
8302     hres = pCreateUri(http_urlW, 0, 0, &uriA);
8303     ok(hres == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hres, S_OK);
8304     hres = pCreateUri(http_urlW, 0, 0, &uriB);
8305     ok(hres == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hres, S_OK);
8306
8307     equal = -1;
8308     hres = IUri_IsEqual(uriA, NULL, &equal);
8309     ok(hres == S_OK, "Error: IsEqual returned 0x%08x, expected 0x%08x.\n", hres, S_OK);
8310     ok(!equal, "Error: Expected equal to be FALSE, but was %d instead.\n", equal);
8311
8312     hres = IUri_IsEqual(uriA, uriB, NULL);
8313     ok(hres == E_POINTER, "Error: IsEqual returned 0x%08x, expected 0x%08x.\n", hres, E_POINTER);
8314
8315     IUri_Release(uriA);
8316     IUri_Release(uriB);
8317
8318     for(i = 0; i < sizeof(equality_tests)/sizeof(equality_tests[0]); ++i) {
8319         uri_equality test = equality_tests[i];
8320         LPWSTR uriA_W, uriB_W;
8321
8322         uriA = uriB = NULL;
8323
8324         uriA_W = a2w(test.a);
8325         uriB_W = a2w(test.b);
8326
8327         hres = pCreateUri(uriA_W, test.create_flags_a, 0, &uriA);
8328         ok(hres == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x on equality_tests[%d].a\n", hres, S_OK, i);
8329
8330         hres = pCreateUri(uriB_W, test.create_flags_b, 0, &uriB);
8331         ok(hres == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x on equality_tests[%d].b\n", hres, S_OK, i);
8332
8333         equal = -1;
8334         hres = IUri_IsEqual(uriA, uriB, &equal);
8335         if(test.todo) todo_wine {
8336             ok(hres == S_OK, "Error: IsEqual returned 0x%08x, expected 0x%08x on equality_tests[%d].\n", hres, S_OK, i);
8337             ok(equal == test.equal, "Error: Expected the comparison to be %d on equality_tests[%d].\n", test.equal, i);
8338         } else {
8339             ok(hres == S_OK, "Error: IsEqual returned 0x%08x, expected 0x%08x on equality_tests[%d].\n", hres, S_OK, i);
8340             ok(equal == test.equal, "Error: Expected the comparison to be %d on equality_tests[%d].\n", test.equal, i);
8341         }
8342         if(uriA) IUri_Release(uriA);
8343         if(uriB) IUri_Release(uriB);
8344
8345         heap_free(uriA_W);
8346         heap_free(uriB_W);
8347     }
8348 }
8349
8350 static void test_CreateUriWithFragment_InvalidArgs(void) {
8351     HRESULT hr;
8352     IUri *uri = (void*) 0xdeadbeef;
8353     const WCHAR fragmentW[] = {'#','f','r','a','g','m','e','n','t',0};
8354
8355     hr = pCreateUriWithFragment(NULL, fragmentW, 0, 0, &uri);
8356     ok(hr == E_INVALIDARG, "Error: CreateUriWithFragment returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
8357     ok(uri == NULL, "Error: Expected uri to be NULL, but was %p instead.\n", uri);
8358
8359     hr = pCreateUriWithFragment(http_urlW, fragmentW, 0, 0, NULL);
8360     ok(hr == E_INVALIDARG, "Error: CreateUriWithFragment returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
8361
8362     /* Original URI can't already contain a fragment component. */
8363     uri = (void*) 0xdeadbeef;
8364     hr = pCreateUriWithFragment(http_url_fragW, fragmentW, 0, 0, &uri);
8365     ok(hr == E_INVALIDARG, "Error: CreateUriWithFragment returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
8366     ok(uri == NULL, "Error: Expected uri to be NULL, but was %p instead.\n", uri);
8367 }
8368
8369 /* CreateUriWithFragment has the same invalid flag combinations as CreateUri. */
8370 static void test_CreateUriWithFragment_InvalidFlags(void) {
8371     DWORD i;
8372
8373     for(i = 0; i < sizeof(invalid_flag_tests)/sizeof(invalid_flag_tests[0]); ++i) {
8374         HRESULT hr;
8375         IUri *uri = (void*) 0xdeadbeef;
8376
8377         hr = pCreateUriWithFragment(http_urlW, NULL, invalid_flag_tests[i].flags, 0, &uri);
8378         ok(hr == invalid_flag_tests[i].expected, "Error: CreateUriWithFragment returned 0x%08x, expected 0x%08x. flags=0x%08x.\n",
8379             hr, invalid_flag_tests[i].expected, invalid_flag_tests[i].flags);
8380         ok(uri == NULL, "Error: Expected uri to be NULL, but was %p instead.\n", uri);
8381     }
8382 }
8383
8384 static void test_CreateUriWithFragment(void) {
8385     DWORD i;
8386
8387     for(i = 0; i < sizeof(uri_fragment_tests)/sizeof(uri_fragment_tests[0]); ++i) {
8388         HRESULT hr;
8389         IUri *uri = NULL;
8390         LPWSTR uriW, fragW;
8391         uri_with_fragment test = uri_fragment_tests[i];
8392
8393         uriW = a2w(test.uri);
8394         fragW = a2w(test.fragment);
8395
8396         hr = pCreateUriWithFragment(uriW, fragW, test.create_flags, 0, &uri);
8397         if(test.expected_todo) {
8398             todo_wine {
8399                 ok(hr == test.create_expected,
8400                     "Error: CreateUriWithFragment returned 0x%08x, expected 0x%08x on uri_fragment_tests[%d].\n",
8401                     hr, test.create_expected, i);
8402             }
8403         } else
8404             ok(hr == test.create_expected,
8405                 "Error: CreateUriWithFragment returned 0x%08x, expected 0x%08x on uri_fragment_tests[%d].\n",
8406                 hr, test.create_expected, i);
8407
8408         if(SUCCEEDED(hr)) {
8409             BSTR received = NULL;
8410
8411             hr = IUri_GetAbsoluteUri(uri, &received);
8412             if(test.expected_todo) {
8413                 todo_wine {
8414                     ok(hr == S_OK,
8415                         "Error: GetAbsoluteUri returned 0x%08x, expected 0x%08x on uri_fragment_tests[%d].\n",
8416                         hr, S_OK, i);
8417                 }
8418                 todo_wine {
8419                     ok(!strcmp_aw(test.expected_uri, received),
8420                         "Error: Expected %s but got %s on uri_fragment_tests[%d].\n",
8421                         test.expected_uri, wine_dbgstr_w(received), i);
8422                 }
8423             } else {
8424                 ok(hr == S_OK, "Error: GetAbsoluteUri returned 0x%08x, expected 0x%08x on uri_fragment_tests[%d].\n",
8425                     hr, S_OK, i);
8426                 ok(!strcmp_aw(test.expected_uri, received), "Error: Expected %s but got %s on uri_fragment_tests[%d].\n",
8427                     test.expected_uri, wine_dbgstr_w(received), i);
8428             }
8429
8430             SysFreeString(received);
8431         }
8432
8433         if(uri) IUri_Release(uri);
8434         heap_free(uriW);
8435         heap_free(fragW);
8436     }
8437 }
8438
8439 static void test_CreateIUriBuilder(void) {
8440     HRESULT hr;
8441     IUriBuilder *builder = NULL;
8442     IUri *uri;
8443
8444     hr = pCreateIUriBuilder(NULL, 0, 0, NULL);
8445     ok(hr == E_POINTER, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x\n",
8446         hr, E_POINTER);
8447
8448     /* CreateIUriBuilder increases the ref count of the IUri it receives. */
8449     hr = pCreateUri(http_urlW, 0, 0, &uri);
8450     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8451     if(SUCCEEDED(hr)) {
8452         ULONG cur_count, orig_count;
8453
8454         orig_count = get_refcnt(uri);
8455         hr = pCreateIUriBuilder(uri, 0, 0, &builder);
8456         ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8457         ok(builder != NULL, "Error: Expecting builder not to be NULL\n");
8458
8459         cur_count = get_refcnt(uri);
8460         ok(cur_count == orig_count+1, "Error: Expected the ref count to be %u, but was %u instead.\n", orig_count+1, cur_count);
8461
8462         if(builder) IUriBuilder_Release(builder);
8463         cur_count = get_refcnt(uri);
8464         ok(cur_count == orig_count, "Error: Expected the ref count to be %u, but was %u instead.\n", orig_count, cur_count);
8465     }
8466     if(uri) IUri_Release(uri);
8467 }
8468
8469 static void test_IUriBuilder_CreateUri(IUriBuilder *builder, const uri_builder_test *test,
8470                                        DWORD test_index) {
8471     HRESULT hr;
8472     IUri *uri = NULL;
8473
8474     hr = IUriBuilder_CreateUri(builder, test->uri_flags, 0, 0, &uri);
8475     if(test->uri_todo) {
8476         todo_wine {
8477             ok(hr == test->uri_hres,
8478                 "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8479                 hr, test->uri_hres, test_index);
8480         }
8481     } else {
8482         ok(hr == test->uri_hres,
8483             "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8484             hr, test->uri_hres, test_index);
8485     }
8486
8487     if(SUCCEEDED(hr)) {
8488         DWORD i;
8489
8490         for(i = 0; i < sizeof(test->expected_str_props)/sizeof(test->expected_str_props[0]); ++i) {
8491             uri_builder_str_property prop = test->expected_str_props[i];
8492             BSTR received = NULL;
8493
8494             hr = IUri_GetPropertyBSTR(uri, i, &received, 0);
8495             if(prop.todo) {
8496                 todo_wine {
8497                     ok(hr == prop.result,
8498                         "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_str_props[%d].\n",
8499                         hr, prop.result, test_index, i);
8500                 }
8501             } else {
8502                 ok(hr == prop.result,
8503                     "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_str_props[%d].\n",
8504                     hr, prop.result, test_index, i);
8505             }
8506             if(SUCCEEDED(hr)) {
8507                 if(prop.todo) {
8508                     todo_wine {
8509                         ok(!strcmp_aw(prop.expected, received),
8510                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].expected_str_props[%d].\n",
8511                             prop.expected, wine_dbgstr_w(received), test_index, i);
8512                     }
8513                 } else {
8514                     ok(!strcmp_aw(prop.expected, received),
8515                         "Error: Expected %s but got %s instead on uri_builder_tests[%d].expected_str_props[%d].\n",
8516                         prop.expected, wine_dbgstr_w(received), test_index, i);
8517                 }
8518             }
8519             SysFreeString(received);
8520         }
8521
8522         for(i = 0; i < sizeof(test->expected_dword_props)/sizeof(test->expected_dword_props[0]); ++i) {
8523             uri_builder_dword_property prop = test->expected_dword_props[i];
8524             DWORD received = -2;
8525
8526             hr = IUri_GetPropertyDWORD(uri, i+Uri_PROPERTY_DWORD_START, &received, 0);
8527             if(prop.todo) {
8528                 todo_wine {
8529                     ok(hr == prop.result,
8530                         "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_dword_props[%d].\n",
8531                         hr, prop.result, test_index, i);
8532                 }
8533             } else {
8534                 ok(hr == prop.result,
8535                     "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_dword_props[%d].\n",
8536                     hr, prop.result, test_index, i);
8537             }
8538             if(SUCCEEDED(hr)) {
8539                 if(prop.todo) {
8540                     todo_wine {
8541                         ok(received == prop.expected,
8542                             "Error: Expected %d but got %d instead on uri_builder_tests[%d].expected_dword_props[%d].\n",
8543                             prop.expected, received, test_index, i);
8544                     }
8545                 } else {
8546                     ok(received == prop.expected,
8547                         "Error: Expected %d but got %d instead on uri_builder_tests[%d].expected_dword_props[%d].\n",
8548                         prop.expected, received, test_index, i);
8549                 }
8550             }
8551         }
8552     }
8553     if(uri) IUri_Release(uri);
8554 }
8555
8556 static void test_IUriBuilder_CreateUriSimple(IUriBuilder *builder, const uri_builder_test *test,
8557                                        DWORD test_index) {
8558     HRESULT hr;
8559     IUri *uri = NULL;
8560
8561     hr = IUriBuilder_CreateUriSimple(builder, test->uri_simple_encode_flags, 0, &uri);
8562     if(test->uri_simple_todo) {
8563         todo_wine {
8564             ok(hr == test->uri_simple_hres,
8565                 "Error: IUriBuilder_CreateUriSimple returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8566                 hr, test->uri_simple_hres, test_index);
8567         }
8568     } else {
8569         ok(hr == test->uri_simple_hres,
8570             "Error: IUriBuilder_CreateUriSimple returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8571             hr, test->uri_simple_hres, test_index);
8572     }
8573
8574     if(SUCCEEDED(hr)) {
8575         DWORD i;
8576
8577         for(i = 0; i < sizeof(test->expected_str_props)/sizeof(test->expected_str_props[0]); ++i) {
8578             uri_builder_str_property prop = test->expected_str_props[i];
8579             BSTR received = NULL;
8580
8581             hr = IUri_GetPropertyBSTR(uri, i, &received, 0);
8582             if(prop.todo) {
8583                 todo_wine {
8584                     ok(hr == prop.result,
8585                         "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_str_props[%d].\n",
8586                         hr, prop.result, test_index, i);
8587                 }
8588             } else {
8589                 ok(hr == prop.result,
8590                     "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_str_props[%d].\n",
8591                     hr, prop.result, test_index, i);
8592             }
8593             if(SUCCEEDED(hr)) {
8594                 if(prop.todo) {
8595                     todo_wine {
8596                         ok(!strcmp_aw(prop.expected, received),
8597                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].expected_str_props[%d].\n",
8598                             prop.expected, wine_dbgstr_w(received), test_index, i);
8599                     }
8600                 } else {
8601                     ok(!strcmp_aw(prop.expected, received),
8602                         "Error: Expected %s but got %s instead on uri_builder_tests[%d].expected_str_props[%d].\n",
8603                         prop.expected, wine_dbgstr_w(received), test_index, i);
8604                 }
8605             }
8606             SysFreeString(received);
8607         }
8608
8609         for(i = 0; i < sizeof(test->expected_dword_props)/sizeof(test->expected_dword_props[0]); ++i) {
8610             uri_builder_dword_property prop = test->expected_dword_props[i];
8611             DWORD received = -2;
8612
8613             hr = IUri_GetPropertyDWORD(uri, i+Uri_PROPERTY_DWORD_START, &received, 0);
8614             if(prop.todo) {
8615                 todo_wine {
8616                     ok(hr == prop.result,
8617                         "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_dword_props[%d].\n",
8618                         hr, prop.result, test_index, i);
8619                 }
8620             } else {
8621                 ok(hr == prop.result,
8622                     "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_dword_props[%d].\n",
8623                     hr, prop.result, test_index, i);
8624             }
8625             if(SUCCEEDED(hr)) {
8626                 if(prop.todo) {
8627                     todo_wine {
8628                         ok(received == prop.expected,
8629                             "Error: Expected %d but got %d instead on uri_builder_tests[%d].expected_dword_props[%d].\n",
8630                             prop.expected, received, test_index, i);
8631                     }
8632                 } else {
8633                     ok(received == prop.expected,
8634                         "Error: Expected %d but got %d instead on uri_builder_tests[%d].expected_dword_props[%d].\n",
8635                         prop.expected, received, test_index, i);
8636                 }
8637             }
8638         }
8639     }
8640     if(uri) IUri_Release(uri);
8641 }
8642
8643 static void test_IUriBuilder_CreateUriWithFlags(IUriBuilder *builder, const uri_builder_test *test,
8644                                                 DWORD test_index) {
8645     HRESULT hr;
8646     IUri *uri = NULL;
8647
8648     hr = IUriBuilder_CreateUriWithFlags(builder, test->uri_with_flags, test->uri_with_builder_flags,
8649                                         test->uri_with_encode_flags, 0, &uri);
8650     if(test->uri_with_todo) {
8651         todo_wine {
8652             ok(hr == test->uri_with_hres,
8653                 "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8654                 hr, test->uri_with_hres, test_index);
8655         }
8656     } else {
8657         ok(hr == test->uri_with_hres,
8658             "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8659             hr, test->uri_with_hres, test_index);
8660     }
8661
8662     if(SUCCEEDED(hr)) {
8663         DWORD i;
8664
8665         for(i = 0; i < sizeof(test->expected_str_props)/sizeof(test->expected_str_props[0]); ++i) {
8666             uri_builder_str_property prop = test->expected_str_props[i];
8667             BSTR received = NULL;
8668
8669             hr = IUri_GetPropertyBSTR(uri, i, &received, 0);
8670             if(prop.todo) {
8671                 todo_wine {
8672                     ok(hr == prop.result,
8673                         "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_str_props[%d].\n",
8674                         hr, prop.result, test_index, i);
8675                 }
8676             } else {
8677                 ok(hr == prop.result,
8678                     "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_str_props[%d].\n",
8679                     hr, prop.result, test_index, i);
8680             }
8681             if(SUCCEEDED(hr)) {
8682                 if(prop.todo) {
8683                     todo_wine {
8684                         ok(!strcmp_aw(prop.expected, received),
8685                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].expected_str_props[%d].\n",
8686                             prop.expected, wine_dbgstr_w(received), test_index, i);
8687                     }
8688                 } else {
8689                     ok(!strcmp_aw(prop.expected, received),
8690                         "Error: Expected %s but got %s instead on uri_builder_tests[%d].expected_str_props[%d].\n",
8691                         prop.expected, wine_dbgstr_w(received), test_index, i);
8692                 }
8693             }
8694             SysFreeString(received);
8695         }
8696
8697         for(i = 0; i < sizeof(test->expected_dword_props)/sizeof(test->expected_dword_props[0]); ++i) {
8698             uri_builder_dword_property prop = test->expected_dword_props[i];
8699             DWORD received = -2;
8700
8701             hr = IUri_GetPropertyDWORD(uri, i+Uri_PROPERTY_DWORD_START, &received, 0);
8702             if(prop.todo) {
8703                 todo_wine {
8704                     ok(hr == prop.result,
8705                         "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_dword_props[%d].\n",
8706                         hr, prop.result, test_index, i);
8707                 }
8708             } else {
8709                 ok(hr == prop.result,
8710                     "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_dword_props[%d].\n",
8711                     hr, prop.result, test_index, i);
8712             }
8713             if(SUCCEEDED(hr)) {
8714                 if(prop.todo) {
8715                     todo_wine {
8716                         ok(received == prop.expected,
8717                             "Error: Expected %d but got %d instead on uri_builder_tests[%d].expected_dword_props[%d].\n",
8718                             prop.expected, received, test_index, i);
8719                     }
8720                 } else {
8721                     ok(received == prop.expected,
8722                         "Error: Expected %d but got %d instead on uri_builder_tests[%d].expected_dword_props[%d].\n",
8723                         prop.expected, received, test_index, i);
8724                 }
8725             }
8726         }
8727     }
8728     if(uri) IUri_Release(uri);
8729 }
8730
8731 static void test_IUriBuilder_CreateInvalidArgs(void) {
8732     IUriBuilder *builder;
8733     HRESULT hr;
8734
8735     hr = pCreateIUriBuilder(NULL, 0, 0, &builder);
8736     ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8737     if(SUCCEEDED(hr)) {
8738         IUri *test = NULL, *uri = (void*) 0xdeadbeef;
8739
8740         /* Test what happens if the IUriBuilder doesn't have a IUri set. */
8741         hr = IUriBuilder_CreateUri(builder, 0, 0, 0, NULL);
8742         ok(hr == E_POINTER, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
8743
8744         uri = (void*) 0xdeadbeef;
8745         hr = IUriBuilder_CreateUri(builder, 0, Uri_HAS_USER_NAME, 0, &uri);
8746         ok(hr == E_NOTIMPL, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, E_NOTIMPL);
8747         ok(uri == NULL, "Error: expected uri to be NULL, but was %p instead.\n", uri);
8748
8749         hr = IUriBuilder_CreateUriSimple(builder, 0, 0, NULL);
8750         ok(hr == E_POINTER, "Error: IUriBuilder_CreateUriSimple returned 0x%08x, expected 0x%08x.\n",
8751             hr, E_POINTER);
8752
8753         uri = (void*) 0xdeadbeef;
8754         hr = IUriBuilder_CreateUriSimple(builder, Uri_HAS_USER_NAME, 0, &uri);
8755         ok(hr == E_NOTIMPL, "Error: IUriBuilder_CreateUriSimple returned 0x%08x, expected 0x%08x.\n",
8756             hr, E_NOTIMPL);
8757         ok(!uri, "Error: Expected uri to NULL, but was %p instead.\n", uri);
8758
8759         hr = IUriBuilder_CreateUriWithFlags(builder, 0, 0, 0, 0, NULL);
8760         ok(hr == E_POINTER, "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x.\n",
8761             hr, E_POINTER);
8762
8763         uri = (void*) 0xdeadbeef;
8764         hr = IUriBuilder_CreateUriWithFlags(builder, 0, 0, Uri_HAS_USER_NAME, 0, &uri);
8765         ok(hr == E_NOTIMPL, "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x.\n",
8766             hr, E_NOTIMPL);
8767         ok(!uri, "Error: Expected uri to be NULL, but was %p instead.\n", uri);
8768
8769         hr = pCreateUri(http_urlW, 0, 0, &test);
8770         ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8771         if(SUCCEEDED(hr)) {
8772             hr = IUriBuilder_SetIUri(builder, test);
8773             ok(hr == S_OK, "Error: IUriBuilder_SetIUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8774
8775             /* No longer returns E_NOTIMPL, since a IUri has been set and hasn't been modified. */
8776             uri = NULL;
8777             hr = IUriBuilder_CreateUri(builder, 0, Uri_HAS_USER_NAME, 0, &uri);
8778             ok(hr == S_OK, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8779             ok(uri != NULL, "Error: The uri was NULL.\n");
8780             if(uri) IUri_Release(uri);
8781
8782             uri = NULL;
8783             hr = IUriBuilder_CreateUriSimple(builder, Uri_HAS_USER_NAME, 0, &uri);
8784             ok(hr == S_OK, "Error: IUriBuilder_CreateUriSimple returned 0x%08x, expected 0x%08x.\n",
8785                 hr, S_OK);
8786             ok(uri != NULL, "Error: uri was NULL.\n");
8787             if(uri) IUri_Release(uri);
8788
8789             uri = NULL;
8790             hr = IUriBuilder_CreateUriWithFlags(builder, 0, 0, 0, 0, &uri);
8791             ok(hr == S_OK, "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x.\n",
8792                 hr, S_OK);
8793             ok(uri != NULL, "Error: uri was NULL.\n");
8794             if(uri) IUri_Release(uri);
8795
8796             hr = IUriBuilder_SetFragment(builder, NULL);
8797             ok(hr == S_OK, "Error: IUriBuilder_SetFragment returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8798
8799             /* The IUriBuilder is changed, so it returns E_NOTIMPL again. */
8800             uri = (void*) 0xdeadbeef;
8801             hr = IUriBuilder_CreateUri(builder, 0, Uri_HAS_USER_NAME, 0, &uri);
8802             ok(hr == E_NOTIMPL, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8803             ok(!uri, "Error: Expected uri to be NULL but was %p instead.\n", uri);
8804
8805             uri = (void*) 0xdeadbeef;
8806             hr = IUriBuilder_CreateUriSimple(builder, Uri_HAS_USER_NAME, 0, &uri);
8807             ok(hr == E_NOTIMPL, "Error: IUriBuilder_CreateUriSimple returned 0x%08x, expected 0x%08x.\n",
8808                 hr, S_OK);
8809             ok(!uri, "Error: Expected uri to be NULL, but was %p instead.\n", uri);
8810
8811             uri = (void*) 0xdeadbeef;
8812             hr = IUriBuilder_CreateUriWithFlags(builder, 0, 0, Uri_HAS_USER_NAME, 0, &uri);
8813             ok(hr == E_NOTIMPL, "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x.\n",
8814                 hr, E_NOTIMPL);
8815             ok(!uri, "Error: Expected uri to be NULL, but was %p instead.\n", uri);
8816         }
8817         if(test) IUri_Release(test);
8818     }
8819     if(builder) IUriBuilder_Release(builder);
8820 }
8821
8822 /* Tests invalid args to the "Get*" functions. */
8823 static void test_IUriBuilder_GetInvalidArgs(void) {
8824     IUriBuilder *builder = NULL;
8825     HRESULT hr;
8826
8827     hr = pCreateIUriBuilder(NULL, 0, 0, &builder);
8828     ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8829     if(SUCCEEDED(hr)) {
8830         LPCWSTR received = (void*) 0xdeadbeef;
8831         DWORD len = -1, port = -1;
8832         BOOL set = -1;
8833
8834         hr = IUriBuilder_GetFragment(builder, NULL, NULL);
8835         ok(hr == E_POINTER, "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x.\n",
8836             hr, E_POINTER);
8837         hr = IUriBuilder_GetFragment(builder, NULL, &received);
8838         ok(hr == E_POINTER, "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x.\n",
8839             hr, E_POINTER);
8840         ok(!received, "Error: Expected received to be NULL, but was %p instead.\n", received);
8841         hr = IUriBuilder_GetFragment(builder, &len, NULL);
8842         ok(hr == E_POINTER, "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x.\n",
8843             hr, E_POINTER);
8844         ok(!len, "Error: Expected len to be 0, but was %d instead.\n", len);
8845
8846         hr = IUriBuilder_GetHost(builder, NULL, NULL);
8847         ok(hr == E_POINTER, "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x.\n",
8848             hr, E_POINTER);
8849         received = (void*) 0xdeadbeef;
8850         hr = IUriBuilder_GetHost(builder, NULL, &received);
8851         ok(hr == E_POINTER, "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x.\n",
8852             hr, E_POINTER);
8853         ok(!received, "Error: Expected received to be NULL, but was %p instead.\n", received);
8854         len = -1;
8855         hr = IUriBuilder_GetHost(builder, &len, NULL);
8856         ok(hr == E_POINTER, "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x.\n",
8857             hr, E_POINTER);
8858         ok(!len, "Error: Expected len to be 0, but was %d instead.\n", len);
8859
8860         hr = IUriBuilder_GetPassword(builder, NULL, NULL);
8861         ok(hr == E_POINTER, "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x.\n",
8862             hr, E_POINTER);
8863         received = (void*) 0xdeadbeef;
8864         hr = IUriBuilder_GetPassword(builder, NULL, &received);
8865         ok(hr == E_POINTER, "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x.\n",
8866             hr, E_POINTER);
8867         ok(!received, "Error: Expected received to be NULL, but was %p instead.\n", received);
8868         len = -1;
8869         hr = IUriBuilder_GetPassword(builder, &len, NULL);
8870         ok(hr == E_POINTER, "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x.\n",
8871             hr, E_POINTER);
8872         ok(!len, "Error: Expected len to be 0, but was %d instead.\n", len);
8873
8874         hr = IUriBuilder_GetPath(builder, NULL, NULL);
8875         ok(hr == E_POINTER, "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x.\n",
8876             hr, E_POINTER);
8877         received = (void*) 0xdeadbeef;
8878         hr = IUriBuilder_GetPath(builder, NULL, &received);
8879         ok(hr == E_POINTER, "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x.\n",
8880             hr, E_POINTER);
8881         ok(!received, "Error: Expected received to be NULL, but was %p instead.\n", received);
8882         len = -1;
8883         hr = IUriBuilder_GetPath(builder, &len, NULL);
8884         ok(hr == E_POINTER, "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x.\n",
8885             hr, E_POINTER);
8886         ok(!len, "Error: Expected len to be 0, but was %d instead.\n", len);
8887
8888         hr = IUriBuilder_GetPort(builder, NULL, NULL);
8889         ok(hr == E_POINTER, "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x.\n",
8890             hr, E_POINTER);
8891         hr = IUriBuilder_GetPort(builder, NULL, &port);
8892         ok(hr == E_POINTER, "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x.\n",
8893             hr, E_POINTER);
8894         ok(!port, "Error: Expected port to be 0, but was %d instead.\n", port);
8895         hr = IUriBuilder_GetPort(builder, &set, NULL);
8896         ok(hr == E_POINTER, "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x.\n",
8897             hr, E_POINTER);
8898         ok(!set, "Error: Expected set to be FALSE, but was %d instead.\n", set);
8899
8900         hr = IUriBuilder_GetQuery(builder, NULL, NULL);
8901         ok(hr == E_POINTER, "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x.\n",
8902             hr, E_POINTER);
8903         received = (void*) 0xdeadbeef;
8904         hr = IUriBuilder_GetQuery(builder, NULL, &received);
8905         ok(hr == E_POINTER, "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x.\n",
8906             hr, E_POINTER);
8907         ok(!received, "Error: Expected received to be NULL, but was %p instead.\n", received);
8908         len = -1;
8909         hr = IUriBuilder_GetQuery(builder, &len, NULL);
8910         ok(hr == E_POINTER, "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x.\n",
8911             hr, E_POINTER);
8912         ok(!len, "Error: Expected len to be 0, but was %d instead.\n", len);
8913
8914         hr = IUriBuilder_GetSchemeName(builder, NULL, NULL);
8915         ok(hr == E_POINTER, "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x.\n",
8916             hr, E_POINTER);
8917         received = (void*) 0xdeadbeef;
8918         hr = IUriBuilder_GetSchemeName(builder, NULL, &received);
8919         ok(hr == E_POINTER, "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x.\n",
8920             hr, E_POINTER);
8921         ok(!received, "Error: Expected received to be NULL, but was %p instead.\n", received);
8922         len = -1;
8923         hr = IUriBuilder_GetSchemeName(builder, &len, NULL);
8924         ok(hr == E_POINTER, "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x.\n",
8925             hr, E_POINTER);
8926         ok(!len, "Error: Expected len to be 0, but was %d instead.\n", len);
8927
8928         hr = IUriBuilder_GetUserName(builder, NULL, NULL);
8929         ok(hr == E_POINTER, "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x.\n",
8930             hr, E_POINTER);
8931         received = (void*) 0xdeadbeef;
8932         hr = IUriBuilder_GetUserName(builder, NULL, &received);
8933         ok(hr == E_POINTER, "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x.\n",
8934             hr, E_POINTER);
8935         ok(!received, "Error: Expected received to be NULL, but was %p instead.\n", received);
8936         len = -1;
8937         hr = IUriBuilder_GetUserName(builder, &len, NULL);
8938         ok(hr == E_POINTER, "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x.\n",
8939             hr, E_POINTER);
8940         ok(!len, "Error: Expected len to be 0, but was %d instead.\n", len);
8941     }
8942     if(builder) IUriBuilder_Release(builder);
8943 }
8944
8945 static void test_IUriBuilder_GetFragment(IUriBuilder *builder, const uri_builder_test *test,
8946                                          DWORD test_index) {
8947     HRESULT hr;
8948     DWORD i;
8949     LPCWSTR received = NULL;
8950     DWORD len = -1;
8951     const uri_builder_property *prop = NULL;
8952
8953     /* Check if the property was set earlier. */
8954     for(i = 0; i < sizeof(test->properties)/sizeof(test->properties[0]); ++i) {
8955         if(test->properties[i].change && test->properties[i].property == Uri_PROPERTY_FRAGMENT)
8956             prop = &(test->properties[i]);
8957     }
8958
8959     if(prop) {
8960         /* Use expected_value unless it's NULL, then use value. */
8961         LPCSTR expected = prop->expected_value ? prop->expected_value : prop->value;
8962         hr = IUriBuilder_GetFragment(builder, &len, &received);
8963         if(prop->todo) {
8964             todo_wine {
8965                 ok(hr == (expected ? S_OK : S_FALSE),
8966                     "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8967                     hr, (expected ? S_OK : S_FALSE), test_index);
8968             }
8969             if(SUCCEEDED(hr)) {
8970                 todo_wine {
8971                     ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
8972                         expected, wine_dbgstr_w(received), test_index);
8973                 }
8974                 todo_wine {
8975                     ok(lstrlen(expected) == len,
8976                         "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8977                         lstrlen(expected), len, test_index);
8978                 }
8979             }
8980         } else {
8981             ok(hr == (expected ? S_OK : S_FALSE),
8982                 "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8983                 hr, (expected ? S_OK : S_FALSE), test_index);
8984             ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
8985                 expected, wine_dbgstr_w(received), test_index);
8986             ok(lstrlen(expected) == len,
8987                 "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8988                 lstrlen(expected), len, test_index);
8989         }
8990     } else {
8991         /* The property wasn't set earlier, so it should return whatever
8992          * the base IUri contains (if anything).
8993          */
8994         IUri *uri = NULL;
8995         hr = IUriBuilder_GetIUri(builder, &uri);
8996         ok(hr == S_OK,
8997             "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8998             hr, S_OK, test_index);
8999         if(SUCCEEDED(hr)) {
9000             if(!uri) {
9001                 received = (void*) 0xdeadbeef;
9002                 len = -1;
9003
9004                 hr = IUriBuilder_GetFragment(builder, &len, &received);
9005                 ok(hr == S_FALSE,
9006                     "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9007                     hr, S_FALSE, test_index);
9008                 if(SUCCEEDED(hr)) {
9009                     ok(!len, "Error: Expected len to be 0, but was %d instead on uri_builder_tests[%d].\n",
9010                         len, test_index);
9011                     ok(!received, "Error: Expected received to be NULL, but was %p instead on uri_builder_tests[%d].\n",
9012                         received, test_index);
9013                 }
9014             } else {
9015                 BOOL has_prop = FALSE;
9016                 BSTR expected = NULL;
9017
9018                 hr = IUri_GetFragment(uri, &expected);
9019                 ok(SUCCEEDED(hr),
9020                     "Error: Expected IUri_GetFragment to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
9021                     hr, test_index);
9022                 has_prop = hr == S_OK;
9023
9024                 hr = IUriBuilder_GetFragment(builder, &len, &received);
9025                 if(has_prop) {
9026                     ok(hr == S_OK,
9027                         "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9028                         hr, S_OK, test_index);
9029                     if(SUCCEEDED(hr)) {
9030                         ok(!lstrcmpW(expected, received),
9031                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].\n",
9032                             wine_dbgstr_w(expected), wine_dbgstr_w(received), test_index);
9033                         ok(lstrlenW(expected) == len,
9034                             "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
9035                             lstrlenW(expected), len, test_index);
9036                     }
9037                 } else {
9038                     ok(hr == S_FALSE,
9039                         "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9040                         hr, S_FALSE, test_index);
9041                     if(SUCCEEDED(hr)) {
9042                         ok(!received, "Error: Expected received to be NULL on uri_builder_tests[%d].\n", test_index);
9043                         ok(!len, "Error: Expected the length to be 0, but was %d instead on uri_builder_tests[%d].\n",
9044                             len, test_index);
9045                     }
9046                 }
9047                 SysFreeString(expected);
9048             }
9049         }
9050         if(uri) IUri_Release(uri);
9051     }
9052 }
9053
9054 static void test_IUriBuilder_GetHost(IUriBuilder *builder, const uri_builder_test *test,
9055                                      DWORD test_index) {
9056     HRESULT hr;
9057     DWORD i;
9058     LPCWSTR received = NULL;
9059     DWORD len = -1;
9060     const uri_builder_property *prop = NULL;
9061
9062     /* Check if the property was set earlier. */
9063     for(i = 0; i < sizeof(test->properties)/sizeof(test->properties[0]); ++i) {
9064         if(test->properties[i].change && test->properties[i].property == Uri_PROPERTY_HOST)
9065             prop = &(test->properties[i]);
9066     }
9067
9068     if(prop) {
9069         /* Use expected_value unless it's NULL, then use value. */
9070         LPCSTR expected = prop->expected_value ? prop->expected_value : prop->value;
9071         hr = IUriBuilder_GetHost(builder, &len, &received);
9072         if(prop->todo) {
9073             todo_wine {
9074                 ok(hr == (expected ? S_OK : S_FALSE),
9075                     "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9076                     hr, (expected ? S_OK : S_FALSE), test_index);
9077             }
9078             if(SUCCEEDED(hr)) {
9079                 todo_wine {
9080                     ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
9081                         expected, wine_dbgstr_w(received), test_index);
9082                 }
9083                 todo_wine {
9084                     ok(lstrlen(expected) == len,
9085                         "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
9086                         lstrlen(expected), len, test_index);
9087                 }
9088             }
9089         } else {
9090             ok(hr == (expected ? S_OK : S_FALSE),
9091                 "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9092                 hr, (expected ? S_OK : S_FALSE), test_index);
9093             ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
9094                 expected, wine_dbgstr_w(received), test_index);
9095             ok(lstrlen(expected) == len,
9096                 "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
9097                 lstrlen(expected), len, test_index);
9098         }
9099     } else {
9100         /* The property wasn't set earlier, so it should return whatever
9101          * the base IUri contains (if anything).
9102          */
9103         IUri *uri = NULL;
9104         hr = IUriBuilder_GetIUri(builder, &uri);
9105         ok(hr == S_OK,
9106             "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9107             hr, S_OK, test_index);
9108         if(SUCCEEDED(hr)) {
9109             if(!uri) {
9110                 received = (void*) 0xdeadbeef;
9111                 len = -1;
9112
9113                 hr = IUriBuilder_GetHost(builder, &len, &received);
9114                 ok(hr == S_FALSE,
9115                     "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9116                     hr, S_FALSE, test_index);
9117                 if(SUCCEEDED(hr)) {
9118                     ok(!len, "Error: Expected len to be 0, but was %d instead on uri_builder_tests[%d].\n",
9119                         len, test_index);
9120                     ok(!received, "Error: Expected received to be NULL, but was %p instead on uri_builder_tests[%d].\n",
9121                         received, test_index);
9122                 }
9123             } else {
9124                 BOOL has_prop = FALSE;
9125                 BSTR expected = NULL;
9126
9127                 hr = IUri_GetHost(uri, &expected);
9128                 ok(SUCCEEDED(hr),
9129                     "Error: Expected IUri_GetHost to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
9130                     hr, test_index);
9131                 has_prop = hr == S_OK;
9132
9133                 hr = IUriBuilder_GetHost(builder, &len, &received);
9134                 if(has_prop) {
9135                     ok(hr == S_OK,
9136                         "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9137                         hr, S_OK, test_index);
9138                     if(SUCCEEDED(hr)) {
9139                         ok(!lstrcmpW(expected, received),
9140                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].\n",
9141                             wine_dbgstr_w(expected), wine_dbgstr_w(received), test_index);
9142                         ok(lstrlenW(expected) == len,
9143                             "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
9144                             lstrlenW(expected), len, test_index);
9145                     }
9146                 } else {
9147                     ok(hr == S_FALSE,
9148                         "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9149                         hr, S_FALSE, test_index);
9150                     if(SUCCEEDED(hr)) {
9151                         ok(!received, "Error: Expected received to be NULL on uri_builder_tests[%d].\n", test_index);
9152                         ok(!len, "Error: Expected the length to be 0, but was %d instead on uri_builder_tests[%d].\n",
9153                             len, test_index);
9154                     }
9155                 }
9156                 SysFreeString(expected);
9157             }
9158         }
9159         if(uri) IUri_Release(uri);
9160     }
9161 }
9162
9163 static void test_IUriBuilder_GetPassword(IUriBuilder *builder, const uri_builder_test *test,
9164                                          DWORD test_index) {
9165     HRESULT hr;
9166     DWORD i;
9167     LPCWSTR received = NULL;
9168     DWORD len = -1;
9169     const uri_builder_property *prop = NULL;
9170
9171     /* Check if the property was set earlier. */
9172     for(i = 0; i < sizeof(test->properties)/sizeof(test->properties[0]); ++i) {
9173         if(test->properties[i].change && test->properties[i].property == Uri_PROPERTY_PASSWORD)
9174             prop = &(test->properties[i]);
9175     }
9176
9177     if(prop) {
9178         /* Use expected_value unless it's NULL, then use value. */
9179         LPCSTR expected = prop->expected_value ? prop->expected_value : prop->value;
9180         hr = IUriBuilder_GetPassword(builder, &len, &received);
9181         if(prop->todo) {
9182             todo_wine {
9183                 ok(hr == (expected ? S_OK : S_FALSE),
9184                     "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9185                     hr, (expected ? S_OK : S_FALSE), test_index);
9186             }
9187             if(SUCCEEDED(hr)) {
9188                 todo_wine {
9189                     ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
9190                         expected, wine_dbgstr_w(received), test_index);
9191                 }
9192                 todo_wine {
9193                     ok(lstrlen(expected) == len,
9194                         "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
9195                         lstrlen(expected), len, test_index);
9196                 }
9197             }
9198         } else {
9199             ok(hr == (expected ? S_OK : S_FALSE),
9200                 "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9201                 hr, (expected ? S_OK : S_FALSE), test_index);
9202             ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
9203                 expected, wine_dbgstr_w(received), test_index);
9204             ok(lstrlen(expected) == len,
9205                 "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
9206                 lstrlen(expected), len, test_index);
9207         }
9208     } else {
9209         /* The property wasn't set earlier, so it should return whatever
9210          * the base IUri contains (if anything).
9211          */
9212         IUri *uri = NULL;
9213         hr = IUriBuilder_GetIUri(builder, &uri);
9214         ok(hr == S_OK,
9215             "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9216             hr, S_OK, test_index);
9217         if(SUCCEEDED(hr)) {
9218             if(!uri) {
9219                 received = (void*) 0xdeadbeef;
9220                 len = -1;
9221
9222                 hr = IUriBuilder_GetPassword(builder, &len, &received);
9223                 ok(hr == S_FALSE,
9224                     "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9225                     hr, S_FALSE, test_index);
9226                 if(SUCCEEDED(hr)) {
9227                     ok(!len, "Error: Expected len to be 0, but was %d instead on uri_builder_tests[%d].\n",
9228                         len, test_index);
9229                     ok(!received, "Error: Expected received to be NULL, but was %p instead on uri_builder_tests[%d].\n",
9230                         received, test_index);
9231                 }
9232             } else {
9233                 BOOL has_prop = FALSE;
9234                 BSTR expected = NULL;
9235
9236                 hr = IUri_GetPassword(uri, &expected);
9237                 ok(SUCCEEDED(hr),
9238                     "Error: Expected IUri_GetPassword to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
9239                     hr, test_index);
9240                 has_prop = hr == S_OK;
9241
9242                 hr = IUriBuilder_GetPassword(builder, &len, &received);
9243                 if(has_prop) {
9244                     ok(hr == S_OK,
9245                         "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9246                         hr, S_OK, test_index);
9247                     if(SUCCEEDED(hr)) {
9248                         ok(!lstrcmpW(expected, received),
9249                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].\n",
9250                             wine_dbgstr_w(expected), wine_dbgstr_w(received), test_index);
9251                         ok(lstrlenW(expected) == len,
9252                             "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
9253                             lstrlenW(expected), len, test_index);
9254                     }
9255                 } else {
9256                     ok(hr == S_FALSE,
9257                         "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9258                         hr, S_FALSE, test_index);
9259                     if(SUCCEEDED(hr)) {
9260                         ok(!received, "Error: Expected received to be NULL on uri_builder_tests[%d].\n", test_index);
9261                         ok(!len, "Error: Expected the length to be 0, but was %d instead on uri_builder_tests[%d].\n",
9262                             len, test_index);
9263                     }
9264                 }
9265                 SysFreeString(expected);
9266             }
9267         }
9268         if(uri) IUri_Release(uri);
9269     }
9270 }
9271
9272 static void test_IUriBuilder_GetPath(IUriBuilder *builder, const uri_builder_test *test,
9273                                      DWORD test_index) {
9274     HRESULT hr;
9275     DWORD i;
9276     LPCWSTR received = NULL;
9277     DWORD len = -1;
9278     const uri_builder_property *prop = NULL;
9279
9280     /* Check if the property was set earlier. */
9281     for(i = 0; i < sizeof(test->properties)/sizeof(test->properties[0]); ++i) {
9282         if(test->properties[i].change && test->properties[i].property == Uri_PROPERTY_PATH)
9283             prop = &(test->properties[i]);
9284     }
9285
9286     if(prop) {
9287         /* Use expected_value unless it's NULL, then use value. */
9288         LPCSTR expected = prop->expected_value ? prop->expected_value : prop->value;
9289         hr = IUriBuilder_GetPath(builder, &len, &received);
9290         if(prop->todo) {
9291             todo_wine {
9292                 ok(hr == (expected ? S_OK : S_FALSE),
9293                     "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9294                     hr, (expected ? S_OK : S_FALSE), test_index);
9295             }
9296             if(SUCCEEDED(hr)) {
9297                 todo_wine {
9298                     ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
9299                         expected, wine_dbgstr_w(received), test_index);
9300                 }
9301                 todo_wine {
9302                     ok(lstrlen(expected) == len,
9303                         "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
9304                         lstrlen(expected), len, test_index);
9305                 }
9306             }
9307         } else {
9308             ok(hr == (expected ? S_OK : S_FALSE),
9309                 "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9310                 hr, (expected ? S_OK : S_FALSE), test_index);
9311             ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
9312                 expected, wine_dbgstr_w(received), test_index);
9313             ok(lstrlen(expected) == len,
9314                 "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
9315                 lstrlen(expected), len, test_index);
9316         }
9317     } else {
9318         /* The property wasn't set earlier, so it should return whatever
9319          * the base IUri contains (if anything).
9320          */
9321         IUri *uri = NULL;
9322         hr = IUriBuilder_GetIUri(builder, &uri);
9323         ok(hr == S_OK,
9324             "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9325             hr, S_OK, test_index);
9326         if(SUCCEEDED(hr)) {
9327             if(!uri) {
9328                 received = (void*) 0xdeadbeef;
9329                 len = -1;
9330
9331                 hr = IUriBuilder_GetPath(builder, &len, &received);
9332                 ok(hr == S_FALSE,
9333                     "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9334                     hr, S_FALSE, test_index);
9335                 if(SUCCEEDED(hr)) {
9336                     ok(!len, "Error: Expected len to be 0, but was %d instead on uri_builder_tests[%d].\n",
9337                         len, test_index);
9338                     ok(!received, "Error: Expected received to be NULL, but was %p instead on uri_builder_tests[%d].\n",
9339                         received, test_index);
9340                 }
9341             } else {
9342                 BOOL has_prop = FALSE;
9343                 BSTR expected = NULL;
9344
9345                 hr = IUri_GetPath(uri, &expected);
9346                 ok(SUCCEEDED(hr),
9347                     "Error: Expected IUri_GetPath to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
9348                     hr, test_index);
9349                 has_prop = hr == S_OK;
9350
9351                 hr = IUriBuilder_GetPath(builder, &len, &received);
9352                 if(has_prop) {
9353                     ok(hr == S_OK,
9354                         "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9355                         hr, S_OK, test_index);
9356                     if(SUCCEEDED(hr)) {
9357                         ok(!lstrcmpW(expected, received),
9358                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].\n",
9359                             wine_dbgstr_w(expected), wine_dbgstr_w(received), test_index);
9360                         ok(lstrlenW(expected) == len,
9361                             "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
9362                             lstrlenW(expected), len, test_index);
9363                     }
9364                 } else {
9365                     ok(hr == S_FALSE,
9366                         "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9367                         hr, S_FALSE, test_index);
9368                     if(SUCCEEDED(hr)) {
9369                         ok(!received, "Error: Expected received to be NULL on uri_builder_tests[%d].\n", test_index);
9370                         ok(!len, "Error: Expected the length to be 0, but was %d instead on uri_builder_tests[%d].\n",
9371                             len, test_index);
9372                     }
9373                 }
9374                 SysFreeString(expected);
9375             }
9376         }
9377         if(uri) IUri_Release(uri);
9378     }
9379 }
9380
9381 static void test_IUriBuilder_GetPort(IUriBuilder *builder, const uri_builder_test *test,
9382                                      DWORD test_index) {
9383     HRESULT hr;
9384     BOOL has_port = FALSE;
9385     DWORD received = -1;
9386
9387     if(test->port_prop.change) {
9388         DWORD expected = test->port_prop.value;
9389
9390         hr = IUriBuilder_GetPort(builder, &has_port, &received);
9391         if(test->port_prop.todo) {
9392             todo_wine {
9393                 ok(hr == S_OK,
9394                     "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9395                     hr, S_OK, test_index);
9396             }
9397             if(SUCCEEDED(hr)) {
9398                 todo_wine {
9399                     ok(has_port == test->port_prop.set,
9400                         "Error: Expected has_port to be %d but was %d instead on uri_builder_tests[%d].\n",
9401                         test->port_prop.set, has_port, test_index);
9402                 }
9403                 todo_wine {
9404                     ok(received == expected,
9405                         "Error: Expected received to be %d, but was %d instead on uri_builder_tests[%d].\n",
9406                         expected, received, test_index);
9407                 }
9408             }
9409         } else {
9410             ok(hr == S_OK,
9411                 "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9412                 hr, S_OK, test_index);
9413             ok(has_port == test->port_prop.set,
9414                 "Error: Expected has_port to be %d, but was %d instead on uri_builder_tests[%d].\n",
9415                 test->port_prop.set, has_port, test_index);
9416             ok(received == test->port_prop.value,
9417                 "Error: Expected port to be %d, but was %d instead on uri_builder_tests[%d].\n",
9418                 test->port_prop.value, received, test_index);
9419         }
9420     } else {
9421         IUri *uri = NULL;
9422
9423         hr = IUriBuilder_GetIUri(builder, &uri);
9424         ok(hr == S_OK,
9425             "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9426             hr, S_OK, test_index);
9427         if(SUCCEEDED(hr)) {
9428             if(!uri) {
9429                 hr = IUriBuilder_GetPort(builder, &has_port, &received);
9430                 ok(hr == S_OK,
9431                     "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9432                     hr, S_OK, test_index);
9433                 if(SUCCEEDED(hr)) {
9434                     ok(has_port == FALSE,
9435                         "Error: Expected has_port to be FALSE, but was %d instead on uri_builder_tests[%d].\n",
9436                         has_port, test_index);
9437                     ok(!received, "Error: Expected received to be 0, but was %d instead on uri_builder_tests[%d].\n",
9438                         received, test_index);
9439                 }
9440             } else {
9441                 DWORD expected;
9442
9443                 hr = IUri_GetPort(uri, &expected);
9444                 ok(SUCCEEDED(hr),
9445                     "Error: Expected IUri_Port to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
9446                     hr, test_index);
9447
9448                 hr = IUriBuilder_GetPort(builder, &has_port, &received);
9449                 ok(hr == S_OK,
9450                     "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9451                     hr, S_OK, test_index);
9452                 if(SUCCEEDED(hr)) {
9453                     ok(!has_port,
9454                         "Error: Expected has_port to be FALSE but was TRUE instead on uri_builder_tests[%d].\n",
9455                         test_index);
9456                     ok(received == expected,
9457                         "Error: Expected received to be %d, but was %d instead on uri_builder_tests[%d].\n",
9458                         expected, received, test_index);
9459                 }
9460             }
9461         }
9462         if(uri) IUri_Release(uri);
9463     }
9464 }
9465
9466 static void test_IUriBuilder_GetQuery(IUriBuilder *builder, const uri_builder_test *test,
9467                                       DWORD test_index) {
9468     HRESULT hr;
9469     DWORD i;
9470     LPCWSTR received = NULL;
9471     DWORD len = -1;
9472     const uri_builder_property *prop = NULL;
9473
9474     /* Check if the property was set earlier. */
9475     for(i = 0; i < sizeof(test->properties)/sizeof(test->properties[0]); ++i) {
9476         if(test->properties[i].change && test->properties[i].property == Uri_PROPERTY_QUERY)
9477             prop = &(test->properties[i]);
9478     }
9479
9480     if(prop) {
9481         /* Use expected_value unless it's NULL, then use value. */
9482         LPCSTR expected = prop->expected_value ? prop->expected_value : prop->value;
9483         hr = IUriBuilder_GetQuery(builder, &len, &received);
9484         if(prop->todo) {
9485             todo_wine {
9486                 ok(hr == (expected ? S_OK : S_FALSE),
9487                     "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9488                     hr, (expected ? S_OK : S_FALSE), test_index);
9489             }
9490             if(SUCCEEDED(hr)) {
9491                 todo_wine {
9492                     ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
9493                         expected, wine_dbgstr_w(received), test_index);
9494                 }
9495                 todo_wine {
9496                     ok(lstrlen(expected) == len,
9497                         "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
9498                         lstrlen(expected), len, test_index);
9499                 }
9500             }
9501         } else {
9502             ok(hr == (expected ? S_OK : S_FALSE),
9503                 "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9504                 hr, (expected ? S_OK : S_FALSE), test_index);
9505             ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
9506                 expected, wine_dbgstr_w(received), test_index);
9507             ok(lstrlen(expected) == len,
9508                 "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
9509                 lstrlen(expected), len, test_index);
9510         }
9511     } else {
9512         /* The property wasn't set earlier, so it should return whatever
9513          * the base IUri contains (if anything).
9514          */
9515         IUri *uri = NULL;
9516         hr = IUriBuilder_GetIUri(builder, &uri);
9517         ok(hr == S_OK,
9518             "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9519             hr, S_OK, test_index);
9520         if(SUCCEEDED(hr)) {
9521             if(!uri) {
9522                 received = (void*) 0xdeadbeef;
9523                 len = -1;
9524
9525                 hr = IUriBuilder_GetQuery(builder, &len, &received);
9526                 ok(hr == S_FALSE,
9527                     "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9528                     hr, S_FALSE, test_index);
9529                 if(SUCCEEDED(hr)) {
9530                     ok(!len, "Error: Expected len to be 0, but was %d instead on uri_builder_tests[%d].\n",
9531                         len, test_index);
9532                     ok(!received, "Error: Expected received to be NULL, but was %p instead on uri_builder_tests[%d].\n",
9533                         received, test_index);
9534                 }
9535             } else {
9536                 BOOL has_prop = FALSE;
9537                 BSTR expected = NULL;
9538
9539                 hr = IUri_GetQuery(uri, &expected);
9540                 ok(SUCCEEDED(hr),
9541                     "Error: Expected IUri_GetQuery to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
9542                     hr, test_index);
9543                 has_prop = hr == S_OK;
9544
9545                 hr = IUriBuilder_GetQuery(builder, &len, &received);
9546                 if(has_prop) {
9547                     ok(hr == S_OK,
9548                         "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9549                         hr, S_OK, test_index);
9550                     if(SUCCEEDED(hr)) {
9551                         ok(!lstrcmpW(expected, received),
9552                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].\n",
9553                             wine_dbgstr_w(expected), wine_dbgstr_w(received), test_index);
9554                         ok(lstrlenW(expected) == len,
9555                             "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
9556                             lstrlenW(expected), len, test_index);
9557                     }
9558                 } else {
9559                     ok(hr == S_FALSE,
9560                         "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9561                         hr, S_FALSE, test_index);
9562                     if(SUCCEEDED(hr)) {
9563                         ok(!received, "Error: Expected received to be NULL on uri_builder_tests[%d].\n", test_index);
9564                         ok(!len, "Error: Expected the length to be 0, but was %d instead on uri_builder_tests[%d].\n",
9565                             len, test_index);
9566                     }
9567                 }
9568                 SysFreeString(expected);
9569             }
9570         }
9571         if(uri) IUri_Release(uri);
9572     }
9573 }
9574
9575 static void test_IUriBuilder_GetSchemeName(IUriBuilder *builder, const uri_builder_test *test,
9576                                            DWORD test_index) {
9577     HRESULT hr;
9578     DWORD i;
9579     LPCWSTR received = NULL;
9580     DWORD len = -1;
9581     const uri_builder_property *prop = NULL;
9582
9583     /* Check if the property was set earlier. */
9584     for(i = 0; i < sizeof(test->properties)/sizeof(test->properties[0]); ++i) {
9585         if(test->properties[i].change && test->properties[i].property == Uri_PROPERTY_SCHEME_NAME)
9586             prop = &(test->properties[i]);
9587     }
9588
9589     if(prop) {
9590         /* Use expected_value unless it's NULL, then use value. */
9591         LPCSTR expected = prop->expected_value ? prop->expected_value : prop->value;
9592         hr = IUriBuilder_GetSchemeName(builder, &len, &received);
9593         if(prop->todo) {
9594             todo_wine {
9595                 ok(hr == (expected ? S_OK : S_FALSE),
9596                     "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9597                     hr, (expected ? S_OK : S_FALSE), test_index);
9598             }
9599             if(SUCCEEDED(hr)) {
9600                 todo_wine {
9601                     ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
9602                         expected, wine_dbgstr_w(received), test_index);
9603                 }
9604                 todo_wine {
9605                     ok(lstrlen(expected) == len,
9606                         "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
9607                         lstrlen(expected), len, test_index);
9608                 }
9609             }
9610         } else {
9611             ok(hr == (expected ? S_OK : S_FALSE),
9612                 "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9613                 hr, (expected ? S_OK : S_FALSE), test_index);
9614             ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
9615                 expected, wine_dbgstr_w(received), test_index);
9616             ok(lstrlen(expected) == len,
9617                 "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
9618                 lstrlen(expected), len, test_index);
9619         }
9620     } else {
9621         /* The property wasn't set earlier, so it should return whatever
9622          * the base IUri contains (if anything).
9623          */
9624         IUri *uri = NULL;
9625         hr = IUriBuilder_GetIUri(builder, &uri);
9626         ok(hr == S_OK,
9627             "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9628             hr, S_OK, test_index);
9629         if(SUCCEEDED(hr)) {
9630             if(!uri) {
9631                 received = (void*) 0xdeadbeef;
9632                 len = -1;
9633
9634                 hr = IUriBuilder_GetSchemeName(builder, &len, &received);
9635                 ok(hr == S_FALSE,
9636                     "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9637                     hr, S_FALSE, test_index);
9638                 if(SUCCEEDED(hr)) {
9639                     ok(!len, "Error: Expected len to be 0, but was %d instead on uri_builder_tests[%d].\n",
9640                         len, test_index);
9641                     ok(!received, "Error: Expected received to be NULL, but was %p instead on uri_builder_tests[%d].\n",
9642                         received, test_index);
9643                 }
9644             } else {
9645                 BOOL has_prop = FALSE;
9646                 BSTR expected = NULL;
9647
9648                 hr = IUri_GetSchemeName(uri, &expected);
9649                 ok(SUCCEEDED(hr),
9650                     "Error: Expected IUri_GetSchemeName to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
9651                     hr, test_index);
9652                 has_prop = hr == S_OK;
9653
9654                 hr = IUriBuilder_GetSchemeName(builder, &len, &received);
9655                 if(has_prop) {
9656                     ok(hr == S_OK,
9657                         "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9658                         hr, S_OK, test_index);
9659                     if(SUCCEEDED(hr)) {
9660                         ok(!lstrcmpW(expected, received),
9661                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].\n",
9662                             wine_dbgstr_w(expected), wine_dbgstr_w(received), test_index);
9663                         ok(lstrlenW(expected) == len,
9664                             "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
9665                             lstrlenW(expected), len, test_index);
9666                     }
9667                 } else {
9668                     ok(hr == S_FALSE,
9669                         "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9670                         hr, S_FALSE, test_index);
9671                     if(SUCCEEDED(hr)) {
9672                         ok(!received, "Error: Expected received to be NULL on uri_builder_tests[%d].\n", test_index);
9673                         ok(!len, "Error: Expected the length to be 0, but was %d instead on uri_builder_tests[%d].\n",
9674                             len, test_index);
9675                     }
9676                 }
9677                 SysFreeString(expected);
9678             }
9679         }
9680         if(uri) IUri_Release(uri);
9681     }
9682 }
9683
9684 static void test_IUriBuilder_GetUserName(IUriBuilder *builder, const uri_builder_test *test,
9685                                          DWORD test_index) {
9686     HRESULT hr;
9687     DWORD i;
9688     LPCWSTR received = NULL;
9689     DWORD len = -1;
9690     const uri_builder_property *prop = NULL;
9691
9692     /* Check if the property was set earlier. */
9693     for(i = 0; i < sizeof(test->properties)/sizeof(test->properties[0]); ++i) {
9694         if(test->properties[i].change && test->properties[i].property == Uri_PROPERTY_USER_NAME)
9695             prop = &(test->properties[i]);
9696     }
9697
9698     if(prop && prop->value && *prop->value) {
9699         /* Use expected_value unless it's NULL, then use value. */
9700         LPCSTR expected = prop->expected_value ? prop->expected_value : prop->value;
9701         hr = IUriBuilder_GetUserName(builder, &len, &received);
9702         if(prop->todo) {
9703             todo_wine {
9704                 ok(hr == (expected ? S_OK : S_FALSE),
9705                     "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9706                     hr, (expected ? S_OK : S_FALSE), test_index);
9707             }
9708             if(SUCCEEDED(hr)) {
9709                 todo_wine {
9710                     ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
9711                         expected, wine_dbgstr_w(received), test_index);
9712                 }
9713                 todo_wine {
9714                     ok(lstrlen(expected) == len,
9715                         "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
9716                         lstrlen(expected), len, test_index);
9717                 }
9718             }
9719         } else {
9720             ok(hr == (expected ? S_OK : S_FALSE),
9721                 "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9722                 hr, (expected ? S_OK : S_FALSE), test_index);
9723             ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
9724                 expected, wine_dbgstr_w(received), test_index);
9725             ok(lstrlen(expected) == len,
9726                 "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
9727                 lstrlen(expected), len, test_index);
9728         }
9729     } else {
9730         /* The property wasn't set earlier, so it should return whatever
9731          * the base IUri contains (if anything).
9732          */
9733         IUri *uri = NULL;
9734         hr = IUriBuilder_GetIUri(builder, &uri);
9735         ok(hr == S_OK,
9736             "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9737             hr, S_OK, test_index);
9738         if(SUCCEEDED(hr)) {
9739             if(!uri) {
9740                 received = (void*) 0xdeadbeef;
9741                 len = -1;
9742
9743                 hr = IUriBuilder_GetUserName(builder, &len, &received);
9744                 ok(hr == S_FALSE,
9745                     "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9746                     hr, S_FALSE, test_index);
9747                 if(SUCCEEDED(hr)) {
9748                     ok(!len, "Error: Expected len to be 0, but was %d instead on uri_builder_tests[%d].\n",
9749                         len, test_index);
9750                     ok(!received, "Error: Expected received to be NULL, but was %p instead on uri_builder_tests[%d].\n",
9751                         received, test_index);
9752                 }
9753             } else {
9754                 BSTR expected = NULL;
9755                 BOOL has_prop = FALSE;
9756
9757                 hr = IUri_GetUserName(uri, &expected);
9758                 ok(SUCCEEDED(hr),
9759                     "Error: Expected IUri_GetUserName to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
9760                     hr, test_index);
9761                 has_prop = hr == S_OK;
9762
9763                 hr = IUriBuilder_GetUserName(builder, &len, &received);
9764                 if(has_prop) {
9765                     ok(hr == S_OK,
9766                         "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9767                         hr, S_OK, test_index);
9768                     if(SUCCEEDED(hr)) {
9769                         ok(!lstrcmpW(expected, received),
9770                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].\n",
9771                             wine_dbgstr_w(expected), wine_dbgstr_w(received), test_index);
9772                         ok(lstrlenW(expected) == len,
9773                             "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
9774                             lstrlenW(expected), len, test_index);
9775                     }
9776                 } else {
9777                     ok(hr == S_FALSE,
9778                         "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9779                         hr, S_FALSE, test_index);
9780                     if(SUCCEEDED(hr)) {
9781                         ok(!received, "Error: Expected received to be NULL on uri_builder_tests[%d].\n", test_index);
9782                         ok(!len, "Error: Expected the length to be 0, but was %d instead on uri_builder_tests[%d].\n",
9783                             len, test_index);
9784                     }
9785                 }
9786                 SysFreeString(expected);
9787             }
9788         }
9789         if(uri) IUri_Release(uri);
9790     }
9791 }
9792
9793 /* Tests IUriBuilder functions. */
9794 static void test_IUriBuilder(void) {
9795     HRESULT hr;
9796     IUriBuilder *builder;
9797     DWORD i;
9798
9799     for(i = 0; i < sizeof(uri_builder_tests)/sizeof(uri_builder_tests[0]); ++i) {
9800         IUri *uri = NULL;
9801         uri_builder_test test = uri_builder_tests[i];
9802         LPWSTR uriW = NULL;
9803
9804         if(test.uri) {
9805             uriW = a2w(test.uri);
9806             hr = pCreateUri(uriW, test.create_flags, 0, &uri);
9807             ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9808                 hr, S_OK, i);
9809             if(FAILED(hr)) continue;
9810         }
9811         hr = pCreateIUriBuilder(uri, 0, 0, &builder);
9812         if(test.create_builder_todo) {
9813             todo_wine {
9814                 ok(hr == test.create_builder_expected,
9815                     "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9816                     hr, test.create_builder_expected, i);
9817             }
9818         } else {
9819             ok(hr == test.create_builder_expected,
9820                 "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9821                 hr, test.create_builder_expected, i);
9822         }
9823         if(SUCCEEDED(hr)) {
9824             DWORD j;
9825             BOOL modified = FALSE, received = FALSE;
9826
9827             /* Perform all the string property changes. */
9828             for(j = 0; j < URI_BUILDER_STR_PROPERTY_COUNT; ++j) {
9829                 uri_builder_property prop = test.properties[j];
9830                 if(prop.change) {
9831                     change_property(builder, &prop, i);
9832                     if(prop.property != Uri_PROPERTY_SCHEME_NAME &&
9833                        prop.property != Uri_PROPERTY_HOST)
9834                         modified = TRUE;
9835                     else if(prop.value && *prop.value)
9836                         modified = TRUE;
9837                     else if(prop.value && !*prop.value && prop.property == Uri_PROPERTY_HOST)
9838                         /* Host name property can't be NULL, but it can be empty. */
9839                         modified = TRUE;
9840                 }
9841             }
9842
9843             if(test.port_prop.change) {
9844                 hr = IUriBuilder_SetPort(builder, test.port_prop.set, test.port_prop.value);
9845                 modified = TRUE;
9846                 if(test.port_prop.todo) {
9847                     todo_wine {
9848                         ok(hr == test.port_prop.expected,
9849                             "Error: IUriBuilder_SetPort returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9850                             hr, test.port_prop.expected, i);
9851                     }
9852                 } else {
9853                     ok(hr == test.port_prop.expected,
9854                         "Error: IUriBuilder_SetPort returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9855                         hr, test.port_prop.expected, i);
9856                 }
9857             }
9858
9859             hr = IUriBuilder_HasBeenModified(builder, &received);
9860             ok(hr == S_OK,
9861                 "Error IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9862                 hr, S_OK, i);
9863             if(SUCCEEDED(hr))
9864                 ok(received == modified,
9865                     "Error: Expected received to be %d but was %d instead on uri_builder_tests[%d].\n",
9866                     modified, received, i);
9867
9868             /* Test the "Get*" functions. */
9869             test_IUriBuilder_GetFragment(builder, &test, i);
9870             test_IUriBuilder_GetHost(builder, &test, i);
9871             test_IUriBuilder_GetPassword(builder, &test, i);
9872             test_IUriBuilder_GetPath(builder, &test, i);
9873             test_IUriBuilder_GetPort(builder, &test, i);
9874             test_IUriBuilder_GetQuery(builder, &test, i);
9875             test_IUriBuilder_GetSchemeName(builder, &test, i);
9876             test_IUriBuilder_GetUserName(builder, &test, i);
9877
9878             test_IUriBuilder_CreateUri(builder, &test, i);
9879             test_IUriBuilder_CreateUriSimple(builder, &test, i);
9880             test_IUriBuilder_CreateUriWithFlags(builder, &test, i);
9881         }
9882         if(builder) IUriBuilder_Release(builder);
9883         if(uri) IUri_Release(uri);
9884         heap_free(uriW);
9885     }
9886 }
9887
9888 static void test_IUriBuilder_HasBeenModified(void) {
9889     HRESULT hr;
9890     IUriBuilder *builder = NULL;
9891
9892     hr = pCreateIUriBuilder(NULL, 0, 0, &builder);
9893     ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9894     if(SUCCEEDED(hr)) {
9895         static const WCHAR hostW[] = {'g','o','o','g','l','e','.','c','o','m',0};
9896         IUri *uri = NULL;
9897         BOOL received;
9898
9899         hr = IUriBuilder_HasBeenModified(builder, NULL);
9900         ok(hr == E_POINTER, "Error: IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x.\n",
9901             hr, E_POINTER);
9902
9903         hr = IUriBuilder_SetHost(builder, hostW);
9904         ok(hr == S_OK, "Error: IUriBuilder_SetHost returned 0x%08x, expected 0x%08x.\n",
9905             hr, S_OK);
9906
9907         hr = IUriBuilder_HasBeenModified(builder, &received);
9908         ok(hr == S_OK, "Error: IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x.\n",
9909             hr, S_OK);
9910         if(SUCCEEDED(hr))
9911             ok(received == TRUE, "Error: Expected received to be TRUE.\n");
9912
9913         hr = pCreateUri(http_urlW, 0, 0, &uri);
9914         ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9915         if(SUCCEEDED(hr)) {
9916             LPCWSTR prop;
9917             DWORD len = -1;
9918
9919             hr = IUriBuilder_SetIUri(builder, uri);
9920             ok(hr == S_OK, "Error: IUriBuilder_SetIUri returned 0x%08x, expected 0x%08x.\n",
9921                 hr, S_OK);
9922
9923             hr = IUriBuilder_HasBeenModified(builder, &received);
9924             ok(hr == S_OK, "Error: IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x.\n",
9925                 hr, S_OK);
9926             if(SUCCEEDED(hr))
9927                 ok(received == FALSE, "Error: Expected received to be FALSE.\n");
9928
9929             /* Test what happens with you call SetIUri with the same IUri again. */
9930             hr = IUriBuilder_SetHost(builder, hostW);
9931             ok(hr == S_OK, "Error: IUriBuilder_SetHost returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9932
9933             hr = IUriBuilder_HasBeenModified(builder, &received);
9934             ok(hr == S_OK, "Error: IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x.\n",
9935                 hr, S_OK);
9936             if(SUCCEEDED(hr))
9937                 ok(received == TRUE, "Error: Expected received to be TRUE.\n");
9938
9939             hr = IUriBuilder_SetIUri(builder, uri);
9940             ok(hr == S_OK, "Error: IUriBuilder_SetIUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9941
9942             /* IUriBuilder already had 'uri' as it's IUri property and so Windows doesn't
9943              * reset any of the changes that were made to the IUriBuilder.
9944              */
9945             hr = IUriBuilder_HasBeenModified(builder, &received);
9946             ok(hr == S_OK, "Error: IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9947             if(SUCCEEDED(hr))
9948                 ok(received == TRUE, "Error: Expected received to be TRUE.\n");
9949
9950             hr = IUriBuilder_GetHost(builder, &len, &prop);
9951             ok(hr == S_OK, "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9952             if(SUCCEEDED(hr)) {
9953                 ok(!lstrcmpW(prop, hostW), "Error: Expected %s but got %s instead.\n",
9954                     wine_dbgstr_w(hostW), wine_dbgstr_w(prop));
9955                 ok(len == lstrlenW(hostW), "Error: Expected len to be %d, but was %d instead.\n",
9956                     lstrlenW(hostW), len);
9957             }
9958
9959             hr = IUriBuilder_SetIUri(builder, NULL);
9960             ok(hr == S_OK, "Error: IUriBuilder_SetIUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9961
9962             hr = IUriBuilder_SetHost(builder, hostW);
9963             ok(hr == S_OK, "Error: IUriBuilder_SetHost returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9964             hr = IUriBuilder_HasBeenModified(builder, &received);
9965             ok(hr == S_OK, "Error: IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x.\n",
9966                 hr, S_OK);
9967             if(SUCCEEDED(hr))
9968                 ok(received == TRUE, "Error: Expected received to be TRUE.\n");
9969
9970             hr = IUriBuilder_SetIUri(builder, NULL);
9971             ok(hr == S_OK, "Error: IUriBuilder_SetIUri returned 0x%08x, expected 0x%09x.\n", hr, S_OK);
9972
9973             hr = IUriBuilder_HasBeenModified(builder, &received);
9974             ok(hr == S_OK, "Error: IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x.\n",
9975                 hr, S_OK);
9976             if(SUCCEEDED(hr))
9977                 ok(received == TRUE, "Error: Expected received to be TRUE.\n");
9978
9979             hr = IUriBuilder_GetHost(builder, &len, &prop);
9980             ok(hr == S_OK, "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9981             if(SUCCEEDED(hr)) {
9982                 ok(!lstrcmpW(prop, hostW), "Error: Expected %s but got %s instead.\n",
9983                     wine_dbgstr_w(hostW), wine_dbgstr_w(prop));
9984                 ok(len == lstrlenW(hostW), "Error: Expected len to %d, but was %d instead.\n",
9985                     lstrlenW(hostW), len);
9986             }
9987         }
9988         if(uri) IUri_Release(uri);
9989     }
9990     if(builder) IUriBuilder_Release(builder);
9991 }
9992
9993 /* Test IUriBuilder {Get,Set}IUri functions. */
9994 static void test_IUriBuilder_IUriProperty(void) {
9995     IUriBuilder *builder = NULL;
9996     HRESULT hr;
9997
9998     hr = pCreateIUriBuilder(NULL, 0, 0, &builder);
9999     ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
10000     if(SUCCEEDED(hr)) {
10001         IUri *uri = NULL;
10002
10003         hr = IUriBuilder_GetIUri(builder, NULL);
10004         ok(hr == E_POINTER, "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x.\n",
10005             hr, E_POINTER);
10006
10007         hr = pCreateUri(http_urlW, 0, 0, &uri);
10008         if(SUCCEEDED(hr)) {
10009             IUri *test = NULL;
10010             ULONG cur_count, orig_count;
10011
10012             /* IUriBuilder doesn't clone the IUri, it use the same IUri. */
10013             orig_count = get_refcnt(uri);
10014             hr = IUriBuilder_SetIUri(builder, uri);
10015             cur_count = get_refcnt(uri);
10016             if(SUCCEEDED(hr))
10017                 ok(cur_count == orig_count+1, "Error: Expected uri ref count to be %d, but was %d instead.\n",
10018                     orig_count+1, cur_count);
10019
10020             hr = IUriBuilder_SetIUri(builder, NULL);
10021             cur_count = get_refcnt(uri);
10022             if(SUCCEEDED(hr))
10023                 ok(cur_count == orig_count, "Error: Expected uri ref count to be %d, but was %d instead.\n",
10024                     orig_count, cur_count);
10025
10026             /* CreateUri* functions will return back the same IUri if nothing has changed. */
10027             hr = IUriBuilder_SetIUri(builder, uri);
10028             ok(hr == S_OK, "Error: IUriBuilder_SetIUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
10029             orig_count = get_refcnt(uri);
10030
10031             hr = IUriBuilder_CreateUri(builder, 0, 0, 0, &test);
10032             ok(hr == S_OK, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
10033             if(SUCCEEDED(hr)) {
10034                 cur_count = get_refcnt(uri);
10035                 ok(cur_count == orig_count+1, "Error: Expected uri ref count to be %d, but was %d instead.\n",
10036                     orig_count+1, cur_count);
10037                 ok(test == uri, "Error: Expected test to be %p, but was %p instead.\n",
10038                     uri, test);
10039             }
10040             if(test) IUri_Release(test);
10041
10042             test = NULL;
10043             hr = IUriBuilder_CreateUri(builder, -1, 0, 0, &test);
10044             ok(hr == S_OK, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
10045             if(SUCCEEDED(hr)) {
10046                 cur_count = get_refcnt(uri);
10047                 ok(cur_count == orig_count+1, "Error: Expected uri ref count to be %d, but was %d instead.\n",
10048                     orig_count+1, cur_count);
10049                 ok(test == uri, "Error: Expected test to be %p, but was %p instead.\n", uri, test);
10050             }
10051             if(test) IUri_Release(test);
10052
10053             /* Doesn't return the same IUri, if the flag combination is different then the one that created
10054              * the base IUri.
10055              */
10056             test = NULL;
10057             hr = IUriBuilder_CreateUri(builder, Uri_CREATE_ALLOW_RELATIVE, 0, 0, &test);
10058             ok(hr == S_OK, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
10059             if(SUCCEEDED(hr))
10060                 ok(test != uri, "Error: Wasn't expecting 'test' to be 'uri'\n");
10061
10062             if(test) IUri_Release(test);
10063
10064             /* Still returns the same IUri, even though the base one wasn't created with CREATE_CANONICALIZE
10065              * explicitly set (because it's a default flags).
10066              */
10067             test = NULL;
10068             hr = IUriBuilder_CreateUri(builder, Uri_CREATE_CANONICALIZE, 0, 0, &test);
10069             ok(hr == S_OK, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
10070             if(SUCCEEDED(hr)) {
10071                 cur_count = get_refcnt(uri);
10072                 ok(cur_count == orig_count+1, "Error: Expected uri ref count to be %d, but was %d instead.\n",
10073                     orig_count+1, cur_count);
10074                 ok(test == uri, "Error: Expected 'test' to be %p, but was %p instead.\n", uri, test);
10075             }
10076             if(test) IUri_Release(test);
10077
10078             test = NULL;
10079             hr = IUriBuilder_CreateUriSimple(builder, 0, 0, &test);
10080             ok(hr == S_OK, "Error: IUriBuilder_CreateUriSimple returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
10081             if(SUCCEEDED(hr)) {
10082                 cur_count = get_refcnt(uri);
10083                 ok(cur_count == orig_count+1, "Error: Expected uri ref count to be %d, but was %d instead.\n",
10084                     orig_count+1, cur_count);
10085                 ok(test == uri, "Error: Expected test to be %p, but was %p instead.\n", uri, test);
10086             }
10087             if(test) IUri_Release(test);
10088
10089             test = NULL;
10090             hr = IUriBuilder_CreateUriWithFlags(builder, 0, 0, 0, 0, &test);
10091             ok(hr == S_OK, "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x.\n",
10092                 hr, S_OK);
10093             if(SUCCEEDED(hr)) {
10094                 cur_count = get_refcnt(uri);
10095                 ok(cur_count == orig_count+1, "Error: Expected uri ref count to be %d, but was %d instead.\n",
10096                     orig_count+1, cur_count);
10097                 ok(test == uri, "Error: Expected test to be %p, but was %p instead.\n", uri, test);
10098             }
10099             if(test) IUri_Release(test);
10100
10101             /* Doesn't return the same IUri, if the flag combination is different then the one that created
10102              * the base IUri.
10103              */
10104             test = NULL;
10105             hr = IUriBuilder_CreateUriWithFlags(builder, Uri_CREATE_ALLOW_RELATIVE, 0, 0, 0, &test);
10106             ok(hr == S_OK, "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
10107             if(SUCCEEDED(hr))
10108                 ok(test != uri, "Error: Wasn't expecting 'test' to be 'uri'\n");
10109
10110             if(test) IUri_Release(test);
10111
10112             /* Still returns the same IUri, even though the base one wasn't created with CREATE_CANONICALIZE
10113              * explicitly set (because it's a default flags).
10114              */
10115             test = NULL;
10116             hr = IUriBuilder_CreateUriWithFlags(builder, Uri_CREATE_CANONICALIZE, 0, 0, 0, &test);
10117             ok(hr == S_OK, "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
10118             if(SUCCEEDED(hr)) {
10119                 cur_count = get_refcnt(uri);
10120                 ok(cur_count == orig_count+1, "Error: Expected uri ref count to be %d, but was %d instead.\n",
10121                     orig_count+1, cur_count);
10122                 ok(test == uri, "Error: Expected 'test' to be %p, but was %p instead.\n", uri, test);
10123             }
10124             if(test) IUri_Release(test);
10125         }
10126         if(uri) IUri_Release(uri);
10127     }
10128     if(builder) IUriBuilder_Release(builder);
10129 }
10130
10131 static void test_IUriBuilder_RemoveProperties(void) {
10132     IUriBuilder *builder = NULL;
10133     HRESULT hr;
10134     DWORD i;
10135
10136     hr = pCreateIUriBuilder(NULL, 0, 0, &builder);
10137     ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
10138     if(SUCCEEDED(hr)) {
10139         /* Properties that can't be removed. */
10140         const DWORD invalid = Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_RAW_URI|Uri_HAS_HOST_TYPE|
10141                               Uri_HAS_SCHEME|Uri_HAS_ZONE;
10142
10143         for(i = Uri_PROPERTY_STRING_START; i <= Uri_PROPERTY_DWORD_LAST; ++i) {
10144             hr = IUriBuilder_RemoveProperties(builder, i << 1);
10145             if((i << 1) & invalid) {
10146                 ok(hr == E_INVALIDARG,
10147                     "Error: IUriBuilder_RemoveProperties returned 0x%08x, expected 0x%08x with prop=%d.\n",
10148                     hr, E_INVALIDARG, i);
10149             } else {
10150                 ok(hr == S_OK,
10151                     "Error: IUriBuilder_RemoveProperties returned 0x%08x, expected 0x%08x with prop=%d.\n",
10152                     hr, S_OK, i);
10153             }
10154         }
10155
10156         /* Also doesn't accept anything that's outside the range of the
10157          * Uri_HAS flags.
10158          */
10159         hr = IUriBuilder_RemoveProperties(builder, (Uri_PROPERTY_DWORD_LAST+1) << 1);
10160         ok(hr == E_INVALIDARG, "Error: IUriBuilder_RemoveProperties returned 0x%08x, expected 0x%08x.\n",
10161             hr, E_INVALIDARG);
10162     }
10163     if(builder) IUriBuilder_Release(builder);
10164
10165     for(i = 0; i < sizeof(uri_builder_remove_tests)/sizeof(uri_builder_remove_tests[0]); ++i) {
10166         uri_builder_remove_test test = uri_builder_remove_tests[i];
10167         IUri *uri = NULL;
10168         LPWSTR uriW;
10169
10170         uriW = a2w(test.uri);
10171         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
10172         if(SUCCEEDED(hr)) {
10173             builder = NULL;
10174
10175             hr = pCreateIUriBuilder(uri, 0, 0, &builder);
10176             if(test.create_builder_todo) {
10177                 todo_wine {
10178                     ok(hr == test.create_builder_expected,
10179                         "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x on test %d.\n",
10180                         hr, test.create_builder_expected, i);
10181                 }
10182             } else {
10183                 ok(hr == test.create_builder_expected,
10184                     "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x on test %d.\n",
10185                     hr, test.create_builder_expected, i);
10186             }
10187             if(SUCCEEDED(hr)) {
10188                 hr = IUriBuilder_RemoveProperties(builder, test.remove_properties);
10189                 if(test.remove_todo) {
10190                     todo_wine {
10191                         ok(hr == test.remove_expected,
10192                             "Error: IUriBuilder_RemoveProperties returned 0x%08x, expected 0x%08x on test %d.\n",
10193                             hr, test.remove_expected, i);
10194                     }
10195                 } else {
10196                     ok(hr == test.remove_expected,
10197                         "Error: IUriBuilder returned 0x%08x, expected 0x%08x on test %d.\n",
10198                         hr, test.remove_expected, i);
10199                 }
10200                 if(SUCCEEDED(hr)) {
10201                     IUri *result = NULL;
10202
10203                     hr = IUriBuilder_CreateUri(builder, test.expected_flags, 0, 0, &result);
10204                     if(test.expected_todo) {
10205                         todo_wine {
10206                             ok(hr == test.expected_hres,
10207                                 "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x on test %d.\n",
10208                                 hr, test.expected_hres, i);
10209                         }
10210                     } else {
10211                         ok(hr == test.expected_hres,
10212                             "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x on test %d.\n",
10213                             hr, test.expected_hres, i);
10214                     }
10215                     if(SUCCEEDED(hr)) {
10216                         BSTR received = NULL;
10217
10218                         hr = IUri_GetAbsoluteUri(result, &received);
10219                         ok(hr == S_OK, "Error: Expected S_OK, but got 0x%08x instead.\n", hr);
10220                         ok(!strcmp_aw(test.expected_uri, received),
10221                             "Error: Expected %s but got %s instead on test %d.\n",
10222                             test.expected_uri, wine_dbgstr_w(received), i);
10223                         SysFreeString(received);
10224                     }
10225                     if(result) IUri_Release(result);
10226                 }
10227             }
10228             if(builder) IUriBuilder_Release(builder);
10229         }
10230         if(uri) IUri_Release(uri);
10231         heap_free(uriW);
10232     }
10233 }
10234
10235 static void test_IUriBuilder_Misc(void) {
10236     HRESULT hr;
10237     IUri *uri;
10238
10239     hr = pCreateUri(http_urlW, 0, 0, &uri);
10240     if(SUCCEEDED(hr)) {
10241         IUriBuilder *builder;
10242
10243         hr = pCreateIUriBuilder(uri, 0, 0, &builder);
10244         ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
10245         if(SUCCEEDED(hr)) {
10246             BOOL has = -1;
10247             DWORD port = -1;
10248
10249             hr = IUriBuilder_GetPort(builder, &has, &port);
10250             ok(hr == S_OK, "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
10251             if(SUCCEEDED(hr)) {
10252                 /* 'has' will be set to FALSE, even though uri had a port. */
10253                 ok(has == FALSE, "Error: Expected 'has' to be FALSE, was %d instead.\n", has);
10254                 /* Still sets 'port' to 80. */
10255                 ok(port == 80, "Error: Expected the port to be 80, but, was %d instead.\n", port);
10256             }
10257         }
10258         if(builder) IUriBuilder_Release(builder);
10259     }
10260     if(uri) IUri_Release(uri);
10261 }
10262
10263 static void test_IUriBuilderFactory(void) {
10264     HRESULT hr;
10265     IUri *uri;
10266     IUriBuilderFactory *factory;
10267     IUriBuilder *builder;
10268
10269     hr = pCreateUri(http_urlW, 0, 0, &uri);
10270     ok(SUCCEEDED(hr), "Error: CreateUri returned 0x%08x.\n", hr);
10271     if(SUCCEEDED(hr)) {
10272         factory = NULL;
10273         hr = IUri_QueryInterface(uri, &IID_IUriBuilderFactory, (void**)&factory);
10274         ok(hr == S_OK, "Error: Expected S_OK, but got 0x%08x.\n", hr);
10275         ok(factory != NULL, "Error: Expected 'factory' to not be NULL.\n");
10276
10277         if(SUCCEEDED(hr)) {
10278             builder = (void*) 0xdeadbeef;
10279             hr = IUriBuilderFactory_CreateIUriBuilder(factory, 10, 0, &builder);
10280             ok(hr == E_INVALIDARG, "Error: CreateInitializedIUriBuilder returned 0x%08x, expected 0x%08x.\n",
10281                 hr, E_INVALIDARG);
10282             ok(!builder, "Error: Expected 'builder' to be NULL, but was %p.\n", builder);
10283
10284             builder = (void*) 0xdeadbeef;
10285             hr = IUriBuilderFactory_CreateIUriBuilder(factory, 0, 10, &builder);
10286             ok(hr == E_INVALIDARG, "Error: CreateInitializedIUriBuilder returned 0x%08x, expected 0x%08x.\n",
10287                 hr, E_INVALIDARG);
10288             ok(!builder, "Error: Expected 'builder' to be NULL, but was %p.\n", builder);
10289
10290             hr = IUriBuilderFactory_CreateIUriBuilder(factory, 0, 0, NULL);
10291             ok(hr == E_POINTER, "Error: CreateInitializedIUriBuilder returned 0x%08x, expected 0x%08x.\n",
10292                 hr, E_POINTER);
10293
10294             builder = NULL;
10295             hr = IUriBuilderFactory_CreateIUriBuilder(factory, 0, 0, &builder);
10296             ok(hr == S_OK, "Error: CreateInitializedIUriBuilder returned 0x%08x, expected 0x%08x.\n",
10297                 hr, S_OK);
10298             if(SUCCEEDED(hr)) {
10299                 IUri *tmp = (void*) 0xdeadbeef;
10300                 LPCWSTR result;
10301                 DWORD result_len;
10302
10303                 hr = IUriBuilder_GetIUri(builder, &tmp);
10304                 ok(hr == S_OK, "Error: GetIUri returned 0x%08x, expected 0x%08x.\n",
10305                     hr, S_OK);
10306                 ok(!tmp, "Error: Expected 'tmp' to be NULL, but was %p instead.\n", tmp);
10307
10308                 hr = IUriBuilder_GetHost(builder, &result_len, &result);
10309                 ok(hr == S_FALSE, "Error: GetHost returned 0x%08x, expected 0x%08x.\n",
10310                     hr, S_FALSE);
10311             }
10312             if(builder) IUriBuilder_Release(builder);
10313
10314             builder = (void*) 0xdeadbeef;
10315             hr = IUriBuilderFactory_CreateInitializedIUriBuilder(factory, 10, 0, &builder);
10316             ok(hr == E_INVALIDARG, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n",
10317                 hr, E_INVALIDARG);
10318             ok(!builder, "Error: Expected 'builder' to be NULL, but was %p.\n", builder);
10319
10320             builder = (void*) 0xdeadbeef;
10321             hr = IUriBuilderFactory_CreateInitializedIUriBuilder(factory, 0, 10, &builder);
10322             ok(hr == E_INVALIDARG, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n",
10323                 hr, E_INVALIDARG);
10324             ok(!builder, "Error: Expected 'builder' to be NULL, but was %p.\n", builder);
10325
10326             hr = IUriBuilderFactory_CreateInitializedIUriBuilder(factory, 0, 0, NULL);
10327             ok(hr == E_POINTER, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n",
10328                 hr, E_POINTER);
10329
10330             builder = NULL;
10331             hr = IUriBuilderFactory_CreateInitializedIUriBuilder(factory, 0, 0, &builder);
10332             ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n",
10333                 hr, S_OK);
10334             if(SUCCEEDED(hr)) {
10335                 IUri *tmp = NULL;
10336
10337                 hr = IUriBuilder_GetIUri(builder, &tmp);
10338                 ok(hr == S_OK, "Error: GetIUri return 0x%08x, expected 0x%08x.\n",
10339                     hr, S_OK);
10340                 ok(tmp == uri, "Error: Expected tmp to be %p, but was %p.\n", uri, tmp);
10341                 if(uri) IUri_Release(uri);
10342             }
10343             if(builder) IUriBuilder_Release(builder);
10344         }
10345         if(factory) IUriBuilderFactory_Release(factory);
10346     }
10347     if(uri) IUri_Release(uri);
10348 }
10349
10350 static void test_CoInternetCombineIUri(void) {
10351     HRESULT hr;
10352     IUri *base, *relative, *result;
10353     DWORD i;
10354
10355     base = NULL;
10356     hr = pCreateUri(http_urlW, 0, 0, &base);
10357     ok(SUCCEEDED(hr), "Error: Expected CreateUri to succeed, got 0x%08x.\n", hr);
10358     if(SUCCEEDED(hr)) {
10359         result = (void*) 0xdeadbeef;
10360         hr = pCoInternetCombineIUri(base, NULL, 0, &result, 0);
10361         ok(hr == E_INVALIDARG, "Error: CoInternetCombineIUri returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
10362         ok(!result, "Error: Expected 'result' to be NULL, was %p.\n", result);
10363     }
10364
10365     relative = NULL;
10366     hr = pCreateUri(http_urlW, 0, 0, &relative);
10367     ok(SUCCEEDED(hr), "Error: Expected CreateUri to succeed, got 0x%08x.\n", hr);
10368     if(SUCCEEDED(hr)) {
10369         result = (void*) 0xdeadbeef;
10370         hr = pCoInternetCombineIUri(NULL, relative, 0, &result, 0);
10371         ok(hr == E_INVALIDARG, "Error: CoInternetCombineIUri returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
10372         ok(!result, "Error: Expected 'result' to be NULL, was %p.\n", result);
10373     }
10374
10375     hr = pCoInternetCombineIUri(base, relative, 0, NULL, 0);
10376     ok(hr == E_INVALIDARG, "Error: CoInternetCombineIUri returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
10377
10378     if(base) IUri_Release(base);
10379     if(relative) IUri_Release(relative);
10380
10381     for(i = 0; i < sizeof(uri_combine_tests)/sizeof(uri_combine_tests[0]); ++i) {
10382         LPWSTR baseW = a2w(uri_combine_tests[i].base_uri);
10383
10384         hr = pCreateUri(baseW, uri_combine_tests[i].base_create_flags, 0, &base);
10385         ok(SUCCEEDED(hr), "Error: Expected CreateUri to succeed, got 0x%08x on uri_combine_tests[%d].\n", hr, i);
10386         if(SUCCEEDED(hr)) {
10387             LPWSTR relativeW = a2w(uri_combine_tests[i].relative_uri);
10388
10389             hr = pCreateUri(relativeW, uri_combine_tests[i].relative_create_flags, 0, &relative);
10390             ok(SUCCEEDED(hr), "Error: Expected CreateUri to succeed, got 0x%08x on uri_combine_tests[%d].\n", hr, i);
10391             if(SUCCEEDED(hr)) {
10392                 result = NULL;
10393
10394                 hr = pCoInternetCombineIUri(base, relative, uri_combine_tests[i].combine_flags, &result, 0);
10395                 if(uri_combine_tests[i].todo) {
10396                     todo_wine {
10397                         ok(hr == uri_combine_tests[i].expected,
10398                             "Error: CoInternetCombineIUri returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].\n",
10399                             hr, uri_combine_tests[i].expected, i);
10400                     }
10401                 } else {
10402                     ok(hr == uri_combine_tests[i].expected,
10403                         "Error: CoInternetCombineIUri returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].\n",
10404                         hr, uri_combine_tests[i]. expected, i);
10405                 }
10406                 if(SUCCEEDED(hr)) {
10407                     DWORD j;
10408
10409                     for(j = 0; j < sizeof(uri_combine_tests[i].str_props)/sizeof(uri_combine_tests[i].str_props[0]); ++j) {
10410                         uri_combine_str_property prop = uri_combine_tests[i].str_props[j];
10411                         BSTR received;
10412
10413                         hr = IUri_GetPropertyBSTR(result, j, &received, 0);
10414                         if(prop.todo) {
10415                             todo_wine {
10416                                 ok(hr == prop.expected,
10417                                     "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].str_props[%d].\n",
10418                                     hr, prop.expected, i, j);
10419                             }
10420                             todo_wine {
10421                                 ok(!strcmp_aw(prop.value, received) ||
10422                                    broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
10423                                     "Error: Expected \"%s\" but got %s instead on uri_combine_tests[%d].str_props[%d].\n",
10424                                     prop.value, wine_dbgstr_w(received), i, j);
10425                             }
10426                         } else {
10427                             ok(hr == prop.expected,
10428                                 "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].str_props[%d].\n",
10429                                 hr, prop.expected, i, j);
10430                             ok(!strcmp_aw(prop.value, received) ||
10431                                broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
10432                                 "Error: Expected \"%s\" but got %s instead on uri_combine_tests[%d].str_props[%d].\n",
10433                                 prop.value, wine_dbgstr_w(received), i, j);
10434                         }
10435                         SysFreeString(received);
10436                     }
10437
10438                     for(j = 0; j < sizeof(uri_combine_tests[i].dword_props)/sizeof(uri_combine_tests[i].dword_props[0]); ++j) {
10439                         uri_dword_property prop = uri_combine_tests[i].dword_props[j];
10440                         DWORD received;
10441
10442                         hr = IUri_GetPropertyDWORD(result, j+Uri_PROPERTY_DWORD_START, &received, 0);
10443                         if(prop.todo) {
10444                             todo_wine {
10445                                 ok(hr == prop.expected,
10446                                     "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].dword_props[%d].\n",
10447                                     hr, prop.expected, i, j);
10448                             }
10449                             todo_wine {
10450                                 ok(prop.value == received, "Error: Expected %d, but got %d instead on uri_combine_tests[%d].dword_props[%d].\n",
10451                                     prop.value, received, i, j);
10452                             }
10453                         } else {
10454                             ok(hr == prop.expected || broken(prop.broken_combine_hres && hr == S_FALSE),
10455                                 "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].dword_props[%d].\n",
10456                                 hr, prop.expected, i, j);
10457                             if(!prop.broken_combine_hres || hr != S_FALSE)
10458                                 ok(prop.value == received, "Error: Expected %d, but got %d instead on uri_combine_tests[%d].dword_props[%d].\n",
10459                                     prop.value, received, i, j);
10460                         }
10461                     }
10462                 }
10463                 if(result) IUri_Release(result);
10464             }
10465             if(relative) IUri_Release(relative);
10466             heap_free(relativeW);
10467         }
10468         if(base) IUri_Release(base);
10469         heap_free(baseW);
10470     }
10471 }
10472
10473 static HRESULT WINAPI InternetProtocolInfo_QueryInterface(IInternetProtocolInfo *iface,
10474                                                           REFIID riid, void **ppv)
10475 {
10476     ok(0, "unexpected call\n");
10477     return E_NOINTERFACE;
10478 }
10479
10480 static ULONG WINAPI InternetProtocolInfo_AddRef(IInternetProtocolInfo *iface)
10481 {
10482     return 2;
10483 }
10484
10485 static ULONG WINAPI InternetProtocolInfo_Release(IInternetProtocolInfo *iface)
10486 {
10487     return 1;
10488 }
10489
10490 static HRESULT WINAPI InternetProtocolInfo_ParseUrl(IInternetProtocolInfo *iface, LPCWSTR pwzUrl,
10491         PARSEACTION ParseAction, DWORD dwParseFlags, LPWSTR pwzResult, DWORD cchResult,
10492         DWORD *pcchResult, DWORD dwReserved)
10493 {
10494     CHECK_EXPECT(ParseUrl);
10495     ok(!lstrcmpW(pwzUrl, parse_urlW), "Error: Expected %s, but got %s instead.\n",
10496         wine_dbgstr_w(parse_urlW), wine_dbgstr_w(pwzUrl));
10497     ok(ParseAction == parse_action, "Error: Expected %d, but got %d.\n", parse_action, ParseAction);
10498     ok(dwParseFlags == parse_flags, "Error: Expected 0x%08x, but got 0x%08x.\n", parse_flags, dwParseFlags);
10499     ok(cchResult == 200, "Error: Got %d.\n", cchResult);
10500
10501     memcpy(pwzResult, parse_resultW, sizeof(parse_resultW));
10502     *pcchResult = lstrlenW(parse_resultW);
10503
10504     return S_OK;
10505 }
10506
10507 static HRESULT WINAPI InternetProtocolInfo_CombineUrl(IInternetProtocolInfo *iface,
10508         LPCWSTR pwzBaseUrl, LPCWSTR pwzRelativeUrl, DWORD dwCombineFlags,
10509         LPWSTR pwzResult, DWORD cchResult, DWORD *pcchResult, DWORD dwReserved)
10510 {
10511     CHECK_EXPECT(CombineUrl);
10512     ok(!lstrcmpW(pwzBaseUrl, combine_baseW), "Error: Expected %s, but got %s instead.\n",
10513         wine_dbgstr_w(combine_baseW), wine_dbgstr_w(pwzBaseUrl));
10514     ok(!lstrcmpW(pwzRelativeUrl, combine_relativeW), "Error: Expected %s, but got %s instead.\n",
10515         wine_dbgstr_w(combine_relativeW), wine_dbgstr_w(pwzRelativeUrl));
10516     ok(dwCombineFlags == (URL_DONT_SIMPLIFY|URL_FILE_USE_PATHURL|URL_DONT_UNESCAPE_EXTRA_INFO),
10517         "Error: Expected 0, but got 0x%08x.\n", dwCombineFlags);
10518     ok(cchResult == INTERNET_MAX_URL_LENGTH+1, "Error: Got %d.\n", cchResult);
10519
10520     memcpy(pwzResult, combine_resultW, sizeof(combine_resultW));
10521     *pcchResult = lstrlenW(combine_resultW);
10522
10523     return S_OK;
10524 }
10525
10526 static HRESULT WINAPI InternetProtocolInfo_CompareUrl(IInternetProtocolInfo *iface,
10527         LPCWSTR pwzUrl1, LPCWSTR pwzUrl2, DWORD dwCompareFlags)
10528 {
10529     ok(0, "unexpected call\n");
10530     return E_NOTIMPL;
10531 }
10532
10533 static HRESULT WINAPI InternetProtocolInfo_QueryInfo(IInternetProtocolInfo *iface,
10534         LPCWSTR pwzUrl, QUERYOPTION OueryOption, DWORD dwQueryFlags, LPVOID pBuffer,
10535         DWORD cbBuffer, DWORD *pcbBuf, DWORD dwReserved)
10536 {
10537     ok(0, "unexpected call\n");
10538     return E_NOTIMPL;
10539 }
10540
10541 static const IInternetProtocolInfoVtbl InternetProtocolInfoVtbl = {
10542     InternetProtocolInfo_QueryInterface,
10543     InternetProtocolInfo_AddRef,
10544     InternetProtocolInfo_Release,
10545     InternetProtocolInfo_ParseUrl,
10546     InternetProtocolInfo_CombineUrl,
10547     InternetProtocolInfo_CompareUrl,
10548     InternetProtocolInfo_QueryInfo
10549 };
10550
10551 static IInternetProtocolInfo protocol_info = { &InternetProtocolInfoVtbl };
10552
10553 static HRESULT WINAPI ClassFactory_QueryInterface(IClassFactory *iface, REFIID riid, void **ppv)
10554 {
10555     if(IsEqualGUID(&IID_IInternetProtocolInfo, riid)) {
10556         *ppv = &protocol_info;
10557         return S_OK;
10558     }
10559
10560     ok(0, "unexpected call\n");
10561     return E_NOINTERFACE;
10562 }
10563
10564 static ULONG WINAPI ClassFactory_AddRef(IClassFactory *iface)
10565 {
10566     return 2;
10567 }
10568
10569 static ULONG WINAPI ClassFactory_Release(IClassFactory *iface)
10570 {
10571     return 1;
10572 }
10573
10574 static HRESULT WINAPI ClassFactory_CreateInstance(IClassFactory *iface, IUnknown *pOuter,
10575                                         REFIID riid, void **ppv)
10576 {
10577     ok(0, "unexpected call\n");
10578     return E_NOTIMPL;
10579 }
10580
10581 static HRESULT WINAPI ClassFactory_LockServer(IClassFactory *iface, BOOL dolock)
10582 {
10583     ok(0, "unexpected call\n");
10584     return S_OK;
10585 }
10586
10587 static const IClassFactoryVtbl ClassFactoryVtbl = {
10588     ClassFactory_QueryInterface,
10589     ClassFactory_AddRef,
10590     ClassFactory_Release,
10591     ClassFactory_CreateInstance,
10592     ClassFactory_LockServer
10593 };
10594
10595 static IClassFactory protocol_cf = { &ClassFactoryVtbl };
10596
10597 static void register_protocols(void)
10598 {
10599     IInternetSession *session;
10600     HRESULT hres;
10601
10602     hres = pCoInternetGetSession(0, &session, 0);
10603     ok(hres == S_OK, "CoInternetGetSession failed: %08x\n", hres);
10604     if(FAILED(hres))
10605         return;
10606
10607     hres = IInternetSession_RegisterNameSpace(session, &protocol_cf, &IID_NULL,
10608             winetestW, 0, NULL, 0);
10609     ok(hres == S_OK, "RegisterNameSpace failed: %08x\n", hres);
10610
10611     IInternetSession_Release(session);
10612 }
10613
10614 static void unregister_protocols(void) {
10615     IInternetSession *session;
10616     HRESULT hr;
10617
10618     hr = pCoInternetGetSession(0, &session, 0);
10619     ok(hr == S_OK, "CoInternetGetSession failed: 0x%08x\n", hr);
10620     if(FAILED(hr))
10621         return;
10622
10623     hr = IInternetSession_UnregisterNameSpace(session, &protocol_cf, winetestW);
10624     ok(hr == S_OK, "UnregisterNameSpace failed: 0x%08x\n", hr);
10625
10626     IInternetSession_Release(session);
10627 }
10628
10629 static void test_CoInternetCombineIUri_Pluggable(void) {
10630     HRESULT hr;
10631     IUri *base = NULL;
10632
10633     hr = pCreateUri(combine_baseW, 0, 0, &base);
10634     ok(SUCCEEDED(hr), "Error: CreateUri returned 0x%08x.\n", hr);
10635     if(SUCCEEDED(hr)) {
10636         IUri *relative = NULL;
10637
10638         hr = pCreateUri(combine_relativeW, Uri_CREATE_ALLOW_RELATIVE, 0, &relative);
10639         ok(SUCCEEDED(hr), "Error: CreateUri returned 0x%08x.\n", hr);
10640         if(SUCCEEDED(hr)) {
10641             IUri *result = NULL;
10642
10643             SET_EXPECT(CombineUrl);
10644
10645             hr = pCoInternetCombineIUri(base, relative, URL_DONT_SIMPLIFY|URL_FILE_USE_PATHURL|URL_DONT_UNESCAPE_EXTRA_INFO,
10646                                         &result, 0);
10647             ok(hr == S_OK, "Error: CoInternetCombineIUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
10648
10649             CHECK_CALLED(CombineUrl);
10650
10651             if(SUCCEEDED(hr)) {
10652                 BSTR received = NULL;
10653                 hr = IUri_GetAbsoluteUri(result, &received);
10654                 ok(hr == S_OK, "Error: Expected S_OK, but got 0x%08x instead.\n", hr);
10655                 if(SUCCEEDED(hr)) {
10656                     ok(!lstrcmpW(combine_resultW, received), "Error: Expected %s, but got %s.\n",
10657                         wine_dbgstr_w(combine_resultW), wine_dbgstr_w(received));
10658                 }
10659                 SysFreeString(received);
10660             }
10661             if(result) IUri_Release(result);
10662         }
10663         if(relative) IUri_Release(relative);
10664     }
10665     if(base) IUri_Release(base);
10666 }
10667
10668 static void test_CoInternetCombineUrlEx(void) {
10669     HRESULT hr;
10670     IUri *base, *result;
10671     DWORD i;
10672
10673     base = NULL;
10674     hr = pCreateUri(http_urlW, 0, 0, &base);
10675     ok(SUCCEEDED(hr), "Error: CreateUri returned 0x%08x.\n", hr);
10676     if(SUCCEEDED(hr)) {
10677         result = (void*) 0xdeadbeef;
10678         hr = pCoInternetCombineUrlEx(base, NULL, 0, &result, 0);
10679         ok(hr == E_UNEXPECTED, "Error: CoInternetCombineUrlEx returned 0x%08x, expected 0x%08x.\n",
10680             hr, E_UNEXPECTED);
10681         ok(!result, "Error: Expected 'result' to be NULL was %p instead.\n", result);
10682     }
10683
10684     result = (void*) 0xdeadbeef;
10685     hr = pCoInternetCombineUrlEx(NULL, http_urlW, 0, &result, 0);
10686     ok(hr == E_INVALIDARG, "Error: CoInternetCombineUrlEx returned 0x%08x, expected 0x%08x.\n",
10687         hr, E_INVALIDARG);
10688     ok(!result, "Error: Expected 'result' to be NULL, but was %p instead.\n", result);
10689
10690     result = (void*) 0xdeadbeef;
10691     hr = pCoInternetCombineUrlEx(NULL, NULL, 0, &result, 0);
10692     ok(hr == E_UNEXPECTED, "Error: CoInternetCombineUrlEx returned 0x%08x, expected 0x%08x.\n",
10693         hr, E_UNEXPECTED);
10694     ok(!result, "Error: Expected 'result' to be NULL, but was %p instead.\n", result);
10695
10696     hr = pCoInternetCombineUrlEx(base, http_urlW, 0, NULL, 0);
10697     ok(hr == E_POINTER, "Error: CoInternetCombineUrlEx returned 0x%08x, expected 0x%08x.\n",
10698         hr, E_POINTER);
10699     if(base) IUri_Release(base);
10700
10701     for(i = 0; i < sizeof(uri_combine_tests)/sizeof(uri_combine_tests[0]); ++i) {
10702         LPWSTR baseW = a2w(uri_combine_tests[i].base_uri);
10703
10704         hr = pCreateUri(baseW, uri_combine_tests[i].base_create_flags, 0, &base);
10705         ok(SUCCEEDED(hr), "Error: CreateUri returned 0x%08x on uri_combine_tests[%d].\n", hr, i);
10706         if(SUCCEEDED(hr)) {
10707             LPWSTR relativeW = a2w(uri_combine_tests[i].relative_uri);
10708
10709             hr = pCoInternetCombineUrlEx(base, relativeW, uri_combine_tests[i].combine_flags,
10710                                          &result, 0);
10711             if(uri_combine_tests[i].todo) {
10712                 todo_wine {
10713                     ok(hr == uri_combine_tests[i].expected,
10714                         "Error: CoInternetCombineUrlEx returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].\n",
10715                         hr, uri_combine_tests[i].expected, i);
10716                 }
10717             } else {
10718                 ok(hr == uri_combine_tests[i].expected,
10719                     "Error: CoInternetCombineUrlEx returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].\n",
10720                     hr, uri_combine_tests[i]. expected, i);
10721             }
10722             if(SUCCEEDED(hr)) {
10723                 DWORD j;
10724
10725                 for(j = 0; j < sizeof(uri_combine_tests[i].str_props)/sizeof(uri_combine_tests[i].str_props[0]); ++j) {
10726                     uri_combine_str_property prop = uri_combine_tests[i].str_props[j];
10727                     BSTR received;
10728                     LPCSTR value = (prop.value_ex) ? prop.value_ex : prop.value;
10729
10730                     hr = IUri_GetPropertyBSTR(result, j, &received, 0);
10731                     if(prop.todo) {
10732                         todo_wine {
10733                             ok(hr == prop.expected,
10734                                 "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].str_props[%d].\n",
10735                                 hr, prop.expected, i, j);
10736                         }
10737                         todo_wine {
10738                             ok(!strcmp_aw(value, received) ||
10739                                broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
10740                                 "Error: Expected \"%s\" but got %s instead on uri_combine_tests[%d].str_props[%d].\n",
10741                                 value, wine_dbgstr_w(received), i, j);
10742                         }
10743                     } else {
10744                         ok(hr == prop.expected,
10745                             "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].str_props[%d].\n",
10746                             hr, prop.expected, i, j);
10747                         ok(!strcmp_aw(value, received) ||
10748                            broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
10749                             "Error: Expected \"%s\" but got %s instead on uri_combine_tests[%d].str_props[%d].\n",
10750                             value, wine_dbgstr_w(received), i, j);
10751                     }
10752                     SysFreeString(received);
10753                 }
10754
10755                 for(j = 0; j < sizeof(uri_combine_tests[i].dword_props)/sizeof(uri_combine_tests[i].dword_props[0]); ++j) {
10756                     uri_dword_property prop = uri_combine_tests[i].dword_props[j];
10757                     DWORD received;
10758
10759                     hr = IUri_GetPropertyDWORD(result, j+Uri_PROPERTY_DWORD_START, &received, 0);
10760                     if(prop.todo) {
10761                         todo_wine {
10762                             ok(hr == prop.expected,
10763                                 "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].dword_props[%d].\n",
10764                                 hr, prop.expected, i, j);
10765                         }
10766                         todo_wine {
10767                             ok(prop.value == received, "Error: Expected %d, but got %d instead on uri_combine_tests[%d].dword_props[%d].\n",
10768                                 prop.value, received, i, j);
10769                         }
10770                     } else {
10771                         ok(hr == prop.expected || broken(prop.broken_combine_hres && hr == S_FALSE),
10772                             "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].dword_props[%d].\n",
10773                             hr, prop.expected, i, j);
10774                         if(!prop.broken_combine_hres || hr != S_FALSE)
10775                             ok(prop.value == received, "Error: Expected %d, but got %d instead on uri_combine_tests[%d].dword_props[%d].\n",
10776                                 prop.value, received, i, j);
10777                     }
10778                 }
10779             }
10780             if(result) IUri_Release(result);
10781             heap_free(relativeW);
10782         }
10783         if(base) IUri_Release(base);
10784         heap_free(baseW);
10785     }
10786 }
10787
10788 static void test_CoInternetCombineUrlEx_Pluggable(void) {
10789     HRESULT hr;
10790     IUri *base = NULL;
10791
10792     hr = pCreateUri(combine_baseW, 0, 0, &base);
10793     ok(SUCCEEDED(hr), "Error: CreateUri returned 0x%08x.\n", hr);
10794     if(SUCCEEDED(hr)) {
10795         IUri *result = NULL;
10796
10797         SET_EXPECT(CombineUrl);
10798
10799         hr = pCoInternetCombineUrlEx(base, combine_relativeW, URL_DONT_SIMPLIFY|URL_FILE_USE_PATHURL|URL_DONT_UNESCAPE_EXTRA_INFO,
10800                                      &result, 0);
10801         ok(hr == S_OK, "Error: CoInternetCombineUrlEx returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
10802
10803         CHECK_CALLED(CombineUrl);
10804
10805         if(SUCCEEDED(hr)) {
10806             BSTR received = NULL;
10807             hr = IUri_GetAbsoluteUri(result, &received);
10808             ok(hr == S_OK, "Error: Expected S_OK, but got 0x%08x instead.\n", hr);
10809             if(SUCCEEDED(hr)) {
10810                 ok(!lstrcmpW(combine_resultW, received), "Error: Expected %s, but got %s.\n",
10811                     wine_dbgstr_w(combine_resultW), wine_dbgstr_w(received));
10812             }
10813             SysFreeString(received);
10814         }
10815         if(result) IUri_Release(result);
10816     }
10817     if(base) IUri_Release(base);
10818 }
10819
10820 static void test_CoInternetParseIUri_InvalidArgs(void) {
10821     HRESULT hr;
10822     IUri *uri = NULL;
10823     WCHAR tmp[3];
10824     DWORD result = -1;
10825
10826     hr = pCoInternetParseIUri(NULL, PARSE_CANONICALIZE, 0, tmp, 3, &result, 0);
10827     ok(hr == E_INVALIDARG, "Error: CoInternetParseIUri returned 0x%08x, expected 0x%08x.\n",
10828         hr, E_INVALIDARG);
10829     ok(!result, "Error: Expected 'result' to be 0, but was %d.\n", result);
10830
10831     hr = pCreateUri(http_urlW, 0, 0, &uri);
10832     ok(SUCCEEDED(hr), "Error: CreateUri returned 0x%08x.\n", hr);
10833     if(SUCCEEDED(hr)) {
10834         DWORD expected_len;
10835
10836         result = -1;
10837         hr = pCoInternetParseIUri(uri, PARSE_CANONICALIZE, 0, NULL, 0, &result, 0);
10838         ok(hr == E_INVALIDARG, "Error: CoInternetParseIUri returned 0x%08x, expected 0x%08x.\n",
10839             hr, E_INVALIDARG);
10840         ok(!result, "Error: Expected 'result' to be 0, but was %d.\n", result);
10841
10842         hr = pCoInternetParseIUri(uri, PARSE_CANONICALIZE, 0, tmp, 3, NULL, 0);
10843         ok(hr == E_POINTER, "Error: CoInternetParseIUri returned 0x%08x, expected 0x%08x.\n",
10844             hr, E_POINTER);
10845
10846         result = -1;
10847         hr = pCoInternetParseIUri(uri, PARSE_SECURITY_URL, 0, tmp, 3, &result, 0);
10848         ok(hr == E_FAIL, "Error: CoInternetParseIUri returned 0x%08x expected 0x%08x.\n",
10849             hr, E_FAIL);
10850         ok(!result, "Error: Expected 'result' to be 0, but was %d.\n", result);
10851
10852         result = -1;
10853         hr = pCoInternetParseIUri(uri, PARSE_MIME, 0, tmp, 3, &result, 0);
10854         ok(hr == E_FAIL, "Error: CoInternetParseIUri returned 0x%08x, expected 0x%08x.\n",
10855             hr, E_FAIL);
10856         ok(!result, "Error: Expected 'result' to be 0, but was %d.\n", result);
10857
10858         result = -1;
10859         hr = pCoInternetParseIUri(uri, PARSE_SERVER, 0, tmp, 3, &result, 0);
10860         ok(hr == E_FAIL, "Error: CoInternetParseIUri returned 0x%08x, expected 0x%08x.\n",
10861             hr, E_FAIL);
10862         ok(!result, "Error: Expected 'result' to be 0, but was %d.\n", result);
10863
10864         result = -1;
10865         hr = pCoInternetParseIUri(uri, PARSE_SECURITY_DOMAIN, 0, tmp, 3, &result, 0);
10866         ok(hr == E_FAIL, "Error: CoInternetParseIUri returned 0x%08x, expected 0x%08x.\n",
10867             hr, E_FAIL);
10868         ok(!result, "Error: Expected 'result' to be 0, but was %d.\n", result);
10869
10870         expected_len = lstrlenW(http_urlW);
10871         result = -1;
10872         hr = pCoInternetParseIUri(uri, PARSE_CANONICALIZE, 0, tmp, 3, &result, 0);
10873         ok(hr == STRSAFE_E_INSUFFICIENT_BUFFER,
10874             "Error: CoInternetParseIUri returned 0x%08x, expected 0x%08x.\n",
10875             hr, STRSAFE_E_INSUFFICIENT_BUFFER);
10876         ok(result == expected_len, "Error: Expected 'result' to be %d, but was %d instead.\n",
10877             expected_len, result);
10878     }
10879     if(uri) IUri_Release(uri);
10880 }
10881
10882 static void test_CoInternetParseIUri(void) {
10883     DWORD i;
10884
10885     for(i = 0; i < sizeof(uri_parse_tests)/sizeof(uri_parse_tests[0]); ++i) {
10886         HRESULT hr;
10887         IUri *uri;
10888         LPWSTR uriW;
10889         uri_parse_test test = uri_parse_tests[i];
10890
10891         uriW = a2w(test.uri);
10892         hr = pCreateUri(uriW, test.uri_flags, 0, &uri);
10893         ok(SUCCEEDED(hr), "Error: CreateUri returned 0x%08x on uri_parse_tests[%d].\n", hr, i);
10894         if(SUCCEEDED(hr)) {
10895             WCHAR result[INTERNET_MAX_URL_LENGTH+1];
10896             DWORD result_len = -1;
10897
10898             hr = pCoInternetParseIUri(uri, test.action, test.flags, result, INTERNET_MAX_URL_LENGTH+1, &result_len, 0);
10899             if(test.todo) {
10900                 todo_wine {
10901                     ok(hr == test.expected,
10902                         "Error: CoInternetParseIUri returned 0x%08x, expected 0x%08x on uri_parse_tests[%d].\n",
10903                         hr, test.expected, i);
10904                 }
10905             } else {
10906                 ok(hr == test.expected,
10907                     "Error: CoInternetParseIUri returned 0x%08x, expected 0x%08x on uri_parse_tests[%d].\n",
10908                     hr, test.expected, i);
10909             }
10910             if(SUCCEEDED(hr)) {
10911                 DWORD len = lstrlenA(test.property);
10912                 ok(!strcmp_aw(test.property, result),
10913                     "Error: Expected %s but got %s instead on uri_parse_tests[%d].\n",
10914                     test.property, wine_dbgstr_w(result), i);
10915                 ok(len == result_len,
10916                     "Error: Expected %d, but got %d instead on uri_parse_tests[%d].\n",
10917                     len, result_len, i);
10918             } else {
10919                 ok(!result_len,
10920                     "Error: Expected 'result_len' to be 0, but was %d on uri_parse_tests[%d].\n",
10921                     result_len, i);
10922             }
10923         }
10924         if(uri) IUri_Release(uri);
10925         heap_free(uriW);
10926     }
10927 }
10928
10929 static void test_CoInternetParseIUri_Pluggable(void) {
10930     HRESULT hr;
10931     IUri *uri = NULL;
10932
10933     hr = pCreateUri(parse_urlW, 0, 0, &uri);
10934     ok(SUCCEEDED(hr), "Error: Expected CreateUri to succeed, but got 0x%08x.\n", hr);
10935     if(SUCCEEDED(hr)) {
10936         WCHAR result[200];
10937         DWORD result_len;
10938
10939         SET_EXPECT(ParseUrl);
10940
10941         parse_action = PARSE_CANONICALIZE;
10942         parse_flags = URL_UNESCAPE|URL_ESCAPE_UNSAFE;
10943
10944         hr = pCoInternetParseIUri(uri, parse_action, parse_flags, result, 200, &result_len, 0);
10945         ok(hr == S_OK, "Error: CoInternetParseIUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
10946
10947         CHECK_CALLED(ParseUrl);
10948
10949         if(SUCCEEDED(hr)) {
10950             ok(result_len == lstrlenW(parse_resultW), "Error: Expected %d, but got %d.\n",
10951                 lstrlenW(parse_resultW), result_len);
10952             ok(!lstrcmpW(result, parse_resultW), "Error: Expected %s, but got %s.\n",
10953                 wine_dbgstr_w(parse_resultW), wine_dbgstr_w(result));
10954         }
10955     }
10956     if(uri) IUri_Release(uri);
10957 }
10958
10959 typedef struct {
10960     const char *url;
10961     DWORD uri_flags;
10962     const char *base_url;
10963     DWORD base_uri_flags;
10964     const char *legacy_url;
10965     const char *uniform_url;
10966     const char *no_canon_url;
10967     const char *uri_url;
10968 } create_urlmon_test_t;
10969
10970 static const create_urlmon_test_t create_urlmon_tests[] = {
10971     {
10972         "http://www.winehq.org",Uri_CREATE_NO_CANONICALIZE,
10973         NULL,0,
10974         "http://www.winehq.org/",
10975         "http://www.winehq.org/",
10976         "http://www.winehq.org",
10977         "http://www.winehq.org"
10978     },
10979     {
10980         "file://c:\\dir\\file.txt",Uri_CREATE_NO_CANONICALIZE,
10981         NULL,0,
10982         "file://c:\\dir\\file.txt",
10983         "file:///c:/dir/file.txt",
10984         "file:///c:/dir/file.txt",
10985         "file:///c:/dir/file.txt"
10986     },
10987     {
10988         "file://c:\\dir\\file.txt",Uri_CREATE_FILE_USE_DOS_PATH,
10989         NULL,0,
10990         "file://c:\\dir\\file.txt",
10991         "file:///c:/dir/file.txt",
10992         "file:///c:/dir/file.txt",
10993         "file://c:\\dir\\file.txt"
10994     },
10995     {
10996         "dat%61",Uri_CREATE_ALLOW_RELATIVE,
10997         "http://www.winehq.org",0,
10998         "http://www.winehq.org/data",
10999         "http://www.winehq.org/data",
11000         "http://www.winehq.org:80/data",
11001     },
11002     {
11003         "file.txt",Uri_CREATE_ALLOW_RELATIVE,
11004         "file://c:\\dir\\x.txt",Uri_CREATE_NO_CANONICALIZE,
11005         "file://c:\\dir\\file.txt",
11006         "file:///c:/dir/file.txt",
11007         "file:///c:/dir/file.txt",
11008     },
11009     {
11010         "",Uri_CREATE_ALLOW_RELATIVE,
11011         NULL,0,
11012         "",
11013         "",
11014         "",
11015         ""
11016     },
11017     {
11018         "test",Uri_CREATE_ALLOW_RELATIVE,
11019         NULL,0,
11020         "test",
11021         "test",
11022         "test",
11023         "test"
11024     },
11025     {
11026         "c:\\dir\\file.txt",Uri_CREATE_ALLOW_IMPLICIT_FILE_SCHEME,
11027         NULL,0,
11028         "file://c:\\dir\\file.txt",
11029         "file:///c:/dir/file.txt",
11030         "file:///c:/dir/file.txt",
11031         "file:///c:/dir/file.txt",
11032     }
11033 };
11034
11035 #define test_urlmon_display_name(a,b) _test_urlmon_display_name(__LINE__,a,b)
11036 static void _test_urlmon_display_name(unsigned line, IMoniker *mon, const char *exurl)
11037 {
11038     WCHAR *display_name;
11039     HRESULT hres;
11040
11041     hres = IMoniker_GetDisplayName(mon, NULL, NULL, &display_name);
11042     ok_(__FILE__,line)(hres == S_OK, "GetDisplayName failed: %08x\n", hres);
11043     ok_(__FILE__,line)(!strcmp_aw(exurl, display_name), "unexpected display name: %s, expected %s\n",
11044             wine_dbgstr_w(display_name), exurl);
11045
11046     CoTaskMemFree(display_name);
11047 }
11048
11049 #define test_display_uri(a,b) _test_display_uri(__LINE__,a,b)
11050 static void _test_display_uri(unsigned line, IMoniker *mon, const char *exurl)
11051 {
11052     IUriContainer *uri_container;
11053     IUri *uri;
11054     BSTR display_uri;
11055     HRESULT hres;
11056
11057     hres = IMoniker_QueryInterface(mon, &IID_IUriContainer, (void**)&uri_container);
11058     ok(hres == S_OK, "Could not get IUriContainer iface: %08x\n", hres);
11059
11060     uri = NULL;
11061     hres = IUriContainer_GetIUri(uri_container, &uri);
11062     IUriContainer_Release(uri_container);
11063     ok(hres == S_OK, "GetIUri failed: %08x\n", hres);
11064     ok(uri != NULL, "uri == NULL\n");
11065
11066     hres = IUri_GetDisplayUri(uri, &display_uri);
11067     IUri_Release(uri);
11068     ok(hres == S_OK, "GetDisplayUri failed: %08x\n", hres);
11069     ok_(__FILE__,line)(!strcmp_aw(exurl, display_uri), "unexpected display uri: %s, expected %s\n",
11070             wine_dbgstr_w(display_uri), exurl);
11071     SysFreeString(display_uri);
11072 }
11073
11074 static void test_CreateURLMoniker(void)
11075 {
11076     const create_urlmon_test_t *test;
11077     IMoniker *mon, *base_mon;
11078     WCHAR *url, *base_url;
11079     IUri *uri, *base_uri;
11080     HRESULT hres;
11081
11082     for(test = create_urlmon_tests; test < create_urlmon_tests + sizeof(create_urlmon_tests)/sizeof(*create_urlmon_tests); test++) {
11083         url = a2w(test->url);
11084         base_url = a2w(test->base_url);
11085
11086         if(base_url) {
11087             hres = pCreateUri(base_url, test->base_uri_flags, 0, &base_uri);
11088             ok(hres == S_OK, "CreateUri failed: %08x\n", hres);
11089
11090             hres = pCreateURLMonikerEx2(NULL, base_uri, &base_mon, URL_MK_NO_CANONICALIZE);
11091             ok(hres == S_OK, "CreateURLMonikerEx2 failed: %08x\n", hres);
11092         }else {
11093             base_uri = NULL;
11094             base_mon = NULL;
11095         }
11096
11097         hres = CreateURLMoniker(base_mon, url, &mon);
11098         ok(hres == S_OK, "CreateURLMoniker failed: %08x\n", hres);
11099         test_urlmon_display_name(mon, test->legacy_url);
11100         test_display_uri(mon, test->legacy_url);
11101         IMoniker_Release(mon);
11102
11103         hres = pCreateURLMonikerEx(base_mon, url, &mon, URL_MK_LEGACY);
11104         ok(hres == S_OK, "CreateURLMoniker failed: %08x\n", hres);
11105         test_urlmon_display_name(mon, test->legacy_url);
11106         test_display_uri(mon, test->legacy_url);
11107         IMoniker_Release(mon);
11108
11109         hres = pCreateURLMonikerEx(base_mon, url, &mon, URL_MK_UNIFORM);
11110         ok(hres == S_OK, "CreateURLMoniker failed: %08x\n", hres);
11111         test_urlmon_display_name(mon, test->uniform_url);
11112         test_display_uri(mon, test->uniform_url);
11113         IMoniker_Release(mon);
11114
11115         hres = pCreateURLMonikerEx(base_mon, url, &mon, URL_MK_NO_CANONICALIZE);
11116         ok(hres == S_OK, "CreateURLMoniker failed: %08x\n", hres);
11117         test_urlmon_display_name(mon, test->no_canon_url);
11118         test_display_uri(mon, test->no_canon_url);
11119         IMoniker_Release(mon);
11120
11121         hres = pCreateUri(url, test->uri_flags, 0, &uri);
11122         ok(hres == S_OK, "CreateUri failed: %08x\n", hres);
11123
11124         hres = pCreateURLMonikerEx2(base_mon, uri, &mon, URL_MK_LEGACY);
11125         ok(hres == S_OK, "CreateURLMonikerEx2 failed: %08x\n", hres);
11126         test_urlmon_display_name(mon, base_url ? test->legacy_url : test->uri_url);
11127         test_display_uri(mon, base_url ? test->legacy_url : test->uri_url);
11128         IMoniker_Release(mon);
11129
11130         hres = pCreateURLMonikerEx2(base_mon, uri, &mon, URL_MK_UNIFORM);
11131         ok(hres == S_OK, "CreateURLMonikerEx2 failed: %08x\n", hres);
11132         test_urlmon_display_name(mon, base_url ? test->uniform_url : test->uri_url);
11133         test_display_uri(mon, base_url ? test->uniform_url : test->uri_url);
11134         IMoniker_Release(mon);
11135
11136         hres = pCreateURLMonikerEx2(base_mon, uri, &mon, URL_MK_NO_CANONICALIZE);
11137         ok(hres == S_OK, "CreateURLMonikerEx2 failed: %08x\n", hres);
11138         test_urlmon_display_name(mon, base_url ? test->no_canon_url : test->uri_url);
11139         test_display_uri(mon, base_url ? test->no_canon_url : test->uri_url);
11140         IMoniker_Release(mon);
11141
11142         IUri_Release(uri);
11143         heap_free(url);
11144         heap_free(base_url);
11145         if(base_uri)
11146             IUri_Release(base_uri);
11147         if(base_mon)
11148             IMoniker_Release(base_mon);
11149     }
11150 }
11151
11152 static int add_default_flags(DWORD flags) {
11153     if(!(flags & Uri_CREATE_NO_CANONICALIZE))
11154         flags |= Uri_CREATE_CANONICALIZE;
11155     if(!(flags & Uri_CREATE_NO_DECODE_EXTRA_INFO))
11156         flags |= Uri_CREATE_DECODE_EXTRA_INFO;
11157     if(!(flags & Uri_CREATE_NO_CRACK_UNKNOWN_SCHEMES))
11158         flags |= Uri_CREATE_CRACK_UNKNOWN_SCHEMES;
11159     if(!(flags & Uri_CREATE_NO_PRE_PROCESS_HTML_URI))
11160         flags |= Uri_CREATE_PRE_PROCESS_HTML_URI;
11161     if(!(flags & Uri_CREATE_IE_SETTINGS))
11162         flags |= Uri_CREATE_NO_IE_SETTINGS;
11163
11164     return flags;
11165 }
11166
11167 static void test_IPersistStream(void)
11168 {
11169     int i, props_order[Uri_PROPERTY_DWORD_LAST+1] = { 0 };
11170
11171     props_order[Uri_PROPERTY_RAW_URI] = 1;
11172     props_order[Uri_PROPERTY_FRAGMENT] = 2;
11173     props_order[Uri_PROPERTY_HOST] = 3;
11174     props_order[Uri_PROPERTY_PASSWORD] = 4;
11175     props_order[Uri_PROPERTY_PATH] = 5;
11176     props_order[Uri_PROPERTY_PORT] = 6;
11177     props_order[Uri_PROPERTY_QUERY] = 7;
11178     props_order[Uri_PROPERTY_SCHEME_NAME] = 8;
11179     props_order[Uri_PROPERTY_USER_NAME] = 9;
11180
11181     for(i=0; i<sizeof(uri_tests)/sizeof(*uri_tests); i++) {
11182         const uri_properties *test = uri_tests+i;
11183         LPWSTR uriW;
11184         IUri *uri;
11185         IPersistStream *persist_stream;
11186         IStream *stream;
11187         IMarshal *marshal;
11188         DWORD props, props_no, dw_data[6];
11189         WCHAR str_data[1024];
11190         ULARGE_INTEGER size, max_size;
11191         LARGE_INTEGER no_off;
11192         CLSID curi;
11193         BSTR raw_uri;
11194         HRESULT hr;
11195
11196         if(test->create_todo || test->create_expected!=S_OK)
11197             continue;
11198
11199         uriW = a2w(test->uri);
11200         hr = pCreateUri(uriW, test->create_flags, 0, &uri);
11201         ok(hr == S_OK, "%d) CreateUri failed 0x%08x, expected S_OK..\n", i, hr);
11202
11203         hr = IUri_QueryInterface(uri, &IID_IPersistStream, (void**)&persist_stream);
11204         ok(hr == S_OK, "%d) QueryInterface failed 0x%08x, expected S_OK.\n", i, hr);
11205
11206         hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
11207         ok(hr == S_OK, "CreateStreamOnHGlobal failed 0x%08x.\n", hr);
11208         hr = IPersistStream_IsDirty(persist_stream);
11209         ok(hr == S_FALSE, "%d) IsDirty returned 0x%08x, expected S_FALSE.\n", i, hr);
11210         hr = IPersistStream_Save(persist_stream, stream, FALSE);
11211         ok(hr == S_OK, "%d) Save failed 0x%08x, expected S_OK.\n", i, hr);
11212         hr = IPersistStream_IsDirty(persist_stream);
11213         ok(hr == S_FALSE, "%d) IsDirty returned 0x%08x, expected S_FALSE.\n", i, hr);
11214         no_off.QuadPart = 0;
11215         hr = IStream_Seek(stream, no_off, STREAM_SEEK_CUR, &size);
11216         ok(hr == S_OK, "%d) Seek failed 0x%08x, expected S_OK.\n", i, hr);
11217         hr = IStream_Seek(stream, no_off, STREAM_SEEK_SET, NULL);
11218         ok(hr == S_OK, "%d) Seek failed 0x%08x, expected S_OK.\n", i, hr);
11219         hr = IPersistStream_GetSizeMax(persist_stream, &max_size);
11220         ok(hr == S_OK, "%d) GetSizeMax failed 0x%08x, expected S_OK.\n", i, hr);
11221         ok(U(size).LowPart+2 == U(max_size).LowPart,
11222                 "%d) Written data size is %d, max_size %d.\n",
11223                 i, U(size).LowPart, U(max_size).LowPart);
11224
11225         hr = IStream_Read(stream, (void*)dw_data, sizeof(DWORD), NULL);
11226         ok(hr == S_OK, "%d) Read failed 0x%08x, expected S_OK.\n", i, hr);
11227         ok(dw_data[0]-2 == U(size).LowPart, "%d) Structure size is %d, expected %d\n",
11228                 i, dw_data[0]-2, U(size).LowPart);
11229         hr = IStream_Read(stream, (void*)dw_data, 6*sizeof(DWORD), NULL);
11230         ok(hr == S_OK, "%d) Read failed 0x%08x, expected S_OK.\n", i, hr);
11231         ok(dw_data[0] == 0, "%d) Incorrect value %x, expected 0 (unknown).\n", i, dw_data[0]);
11232         ok(dw_data[1] == 0, "%d) Incorrect value %x, expected 0 (unknown).\n", i, dw_data[1]);
11233         ok(dw_data[2] == add_default_flags(test->create_flags),
11234                 "%d) Incorrect value %x, expected %x (creation flags).\n",
11235                 i, dw_data[2], add_default_flags(test->create_flags));
11236         ok(dw_data[3] == 0, "%d) Incorrect value %x, expected 0 (unknown).\n", i, dw_data[3]);
11237         ok(dw_data[4] == 0, "%d) Incorrect value %x, expected 0 (unknown).\n", i, dw_data[4]);
11238         ok(dw_data[5] == 0, "%d) Incorrect value %x, expected 0 (unknown).\n", i, dw_data[5]);
11239
11240         props_no = 0;
11241         for(props=0; props<=Uri_PROPERTY_DWORD_LAST; props++) {
11242             if(!props_order[props])
11243                 continue;
11244
11245             if(props <= Uri_PROPERTY_STRING_LAST) {
11246                 if(test->str_props[props].expected == S_OK)
11247                     props_no++;
11248             } else {
11249                 if(test->dword_props[props-Uri_PROPERTY_DWORD_START].expected == S_OK)
11250                     props_no++;
11251             }
11252         }
11253         if(test->dword_props[Uri_PROPERTY_SCHEME-Uri_PROPERTY_DWORD_START].value != URL_SCHEME_HTTP
11254                 && test->dword_props[Uri_PROPERTY_SCHEME-Uri_PROPERTY_DWORD_START].value != URL_SCHEME_FTP
11255                 && test->dword_props[Uri_PROPERTY_SCHEME-Uri_PROPERTY_DWORD_START].value != URL_SCHEME_HTTPS)
11256             props_no = 1;
11257
11258         hr = IStream_Read(stream, (void*)&props, sizeof(DWORD), NULL);
11259         ok(hr == S_OK, "%d) Read failed 0x%08x, expected S_OK.\n", i, hr);
11260         ok(props == props_no, "%d) Properties no is %d, expected %d.\n", i, props, props_no);
11261
11262         dw_data[2] = 0;
11263         dw_data[3] = -1;
11264         while(props) {
11265             hr = IStream_Read(stream, (void*)dw_data, 2*sizeof(DWORD), NULL);
11266             ok(hr == S_OK, "%d) Read failed 0x%08x, expected S_OK.\n", i, hr);
11267             props--;
11268             ok(dw_data[2]<props_order[dw_data[0]],
11269                     "%d) Incorrect properties order (%d, %d)\n",
11270                     i, dw_data[0], dw_data[3]);
11271             dw_data[2] = props_order[dw_data[0]];
11272             dw_data[3] = dw_data[0];
11273
11274             if(dw_data[0]<=Uri_PROPERTY_STRING_LAST) {
11275                 const uri_str_property *prop = test->str_props+dw_data[0];
11276                 hr = IStream_Read(stream, (void*)str_data, dw_data[1], NULL);
11277                 ok(hr == S_OK, "%d) Read failed 0x%08x, expected S_OK.\n", i, hr);
11278                 ok(!strcmp_aw(prop->value, str_data) || broken(prop->broken_value && !strcmp_aw(prop->broken_value, str_data)),
11279                         "%d) Expected %s but got %s (%d).\n", i, prop->value, wine_dbgstr_w(str_data), dw_data[0]);
11280             } else if(dw_data[0]>=Uri_PROPERTY_DWORD_START && dw_data[0]<=Uri_PROPERTY_DWORD_LAST) {
11281                 const uri_dword_property *prop = test->dword_props+dw_data[0]-Uri_PROPERTY_DWORD_START;
11282                 ok(dw_data[1] == sizeof(DWORD), "%d) Size of dword property is %d (%d)\n", i, dw_data[1], dw_data[0]);
11283                 hr = IStream_Read(stream, (void*)&dw_data[1], sizeof(DWORD), NULL);
11284                 ok(hr == S_OK, "%d) Read failed 0x%08x, expected S_OK.\n", i, hr);
11285                 ok(prop->value == dw_data[1], "%d) Expected %d but got %d (%d).\n", i, prop->value, dw_data[1], dw_data[0]);
11286             } else {
11287                 ok(FALSE, "%d) Incorrect property type (%d)\n", i, dw_data[0]);
11288                 break;
11289             }
11290         }
11291         ok(props == 0, "%d) Not all properties were processed %d. Next property type: %d\n",
11292                 i, props, dw_data[0]);
11293
11294         IPersistStream_Release(persist_stream);
11295         IUri_Release(uri);
11296
11297         hr = IStream_Seek(stream, no_off, STREAM_SEEK_SET, NULL);
11298         ok(hr == S_OK, "%d) Seek failed 0x%08x, expected S_OK.\n", i, hr);
11299         hr = IPersistStream_GetClassID(persist_stream, &curi);
11300         ok(hr == S_OK, "%d) GetClassID failed 0x%08x, expected S_OK.\n", i, hr);
11301         ok(IsEqualCLSID(&curi, &CLSID_CUri), "%d) GetClassID returned incorrect CLSID.\n", i);
11302         hr = CoCreateInstance(&curi, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
11303                 &IID_IUri, (void**)&uri);
11304         ok(hr == S_OK, "%d) Error creating uninitialized Uri: 0x%08x.\n", i, hr);
11305         hr = IUri_QueryInterface(uri, &IID_IPersistStream, (void**)&persist_stream);
11306         ok(hr == S_OK, "%d) QueryInterface failed 0x%08x, expected S_OK.\n", i, hr);
11307         hr = IPersistStream_Load(persist_stream, stream);
11308         ok(hr == S_OK, "%d) Load failed 0x%08x, expected S_OK.\n", i, hr);
11309         hr = IUri_GetRawUri(uri, &raw_uri);
11310         ok(hr == S_OK, "%d) GetRawUri failed 0x%08x, expected S_OK.\n", i, hr);
11311         ok(!strcmp_aw(test->str_props[Uri_PROPERTY_RAW_URI].value, raw_uri)
11312                 || broken(test->str_props[Uri_PROPERTY_RAW_URI].broken_value
11313                     && !strcmp_aw(test->str_props[Uri_PROPERTY_RAW_URI].broken_value, raw_uri)),
11314                 "%d) Expected %s but got %s.\n", i, test->str_props[Uri_PROPERTY_RAW_URI].value,
11315                 wine_dbgstr_w(raw_uri));
11316         SysFreeString(raw_uri);
11317
11318         hr = IUri_QueryInterface(uri, &IID_IMarshal, (void**)&marshal);
11319         ok(hr == S_OK, "%d) QueryInterface(IID_IMarshal) failed 0x%08x, expected S_OK.\n", i, hr);
11320         hr = IStream_Seek(stream, no_off, STREAM_SEEK_SET, NULL);
11321         ok(hr == S_OK, "%d) Seek failed 0x%08x, expected S_OK.\n", i, hr);
11322         hr = IMarshal_MarshalInterface(marshal, stream, &IID_IUri, (void*)uri,
11323                 MSHCTX_DIFFERENTMACHINE, NULL, MSHLFLAGS_NORMAL);
11324         ok(hr == E_INVALIDARG, "%d) MarshalInterface returned 0x%08x, expected E_INVALIDARG.\n", i, hr);
11325         hr = IMarshal_MarshalInterface(marshal, stream, &IID_IUri, (void*)uri,
11326                 MSHCTX_CROSSCTX, NULL, MSHLFLAGS_NORMAL);
11327         ok(hr == E_INVALIDARG, "%d) MarshalInterface returned 0x%08x, expected E_INVALIDARG.\n", i, hr);
11328         hr = IMarshal_MarshalInterface(marshal, stream, &IID_IUri, (void*)uri,
11329                 MSHCTX_LOCAL, NULL, MSHLFLAGS_TABLESTRONG);
11330         ok(hr == E_INVALIDARG, "%d) MarshalInterface returned 0x%08x, expected E_INVALIDARG.\n", i, hr);
11331         hr = IMarshal_MarshalInterface(marshal, stream, &IID_IUri, (void*)uri,
11332                 MSHCTX_LOCAL, NULL, MSHLFLAGS_TABLEWEAK);
11333         ok(hr == E_INVALIDARG, "%d) MarshalInterface returned 0x%08x, expected E_INVALIDARG.\n", i, hr);
11334         hr = IMarshal_MarshalInterface(marshal, stream, &IID_IUri, (void*)uri,
11335                 MSHCTX_LOCAL, NULL, MSHLFLAGS_NOPING);
11336         ok(hr == E_INVALIDARG, "%d) MarshalInterface returned 0x%08x, expected E_INVALIDARG.\n", i, hr);
11337         hr = IMarshal_MarshalInterface(marshal, stream, &IID_IUri, (void*)uri,
11338                 MSHCTX_LOCAL, NULL, MSHLFLAGS_NORMAL);
11339         ok(hr == S_OK, "%d) MarshalInterface failed 0x%08x, expected S_OK.\n", i, hr);
11340         hr = IMarshal_GetUnmarshalClass(marshal, &IID_IUri, (void*)uri,
11341                 MSHCTX_CROSSCTX, NULL, MSHLFLAGS_NORMAL, &curi);
11342         ok(hr == E_INVALIDARG, "%d) GetUnmarshalClass returned 0x%08x, expected E_INVALIDARG.\n", i, hr);
11343         hr = IMarshal_GetUnmarshalClass(marshal, &IID_IUri, (void*)uri,
11344                 MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL, &curi);
11345         ok(hr == S_OK, "%d) GetUnmarshalClass failed 0x%08x, expected S_OK.\n", i, hr);
11346         ok(IsEqualCLSID(&curi, &CLSID_CUri), "%d) GetUnmarshalClass returned incorrect CLSID.\n", i);
11347
11348         hr = IStream_Seek(stream, no_off, STREAM_SEEK_CUR, &size);
11349         ok(hr == S_OK, "%d) Seek failed 0x%08x, expected S_OK.\n", i, hr);
11350         hr = IStream_Seek(stream, no_off, STREAM_SEEK_SET, NULL);
11351         ok(hr == S_OK, "%d) Seek failed 0x%08x, expected S_OK.\n", i, hr);
11352         hr = IStream_Read(stream, (void*)dw_data, 3*sizeof(DWORD), NULL);
11353         ok(hr == S_OK, "%d) Read failed 0x%08x, expected S_OK.\n", i, hr);
11354         ok(dw_data[0]-2 == U(size).LowPart, "%d) Structure size is %d, expected %d\n",
11355                 i, dw_data[0]-2, U(size).LowPart);
11356         ok(dw_data[1] == MSHCTX_LOCAL, "%d) Incorrect value %d, expected MSHCTX_LOCAL.\n",
11357                 i, dw_data[1]);
11358         ok(dw_data[2] == dw_data[0]-8, "%d) Incorrect value %d, expected %d (PersistStream size).\n",
11359                 i, dw_data[2], dw_data[0]-8);
11360         if(!test->str_props[Uri_PROPERTY_PATH].value[0] &&
11361                 (test->dword_props[Uri_PROPERTY_SCHEME-Uri_PROPERTY_DWORD_START].value == URL_SCHEME_HTTP
11362                  || test->dword_props[Uri_PROPERTY_SCHEME-Uri_PROPERTY_DWORD_START].value == URL_SCHEME_FTP
11363                  || test->dword_props[Uri_PROPERTY_SCHEME-Uri_PROPERTY_DWORD_START].value == URL_SCHEME_HTTPS))
11364             U(max_size).LowPart += 3*sizeof(DWORD);
11365         ok(dw_data[2] == U(max_size).LowPart, "%d) Incorrect value %d, expected %d (PersistStream size).\n",
11366                 i, dw_data[2], U(max_size).LowPart);
11367         IMarshal_Release(marshal);
11368         IUri_Release(uri);
11369
11370         hr = IStream_Seek(stream, no_off, STREAM_SEEK_SET, NULL);
11371         ok(hr == S_OK, "%d) Seek failed 0x%08x, expected S_OK.\n", i, hr);
11372         hr = CoCreateInstance(&curi, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
11373                 &IID_IUri, (void**)&uri);
11374         ok(hr == S_OK, "%d) Error creating uninitialized Uri: 0x%08x.\n", i, hr);
11375         hr = IUri_QueryInterface(uri, &IID_IMarshal, (void**)&marshal);
11376         ok(hr == S_OK, "%d) QueryInterface failed 0x%08x, expected S_OK.\n", i, hr);
11377         hr = IMarshal_UnmarshalInterface(marshal, stream, &IID_IUri, (void**)&uri);
11378         ok(hr == S_OK, "%d) UnmarshalInterface failed 0x%08x, expected S_OK.\n", i, hr);
11379         hr = IUri_GetRawUri(uri, &raw_uri);
11380         ok(hr == S_OK, "%d) GetRawUri failed 0x%08x, expected S_OK.\n", i, hr);
11381         ok(!strcmp_aw(test->str_props[Uri_PROPERTY_RAW_URI].value, raw_uri)
11382                 || broken(test->str_props[Uri_PROPERTY_RAW_URI].broken_value
11383                     && !strcmp_aw(test->str_props[Uri_PROPERTY_RAW_URI].broken_value, raw_uri)),
11384                 "%d) Expected %s but got %s.\n", i, test->str_props[Uri_PROPERTY_RAW_URI].value,
11385                 wine_dbgstr_w(raw_uri));
11386         SysFreeString(raw_uri);
11387
11388         IMarshal_Release(marshal);
11389         IStream_Release(stream);
11390         IPersistStream_Release(persist_stream);
11391         IUri_Release(uri);
11392         heap_free(uriW);
11393     }
11394 }
11395
11396 static void test_UninitializedUri(void)
11397 {
11398     IUri *uri;
11399     IUriBuilderFactory *ubf;
11400     IPersistStream *ps;
11401     IUriBuilder *ub;
11402     BSTR bstr;
11403     DWORD dword;
11404     BOOL eq;
11405     ULARGE_INTEGER ui;
11406     HRESULT hr;
11407
11408     hr = CoCreateInstance(&CLSID_CUri, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
11409             &IID_IUri, (void**)&uri);
11410     if(FAILED(hr)) {
11411         win_skip("Skipping uninitialized Uri tests.\n");
11412         return;
11413     }
11414
11415     hr = IUri_QueryInterface(uri, &IID_IUriBuilderFactory, (void**)&ubf);
11416     ok(hr == S_OK, "QueryInterface(IID_IUriBuillderFactory) failed: %x.\n", hr);
11417     hr = IUri_QueryInterface(uri, &IID_IPersistStream, (void**)&ps);
11418     ok(hr == S_OK, "QueryInterface(IID_IPersistStream) failed: %x.\n", hr);
11419
11420     hr = IUri_GetAbsoluteUri(uri, NULL);
11421     ok(hr == E_UNEXPECTED, "GetAbsoluteUri returned %x, expected E_UNEXPECTED.\n", hr);
11422     hr = IUri_GetAbsoluteUri(uri, &bstr);
11423     ok(hr == E_UNEXPECTED, "GetAbsoluteUri returned %x, expected E_UNEXPECTED.\n", hr);
11424     hr = IUri_GetAuthority(uri, &bstr);
11425     ok(hr == E_UNEXPECTED, "GetAuthority returned %x, expected E_UNEXPECTED.\n", hr);
11426     hr = IUri_GetDisplayUri(uri, &bstr);
11427     ok(hr == E_UNEXPECTED, "GetDisplayUri returned %x, expected E_UNEXPECTED.\n", hr);
11428     hr = IUri_GetDomain(uri, &bstr);
11429     ok(hr == E_UNEXPECTED, "GetDomain returned %x, expected E_UNEXPECTED.\n", hr);
11430     hr = IUri_GetExtension(uri, &bstr);
11431     ok(hr == E_UNEXPECTED, "GetExtension returned %x, expected E_UNEXPECTED.\n", hr);
11432     hr = IUri_GetFragment(uri, &bstr);
11433     ok(hr == E_UNEXPECTED, "GetFragment returned %x, expected E_UNEXPECTED.\n", hr);
11434     hr = IUri_GetHost(uri, &bstr);
11435     ok(hr == E_UNEXPECTED, "GetHost returned %x, expected E_UNEXPECTED.\n", hr);
11436     hr = IUri_GetHostType(uri, &dword);
11437     ok(hr == E_UNEXPECTED, "GetHostType returned %x, expected E_UNEXPECTED.\n", hr);
11438     hr = IUri_GetPassword(uri, &bstr);
11439     ok(hr == E_UNEXPECTED, "GetPassword returned %x, expected E_UNEXPECTED.\n", hr);
11440     hr = IUri_GetPassword(uri, &bstr);
11441     ok(hr == E_UNEXPECTED, "GetPassword returned %x, expected E_UNEXPECTED.\n", hr);
11442     hr = IUri_GetPathAndQuery(uri, &bstr);
11443     ok(hr == E_UNEXPECTED, "GetPathAndQuery returned %x, expected E_UNEXPECTED.\n", hr);
11444     hr = IUri_GetPort(uri, &dword);
11445     ok(hr == E_UNEXPECTED, "GetPort returned %x, expected E_UNEXPECTED.\n", hr);
11446     hr = IUri_GetProperties(uri, &dword);
11447     ok(hr == E_UNEXPECTED, "GetProperties returned %x, expected E_UNEXPECTED.\n", hr);
11448     hr = IUri_GetPropertyBSTR(uri, Uri_PROPERTY_RAW_URI, &bstr, 0);
11449     ok(hr == E_UNEXPECTED, "GetPropertyBSTR returned %x, expected E_UNEXPECTED.\n", hr);
11450     hr = IUri_GetPropertyDWORD(uri, Uri_PROPERTY_PORT, &dword, 0);
11451     ok(hr == E_UNEXPECTED, "GetPropertyDWORD returned %x, expected E_UNEXPECTED.\n", hr);
11452     hr = IUri_GetPropertyLength(uri, Uri_PROPERTY_RAW_URI, &dword, 0);
11453     ok(hr == E_UNEXPECTED, "GetPropertyLength returned %x, expected E_UNEXPECTED.\n", hr);
11454     hr = IUri_GetQuery(uri, &bstr);
11455     ok(hr == E_UNEXPECTED, "GetQuery returned %x, expected E_UNEXPECTED.\n", hr);
11456     hr = IUri_GetRawUri(uri, &bstr);
11457     ok(hr == E_UNEXPECTED, "GetRawUri returned %x, expected E_UNEXPECTED.\n", hr);
11458     hr = IUri_GetScheme(uri, &dword);
11459     ok(hr == E_UNEXPECTED, "GetScheme returned %x, expected E_UNEXPECTED.\n", hr);
11460     hr = IUri_GetSchemeName(uri, &bstr);
11461     ok(hr == E_UNEXPECTED, "GetSchemeName returned %x, expected E_UNEXPECTED.\n", hr);
11462     hr = IUri_GetUserInfo(uri, &bstr);
11463     ok(hr == E_UNEXPECTED, "GetUserInfo returned %x, expected E_UNEXPECTED.\n", hr);
11464     hr = IUri_GetUserName(uri, &bstr);
11465     ok(hr == E_UNEXPECTED, "GetUserName returned %x, expected E_UNEXPECTED.\n", hr);
11466     hr = IUri_GetZone(uri, &dword);
11467     ok(hr == E_UNEXPECTED, "GetZone returned %x, expected E_UNEXPECTED.\n", hr);
11468     hr = IUri_IsEqual(uri, uri, &eq);
11469     ok(hr == E_UNEXPECTED, "IsEqual returned %x, expected E_UNEXPECTED.\n", hr);
11470
11471     hr = IUriBuilderFactory_CreateInitializedIUriBuilder(ubf, 0, 0, &ub);
11472     ok(hr == E_UNEXPECTED, "CreateInitializedIUriBuilder returned %x, expected E_UNEXPECTED.\n", hr);
11473     hr = IUriBuilderFactory_CreateIUriBuilder(ubf, 0, 0, &ub);
11474     ok(hr == S_OK, "CreateIUriBuilder returned %x, expected S_OK.\n", hr);
11475     IUriBuilder_Release(ub);
11476
11477     hr = IPersistStream_GetSizeMax(ps, &ui);
11478     ok(hr == S_OK, "GetSizeMax returned %x, expected S_OK.\n", hr);
11479     ok(ui.u.LowPart == 34, "ui.LowPart = %d, expected 34.\n", ui.u.LowPart);
11480     hr = IPersistStream_IsDirty(ps);
11481     ok(hr == S_FALSE, "IsDirty returned %x, expected S_FALSE.\n", hr);
11482
11483     IPersistStream_Release(ps);
11484     IUriBuilderFactory_Release(ubf);
11485     IUri_Release(uri);
11486 }
11487
11488 START_TEST(uri) {
11489     HMODULE hurlmon;
11490
11491     hurlmon = GetModuleHandle("urlmon.dll");
11492     pCoInternetGetSession = (void*) GetProcAddress(hurlmon, "CoInternetGetSession");
11493     pCreateUri = (void*) GetProcAddress(hurlmon, "CreateUri");
11494     pCreateUriWithFragment = (void*) GetProcAddress(hurlmon, "CreateUriWithFragment");
11495     pCreateIUriBuilder = (void*) GetProcAddress(hurlmon, "CreateIUriBuilder");
11496     pCoInternetCombineIUri = (void*) GetProcAddress(hurlmon, "CoInternetCombineIUri");
11497     pCoInternetCombineUrlEx = (void*) GetProcAddress(hurlmon, "CoInternetCombineUrlEx");
11498     pCoInternetParseIUri = (void*) GetProcAddress(hurlmon, "CoInternetParseIUri");
11499     pCreateURLMonikerEx = (void*) GetProcAddress(hurlmon, "CreateURLMonikerEx");
11500     pCreateURLMonikerEx2 = (void*) GetProcAddress(hurlmon, "CreateURLMonikerEx2");
11501
11502     if(!pCreateUri) {
11503         win_skip("CreateUri is not present, skipping tests.\n");
11504         return;
11505     }
11506
11507     trace("test CreateUri invalid flags...\n");
11508     test_CreateUri_InvalidFlags();
11509
11510     trace("test CreateUri invalid args...\n");
11511     test_CreateUri_InvalidArgs();
11512
11513     trace("test CreateUri invalid URIs...\n");
11514     test_CreateUri_InvalidUri();
11515
11516     trace("test IUri_GetPropertyBSTR...\n");
11517     test_IUri_GetPropertyBSTR();
11518
11519     trace("test IUri_GetPropertyDWORD...\n");
11520     test_IUri_GetPropertyDWORD();
11521
11522     trace("test IUri_GetStrProperties...\n");
11523     test_IUri_GetStrProperties();
11524
11525     trace("test IUri_GetDwordProperties...\n");
11526     test_IUri_GetDwordProperties();
11527
11528     trace("test IUri_GetPropertyLength...\n");
11529     test_IUri_GetPropertyLength();
11530
11531     trace("test IUri_GetProperties...\n");
11532     test_IUri_GetProperties();
11533
11534     trace("test IUri_HasProperty...\n");
11535     test_IUri_HasProperty();
11536
11537     trace("test IUri_IsEqual...\n");
11538     test_IUri_IsEqual();
11539
11540     trace("test CreateUriWithFragment invalid args...\n");
11541     test_CreateUriWithFragment_InvalidArgs();
11542
11543     trace("test CreateUriWithFragment invalid flags...\n");
11544     test_CreateUriWithFragment_InvalidFlags();
11545
11546     trace("test CreateUriWithFragment...\n");
11547     test_CreateUriWithFragment();
11548
11549     trace("test CreateIUriBuilder...\n");
11550     test_CreateIUriBuilder();
11551
11552     trace("test IUriBuilder_CreateInvalidArgs...\n");
11553     test_IUriBuilder_CreateInvalidArgs();
11554
11555     trace("test IUriBuilder...\n");
11556     test_IUriBuilder();
11557
11558     trace("test IUriBuilder_GetInvalidArgs...\n");
11559     test_IUriBuilder_GetInvalidArgs();
11560
11561     trace("test IUriBuilder_HasBeenModified...\n");
11562     test_IUriBuilder_HasBeenModified();
11563
11564     trace("test IUriBuilder_IUriProperty...\n");
11565     test_IUriBuilder_IUriProperty();
11566
11567     trace("test IUriBuilder_RemoveProperties...\n");
11568     test_IUriBuilder_RemoveProperties();
11569
11570     trace("test IUriBuilder miscellaneous...\n");
11571     test_IUriBuilder_Misc();
11572
11573     trace("test IUriBuilderFactory...\n");
11574     test_IUriBuilderFactory();
11575
11576     trace("test CoInternetCombineIUri...\n");
11577     test_CoInternetCombineIUri();
11578
11579     trace("test CoInternetCombineUrlEx...\n");
11580     test_CoInternetCombineUrlEx();
11581
11582     trace("test CoInternetParseIUri Invalid Args...\n");
11583     test_CoInternetParseIUri_InvalidArgs();
11584
11585     trace("test CoInternetParseIUri...\n");
11586     test_CoInternetParseIUri();
11587
11588     register_protocols();
11589
11590     trace("test CoInternetCombineIUri pluggable...\n");
11591     test_CoInternetCombineIUri_Pluggable();
11592
11593     trace("test CoInternetCombineUrlEx Pluggable...\n");
11594     test_CoInternetCombineUrlEx_Pluggable();
11595
11596     trace("test CoInternetParseIUri pluggable...\n");
11597     test_CoInternetParseIUri_Pluggable();
11598
11599     trace("test CreateURLMoniker...\n");
11600     test_CreateURLMoniker();
11601
11602     CoInitialize(NULL);
11603
11604     trace("test IPersistStream...\n");
11605     test_IPersistStream();
11606
11607     trace("test uninitialized Uri...\n");
11608     test_UninitializedUri();
11609
11610     CoUninitialize();
11611     unregister_protocols();
11612 }