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 #include <wine/heap.h>
37 
38 DEFINE_GUID(CLSID_CUri, 0xDF2FCE13, 0x25EC, 0x45BB, 0x9D,0x4C, 0xCE,0xCD,0x47,0xC2,0x43,0x0C);
39 
40 #define URI_STR_PROPERTY_COUNT Uri_PROPERTY_STRING_LAST+1
41 #define URI_DWORD_PROPERTY_COUNT (Uri_PROPERTY_DWORD_LAST - Uri_PROPERTY_DWORD_START)+1
42 #define URI_BUILDER_STR_PROPERTY_COUNT 7
43 
44 #define DEFINE_EXPECT(func) \
45     static BOOL expect_ ## func = FALSE, called_ ## func = FALSE
46 
47 #define SET_EXPECT(func) \
48     expect_ ## func = TRUE
49 
50 #define CHECK_EXPECT(func) \
51     do { \
52         ok(expect_ ##func, "unexpected call " #func "\n"); \
53         expect_ ## func = FALSE; \
54         called_ ## func = TRUE; \
55     }while(0)
56 
57 #define CHECK_EXPECT2(func) \
58     do { \
59         ok(expect_ ##func, "unexpected call " #func "\n"); \
60         called_ ## func = TRUE; \
61     }while(0)
62 
63 #define CHECK_CALLED(func) \
64     do { \
65         ok(called_ ## func, "expected " #func "\n"); \
66         expect_ ## func = called_ ## func = FALSE; \
67     }while(0)
68 
69 DEFINE_EXPECT(CombineUrl);
70 DEFINE_EXPECT(ParseUrl);
71 
72 static HRESULT (WINAPI *pCreateUri)(LPCWSTR, DWORD, DWORD_PTR, IUri**);
73 static HRESULT (WINAPI *pCreateUriWithFragment)(LPCWSTR, LPCWSTR, DWORD, DWORD_PTR, IUri**);
74 static HRESULT (WINAPI *pCreateIUriBuilder)(IUri*, DWORD, DWORD_PTR, IUriBuilder**);
75 static HRESULT (WINAPI *pCoInternetCombineIUri)(IUri*,IUri*,DWORD,IUri**,DWORD_PTR);
76 static HRESULT (WINAPI *pCoInternetGetSession)(DWORD,IInternetSession**,DWORD);
77 static HRESULT (WINAPI *pCoInternetCombineUrlEx)(IUri*,LPCWSTR,DWORD,IUri**,DWORD_PTR);
78 static HRESULT (WINAPI *pCoInternetParseIUri)(IUri*,PARSEACTION,DWORD,LPWSTR,DWORD,DWORD*,DWORD_PTR);
79 static HRESULT (WINAPI *pCreateURLMonikerEx)(IMoniker*,LPCWSTR,IMoniker**,DWORD);
80 static HRESULT (WINAPI *pCreateURLMonikerEx2)(IMoniker*,IUri*,IMoniker**,DWORD);
81 
82 static const WCHAR http_urlW[] = { 'h','t','t','p',':','/','/','w','w','w','.','w','i','n','e','h','q',
83         '.','o','r','g','/',0};
84 static const WCHAR http_url_fragW[] = { 'h','t','t','p',':','/','/','w','w','w','.','w','i','n','e','h','q',
85         '.','o','r','g','/','#','F','r','a','g',0};
86 
87 static const WCHAR combine_baseW[] = {'w','i','n','e','t','e','s','t',':','?','t',
88         'e','s','t','i','n','g',0};
89 static const WCHAR combine_relativeW[] = {'?','t','e','s','t',0};
90 static const WCHAR combine_resultW[] = {'z','i','p',':','t','e','s','t',0};
91 
92 static const WCHAR winetestW[] = {'w','i','n','e','t','e','s','t',0};
93 
94 static const WCHAR parse_urlW[] = {'w','i','n','e','t','e','s','t',':','t','e','s','t',0};
95 static const WCHAR parse_resultW[] = {'z','i','p',':','t','e','s','t',0};
96 
97 static PARSEACTION parse_action;
98 static DWORD parse_flags;
99 
100 typedef struct _uri_create_flag_test {
101     DWORD   flags;
102     HRESULT expected;
103 } uri_create_flag_test;
104 
105 static const uri_create_flag_test invalid_flag_tests[] = {
106     /* Set of invalid flag combinations to test for. */
107     {Uri_CREATE_DECODE_EXTRA_INFO | Uri_CREATE_NO_DECODE_EXTRA_INFO, E_INVALIDARG},
108     {Uri_CREATE_CANONICALIZE | Uri_CREATE_NO_CANONICALIZE, E_INVALIDARG},
109     {Uri_CREATE_CRACK_UNKNOWN_SCHEMES | Uri_CREATE_NO_CRACK_UNKNOWN_SCHEMES, E_INVALIDARG},
110     {Uri_CREATE_PRE_PROCESS_HTML_URI | Uri_CREATE_NO_PRE_PROCESS_HTML_URI, E_INVALIDARG},
111     {Uri_CREATE_IE_SETTINGS | Uri_CREATE_NO_IE_SETTINGS, E_INVALIDARG}
112 };
113 
114 typedef struct _uri_str_property {
115     const char* value;
116     HRESULT     expected;
117     BOOL        todo;
118     const char* broken_value;
119     const char* value2;
120     HRESULT     expected2;
121 } uri_str_property;
122 
123 typedef struct _uri_dword_property {
124     DWORD   value;
125     HRESULT expected;
126     BOOL    todo;
127     BOOL    broken_combine_hres;
128 } uri_dword_property;
129 
130 typedef struct _uri_properties {
131     const char*         uri;
132     DWORD               create_flags;
133     HRESULT             create_expected;
134     BOOL                create_todo;
135 
136     uri_str_property    str_props[URI_STR_PROPERTY_COUNT];
137     uri_dword_property  dword_props[URI_DWORD_PROPERTY_COUNT];
138 } uri_properties;
139 
140 static const uri_properties uri_tests[] = {
141     {   "http://www.winehq.org/tests/../tests/../..", 0, S_OK, FALSE,
142         {
143             {"http://www.winehq.org/",S_OK,FALSE},                      /* ABSOLUTE_URI */
144             {"www.winehq.org",S_OK,FALSE},                              /* AUTHORITY */
145             {"http://www.winehq.org/",S_OK,FALSE},                      /* DISPLAY_URI */
146             {"winehq.org",S_OK,FALSE},                                  /* DOMAIN */
147             {"",S_FALSE,FALSE},                                         /* EXTENSION */
148             {"",S_FALSE,FALSE},                                         /* FRAGMENT */
149             {"www.winehq.org",S_OK,FALSE},                              /* HOST */
150             {"",S_FALSE,FALSE},                                         /* PASSWORD */
151             {"/",S_OK,FALSE},                                           /* PATH */
152             {"/",S_OK,FALSE},                                           /* PATH_AND_QUERY */
153             {"",S_FALSE,FALSE},                                         /* QUERY */
154             {"http://www.winehq.org/tests/../tests/../..",S_OK,FALSE},  /* RAW_URI */
155             {"http",S_OK,FALSE},                                        /* SCHEME_NAME */
156             {"",S_FALSE,FALSE},                                         /* USER_INFO */
157             {"",S_FALSE,FALSE}                                          /* USER_NAME */
158         },
159         {
160             {Uri_HOST_DNS,S_OK,FALSE},                                  /* HOST_TYPE */
161             {80,S_OK,FALSE},                                            /* PORT */
162             {URL_SCHEME_HTTP,S_OK,FALSE},                               /* SCHEME */
163             {URLZONE_INVALID,E_NOTIMPL,FALSE}                           /* ZONE */
164         }
165     },
166     {   "http://winehq.org/tests/.././tests", 0, S_OK, FALSE,
167         {
168             {"http://winehq.org/tests",S_OK,FALSE},
169             {"winehq.org",S_OK,FALSE},
170             {"http://winehq.org/tests",S_OK,FALSE},
171             {"winehq.org",S_OK,FALSE},
172             {"",S_FALSE,FALSE},
173             {"",S_FALSE,FALSE},
174             {"winehq.org",S_OK,FALSE},
175             {"",S_FALSE,FALSE},
176             {"/tests",S_OK,FALSE},
177             {"/tests",S_OK,FALSE},
178             {"",S_FALSE,FALSE},
179             {"http://winehq.org/tests/.././tests",S_OK,FALSE},
180             {"http",S_OK,FALSE},
181             {"",S_FALSE,FALSE},
182             {"",S_FALSE,FALSE}
183         },
184         {
185             {Uri_HOST_DNS,S_OK,FALSE},
186             {80,S_OK,FALSE},
187             {URL_SCHEME_HTTP,S_OK,FALSE},
188             {URLZONE_INVALID,E_NOTIMPL,FALSE}
189         }
190     },
191     {   "HtTp://www.winehq.org/tests/..?query=x&return=y", 0, S_OK, FALSE,
192         {
193             {"http://www.winehq.org/?query=x&return=y",S_OK,FALSE},
194             {"www.winehq.org",S_OK,FALSE},
195             {"http://www.winehq.org/?query=x&return=y",S_OK,FALSE},
196             {"winehq.org",S_OK,FALSE},
197             {"",S_FALSE,FALSE},
198             {"",S_FALSE,FALSE},
199             {"www.winehq.org",S_OK,FALSE},
200             {"",S_FALSE,FALSE},
201             {"/",S_OK,FALSE},
202             {"/?query=x&return=y",S_OK,FALSE},
203             {"?query=x&return=y",S_OK,FALSE},
204             {"HtTp://www.winehq.org/tests/..?query=x&return=y",S_OK,FALSE},
205             {"http",S_OK,FALSE},
206             {"",S_FALSE,FALSE},
207             {"",S_FALSE,FALSE}
208         },
209         {
210             {Uri_HOST_DNS,S_OK,FALSE},
211             {80,S_OK,FALSE},
212             {URL_SCHEME_HTTP,S_OK,FALSE},
213             {URLZONE_INVALID,E_NOTIMPL,FALSE},
214         }
215     },
216     {   "HtTpS://www.winehq.org/tests/..?query=x&return=y", 0, S_OK, FALSE,
217         {
218             {"https://www.winehq.org/?query=x&return=y",S_OK,FALSE},
219             {"www.winehq.org",S_OK,FALSE},
220             {"https://www.winehq.org/?query=x&return=y",S_OK,FALSE},
221             {"winehq.org",S_OK,FALSE},
222             {"",S_FALSE,FALSE},
223             {"",S_FALSE,FALSE},
224             {"www.winehq.org",S_OK,FALSE},
225             {"",S_FALSE,FALSE},
226             {"/",S_OK,FALSE},
227             {"/?query=x&return=y",S_OK,FALSE},
228             {"?query=x&return=y",S_OK,FALSE},
229             {"HtTpS://www.winehq.org/tests/..?query=x&return=y",S_OK,FALSE},
230             {"https",S_OK,FALSE},
231             {"",S_FALSE,FALSE},
232             {"",S_FALSE,FALSE}
233         },
234         {
235             {Uri_HOST_DNS,S_OK,FALSE},
236             {443,S_OK,FALSE},
237             {URL_SCHEME_HTTPS,S_OK,FALSE},
238             {URLZONE_INVALID,E_NOTIMPL,FALSE},
239         }
240     },
241     {   "hTTp://us%45r%3Ainfo@examp%4CE.com:80/path/a/b/./c/../%2E%2E/Forbidden'<|> Characters", 0, S_OK, FALSE,
242         {
243             {"http://usEr%3Ainfo@example.com/path/a/Forbidden'%3C%7C%3E%20Characters",S_OK,FALSE},
244             {"usEr%3Ainfo@example.com",S_OK,FALSE},
245             {"http://example.com/path/a/Forbidden'%3C%7C%3E%20Characters",S_OK,FALSE},
246             {"example.com",S_OK,FALSE},
247             {"",S_FALSE,FALSE},
248             {"",S_FALSE,FALSE},
249             {"example.com",S_OK,FALSE},
250             {"",S_FALSE,FALSE},
251             {"/path/a/Forbidden'%3C%7C%3E%20Characters",S_OK,FALSE},
252             {"/path/a/Forbidden'%3C%7C%3E%20Characters",S_OK,FALSE},
253             {"",S_FALSE,FALSE},
254             {"hTTp://us%45r%3Ainfo@examp%4CE.com:80/path/a/b/./c/../%2E%2E/Forbidden'<|> Characters",S_OK,FALSE},
255             {"http",S_OK,FALSE},
256             {"usEr%3Ainfo",S_OK,FALSE},
257             {"usEr%3Ainfo",S_OK,FALSE}
258         },
259         {
260             {Uri_HOST_DNS,S_OK,FALSE},
261             {80,S_OK,FALSE},
262             {URL_SCHEME_HTTP,S_OK,FALSE},
263             {URLZONE_INVALID,E_NOTIMPL,FALSE},
264         }
265     },
266     {   "ftp://winepass:wine@ftp.winehq.org:9999/dir/foo bar.txt", 0, S_OK, FALSE,
267         {
268             {"ftp://winepass:wine@ftp.winehq.org:9999/dir/foo%20bar.txt",S_OK,FALSE},
269             {"winepass:wine@ftp.winehq.org:9999",S_OK,FALSE},
270             {"ftp://ftp.winehq.org:9999/dir/foo%20bar.txt",S_OK,FALSE},
271             {"winehq.org",S_OK,FALSE},
272             {".txt",S_OK,FALSE},
273             {"",S_FALSE,FALSE},
274             {"ftp.winehq.org",S_OK,FALSE},
275             {"wine",S_OK,FALSE},
276             {"/dir/foo%20bar.txt",S_OK,FALSE},
277             {"/dir/foo%20bar.txt",S_OK,FALSE},
278             {"",S_FALSE,FALSE},
279             {"ftp://winepass:wine@ftp.winehq.org:9999/dir/foo bar.txt",S_OK,FALSE},
280             {"ftp",S_OK,FALSE},
281             {"winepass:wine",S_OK,FALSE},
282             {"winepass",S_OK,FALSE}
283         },
284         {
285             {Uri_HOST_DNS,S_OK,FALSE},
286             {9999,S_OK,FALSE},
287             {URL_SCHEME_FTP,S_OK,FALSE},
288             {URLZONE_INVALID,E_NOTIMPL,FALSE}
289         }
290     },
291     {   "file://c:\\tests\\../tests/foo%20bar.mp3", 0, S_OK, FALSE,
292         {
293             {"file:///c:/tests/foo%2520bar.mp3",S_OK,FALSE},
294             {"",S_FALSE,FALSE},
295             {"file:///c:/tests/foo%2520bar.mp3",S_OK,FALSE},
296             {"",S_FALSE,FALSE},
297             {".mp3",S_OK,FALSE},
298             {"",S_FALSE,FALSE},
299             {"",S_FALSE,FALSE},
300             {"",S_FALSE,FALSE},
301             {"/c:/tests/foo%2520bar.mp3",S_OK,FALSE},
302             {"/c:/tests/foo%2520bar.mp3",S_OK,FALSE},
303             {"",S_FALSE,FALSE},
304             {"file://c:\\tests\\../tests/foo%20bar.mp3",S_OK,FALSE},
305             {"file",S_OK,FALSE},
306             {"",S_FALSE,FALSE},
307             {"",S_FALSE,FALSE}
308         },
309         {
310             {Uri_HOST_UNKNOWN,S_OK,FALSE},
311             {0,S_FALSE,FALSE},
312             {URL_SCHEME_FILE,S_OK,FALSE},
313             {URLZONE_INVALID,E_NOTIMPL,FALSE}
314         }
315     },
316     {   "file://c:\\tests\\../tests/foo%20bar.mp3", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
317         {
318             {"file:///c:/tests/../tests/foo%2520bar.mp3",S_OK,FALSE},
319             {"",S_FALSE,FALSE},
320             {"file:///c:/tests/../tests/foo%2520bar.mp3",S_OK,FALSE},
321             {"",S_FALSE,FALSE},
322             {".mp3",S_OK,FALSE},
323             {"",S_FALSE,FALSE},
324             {"",S_FALSE,FALSE},
325             {"",S_FALSE,FALSE},
326             {"/c:/tests/../tests/foo%2520bar.mp3",S_OK,FALSE},
327             {"/c:/tests/../tests/foo%2520bar.mp3",S_OK,FALSE},
328             {"",S_FALSE,FALSE},
329             {"file://c:\\tests\\../tests/foo%20bar.mp3",S_OK,FALSE},
330             {"file",S_OK,FALSE},
331             {"",S_FALSE,FALSE},
332             {"",S_FALSE,FALSE}
333         },
334         {
335             {Uri_HOST_UNKNOWN,S_OK,FALSE},
336             {0,S_FALSE,FALSE},
337             {URL_SCHEME_FILE,S_OK,FALSE},
338             {URLZONE_INVALID,E_NOTIMPL,FALSE}
339         }
340     },
341     {   "FILE://localhost/test dir\\../tests/test%20file.README.txt", 0, S_OK, FALSE,
342         {
343             {"file:///tests/test%20file.README.txt",S_OK,FALSE},
344             {"",S_FALSE,FALSE},
345             {"file:///tests/test%20file.README.txt",S_OK,FALSE},
346             {"",S_FALSE,FALSE},
347             {".txt",S_OK,FALSE},
348             {"",S_FALSE,FALSE},
349             {"",S_FALSE,FALSE},
350             {"",S_FALSE,FALSE},
351             {"/tests/test%20file.README.txt",S_OK,FALSE},
352             {"/tests/test%20file.README.txt",S_OK,FALSE},
353             {"",S_FALSE,FALSE},
354             {"FILE://localhost/test dir\\../tests/test%20file.README.txt",S_OK,FALSE},
355             {"file",S_OK,FALSE},
356             {"",S_FALSE,FALSE},
357             {"",S_FALSE,FALSE}
358         },
359         {
360             {Uri_HOST_UNKNOWN,S_OK,FALSE},
361             {0,S_FALSE,FALSE},
362             {URL_SCHEME_FILE,S_OK,FALSE},
363             {URLZONE_INVALID,E_NOTIMPL,FALSE}
364         }
365     },
366     {   "file:///z:/test dir/README.txt", 0, S_OK, FALSE,
367         {
368             {"file:///z:/test%20dir/README.txt",S_OK},
369             {"",S_FALSE},
370             {"file:///z:/test%20dir/README.txt",S_OK},
371             {"",S_FALSE},
372             {".txt",S_OK},
373             {"",S_FALSE},
374             {"",S_FALSE},
375             {"",S_FALSE},
376             {"/z:/test%20dir/README.txt",S_OK},
377             {"/z:/test%20dir/README.txt",S_OK},
378             {"",S_FALSE},
379             {"file:///z:/test dir/README.txt",S_OK},
380             {"file",S_OK},
381             {"",S_FALSE},
382             {"",S_FALSE}
383         },
384         {
385             {Uri_HOST_UNKNOWN,S_OK,FALSE},
386             {0,S_FALSE,FALSE},
387             {URL_SCHEME_FILE,S_OK,FALSE},
388             {URLZONE_INVALID,E_NOTIMPL,FALSE}
389         }
390     },
391     {   "file:///z:/test dir/README.txt#hash part", 0, S_OK, FALSE,
392         {
393             {"file:///z:/test%20dir/README.txt#hash%20part",S_OK},
394             {"",S_FALSE},
395             {"file:///z:/test%20dir/README.txt#hash%20part",S_OK},
396             {"",S_FALSE},
397             {".txt#hash%20part",S_OK},
398             {"",S_FALSE},
399             {"",S_FALSE},
400             {"",S_FALSE},
401             {"/z:/test%20dir/README.txt#hash%20part",S_OK},
402             {"/z:/test%20dir/README.txt#hash%20part",S_OK},
403             {"",S_FALSE},
404             {"file:///z:/test dir/README.txt#hash part",S_OK},
405             {"file",S_OK},
406             {"",S_FALSE},
407             {"",S_FALSE}
408         },
409         {
410             {Uri_HOST_UNKNOWN,S_OK,FALSE},
411             {0,S_FALSE,FALSE},
412             {URL_SCHEME_FILE,S_OK,FALSE},
413             {URLZONE_INVALID,E_NOTIMPL,FALSE}
414         }
415     },
416     {   "urn:nothing:should:happen here", 0, S_OK, FALSE,
417         {
418             {"urn:nothing:should:happen here",S_OK,FALSE},
419             {"",S_FALSE,FALSE},
420             {"urn:nothing:should:happen here",S_OK,FALSE},
421             {"",S_FALSE,FALSE},
422             {"",S_FALSE,FALSE},
423             {"",S_FALSE,FALSE},
424             {"",S_FALSE,FALSE},
425             {"",S_FALSE,FALSE},
426             {"nothing:should:happen here",S_OK,FALSE},
427             {"nothing:should:happen here",S_OK,FALSE},
428             {"",S_FALSE,FALSE},
429             {"urn:nothing:should:happen here",S_OK,FALSE},
430             {"urn",S_OK,FALSE},
431             {"",S_FALSE,FALSE},
432             {"",S_FALSE,FALSE}
433         },
434         {
435             {Uri_HOST_UNKNOWN,S_OK,FALSE},
436             {0,S_FALSE,FALSE},
437             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
438             {URLZONE_INVALID,E_NOTIMPL,FALSE}
439         }
440     },
441     {   "http://127.0.0.1/tests/../test dir/./test.txt", 0, S_OK, FALSE,
442         {
443             {"http://127.0.0.1/test%20dir/test.txt",S_OK,FALSE},
444             {"127.0.0.1",S_OK,FALSE},
445             {"http://127.0.0.1/test%20dir/test.txt",S_OK,FALSE},
446             {"",S_FALSE,FALSE},
447             {".txt",S_OK,FALSE},
448             {"",S_FALSE,FALSE},
449             {"127.0.0.1",S_OK,FALSE},
450             {"",S_FALSE,FALSE},
451             {"/test%20dir/test.txt",S_OK,FALSE},
452             {"/test%20dir/test.txt",S_OK,FALSE},
453             {"",S_FALSE,FALSE},
454             {"http://127.0.0.1/tests/../test dir/./test.txt",S_OK,FALSE},
455             {"http",S_OK,FALSE},
456             {"",S_FALSE,FALSE},
457             {"",S_FALSE,FALSE}
458         },
459         {
460             {Uri_HOST_IPV4,S_OK,FALSE},
461             {80,S_OK,FALSE},
462             {URL_SCHEME_HTTP,S_OK,FALSE},
463             {URLZONE_INVALID,E_NOTIMPL,FALSE}
464         }
465     },
466     {   "http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]", 0, S_OK, FALSE,
467         {
468             {"http://[fedc:ba98:7654:3210:fedc:ba98:7654:3210]/",S_OK,FALSE},
469             {"[fedc:ba98:7654:3210:fedc:ba98:7654:3210]",S_OK,FALSE},
470             {"http://[fedc:ba98:7654:3210:fedc:ba98:7654:3210]/",S_OK,FALSE},
471             {"",S_FALSE,FALSE},
472             {"",S_FALSE,FALSE},
473             {"",S_FALSE,FALSE},
474             {"fedc:ba98:7654:3210:fedc:ba98:7654:3210",S_OK,FALSE},
475             {"",S_FALSE,FALSE},
476             {"/",S_OK,FALSE},
477             {"/",S_OK,FALSE},
478             {"",S_FALSE,FALSE},
479             {"http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]",S_OK,FALSE},
480             {"http",S_OK,FALSE},
481             {"",S_FALSE,FALSE},
482             {"",S_FALSE,FALSE}
483         },
484         {
485             {Uri_HOST_IPV6,S_OK,FALSE},
486             {80,S_OK,FALSE},
487             {URL_SCHEME_HTTP,S_OK,FALSE},
488             {URLZONE_INVALID,E_NOTIMPL,FALSE}
489         }
490     },
491     {   "ftp://[::13.1.68.3]", 0, S_OK, FALSE,
492         {
493             {"ftp://[::13.1.68.3]/",S_OK,FALSE},
494             {"[::13.1.68.3]",S_OK,FALSE},
495             {"ftp://[::13.1.68.3]/",S_OK,FALSE},
496             {"",S_FALSE,FALSE},
497             {"",S_FALSE,FALSE},
498             {"",S_FALSE,FALSE},
499             {"::13.1.68.3",S_OK,FALSE},
500             {"",S_FALSE,FALSE},
501             {"/",S_OK,FALSE},
502             {"/",S_OK,FALSE},
503             {"",S_FALSE,FALSE},
504             {"ftp://[::13.1.68.3]",S_OK,FALSE},
505             {"ftp",S_OK,FALSE},
506             {"",S_FALSE,FALSE},
507             {"",S_FALSE,FALSE}
508         },
509         {
510             {Uri_HOST_IPV6,S_OK,FALSE},
511             {21,S_OK,FALSE},
512             {URL_SCHEME_FTP,S_OK,FALSE},
513             {URLZONE_INVALID,E_NOTIMPL,FALSE}
514         }
515     },
516     {   "http://[FEDC:BA98:0:0:0:0:0:3210]", 0, S_OK, FALSE,
517         {
518             {"http://[fedc:ba98::3210]/",S_OK,FALSE},
519             {"[fedc:ba98::3210]",S_OK,FALSE},
520             {"http://[fedc:ba98::3210]/",S_OK,FALSE},
521             {"",S_FALSE,FALSE},
522             {"",S_FALSE,FALSE},
523             {"",S_FALSE,FALSE},
524             {"fedc:ba98::3210",S_OK,FALSE},
525             {"",S_FALSE,FALSE},
526             {"/",S_OK,FALSE},
527             {"/",S_OK,FALSE},
528             {"",S_FALSE,FALSE},
529             {"http://[FEDC:BA98:0:0:0:0:0:3210]",S_OK,FALSE},
530             {"http",S_OK,FALSE},
531             {"",S_FALSE,FALSE},
532             {"",S_FALSE,FALSE},
533         },
534         {
535             {Uri_HOST_IPV6,S_OK,FALSE},
536             {80,S_OK,FALSE},
537             {URL_SCHEME_HTTP,S_OK,FALSE},
538             {URLZONE_INVALID,E_NOTIMPL,FALSE}
539         }
540     },
541     {   "1234://www.winehq.org", 0, S_OK, FALSE,
542         {
543             {"1234://www.winehq.org/",S_OK,FALSE},
544             {"www.winehq.org",S_OK,FALSE},
545             {"1234://www.winehq.org/",S_OK,FALSE},
546             {"winehq.org",S_OK,FALSE},
547             {"",S_FALSE,FALSE},
548             {"",S_FALSE,FALSE},
549             {"www.winehq.org",S_OK,FALSE},
550             {"",S_FALSE,FALSE},
551             {"/",S_OK,FALSE},
552             {"/",S_OK,FALSE},
553             {"",S_FALSE,FALSE},
554             {"1234://www.winehq.org",S_OK,FALSE},
555             {"1234",S_OK,FALSE},
556             {"",S_FALSE,FALSE},
557             {"",S_FALSE,FALSE}
558         },
559         {
560             {Uri_HOST_DNS,S_OK,FALSE},
561             {0,S_FALSE,FALSE},
562             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
563             {URLZONE_INVALID,E_NOTIMPL,FALSE}
564         }
565     },
566     /* Test's to make sure the parser/canonicalizer handles implicit file schemes correctly. */
567     {   "C:/test/test.mp3", Uri_CREATE_ALLOW_IMPLICIT_FILE_SCHEME, S_OK, FALSE,
568         {
569             {"file:///C:/test/test.mp3",S_OK,FALSE},
570             {"",S_FALSE,FALSE},
571             {"file:///C:/test/test.mp3",S_OK,FALSE},
572             {"",S_FALSE,FALSE},
573             {".mp3",S_OK,FALSE},
574             {"",S_FALSE,FALSE},
575             {"",S_FALSE,FALSE},
576             {"",S_FALSE,FALSE},
577             {"/C:/test/test.mp3",S_OK,FALSE},
578             {"/C:/test/test.mp3",S_OK,FALSE},
579             {"",S_FALSE,FALSE},
580             {"C:/test/test.mp3",S_OK,FALSE},
581             {"file",S_OK,FALSE},
582             {"",S_FALSE,FALSE},
583             {"",S_FALSE,FALSE}
584         },
585         {
586             {Uri_HOST_UNKNOWN,S_OK,FALSE},
587             {0,S_FALSE,FALSE},
588             {URL_SCHEME_FILE,S_OK,FALSE},
589             {URLZONE_INVALID,E_NOTIMPL,FALSE}
590         }
591     },
592     /* Test's to make sure the parser/canonicalizer handles implicit file schemes correctly. */
593     {   "\\\\Server/test.mp3", Uri_CREATE_ALLOW_IMPLICIT_FILE_SCHEME, S_OK, FALSE,
594         {
595             {"file://server/test.mp3",S_OK,FALSE},
596             {"server",S_OK,FALSE},
597             {"file://server/test.mp3",S_OK,FALSE},
598             {"",S_FALSE,FALSE},
599             {".mp3",S_OK,FALSE},
600             {"",S_FALSE,FALSE},
601             {"server",S_OK,FALSE},
602             {"",S_FALSE,FALSE},
603             {"/test.mp3",S_OK,FALSE},
604             {"/test.mp3",S_OK,FALSE},
605             {"",S_FALSE,FALSE},
606             {"\\\\Server/test.mp3",S_OK,FALSE},
607             {"file",S_OK,FALSE},
608             {"",S_FALSE,FALSE},
609             {"",S_FALSE,FALSE}
610         },
611         {
612             {Uri_HOST_DNS,S_OK,FALSE},
613             {0,S_FALSE,FALSE},
614             {URL_SCHEME_FILE,S_OK,FALSE},
615             {URLZONE_INVALID,E_NOTIMPL,FALSE}
616         }
617     },
618     {   "C:/test/test.mp3#fragment|part", Uri_CREATE_ALLOW_IMPLICIT_FILE_SCHEME|Uri_CREATE_FILE_USE_DOS_PATH|Uri_CREATE_NO_DECODE_EXTRA_INFO, S_OK, FALSE,
619         {
620             {"file://C:\\test\\test.mp3#fragment|part",S_OK,FALSE},
621             {"",S_FALSE,FALSE},
622             {"file://C:\\test\\test.mp3#fragment|part",S_OK,FALSE},
623             {"",S_FALSE,FALSE},
624             {".mp3#fragment|part",S_OK,FALSE},
625             {"",S_FALSE,FALSE},
626             {"",S_FALSE,FALSE},
627             {"",S_FALSE,FALSE},
628             {"C:\\test\\test.mp3#fragment|part",S_OK,FALSE},
629             {"C:\\test\\test.mp3#fragment|part",S_OK,FALSE},
630             {"",S_FALSE,FALSE},
631             {"C:/test/test.mp3#fragment|part",S_OK,FALSE},
632             {"file",S_OK,FALSE},
633             {"",S_FALSE,FALSE},
634             {"",S_FALSE,FALSE}
635         },
636         {
637             {Uri_HOST_UNKNOWN,S_OK,FALSE},
638             {0,S_FALSE,FALSE},
639             {URL_SCHEME_FILE,S_OK,FALSE},
640             {URLZONE_INVALID,E_NOTIMPL,FALSE}
641         }
642     },
643     {   "C:/test/test.mp3?query|part", Uri_CREATE_ALLOW_IMPLICIT_FILE_SCHEME|Uri_CREATE_FILE_USE_DOS_PATH|Uri_CREATE_NO_DECODE_EXTRA_INFO, S_OK, FALSE,
644         {
645             {"file://C:\\test\\test.mp3?query|part",S_OK,FALSE},
646             {"",S_FALSE,FALSE},
647             {"file://C:\\test\\test.mp3?query|part",S_OK,FALSE},
648             {"",S_FALSE,FALSE},
649             {".mp3",S_OK,FALSE},
650             {"",S_FALSE,FALSE},
651             {"",S_FALSE,FALSE},
652             {"",S_FALSE,FALSE},
653             {"C:\\test\\test.mp3",S_OK,FALSE},
654             {"C:\\test\\test.mp3?query|part",S_OK,FALSE},
655             {"?query|part",S_OK,FALSE},
656             {"C:/test/test.mp3?query|part",S_OK,FALSE},
657             {"file",S_OK,FALSE},
658             {"",S_FALSE,FALSE},
659             {"",S_FALSE,FALSE}
660         },
661         {
662             {Uri_HOST_UNKNOWN,S_OK,FALSE},
663             {0,S_FALSE,FALSE},
664             {URL_SCHEME_FILE,S_OK,FALSE},
665             {URLZONE_INVALID,E_NOTIMPL,FALSE}
666         }
667     },
668     {   "C:/test/test.mp3?query|part#hash|part", Uri_CREATE_ALLOW_IMPLICIT_FILE_SCHEME|Uri_CREATE_FILE_USE_DOS_PATH|Uri_CREATE_NO_DECODE_EXTRA_INFO, S_OK, FALSE,
669         {
670             {"file://C:\\test\\test.mp3?query|part#hash|part",S_OK,FALSE},
671             {"",S_FALSE,FALSE},
672             {"file://C:\\test\\test.mp3?query|part#hash|part",S_OK,FALSE},
673             {"",S_FALSE,FALSE},
674             {".mp3",S_OK,FALSE},
675             {"#hash|part",S_OK,FALSE},
676             {"",S_FALSE,FALSE},
677             {"",S_FALSE,FALSE},
678             {"C:\\test\\test.mp3",S_OK,FALSE},
679             {"C:\\test\\test.mp3?query|part",S_OK,FALSE},
680             {"?query|part",S_OK,FALSE},
681             {"C:/test/test.mp3?query|part#hash|part",S_OK,FALSE},
682             {"file",S_OK,FALSE},
683             {"",S_FALSE,FALSE},
684             {"",S_FALSE,FALSE}
685         },
686         {
687             {Uri_HOST_UNKNOWN,S_OK,FALSE},
688             {0,S_FALSE,FALSE},
689             {URL_SCHEME_FILE,S_OK,FALSE},
690             {URLZONE_INVALID,E_NOTIMPL,FALSE}
691         }
692     },
693     {   "www.winehq.org/test", Uri_CREATE_ALLOW_IMPLICIT_WILDCARD_SCHEME, S_OK, FALSE,
694         {
695             {"*:www.winehq.org/test",S_OK,FALSE},
696             {"www.winehq.org",S_OK,FALSE},
697             {"*:www.winehq.org/test",S_OK,FALSE},
698             {"winehq.org",S_OK,FALSE},
699             {"",S_FALSE,FALSE},
700             {"",S_FALSE,FALSE},
701             {"www.winehq.org",S_OK,FALSE},
702             {"",S_FALSE,FALSE},
703             {"/test",S_OK,FALSE},
704             {"/test",S_OK,FALSE},
705             {"",S_FALSE,FALSE},
706             {"www.winehq.org/test",S_OK,FALSE},
707             {"*",S_OK,FALSE},
708             {"",S_FALSE,FALSE},
709             {"",S_FALSE,FALSE}
710         },
711         {
712             {Uri_HOST_DNS,S_OK,FALSE},
713             {0,S_FALSE,FALSE},
714             {URL_SCHEME_WILDCARD,S_OK,FALSE},
715             {URLZONE_INVALID,E_NOTIMPL,FALSE}
716         }
717     },
718     /* Valid since the '*' is the only character in the scheme name. */
719     {   "*:www.winehq.org/test", 0, S_OK, FALSE,
720         {
721             {"*:www.winehq.org/test",S_OK,FALSE},
722             {"www.winehq.org",S_OK,FALSE},
723             {"*:www.winehq.org/test",S_OK,FALSE},
724             {"winehq.org",S_OK,FALSE},
725             {"",S_FALSE,FALSE},
726             {"",S_FALSE,FALSE},
727             {"www.winehq.org",S_OK,FALSE},
728             {"",S_FALSE,FALSE},
729             {"/test",S_OK,FALSE},
730             {"/test",S_OK,FALSE},
731             {"",S_FALSE,FALSE},
732             {"*:www.winehq.org/test",S_OK,FALSE},
733             {"*",S_OK,FALSE},
734             {"",S_FALSE,FALSE},
735             {"",S_FALSE,FALSE}
736         },
737         {
738             {Uri_HOST_DNS,S_OK,FALSE},
739             {0,S_FALSE,FALSE},
740             {URL_SCHEME_WILDCARD,S_OK,FALSE},
741             {URLZONE_INVALID,E_NOTIMPL,FALSE}
742         }
743     },
744     {   "/../some dir/test.ext", Uri_CREATE_ALLOW_RELATIVE, S_OK, FALSE,
745         {
746             {"/../some dir/test.ext",S_OK,FALSE},
747             {"",S_FALSE,FALSE},
748             {"/../some dir/test.ext",S_OK,FALSE},
749             {"",S_FALSE,FALSE},
750             {".ext",S_OK,FALSE},
751             {"",S_FALSE,FALSE},
752             {"",S_FALSE,FALSE},
753             {"",S_FALSE,FALSE},
754             {"/../some dir/test.ext",S_OK,FALSE},
755             {"/../some dir/test.ext",S_OK,FALSE},
756             {"",S_FALSE,FALSE},
757             {"/../some dir/test.ext",S_OK,FALSE},
758             {"",S_FALSE,FALSE},
759             {"",S_FALSE,FALSE},
760             {"",S_FALSE,FALSE}
761         },
762         {
763             {Uri_HOST_UNKNOWN,S_OK,FALSE},
764             {0,S_FALSE,FALSE},
765             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
766             {URLZONE_INVALID,E_NOTIMPL,FALSE}
767         }
768     },
769     {   "//implicit/wildcard/uri scheme", Uri_CREATE_ALLOW_RELATIVE|Uri_CREATE_ALLOW_IMPLICIT_WILDCARD_SCHEME, S_OK, FALSE,
770         {
771             {"*://implicit/wildcard/uri%20scheme",S_OK,FALSE},
772             {"",S_OK,FALSE},
773             {"*://implicit/wildcard/uri%20scheme",S_OK,FALSE},
774             {"",S_FALSE,FALSE},
775             {"",S_FALSE,FALSE},
776             {"",S_FALSE,FALSE},
777             {"",S_OK,FALSE},
778             {"",S_FALSE,FALSE},
779             {"//implicit/wildcard/uri%20scheme",S_OK,FALSE},
780             {"//implicit/wildcard/uri%20scheme",S_OK,FALSE},
781             {"",S_FALSE,FALSE},
782             {"//implicit/wildcard/uri scheme",S_OK,FALSE},
783             {"*",S_OK,FALSE},
784             {"",S_FALSE,FALSE},
785             {"",S_FALSE,FALSE},
786         },
787         {
788             {Uri_HOST_UNKNOWN,S_OK,FALSE},
789             {0,S_FALSE,FALSE},
790             {URL_SCHEME_WILDCARD,S_OK,FALSE},
791             {URLZONE_INVALID,E_NOTIMPL,FALSE}
792         }
793     },
794     /* URI is considered opaque since CREATE_NO_CRACK_UNKNOWN_SCHEMES is set and it's an unknown scheme. */
795     {   "zip://google.com", Uri_CREATE_NO_CRACK_UNKNOWN_SCHEMES, S_OK, FALSE,
796         {
797             {"zip:/.//google.com",S_OK,FALSE},
798             {"",S_FALSE,FALSE},
799             {"zip:/.//google.com",S_OK,FALSE},
800             {"",S_FALSE,FALSE},
801             {".com",S_OK,FALSE},
802             {"",S_FALSE,FALSE},
803             {"",S_FALSE,FALSE},
804             {"",S_FALSE,FALSE},
805             {"/.//google.com",S_OK,FALSE},
806             {"/.//google.com",S_OK,FALSE},
807             {"",S_FALSE,FALSE},
808             {"zip://google.com",S_OK,FALSE},
809             {"zip",S_OK,FALSE},
810             {"",S_FALSE,FALSE},
811             {"",S_FALSE,FALSE}
812         },
813         {
814             {Uri_HOST_UNKNOWN,S_OK,FALSE},
815             {0,S_FALSE,FALSE},
816             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
817             {URLZONE_INVALID,E_NOTIMPL,FALSE}
818         }
819     },
820     /* Windows uses the first occurrence of ':' to delimit the userinfo. */
821     {   "ftp://user:pass:word@winehq.org/", 0, S_OK, FALSE,
822         {
823             {"ftp://user:pass:word@winehq.org/",S_OK,FALSE},
824             {"user:pass:word@winehq.org",S_OK,FALSE},
825             {"ftp://winehq.org/",S_OK,FALSE},
826             {"winehq.org",S_OK,FALSE},
827             {"",S_FALSE,FALSE},
828             {"",S_FALSE,FALSE},
829             {"winehq.org",S_OK,FALSE},
830             {"pass:word",S_OK,FALSE},
831             {"/",S_OK,FALSE},
832             {"/",S_OK,FALSE},
833             {"",S_FALSE,FALSE},
834             {"ftp://user:pass:word@winehq.org/",S_OK,FALSE},
835             {"ftp",S_OK,FALSE},
836             {"user:pass:word",S_OK,FALSE},
837             {"user",S_OK,FALSE}
838         },
839         {
840             {Uri_HOST_DNS,S_OK,FALSE},
841             {21,S_OK,FALSE},
842             {URL_SCHEME_FTP,S_OK,FALSE},
843             {URLZONE_INVALID,E_NOTIMPL,FALSE}
844         }
845     },
846     /* Make sure % encoded unreserved characters are decoded. */
847     {   "ftp://w%49%4Ee:PA%53%53@ftp.google.com/", 0, S_OK, FALSE,
848         {
849             {"ftp://wINe:PASS@ftp.google.com/",S_OK,FALSE},
850             {"wINe:PASS@ftp.google.com",S_OK,FALSE},
851             {"ftp://ftp.google.com/",S_OK,FALSE},
852             {"google.com",S_OK,FALSE},
853             {"",S_FALSE,FALSE},
854             {"",S_FALSE,FALSE},
855             {"ftp.google.com",S_OK,FALSE},
856             {"PASS",S_OK,FALSE},
857             {"/",S_OK,FALSE},
858             {"/",S_OK,FALSE},
859             {"",S_FALSE,FALSE},
860             {"ftp://w%49%4Ee:PA%53%53@ftp.google.com/",S_OK,FALSE},
861             {"ftp",S_OK,FALSE},
862             {"wINe:PASS",S_OK,FALSE},
863             {"wINe",S_OK,FALSE}
864         },
865         {
866             {Uri_HOST_DNS,S_OK,FALSE},
867             {21,S_OK,FALSE},
868             {URL_SCHEME_FTP,S_OK,FALSE},
869             {URLZONE_INVALID,E_NOTIMPL,FALSE}
870         }
871     },
872     /* Make sure % encoded characters which are NOT unreserved are NOT decoded. */
873     {   "ftp://w%5D%5Be:PA%7B%7D@ftp.google.com/", 0, S_OK, FALSE,
874         {
875             {"ftp://w%5D%5Be:PA%7B%7D@ftp.google.com/",S_OK,FALSE},
876             {"w%5D%5Be:PA%7B%7D@ftp.google.com",S_OK,FALSE},
877             {"ftp://ftp.google.com/",S_OK,FALSE},
878             {"google.com",S_OK,FALSE},
879             {"",S_FALSE,FALSE},
880             {"",S_FALSE,FALSE},
881             {"ftp.google.com",S_OK,FALSE},
882             {"PA%7B%7D",S_OK,FALSE},
883             {"/",S_OK,FALSE},
884             {"/",S_OK,FALSE},
885             {"",S_FALSE,FALSE},
886             {"ftp://w%5D%5Be:PA%7B%7D@ftp.google.com/",S_OK,FALSE},
887             {"ftp",S_OK,FALSE},
888             {"w%5D%5Be:PA%7B%7D",S_OK,FALSE},
889             {"w%5D%5Be",S_OK,FALSE}
890         },
891         {
892             {Uri_HOST_DNS,S_OK,FALSE},
893             {21,S_OK,FALSE},
894             {URL_SCHEME_FTP,S_OK,FALSE},
895             {URLZONE_INVALID,E_NOTIMPL,FALSE}
896         }
897     },
898     /* You're allowed to have an empty password portion in the userinfo section. */
899     {   "ftp://empty:@ftp.google.com/", 0, S_OK, FALSE,
900         {
901             {"ftp://empty:@ftp.google.com/",S_OK,FALSE},
902             {"empty:@ftp.google.com",S_OK,FALSE},
903             {"ftp://ftp.google.com/",S_OK,FALSE},
904             {"google.com",S_OK,FALSE},
905             {"",S_FALSE,FALSE},
906             {"",S_FALSE,FALSE},
907             {"ftp.google.com",S_OK,FALSE},
908             {"",S_OK,FALSE},
909             {"/",S_OK,FALSE},
910             {"/",S_OK,FALSE},
911             {"",S_FALSE,FALSE},
912             {"ftp://empty:@ftp.google.com/",S_OK,FALSE},
913             {"ftp",S_OK,FALSE},
914             {"empty:",S_OK,FALSE},
915             {"empty",S_OK,FALSE}
916         },
917         {
918             {Uri_HOST_DNS,S_OK,FALSE},
919             {21,S_OK,FALSE},
920             {URL_SCHEME_FTP,S_OK,FALSE},
921             {URLZONE_INVALID,E_NOTIMPL,FALSE}
922         }
923     },
924     /* Make sure forbidden characters in "userinfo" get encoded. */
925     {   "ftp://\" \"weird@ftp.google.com/", 0, S_OK, FALSE,
926         {
927             {"ftp://%22%20%22weird@ftp.google.com/",S_OK,FALSE},
928             {"%22%20%22weird@ftp.google.com",S_OK,FALSE},
929             {"ftp://ftp.google.com/",S_OK,FALSE},
930             {"google.com",S_OK,FALSE},
931             {"",S_FALSE,FALSE},
932             {"",S_FALSE,FALSE},
933             {"ftp.google.com",S_OK,FALSE},
934             {"",S_FALSE,FALSE},
935             {"/",S_OK,FALSE},
936             {"/",S_OK,FALSE},
937             {"",S_FALSE,FALSE},
938             {"ftp://\" \"weird@ftp.google.com/",S_OK,FALSE},
939             {"ftp",S_OK,FALSE},
940             {"%22%20%22weird",S_OK,FALSE},
941             {"%22%20%22weird",S_OK,FALSE}
942         },
943         {
944             {Uri_HOST_DNS,S_OK,FALSE},
945             {21,S_OK,FALSE},
946             {URL_SCHEME_FTP,S_OK,FALSE},
947             {URLZONE_INVALID,E_NOTIMPL,FALSE}
948         }
949     },
950     /* Make sure the forbidden characters don't get percent encoded. */
951     {   "ftp://\" \"weird@ftp.google.com/", Uri_CREATE_NO_ENCODE_FORBIDDEN_CHARACTERS, S_OK, FALSE,
952         {
953             {"ftp://\" \"weird@ftp.google.com/",S_OK,FALSE},
954             {"\" \"weird@ftp.google.com",S_OK,FALSE},
955             {"ftp://ftp.google.com/",S_OK,FALSE},
956             {"google.com",S_OK,FALSE},
957             {"",S_FALSE,FALSE},
958             {"",S_FALSE,FALSE},
959             {"ftp.google.com",S_OK,FALSE},
960             {"",S_FALSE,FALSE},
961             {"/",S_OK,FALSE},
962             {"/",S_OK,FALSE},
963             {"",S_FALSE,FALSE},
964             {"ftp://\" \"weird@ftp.google.com/",S_OK,FALSE},
965             {"ftp",S_OK,FALSE},
966             {"\" \"weird",S_OK,FALSE},
967             {"\" \"weird",S_OK,FALSE}
968         },
969         {
970             {Uri_HOST_DNS,S_OK,FALSE},
971             {21,S_OK,FALSE},
972             {URL_SCHEME_FTP,S_OK,FALSE},
973             {URLZONE_INVALID,E_NOTIMPL,FALSE}
974         }
975     },
976     /* Make sure already percent encoded characters don't get unencoded. */
977     {   "ftp://\"%20\"weird@ftp.google.com/\"%20\"weird", Uri_CREATE_NO_ENCODE_FORBIDDEN_CHARACTERS, S_OK, FALSE,
978         {
979             {"ftp://\"%20\"weird@ftp.google.com/\"%20\"weird",S_OK,FALSE},
980             {"\"%20\"weird@ftp.google.com",S_OK,FALSE},
981             {"ftp://ftp.google.com/\"%20\"weird",S_OK,FALSE},
982             {"google.com",S_OK,FALSE},
983             {"",S_FALSE,FALSE},
984             {"",S_FALSE,FALSE},
985             {"ftp.google.com",S_OK,FALSE},
986             {"",S_FALSE,FALSE},
987             {"/\"%20\"weird",S_OK,FALSE},
988             {"/\"%20\"weird",S_OK,FALSE},
989             {"",S_FALSE,FALSE},
990             {"ftp://\"%20\"weird@ftp.google.com/\"%20\"weird",S_OK,FALSE},
991             {"ftp",S_OK,FALSE},
992             {"\"%20\"weird",S_OK,FALSE},
993             {"\"%20\"weird",S_OK,FALSE}
994         },
995         {
996             {Uri_HOST_DNS,S_OK,FALSE},
997             {21,S_OK,FALSE},
998             {URL_SCHEME_FTP,S_OK,FALSE},
999             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1000         }
1001     },
1002     /* Allowed to have invalid % encoded because it's an unknown scheme type. */
1003     {   "zip://%xy:word@winehq.org/", 0, S_OK, FALSE,
1004         {
1005             {"zip://%xy:word@winehq.org/",S_OK,FALSE},
1006             {"%xy:word@winehq.org",S_OK,FALSE},
1007             {"zip://%xy:word@winehq.org/",S_OK,FALSE},
1008             {"winehq.org",S_OK,FALSE},
1009             {"",S_FALSE,FALSE},
1010             {"",S_FALSE,FALSE},
1011             {"winehq.org",S_OK,FALSE},
1012             {"word",S_OK,FALSE},
1013             {"/",S_OK,FALSE},
1014             {"/",S_OK,FALSE},
1015             {"",S_FALSE,FALSE},
1016             {"zip://%xy:word@winehq.org/",S_OK,FALSE},
1017             {"zip",S_OK,FALSE},
1018             {"%xy:word",S_OK,FALSE},
1019             {"%xy",S_OK,FALSE}
1020         },
1021         {
1022             {Uri_HOST_DNS,S_OK,FALSE},
1023             {0,S_FALSE,FALSE},
1024             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1025             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1026         }
1027     },
1028     /* Unreserved, percent encoded characters aren't decoded in the userinfo because the scheme
1029      * isn't known.
1030      */
1031     {   "zip://%2E:%52%53ord@winehq.org/", 0, S_OK, FALSE,
1032         {
1033             {"zip://%2E:%52%53ord@winehq.org/",S_OK,FALSE},
1034             {"%2E:%52%53ord@winehq.org",S_OK,FALSE},
1035             {"zip://%2E:%52%53ord@winehq.org/",S_OK,FALSE},
1036             {"winehq.org",S_OK,FALSE},
1037             {"",S_FALSE,FALSE},
1038             {"",S_FALSE,FALSE},
1039             {"winehq.org",S_OK,FALSE},
1040             {"%52%53ord",S_OK,FALSE},
1041             {"/",S_OK,FALSE},
1042             {"/",S_OK,FALSE},
1043             {"",S_FALSE,FALSE},
1044             {"zip://%2E:%52%53ord@winehq.org/",S_OK,FALSE},
1045             {"zip",S_OK,FALSE},
1046             {"%2E:%52%53ord",S_OK,FALSE},
1047             {"%2E",S_OK,FALSE}
1048         },
1049         {
1050             {Uri_HOST_DNS,S_OK,FALSE},
1051             {0,S_FALSE,FALSE},
1052             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1053             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1054         }
1055     },
1056     {   "ftp://[](),'test':word@winehq.org/", 0, S_OK, FALSE,
1057         {
1058             {"ftp://[](),'test':word@winehq.org/",S_OK,FALSE},
1059             {"[](),'test':word@winehq.org",S_OK,FALSE},
1060             {"ftp://winehq.org/",S_OK,FALSE},
1061             {"winehq.org",S_OK,FALSE},
1062             {"",S_FALSE,FALSE},
1063             {"",S_FALSE,FALSE},
1064             {"winehq.org",S_OK,FALSE},
1065             {"word",S_OK,FALSE},
1066             {"/",S_OK,FALSE},
1067             {"/",S_OK,FALSE},
1068             {"",S_FALSE,FALSE},
1069             {"ftp://[](),'test':word@winehq.org/",S_OK,FALSE},
1070             {"ftp",S_OK,FALSE},
1071             {"[](),'test':word",S_OK,FALSE},
1072             {"[](),'test'",S_OK,FALSE}
1073         },
1074         {
1075             {Uri_HOST_DNS,S_OK,FALSE},
1076             {21,S_OK,FALSE},
1077             {URL_SCHEME_FTP,S_OK,FALSE},
1078             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1079         }
1080     },
1081     {   "ftp://test?:word@winehq.org/", 0, S_OK, FALSE,
1082         {
1083             {"ftp://test/?:word@winehq.org/",S_OK,FALSE},
1084             {"test",S_OK,FALSE},
1085             {"ftp://test/?:word@winehq.org/",S_OK,FALSE},
1086             {"",S_FALSE,FALSE},
1087             {"",S_FALSE,FALSE},
1088             {"",S_FALSE,FALSE},
1089             {"test",S_OK,FALSE},
1090             {"",S_FALSE,FALSE},
1091             {"/",S_OK,FALSE},
1092             {"/?:word@winehq.org/",S_OK,FALSE},
1093             {"?:word@winehq.org/",S_OK,FALSE},
1094             {"ftp://test?:word@winehq.org/",S_OK,FALSE},
1095             {"ftp",S_OK,FALSE},
1096             {"",S_FALSE,FALSE},
1097             {"",S_FALSE,FALSE}
1098         },
1099         {
1100             {Uri_HOST_DNS,S_OK,FALSE},
1101             {21,S_OK,FALSE},
1102             {URL_SCHEME_FTP,S_OK,FALSE},
1103             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1104         }
1105     },
1106     {   "ftp://test#:word@winehq.org/", 0, S_OK, FALSE,
1107         {
1108             {"ftp://test/#:word@winehq.org/",S_OK,FALSE},
1109             {"test",S_OK,FALSE},
1110             {"ftp://test/#:word@winehq.org/",S_OK,FALSE},
1111             {"",S_FALSE,FALSE},
1112             {"",S_FALSE,FALSE},
1113             {"#:word@winehq.org/",S_OK,FALSE},
1114             {"test",S_OK,FALSE},
1115             {"",S_FALSE,FALSE},
1116             {"/",S_OK,FALSE},
1117             {"/",S_OK,FALSE},
1118             {"",S_FALSE,FALSE},
1119             {"ftp://test#:word@winehq.org/",S_OK,FALSE},
1120             {"ftp",S_OK,FALSE},
1121             {"",S_FALSE,FALSE},
1122             {"",S_FALSE,FALSE}
1123         },
1124         {
1125             {Uri_HOST_DNS,S_OK,FALSE},
1126             {21,S_OK,FALSE},
1127             {URL_SCHEME_FTP,S_OK,FALSE},
1128             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1129         }
1130     },
1131     /* Allowed to have a backslash in the userinfo since it's an unknown scheme. */
1132     {   "zip://test\\:word@winehq.org/", 0, S_OK, FALSE,
1133         {
1134             {"zip://test\\:word@winehq.org/",S_OK,FALSE},
1135             {"test\\:word@winehq.org",S_OK,FALSE},
1136             {"zip://test\\:word@winehq.org/",S_OK,FALSE},
1137             {"winehq.org",S_OK,FALSE},
1138             {"",S_FALSE,FALSE},
1139             {"",S_FALSE,FALSE},
1140             {"winehq.org",S_OK,FALSE},
1141             {"word",S_OK,FALSE},
1142             {"/",S_OK,FALSE},
1143             {"/",S_OK,FALSE},
1144             {"",S_FALSE,FALSE},
1145             {"zip://test\\:word@winehq.org/",S_OK,FALSE},
1146             {"zip",S_OK,FALSE},
1147             {"test\\:word",S_OK,FALSE},
1148             {"test\\",S_OK,FALSE}
1149         },
1150         {
1151             {Uri_HOST_DNS,S_OK,FALSE},
1152             {0,S_FALSE,FALSE},
1153             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1154             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1155         }
1156     },
1157     /* It normalizes IPv4 addresses correctly. */
1158     {   "http://127.000.000.100/", 0, S_OK, FALSE,
1159         {
1160             {"http://127.0.0.100/",S_OK,FALSE},
1161             {"127.0.0.100",S_OK,FALSE},
1162             {"http://127.0.0.100/",S_OK,FALSE},
1163             {"",S_FALSE,FALSE},
1164             {"",S_FALSE,FALSE},
1165             {"",S_FALSE,FALSE},
1166             {"127.0.0.100",S_OK,FALSE},
1167             {"",S_FALSE,FALSE},
1168             {"/",S_OK,FALSE},
1169             {"/",S_OK,FALSE},
1170             {"",S_FALSE,FALSE},
1171             {"http://127.000.000.100/",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     {   "http://127.0.0.1:8000", 0, S_OK, FALSE,
1184         {
1185             {"http://127.0.0.1:8000/",S_OK},
1186             {"127.0.0.1:8000",S_OK},
1187             {"http://127.0.0.1:8000/",S_OK},
1188             {"",S_FALSE},
1189             {"",S_FALSE},
1190             {"",S_FALSE},
1191             {"127.0.0.1",S_OK},
1192             {"",S_FALSE},
1193             {"/",S_OK},
1194             {"/",S_OK},
1195             {"",S_FALSE},
1196             {"http://127.0.0.1:8000",S_OK},
1197             {"http",S_OK},
1198             {"",S_FALSE},
1199             {"",S_FALSE}
1200         },
1201         {
1202             {Uri_HOST_IPV4,S_OK,FALSE},
1203             {8000,S_OK,FALSE},
1204             {URL_SCHEME_HTTP,S_OK,FALSE},
1205             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1206         }
1207     },
1208     /* Make sure it normalizes partial IPv4 addresses correctly. */
1209     {   "http://127.0/", 0, S_OK, FALSE,
1210         {
1211             {"http://127.0.0.0/",S_OK,FALSE},
1212             {"127.0.0.0",S_OK,FALSE},
1213             {"http://127.0.0.0/",S_OK,FALSE},
1214             {"",S_FALSE,FALSE},
1215             {"",S_FALSE,FALSE},
1216             {"",S_FALSE,FALSE},
1217             {"127.0.0.0",S_OK,FALSE},
1218             {"",S_FALSE,FALSE},
1219             {"/",S_OK,FALSE},
1220             {"/",S_OK,FALSE},
1221             {"",S_FALSE,FALSE},
1222             {"http://127.0/",S_OK,FALSE},
1223             {"http",S_OK,FALSE},
1224             {"",S_FALSE,FALSE},
1225             {"",S_FALSE,FALSE}
1226         },
1227         {
1228             {Uri_HOST_IPV4,S_OK,FALSE},
1229             {80,S_OK,FALSE},
1230             {URL_SCHEME_HTTP,S_OK,FALSE},
1231             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1232         }
1233     },
1234     /* Make sure it converts implicit IPv4's correctly. */
1235     {   "http://123456/", 0, S_OK, FALSE,
1236         {
1237             {"http://0.1.226.64/",S_OK,FALSE},
1238             {"0.1.226.64",S_OK,FALSE},
1239             {"http://0.1.226.64/",S_OK,FALSE},
1240             {"",S_FALSE,FALSE},
1241             {"",S_FALSE,FALSE},
1242             {"",S_FALSE,FALSE},
1243             {"0.1.226.64",S_OK,FALSE},
1244             {"",S_FALSE,FALSE},
1245             {"/",S_OK,FALSE},
1246             {"/",S_OK,FALSE},
1247             {"",S_FALSE,FALSE},
1248             {"http://123456/",S_OK,FALSE},
1249             {"http",S_OK,FALSE},
1250             {"",S_FALSE,FALSE},
1251             {"",S_FALSE,FALSE}
1252         },
1253         {
1254             {Uri_HOST_IPV4,S_OK,FALSE},
1255             {80,S_OK,FALSE},
1256             {URL_SCHEME_HTTP,S_OK,FALSE},
1257             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1258         }
1259     },
1260     /* UINT_MAX */
1261     {   "http://4294967295/", 0, S_OK, FALSE,
1262         {
1263             {"http://255.255.255.255/",S_OK,FALSE},
1264             {"255.255.255.255",S_OK,FALSE},
1265             {"http://255.255.255.255/",S_OK,FALSE},
1266             {"",S_FALSE,FALSE},
1267             {"",S_FALSE,FALSE},
1268             {"",S_FALSE,FALSE},
1269             {"255.255.255.255",S_OK,FALSE},
1270             {"",S_FALSE,FALSE},
1271             {"/",S_OK,FALSE},
1272             {"/",S_OK,FALSE},
1273             {"",S_FALSE,FALSE},
1274             {"http://4294967295/",S_OK,FALSE},
1275             {"http",S_OK,FALSE},
1276             {"",S_FALSE,FALSE},
1277             {"",S_FALSE,FALSE}
1278         },
1279         {
1280             {Uri_HOST_IPV4,S_OK,FALSE},
1281             {80,S_OK,FALSE},
1282             {URL_SCHEME_HTTP,S_OK,FALSE},
1283             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1284         }
1285     },
1286     /* UINT_MAX+1 */
1287     {   "http://4294967296/", 0, S_OK, FALSE,
1288         {
1289             {"http://4294967296/",S_OK,FALSE},
1290             {"4294967296",S_OK,FALSE},
1291             {"http://4294967296/",S_OK,FALSE},
1292             {"",S_FALSE,FALSE},
1293             {"",S_FALSE,FALSE},
1294             {"",S_FALSE,FALSE},
1295             {"4294967296",S_OK,FALSE},
1296             {"",S_FALSE,FALSE},
1297             {"/",S_OK,FALSE},
1298             {"/",S_OK,FALSE},
1299             {"",S_FALSE,FALSE},
1300             {"http://4294967296/",S_OK,FALSE},
1301             {"http",S_OK,FALSE},
1302             {"",S_FALSE,FALSE},
1303             {"",S_FALSE,FALSE}
1304         },
1305         {
1306             {Uri_HOST_DNS,S_OK,FALSE},
1307             {80,S_OK,FALSE},
1308             {URL_SCHEME_HTTP,S_OK,FALSE},
1309             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1310         }
1311     },
1312     /* Window's doesn't normalize IP address for unknown schemes. */
1313     {   "1234://4294967295/", 0, S_OK, FALSE,
1314         {
1315             {"1234://4294967295/",S_OK,FALSE},
1316             {"4294967295",S_OK,FALSE},
1317             {"1234://4294967295/",S_OK,FALSE},
1318             {"",S_FALSE,FALSE},
1319             {"",S_FALSE,FALSE},
1320             {"",S_FALSE,FALSE},
1321             {"4294967295",S_OK,FALSE},
1322             {"",S_FALSE,FALSE},
1323             {"/",S_OK,FALSE},
1324             {"/",S_OK,FALSE},
1325             {"",S_FALSE,FALSE},
1326             {"1234://4294967295/",S_OK,FALSE},
1327             {"1234",S_OK,FALSE},
1328             {"",S_FALSE,FALSE},
1329             {"",S_FALSE,FALSE}
1330         },
1331         {
1332             {Uri_HOST_IPV4,S_OK,FALSE},
1333             {0,S_FALSE,FALSE},
1334             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1335             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1336         }
1337     },
1338     /* Window's doesn't normalize IP address for unknown schemes. */
1339     {   "1234://127.001/", 0, S_OK, FALSE,
1340         {
1341             {"1234://127.001/",S_OK,FALSE},
1342             {"127.001",S_OK,FALSE},
1343             {"1234://127.001/",S_OK,FALSE},
1344             {"",S_FALSE,FALSE},
1345             {"",S_FALSE,FALSE},
1346             {"",S_FALSE,FALSE},
1347             {"127.001",S_OK,FALSE},
1348             {"",S_FALSE,FALSE},
1349             {"/",S_OK,FALSE},
1350             {"/",S_OK,FALSE},
1351             {"",S_FALSE,FALSE},
1352             {"1234://127.001/",S_OK,FALSE},
1353             {"1234",S_OK,FALSE},
1354             {"",S_FALSE,FALSE},
1355             {"",S_FALSE,FALSE}
1356         },
1357         {
1358             {Uri_HOST_IPV4,S_OK,FALSE},
1359             {0,S_FALSE,FALSE},
1360             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1361             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1362         }
1363     },
1364     {   "http://[FEDC:BA98::3210]", 0, S_OK, FALSE,
1365         {
1366             {"http://[fedc:ba98::3210]/",S_OK,FALSE},
1367             {"[fedc:ba98::3210]",S_OK,FALSE},
1368             {"http://[fedc:ba98::3210]/",S_OK,FALSE},
1369             {"",S_FALSE,FALSE},
1370             {"",S_FALSE,FALSE},
1371             {"",S_FALSE,FALSE},
1372             {"fedc:ba98::3210",S_OK,FALSE},
1373             {"",S_FALSE,FALSE},
1374             {"/",S_OK,FALSE},
1375             {"/",S_OK,FALSE},
1376             {"",S_FALSE,FALSE},
1377             {"http://[FEDC:BA98::3210]",S_OK,FALSE},
1378             {"http",S_OK,FALSE},
1379             {"",S_FALSE,FALSE},
1380             {"",S_FALSE,FALSE},
1381         },
1382         {
1383             {Uri_HOST_IPV6,S_OK,FALSE},
1384             {80,S_OK,FALSE},
1385             {URL_SCHEME_HTTP,S_OK,FALSE},
1386             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1387         }
1388     },
1389     {   "http://[::]", 0, S_OK, FALSE,
1390         {
1391             {"http://[::]/",S_OK,FALSE},
1392             {"[::]",S_OK,FALSE},
1393             {"http://[::]/",S_OK,FALSE},
1394             {"",S_FALSE,FALSE},
1395             {"",S_FALSE,FALSE},
1396             {"",S_FALSE,FALSE},
1397             {"::",S_OK,FALSE},
1398             {"",S_FALSE,FALSE},
1399             {"/",S_OK,FALSE},
1400             {"/",S_OK,FALSE},
1401             {"",S_FALSE,FALSE},
1402             {"http://[::]",S_OK,FALSE},
1403             {"http",S_OK,FALSE},
1404             {"",S_FALSE,FALSE},
1405             {"",S_FALSE,FALSE},
1406         },
1407         {
1408             {Uri_HOST_IPV6,S_OK,FALSE},
1409             {80,S_OK,FALSE},
1410             {URL_SCHEME_HTTP,S_OK,FALSE},
1411             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1412         }
1413     },
1414     {   "http://[FEDC:BA98::]", 0, S_OK, FALSE,
1415         {
1416             {"http://[fedc:ba98::]/",S_OK,FALSE},
1417             {"[fedc:ba98::]",S_OK,FALSE},
1418             {"http://[fedc:ba98::]/",S_OK,FALSE},
1419             {"",S_FALSE,FALSE},
1420             {"",S_FALSE,FALSE},
1421             {"",S_FALSE,FALSE},
1422             {"fedc:ba98::",S_OK,FALSE},
1423             {"",S_FALSE,FALSE},
1424             {"/",S_OK,FALSE},
1425             {"/",S_OK,FALSE},
1426             {"",S_FALSE,FALSE},
1427             {"http://[FEDC:BA98::]",S_OK,FALSE},
1428             {"http",S_OK,FALSE},
1429             {"",S_FALSE,FALSE},
1430             {"",S_FALSE,FALSE},
1431         },
1432         {
1433             {Uri_HOST_IPV6,S_OK,FALSE},
1434             {80,S_OK,FALSE},
1435             {URL_SCHEME_HTTP,S_OK,FALSE},
1436             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1437         }
1438     },
1439     /* Valid even with 2 byte elision because it doesn't appear the beginning or end. */
1440     {   "http://[1::3:4:5:6:7:8]", 0, S_OK, FALSE,
1441         {
1442             {"http://[1:0:3:4:5:6:7:8]/",S_OK,FALSE},
1443             {"[1:0:3:4:5:6:7:8]",S_OK,FALSE},
1444             {"http://[1:0:3:4:5:6:7:8]/",S_OK,FALSE},
1445             {"",S_FALSE,FALSE},
1446             {"",S_FALSE,FALSE},
1447             {"",S_FALSE,FALSE},
1448             {"1:0:3:4:5:6:7:8",S_OK,FALSE},
1449             {"",S_FALSE,FALSE},
1450             {"/",S_OK,FALSE},
1451             {"/",S_OK,FALSE},
1452             {"",S_FALSE,FALSE},
1453             {"http://[1::3:4:5:6:7:8]",S_OK,FALSE},
1454             {"http",S_OK,FALSE},
1455             {"",S_FALSE,FALSE},
1456             {"",S_FALSE,FALSE},
1457         },
1458         {
1459             {Uri_HOST_IPV6,S_OK,FALSE},
1460             {80,S_OK,FALSE},
1461             {URL_SCHEME_HTTP,S_OK,FALSE},
1462             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1463         }
1464     },
1465     {   "http://[v2.34]/", 0, S_OK, FALSE,
1466         {
1467             {"http://[v2.34]/",S_OK,FALSE},
1468             {"[v2.34]",S_OK,FALSE},
1469             {"http://[v2.34]/",S_OK,FALSE},
1470             {"",S_FALSE,FALSE},
1471             {"",S_FALSE,FALSE},
1472             {"",S_FALSE,FALSE},
1473             {"[v2.34]",S_OK,FALSE},
1474             {"",S_FALSE,FALSE},
1475             {"/",S_OK,FALSE},
1476             {"/",S_OK,FALSE},
1477             {"",S_FALSE,FALSE},
1478             {"http://[v2.34]/",S_OK,FALSE},
1479             {"http",S_OK,FALSE},
1480             {"",S_FALSE,FALSE},
1481             {"",S_FALSE,FALSE}
1482         },
1483         {
1484             {Uri_HOST_UNKNOWN,S_OK,FALSE},
1485             {80,S_OK,FALSE},
1486             {URL_SCHEME_HTTP,S_OK,FALSE},
1487             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1488         }
1489     },
1490     /* Windows ignores ':' if they appear after a '[' on a non-IPLiteral host. */
1491     {   "http://[xyz:12345.com/test", 0, S_OK, FALSE,
1492         {
1493             {"http://[xyz:12345.com/test",S_OK,FALSE},
1494             {"[xyz:12345.com",S_OK,FALSE},
1495             {"http://[xyz:12345.com/test",S_OK,FALSE},
1496             {"[xyz:12345.com",S_OK,FALSE},
1497             {"",S_FALSE,FALSE},
1498             {"",S_FALSE,FALSE},
1499             {"[xyz:12345.com",S_OK,FALSE},
1500             {"",S_FALSE,FALSE},
1501             {"/test",S_OK,FALSE},
1502             {"/test",S_OK,FALSE},
1503             {"",S_FALSE,FALSE},
1504             {"http://[xyz:12345.com/test",S_OK,FALSE},
1505             {"http",S_OK,FALSE},
1506             {"",S_FALSE,FALSE},
1507             {"",S_FALSE,FALSE}
1508         },
1509         {
1510             {Uri_HOST_DNS,S_OK,FALSE},
1511             {80,S_OK,FALSE},
1512             {URL_SCHEME_HTTP,S_OK,FALSE},
1513             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1514         }
1515     },
1516     /* Valid URI since the '[' and ']' don't appear at the beginning and end
1517      * of the host name (respectively).
1518      */
1519     {   "ftp://www.[works].com/", 0, S_OK, FALSE,
1520         {
1521             {"ftp://www.[works].com/",S_OK,FALSE},
1522             {"www.[works].com",S_OK,FALSE},
1523             {"ftp://www.[works].com/",S_OK,FALSE},
1524             {"[works].com",S_OK,FALSE},
1525             {"",S_FALSE,FALSE},
1526             {"",S_FALSE,FALSE},
1527             {"www.[works].com",S_OK,FALSE},
1528             {"",S_FALSE,FALSE},
1529             {"/",S_OK,FALSE},
1530             {"/",S_OK,FALSE},
1531             {"",S_FALSE,FALSE},
1532             {"ftp://www.[works].com/",S_OK,FALSE},
1533             {"ftp",S_OK,FALSE},
1534             {"",S_FALSE,FALSE},
1535             {"",S_FALSE,FALSE}
1536         },
1537         {
1538             {Uri_HOST_DNS,S_OK,FALSE},
1539             {21,S_OK,FALSE},
1540             {URL_SCHEME_FTP,S_OK,FALSE},
1541             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1542         }
1543     },
1544     /* Considers ':' a delimiter since it appears after the ']'. */
1545     {   "http://www.google.com]:12345/", 0, S_OK, FALSE,
1546         {
1547             {"http://www.google.com]:12345/",S_OK,FALSE},
1548             {"www.google.com]:12345",S_OK,FALSE},
1549             {"http://www.google.com]:12345/",S_OK,FALSE},
1550             {"google.com]",S_OK,FALSE},
1551             {"",S_FALSE,FALSE},
1552             {"",S_FALSE,FALSE},
1553             {"www.google.com]",S_OK,FALSE},
1554             {"",S_FALSE,FALSE},
1555             {"/",S_OK,FALSE},
1556             {"/",S_OK,FALSE},
1557             {"",S_FALSE,FALSE},
1558             {"http://www.google.com]:12345/",S_OK,FALSE},
1559             {"http",S_OK,FALSE},
1560             {"",S_FALSE,FALSE},
1561             {"",S_FALSE,FALSE}
1562         },
1563         {
1564             {Uri_HOST_DNS,S_OK,FALSE},
1565             {12345,S_OK,FALSE},
1566             {URL_SCHEME_HTTP,S_OK,FALSE},
1567             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1568         }
1569     },
1570     /* Unknown scheme types can have invalid % encoded data in the hostname. */
1571     {   "zip://w%XXw%GEw.google.com/", 0, S_OK, FALSE,
1572         {
1573             {"zip://w%XXw%GEw.google.com/",S_OK,FALSE},
1574             {"w%XXw%GEw.google.com",S_OK,FALSE},
1575             {"zip://w%XXw%GEw.google.com/",S_OK,FALSE},
1576             {"google.com",S_OK,FALSE},
1577             {"",S_FALSE,FALSE},
1578             {"",S_FALSE,FALSE},
1579             {"w%XXw%GEw.google.com",S_OK,FALSE},
1580             {"",S_FALSE,FALSE},
1581             {"/",S_OK,FALSE},
1582             {"/",S_OK,FALSE},
1583             {"",S_FALSE,FALSE},
1584             {"zip://w%XXw%GEw.google.com/",S_OK,FALSE},
1585             {"zip",S_OK,FALSE},
1586             {"",S_FALSE,FALSE},
1587             {"",S_FALSE,FALSE}
1588         },
1589         {
1590             {Uri_HOST_DNS,S_OK,FALSE},
1591             {0,S_FALSE,FALSE},
1592             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1593             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1594         }
1595     },
1596     /* Unknown scheme types hostname doesn't get lower cased. */
1597     {   "zip://GOOGLE.com/", 0, S_OK, FALSE,
1598         {
1599             {"zip://GOOGLE.com/",S_OK,FALSE},
1600             {"GOOGLE.com",S_OK,FALSE},
1601             {"zip://GOOGLE.com/",S_OK,FALSE},
1602             {"GOOGLE.com",S_OK,FALSE},
1603             {"",S_FALSE,FALSE},
1604             {"",S_FALSE,FALSE},
1605             {"GOOGLE.com",S_OK,FALSE},
1606             {"",S_FALSE,FALSE},
1607             {"/",S_OK,FALSE},
1608             {"/",S_OK,FALSE},
1609             {"",S_FALSE,FALSE},
1610             {"zip://GOOGLE.com/",S_OK,FALSE},
1611             {"zip",S_OK,FALSE},
1612             {"",S_FALSE,FALSE},
1613             {"",S_FALSE,FALSE}
1614         },
1615         {
1616             {Uri_HOST_DNS,S_OK,FALSE},
1617             {0,S_FALSE,FALSE},
1618             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1619             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1620         }
1621     },
1622     /* Hostname gets lower-cased for known scheme types. */
1623     {   "http://WWW.GOOGLE.com/", 0, S_OK, FALSE,
1624         {
1625             {"http://www.google.com/",S_OK,FALSE},
1626             {"www.google.com",S_OK,FALSE},
1627             {"http://www.google.com/",S_OK,FALSE},
1628             {"google.com",S_OK,FALSE},
1629             {"",S_FALSE,FALSE},
1630             {"",S_FALSE,FALSE},
1631             {"www.google.com",S_OK,FALSE},
1632             {"",S_FALSE,FALSE},
1633             {"/",S_OK,FALSE},
1634             {"/",S_OK,FALSE},
1635             {"",S_FALSE,FALSE},
1636             {"http://WWW.GOOGLE.com/",S_OK,FALSE},
1637             {"http",S_OK,FALSE},
1638             {"",S_FALSE,FALSE},
1639             {"",S_FALSE,FALSE}
1640         },
1641         {
1642             {Uri_HOST_DNS,S_OK,FALSE},
1643             {80,S_OK,FALSE},
1644             {URL_SCHEME_HTTP,S_OK,FALSE},
1645             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1646         }
1647     },
1648     /* Characters that get % encoded in the hostname also have their percent
1649      * encoded forms lower cased.
1650      */
1651     {   "http://www.%7Cgoogle|.com/", 0, S_OK, FALSE,
1652         {
1653             {"http://www.%7cgoogle%7c.com/",S_OK,FALSE},
1654             {"www.%7cgoogle%7c.com",S_OK,FALSE},
1655             {"http://www.%7cgoogle%7c.com/",S_OK,FALSE},
1656             {"%7cgoogle%7c.com",S_OK,FALSE},
1657             {"",S_FALSE,FALSE},
1658             {"",S_FALSE,FALSE},
1659             {"www.%7cgoogle%7c.com",S_OK,FALSE},
1660             {"",S_FALSE,FALSE},
1661             {"/",S_OK,FALSE},
1662             {"/",S_OK,FALSE},
1663             {"",S_FALSE,FALSE},
1664             {"http://www.%7Cgoogle|.com/",S_OK,FALSE},
1665             {"http",S_OK,FALSE},
1666             {"",S_FALSE,FALSE},
1667             {"",S_FALSE,FALSE}
1668         },
1669         {
1670             {Uri_HOST_DNS,S_OK,FALSE},
1671             {80,S_OK,FALSE},
1672             {URL_SCHEME_HTTP,S_OK,FALSE},
1673             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1674         }
1675     },
1676     /* IPv4 addresses attached to IPv6 can be included in elisions. */
1677     {   "http://[1:2:3:4:5:6:0.0.0.0]", 0, S_OK, FALSE,
1678         {
1679             {"http://[1:2:3:4:5:6::]/",S_OK,FALSE},
1680             {"[1:2:3:4:5:6::]",S_OK,FALSE},
1681             {"http://[1:2:3:4:5:6::]/",S_OK,FALSE},
1682             {"",S_FALSE,FALSE},
1683             {"",S_FALSE,FALSE},
1684             {"",S_FALSE,FALSE},
1685             {"1:2:3:4:5:6::",S_OK,FALSE},
1686             {"",S_FALSE,FALSE},
1687             {"/",S_OK,FALSE},
1688             {"/",S_OK,FALSE},
1689             {"",S_FALSE,FALSE},
1690             {"http://[1:2:3:4:5:6:0.0.0.0]",S_OK,FALSE},
1691             {"http",S_OK,FALSE},
1692             {"",S_FALSE,FALSE},
1693             {"",S_FALSE,FALSE},
1694         },
1695         {
1696             {Uri_HOST_IPV6,S_OK,FALSE},
1697             {80,S_OK,FALSE},
1698             {URL_SCHEME_HTTP,S_OK,FALSE},
1699             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1700         }
1701     },
1702     /* IPv4 addresses get normalized. */
1703     {   "http://[::001.002.003.000]", 0, S_OK, FALSE,
1704         {
1705             {"http://[::1.2.3.0]/",S_OK,FALSE},
1706             {"[::1.2.3.0]",S_OK,FALSE},
1707             {"http://[::1.2.3.0]/",S_OK,FALSE},
1708             {"",S_FALSE,FALSE},
1709             {"",S_FALSE,FALSE},
1710             {"",S_FALSE,FALSE},
1711             {"::1.2.3.0",S_OK,FALSE},
1712             {"",S_FALSE,FALSE},
1713             {"/",S_OK,FALSE},
1714             {"/",S_OK,FALSE},
1715             {"",S_FALSE,FALSE},
1716             {"http://[::001.002.003.000]",S_OK,FALSE},
1717             {"http",S_OK,FALSE},
1718             {"",S_FALSE,FALSE},
1719             {"",S_FALSE,FALSE},
1720         },
1721         {
1722             {Uri_HOST_IPV6,S_OK,FALSE},
1723             {80,S_OK,FALSE},
1724             {URL_SCHEME_HTTP,S_OK,FALSE},
1725             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1726         }
1727     },
1728     /* Windows doesn't do anything to IPv6's in unknown schemes. */
1729     {   "zip://[0001:0:000:0004:0005:0006:001.002.003.000]", 0, S_OK, FALSE,
1730         {
1731             {"zip://[0001:0:000:0004:0005:0006:001.002.003.000]/",S_OK,FALSE},
1732             {"[0001:0:000:0004:0005:0006:001.002.003.000]",S_OK,FALSE},
1733             {"zip://[0001:0:000:0004:0005:0006:001.002.003.000]/",S_OK,FALSE},
1734             {"",S_FALSE,FALSE},
1735             {"",S_FALSE,FALSE},
1736             {"",S_FALSE,FALSE},
1737             {"0001:0:000:0004:0005:0006:001.002.003.000",S_OK,FALSE},
1738             {"",S_FALSE,FALSE},
1739             {"/",S_OK,FALSE},
1740             {"/",S_OK,FALSE},
1741             {"",S_FALSE,FALSE},
1742             {"zip://[0001:0:000:0004:0005:0006:001.002.003.000]",S_OK,FALSE},
1743             {"zip",S_OK,FALSE},
1744             {"",S_FALSE,FALSE},
1745             {"",S_FALSE,FALSE},
1746         },
1747         {
1748             {Uri_HOST_IPV6,S_OK,FALSE},
1749             {0,S_FALSE,FALSE},
1750             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1751             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1752         }
1753     },
1754     /* IPv4 address is converted into 2 h16 components. */
1755     {   "http://[ffff::192.222.111.32]", 0, S_OK, FALSE,
1756         {
1757             {"http://[ffff::c0de:6f20]/",S_OK,FALSE},
1758             {"[ffff::c0de:6f20]",S_OK,FALSE},
1759             {"http://[ffff::c0de:6f20]/",S_OK,FALSE},
1760             {"",S_FALSE,FALSE},
1761             {"",S_FALSE,FALSE},
1762             {"",S_FALSE,FALSE},
1763             {"ffff::c0de:6f20",S_OK,FALSE},
1764             {"",S_FALSE,FALSE},
1765             {"/",S_OK,FALSE},
1766             {"/",S_OK,FALSE},
1767             {"",S_FALSE,FALSE},
1768             {"http://[ffff::192.222.111.32]",S_OK,FALSE},
1769             {"http",S_OK,FALSE},
1770             {"",S_FALSE,FALSE},
1771             {"",S_FALSE,FALSE},
1772         },
1773         {
1774             {Uri_HOST_IPV6,S_OK,FALSE},
1775             {80,S_OK,FALSE},
1776             {URL_SCHEME_HTTP,S_OK,FALSE},
1777             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1778         }
1779     },
1780     /* Max value for a port. */
1781     {   "http://google.com:65535", 0, S_OK, FALSE,
1782         {
1783             {"http://google.com:65535/",S_OK,FALSE},
1784             {"google.com:65535",S_OK,FALSE},
1785             {"http://google.com:65535/",S_OK,FALSE},
1786             {"google.com",S_OK,FALSE},
1787             {"",S_FALSE,FALSE},
1788             {"",S_FALSE,FALSE},
1789             {"google.com",S_OK,FALSE},
1790             {"",S_FALSE,FALSE},
1791             {"/",S_OK,FALSE},
1792             {"/",S_OK,FALSE},
1793             {"",S_FALSE,FALSE},
1794             {"http://google.com:65535",S_OK,FALSE},
1795             {"http",S_OK,FALSE},
1796             {"",S_FALSE,FALSE},
1797             {"",S_FALSE,FALSE}
1798         },
1799         {
1800             {Uri_HOST_DNS,S_OK,FALSE},
1801             {65535,S_OK,FALSE},
1802             {URL_SCHEME_HTTP,S_OK,FALSE},
1803             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1804         }
1805     },
1806     {   "zip://google.com:65536", 0, S_OK, FALSE,
1807         {
1808             {"zip://google.com:65536/",S_OK,FALSE},
1809             {"google.com:65536",S_OK,FALSE},
1810             {"zip://google.com:65536/",S_OK,FALSE},
1811             {"google.com:65536",S_OK,FALSE},
1812             {"",S_FALSE,FALSE},
1813             {"",S_FALSE,FALSE},
1814             {"google.com:65536",S_OK,FALSE},
1815             {"",S_FALSE,FALSE},
1816             {"/",S_OK,FALSE},
1817             {"/",S_OK,FALSE},
1818             {"",S_FALSE,FALSE},
1819             {"zip://google.com:65536",S_OK,FALSE},
1820             {"zip",S_OK,FALSE},
1821             {"",S_FALSE,FALSE},
1822             {"",S_FALSE,FALSE}
1823         },
1824         {
1825             {Uri_HOST_DNS,S_OK,FALSE},
1826             {0,S_FALSE,FALSE},
1827             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1828             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1829         }
1830     },
1831     {   "zip://google.com:65536:25", 0, S_OK, FALSE,
1832         {
1833             {"zip://google.com:65536:25/",S_OK,FALSE},
1834             {"google.com:65536:25",S_OK,FALSE},
1835             {"zip://google.com:65536:25/",S_OK,FALSE},
1836             {"google.com:65536:25",S_OK,FALSE},
1837             {"",S_FALSE,FALSE},
1838             {"",S_FALSE,FALSE},
1839             {"google.com:65536:25",S_OK,FALSE},
1840             {"",S_FALSE,FALSE},
1841             {"/",S_OK,FALSE},
1842             {"/",S_OK,FALSE},
1843             {"",S_FALSE,FALSE},
1844             {"zip://google.com:65536:25",S_OK,FALSE},
1845             {"zip",S_OK,FALSE},
1846             {"",S_FALSE,FALSE},
1847             {"",S_FALSE,FALSE}
1848         },
1849         {
1850             {Uri_HOST_DNS,S_OK,FALSE},
1851             {0,S_FALSE,FALSE},
1852             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1853             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1854         }
1855     },
1856     {   "zip://[::ffff]:abcd", 0, S_OK, FALSE,
1857         {
1858             {"zip://[::ffff]:abcd/",S_OK,FALSE},
1859             {"[::ffff]:abcd",S_OK,FALSE},
1860             {"zip://[::ffff]:abcd/",S_OK,FALSE},
1861             {"",S_FALSE,FALSE},
1862             {"",S_FALSE,FALSE},
1863             {"",S_FALSE,FALSE},
1864             {"[::ffff]:abcd",S_OK,FALSE},
1865             {"",S_FALSE,FALSE},
1866             {"/",S_OK,FALSE},
1867             {"/",S_OK,FALSE},
1868             {"",S_FALSE,FALSE},
1869             {"zip://[::ffff]:abcd",S_OK,FALSE},
1870             {"zip",S_OK,FALSE},
1871             {"",S_FALSE,FALSE},
1872             {"",S_FALSE,FALSE}
1873         },
1874         {
1875             {Uri_HOST_DNS,S_OK,FALSE},
1876             {0,S_FALSE,FALSE},
1877             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1878             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1879         }
1880     },
1881     {   "zip://127.0.0.1:abcd", 0, S_OK, FALSE,
1882         {
1883             {"zip://127.0.0.1:abcd/",S_OK,FALSE},
1884             {"127.0.0.1:abcd",S_OK,FALSE},
1885             {"zip://127.0.0.1:abcd/",S_OK,FALSE},
1886             {"0.1:abcd",S_OK,FALSE},
1887             {"",S_FALSE,FALSE},
1888             {"",S_FALSE,FALSE},
1889             {"127.0.0.1:abcd",S_OK,FALSE},
1890             {"",S_FALSE,FALSE},
1891             {"/",S_OK,FALSE},
1892             {"/",S_OK,FALSE},
1893             {"",S_FALSE,FALSE},
1894             {"zip://127.0.0.1:abcd",S_OK,FALSE},
1895             {"zip",S_OK,FALSE},
1896             {"",S_FALSE,FALSE},
1897             {"",S_FALSE,FALSE}
1898         },
1899         {
1900             {Uri_HOST_DNS,S_OK,FALSE},
1901             {0,S_FALSE,FALSE},
1902             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1903             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1904         }
1905     },
1906     /* Port is just copied over. */
1907     {   "http://google.com:00035", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
1908         {
1909             {"http://google.com:00035",S_OK,FALSE},
1910             {"google.com:00035",S_OK,FALSE},
1911             {"http://google.com:00035",S_OK,FALSE,"http://google.com:35"},
1912             {"google.com",S_OK,FALSE},
1913             {"",S_FALSE,FALSE},
1914             {"",S_FALSE,FALSE},
1915             {"google.com",S_OK,FALSE},
1916             {"",S_FALSE,FALSE},
1917             {"",S_FALSE,FALSE},
1918             {"",S_FALSE,FALSE},
1919             {"",S_FALSE,FALSE},
1920             {"http://google.com:00035",S_OK,FALSE},
1921             {"http",S_OK,FALSE},
1922             {"",S_FALSE,FALSE},
1923             {"",S_FALSE,FALSE}
1924         },
1925         {
1926             {Uri_HOST_DNS,S_OK,FALSE},
1927             {35,S_OK,FALSE},
1928             {URL_SCHEME_HTTP,S_OK,FALSE},
1929             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1930         }
1931     },
1932     /* Default port is copied over. */
1933     {   "http://google.com:80", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
1934         {
1935             {"http://google.com:80",S_OK,FALSE},
1936             {"google.com:80",S_OK,FALSE},
1937             {"http://google.com:80",S_OK,FALSE},
1938             {"google.com",S_OK,FALSE},
1939             {"",S_FALSE,FALSE},
1940             {"",S_FALSE,FALSE},
1941             {"google.com",S_OK,FALSE},
1942             {"",S_FALSE,FALSE},
1943             {"",S_FALSE,FALSE},
1944             {"",S_FALSE,FALSE},
1945             {"",S_FALSE,FALSE},
1946             {"http://google.com:80",S_OK,FALSE},
1947             {"http",S_OK,FALSE},
1948             {"",S_FALSE,FALSE},
1949             {"",S_FALSE,FALSE}
1950         },
1951         {
1952             {Uri_HOST_DNS,S_OK,FALSE},
1953             {80,S_OK,FALSE},
1954             {URL_SCHEME_HTTP,S_OK,FALSE},
1955             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1956         }
1957     },
1958     {   "http://google.com.uk", 0, S_OK, FALSE,
1959         {
1960             {"http://google.com.uk/",S_OK,FALSE},
1961             {"google.com.uk",S_OK,FALSE},
1962             {"http://google.com.uk/",S_OK,FALSE},
1963             {"google.com.uk",S_OK,FALSE,NULL,"com.uk",S_OK},  /* cf. google.co.uk below */
1964             {"",S_FALSE,FALSE},
1965             {"",S_FALSE,FALSE},
1966             {"google.com.uk",S_OK,FALSE},
1967             {"",S_FALSE,FALSE},
1968             {"/",S_OK,FALSE},
1969             {"/",S_OK,FALSE},
1970             {"",S_FALSE,FALSE},
1971             {"http://google.com.uk",S_OK,FALSE},
1972             {"http",S_OK,FALSE},
1973             {"",S_FALSE,FALSE},
1974             {"",S_FALSE,FALSE}
1975         },
1976         {
1977             {Uri_HOST_DNS,S_OK,FALSE},
1978             {80,S_OK,FALSE},
1979             {URL_SCHEME_HTTP,S_OK,FALSE},
1980             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1981         }
1982     },
1983     {   "http://google.co.uk", 0, S_OK, FALSE,
1984         {
1985             {"http://google.co.uk/",S_OK,FALSE},
1986             {"google.co.uk",S_OK,FALSE},
1987             {"http://google.co.uk/",S_OK,FALSE},
1988             {"google.co.uk",S_OK,FALSE},
1989             {"",S_FALSE,FALSE},
1990             {"",S_FALSE,FALSE},
1991             {"google.co.uk",S_OK,FALSE},
1992             {"",S_FALSE,FALSE},
1993             {"/",S_OK,FALSE},
1994             {"/",S_OK,FALSE},
1995             {"",S_FALSE,FALSE},
1996             {"http://google.co.uk",S_OK,FALSE},
1997             {"http",S_OK,FALSE},
1998             {"",S_FALSE,FALSE},
1999             {"",S_FALSE,FALSE}
2000         },
2001         {
2002             {Uri_HOST_DNS,S_OK,FALSE},
2003             {80,S_OK,FALSE},
2004             {URL_SCHEME_HTTP,S_OK,FALSE},
2005             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2006         }
2007     },
2008     {   "http://google.com.com", 0, S_OK, FALSE,
2009         {
2010             {"http://google.com.com/",S_OK,FALSE},
2011             {"google.com.com",S_OK,FALSE},
2012             {"http://google.com.com/",S_OK,FALSE},
2013             {"com.com",S_OK,FALSE},
2014             {"",S_FALSE,FALSE},
2015             {"",S_FALSE,FALSE},
2016             {"google.com.com",S_OK,FALSE},
2017             {"",S_FALSE,FALSE},
2018             {"/",S_OK,FALSE},
2019             {"/",S_OK,FALSE},
2020             {"",S_FALSE,FALSE},
2021             {"http://google.com.com",S_OK,FALSE},
2022             {"http",S_OK,FALSE},
2023             {"",S_FALSE,FALSE},
2024             {"",S_FALSE,FALSE}
2025         },
2026         {
2027             {Uri_HOST_DNS,S_OK,FALSE},
2028             {80,S_OK,FALSE},
2029             {URL_SCHEME_HTTP,S_OK,FALSE},
2030             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2031         }
2032     },
2033     {   "http://google.uk.1", 0, S_OK, FALSE,
2034         {
2035             {"http://google.uk.1/",S_OK,FALSE},
2036             {"google.uk.1",S_OK,FALSE},
2037             {"http://google.uk.1/",S_OK,FALSE},
2038             {"google.uk.1",S_OK,FALSE,NULL,"uk.1",S_OK},
2039             {"",S_FALSE,FALSE},
2040             {"",S_FALSE,FALSE},
2041             {"google.uk.1",S_OK,FALSE},
2042             {"",S_FALSE,FALSE},
2043             {"/",S_OK,FALSE},
2044             {"/",S_OK,FALSE},
2045             {"",S_FALSE,FALSE},
2046             {"http://google.uk.1",S_OK,FALSE},
2047             {"http",S_OK,FALSE},
2048             {"",S_FALSE,FALSE},
2049             {"",S_FALSE,FALSE}
2050         },
2051         {
2052             {Uri_HOST_DNS,S_OK,FALSE},
2053             {80,S_OK,FALSE},
2054             {URL_SCHEME_HTTP,S_OK,FALSE},
2055             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2056         }
2057     },
2058     /* Since foo isn't a recognized 3 character TLD it's considered the domain name. */
2059     {   "http://google.foo.uk", 0, S_OK, FALSE,
2060         {
2061             {"http://google.foo.uk/",S_OK,FALSE},
2062             {"google.foo.uk",S_OK,FALSE},
2063             {"http://google.foo.uk/",S_OK,FALSE},
2064             {"foo.uk",S_OK,FALSE},
2065             {"",S_FALSE,FALSE},
2066             {"",S_FALSE,FALSE},
2067             {"google.foo.uk",S_OK,FALSE},
2068             {"",S_FALSE,FALSE},
2069             {"/",S_OK,FALSE},
2070             {"/",S_OK,FALSE},
2071             {"",S_FALSE,FALSE},
2072             {"http://google.foo.uk",S_OK,FALSE},
2073             {"http",S_OK,FALSE},
2074             {"",S_FALSE,FALSE},
2075             {"",S_FALSE,FALSE}
2076         },
2077         {
2078             {Uri_HOST_DNS,S_OK,FALSE},
2079             {80,S_OK,FALSE},
2080             {URL_SCHEME_HTTP,S_OK,FALSE},
2081             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2082         }
2083     },
2084     {   "http://.com", 0, S_OK, FALSE,
2085         {
2086             {"http://.com/",S_OK,FALSE},
2087             {".com",S_OK,FALSE},
2088             {"http://.com/",S_OK,FALSE},
2089             {".com",S_OK,FALSE},
2090             {"",S_FALSE,FALSE},
2091             {"",S_FALSE,FALSE},
2092             {".com",S_OK,FALSE},
2093             {"",S_FALSE,FALSE},
2094             {"/",S_OK,FALSE},
2095             {"/",S_OK,FALSE},
2096             {"",S_FALSE,FALSE},
2097             {"http://.com",S_OK,FALSE},
2098             {"http",S_OK,FALSE},
2099             {"",S_FALSE,FALSE},
2100             {"",S_FALSE,FALSE}
2101         },
2102         {
2103             {Uri_HOST_DNS,S_OK,FALSE},
2104             {80,S_OK,FALSE},
2105             {URL_SCHEME_HTTP,S_OK,FALSE},
2106             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2107         }
2108     },
2109     {   "http://.uk", 0, S_OK, FALSE,
2110         {
2111             {"http://.uk/",S_OK,FALSE},
2112             {".uk",S_OK,FALSE},
2113             {"http://.uk/",S_OK,FALSE},
2114             {"",S_FALSE,FALSE,NULL,".uk",S_OK},
2115             {"",S_FALSE,FALSE},
2116             {"",S_FALSE,FALSE},
2117             {".uk",S_OK,FALSE},
2118             {"",S_FALSE,FALSE},
2119             {"/",S_OK,FALSE},
2120             {"/",S_OK,FALSE},
2121             {"",S_FALSE,FALSE},
2122             {"http://.uk",S_OK,FALSE},
2123             {"http",S_OK,FALSE},
2124             {"",S_FALSE,FALSE},
2125             {"",S_FALSE,FALSE}
2126         },
2127         {
2128             {Uri_HOST_DNS,S_OK,FALSE},
2129             {80,S_OK,FALSE},
2130             {URL_SCHEME_HTTP,S_OK,FALSE},
2131             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2132         }
2133     },
2134     {   "http://www.co.google.com.[]", 0, S_OK, FALSE,
2135         {
2136             {"http://www.co.google.com.[]/",S_OK,FALSE},
2137             {"www.co.google.com.[]",S_OK,FALSE},
2138             {"http://www.co.google.com.[]/",S_OK,FALSE},
2139             {"google.com.[]",S_OK,FALSE,NULL,"com.[]",S_OK},
2140             {"",S_FALSE,FALSE},
2141             {"",S_FALSE,FALSE},
2142             {"www.co.google.com.[]",S_OK,FALSE},
2143             {"",S_FALSE,FALSE},
2144             {"/",S_OK,FALSE},
2145             {"/",S_OK,FALSE},
2146             {"",S_FALSE,FALSE},
2147             {"http://www.co.google.com.[]",S_OK,FALSE},
2148             {"http",S_OK,FALSE},
2149             {"",S_FALSE,FALSE},
2150             {"",S_FALSE,FALSE}
2151         },
2152         {
2153             {Uri_HOST_DNS,S_OK,FALSE},
2154             {80,S_OK,FALSE},
2155             {URL_SCHEME_HTTP,S_OK,FALSE},
2156             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2157         }
2158     },
2159     {   "http://co.uk", 0, S_OK, FALSE,
2160         {
2161             {"http://co.uk/",S_OK,FALSE},
2162             {"co.uk",S_OK,FALSE},
2163             {"http://co.uk/",S_OK,FALSE},
2164             {"",S_FALSE,FALSE},
2165             {"",S_FALSE,FALSE},
2166             {"",S_FALSE,FALSE},
2167             {"co.uk",S_OK,FALSE},
2168             {"",S_FALSE,FALSE},
2169             {"/",S_OK,FALSE},
2170             {"/",S_OK,FALSE},
2171             {"",S_FALSE,FALSE},
2172             {"http://co.uk",S_OK,FALSE},
2173             {"http",S_OK,FALSE},
2174             {"",S_FALSE,FALSE},
2175             {"",S_FALSE,FALSE}
2176         },
2177         {
2178             {Uri_HOST_DNS,S_OK,FALSE},
2179             {80,S_OK,FALSE},
2180             {URL_SCHEME_HTTP,S_OK,FALSE},
2181             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2182         }
2183     },
2184     {   "http://www.co.google.us.test", 0, S_OK, FALSE,
2185         {
2186             {"http://www.co.google.us.test/",S_OK,FALSE},
2187             {"www.co.google.us.test",S_OK,FALSE},
2188             {"http://www.co.google.us.test/",S_OK,FALSE},
2189             {"us.test",S_OK,FALSE},
2190             {"",S_FALSE,FALSE},
2191             {"",S_FALSE,FALSE},
2192             {"www.co.google.us.test",S_OK,FALSE},
2193             {"",S_FALSE,FALSE},
2194             {"/",S_OK,FALSE},
2195             {"/",S_OK,FALSE},
2196             {"",S_FALSE,FALSE},
2197             {"http://www.co.google.us.test",S_OK,FALSE},
2198             {"http",S_OK,FALSE},
2199             {"",S_FALSE,FALSE},
2200             {"",S_FALSE,FALSE}
2201         },
2202         {
2203             {Uri_HOST_DNS,S_OK,FALSE},
2204             {80,S_OK,FALSE},
2205             {URL_SCHEME_HTTP,S_OK,FALSE},
2206             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2207         }
2208     },
2209     {   "http://gov.uk", 0, S_OK, FALSE,
2210         {
2211             {"http://gov.uk/",S_OK,FALSE},
2212             {"gov.uk",S_OK,FALSE},
2213             {"http://gov.uk/",S_OK,FALSE},
2214             {"",S_FALSE,FALSE},
2215             {"",S_FALSE,FALSE},
2216             {"",S_FALSE,FALSE},
2217             {"gov.uk",S_OK,FALSE},
2218             {"",S_FALSE,FALSE},
2219             {"/",S_OK,FALSE},
2220             {"/",S_OK,FALSE},
2221             {"",S_FALSE,FALSE},
2222             {"http://gov.uk",S_OK,FALSE},
2223             {"http",S_OK,FALSE},
2224             {"",S_FALSE,FALSE},
2225             {"",S_FALSE,FALSE}
2226         },
2227         {
2228             {Uri_HOST_DNS,S_OK,FALSE},
2229             {80,S_OK,FALSE},
2230             {URL_SCHEME_HTTP,S_OK,FALSE},
2231             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2232         }
2233     },
2234     {   "zip://www.google.com\\test", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
2235         {
2236             {"zip://www.google.com\\test",S_OK,FALSE},
2237             {"www.google.com\\test",S_OK,FALSE},
2238             {"zip://www.google.com\\test",S_OK,FALSE},
2239             {"google.com\\test",S_OK,FALSE},
2240             {"",S_FALSE,FALSE},
2241             {"",S_FALSE,FALSE},
2242             {"www.google.com\\test",S_OK,FALSE},
2243             {"",S_FALSE,FALSE},
2244             {"",S_FALSE,FALSE},
2245             {"",S_FALSE,FALSE},
2246             {"",S_FALSE,FALSE},
2247             {"zip://www.google.com\\test",S_OK,FALSE},
2248             {"zip",S_OK,FALSE},
2249             {"",S_FALSE,FALSE},
2250             {"",S_FALSE,FALSE}
2251         },
2252         {
2253             {Uri_HOST_DNS,S_OK,FALSE},
2254             {0,S_FALSE,FALSE},
2255             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2256             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2257         }
2258     },
2259     {   "urn:excepts:bad:%XY:encoded", 0, S_OK, FALSE,
2260         {
2261             {"urn:excepts:bad:%XY:encoded",S_OK,FALSE},
2262             {"",S_FALSE,FALSE},
2263             {"urn:excepts:bad:%XY:encoded",S_OK,FALSE},
2264             {"",S_FALSE,FALSE},
2265             {"",S_FALSE,FALSE},
2266             {"",S_FALSE,FALSE},
2267             {"",S_FALSE,FALSE},
2268             {"",S_FALSE,FALSE},
2269             {"excepts:bad:%XY:encoded",S_OK,FALSE},
2270             {"excepts:bad:%XY:encoded",S_OK,FALSE},
2271             {"",S_FALSE,FALSE},
2272             {"urn:excepts:bad:%XY:encoded",S_OK,FALSE},
2273             {"urn",S_OK,FALSE},
2274             {"",S_FALSE,FALSE},
2275             {"",S_FALSE,FALSE}
2276         },
2277         {
2278             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2279             {0,S_FALSE,FALSE},
2280             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2281             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2282         }
2283     },
2284     /* Since the original URI doesn't contain an extra '/' before the path no % encoded values
2285      * are decoded and all '%' are encoded.
2286      */
2287     {   "file://C:/te%3Es%2Et/tes%t.mp3", 0, S_OK, FALSE,
2288         {
2289             {"file:///C:/te%253Es%252Et/tes%25t.mp3",S_OK,FALSE},
2290             {"",S_FALSE,FALSE},
2291             {"file:///C:/te%253Es%252Et/tes%25t.mp3",S_OK,FALSE},
2292             {"",S_FALSE,FALSE},
2293             {".mp3",S_OK,FALSE},
2294             {"",S_FALSE,FALSE},
2295             {"",S_FALSE,FALSE},
2296             {"",S_FALSE,FALSE},
2297             {"/C:/te%253Es%252Et/tes%25t.mp3",S_OK,FALSE},
2298             {"/C:/te%253Es%252Et/tes%25t.mp3",S_OK,FALSE},
2299             {"",S_FALSE,FALSE},
2300             {"file://C:/te%3Es%2Et/tes%t.mp3",S_OK,FALSE},
2301             {"file",S_OK,FALSE},
2302             {"",S_FALSE,FALSE},
2303             {"",S_FALSE,FALSE}
2304         },
2305         {
2306             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2307             {0,S_FALSE,FALSE},
2308             {URL_SCHEME_FILE,S_OK,FALSE},
2309             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2310         }
2311     },
2312     /* Since there's a '/' in front of the drive letter, any percent encoded, non-forbidden character
2313      * is decoded and only %'s in front of invalid hex digits are encoded.
2314      */
2315     {   "file:///C:/te%3Es%2Et/t%23es%t.mp3", 0, S_OK, FALSE,
2316         {
2317             {"file:///C:/te%3Es.t/t#es%25t.mp3",S_OK,FALSE},
2318             {"",S_FALSE,FALSE},
2319             {"file:///C:/te%3Es.t/t#es%25t.mp3",S_OK,FALSE},
2320             {"",S_FALSE,FALSE},
2321             {".mp3",S_OK,FALSE},
2322             {"",S_FALSE,FALSE},
2323             {"",S_FALSE,FALSE},
2324             {"",S_FALSE,FALSE},
2325             {"/C:/te%3Es.t/t#es%25t.mp3",S_OK,FALSE},
2326             {"/C:/te%3Es.t/t#es%25t.mp3",S_OK,FALSE},
2327             {"",S_FALSE,FALSE},
2328             {"file:///C:/te%3Es%2Et/t%23es%t.mp3",S_OK,FALSE},
2329             {"file",S_OK,FALSE},
2330             {"",S_FALSE,FALSE},
2331             {"",S_FALSE,FALSE}
2332         },
2333         {
2334             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2335             {0,S_FALSE,FALSE},
2336             {URL_SCHEME_FILE,S_OK,FALSE},
2337             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2338         }
2339     },
2340     /* Only unreserved percent encoded characters are decoded for known schemes that aren't file. */
2341     {   "http://[::001.002.003.000]/%3F%23%2E%54/test", 0, S_OK, FALSE,
2342         {
2343             {"http://[::1.2.3.0]/%3F%23.T/test",S_OK,FALSE},
2344             {"[::1.2.3.0]",S_OK,FALSE},
2345             {"http://[::1.2.3.0]/%3F%23.T/test",S_OK,FALSE},
2346             {"",S_FALSE,FALSE},
2347             {"",S_FALSE,FALSE},
2348             {"",S_FALSE,FALSE},
2349             {"::1.2.3.0",S_OK,FALSE},
2350             {"",S_FALSE,FALSE},
2351             {"/%3F%23.T/test",S_OK,FALSE},
2352             {"/%3F%23.T/test",S_OK,FALSE},
2353             {"",S_FALSE,FALSE},
2354             {"http://[::001.002.003.000]/%3F%23%2E%54/test",S_OK,FALSE},
2355             {"http",S_OK,FALSE},
2356             {"",S_FALSE,FALSE},
2357             {"",S_FALSE,FALSE},
2358         },
2359         {
2360             {Uri_HOST_IPV6,S_OK,FALSE},
2361             {80,S_OK,FALSE},
2362             {URL_SCHEME_HTTP,S_OK,FALSE},
2363             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2364         }
2365     },
2366     /* Forbidden characters are always encoded for file URIs. */
2367     {   "file:///C:/\"test\"/test.mp3", Uri_CREATE_NO_ENCODE_FORBIDDEN_CHARACTERS, S_OK, FALSE,
2368         {
2369             {"file:///C:/%22test%22/test.mp3",S_OK,FALSE},
2370             {"",S_FALSE,FALSE},
2371             {"file:///C:/%22test%22/test.mp3",S_OK,FALSE},
2372             {"",S_FALSE,FALSE},
2373             {".mp3",S_OK,FALSE},
2374             {"",S_FALSE,FALSE},
2375             {"",S_FALSE,FALSE},
2376             {"",S_FALSE,FALSE},
2377             {"/C:/%22test%22/test.mp3",S_OK,FALSE},
2378             {"/C:/%22test%22/test.mp3",S_OK,FALSE},
2379             {"",S_FALSE,FALSE},
2380             {"file:///C:/\"test\"/test.mp3",S_OK,FALSE},
2381             {"file",S_OK,FALSE},
2382             {"",S_FALSE,FALSE},
2383             {"",S_FALSE,FALSE}
2384         },
2385         {
2386             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2387             {0,S_FALSE,FALSE},
2388             {URL_SCHEME_FILE,S_OK,FALSE},
2389             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2390         }
2391     },
2392     /* Forbidden characters are never encoded for unknown scheme types. */
2393     {   "1234://4294967295/<|>\" test<|>", 0, S_OK, FALSE,
2394         {
2395             {"1234://4294967295/<|>\" test<|>",S_OK,FALSE},
2396             {"4294967295",S_OK,FALSE},
2397             {"1234://4294967295/<|>\" test<|>",S_OK,FALSE},
2398             {"",S_FALSE,FALSE},
2399             {"",S_FALSE,FALSE},
2400             {"",S_FALSE,FALSE},
2401             {"4294967295",S_OK,FALSE},
2402             {"",S_FALSE,FALSE},
2403             {"/<|>\" test<|>",S_OK,FALSE},
2404             {"/<|>\" test<|>",S_OK,FALSE},
2405             {"",S_FALSE,FALSE},
2406             {"1234://4294967295/<|>\" test<|>",S_OK,FALSE},
2407             {"1234",S_OK,FALSE},
2408             {"",S_FALSE,FALSE},
2409             {"",S_FALSE,FALSE}
2410         },
2411         {
2412             {Uri_HOST_IPV4,S_OK,FALSE},
2413             {0,S_FALSE,FALSE},
2414             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2415             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2416         }
2417     },
2418     /* Make sure forbidden characters are percent encoded. */
2419     {   "http://gov.uk/<|> test<|>", 0, S_OK, FALSE,
2420         {
2421             {"http://gov.uk/%3C%7C%3E%20test%3C%7C%3E",S_OK,FALSE},
2422             {"gov.uk",S_OK,FALSE},
2423             {"http://gov.uk/%3C%7C%3E%20test%3C%7C%3E",S_OK,FALSE},
2424             {"",S_FALSE,FALSE},
2425             {"",S_FALSE,FALSE},
2426             {"",S_FALSE,FALSE},
2427             {"gov.uk",S_OK,FALSE},
2428             {"",S_FALSE,FALSE},
2429             {"/%3C%7C%3E%20test%3C%7C%3E",S_OK,FALSE},
2430             {"/%3C%7C%3E%20test%3C%7C%3E",S_OK,FALSE},
2431             {"",S_FALSE,FALSE},
2432             {"http://gov.uk/<|> test<|>",S_OK,FALSE},
2433             {"http",S_OK,FALSE},
2434             {"",S_FALSE,FALSE},
2435             {"",S_FALSE,FALSE}
2436         },
2437         {
2438             {Uri_HOST_DNS,S_OK,FALSE},
2439             {80,S_OK,FALSE},
2440             {URL_SCHEME_HTTP,S_OK,FALSE},
2441             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2442         }
2443     },
2444     {   "http://gov.uk/test/../test2/././../test3/.././././", 0, S_OK, FALSE,
2445         {
2446             {"http://gov.uk/",S_OK,FALSE},
2447             {"gov.uk",S_OK,FALSE},
2448             {"http://gov.uk/",S_OK,FALSE},
2449             {"",S_FALSE,FALSE},
2450             {"",S_FALSE,FALSE},
2451             {"",S_FALSE,FALSE},
2452             {"gov.uk",S_OK,FALSE},
2453             {"",S_FALSE,FALSE},
2454             {"/",S_OK,FALSE},
2455             {"/",S_OK,FALSE},
2456             {"",S_FALSE,FALSE},
2457             {"http://gov.uk/test/../test2/././../test3/.././././",S_OK,FALSE},
2458             {"http",S_OK,FALSE},
2459             {"",S_FALSE,FALSE},
2460             {"",S_FALSE,FALSE}
2461         },
2462         {
2463             {Uri_HOST_DNS,S_OK,FALSE},
2464             {80,S_OK,FALSE},
2465             {URL_SCHEME_HTTP,S_OK,FALSE},
2466             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2467         }
2468     },
2469     {   "http://gov.uk/test/test2/../../..", 0, S_OK, FALSE,
2470         {
2471             {"http://gov.uk/",S_OK,FALSE},
2472             {"gov.uk",S_OK,FALSE},
2473             {"http://gov.uk/",S_OK,FALSE},
2474             {"",S_FALSE,FALSE},
2475             {"",S_FALSE,FALSE},
2476             {"",S_FALSE,FALSE},
2477             {"gov.uk",S_OK,FALSE},
2478             {"",S_FALSE,FALSE},
2479             {"/",S_OK,FALSE},
2480             {"/",S_OK,FALSE},
2481             {"",S_FALSE,FALSE},
2482             {"http://gov.uk/test/test2/../../..",S_OK,FALSE},
2483             {"http",S_OK,FALSE},
2484             {"",S_FALSE,FALSE},
2485             {"",S_FALSE,FALSE}
2486         },
2487         {
2488             {Uri_HOST_DNS,S_OK,FALSE},
2489             {80,S_OK,FALSE},
2490             {URL_SCHEME_HTTP,S_OK,FALSE},
2491             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2492         }
2493     },
2494     {   "http://gov.uk/test/test2/../../.", 0, S_OK, FALSE,
2495         {
2496             {"http://gov.uk/",S_OK,FALSE},
2497             {"gov.uk",S_OK,FALSE},
2498             {"http://gov.uk/",S_OK,FALSE},
2499             {"",S_FALSE,FALSE},
2500             {"",S_FALSE,FALSE},
2501             {"",S_FALSE,FALSE},
2502             {"gov.uk",S_OK,FALSE},
2503             {"",S_FALSE,FALSE},
2504             {"/",S_OK,FALSE},
2505             {"/",S_OK,FALSE},
2506             {"",S_FALSE,FALSE},
2507             {"http://gov.uk/test/test2/../../.",S_OK,FALSE},
2508             {"http",S_OK,FALSE},
2509             {"",S_FALSE,FALSE},
2510             {"",S_FALSE,FALSE}
2511         },
2512         {
2513             {Uri_HOST_DNS,S_OK,FALSE},
2514             {80,S_OK,FALSE},
2515             {URL_SCHEME_HTTP,S_OK,FALSE},
2516             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2517         }
2518     },
2519     {   "file://c:\\tests\\../tests\\./.\\..\\foo%20bar.mp3", 0, S_OK, FALSE,
2520         {
2521             {"file:///c:/foo%2520bar.mp3",S_OK,FALSE},
2522             {"",S_FALSE,FALSE},
2523             {"file:///c:/foo%2520bar.mp3",S_OK,FALSE},
2524             {"",S_FALSE,FALSE},
2525             {".mp3",S_OK,FALSE},
2526             {"",S_FALSE,FALSE},
2527             {"",S_FALSE,FALSE},
2528             {"",S_FALSE,FALSE},
2529             {"/c:/foo%2520bar.mp3",S_OK,FALSE},
2530             {"/c:/foo%2520bar.mp3",S_OK,FALSE},
2531             {"",S_FALSE,FALSE},
2532             {"file://c:\\tests\\../tests\\./.\\..\\foo%20bar.mp3",S_OK,FALSE},
2533             {"file",S_OK,FALSE},
2534             {"",S_FALSE,FALSE},
2535             {"",S_FALSE,FALSE}
2536         },
2537         {
2538             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2539             {0,S_FALSE,FALSE},
2540             {URL_SCHEME_FILE,S_OK,FALSE},
2541             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2542         }
2543     },
2544     /* Dot removal happens for unknown scheme types. */
2545     {   "zip://gov.uk/test/test2/../../.", 0, S_OK, FALSE,
2546         {
2547             {"zip://gov.uk/",S_OK,FALSE},
2548             {"gov.uk",S_OK,FALSE},
2549             {"zip://gov.uk/",S_OK,FALSE},
2550             {"",S_FALSE,FALSE},
2551             {"",S_FALSE,FALSE},
2552             {"",S_FALSE,FALSE},
2553             {"gov.uk",S_OK,FALSE},
2554             {"",S_FALSE,FALSE},
2555             {"/",S_OK,FALSE},
2556             {"/",S_OK,FALSE},
2557             {"",S_FALSE,FALSE},
2558             {"zip://gov.uk/test/test2/../../.",S_OK,FALSE},
2559             {"zip",S_OK,FALSE},
2560             {"",S_FALSE,FALSE},
2561             {"",S_FALSE,FALSE}
2562         },
2563         {
2564             {Uri_HOST_DNS,S_OK,FALSE},
2565             {0,S_FALSE,FALSE},
2566             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2567             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2568         }
2569     },
2570     /* Dot removal doesn't happen if NO_CANONICALIZE is set. */
2571     {   "http://gov.uk/test/test2/../../.", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
2572         {
2573             {"http://gov.uk/test/test2/../../.",S_OK,FALSE},
2574             {"gov.uk",S_OK,FALSE},
2575             {"http://gov.uk/test/test2/../../.",S_OK,FALSE},
2576             {"",S_FALSE,FALSE},
2577             {".",S_OK,FALSE},
2578             {"",S_FALSE,FALSE},
2579             {"gov.uk",S_OK,FALSE},
2580             {"",S_FALSE,FALSE},
2581             {"/test/test2/../../.",S_OK,FALSE},
2582             {"/test/test2/../../.",S_OK,FALSE},
2583             {"",S_FALSE,FALSE},
2584             {"http://gov.uk/test/test2/../../.",S_OK,FALSE},
2585             {"http",S_OK,FALSE},
2586             {"",S_FALSE,FALSE},
2587             {"",S_FALSE,FALSE}
2588         },
2589         {
2590             {Uri_HOST_DNS,S_OK,FALSE},
2591             {80,S_OK,FALSE},
2592             {URL_SCHEME_HTTP,S_OK,FALSE},
2593             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2594         }
2595     },
2596     /* Dot removal doesn't happen for wildcard scheme types. */
2597     {   "*:gov.uk/test/test2/../../.", 0, S_OK, FALSE,
2598         {
2599             {"*:gov.uk/test/test2/../../.",S_OK,FALSE},
2600             {"gov.uk",S_OK,FALSE},
2601             {"*:gov.uk/test/test2/../../.",S_OK,FALSE},
2602             {"",S_FALSE,FALSE},
2603             {".",S_OK,FALSE},
2604             {"",S_FALSE,FALSE},
2605             {"gov.uk",S_OK,FALSE},
2606             {"",S_FALSE,FALSE},
2607             {"/test/test2/../../.",S_OK,FALSE},
2608             {"/test/test2/../../.",S_OK,FALSE},
2609             {"",S_FALSE,FALSE},
2610             {"*:gov.uk/test/test2/../../.",S_OK,FALSE},
2611             {"*",S_OK,FALSE},
2612             {"",S_FALSE,FALSE},
2613             {"",S_FALSE,FALSE}
2614         },
2615         {
2616             {Uri_HOST_DNS,S_OK,FALSE},
2617             {0,S_FALSE,FALSE},
2618             {URL_SCHEME_WILDCARD,S_OK,FALSE},
2619             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2620         }
2621     },
2622     /* Forbidden characters are encoded for opaque known scheme types. */
2623     {   "mailto:\"acco<|>unt@example.com\"", 0, S_OK, FALSE,
2624         {
2625             {"mailto:%22acco%3C%7C%3Eunt@example.com%22",S_OK,FALSE},
2626             {"",S_FALSE,FALSE},
2627             {"mailto:%22acco%3C%7C%3Eunt@example.com%22",S_OK,FALSE},
2628             {"",S_FALSE,FALSE},
2629             {".com%22",S_OK,FALSE},
2630             {"",S_FALSE,FALSE},
2631             {"",S_FALSE,FALSE},
2632             {"",S_FALSE,FALSE},
2633             {"%22acco%3C%7C%3Eunt@example.com%22",S_OK,FALSE},
2634             {"%22acco%3C%7C%3Eunt@example.com%22",S_OK,FALSE},
2635             {"",S_FALSE,FALSE},
2636             {"mailto:\"acco<|>unt@example.com\"",S_OK,FALSE},
2637             {"mailto",S_OK,FALSE},
2638             {"",S_FALSE,FALSE},
2639             {"",S_FALSE,FALSE}
2640         },
2641         {
2642             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2643             {0,S_FALSE,FALSE},
2644             {URL_SCHEME_MAILTO,S_OK,FALSE},
2645             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2646         }
2647     },
2648     {   "news:test.tes<|>t.com", 0, S_OK, FALSE,
2649         {
2650             {"news:test.tes%3C%7C%3Et.com",S_OK,FALSE},
2651             {"",S_FALSE,FALSE},
2652             {"news:test.tes%3C%7C%3Et.com",S_OK,FALSE},
2653             {"",S_FALSE,FALSE},
2654             {".com",S_OK,FALSE},
2655             {"",S_FALSE,FALSE},
2656             {"",S_FALSE,FALSE},
2657             {"",S_FALSE,FALSE},
2658             {"test.tes%3C%7C%3Et.com",S_OK,FALSE},
2659             {"test.tes%3C%7C%3Et.com",S_OK,FALSE},
2660             {"",S_FALSE,FALSE},
2661             {"news:test.tes<|>t.com",S_OK,FALSE},
2662             {"news",S_OK,FALSE},
2663             {"",S_FALSE,FALSE},
2664             {"",S_FALSE,FALSE}
2665         },
2666         {
2667             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2668             {0,S_FALSE,FALSE},
2669             {URL_SCHEME_NEWS,S_OK,FALSE},
2670             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2671         }
2672     },
2673     /* Don't encode forbidden characters. */
2674     {   "news:test.tes<|>t.com", Uri_CREATE_NO_ENCODE_FORBIDDEN_CHARACTERS, S_OK, FALSE,
2675         {
2676             {"news:test.tes<|>t.com",S_OK,FALSE},
2677             {"",S_FALSE,FALSE},
2678             {"news:test.tes<|>t.com",S_OK,FALSE},
2679             {"",S_FALSE,FALSE},
2680             {".com",S_OK,FALSE},
2681             {"",S_FALSE,FALSE},
2682             {"",S_FALSE,FALSE},
2683             {"",S_FALSE,FALSE},
2684             {"test.tes<|>t.com",S_OK,FALSE},
2685             {"test.tes<|>t.com",S_OK,FALSE},
2686             {"",S_FALSE,FALSE},
2687             {"news:test.tes<|>t.com",S_OK,FALSE},
2688             {"news",S_OK,FALSE},
2689             {"",S_FALSE,FALSE},
2690             {"",S_FALSE,FALSE}
2691         },
2692         {
2693             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2694             {0,S_FALSE,FALSE},
2695             {URL_SCHEME_NEWS,S_OK,FALSE},
2696             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2697         }
2698     },
2699     /* Forbidden characters aren't encoded for unknown, opaque URIs. */
2700     {   "urn:test.tes<|>t.com", 0, S_OK, FALSE,
2701         {
2702             {"urn:test.tes<|>t.com",S_OK,FALSE},
2703             {"",S_FALSE,FALSE},
2704             {"urn:test.tes<|>t.com",S_OK,FALSE},
2705             {"",S_FALSE,FALSE},
2706             {".com",S_OK,FALSE},
2707             {"",S_FALSE,FALSE},
2708             {"",S_FALSE,FALSE},
2709             {"",S_FALSE,FALSE},
2710             {"test.tes<|>t.com",S_OK,FALSE},
2711             {"test.tes<|>t.com",S_OK,FALSE},
2712             {"",S_FALSE,FALSE},
2713             {"urn:test.tes<|>t.com",S_OK,FALSE},
2714             {"urn",S_OK,FALSE},
2715             {"",S_FALSE,FALSE},
2716             {"",S_FALSE,FALSE}
2717         },
2718         {
2719             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2720             {0,S_FALSE,FALSE},
2721             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2722             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2723         }
2724     },
2725     /* Percent encoded unreserved characters are decoded for known opaque URIs. */
2726     {   "news:test.%74%65%73%74.com", 0, S_OK, FALSE,
2727         {
2728             {"news:test.test.com",S_OK,FALSE},
2729             {"",S_FALSE,FALSE},
2730             {"news:test.test.com",S_OK,FALSE},
2731             {"",S_FALSE,FALSE},
2732             {".com",S_OK,FALSE},
2733             {"",S_FALSE,FALSE},
2734             {"",S_FALSE,FALSE},
2735             {"",S_FALSE,FALSE},
2736             {"test.test.com",S_OK,FALSE},
2737             {"test.test.com",S_OK,FALSE},
2738             {"",S_FALSE,FALSE},
2739             {"news:test.%74%65%73%74.com",S_OK,FALSE},
2740             {"news",S_OK,FALSE},
2741             {"",S_FALSE,FALSE},
2742             {"",S_FALSE,FALSE}
2743         },
2744         {
2745             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2746             {0,S_FALSE,FALSE},
2747             {URL_SCHEME_NEWS,S_OK,FALSE},
2748             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2749         }
2750     },
2751     /* Percent encoded characters are still decoded for known scheme types. */
2752     {   "news:test.%74%65%73%74.com", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
2753         {
2754             {"news:test.test.com",S_OK,FALSE},
2755             {"",S_FALSE,FALSE},
2756             {"news:test.test.com",S_OK,FALSE},
2757             {"",S_FALSE,FALSE},
2758             {".com",S_OK,FALSE},
2759             {"",S_FALSE,FALSE},
2760             {"",S_FALSE,FALSE},
2761             {"",S_FALSE,FALSE},
2762             {"test.test.com",S_OK,FALSE},
2763             {"test.test.com",S_OK,FALSE},
2764             {"",S_FALSE,FALSE},
2765             {"news:test.%74%65%73%74.com",S_OK,FALSE},
2766             {"news",S_OK,FALSE},
2767             {"",S_FALSE,FALSE},
2768             {"",S_FALSE,FALSE}
2769         },
2770         {
2771             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2772             {0,S_FALSE,FALSE},
2773             {URL_SCHEME_NEWS,S_OK,FALSE},
2774             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2775         }
2776     },
2777     /* Percent encoded characters aren't decoded for unknown scheme types. */
2778     {   "urn:test.%74%65%73%74.com", 0, S_OK, FALSE,
2779         {
2780             {"urn:test.%74%65%73%74.com",S_OK,FALSE},
2781             {"",S_FALSE,FALSE},
2782             {"urn:test.%74%65%73%74.com",S_OK,FALSE},
2783             {"",S_FALSE,FALSE},
2784             {".com",S_OK,FALSE},
2785             {"",S_FALSE,FALSE},
2786             {"",S_FALSE,FALSE},
2787             {"",S_FALSE,FALSE},
2788             {"test.%74%65%73%74.com",S_OK,FALSE},
2789             {"test.%74%65%73%74.com",S_OK,FALSE},
2790             {"",S_FALSE,FALSE},
2791             {"urn:test.%74%65%73%74.com",S_OK,FALSE},
2792             {"urn",S_OK,FALSE},
2793             {"",S_FALSE,FALSE},
2794             {"",S_FALSE,FALSE}
2795         },
2796         {
2797             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2798             {0,S_FALSE,FALSE},
2799             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2800             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2801         }
2802     },
2803     /* Unknown scheme types can have invalid % encoded data in query string. */
2804     {   "zip://www.winehq.org/tests/..?query=%xx&return=y", 0, S_OK, FALSE,
2805         {
2806             {"zip://www.winehq.org/?query=%xx&return=y",S_OK,FALSE},
2807             {"www.winehq.org",S_OK,FALSE},
2808             {"zip://www.winehq.org/?query=%xx&return=y",S_OK,FALSE},
2809             {"winehq.org",S_OK,FALSE},
2810             {"",S_FALSE,FALSE},
2811             {"",S_FALSE,FALSE},
2812             {"www.winehq.org",S_OK,FALSE},
2813             {"",S_FALSE,FALSE},
2814             {"/",S_OK,FALSE},
2815             {"/?query=%xx&return=y",S_OK,FALSE},
2816             {"?query=%xx&return=y",S_OK,FALSE},
2817             {"zip://www.winehq.org/tests/..?query=%xx&return=y",S_OK,FALSE},
2818             {"zip",S_OK,FALSE},
2819             {"",S_FALSE,FALSE},
2820             {"",S_FALSE,FALSE}
2821         },
2822         {
2823             {Uri_HOST_DNS,S_OK,FALSE},
2824             {0,S_FALSE,FALSE},
2825             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2826             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2827         }
2828     },
2829     /* Known scheme types can have invalid % encoded data with the right flags. */
2830     {   "http://www.winehq.org/tests/..?query=%xx&return=y", Uri_CREATE_NO_DECODE_EXTRA_INFO, S_OK, FALSE,
2831         {
2832             {"http://www.winehq.org/?query=%xx&return=y",S_OK,FALSE},
2833             {"www.winehq.org",S_OK,FALSE},
2834             {"http://www.winehq.org/?query=%xx&return=y",S_OK,FALSE},
2835             {"winehq.org",S_OK,FALSE},
2836             {"",S_FALSE,FALSE},
2837             {"",S_FALSE,FALSE},
2838             {"www.winehq.org",S_OK,FALSE},
2839             {"",S_FALSE,FALSE},
2840             {"/",S_OK,FALSE},
2841             {"/?query=%xx&return=y",S_OK,FALSE},
2842             {"?query=%xx&return=y",S_OK,FALSE},
2843             {"http://www.winehq.org/tests/..?query=%xx&return=y",S_OK,FALSE},
2844             {"http",S_OK,FALSE},
2845             {"",S_FALSE,FALSE},
2846             {"",S_FALSE,FALSE}
2847         },
2848         {
2849             {Uri_HOST_DNS,S_OK,FALSE},
2850             {80,S_OK,FALSE},
2851             {URL_SCHEME_HTTP,S_OK,FALSE},
2852             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2853         }
2854     },
2855     /* Forbidden characters in query aren't percent encoded for known scheme types with this flag. */
2856     {   "http://www.winehq.org/tests/..?query=<|>&return=y", Uri_CREATE_NO_DECODE_EXTRA_INFO, S_OK, FALSE,
2857         {
2858             {"http://www.winehq.org/?query=<|>&return=y",S_OK,FALSE},
2859             {"www.winehq.org",S_OK,FALSE},
2860             {"http://www.winehq.org/?query=<|>&return=y",S_OK,FALSE},
2861             {"winehq.org",S_OK,FALSE},
2862             {"",S_FALSE,FALSE},
2863             {"",S_FALSE,FALSE},
2864             {"www.winehq.org",S_OK,FALSE},
2865             {"",S_FALSE,FALSE},
2866             {"/",S_OK,FALSE},
2867             {"/?query=<|>&return=y",S_OK,FALSE},
2868             {"?query=<|>&return=y",S_OK,FALSE},
2869             {"http://www.winehq.org/tests/..?query=<|>&return=y",S_OK,FALSE},
2870             {"http",S_OK,FALSE},
2871             {"",S_FALSE,FALSE},
2872             {"",S_FALSE,FALSE}
2873         },
2874         {
2875             {Uri_HOST_DNS,S_OK,FALSE},
2876             {80,S_OK,FALSE},
2877             {URL_SCHEME_HTTP,S_OK,FALSE},
2878             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2879         }
2880     },
2881     /* Forbidden characters in query aren't percent encoded for known scheme types with this flag. */
2882     {   "http://www.winehq.org/tests/..?query=<|>&return=y", Uri_CREATE_NO_ENCODE_FORBIDDEN_CHARACTERS, S_OK, FALSE,
2883         {
2884             {"http://www.winehq.org/?query=<|>&return=y",S_OK,FALSE},
2885             {"www.winehq.org",S_OK,FALSE},
2886             {"http://www.winehq.org/?query=<|>&return=y",S_OK,FALSE},
2887             {"winehq.org",S_OK,FALSE},
2888             {"",S_FALSE,FALSE},
2889             {"",S_FALSE,FALSE},
2890             {"www.winehq.org",S_OK,FALSE},
2891             {"",S_FALSE,FALSE},
2892             {"/",S_OK,FALSE},
2893             {"/?query=<|>&return=y",S_OK,FALSE},
2894             {"?query=<|>&return=y",S_OK,FALSE},
2895             {"http://www.winehq.org/tests/..?query=<|>&return=y",S_OK,FALSE},
2896             {"http",S_OK,FALSE},
2897             {"",S_FALSE,FALSE},
2898             {"",S_FALSE,FALSE}
2899         },
2900         {
2901             {Uri_HOST_DNS,S_OK,FALSE},
2902             {80,S_OK,FALSE},
2903             {URL_SCHEME_HTTP,S_OK,FALSE},
2904             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2905         }
2906     },
2907     /* Forbidden characters are encoded for known scheme types. */
2908     {   "http://www.winehq.org/tests/..?query=<|>&return=y", 0, S_OK, FALSE,
2909         {
2910             {"http://www.winehq.org/?query=%3C%7C%3E&return=y",S_OK,FALSE},
2911             {"www.winehq.org",S_OK,FALSE},
2912             {"http://www.winehq.org/?query=%3C%7C%3E&return=y",S_OK,FALSE},
2913             {"winehq.org",S_OK,FALSE},
2914             {"",S_FALSE,FALSE},
2915             {"",S_FALSE,FALSE},
2916             {"www.winehq.org",S_OK,FALSE},
2917             {"",S_FALSE,FALSE},
2918             {"/",S_OK,FALSE},
2919             {"/?query=%3C%7C%3E&return=y",S_OK,FALSE},
2920             {"?query=%3C%7C%3E&return=y",S_OK,FALSE},
2921             {"http://www.winehq.org/tests/..?query=<|>&return=y",S_OK,FALSE},
2922             {"http",S_OK,FALSE},
2923             {"",S_FALSE,FALSE},
2924             {"",S_FALSE,FALSE}
2925         },
2926         {
2927             {Uri_HOST_DNS,S_OK,FALSE},
2928             {80,S_OK,FALSE},
2929             {URL_SCHEME_HTTP,S_OK,FALSE},
2930             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2931         }
2932     },
2933     /* Forbidden characters are not encoded for unknown scheme types. */
2934     {   "zip://www.winehq.org/tests/..?query=<|>&return=y", 0, S_OK, FALSE,
2935         {
2936             {"zip://www.winehq.org/?query=<|>&return=y",S_OK,FALSE},
2937             {"www.winehq.org",S_OK,FALSE},
2938             {"zip://www.winehq.org/?query=<|>&return=y",S_OK,FALSE},
2939             {"winehq.org",S_OK,FALSE},
2940             {"",S_FALSE,FALSE},
2941             {"",S_FALSE,FALSE},
2942             {"www.winehq.org",S_OK,FALSE},
2943             {"",S_FALSE,FALSE},
2944             {"/",S_OK,FALSE},
2945             {"/?query=<|>&return=y",S_OK,FALSE},
2946             {"?query=<|>&return=y",S_OK,FALSE},
2947             {"zip://www.winehq.org/tests/..?query=<|>&return=y",S_OK,FALSE},
2948             {"zip",S_OK,FALSE},
2949             {"",S_FALSE,FALSE},
2950             {"",S_FALSE,FALSE}
2951         },
2952         {
2953             {Uri_HOST_DNS,S_OK,FALSE},
2954             {0,S_FALSE,FALSE},
2955             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2956             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2957         }
2958     },
2959     /* Percent encoded, unreserved characters are decoded for known scheme types. */
2960     {   "http://www.winehq.org/tests/..?query=%30%31&return=y", 0, S_OK, FALSE,
2961         {
2962             {"http://www.winehq.org/?query=01&return=y",S_OK,FALSE},
2963             {"www.winehq.org",S_OK,FALSE},
2964             {"http://www.winehq.org/?query=01&return=y",S_OK,FALSE},
2965             {"winehq.org",S_OK,FALSE},
2966             {"",S_FALSE,FALSE},
2967             {"",S_FALSE,FALSE},
2968             {"www.winehq.org",S_OK,FALSE},
2969             {"",S_FALSE,FALSE},
2970             {"/",S_OK,FALSE},
2971             {"/?query=01&return=y",S_OK,FALSE},
2972             {"?query=01&return=y",S_OK,FALSE},
2973             {"http://www.winehq.org/tests/..?query=%30%31&return=y",S_OK,FALSE},
2974             {"http",S_OK,FALSE},
2975             {"",S_FALSE,FALSE},
2976             {"",S_FALSE,FALSE}
2977         },
2978         {
2979             {Uri_HOST_DNS,S_OK,FALSE},
2980             {80,S_OK,FALSE},
2981             {URL_SCHEME_HTTP,S_OK,FALSE},
2982             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2983         }
2984     },
2985     /* Percent encoded, unreserved characters aren't decoded for unknown scheme types. */
2986     {   "zip://www.winehq.org/tests/..?query=%30%31&return=y", 0, S_OK, FALSE,
2987         {
2988             {"zip://www.winehq.org/?query=%30%31&return=y",S_OK,FALSE},
2989             {"www.winehq.org",S_OK,FALSE},
2990             {"zip://www.winehq.org/?query=%30%31&return=y",S_OK,FALSE},
2991             {"winehq.org",S_OK,FALSE},
2992             {"",S_FALSE,FALSE},
2993             {"",S_FALSE,FALSE},
2994             {"www.winehq.org",S_OK,FALSE},
2995             {"",S_FALSE,FALSE},
2996             {"/",S_OK,FALSE},
2997             {"/?query=%30%31&return=y",S_OK,FALSE},
2998             {"?query=%30%31&return=y",S_OK,FALSE},
2999             {"zip://www.winehq.org/tests/..?query=%30%31&return=y",S_OK,FALSE},
3000             {"zip",S_OK,FALSE},
3001             {"",S_FALSE,FALSE},
3002             {"",S_FALSE,FALSE}
3003         },
3004         {
3005             {Uri_HOST_DNS,S_OK,FALSE},
3006             {0,S_FALSE,FALSE},
3007             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
3008             {URLZONE_INVALID,E_NOTIMPL,FALSE},
3009         }
3010     },
3011     /* Percent encoded characters aren't decoded when NO_DECODE_EXTRA_INFO is set. */
3012     {   "http://www.winehq.org/tests/..?query=%30%31&return=y", Uri_CREATE_NO_DECODE_EXTRA_INFO, S_OK, FALSE,
3013         {
3014             {"http://www.winehq.org/?query=%30%31&return=y",S_OK,FALSE},
3015             {"www.winehq.org",S_OK,FALSE},
3016             {"http://www.winehq.org/?query=%30%31&return=y",S_OK,FALSE},
3017             {"winehq.org",S_OK,FALSE},
3018             {"",S_FALSE,FALSE},
3019             {"",S_FALSE,FALSE},
3020             {"www.winehq.org",S_OK,FALSE},
3021             {"",S_FALSE,FALSE},
3022             {"/",S_OK,FALSE},
3023             {"/?query=%30%31&return=y",S_OK,FALSE},
3024             {"?query=%30%31&return=y",S_OK,FALSE},
3025             {"http://www.winehq.org/tests/..?query=%30%31&return=y",S_OK,FALSE},
3026             {"http",S_OK,FALSE},
3027             {"",S_FALSE,FALSE},
3028             {"",S_FALSE,FALSE}
3029         },
3030         {
3031             {Uri_HOST_DNS,S_OK,FALSE},
3032             {80,S_OK,FALSE},
3033             {URL_SCHEME_HTTP,S_OK,FALSE},
3034             {URLZONE_INVALID,E_NOTIMPL,FALSE},
3035         }
3036     },
3037     {   "http://www.winehq.org?query=12&return=y", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
3038         {
3039             {"http://www.winehq.org?query=12&return=y",S_OK,FALSE},
3040             {"www.winehq.org",S_OK,FALSE},
3041             {"http://www.winehq.org?query=12&return=y",S_OK,FALSE},
3042             {"winehq.org",S_OK,FALSE},
3043             {"",S_FALSE,FALSE},
3044             {"",S_FALSE,FALSE},
3045             {"www.winehq.org",S_OK,FALSE},
3046             {"",S_FALSE,FALSE},
3047             {"",S_FALSE,FALSE},
3048             {"?query=12&return=y",S_OK,FALSE},
3049             {"?query=12&return=y",S_OK,FALSE},
3050             {"http://www.winehq.org?query=12&return=y",S_OK,FALSE},
3051             {"http",S_OK,FALSE},
3052             {"",S_FALSE,FALSE},
3053             {"",S_FALSE,FALSE}
3054         },
3055         {
3056             {Uri_HOST_DNS,S_OK,FALSE},
3057             {80,S_OK,FALSE},
3058             {URL_SCHEME_HTTP,S_OK,FALSE},
3059             {URLZONE_INVALID,E_NOTIMPL,FALSE},
3060         }
3061     },
3062     /* Unknown scheme types can have invalid % encoded data in fragments. */
3063     {   "zip://www.winehq.org/tests/#Te%xx", 0, S_OK, FALSE,
3064         {
3065             {"zip://www.winehq.org/tests/#Te%xx",S_OK,FALSE},
3066             {"www.winehq.org",S_OK,FALSE},
3067             {"zip://www.winehq.org/tests/#Te%xx",S_OK,FALSE},
3068             {"winehq.org",S_OK,FALSE},
3069             {"",S_FALSE,FALSE},
3070             {"#Te%xx",S_OK,FALSE},
3071             {"www.winehq.org",S_OK,FALSE},
3072             {"",S_FALSE,FALSE},
3073             {"/tests/",S_OK,FALSE},
3074             {"/tests/",S_OK,FALSE},
3075             {"",S_FALSE,FALSE},
3076             {"zip://www.winehq.org/tests/#Te%xx",S_OK,FALSE},
3077             {"zip",S_OK,FALSE},
3078             {"",S_FALSE,FALSE},
3079             {"",S_FALSE,FALSE}
3080         },
3081         {
3082             {Uri_HOST_DNS,S_OK,FALSE},
3083             {0,S_FALSE,FALSE},
3084             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
3085             {URLZONE_INVALID,E_NOTIMPL,FALSE},
3086         }
3087     },
3088     /* Forbidden characters in fragment aren't encoded for unknown schemes. */
3089     {   "zip://www.winehq.org/tests/#Te<|>", 0, S_OK, FALSE,
3090         {
3091             {"zip://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
3092             {"www.winehq.org",S_OK,FALSE},
3093             {"zip://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
3094             {"winehq.org",S_OK,FALSE},
3095             {"",S_FALSE,FALSE},
3096             {"#Te<|>",S_OK,FALSE},
3097             {"www.winehq.org",S_OK,FALSE},
3098             {"",S_FALSE,FALSE},
3099             {"/tests/",S_OK,FALSE},
3100             {"/tests/",S_OK,FALSE},
3101             {"",S_FALSE,FALSE},
3102             {"zip://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
3103             {"zip",S_OK,FALSE},
3104             {"",S_FALSE,FALSE},
3105             {"",S_FALSE,FALSE}
3106         },
3107         {
3108             {Uri_HOST_DNS,S_OK,FALSE},
3109             {0,S_FALSE,FALSE},
3110             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
3111             {URLZONE_INVALID,E_NOTIMPL,FALSE},
3112         }
3113     },
3114     /* Forbidden characters in the fragment are percent encoded for known schemes. */
3115     {   "http://www.winehq.org/tests/#Te<|>", 0, S_OK, FALSE,
3116         {
3117             {"http://www.winehq.org/tests/#Te%3C%7C%3E",S_OK,FALSE},
3118             {"www.winehq.org",S_OK,FALSE},
3119             {"http://www.winehq.org/tests/#Te%3C%7C%3E",S_OK,FALSE},
3120             {"winehq.org",S_OK,FALSE},
3121             {"",S_FALSE,FALSE},
3122             {"#Te%3C%7C%3E",S_OK,FALSE},
3123             {"www.winehq.org",S_OK,FALSE},
3124             {"",S_FALSE,FALSE},
3125             {"/tests/",S_OK,FALSE},
3126             {"/tests/",S_OK,FALSE},
3127             {"",S_FALSE,FALSE},
3128             {"http://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
3129             {"http",S_OK,FALSE},
3130             {"",S_FALSE,FALSE},
3131             {"",S_FALSE,FALSE}
3132         },
3133         {
3134             {Uri_HOST_DNS,S_OK,FALSE},
3135             {80,S_OK,FALSE},
3136             {URL_SCHEME_HTTP,S_OK,FALSE},
3137             {URLZONE_INVALID,E_NOTIMPL,FALSE},
3138         }
3139     },
3140     /* Forbidden characters aren't encoded in the fragment with this flag. */
3141     {   "http://www.winehq.org/tests/#Te<|>", Uri_CREATE_NO_DECODE_EXTRA_INFO, S_OK, FALSE,
3142         {
3143             {"http://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
3144             {"www.winehq.org",S_OK,FALSE},
3145             {"http://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
3146             {"winehq.org",S_OK,FALSE},
3147             {"",S_FALSE,FALSE},
3148             {"#Te<|>",S_OK,FALSE},
3149             {"www.winehq.org",S_OK,FALSE},
3150             {"",S_FALSE,FALSE},
3151             {"/tests/",S_OK,FALSE},
3152             {"/tests/",S_OK,FALSE},
3153             {"",S_FALSE,FALSE},
3154             {"http://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
3155             {"http",S_OK,FALSE},
3156             {"",S_FALSE,FALSE},
3157             {"",S_FALSE,FALSE}
3158         },
3159         {
3160             {Uri_HOST_DNS,S_OK,FALSE},
3161             {80,S_OK,FALSE},
3162             {URL_SCHEME_HTTP,S_OK,FALSE},
3163             {URLZONE_INVALID,E_NOTIMPL,FALSE},
3164         }
3165     },
3166     /* Forbidden characters aren't encoded in the fragment with this flag. */
3167     {   "http://www.winehq.org/tests/#Te<|>", Uri_CREATE_NO_ENCODE_FORBIDDEN_CHARACTERS, S_OK, FALSE,
3168         {
3169             {"http://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
3170             {"www.winehq.org",S_OK,FALSE},
3171             {"http://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
3172             {"winehq.org",S_OK,FALSE},
3173             {"",S_FALSE,FALSE},
3174             {"#Te<|>",S_OK,FALSE},
3175             {"www.winehq.org",S_OK,FALSE},
3176             {"",S_FALSE,FALSE},
3177             {"/tests/",S_OK,FALSE},
3178             {"/tests/",S_OK,FALSE},
3179             {"",S_FALSE,FALSE},
3180             {"http://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
3181             {"http",S_OK,FALSE},
3182             {"",S_FALSE,FALSE},
3183             {"",S_FALSE,FALSE}
3184         },
3185         {
3186             {Uri_HOST_DNS,S_OK,FALSE},
3187             {80,S_OK,FALSE},
3188             {URL_SCHEME_HTTP,S_OK,FALSE},
3189             {URLZONE_INVALID,E_NOTIMPL,FALSE},
3190         }
3191     },
3192     /* Percent encoded, unreserved characters aren't decoded for known scheme types. */
3193     {   "zip://www.winehq.org/tests/#Te%30%31%32", 0, S_OK, FALSE,
3194         {
3195             {"zip://www.winehq.org/tests/#Te%30%31%32",S_OK,FALSE},
3196             {"www.winehq.org",S_OK,FALSE},
3197             {"zip://www.winehq.org/tests/#Te%30%31%32",S_OK,FALSE},
3198             {"winehq.org",S_OK,FALSE},
3199             {"",S_FALSE,FALSE},
3200             {"#Te%30%31%32",S_OK,FALSE},
3201             {"www.winehq.org",S_OK,FALSE},
3202             {"",S_FALSE,FALSE},
3203             {"/tests/",S_OK,FALSE},
3204             {"/tests/",S_OK,FALSE},
3205             {"",S_FALSE,FALSE},
3206             {"zip://www.winehq.org/tests/#Te%30%31%32",S_OK,FALSE},
3207             {"zip",S_OK,FALSE},
3208             {"",S_FALSE,FALSE},
3209             {"",S_FALSE,FALSE}
3210         },
3211         {
3212             {Uri_HOST_DNS,S_OK,FALSE},
3213             {0,S_FALSE,FALSE},
3214             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
3215             {URLZONE_INVALID,E_NOTIMPL,FALSE},
3216         }
3217     },
3218     /* Percent encoded, unreserved characters are decoded for known schemes. */
3219     {   "http://www.winehq.org/tests/#Te%30%31%32", 0, S_OK, FALSE,
3220         {
3221             {"http://www.winehq.org/tests/#Te012",S_OK,FALSE},
3222             {"www.winehq.org",S_OK,FALSE},
3223             {"http://www.winehq.org/tests/#Te012",S_OK,FALSE},
3224             {"winehq.org",S_OK,FALSE},
3225             {"",S_FALSE,FALSE},
3226             {"#Te012",S_OK,FALSE},
3227             {"www.winehq.org",S_OK,FALSE},
3228             {"",S_FALSE,FALSE},
3229             {"/tests/",S_OK,FALSE},
3230             {"/tests/",S_OK,FALSE},
3231             {"",S_FALSE,FALSE},
3232             {"http://www.winehq.org/tests/#Te%30%31%32",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     /* Percent encoded, unreserved characters are decoded even if NO_CANONICALIZE is set. */
3245     {   "http://www.winehq.org/tests/#Te%30%31%32", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
3246         {
3247             {"http://www.winehq.org/tests/#Te012",S_OK,FALSE},
3248             {"www.winehq.org",S_OK,FALSE},
3249             {"http://www.winehq.org/tests/#Te012",S_OK,FALSE},
3250             {"winehq.org",S_OK,FALSE},
3251             {"",S_FALSE,FALSE},
3252             {"#Te012",S_OK,FALSE},
3253             {"www.winehq.org",S_OK,FALSE},
3254             {"",S_FALSE,FALSE},
3255             {"/tests/",S_OK,FALSE},
3256             {"/tests/",S_OK,FALSE},
3257             {"",S_FALSE,FALSE},
3258             {"http://www.winehq.org/tests/#Te%30%31%32",S_OK,FALSE},
3259             {"http",S_OK,FALSE},
3260             {"",S_FALSE,FALSE},
3261             {"",S_FALSE,FALSE}
3262         },
3263         {
3264             {Uri_HOST_DNS,S_OK,FALSE},
3265             {80,S_OK,FALSE},
3266             {URL_SCHEME_HTTP,S_OK,FALSE},
3267             {URLZONE_INVALID,E_NOTIMPL,FALSE},
3268         }
3269     },
3270     /* Percent encoded, unreserved characters aren't decoded when NO_DECODE_EXTRA is set. */
3271     {   "http://www.winehq.org/tests/#Te%30%31%32", Uri_CREATE_NO_DECODE_EXTRA_INFO, S_OK, FALSE,
3272         {
3273             {"http://www.winehq.org/tests/#Te%30%31%32",S_OK,FALSE},
3274             {"www.winehq.org",S_OK,FALSE},
3275             {"http://www.winehq.org/tests/#Te%30%31%32",S_OK,FALSE},
3276             {"winehq.org",S_OK,FALSE},
3277             {"",S_FALSE,FALSE},
3278             {"#Te%30%31%32",S_OK,FALSE},
3279             {"www.winehq.org",S_OK,FALSE},
3280             {"",S_FALSE,FALSE},
3281             {"/tests/",S_OK,FALSE},
3282             {"/tests/",S_OK,FALSE},
3283             {"",S_FALSE,FALSE},
3284             {"http://www.winehq.org/tests/#Te%30%31%32",S_OK,FALSE},
3285             {"http",S_OK,FALSE},
3286             {"",S_FALSE,FALSE},
3287             {"",S_FALSE,FALSE}
3288         },
3289         {
3290             {Uri_HOST_DNS,S_OK,FALSE},
3291             {80,S_OK,FALSE},
3292             {URL_SCHEME_HTTP,S_OK,FALSE},
3293             {URLZONE_INVALID,E_NOTIMPL,FALSE},
3294         }
3295     },
3296     /* Leading/Trailing whitespace is removed. */
3297     {   "    http://google.com/     ", 0, S_OK, FALSE,
3298         {
3299             {"http://google.com/",S_OK,FALSE},
3300             {"google.com",S_OK,FALSE},
3301             {"http://google.com/",S_OK,FALSE},
3302             {"google.com",S_OK,FALSE},
3303             {"",S_FALSE,FALSE},
3304             {"",S_FALSE,FALSE},
3305             {"google.com",S_OK,FALSE},
3306             {"",S_FALSE,FALSE},
3307             {"/",S_OK,FALSE},
3308             {"/",S_OK,FALSE},
3309             {"",S_FALSE,FALSE},
3310             {"http://google.com/",S_OK,FALSE},
3311             {"http",S_OK,FALSE},
3312             {"",S_FALSE,FALSE},
3313             {"",S_FALSE,FALSE}
3314         },
3315         {
3316             {Uri_HOST_DNS,S_OK,FALSE},
3317             {80,S_OK,FALSE},
3318             {URL_SCHEME_HTTP,S_OK,FALSE},
3319             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3320         }
3321     },
3322     {   "\t\t\r\nhttp\n://g\noogle.co\rm/\n\n\n", 0, S_OK, FALSE,
3323         {
3324             {"http://google.com/",S_OK,FALSE},
3325             {"google.com",S_OK,FALSE},
3326             {"http://google.com/",S_OK,FALSE},
3327             {"google.com",S_OK,FALSE},
3328             {"",S_FALSE,FALSE},
3329             {"",S_FALSE,FALSE},
3330             {"google.com",S_OK,FALSE},
3331             {"",S_FALSE,FALSE},
3332             {"/",S_OK,FALSE},
3333             {"/",S_OK,FALSE},
3334             {"",S_FALSE,FALSE},
3335             {"http://google.com/",S_OK,FALSE},
3336             {"http",S_OK,FALSE},
3337             {"",S_FALSE,FALSE},
3338             {"",S_FALSE,FALSE}
3339         },
3340         {
3341             {Uri_HOST_DNS,S_OK,FALSE},
3342             {80,S_OK,FALSE},
3343             {URL_SCHEME_HTTP,S_OK,FALSE},
3344             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3345         }
3346     },
3347     {   "http://g\noogle.co\rm/\n\n\n", Uri_CREATE_NO_PRE_PROCESS_HTML_URI, S_OK, FALSE,
3348         {
3349             {"http://g%0aoogle.co%0dm/%0A%0A%0A",S_OK,FALSE},
3350             {"g%0aoogle.co%0dm",S_OK,FALSE},
3351             {"http://g%0aoogle.co%0dm/%0A%0A%0A",S_OK,FALSE},
3352             {"g%0aoogle.co%0dm",S_OK,FALSE},
3353             {"",S_FALSE,FALSE},
3354             {"",S_FALSE,FALSE},
3355             {"g%0aoogle.co%0dm",S_OK,FALSE},
3356             {"",S_FALSE,FALSE},
3357             {"/%0A%0A%0A",S_OK,FALSE},
3358             {"/%0A%0A%0A",S_OK,FALSE},
3359             {"",S_FALSE,FALSE},
3360             {"http://g\noogle.co\rm/\n\n\n",S_OK,FALSE},
3361             {"http",S_OK,FALSE},
3362             {"",S_FALSE,FALSE},
3363             {"",S_FALSE,FALSE}
3364         },
3365         {
3366             {Uri_HOST_DNS,S_OK,FALSE},
3367             {80,S_OK,FALSE},
3368             {URL_SCHEME_HTTP,S_OK,FALSE},
3369             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3370         }
3371     },
3372     {   "zip://g\noogle.co\rm/\n\n\n", Uri_CREATE_NO_PRE_PROCESS_HTML_URI, S_OK, FALSE,
3373         {
3374             {"zip://g\noogle.co\rm/\n\n\n",S_OK,FALSE},
3375             {"g\noogle.co\rm",S_OK,FALSE},
3376             {"zip://g\noogle.co\rm/\n\n\n",S_OK,FALSE},
3377             {"g\noogle.co\rm",S_OK,FALSE},
3378             {"",S_FALSE,FALSE},
3379             {"",S_FALSE,FALSE},
3380             {"g\noogle.co\rm",S_OK,FALSE},
3381             {"",S_FALSE,FALSE},
3382             {"/\n\n\n",S_OK,FALSE},
3383             {"/\n\n\n",S_OK,FALSE},
3384             {"",S_FALSE,FALSE},
3385             {"zip://g\noogle.co\rm/\n\n\n",S_OK,FALSE},
3386             {"zip",S_OK,FALSE},
3387             {"",S_FALSE,FALSE},
3388             {"",S_FALSE,FALSE}
3389         },
3390         {
3391             {Uri_HOST_DNS,S_OK,FALSE},
3392             {0,S_FALSE,FALSE},
3393             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
3394             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3395         }
3396     },
3397     /* Since file URLs are usually hierarchical, it returns an empty string
3398      * for the absolute URI property since it was declared as an opaque URI.
3399      */
3400     {   "file:index.html", 0, S_OK, FALSE,
3401         {
3402             {"",S_FALSE,FALSE},
3403             {"",S_FALSE,FALSE},
3404             {"file:index.html",S_OK,FALSE},
3405             {"",S_FALSE,FALSE},
3406             {".html",S_OK,FALSE},
3407             {"",S_FALSE,FALSE},
3408             {"",S_FALSE,FALSE},
3409             {"",S_FALSE,FALSE},
3410             {"index.html",S_OK,FALSE},
3411             {"index.html",S_OK,FALSE},
3412             {"",S_FALSE,FALSE},
3413             {"file:index.html",S_OK,FALSE},
3414             {"file",S_OK,FALSE},
3415             {"",S_FALSE,FALSE},
3416             {"",S_FALSE,FALSE}
3417         },
3418         {
3419             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3420             {0,S_FALSE,FALSE},
3421             {URL_SCHEME_FILE,S_OK,FALSE},
3422             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3423         }
3424     },
3425     /* Doesn't have an absolute since it's opaque, but gets it port set. */
3426     {   "http:test.com/index.html", 0, S_OK, FALSE,
3427         {
3428             {"",S_FALSE,FALSE},
3429             {"",S_FALSE,FALSE},
3430             {"http:test.com/index.html",S_OK,FALSE},
3431             {"",S_FALSE,FALSE},
3432             {".html",S_OK,FALSE},
3433             {"",S_FALSE,FALSE},
3434             {"",S_FALSE,FALSE},
3435             {"",S_FALSE,FALSE},
3436             {"test.com/index.html",S_OK,FALSE},
3437             {"test.com/index.html",S_OK,FALSE},
3438             {"",S_FALSE,FALSE},
3439             {"http:test.com/index.html",S_OK,FALSE},
3440             {"http",S_OK,FALSE},
3441             {"",S_FALSE,FALSE},
3442             {"",S_FALSE,FALSE}
3443         },
3444         {
3445             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3446             {80,S_OK,FALSE},
3447             {URL_SCHEME_HTTP,S_OK,FALSE},
3448             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3449         }
3450     },
3451     {   "ftp:test.com/index.html", 0, S_OK, FALSE,
3452         {
3453             {"",S_FALSE,FALSE},
3454             {"",S_FALSE,FALSE},
3455             {"ftp:test.com/index.html",S_OK,FALSE},
3456             {"",S_FALSE,FALSE},
3457             {".html",S_OK,FALSE},
3458             {"",S_FALSE,FALSE},
3459             {"",S_FALSE,FALSE},
3460             {"",S_FALSE,FALSE},
3461             {"test.com/index.html",S_OK,FALSE},
3462             {"test.com/index.html",S_OK,FALSE},
3463             {"",S_FALSE,FALSE},
3464             {"ftp:test.com/index.html",S_OK,FALSE},
3465             {"ftp",S_OK,FALSE},
3466             {"",S_FALSE,FALSE},
3467             {"",S_FALSE,FALSE}
3468         },
3469         {
3470             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3471             {21,S_OK,FALSE},
3472             {URL_SCHEME_FTP,S_OK,FALSE},
3473             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3474         }
3475     },
3476     {   "file://C|/test.mp3", 0, S_OK, FALSE,
3477         {
3478             {"file:///C:/test.mp3",S_OK,FALSE},
3479             {"",S_FALSE,FALSE},
3480             {"file:///C:/test.mp3",S_OK,FALSE},
3481             {"",S_FALSE,FALSE},
3482             {".mp3",S_OK,FALSE},
3483             {"",S_FALSE,FALSE},
3484             {"",S_FALSE,FALSE},
3485             {"",S_FALSE,FALSE},
3486             {"/C:/test.mp3",S_OK,FALSE},
3487             {"/C:/test.mp3",S_OK,FALSE},
3488             {"",S_FALSE,FALSE},
3489             {"file://C|/test.mp3",S_OK,FALSE},
3490             {"file",S_OK,FALSE},
3491             {"",S_FALSE,FALSE},
3492             {"",S_FALSE,FALSE}
3493         },
3494         {
3495             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3496             {0,S_FALSE,FALSE},
3497             {URL_SCHEME_FILE,S_OK,FALSE},
3498             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3499         }
3500     },
3501     {   "file:///C|/test.mp3", 0, S_OK, FALSE,
3502         {
3503             {"file:///C:/test.mp3",S_OK,FALSE},
3504             {"",S_FALSE,FALSE},
3505             {"file:///C:/test.mp3",S_OK,FALSE},
3506             {"",S_FALSE,FALSE},
3507             {".mp3",S_OK,FALSE},
3508             {"",S_FALSE,FALSE},
3509             {"",S_FALSE,FALSE},
3510             {"",S_FALSE,FALSE},
3511             {"/C:/test.mp3",S_OK,FALSE},
3512             {"/C:/test.mp3",S_OK,FALSE},
3513             {"",S_FALSE,FALSE},
3514             {"file:///C|/test.mp3",S_OK,FALSE},
3515             {"file",S_OK,FALSE},
3516             {"",S_FALSE,FALSE},
3517             {"",S_FALSE,FALSE}
3518         },
3519         {
3520             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3521             {0,S_FALSE,FALSE},
3522             {URL_SCHEME_FILE,S_OK,FALSE},
3523             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3524         }
3525     },
3526     /* Extra '/' isn't added before "c:" since USE_DOS_PATH is set and '/' are converted
3527      * to '\\'.
3528      */
3529     {   "file://c:/dir/index.html", Uri_CREATE_FILE_USE_DOS_PATH, 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     /* Extra '/' after "file://" is removed. */
3555     {   "file:///c:/dir/index.html", Uri_CREATE_FILE_USE_DOS_PATH, S_OK, FALSE,
3556         {
3557             {"file://c:\\dir\\index.html",S_OK,FALSE},
3558             {"",S_FALSE,FALSE},
3559             {"file://c:\\dir\\index.html",S_OK,FALSE},
3560             {"",S_FALSE,FALSE},
3561             {".html",S_OK,FALSE},
3562             {"",S_FALSE,FALSE},
3563             {"",S_FALSE,FALSE},
3564             {"",S_FALSE,FALSE},
3565             {"c:\\dir\\index.html",S_OK,FALSE},
3566             {"c:\\dir\\index.html",S_OK,FALSE},
3567             {"",S_FALSE,FALSE},
3568             {"file:///c:/dir/index.html",S_OK,FALSE},
3569             {"file",S_OK,FALSE},
3570             {"",S_FALSE,FALSE},
3571             {"",S_FALSE,FALSE}
3572         },
3573         {
3574             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3575             {0,S_FALSE,FALSE},
3576             {URL_SCHEME_FILE,S_OK,FALSE},
3577             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3578         }
3579     },
3580     /* Allow more characters when Uri_CREATE_FILE_USE_DOS_PATH is specified */
3581     {   "file:///c:/dir\\%%61%20%5Fname/file%2A.html", Uri_CREATE_FILE_USE_DOS_PATH, S_OK, FALSE,
3582         {
3583             {"file://c:\\dir\\%a _name\\file*.html",S_OK,FALSE},
3584             {"",S_FALSE,FALSE},
3585             {"file://c:\\dir\\%a _name\\file*.html",S_OK,FALSE},
3586             {"",S_FALSE,FALSE},
3587             {".html",S_OK,FALSE},
3588             {"",S_FALSE,FALSE},
3589             {"",S_FALSE,FALSE},
3590             {"",S_FALSE,FALSE},
3591             {"c:\\dir\\%a _name\\file*.html",S_OK,FALSE},
3592             {"c:\\dir\\%a _name\\file*.html",S_OK,FALSE},
3593             {"",S_FALSE,FALSE},
3594             {"file:///c:/dir\\%%61%20%5Fname/file%2A.html",S_OK,FALSE},
3595             {"file",S_OK,FALSE},
3596             {"",S_FALSE,FALSE},
3597             {"",S_FALSE,FALSE}
3598         },
3599         {
3600             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3601             {0,S_FALSE,FALSE},
3602             {URL_SCHEME_FILE,S_OK,FALSE},
3603             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3604         }
3605     },
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     /* The backslashes after the scheme name are converted to forward slashes. */
3632     {   "file:\\\\c:\\dir\\index.html", Uri_CREATE_FILE_USE_DOS_PATH, S_OK, FALSE,
3633         {
3634             {"file://c:\\dir\\index.html",S_OK,FALSE},
3635             {"",S_FALSE,FALSE},
3636             {"file://c:\\dir\\index.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\\index.html",S_OK,FALSE},
3643             {"c:\\dir\\index.html",S_OK,FALSE},
3644             {"",S_FALSE,FALSE},
3645             {"file:\\\\c:\\dir\\index.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     {   "file:\\\\c:/dir/index.html", 0, S_OK, FALSE,
3658         {
3659             {"file:///c:/dir/index.html",S_OK,FALSE},
3660             {"",S_FALSE,FALSE},
3661             {"file:///c:/dir/index.html",S_OK,FALSE},
3662             {"",S_FALSE,FALSE},
3663             {".html",S_OK,FALSE},
3664             {"",S_FALSE,FALSE},
3665             {"",S_FALSE,FALSE},
3666             {"",S_FALSE,FALSE},
3667             {"/c:/dir/index.html",S_OK,FALSE},
3668             {"/c:/dir/index.html",S_OK,FALSE},
3669             {"",S_FALSE,FALSE},
3670             {"file:\\\\c:/dir/index.html",S_OK,FALSE},
3671             {"file",S_OK,FALSE},
3672             {"",S_FALSE,FALSE},
3673             {"",S_FALSE,FALSE}
3674         },
3675         {
3676             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3677             {0,S_FALSE,FALSE},
3678             {URL_SCHEME_FILE,S_OK,FALSE},
3679             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3680         }
3681     },
3682     {   "http:\\\\google.com", 0, S_OK, FALSE,
3683         {
3684             {"http://google.com/",S_OK,FALSE},
3685             {"google.com",S_OK,FALSE},
3686             {"http://google.com/",S_OK,FALSE},
3687             {"google.com",S_OK,FALSE},
3688             {"",S_FALSE,FALSE},
3689             {"",S_FALSE,FALSE},
3690             {"google.com",S_OK,FALSE},
3691             {"",S_FALSE,FALSE},
3692             {"/",S_OK,FALSE},
3693             {"/",S_OK,FALSE},
3694             {"",S_FALSE,FALSE},
3695             {"http:\\\\google.com",S_OK,FALSE},
3696             {"http",S_OK,FALSE},
3697             {"",S_FALSE,FALSE},
3698             {"",S_FALSE,FALSE}
3699         },
3700         {
3701             {Uri_HOST_DNS,S_OK,FALSE},
3702             {80,S_OK,FALSE},
3703             {URL_SCHEME_HTTP,S_OK,FALSE},
3704             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3705         }
3706     },
3707     /* the "\\\\" aren't converted to "//" for unknown scheme types and it's considered opaque. */
3708     {   "zip:\\\\google.com", 0, S_OK, FALSE,
3709         {
3710             {"zip:\\\\google.com",S_OK,FALSE},
3711             {"",S_FALSE,FALSE},
3712             {"zip:\\\\google.com",S_OK,FALSE},
3713             {"",S_FALSE,FALSE},
3714             {".com",S_OK,FALSE},
3715             {"",S_FALSE,FALSE},
3716             {"",S_FALSE,FALSE},
3717             {"",S_FALSE,FALSE},
3718             {"\\\\google.com",S_OK,FALSE},
3719             {"\\\\google.com",S_OK,FALSE},
3720             {"",S_FALSE,FALSE},
3721             {"zip:\\\\google.com",S_OK,FALSE},
3722             {"zip",S_OK,FALSE},
3723             {"",S_FALSE,FALSE},
3724             {"",S_FALSE,FALSE}
3725         },
3726         {
3727             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3728             {0,S_FALSE,FALSE},
3729             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
3730             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3731         }
3732     },
3733     /* Dot segments aren't removed. */
3734     {   "file://c:\\dir\\../..\\./index.html", Uri_CREATE_FILE_USE_DOS_PATH, S_OK, FALSE,
3735         {
3736             {"file://c:\\dir\\..\\..\\.\\index.html",S_OK,FALSE},
3737             {"",S_FALSE,FALSE},
3738             {"file://c:\\dir\\..\\..\\.\\index.html",S_OK,FALSE},
3739             {"",S_FALSE,FALSE},
3740             {".html",S_OK,FALSE},
3741             {"",S_FALSE,FALSE},
3742             {"",S_FALSE,FALSE},
3743             {"",S_FALSE,FALSE},
3744             {"c:\\dir\\..\\..\\.\\index.html",S_OK,FALSE},
3745             {"c:\\dir\\..\\..\\.\\index.html",S_OK,FALSE},
3746             {"",S_FALSE,FALSE},
3747             {"file://c:\\dir\\../..\\./index.html",S_OK,FALSE},
3748             {"file",S_OK,FALSE},
3749             {"",S_FALSE,FALSE},
3750             {"",S_FALSE,FALSE}
3751         },
3752         {
3753             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3754             {0,S_FALSE,FALSE},
3755             {URL_SCHEME_FILE,S_OK,FALSE},
3756             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3757         }
3758     },
3759     /* Forbidden characters aren't percent encoded. */
3760     {   "file://c:\\dir\\i^|ndex.html", Uri_CREATE_FILE_USE_DOS_PATH, S_OK, FALSE,
3761         {
3762             {"file://c:\\dir\\i^|ndex.html",S_OK,FALSE},
3763             {"",S_FALSE,FALSE},
3764             {"file://c:\\dir\\i^|ndex.html",S_OK,FALSE},
3765             {"",S_FALSE,FALSE},
3766             {".html",S_OK,FALSE},
3767             {"",S_FALSE,FALSE},
3768             {"",S_FALSE,FALSE},
3769             {"",S_FALSE,FALSE},
3770             {"c:\\dir\\i^|ndex.html",S_OK,FALSE},
3771             {"c:\\dir\\i^|ndex.html",S_OK,FALSE},
3772             {"",S_FALSE,FALSE},
3773             {"file://c:\\dir\\i^|ndex.html",S_OK,FALSE},
3774             {"file",S_OK,FALSE},
3775             {"",S_FALSE,FALSE},
3776             {"",S_FALSE,FALSE}
3777         },
3778         {
3779             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3780             {0,S_FALSE,FALSE},
3781             {URL_SCHEME_FILE,S_OK,FALSE},
3782             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3783         }
3784     },
3785     /* The '\' are still converted to '/' even though it's an opaque file URI. */
3786     {   "file:c:\\dir\\../..\\index.html", 0, S_OK, FALSE,
3787         {
3788             {"",S_FALSE,FALSE},
3789             {"",S_FALSE,FALSE},
3790             {"file:c:/dir/../../index.html",S_OK,FALSE},
3791             {"",S_FALSE,FALSE},
3792             {".html",S_OK,FALSE},
3793             {"",S_FALSE,FALSE},
3794             {"",S_FALSE,FALSE},
3795             {"",S_FALSE,FALSE},
3796             {"c:/dir/../../index.html",S_OK,FALSE},
3797             {"c:/dir/../../index.html",S_OK,FALSE},
3798             {"",S_FALSE,FALSE},
3799             {"file:c:\\dir\\../..\\index.html",S_OK,FALSE},
3800             {"file",S_OK,FALSE},
3801             {"",S_FALSE,FALSE},
3802             {"",S_FALSE,FALSE}
3803         },
3804         {
3805             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3806             {0,S_FALSE,FALSE},
3807             {URL_SCHEME_FILE,S_OK,FALSE},
3808             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3809         }
3810     },
3811     /* '/' are still converted to '\' even though it's an opaque URI. */
3812     {   "file:c:/dir\\../..\\index.html", Uri_CREATE_FILE_USE_DOS_PATH, S_OK, FALSE,
3813         {
3814             {"",S_FALSE,FALSE},
3815             {"",S_FALSE,FALSE},
3816             {"file:c:\\dir\\..\\..\\index.html",S_OK,FALSE},
3817             {"",S_FALSE,FALSE},
3818             {".html",S_OK,FALSE},
3819             {"",S_FALSE,FALSE},
3820             {"",S_FALSE,FALSE},
3821             {"",S_FALSE,FALSE},
3822             {"c:\\dir\\..\\..\\index.html",S_OK,FALSE},
3823             {"c:\\dir\\..\\..\\index.html",S_OK,FALSE},
3824             {"",S_FALSE,FALSE},
3825             {"file:c:/dir\\../..\\index.html",S_OK,FALSE},
3826             {"file",S_OK,FALSE},
3827             {"",S_FALSE,FALSE},
3828             {"",S_FALSE,FALSE}
3829         },
3830         {
3831             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3832             {0,S_FALSE,FALSE},
3833             {URL_SCHEME_FILE,S_OK,FALSE},
3834             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3835         }
3836     },
3837     /* Forbidden characters aren't percent encoded. */
3838     {   "file:c:\\in^|dex.html", Uri_CREATE_FILE_USE_DOS_PATH, S_OK, FALSE,
3839         {
3840             {"",S_FALSE,FALSE},
3841             {"",S_FALSE,FALSE},
3842             {"file:c:\\in^|dex.html",S_OK,FALSE},
3843             {"",S_FALSE,FALSE},
3844             {".html",S_OK,FALSE},
3845             {"",S_FALSE,FALSE},
3846             {"",S_FALSE,FALSE},
3847             {"",S_FALSE,FALSE},
3848             {"c:\\in^|dex.html",S_OK,FALSE},
3849             {"c:\\in^|dex.html",S_OK,FALSE},
3850             {"",S_FALSE,FALSE},
3851             {"file:c:\\in^|dex.html",S_OK,FALSE},
3852             {"file",S_OK,FALSE},
3853             {"",S_FALSE,FALSE},
3854             {"",S_FALSE,FALSE}
3855         },
3856         {
3857             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3858             {0,S_FALSE,FALSE},
3859             {URL_SCHEME_FILE,S_OK,FALSE},
3860             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3861         }
3862     },
3863     /* Doesn't have a UserName since the ':' appears at the beginning of the
3864      * userinfo section.
3865      */
3866     {   "http://:password@gov.uk", 0, S_OK, FALSE,
3867         {
3868             {"http://:password@gov.uk/",S_OK,FALSE},
3869             {":password@gov.uk",S_OK,FALSE},
3870             {"http://gov.uk/",S_OK,FALSE},
3871             {"",S_FALSE,FALSE},
3872             {"",S_FALSE,FALSE},
3873             {"",S_FALSE,FALSE},
3874             {"gov.uk",S_OK,FALSE},
3875             {"password",S_OK,FALSE},
3876             {"/",S_OK,FALSE},
3877             {"/",S_OK,FALSE},
3878             {"",S_FALSE,FALSE},
3879             {"http://:password@gov.uk",S_OK,FALSE},
3880             {"http",S_OK,FALSE},
3881             {":password",S_OK,FALSE},
3882             {"",S_FALSE,FALSE}
3883         },
3884         {
3885             {Uri_HOST_DNS,S_OK,FALSE},
3886             {80,S_OK,FALSE},
3887             {URL_SCHEME_HTTP,S_OK,FALSE},
3888             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3889         }
3890     },
3891     /* Has a UserName since the userinfo section doesn't contain a password. */
3892     {   "http://@gov.uk", 0, S_OK, FALSE,
3893         {
3894             {"http://gov.uk/",S_OK,FALSE,"http://@gov.uk/"},
3895             {"@gov.uk",S_OK,FALSE},
3896             {"http://gov.uk/",S_OK,FALSE},
3897             {"",S_FALSE,FALSE},
3898             {"",S_FALSE,FALSE},
3899             {"",S_FALSE,FALSE},
3900             {"gov.uk",S_OK,FALSE},
3901             {"",S_FALSE,FALSE},
3902             {"/",S_OK,FALSE},
3903             {"/",S_OK,FALSE},
3904             {"",S_FALSE,FALSE},
3905             {"http://@gov.uk",S_OK,FALSE},
3906             {"http",S_OK,FALSE},
3907             {"",S_OK,FALSE},
3908             {"",S_OK,FALSE}
3909         },
3910         {
3911             {Uri_HOST_DNS,S_OK,FALSE},
3912             {80,S_OK,FALSE},
3913             {URL_SCHEME_HTTP,S_OK,FALSE},
3914             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3915         }
3916     },
3917     /* ":@" not included in the absolute URI. */
3918     {   "http://:@gov.uk", 0, S_OK, FALSE,
3919         {
3920             {"http://gov.uk/",S_OK,FALSE,"http://:@gov.uk/"},
3921             {":@gov.uk",S_OK,FALSE},
3922             {"http://gov.uk/",S_OK,FALSE},
3923             {"",S_FALSE,FALSE},
3924             {"",S_FALSE,FALSE},
3925             {"",S_FALSE,FALSE},
3926             {"gov.uk",S_OK,FALSE},
3927             {"",S_OK,FALSE},
3928             {"/",S_OK,FALSE},
3929             {"/",S_OK,FALSE},
3930             {"",S_FALSE,FALSE},
3931             {"http://:@gov.uk",S_OK,FALSE},
3932             {"http",S_OK,FALSE},
3933             {":",S_OK,FALSE},
3934             {"",S_FALSE,FALSE}
3935         },
3936         {
3937             {Uri_HOST_DNS,S_OK,FALSE},
3938             {80,S_OK,FALSE},
3939             {URL_SCHEME_HTTP,S_OK,FALSE},
3940             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3941         }
3942     },
3943     /* '@' is included because it's an unknown scheme type. */
3944     {   "zip://@gov.uk", 0, S_OK, FALSE,
3945         {
3946             {"zip://@gov.uk/",S_OK,FALSE},
3947             {"@gov.uk",S_OK,FALSE},
3948             {"zip://@gov.uk/",S_OK,FALSE},
3949             {"",S_FALSE,FALSE},
3950             {"",S_FALSE,FALSE},
3951             {"",S_FALSE,FALSE},
3952             {"gov.uk",S_OK,FALSE},
3953             {"",S_FALSE,FALSE},
3954             {"/",S_OK,FALSE},
3955             {"/",S_OK,FALSE},
3956             {"",S_FALSE,FALSE},
3957             {"zip://@gov.uk",S_OK,FALSE},
3958             {"zip",S_OK,FALSE},
3959             {"",S_OK,FALSE},
3960             {"",S_OK,FALSE}
3961         },
3962         {
3963             {Uri_HOST_DNS,S_OK,FALSE},
3964             {0,S_FALSE,FALSE},
3965             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
3966             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3967         }
3968     },
3969     /* ":@" are included because it's an unknown scheme type. */
3970     {   "zip://:@gov.uk", 0, S_OK, FALSE,
3971         {
3972             {"zip://:@gov.uk/",S_OK,FALSE},
3973             {":@gov.uk",S_OK,FALSE},
3974             {"zip://:@gov.uk/",S_OK,FALSE},
3975             {"",S_FALSE,FALSE},
3976             {"",S_FALSE,FALSE},
3977             {"",S_FALSE,FALSE},
3978             {"gov.uk",S_OK,FALSE},
3979             {"",S_OK,FALSE},
3980             {"/",S_OK,FALSE},
3981             {"/",S_OK,FALSE},
3982             {"",S_FALSE,FALSE},
3983             {"zip://:@gov.uk",S_OK,FALSE},
3984             {"zip",S_OK,FALSE},
3985             {":",S_OK,FALSE},
3986             {"",S_FALSE,FALSE}
3987         },
3988         {
3989             {Uri_HOST_DNS,S_OK,FALSE},
3990             {0,S_FALSE,FALSE},
3991             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
3992             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3993         }
3994     },
3995     {   "about:blank", 0, S_OK, FALSE,
3996         {
3997             {"about:blank",S_OK,FALSE},
3998             {"",S_FALSE,FALSE},
3999             {"about:blank",S_OK,FALSE},
4000             {"",S_FALSE,FALSE},
4001             {"",S_FALSE,FALSE},
4002             {"",S_FALSE,FALSE},
4003             {"",S_FALSE,FALSE},
4004             {"",S_FALSE,FALSE},
4005             {"blank",S_OK,FALSE},
4006             {"blank",S_OK,FALSE},
4007             {"",S_FALSE,FALSE},
4008             {"about:blank",S_OK,FALSE},
4009             {"about",S_OK,FALSE},
4010             {"",S_FALSE,FALSE},
4011             {"",S_FALSE,FALSE}
4012         },
4013         {
4014             {Uri_HOST_UNKNOWN,S_OK,FALSE},
4015             {0,S_FALSE,FALSE},
4016             {URL_SCHEME_ABOUT,S_OK,FALSE},
4017             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4018         }
4019     },
4020     {   "mk:@MSITStore:C:\\Program Files/AutoCAD 2008\\Help/acad_acg.chm::/WSfacf1429558a55de1a7524c1004e616f8b-322b.htm",0,S_OK,FALSE,
4021         {
4022             {"mk:@MSITStore:C:\\Program%20Files/AutoCAD%202008\\Help/acad_acg.chm::/WSfacf1429558a55de1a7524c1004e616f8b-322b.htm",S_OK,FALSE},
4023             {"",S_FALSE,FALSE},
4024             {"mk:@MSITStore:C:\\Program%20Files/AutoCAD%202008\\Help/acad_acg.chm::/WSfacf1429558a55de1a7524c1004e616f8b-322b.htm",S_OK,FALSE},
4025             {"",S_FALSE,FALSE},
4026             {".htm",S_OK,FALSE},
4027             {"",S_FALSE,FALSE},
4028             {"",S_FALSE,FALSE},
4029             {"",S_FALSE,FALSE},
4030             {"@MSITStore:C:\\Program%20Files/AutoCAD%202008\\Help/acad_acg.chm::/WSfacf1429558a55de1a7524c1004e616f8b-322b.htm",S_OK,FALSE},
4031             {"@MSITStore:C:\\Program%20Files/AutoCAD%202008\\Help/acad_acg.chm::/WSfacf1429558a55de1a7524c1004e616f8b-322b.htm",S_OK,FALSE},
4032             {"",S_FALSE,FALSE},
4033             {"mk:@MSITStore:C:\\Program Files/AutoCAD 2008\\Help/acad_acg.chm::/WSfacf1429558a55de1a7524c1004e616f8b-322b.htm",S_OK,FALSE},
4034             {"mk",S_OK,FALSE},
4035             {"",S_FALSE,FALSE},
4036             {"",S_FALSE,FALSE}
4037         },
4038         {
4039             {Uri_HOST_UNKNOWN,S_OK,FALSE},
4040             {0,S_FALSE,FALSE},
4041             {URL_SCHEME_MK,S_OK,FALSE},
4042             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4043         }
4044     },
4045     {   "mk:@MSITStore:Z:\\home\\test\\chm\\silqhelp.chm::/thesilqquickstartguide.htm",0,S_OK,FALSE,
4046         {
4047             {"mk:@MSITStore:Z:\\home\\test\\chm\\silqhelp.chm::/thesilqquickstartguide.htm",S_OK,FALSE},
4048             {"",S_FALSE,FALSE},
4049             {"mk:@MSITStore:Z:\\home\\test\\chm\\silqhelp.chm::/thesilqquickstartguide.htm",S_OK,FALSE},
4050             {"",S_FALSE,FALSE},
4051             {".htm",S_OK,FALSE},
4052             {"",S_FALSE,FALSE},
4053             {"",S_FALSE,FALSE},
4054             {"",S_FALSE,FALSE},
4055             {"@MSITStore:Z:\\home\\test\\chm\\silqhelp.chm::/thesilqquickstartguide.htm",S_OK,FALSE},
4056             {"@MSITStore:Z:\\home\\test\\chm\\silqhelp.chm::/thesilqquickstartguide.htm",S_OK,FALSE},
4057             {"",S_FALSE,FALSE},
4058             {"mk:@MSITStore:Z:\\home\\test\\chm\\silqhelp.chm::/thesilqquickstartguide.htm",S_OK,FALSE},
4059             {"mk",S_OK,FALSE},
4060             {"",S_FALSE,FALSE},
4061             {"",S_FALSE,FALSE}
4062         },
4063         {
4064             {Uri_HOST_UNKNOWN,S_OK,FALSE},
4065             {0,S_FALSE,FALSE},
4066             {URL_SCHEME_MK,S_OK,FALSE},
4067             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4068         }
4069     },
4070     /* Two '\' are added to the URI when USE_DOS_PATH is set, and it's a UNC path. */
4071     {   "file://server/dir/index.html", Uri_CREATE_FILE_USE_DOS_PATH, S_OK, FALSE,
4072         {
4073             {"file://\\\\server\\dir\\index.html",S_OK,FALSE},
4074             {"server",S_OK,FALSE},
4075             {"file://\\\\server\\dir\\index.html",S_OK,FALSE},
4076             {"",S_FALSE,FALSE},
4077             {".html",S_OK,FALSE},
4078             {"",S_FALSE,FALSE},
4079             {"server",S_OK,FALSE},
4080             {"",S_FALSE,FALSE},
4081             {"\\dir\\index.html",S_OK,FALSE},
4082             {"\\dir\\index.html",S_OK,FALSE},
4083             {"",S_FALSE,FALSE},
4084             {"file://server/dir/index.html",S_OK,FALSE},
4085             {"file",S_OK,FALSE},
4086             {"",S_FALSE,FALSE},
4087             {"",S_FALSE,FALSE}
4088         },
4089         {
4090             {Uri_HOST_DNS,S_OK,FALSE},
4091             {0,S_FALSE,FALSE},
4092             {URL_SCHEME_FILE,S_OK,FALSE},
4093             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4094         }
4095     },
4096     /* When CreateUri generates an IUri, it still displays the default port in the
4097      * authority.
4098      */
4099     {   "http://google.com:80/", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
4100         {
4101             {"http://google.com:80/",S_OK,FALSE},
4102             {"google.com:80",S_OK,FALSE},
4103             {"http://google.com:80/",S_OK,FALSE},
4104             {"google.com",S_OK,FALSE},
4105             {"",S_FALSE,FALSE},
4106             {"",S_FALSE,FALSE},
4107             {"google.com",S_OK,FALSE},
4108             {"",S_FALSE,FALSE},
4109             {"/",S_OK,FALSE},
4110             {"/",S_OK,FALSE},
4111             {"",S_FALSE,FALSE},
4112             {"http://google.com:80/",S_OK,FALSE},
4113             {"http",S_OK,FALSE},
4114             {"",S_FALSE,FALSE},
4115             {"",S_FALSE,FALSE}
4116         },
4117         {
4118             {Uri_HOST_DNS,S_OK,FALSE},
4119             {80,S_OK,FALSE},
4120             {URL_SCHEME_HTTP,S_OK,FALSE},
4121             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4122         }
4123     },
4124     /* For res URIs the host is everything up until the first '/'. */
4125     {   "res://C:\\dir\\file.exe/DATA/test.html", 0, S_OK, FALSE,
4126         {
4127             {"res://C:\\dir\\file.exe/DATA/test.html",S_OK,FALSE},
4128             {"C:\\dir\\file.exe",S_OK,FALSE},
4129             {"res://C:\\dir\\file.exe/DATA/test.html",S_OK,FALSE},
4130             {"",S_FALSE,FALSE},
4131             {".html",S_OK,FALSE},
4132             {"",S_FALSE,FALSE},
4133             {"C:\\dir\\file.exe",S_OK,FALSE},
4134             {"",S_FALSE,FALSE},
4135             {"/DATA/test.html",S_OK,FALSE},
4136             {"/DATA/test.html",S_OK,FALSE},
4137             {"",S_FALSE,FALSE},
4138             {"res://C:\\dir\\file.exe/DATA/test.html",S_OK,FALSE},
4139             {"res",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_RES,S_OK,FALSE},
4147             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4148         }
4149     },
4150     /* Res URI can contain a '|' in the host name. */
4151     {   "res://c:\\di|r\\file.exe/test", 0, S_OK, FALSE,
4152         {
4153             {"res://c:\\di|r\\file.exe/test",S_OK,FALSE},
4154             {"c:\\di|r\\file.exe",S_OK,FALSE},
4155             {"res://c:\\di|r\\file.exe/test",S_OK,FALSE},
4156             {"",S_FALSE,FALSE},
4157             {"",S_FALSE,FALSE},
4158             {"",S_FALSE,FALSE},
4159             {"c:\\di|r\\file.exe",S_OK,FALSE},
4160             {"",S_FALSE,FALSE},
4161             {"/test",S_OK,FALSE},
4162             {"/test",S_OK,FALSE},
4163             {"",S_FALSE,FALSE},
4164             {"res://c:\\di|r\\file.exe/test",S_OK,FALSE},
4165             {"res",S_OK,FALSE},
4166             {"",S_FALSE,FALSE},
4167             {"",S_FALSE,FALSE}
4168         },
4169         {
4170             {Uri_HOST_UNKNOWN,S_OK,FALSE},
4171             {0,S_FALSE,FALSE},
4172             {URL_SCHEME_RES,S_OK,FALSE},
4173             {URLZONE_INVALID,E_NOTIMPL,FALSE},
4174         }
4175     },
4176     /* Res URIs can have invalid percent encoded values. */
4177     {   "res://c:\\dir%xx\\file.exe/test", 0, S_OK, FALSE,
4178         {
4179             {"res://c:\\dir%xx\\file.exe/test",S_OK,FALSE},
4180             {"c:\\dir%xx\\file.exe",S_OK,FALSE},
4181             {"res://c:\\dir%xx\\file.exe/test",S_OK,FALSE},
4182             {"",S_FALSE,FALSE},
4183             {"",S_FALSE,FALSE},
4184             {"",S_FALSE,FALSE},
4185             {"c:\\dir%xx\\file.exe",S_OK,FALSE},
4186             {"",S_FALSE,FALSE},
4187             {"/test",S_OK,FALSE},
4188             {"/test",S_OK,FALSE},
4189             {"",S_FALSE,FALSE},
4190             {"res://c:\\dir%xx\\file.exe/test",S_OK,FALSE},
4191             {"res",S_OK,FALSE},
4192             {"",S_FALSE,FALSE},
4193             {"",S_FALSE,FALSE}
4194         },
4195         {
4196             {Uri_HOST_UNKNOWN,S_OK,FALSE},
4197             {0,S_FALSE,FALSE},
4198             {URL_SCHEME_RES,S_OK,FALSE},
4199             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4200         }
4201     },
4202     /* Res doesn't get forbidden characters percent encoded in its path. */
4203     {   "res://c:\\test/tes<|>t", 0, S_OK, FALSE,
4204         {
4205             {"res://c:\\test/tes<|>t",S_OK,FALSE},
4206             {"c:\\test",S_OK,FALSE},
4207             {"res://c:\\test/tes<|>t",S_OK,FALSE},
4208             {"",S_FALSE,FALSE},
4209             {"",S_FALSE,FALSE},
4210             {"",S_FALSE,FALSE},
4211             {"c:\\test",S_OK,FALSE},
4212             {"",S_FALSE,FALSE},
4213             {"/tes<|>t",S_OK,FALSE},
4214             {"/tes<|>t",S_OK,FALSE},
4215             {"",S_FALSE,FALSE},
4216             {"res://c:\\test/tes<|>t",S_OK,FALSE},
4217             {"res",S_OK,FALSE},
4218             {"",S_FALSE,FALSE},
4219             {"",S_FALSE,FALSE}
4220         },
4221         {
4222             {Uri_HOST_UNKNOWN,S_OK,FALSE},
4223             {0,S_FALSE,FALSE},
4224             {URL_SCHEME_RES,S_OK,FALSE},
4225             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4226         }
4227     },
4228     {   "mk:@MSITStore:Z:\\dir\\test.chm::/html/../images/xxx.jpg", 0, S_OK, FALSE,
4229         {
4230             {"mk:@MSITStore:Z:\\dir\\test.chm::/images/xxx.jpg",S_OK,FALSE},
4231             {"",S_FALSE,FALSE},
4232             {"mk:@MSITStore:Z:\\dir\\test.chm::/images/xxx.jpg",S_OK,FALSE},
4233             {"",S_FALSE,FALSE},
4234             {".jpg",S_OK,FALSE},
4235             {"",S_FALSE,FALSE},
4236             {"",S_FALSE,FALSE},
4237             {"",S_FALSE,FALSE},
4238             {"@MSITStore:Z:\\dir\\test.chm::/images/xxx.jpg",S_OK,FALSE},
4239             {"@MSITStore:Z:\\dir\\test.chm::/images/xxx.jpg",S_OK,FALSE},
4240             {"",S_FALSE,FALSE},
4241             {"mk:@MSITStore:Z:\\dir\\test.chm::/html/../images/xxx.jpg",S_OK,FALSE},
4242             {"mk",S_OK,FALSE},
4243             {"",S_FALSE,FALSE},
4244             {"",S_FALSE,FALSE}
4245         },
4246         {
4247             {Uri_HOST_UNKNOWN,S_OK,FALSE},
4248             {0,S_FALSE,FALSE},
4249             {URL_SCHEME_MK,S_OK,FALSE},
4250             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4251         }
4252     },
4253     {   "mk:@MSITStore:Z:\\dir\\test.chm::/html/../images/xxx.jpg", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
4254         {
4255             {"mk:@MSITStore:Z:\\dir\\test.chm::/html/../images/xxx.jpg",S_OK,FALSE},
4256             {"",S_FALSE,FALSE},
4257             {"mk:@MSITStore:Z:\\dir\\test.chm::/html/../images/xxx.jpg",S_OK,FALSE},
4258             {"",S_FALSE,FALSE},
4259             {".jpg",S_OK,FALSE},
4260             {"",S_FALSE,FALSE},
4261             {"",S_FALSE,FALSE},
4262             {"",S_FALSE,FALSE},
4263             {"@MSITStore:Z:\\dir\\test.chm::/html/../images/xxx.jpg",S_OK,FALSE},
4264             {"@MSITStore:Z:\\dir\\test.chm::/html/../images/xxx.jpg",S_OK,FALSE},
4265             {"",S_FALSE,FALSE},
4266             {"mk:@MSITStore:Z:\\dir\\test.chm::/html/../images/xxx.jpg",S_OK,FALSE},
4267             {"mk",S_OK,FALSE},
4268             {"",S_FALSE,FALSE},
4269             {"",S_FALSE,FALSE}
4270         },
4271         {
4272             {Uri_HOST_UNKNOWN,S_OK,FALSE},
4273             {0,S_FALSE,FALSE},
4274             {URL_SCHEME_MK,S_OK,FALSE},
4275             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4276         }
4277     },
4278     {   "xx:@MSITStore:Z:\\dir\\test.chm::/html/../images/xxx.jpg", 0, S_OK, FALSE,
4279         {
4280             {"xx:@MSITStore:Z:\\dir\\test.chm::/html/../images/xxx.jpg",S_OK,FALSE},
4281             {"",S_FALSE,FALSE},
4282             {"xx:@MSITStore:Z:\\dir\\test.chm::/html/../images/xxx.jpg",S_OK,FALSE},
4283             {"",S_FALSE,FALSE},
4284             {".jpg",S_OK,FALSE},
4285             {"",S_FALSE,FALSE},
4286             {"",S_FALSE,FALSE},
4287             {"",S_FALSE,FALSE},
4288             {"@MSITStore:Z:\\dir\\test.chm::/html/../images/xxx.jpg",S_OK,FALSE},
4289             {"@MSITStore:Z:\\dir\\test.chm::/html/../images/xxx.jpg",S_OK,FALSE},
4290             {"",S_FALSE,FALSE},
4291             {"xx:@MSITStore:Z:\\dir\\test.chm::/html/../images/xxx.jpg",S_OK,FALSE},
4292             {"xx",S_OK,FALSE},
4293             {"",S_FALSE,FALSE},
4294             {"",S_FALSE,FALSE}
4295         },
4296         {
4297             {Uri_HOST_UNKNOWN,S_OK,FALSE},
4298             {0,S_FALSE,FALSE},
4299             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
4300             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4301         }
4302     },
4303     {   "mk:@MSITStore:Z:\\dir\\test.chm::/html/../../images/xxx.jpg", 0, S_OK, FALSE,
4304         {
4305             {"mk:@MSITStore:Z:\\dir\\images/xxx.jpg",S_OK,FALSE},
4306             {"",S_FALSE,FALSE},
4307             {"mk:@MSITStore:Z:\\dir\\images/xxx.jpg",S_OK,FALSE},
4308             {"",S_FALSE,FALSE},
4309             {".jpg",S_OK,FALSE},
4310             {"",S_FALSE,FALSE},
4311             {"",S_FALSE,FALSE},
4312             {"",S_FALSE,FALSE},
4313             {"@MSITStore:Z:\\dir\\images/xxx.jpg",S_OK,FALSE},
4314             {"@MSITStore:Z:\\dir\\images/xxx.jpg",S_OK,FALSE},
4315             {"",S_FALSE,FALSE},
4316             {"mk:@MSITStore:Z:\\dir\\test.chm::/html/../../images/xxx.jpg",S_OK,FALSE},
4317             {"mk",S_OK,FALSE},
4318             {"",S_FALSE,FALSE},
4319             {"",S_FALSE,FALSE}
4320         },
4321         {
4322             {Uri_HOST_UNKNOWN,S_OK,FALSE},
4323             {0,S_FALSE,FALSE},
4324             {URL_SCHEME_MK,S_OK,FALSE},
4325             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4326         }
4327     },
4328     {   "mk:@MSITStore:Z:\\dir\\dir2\\..\\test.chm::/html/../../images/xxx.jpg", 0, S_OK, FALSE,
4329         {
4330             {"mk:@MSITStore:Z:\\dir\\images/xxx.jpg",S_OK,FALSE},
4331             {"",S_FALSE,FALSE},
4332             {"mk:@MSITStore:Z:\\dir\\images/xxx.jpg",S_OK,FALSE},
4333             {"",S_FALSE,FALSE},
4334             {".jpg",S_OK,FALSE},
4335             {"",S_FALSE,FALSE},
4336             {"",S_FALSE,FALSE},
4337             {"",S_FALSE,FALSE},
4338             {"@MSITStore:Z:\\dir\\images/xxx.jpg",S_OK,FALSE},
4339             {"@MSITStore:Z:\\dir\\images/xxx.jpg",S_OK,FALSE},
4340             {"",S_FALSE,FALSE},
4341             {"mk:@MSITStore:Z:\\dir\\dir2\\..\\test.chm::/html/../../images/xxx.jpg",S_OK,FALSE},
4342             {"mk",S_OK,FALSE},
4343             {"",S_FALSE,FALSE},
4344             {"",S_FALSE,FALSE}
4345         },
4346         {
4347             {Uri_HOST_UNKNOWN,S_OK,FALSE},
4348             {0,S_FALSE,FALSE},
4349             {URL_SCHEME_MK,S_OK,FALSE},
4350             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4351         }
4352     },
4353     {   "mk:@MSITStore:Z:\\dir\\test.chm::/html/../../../../images/xxx.jpg", 0, S_OK, FALSE,
4354         {
4355             {"mk:images/xxx.jpg",S_OK,FALSE},
4356             {"",S_FALSE,FALSE},
4357             {"mk:images/xxx.jpg",S_OK,FALSE},
4358             {"",S_FALSE,FALSE},
4359             {".jpg",S_OK,FALSE},
4360             {"",S_FALSE,FALSE},
4361             {"",S_FALSE,FALSE},
4362             {"",S_FALSE,FALSE},
4363             {"images/xxx.jpg",S_OK,FALSE},
4364             {"images/xxx.jpg",S_OK,FALSE},
4365             {"",S_FALSE,FALSE},
4366             {"mk:@MSITStore:Z:\\dir\\test.chm::/html/../../../../images/xxx.jpg",S_OK,FALSE},
4367             {"mk",S_OK,FALSE},
4368             {"",S_FALSE,FALSE},
4369             {"",S_FALSE,FALSE}
4370         },
4371         {
4372             {Uri_HOST_UNKNOWN,S_OK,FALSE},
4373             {0,S_FALSE,FALSE},
4374             {URL_SCHEME_MK,S_OK,FALSE},
4375             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4376         }
4377     },
4378     {   "", Uri_CREATE_ALLOW_RELATIVE, S_OK, FALSE,
4379         {
4380             {"",S_OK,FALSE},
4381             {"",S_FALSE,FALSE},
4382             {"",S_OK,FALSE},
4383             {"",S_FALSE,FALSE},
4384             {"",S_FALSE,FALSE},
4385             {"",S_FALSE,FALSE},
4386             {"",S_FALSE,FALSE},
4387             {"",S_FALSE,FALSE},
4388             {"",S_OK,FALSE},
4389             {"",S_OK,FALSE},
4390             {"",S_FALSE,FALSE},
4391             {"",S_OK,FALSE},
4392             {"",S_FALSE,FALSE},
4393             {"",S_FALSE,FALSE},
4394             {"",S_FALSE,FALSE}
4395         },
4396         {
4397             {Uri_HOST_UNKNOWN,S_OK,FALSE},
4398             {0,S_FALSE,FALSE},
4399             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
4400             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4401         }
4402     },
4403     {   " \t ", Uri_CREATE_ALLOW_RELATIVE, S_OK, FALSE,
4404         {
4405             {"",S_OK,FALSE},
4406             {"",S_FALSE,FALSE},
4407             {"",S_OK,FALSE},
4408             {"",S_FALSE,FALSE},
4409             {"",S_FALSE,FALSE},
4410             {"",S_FALSE,FALSE},
4411             {"",S_FALSE,FALSE},
4412             {"",S_FALSE,FALSE},
4413             {"",S_OK,FALSE},
4414             {"",S_OK,FALSE},
4415             {"",S_FALSE,FALSE},
4416             {"",S_OK,FALSE},
4417             {"",S_FALSE,FALSE},
4418             {"",S_FALSE,FALSE},
4419             {"",S_FALSE,FALSE}
4420         },
4421         {
4422             {Uri_HOST_UNKNOWN,S_OK,FALSE},
4423             {0,S_FALSE,FALSE},
4424             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
4425             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4426         }
4427     },
4428     {   "javascript:void", 0, S_OK, FALSE,
4429         {
4430             {"javascript:void",S_OK},
4431             {"",S_FALSE},
4432             {"javascript:void",S_OK},
4433             {"",S_FALSE},
4434             {"",S_FALSE},
4435             {"",S_FALSE},
4436             {"",S_FALSE},
4437             {"",S_FALSE},
4438             {"void",S_OK},
4439             {"void",S_OK},
4440             {"",S_FALSE},
4441             {"javascript:void",S_OK},
4442             {"javascript",S_OK},
4443             {"",S_FALSE},
4444             {"",S_FALSE}
4445         },
4446         {
4447             {Uri_HOST_UNKNOWN,S_OK},
4448             {0,S_FALSE},
4449             {URL_SCHEME_JAVASCRIPT,S_OK},
4450             {URLZONE_INVALID,E_NOTIMPL}
4451         }
4452     },
4453     {   "javascript://undefined", 0, S_OK, FALSE,
4454         {
4455             {"javascript://undefined",S_OK},
4456             {"",S_FALSE},
4457             {"javascript://undefined",S_OK},
4458             {"",S_FALSE},
4459             {"",S_FALSE},
4460             {"",S_FALSE},
4461             {"",S_FALSE},
4462             {"",S_FALSE},
4463             {"//undefined",S_OK},
4464             {"//undefined",S_OK},
4465             {"",S_FALSE},
4466             {"javascript://undefined",S_OK},
4467             {"javascript",S_OK},
4468             {"",S_FALSE},
4469             {"",S_FALSE}
4470         },
4471         {
4472             {Uri_HOST_UNKNOWN,S_OK},
4473             {0,S_FALSE},
4474             {URL_SCHEME_JAVASCRIPT,S_OK},
4475             {URLZONE_INVALID,E_NOTIMPL}
4476         }
4477     },
4478     {   "JavaSCript:escape('/\\?#?')", 0, S_OK, FALSE,
4479         {
4480             {"javascript:escape('/\\?#?')",S_OK},
4481             {"",S_FALSE},
4482             {"javascript:escape('/\\?#?')",S_OK},
4483             {"",S_FALSE},
4484             {"",S_FALSE},
4485             {"",S_FALSE},
4486             {"",S_FALSE},
4487             {"",S_FALSE},
4488             {"escape('/\\?#?')",S_OK},
4489             {"escape('/\\?#?')",S_OK},
4490             {"",S_FALSE},
4491             {"JavaSCript:escape('/\\?#?')",S_OK},
4492             {"javascript",S_OK},
4493             {"",S_FALSE},
4494             {"",S_FALSE}
4495         },
4496         {
4497             {Uri_HOST_UNKNOWN,S_OK},
4498             {0,S_FALSE},
4499             {URL_SCHEME_JAVASCRIPT,S_OK},
4500             {URLZONE_INVALID,E_NOTIMPL}
4501         }
4502     },
4503     {   "*://google.com", 0, S_OK, FALSE,
4504         {
4505             {"*:google.com/",S_OK,FALSE},
4506             {"google.com",S_OK},
4507             {"*:google.com/",S_OK,FALSE},
4508             {"google.com",S_OK,FALSE},
4509             {"",S_FALSE,FALSE},
4510             {"",S_FALSE,FALSE},
4511             {"google.com",S_OK,FALSE},
4512             {"",S_FALSE,FALSE},
4513             {"/",S_OK,FALSE},
4514             {"/",S_OK,FALSE},
4515             {"",S_FALSE,FALSE},
4516             {"*://google.com",S_OK,FALSE},
4517             {"*",S_OK,FALSE},
4518             {"",S_FALSE,FALSE},
4519             {"",S_FALSE,FALSE}
4520         },
4521         {
4522             {Uri_HOST_DNS,S_OK,FALSE},
4523             {0,S_FALSE,FALSE},
4524             {URL_SCHEME_WILDCARD,S_OK,FALSE},
4525             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4526         }
4527     },
4528     {   "mk:@MSITSTORE:C:\\Some\\Bogus\\Path.chm::/subdir/file.txt",0,S_OK,FALSE,
4529         {
4530             {"mk:@MSITSTORE:C:\\Some\\Bogus\\Path.chm::/subdir/file.txt",S_OK},
4531             {"",S_FALSE},
4532             {"mk:@MSITSTORE:C:\\Some\\Bogus\\Path.chm::/subdir/file.txt",S_OK},
4533             {"",S_FALSE},
4534             {".txt",S_OK},
4535             {"",S_FALSE},
4536             {"",S_FALSE},
4537             {"",S_FALSE},
4538             {"@MSITSTORE:C:\\Some\\Bogus\\Path.chm::/subdir/file.txt",S_OK},
4539             {"@MSITSTORE:C:\\Some\\Bogus\\Path.chm::/subdir/file.txt",S_OK},
4540             {"",S_FALSE},
4541             {"mk:@MSITSTORE:C:\\Some\\Bogus\\Path.chm::/subdir/file.txt",S_OK},
4542             {"mk",S_OK},
4543             {"",S_FALSE},
4544             {"",S_FALSE}
4545         },
4546         {
4547             {Uri_HOST_UNKNOWN,S_OK},
4548             {0,S_FALSE},
4549             {URL_SCHEME_MK,S_OK},
4550             {URLZONE_INVALID,E_NOTIMPL}
4551         }
4552     },
4553     {   "gopher://test.winehq.org:151/file.txt",0,S_OK,FALSE,
4554         {
4555             {"gopher://test.winehq.org:151/file.txt",S_OK},
4556             {"test.winehq.org:151",S_OK},
4557             {"gopher://test.winehq.org:151/file.txt",S_OK},
4558             {"winehq.org",S_OK},
4559             {".txt",S_OK},
4560             {"",S_FALSE},
4561             {"test.winehq.org",S_OK},
4562             {"",S_FALSE},
4563             {"/file.txt",S_OK},
4564             {"/file.txt",S_OK},
4565             {"",S_FALSE},
4566             {"gopher://test.winehq.org:151/file.txt",S_OK},
4567             {"gopher",S_OK},
4568             {"",S_FALSE},
4569             {"",S_FALSE}
4570         },
4571         {
4572             {Uri_HOST_DNS,S_OK},
4573             {151,S_OK},
4574             {URL_SCHEME_GOPHER,S_OK},
4575             {URLZONE_INVALID,E_NOTIMPL}
4576         }
4577     },
4578     {   "//host.com/path/file.txt?query", Uri_CREATE_ALLOW_RELATIVE, S_OK, FALSE,
4579         {
4580             {"//host.com/path/file.txt?query",S_OK},
4581             {"host.com",S_OK},
4582             {"//host.com/path/file.txt?query",S_OK},
4583             {"host.com",S_OK},
4584             {".txt",S_OK},
4585             {"",S_FALSE},
4586             {"host.com",S_OK},
4587             {"",S_FALSE},
4588             {"/path/file.txt",S_OK},
4589             {"/path/file.txt?query",S_OK},
4590             {"?query",S_OK},
4591             {"//host.com/path/file.txt?query",S_OK},
4592             {"",S_FALSE},
4593             {"",S_FALSE},
4594             {"",S_FALSE},
4595         },
4596         {
4597             {Uri_HOST_DNS,S_OK},
4598             {0,S_FALSE},
4599             {URL_SCHEME_UNKNOWN,S_OK},
4600             {URLZONE_INVALID,E_NOTIMPL}
4601         }
4602     },
4603     {   "//host/path/file.txt?query", Uri_CREATE_ALLOW_RELATIVE, S_OK, FALSE,
4604         {
4605             {"//host/path/file.txt?query",S_OK},
4606             {"host",S_OK},
4607             {"//host/path/file.txt?query",S_OK},
4608             {"",S_FALSE},
4609             {".txt",S_OK},
4610             {"",S_FALSE},
4611             {"host",S_OK},
4612             {"",S_FALSE},
4613             {"/path/file.txt",S_OK},
4614             {"/path/file.txt?query",S_OK},
4615             {"?query",S_OK},
4616             {"//host/path/file.txt?query",S_OK},
4617             {"",S_FALSE},
4618             {"",S_FALSE},
4619             {"",S_FALSE},
4620         },
4621         {
4622             {Uri_HOST_DNS,S_OK},
4623             {0,S_FALSE},
4624             {URL_SCHEME_UNKNOWN,S_OK},
4625             {URLZONE_INVALID,E_NOTIMPL}
4626         }
4627     },
4628     {   "//host", Uri_CREATE_ALLOW_RELATIVE, S_OK, FALSE,
4629         {
4630             {"//host/",S_OK},
4631             {"host",S_OK},
4632             {"//host/",S_OK},
4633             {"",S_FALSE},
4634             {"",S_FALSE},
4635             {"",S_FALSE},
4636             {"host",S_OK},
4637             {"",S_FALSE},
4638             {"/",S_OK},
4639             {"/",S_OK},
4640             {"",S_FALSE},
4641             {"//host",S_OK},
4642             {"",S_FALSE},
4643             {"",S_FALSE},
4644             {"",S_FALSE},
4645         },
4646         {
4647             {Uri_HOST_DNS,S_OK},
4648             {0,S_FALSE},
4649             {URL_SCHEME_UNKNOWN,S_OK},
4650             {URLZONE_INVALID,E_NOTIMPL}
4651         }
4652     },
4653     {   "mailto://", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
4654         {
4655             {"mailto:",S_OK},
4656             {"",S_FALSE},
4657             {"mailto:",S_OK},
4658             {"",S_FALSE},
4659             {"",S_FALSE},
4660             {"",S_FALSE},
4661             {"",S_FALSE},
4662             {"",S_FALSE},
4663             {"",S_FALSE},
4664             {"",S_FALSE},
4665             {"",S_FALSE},
4666             {"mailto://",S_OK,FALSE,"mailto:"},
4667             {"mailto",S_OK},
4668             {"",S_FALSE},
4669             {"",S_FALSE}
4670         },
4671         {
4672             {Uri_HOST_UNKNOWN,S_OK},
4673             {0,S_FALSE},
4674             {URL_SCHEME_MAILTO,S_OK},
4675             {URLZONE_INVALID,E_NOTIMPL}
4676         }
4677     },
4678     {   "mailto://a@b.com", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
4679         {
4680             {"mailto:a@b.com",S_OK},
4681             {"",S_FALSE},
4682             {"mailto:a@b.com",S_OK},
4683             {"",S_FALSE},
4684             {".com",S_OK},
4685             {"",S_FALSE},
4686             {"",S_FALSE},
4687             {"",S_FALSE},
4688             {"a@b.com",S_OK},
4689             {"a@b.com",S_OK},
4690             {"",S_FALSE},
4691             {"mailto://a@b.com",S_OK,FALSE,"mailto:a@b.com"},
4692             {"mailto",S_OK},
4693             {"",S_FALSE},
4694             {"",S_FALSE}
4695         },
4696         {
4697             {Uri_HOST_UNKNOWN,S_OK},
4698             {0,S_FALSE},
4699             {URL_SCHEME_MAILTO,S_OK},
4700             {URLZONE_INVALID,E_NOTIMPL}
4701         }
4702     },
4703     {   "c:\\test file.html", Uri_CREATE_FILE_USE_DOS_PATH|Uri_CREATE_ALLOW_IMPLICIT_FILE_SCHEME, S_OK, FALSE,
4704         {
4705             {"file://c:\\test file.html",S_OK,FALSE},
4706             {"",S_FALSE,FALSE},
4707             {"file://c:\\test file.html",S_OK,FALSE},
4708             {"",S_FALSE,FALSE},
4709             {".html",S_OK,FALSE},
4710             {"",S_FALSE,FALSE},
4711             {"",S_FALSE,FALSE},
4712             {"",S_FALSE,FALSE},
4713             {"c:\\test file.html",S_OK,FALSE},
4714             {"c:\\test file.html",S_OK,FALSE},
4715             {"",S_FALSE,FALSE},
4716             {"c:\\test file.html",S_OK,FALSE},
4717             {"file",S_OK,FALSE},
4718             {"",S_FALSE,FALSE},
4719             {"",S_FALSE,FALSE}
4720         },
4721         {
4722             {Uri_HOST_UNKNOWN,S_OK,FALSE},
4723             {0,S_FALSE,FALSE},
4724             {URL_SCHEME_FILE,S_OK,FALSE},
4725             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4726         }
4727     },
4728     {   "c:\\test%20file.html", Uri_CREATE_FILE_USE_DOS_PATH|Uri_CREATE_ALLOW_IMPLICIT_FILE_SCHEME, S_OK, FALSE,
4729         {
4730             {"file://c:\\test%20file.html",S_OK,FALSE},
4731             {"",S_FALSE,FALSE},
4732             {"file://c:\\test%20file.html",S_OK,FALSE},
4733             {"",S_FALSE,FALSE},
4734             {".html",S_OK,FALSE},
4735             {"",S_FALSE,FALSE},
4736             {"",S_FALSE,FALSE},
4737             {"",S_FALSE,FALSE},
4738             {"c:\\test%20file.html",S_OK,FALSE},
4739             {"c:\\test%20file.html",S_OK,FALSE},
4740             {"",S_FALSE,FALSE},
4741             {"c:\\test%20file.html",S_OK,FALSE},
4742             {"file",S_OK,FALSE},
4743             {"",S_FALSE,FALSE},
4744             {"",S_FALSE,FALSE}
4745         },
4746         {
4747             {Uri_HOST_UNKNOWN,S_OK,FALSE},
4748             {0,S_FALSE,FALSE},
4749             {URL_SCHEME_FILE,S_OK,FALSE},
4750             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4751         }
4752     },
4753     {   "c:\\test file.html", Uri_CREATE_ALLOW_IMPLICIT_FILE_SCHEME, S_OK, FALSE,
4754         {
4755             {"file:///c:/test%20file.html",S_OK,FALSE},
4756             {"",S_FALSE,FALSE},
4757             {"file:///c:/test%20file.html",S_OK,FALSE},
4758             {"",S_FALSE,FALSE},
4759             {".html",S_OK,FALSE},
4760             {"",S_FALSE,FALSE},
4761             {"",S_FALSE,FALSE},
4762             {"",S_FALSE,FALSE},
4763             {"/c:/test%20file.html",S_OK,FALSE},
4764             {"/c:/test%20file.html",S_OK,FALSE},
4765             {"",S_FALSE,FALSE},
4766             {"c:\\test file.html",S_OK,FALSE},
4767             {"file",S_OK,FALSE},
4768             {"",S_FALSE,FALSE},
4769             {"",S_FALSE,FALSE}
4770         },
4771         {
4772             {Uri_HOST_UNKNOWN,S_OK,FALSE},
4773             {0,S_FALSE,FALSE},
4774             {URL_SCHEME_FILE,S_OK,FALSE},
4775             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4776         }
4777     },
4778     {   "c:\\test%20file.html", Uri_CREATE_ALLOW_IMPLICIT_FILE_SCHEME, S_OK, FALSE,
4779         {
4780             {"file:///c:/test%2520file.html",S_OK,FALSE},
4781             {"",S_FALSE,FALSE},
4782             {"file:///c:/test%2520file.html",S_OK,FALSE},
4783             {"",S_FALSE,FALSE},
4784             {".html",S_OK,FALSE},
4785             {"",S_FALSE,FALSE},
4786             {"",S_FALSE,FALSE},
4787             {"",S_FALSE,FALSE},
4788             {"/c:/test%2520file.html",S_OK,FALSE},
4789             {"/c:/test%2520file.html",S_OK,FALSE},
4790             {"",S_FALSE,FALSE},
4791             {"c:\\test%20file.html",S_OK,FALSE},
4792             {"file",S_OK,FALSE},
4793             {"",S_FALSE,FALSE},
4794             {"",S_FALSE,FALSE}
4795         },
4796         {
4797             {Uri_HOST_UNKNOWN,S_OK,FALSE},
4798             {0,S_FALSE,FALSE},
4799             {URL_SCHEME_FILE,S_OK,FALSE},
4800             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4801         }
4802     },
4803     /* Path with Unicode characters. Unicode characters should not be encoded */
4804     {/* "http://127.0.0.1/测试/test.txt" with Chinese in UTF-8 encoding */
4805         "http://127.0.0.1/\xE6\xB5\x8B\xE8\xAF\x95/test.txt", 0, S_OK, FALSE,
4806         {
4807             {"http://127.0.0.1/\xE6\xB5\x8B\xE8\xAF\x95/test.txt",S_OK,FALSE},
4808             {"127.0.0.1",S_OK,FALSE},
4809             {"http://127.0.0.1/\xE6\xB5\x8B\xE8\xAF\x95/test.txt",S_OK,FALSE},
4810             {"",S_FALSE,FALSE},
4811             {".txt",S_OK,FALSE},
4812             {"",S_FALSE,FALSE},
4813             {"127.0.0.1",S_OK,FALSE},
4814             {"",S_FALSE,FALSE},
4815             {"/\xE6\xB5\x8B\xE8\xAF\x95/test.txt",S_OK,FALSE},
4816             {"/\xE6\xB5\x8B\xE8\xAF\x95/test.txt",S_OK,FALSE},
4817             {"",S_FALSE,FALSE},
4818             {"http://127.0.0.1/\xE6\xB5\x8B\xE8\xAF\x95/test.txt",S_OK,FALSE},
4819             {"http",S_OK,FALSE},
4820             {"",S_FALSE,FALSE},
4821             {"",S_FALSE,FALSE}
4822         },
4823         {
4824             {Uri_HOST_IPV4,S_OK,FALSE},
4825             {80,S_OK,FALSE},
4826             {URL_SCHEME_HTTP,S_OK,FALSE},
4827             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4828         }
4829     },
4830     {   "file:\xE6\xB5\x8B\xE8\xAF\x95.html", 0, S_OK, FALSE,
4831         {
4832             {"",S_FALSE,FALSE},
4833             {"",S_FALSE,FALSE},
4834             {"file:\xE6\xB5\x8B\xE8\xAF\x95.html",S_OK,FALSE},
4835             {"",S_FALSE,FALSE},
4836             {".html",S_OK,FALSE},
4837             {"",S_FALSE,FALSE},
4838             {"",S_FALSE,FALSE},
4839             {"",S_FALSE,FALSE},
4840             {"\xE6\xB5\x8B\xE8\xAF\x95.html",S_OK,FALSE},
4841             {"\xE6\xB5\x8B\xE8\xAF\x95.html",S_OK,FALSE},
4842             {"",S_FALSE,FALSE},
4843             {"file:\xE6\xB5\x8B\xE8\xAF\x95.html",S_OK,FALSE},
4844             {"file",S_OK,FALSE},
4845             {"",S_FALSE,FALSE},
4846             {"",S_FALSE,FALSE}
4847         },
4848         {
4849             {Uri_HOST_UNKNOWN,S_OK,FALSE},
4850             {0,S_FALSE,FALSE},
4851             {URL_SCHEME_FILE,S_OK,FALSE},
4852             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4853         }
4854     },
4855     /* Username with Unicode characters. Unicode characters should not be encoded */
4856     {   "ftp://\xE6\xB5\x8B\xE8\xAF\x95:wine@ftp.winehq.org:9999/dir/foobar.txt", 0, S_OK, FALSE,
4857         {
4858             {"ftp://\xE6\xB5\x8B\xE8\xAF\x95:wine@ftp.winehq.org:9999/dir/foobar.txt",S_OK,FALSE},
4859             {"\xE6\xB5\x8B\xE8\xAF\x95:wine@ftp.winehq.org:9999",S_OK,FALSE},
4860             {"ftp://ftp.winehq.org:9999/dir/foobar.txt",S_OK,FALSE},
4861             {"winehq.org",S_OK,FALSE},
4862             {".txt",S_OK,FALSE},
4863             {"",S_FALSE,FALSE},
4864             {"ftp.winehq.org",S_OK,FALSE},
4865             {"wine",S_OK,FALSE},
4866             {"/dir/foobar.txt",S_OK,FALSE},
4867             {"/dir/foobar.txt",S_OK,FALSE},
4868             {"",S_FALSE,FALSE},
4869             {"ftp://\xE6\xB5\x8B\xE8\xAF\x95:wine@ftp.winehq.org:9999/dir/foobar.txt",S_OK,FALSE},
4870             {"ftp",S_OK,FALSE},
4871             {"\xE6\xB5\x8B\xE8\xAF\x95:wine",S_OK,FALSE},
4872             {"\xE6\xB5\x8B\xE8\xAF\x95",S_OK,FALSE}
4873         },
4874         {
4875             {Uri_HOST_DNS,S_OK,FALSE},
4876             {9999,S_OK,FALSE},
4877             {URL_SCHEME_FTP,S_OK,FALSE},
4878             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4879         }
4880     },
4881     /* Password with Unicode characters. Unicode characters should not be encoded */
4882     {   "ftp://winepass:\xE6\xB5\x8B\xE8\xAF\x95@ftp.winehq.org:9999/dir/foobar.txt", 0, S_OK, FALSE,
4883         {
4884             {"ftp://winepass:\xE6\xB5\x8B\xE8\xAF\x95@ftp.winehq.org:9999/dir/foobar.txt",S_OK,FALSE},
4885             {"winepass:\xE6\xB5\x8B\xE8\xAF\x95@ftp.winehq.org:9999",S_OK,FALSE},
4886             {"ftp://ftp.winehq.org:9999/dir/foobar.txt",S_OK,FALSE},
4887             {"winehq.org",S_OK,FALSE},
4888             {".txt",S_OK,FALSE},
4889             {"",S_FALSE,FALSE},
4890             {"ftp.winehq.org",S_OK,FALSE},
4891             {"\xE6\xB5\x8B\xE8\xAF\x95",S_OK,FALSE},
4892             {"/dir/foobar.txt",S_OK,FALSE},
4893             {"/dir/foobar.txt",S_OK,FALSE},
4894             {"",S_FALSE,FALSE},
4895             {"ftp://winepass:\xE6\xB5\x8B\xE8\xAF\x95@ftp.winehq.org:9999/dir/foobar.txt",S_OK,FALSE},
4896             {"ftp",S_OK,FALSE},
4897             {"winepass:\xE6\xB5\x8B\xE8\xAF\x95",S_OK,FALSE},
4898             {"winepass",S_OK,FALSE}
4899         },
4900         {
4901             {Uri_HOST_DNS,S_OK,FALSE},
4902             {9999,S_OK,FALSE},
4903             {URL_SCHEME_FTP,S_OK,FALSE},
4904             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4905         }
4906     },
4907     /* Query with Unicode characters. Unicode characters should not be encoded */
4908     {   "http://www.winehq.org/tests/..?query=\xE6\xB5\x8B\xE8\xAF\x95&return=y", 0, S_OK, FALSE,
4909         {
4910             {"http://www.winehq.org/?query=\xE6\xB5\x8B\xE8\xAF\x95&return=y",S_OK,FALSE},
4911             {"www.winehq.org",S_OK,FALSE},
4912             {"http://www.winehq.org/?query=\xE6\xB5\x8B\xE8\xAF\x95&return=y",S_OK,FALSE},
4913             {"winehq.org",S_OK,FALSE},
4914             {"",S_FALSE,FALSE},
4915             {"",S_FALSE,FALSE},
4916             {"www.winehq.org",S_OK,FALSE},
4917             {"",S_FALSE,FALSE},
4918             {"/",S_OK,FALSE},
4919             {"/?query=\xE6\xB5\x8B\xE8\xAF\x95&return=y",S_OK,FALSE},
4920             {"?query=\xE6\xB5\x8B\xE8\xAF\x95&return=y",S_OK,FALSE},
4921             {"http://www.winehq.org/tests/..?query=\xE6\xB5\x8B\xE8\xAF\x95&return=y",S_OK,FALSE},
4922             {"http",S_OK,FALSE},
4923             {"",S_FALSE,FALSE},
4924             {"",S_FALSE,FALSE}
4925         },
4926         {
4927             {Uri_HOST_DNS,S_OK,FALSE},
4928             {80,S_OK,FALSE},
4929             {URL_SCHEME_HTTP,S_OK,FALSE},
4930             {URLZONE_INVALID,E_NOTIMPL,FALSE},
4931         }
4932     },
4933     /* Fragment with Unicode characters. Unicode characters should not be encoded */
4934     {   "http://www.winehq.org/tests/#\xE6\xB5\x8B\xE8\xAF\x95", 0, S_OK, FALSE,
4935         {
4936             {"http://www.winehq.org/tests/#\xE6\xB5\x8B\xE8\xAF\x95",S_OK,FALSE},
4937             {"www.winehq.org",S_OK,FALSE},
4938             {"http://www.winehq.org/tests/#\xE6\xB5\x8B\xE8\xAF\x95",S_OK,FALSE},
4939             {"winehq.org",S_OK,FALSE},
4940             {"",S_FALSE,FALSE},
4941             {"#\xE6\xB5\x8B\xE8\xAF\x95",S_OK,FALSE},
4942             {"www.winehq.org",S_OK,FALSE},
4943             {"",S_FALSE,FALSE},
4944             {"/tests/",S_OK,FALSE},
4945             {"/tests/",S_OK,FALSE},
4946             {"",S_FALSE,FALSE},
4947             {"http://www.winehq.org/tests/#\xE6\xB5\x8B\xE8\xAF\x95",S_OK,FALSE},
4948             {"http",S_OK,FALSE},
4949             {"",S_FALSE,FALSE},
4950             {"",S_FALSE,FALSE}
4951         },
4952         {
4953             {Uri_HOST_DNS,S_OK,FALSE},
4954             {80,S_OK,FALSE},
4955             {URL_SCHEME_HTTP,S_OK,FALSE},
4956             {URLZONE_INVALID,E_NOTIMPL,FALSE},
4957         }
4958     },
4959     /* ZERO WIDTH JOINER as non-printing Unicode characters should not be encoded if not preprocessed. */
4960     {   "file:a\xE2\x80\x8D.html", Uri_CREATE_NO_PRE_PROCESS_HTML_URI, S_OK, FALSE,
4961         {
4962             {"",S_FALSE,FALSE},
4963             {"",S_FALSE,FALSE},
4964             {"file:a\xE2\x80\x8D.html",S_OK,FALSE},
4965             {"",S_FALSE,FALSE},
4966             {".html",S_OK,FALSE},
4967             {"",S_FALSE,FALSE},
4968             {"",S_FALSE,FALSE},
4969             {"",S_FALSE,FALSE},
4970             {"a\xE2\x80\x8D.html",S_OK,FALSE},
4971             {"a\xE2\x80\x8D.html",S_OK,FALSE},
4972             {"",S_FALSE,FALSE},
4973             {"file:a\xE2\x80\x8D.html",S_OK,FALSE},
4974             {"file",S_OK,FALSE},
4975             {"",S_FALSE,FALSE},
4976             {"",S_FALSE,FALSE}
4977         },
4978         {
4979             {Uri_HOST_UNKNOWN,S_OK,FALSE},
4980             {0,S_FALSE,FALSE},
4981             {URL_SCHEME_FILE,S_OK,FALSE},
4982             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4983         }
4984     },
4985     /* LEFT-TO-RIGHT MARK as non-printing Unicode characters should not be encoded if not preprocessed. */
4986     {   "file:ab\xE2\x80\x8E.html", Uri_CREATE_NO_PRE_PROCESS_HTML_URI, S_OK, FALSE,
4987         {
4988             {"",S_FALSE,FALSE},
4989             {"",S_FALSE,FALSE},
4990             {"file:ab\xE2\x80\x8D.html",S_OK,FALSE},
4991             {"",S_FALSE,FALSE},
4992             {".html",S_OK,FALSE},
4993             {"",S_FALSE,FALSE},
4994             {"",S_FALSE,FALSE},
4995             {"",S_FALSE,FALSE},
4996             {"ab\xE2\x80\x8D.html",S_OK,FALSE},
4997             {"ab\xE2\x80\x8D.html",S_OK,FALSE},
4998             {"",S_FALSE,FALSE},
4999             {"file:ab\xE2\x80\x8D.html",S_OK,FALSE},
5000             {"file",S_OK,FALSE},
5001             {"",S_FALSE,FALSE},
5002             {"",S_FALSE,FALSE}
5003         },
5004         {
5005             {Uri_HOST_UNKNOWN,S_OK,FALSE},
5006             {0,S_FALSE,FALSE},
5007             {URL_SCHEME_FILE,S_OK,FALSE},
5008             {URLZONE_INVALID,E_NOTIMPL,FALSE}
5009         }
5010     },
5011     /* Invalid Unicode characters should not be filtered */
5012     {   "file:ab\xc3\x28.html", 0, S_OK, FALSE,
5013         {
5014             {"",S_FALSE,FALSE},
5015             {"",S_FALSE,FALSE},
5016             {"file:ab\xc3\x28.html",S_OK,FALSE},
5017             {"",S_FALSE,FALSE},
5018             {".html",S_OK,FALSE},
5019             {"",S_FALSE,FALSE},
5020             {"",S_FALSE,FALSE},
5021             {"",S_FALSE,FALSE},
5022             {"ab\xc3\x28.html",S_OK,FALSE},
5023             {"ab\xc3\x28.html",S_OK,FALSE},
5024             {"",S_FALSE,FALSE},
5025             {"file:ab\xc3\x28.html",S_OK,FALSE},
5026             {"file",S_OK,FALSE},
5027             {"",S_FALSE,FALSE},
5028             {"",S_FALSE,FALSE}
5029         },
5030         {
5031             {Uri_HOST_UNKNOWN,S_OK,FALSE},
5032             {0,S_FALSE,FALSE},
5033             {URL_SCHEME_FILE,S_OK,FALSE},
5034             {URLZONE_INVALID,E_NOTIMPL,FALSE}
5035         }
5036     },
5037     /* Make sure % encoded unicode characters are not decoded. */
5038     {   "ftp://%E6%B5%8B%E8%AF%95:%E6%B5%8B%E8%AF%95@ftp.google.com/", 0, S_OK, FALSE,
5039         {
5040             {"ftp://%E6%B5%8B%E8%AF%95:%E6%B5%8B%E8%AF%95@ftp.google.com/",S_OK,FALSE},
5041             {"%E6%B5%8B%E8%AF%95:%E6%B5%8B%E8%AF%95@ftp.google.com",S_OK,FALSE},
5042             {"ftp://ftp.google.com/",S_OK,FALSE},
5043             {"google.com",S_OK,FALSE},
5044             {"",S_FALSE,FALSE},
5045             {"",S_FALSE,FALSE},
5046             {"ftp.google.com",S_OK,FALSE},
5047             {"%E6%B5%8B%E8%AF%95",S_OK,FALSE},
5048             {"/",S_OK,FALSE},
5049             {"/",S_OK,FALSE},
5050             {"",S_FALSE,FALSE},
5051             {"ftp://%E6%B5%8B%E8%AF%95:%E6%B5%8B%E8%AF%95@ftp.google.com/",S_OK,FALSE},
5052             {"ftp",S_OK,FALSE},
5053             {"%E6%B5%8B%E8%AF%95:%E6%B5%8B%E8%AF%95",S_OK,FALSE},
5054             {"%E6%B5%8B%E8%AF%95",S_OK,FALSE}
5055         },
5056         {
5057             {Uri_HOST_DNS,S_OK,FALSE},
5058             {21,S_OK,FALSE},
5059             {URL_SCHEME_FTP,S_OK,FALSE},
5060             {URLZONE_INVALID,E_NOTIMPL,FALSE}
5061         }
5062     }
5063 };
5064 
5065 typedef struct _invalid_uri {
5066     const char* uri;
5067     DWORD       flags;
5068     BOOL        todo;
5069 } invalid_uri;
5070 
5071 static const invalid_uri invalid_uri_tests[] = {
5072     /* Has to have a scheme name. */
5073     {"://www.winehq.org",0,FALSE},
5074     /* Windows doesn't like URIs which are implicitly file paths without the
5075      * ALLOW_IMPLICIT_FILE_SCHEME flag set.
5076      */
5077     {"C:/test/test.mp3",0,FALSE},
5078     {"\\\\Server/test/test.mp3",0,FALSE},
5079     {"C:/test/test.mp3",Uri_CREATE_ALLOW_IMPLICIT_WILDCARD_SCHEME,FALSE},
5080     {"\\\\Server/test/test.mp3",Uri_CREATE_ALLOW_RELATIVE,FALSE},
5081     /* Invalid schemes. */
5082     {"*abcd://not.valid.com",0,FALSE},
5083     {"*a*b*c*d://not.valid.com",0,FALSE},
5084     /* Not allowed to have invalid % encoded data. */
5085     {"ftp://google.co%XX/",0,FALSE},
5086     /* Too many h16 components. */
5087     {"http://[1:2:3:4:5:6:7:8:9]",0,FALSE},
5088     /* Not enough room for IPv4 address. */
5089     {"http://[1:2:3:4:5:6:7:192.0.1.0]",0,FALSE},
5090     /* Not enough h16 components. */
5091     {"http://[1:2:3:4]",0,FALSE},
5092     /* Not enough components including IPv4. */
5093     {"http://[1:192.0.1.0]",0,FALSE},
5094     /* Not allowed to have partial IPv4 in IPv6. */
5095     {"http://[::192.0]",0,FALSE},
5096     /* Can't have elision of 1 h16 at beginning of address. */
5097     {"http://[::2:3:4:5:6:7:8]",0,FALSE},
5098     /* Expects a valid IP Literal. */
5099     {"ftp://[not.valid.uri]/",0,FALSE},
5100     /* Expects valid port for a known scheme type. */
5101     {"ftp://www.winehq.org:123fgh",0,FALSE},
5102     /* Port exceeds USHORT_MAX for known scheme type. */
5103     {"ftp://www.winehq.org:65536",0,FALSE},
5104     /* Invalid port with IPv4 address. */
5105     {"http://www.winehq.org:1abcd",0,FALSE},
5106     /* Invalid port with IPv6 address. */
5107     {"http://[::ffff]:32xy",0,FALSE},
5108     /* Not allowed to have backslashes with NO_CANONICALIZE. */
5109     {"gopher://www.google.com\\test",Uri_CREATE_NO_CANONICALIZE,FALSE},
5110     /* Not allowed to have invalid % encoded data in opaque URI path. */
5111     {"news:test%XX",0,FALSE},
5112     {"mailto:wine@winehq%G8.com",0,FALSE},
5113     /* Known scheme types can't have invalid % encoded data in query string. */
5114     {"http://google.com/?query=te%xx",0,FALSE},
5115     /* Invalid % encoded data in fragment of know scheme type. */
5116     {"ftp://google.com/#Test%xx",0,FALSE},
5117     {"  http://google.com/",Uri_CREATE_NO_PRE_PROCESS_HTML_URI,FALSE},
5118     {"\n\nhttp://google.com/",Uri_CREATE_NO_PRE_PROCESS_HTML_URI,FALSE},
5119     {"file://c:\\test<test",Uri_CREATE_FILE_USE_DOS_PATH,FALSE},
5120     {"file://c:\\test>test",Uri_CREATE_FILE_USE_DOS_PATH,FALSE},
5121     {"file://c:\\test\"test",Uri_CREATE_FILE_USE_DOS_PATH,FALSE},
5122     {"file:c:\\test<test",Uri_CREATE_FILE_USE_DOS_PATH,FALSE},
5123     {"file:c:\\test>test",Uri_CREATE_FILE_USE_DOS_PATH,FALSE},
5124     {"file:c:\\test\"test",Uri_CREATE_FILE_USE_DOS_PATH,FALSE},
5125     /* res URIs aren't allowed to have forbidden dos path characters in the
5126      * hostname.
5127      */
5128     {"res://c:\\te<st\\test/test",0,FALSE},
5129     {"res://c:\\te>st\\test/test",0,FALSE},
5130     {"res://c:\\te\"st\\test/test",0,FALSE},
5131     {"res://c:\\test/te%xxst",0,FALSE}
5132 };
5133 
5134 typedef struct _uri_equality {
5135     const char* a;
5136     DWORD       create_flags_a;
5137     const char* b;
5138     DWORD       create_flags_b;
5139     BOOL        equal;
5140     BOOL        todo;
5141 } uri_equality;
5142 
5143 static const uri_equality equality_tests[] = {
5144     {
5145         "HTTP://www.winehq.org/test dir/./",0,
5146         "http://www.winehq.org/test dir/../test dir/",0,
5147         TRUE
5148     },
5149     {
5150         /* http://www.winehq.org/test%20dir */
5151         "http://%77%77%77%2E%77%69%6E%65%68%71%2E%6F%72%67/%74%65%73%74%20%64%69%72",0,
5152         "http://www.winehq.org/test dir",0,
5153         TRUE
5154     },
5155     {
5156         "c:\\test.mp3",Uri_CREATE_ALLOW_IMPLICIT_FILE_SCHEME,
5157         "file:///c:/test.mp3",0,
5158         TRUE
5159     },
5160     {
5161         "ftp://ftp.winehq.org/",0,
5162         "ftp://ftp.winehq.org",0,
5163         TRUE
5164     },
5165     {
5166         "ftp://ftp.winehq.org/test/test2/../../testB/",0,
5167         "ftp://ftp.winehq.org/t%45stB/",0,
5168         FALSE
5169     },
5170     {
5171         "http://google.com/TEST",0,
5172         "http://google.com/test",0,
5173         FALSE
5174     },
5175     {
5176         "http://GOOGLE.com/",0,
5177         "http://google.com/",0,
5178         TRUE
5179     },
5180     /* Performs case insensitive compare of host names (for known scheme types). */
5181     {
5182         "ftp://GOOGLE.com/",Uri_CREATE_NO_CANONICALIZE,
5183         "ftp://google.com/",0,
5184         TRUE
5185     },
5186     {
5187         "zip://GOOGLE.com/",0,
5188         "zip://google.com/",0,
5189         FALSE
5190     },
5191     {
5192         "file:///c:/TEST/TeST/",0,
5193         "file:///c:/test/test/",0,
5194         TRUE
5195     },
5196     {
5197         "file:///server/TEST",0,
5198         "file:///SERVER/TEST",0,
5199         TRUE
5200     },
5201     {
5202         "http://google.com",Uri_CREATE_NO_CANONICALIZE,
5203         "http://google.com/",0,
5204         TRUE
5205     },
5206     {
5207         "ftp://google.com:21/",0,
5208         "ftp://google.com/",0,
5209         TRUE
5210     },
5211     {
5212         "http://google.com:80/",Uri_CREATE_NO_CANONICALIZE,
5213         "http://google.com/",0,
5214         TRUE
5215     },
5216     {
5217         "http://google.com:70/",0,
5218         "http://google.com:71/",0,
5219         FALSE
5220     },
5221     {
5222         "file:///c:/dir/file.txt", 0,
5223         "file:///c:/dir/file.txt", Uri_CREATE_FILE_USE_DOS_PATH,
5224         TRUE
5225     },
5226     {
5227         "file:///c:/dir/file.txt", 0,
5228         "file:///c:\\dir\\file.txt", Uri_CREATE_NO_CANONICALIZE,
5229         TRUE
5230     },
5231     {
5232         "file:///c:/dir/file.txt", 0,
5233         "file:///c:\\dir2\\..\\dir\\file.txt", Uri_CREATE_NO_CANONICALIZE,
5234         TRUE
5235     },
5236     {
5237         "file:///c:\\dir2\\..\\ dir\\file.txt", Uri_CREATE_NO_CANONICALIZE,
5238         "file:///c:/%20dir/file.txt", 0,
5239         TRUE
5240     },
5241     {
5242         "file:///c:/Dir/file.txt", 0,
5243         "file:///C:/dir/file.TXT", Uri_CREATE_FILE_USE_DOS_PATH,
5244         TRUE
5245     },
5246     {
5247         "file:///c:/dir/file.txt", 0,
5248         "file:///c:\\dir\\file.txt", Uri_CREATE_FILE_USE_DOS_PATH,
5249         TRUE
5250     },
5251     {
5252         "file:///c:/dir/file.txt#a", 0,
5253         "file:///c:\\dir\\file.txt#b", Uri_CREATE_FILE_USE_DOS_PATH,
5254         FALSE
5255     },
5256     /* Tests of an empty hash/fragment part */
5257     {
5258         "http://google.com/test",0,
5259         "http://google.com/test#",0,
5260         FALSE
5261     },
5262     {
5263         "ftp://ftp.winehq.org/",0,
5264         "ftp://ftp.winehq.org/#",0,
5265         FALSE
5266     },
5267     {
5268         "file:///c:/dir/file.txt#", 0,
5269         "file:///c:\\dir\\file.txt", Uri_CREATE_FILE_USE_DOS_PATH,
5270         FALSE
5271     }
5272 };
5273 
5274 typedef struct _uri_with_fragment {
5275     const char* uri;
5276     const char* fragment;
5277     DWORD       create_flags;
5278     HRESULT     create_expected;
5279     BOOL        create_todo;
5280 
5281     const char* expected_uri;
5282     BOOL        expected_todo;
5283 } uri_with_fragment;
5284 
5285 static const uri_with_fragment uri_fragment_tests[] = {
5286     {
5287         "http://google.com/","#fragment",0,S_OK,FALSE,
5288         "http://google.com/#fragment",FALSE
5289     },
5290     {
5291         "http://google.com/","fragment",0,S_OK,FALSE,
5292         "http://google.com/#fragment",FALSE
5293     },
5294     {
5295         "zip://test.com/","?test",0,S_OK,FALSE,
5296         "zip://test.com/#?test",FALSE
5297     },
5298     /* The fragment can be empty. */
5299     {
5300         "ftp://ftp.google.com/","",0,S_OK,FALSE,
5301         "ftp://ftp.google.com/#",FALSE
5302     }
5303 };
5304 
5305 typedef struct _uri_builder_property {
5306     BOOL            change;
5307     const char      *value;
5308     const char      *expected_value;
5309     Uri_PROPERTY    property;
5310     HRESULT         expected;
5311     BOOL            todo;
5312 } uri_builder_property;
5313 
5314 typedef struct _uri_builder_port {
5315     BOOL    change;
5316     BOOL    set;
5317     DWORD   value;
5318     HRESULT expected;
5319     BOOL    todo;
5320 } uri_builder_port;
5321 
5322 typedef struct _uri_builder_str_property {
5323     const char* expected;
5324     HRESULT     result;
5325     BOOL        todo;
5326 } uri_builder_str_property;
5327 
5328 typedef struct _uri_builder_dword_property {
5329     DWORD   expected;
5330     HRESULT result;
5331     BOOL    todo;
5332 } uri_builder_dword_property;
5333 
5334 typedef struct _uri_builder_test {
5335     const char                  *uri;
5336     DWORD                       create_flags;
5337     HRESULT                     create_builder_expected;
5338     BOOL                        create_builder_todo;
5339 
5340     uri_builder_property        properties[URI_BUILDER_STR_PROPERTY_COUNT];
5341 
5342     uri_builder_port            port_prop;
5343 
5344     DWORD                       uri_flags;
5345     HRESULT                     uri_hres;
5346     BOOL                        uri_todo;
5347 
5348     DWORD                       uri_simple_encode_flags;
5349     HRESULT                     uri_simple_hres;
5350     BOOL                        uri_simple_todo;
5351 
5352     DWORD                       uri_with_flags;
5353     DWORD                       uri_with_builder_flags;
5354     DWORD                       uri_with_encode_flags;
5355     HRESULT                     uri_with_hres;
5356     BOOL                        uri_with_todo;
5357 
5358     uri_builder_str_property    expected_str_props[URI_STR_PROPERTY_COUNT];
5359     uri_builder_dword_property  expected_dword_props[URI_DWORD_PROPERTY_COUNT];
5360 } uri_builder_test;
5361 
5362 static const uri_builder_test uri_builder_tests[] = {
5363     {   "http://google.com/",0,S_OK,FALSE,
5364         {
5365             {TRUE,"#fragment",NULL,Uri_PROPERTY_FRAGMENT,S_OK,FALSE},
5366             {TRUE,"password",NULL,Uri_PROPERTY_PASSWORD,S_OK,FALSE},
5367             {TRUE,"?query=x",NULL,Uri_PROPERTY_QUERY,S_OK,FALSE},
5368             {TRUE,"username",NULL,Uri_PROPERTY_USER_NAME,S_OK,FALSE}
5369         },
5370         {FALSE},
5371         0,S_OK,FALSE,
5372         0,S_OK,FALSE,
5373         0,0,0,S_OK,FALSE,
5374         {
5375             {"http://username:password@google.com/?query=x#fragment",S_OK},
5376             {"username:password@google.com",S_OK},
5377             {"http://google.com/?query=x#fragment",S_OK},
5378             {"google.com",S_OK},
5379             {"",S_FALSE},
5380             {"#fragment",S_OK},
5381             {"google.com",S_OK},
5382             {"password",S_OK},
5383             {"/",S_OK},
5384             {"/?query=x",S_OK},
5385             {"?query=x",S_OK},
5386             {"http://username:password@google.com/?query=x#fragment",S_OK},
5387             {"http",S_OK},
5388             {"username:password",S_OK},
5389             {"username",S_OK}
5390         },
5391         {
5392             {Uri_HOST_DNS,S_OK},
5393             {80,S_OK},
5394             {URL_SCHEME_HTTP,S_OK},
5395             {URLZONE_INVALID,E_NOTIMPL}
5396         }
5397     },
5398     {   "http://google.com/",0,S_OK,FALSE,
5399         {
5400             {TRUE,"test",NULL,Uri_PROPERTY_SCHEME_NAME,S_OK,FALSE}
5401         },
5402         {TRUE,TRUE,120,S_OK,FALSE},
5403         0,S_OK,FALSE,
5404         0,S_OK,FALSE,
5405         0,0,0,S_OK,FALSE,
5406         {
5407             {"test://google.com:120/",S_OK},
5408             {"google.com:120",S_OK},
5409             {"test://google.com:120/",S_OK},
5410             {"google.com",S_OK},
5411             {"",S_FALSE},
5412             {"",S_FALSE},
5413             {"google.com",S_OK},
5414             {"",S_FALSE},
5415             {"/",S_OK},
5416             {"/",S_OK},
5417             {"",S_FALSE},
5418             {"test://google.com:120/",S_OK},
5419             {"test",S_OK},
5420             {"",S_FALSE},
5421             {"",S_FALSE}
5422         },
5423         {
5424             {Uri_HOST_DNS,S_OK},
5425             {120,S_OK},
5426             {URL_SCHEME_UNKNOWN,S_OK},
5427             {URLZONE_INVALID,E_NOTIMPL}
5428         }
5429     },
5430     {   "/Test/test dir",Uri_CREATE_ALLOW_RELATIVE,S_OK,FALSE,
5431         {
5432             {TRUE,"http",NULL,Uri_PROPERTY_SCHEME_NAME,S_OK,FALSE},
5433             {TRUE,"::192.2.3.4",NULL,Uri_PROPERTY_HOST,S_OK,FALSE},
5434             {TRUE,NULL,NULL,Uri_PROPERTY_PATH,S_OK,FALSE}
5435         },
5436         {FALSE},
5437         0,S_OK,FALSE,
5438         0,S_OK,FALSE,
5439         0,0,0,S_OK,FALSE,
5440         {
5441             {"http://[::192.2.3.4]/",S_OK},
5442             {"[::192.2.3.4]",S_OK},
5443             {"http://[::192.2.3.4]/",S_OK},
5444             {"",S_FALSE},
5445             {"",S_FALSE},
5446             {"",S_FALSE},
5447             {"::192.2.3.4",S_OK},
5448             {"",S_FALSE},
5449             {"/",S_OK},
5450             {"/",S_OK},
5451             {"",S_FALSE},
5452             {"http://[::192.2.3.4]/",S_OK},
5453             {"http",S_OK},
5454             {"",S_FALSE},
5455             {"",S_FALSE}
5456         },
5457         {
5458             {Uri_HOST_IPV6,S_OK},
5459             {80,S_OK},
5460             {URL_SCHEME_HTTP,S_OK},
5461             {URLZONE_INVALID,E_NOTIMPL}
5462         }
5463     },
5464     {   "http://google.com/",0,S_OK,FALSE,
5465         {
5466             {TRUE,"Frag","#Frag",Uri_PROPERTY_FRAGMENT,S_OK,FALSE}
5467         },
5468         {FALSE},
5469         0,S_OK,FALSE,
5470         0,S_OK,FALSE,
5471         0,0,0,S_OK,FALSE,
5472         {
5473             {"http://google.com/#Frag",S_OK},
5474             {"google.com",S_OK},
5475             {"http://google.com/#Frag",S_OK},
5476             {"google.com",S_OK},
5477             {"",S_FALSE},
5478             {"#Frag",S_OK},
5479             {"google.com",S_OK},
5480             {"",S_FALSE},
5481             {"/",S_OK},
5482             {"/",S_OK},
5483             {"",S_FALSE},
5484             {"http://google.com/#Frag",S_OK},
5485             {"http",S_OK},
5486             {"",S_FALSE},
5487             {"",S_FALSE}
5488         },
5489         {
5490             {Uri_HOST_DNS,S_OK},
5491             {80,S_OK},
5492             {URL_SCHEME_HTTP,S_OK},
5493             {URLZONE_INVALID,E_NOTIMPL}
5494         }
5495     },
5496     {   "http://google.com/",0,S_OK,FALSE,
5497         {
5498             {TRUE,"","#",Uri_PROPERTY_FRAGMENT,S_OK,FALSE},
5499         },
5500         {FALSE},
5501         0,S_OK,FALSE,
5502         0,S_OK,FALSE,
5503         0,0,0,S_OK,FALSE,
5504         {
5505             {"http://google.com/#",S_OK},
5506             {"google.com",S_OK},
5507             {"http://google.com/#",S_OK},
5508             {"google.com",S_OK},
5509             {"",S_FALSE},
5510             {"#",S_OK},
5511             {"google.com",S_OK},
5512             {"",S_FALSE},
5513             {"/",S_OK},
5514             {"/",S_OK},
5515             {"",S_FALSE},
5516             {"http://google.com/#",S_OK},
5517             {"http",S_OK},
5518             {"",S_FALSE},
5519             {"",S_FALSE}
5520         },
5521         {
5522             {Uri_HOST_DNS,S_OK},
5523             {80,S_OK},
5524             {URL_SCHEME_HTTP,S_OK},
5525             {URLZONE_INVALID,E_NOTIMPL}
5526         }
5527     },
5528     {   "http://google.com/",0,S_OK,FALSE,
5529         {
5530             {TRUE,":password",NULL,Uri_PROPERTY_PASSWORD,S_OK,FALSE}
5531         },
5532         {FALSE},
5533         0,S_OK,FALSE,
5534         0,S_OK,FALSE,
5535         0,0,0,S_OK,FALSE,
5536         {
5537             {"http://::password@google.com/",S_OK},
5538             {"::password@google.com",S_OK},
5539             {"http://google.com/",S_OK},
5540             {"google.com",S_OK},
5541             {"",S_FALSE},
5542             {"",S_FALSE},
5543             {"google.com",S_OK},
5544             {":password",S_OK},
5545             {"/",S_OK},
5546             {"/",S_OK},
5547             {"",S_FALSE},
5548             {"http://::password@google.com/",S_OK},
5549             {"http",S_OK},
5550             {"::password",S_OK},
5551             {"",S_FALSE}
5552         },
5553         {
5554             {Uri_HOST_DNS,S_OK},
5555             {80,S_OK},
5556             {URL_SCHEME_HTTP,S_OK},
5557             {URLZONE_INVALID,E_NOTIMPL}
5558         }
5559     },
5560     {   "test/test",Uri_CREATE_ALLOW_RELATIVE,S_OK,FALSE,
5561         {
5562             {TRUE,"password",NULL,Uri_PROPERTY_PASSWORD,S_OK,FALSE}
5563         },
5564         {FALSE},
5565         Uri_CREATE_ALLOW_RELATIVE,S_OK,FALSE,
5566         0,S_OK,FALSE,
5567         Uri_CREATE_ALLOW_RELATIVE,0,0,S_OK,FALSE,
5568         {
5569             {":password@test/test",S_OK},
5570             {":password@",S_OK},
5571             {":password@test/test",S_OK},
5572             {"",S_FALSE},
5573             {"",S_FALSE},
5574             {"",S_FALSE},
5575             {"",S_FALSE},
5576             {"password",S_OK},
5577             {"test/test",S_OK},
5578             {"test/test",S_OK},
5579             {"",S_FALSE},
5580             {":password@test/test",S_OK},
5581             {"",S_FALSE},
5582             {":password",S_OK},
5583             {"",S_FALSE}
5584         },
5585         {
5586             {Uri_HOST_UNKNOWN,S_OK},
5587             {0,S_FALSE},
5588             {URL_SCHEME_UNKNOWN,S_OK},
5589             {URLZONE_INVALID,E_NOTIMPL}
5590         }
5591     },
5592     {   "http://google.com/",0,S_OK,FALSE,
5593         {
5594             {TRUE,"test/test",NULL,Uri_PROPERTY_PATH,S_OK,FALSE},
5595         },
5596         {FALSE},
5597         0,S_OK,FALSE,
5598         0,S_OK,FALSE,
5599         0,0,0,S_OK,FALSE,
5600         {
5601             {"http://google.com/test/test",S_OK},
5602             {"google.com",S_OK},
5603             {"http://google.com/test/test",S_OK},
5604             {"google.com",S_OK},
5605             {"",S_FALSE},
5606             {"",S_FALSE},
5607             {"google.com",S_OK},
5608             {"",S_FALSE},
5609             {"/test/test",S_OK},
5610             {"/test/test",S_OK},
5611             {"",S_FALSE},
5612             {"http://google.com/test/test",S_OK},
5613             {"http",S_OK},
5614             {"",S_FALSE},
5615             {"",S_FALSE}
5616         },
5617         {
5618             {Uri_HOST_DNS,S_OK},
5619             {80,S_OK},
5620             {URL_SCHEME_HTTP,S_OK},
5621             {URLZONE_INVALID,E_NOTIMPL}
5622         }
5623     },
5624     {   "zip:testing/test",0,S_OK,FALSE,
5625         {
5626             {TRUE,"test",NULL,Uri_PROPERTY_PATH,S_OK,FALSE},
5627         },
5628         {FALSE},
5629         0,S_OK,FALSE,
5630         0,S_OK,FALSE,
5631         0,0,0,S_OK,FALSE,
5632         {
5633             {"zip:test",S_OK},
5634             {"",S_FALSE},
5635             {"zip:test",S_OK},
5636             {"",S_FALSE},
5637             {"",S_FALSE},
5638             {"",S_FALSE},
5639             {"",S_FALSE},
5640             {"",S_FALSE},
5641             {"test",S_OK},
5642             {"test",S_OK},
5643             {"",S_FALSE},
5644             {"zip:test",S_OK},
5645             {"zip",S_OK},
5646             {"",S_FALSE},
5647             {"",S_FALSE}
5648         },
5649         {
5650             {Uri_HOST_UNKNOWN,S_OK},
5651             {0,S_FALSE},
5652             {URL_SCHEME_UNKNOWN,S_OK},
5653             {URLZONE_INVALID,E_NOTIMPL}
5654         }
5655     },
5656     {   "http://google.com/",0,S_OK,FALSE,
5657         {
5658             {FALSE},
5659         },
5660         /* 555 will be returned from GetPort even though FALSE was passed as the hasPort parameter. */
5661         {TRUE,FALSE,555,S_OK,FALSE},
5662         0,S_OK,FALSE,
5663         0,S_OK,FALSE,
5664         0,0,0,S_OK,FALSE,
5665         {
5666             {"http://google.com/",S_OK},
5667             {"google.com",S_OK},
5668             {"http://google.com/",S_OK},
5669             {"google.com",S_OK},
5670             {"",S_FALSE},
5671             {"",S_FALSE},
5672             {"google.com",S_OK},
5673             {"",S_FALSE},
5674             {"/",S_OK},
5675             {"/",S_OK},
5676             {"",S_FALSE},
5677             {"http://google.com/",S_OK},
5678             {"http",S_OK},
5679             {"",S_FALSE},
5680             {"",S_FALSE}
5681         },
5682         {
5683             {Uri_HOST_DNS,S_OK},
5684             /* Still returns 80, even though earlier the port was disabled. */
5685             {80,S_OK},
5686             {URL_SCHEME_HTTP,S_OK},
5687             {URLZONE_INVALID,E_NOTIMPL}
5688         }
5689     },
5690     {   "http://google.com/",0,S_OK,FALSE,
5691         {
5692             {FALSE},
5693         },
5694         /* Instead of getting "TRUE" back as the "hasPort" parameter in GetPort,
5695          * you'll get 122345 instead.
5696          */
5697         {TRUE,122345,222,S_OK,FALSE},
5698         0,S_OK,FALSE,
5699         0,S_OK,FALSE,
5700         0,0,0,S_OK,FALSE,
5701         {
5702             {"http://google.com:222/",S_OK},
5703             {"google.com:222",S_OK},
5704             {"http://google.com:222/",S_OK},
5705             {"google.com",S_OK},
5706             {"",S_FALSE},
5707             {"",S_FALSE},
5708             {"google.com",S_OK},
5709             {"",S_FALSE},
5710             {"/",S_OK},
5711             {"/",S_OK},
5712             {"",S_FALSE},
5713             {"http://google.com:222/",S_OK},
5714             {"http",S_OK},
5715             {"",S_FALSE},
5716             {"",S_FALSE}
5717         },
5718         {
5719             {Uri_HOST_DNS,S_OK},
5720             {222,S_OK},
5721             {URL_SCHEME_HTTP,S_OK},
5722             {URLZONE_INVALID,E_NOTIMPL}
5723         }
5724     },
5725     /* IUri's created with the IUriBuilder can have ports that exceed USHORT_MAX. */
5726     {   "http://google.com/",0,S_OK,FALSE,
5727         {
5728             {FALSE},
5729         },
5730         {TRUE,TRUE,999999,S_OK,FALSE},
5731         0,S_OK,FALSE,
5732         0,S_OK,FALSE,
5733         0,0,0,S_OK,FALSE,
5734         {
5735             {"http://google.com:999999/",S_OK},
5736             {"google.com:999999",S_OK},
5737             {"http://google.com:999999/",S_OK},
5738             {"google.com",S_OK},
5739             {"",S_FALSE},
5740             {"",S_FALSE},
5741             {"google.com",S_OK},
5742             {"",S_FALSE},
5743             {"/",S_OK},
5744             {"/",S_OK},
5745             {"",S_FALSE},
5746             {"http://google.com:999999/",S_OK},
5747             {"http",S_OK},
5748             {"",S_FALSE},
5749             {"",S_FALSE}
5750         },
5751         {
5752             {Uri_HOST_DNS,S_OK},
5753             {999999,S_OK},
5754             {URL_SCHEME_HTTP,S_OK},
5755             {URLZONE_INVALID,E_NOTIMPL}
5756         }
5757     },
5758     {   "http://google.com/",0,S_OK,FALSE,
5759         {
5760             {TRUE,"test","?test",Uri_PROPERTY_QUERY,S_OK,FALSE},
5761         },
5762 
5763         {FALSE},
5764         0,S_OK,FALSE,
5765         0,S_OK,FALSE,
5766         0,0,0,S_OK,FALSE,
5767         {
5768             {"http://google.com/?test",S_OK},
5769             {"google.com",S_OK},
5770             {"http://google.com/?test",S_OK},
5771             {"google.com",S_OK},
5772             {"",S_FALSE},
5773             {"",S_FALSE},
5774             {"google.com",S_OK},
5775             {"",S_FALSE},
5776             {"/",S_OK},
5777             {"/?test",S_OK},
5778             {"?test",S_OK},
5779             {"http://google.com/?test",S_OK},
5780             {"http",S_OK},
5781             {"",S_FALSE},
5782             {"",S_FALSE}
5783         },
5784         {
5785             {Uri_HOST_DNS,S_OK},
5786             {80,S_OK},
5787             {URL_SCHEME_HTTP,S_OK},
5788             {URLZONE_INVALID,E_NOTIMPL}
5789         }
5790     },
5791     {   "http://:password@google.com/",0,S_OK,FALSE,
5792         {
5793             {FALSE},
5794         },
5795         {FALSE},
5796         0,S_OK,FALSE,
5797         0,S_OK,FALSE,
5798         0,0,0,S_OK,FALSE,
5799         {
5800             {"http://:password@google.com/",S_OK},
5801             {":password@google.com",S_OK},
5802             {"http://google.com/",S_OK},
5803             {"google.com",S_OK},
5804             {"",S_FALSE},
5805             {"",S_FALSE},
5806             {"google.com",S_OK},
5807             {"password",S_OK},
5808             {"/",S_OK},
5809             {"/",S_OK},
5810             {"",S_FALSE},
5811             {"http://:password@google.com/",S_OK},
5812             {"http",S_OK},
5813             {":password",S_OK},
5814             {"",S_FALSE}
5815         },
5816         {
5817             {Uri_HOST_DNS,S_OK},
5818             {80,S_OK},
5819             {URL_SCHEME_HTTP,S_OK},
5820             {URLZONE_INVALID,E_NOTIMPL}
5821         }
5822     },
5823     /* IUriBuilder doesn't need a base IUri to build a IUri. */
5824     {   NULL,0,S_OK,FALSE,
5825         {
5826             {TRUE,"http",NULL,Uri_PROPERTY_SCHEME_NAME,S_OK,FALSE},
5827             {TRUE,"google.com",NULL,Uri_PROPERTY_HOST,S_OK,FALSE}
5828         },
5829         {FALSE},
5830         0,S_OK,FALSE,
5831         0,S_OK,FALSE,
5832         0,0,0,S_OK,FALSE,
5833         {
5834             {"http://google.com/",S_OK},
5835             {"google.com",S_OK},
5836             {"http://google.com/",S_OK},
5837             {"google.com",S_OK},
5838             {"",S_FALSE},
5839             {"",S_FALSE},
5840             {"google.com",S_OK},
5841             {"",S_FALSE},
5842             {"/",S_OK},
5843             {"/",S_OK},
5844             {"",S_FALSE},
5845             {"http://google.com/",S_OK},
5846             {"http",S_OK},
5847             {"",S_FALSE},
5848             {"",S_FALSE}
5849         },
5850         {
5851             {Uri_HOST_DNS,S_OK},
5852             {80,S_OK},
5853             {URL_SCHEME_HTTP,S_OK},
5854             {URLZONE_INVALID,E_NOTIMPL}
5855         }
5856     },
5857     /* Can't set the scheme name to NULL. */
5858     {   "zip://google.com/",0,S_OK,FALSE,
5859         {
5860             {TRUE,NULL,"zip",Uri_PROPERTY_SCHEME_NAME,E_INVALIDARG,FALSE}
5861         },
5862         {FALSE},
5863         0,S_OK,FALSE,
5864         0,S_OK,FALSE,
5865         0,0,0,S_OK,FALSE,
5866         {
5867             {"zip://google.com/",S_OK},
5868             {"google.com",S_OK},
5869             {"zip://google.com/",S_OK},
5870             {"google.com",S_OK},
5871             {"",S_FALSE},
5872             {"",S_FALSE},
5873             {"google.com",S_OK},
5874             {"",S_FALSE},
5875             {"/",S_OK},
5876             {"/",S_OK},
5877             {"",S_FALSE},
5878             {"zip://google.com/",S_OK},
5879             {"zip",S_OK},
5880             {"",S_FALSE},
5881             {"",S_FALSE}
5882         },
5883         {
5884             {Uri_HOST_DNS,S_OK},
5885             {0,S_FALSE},
5886             {URL_SCHEME_UNKNOWN,S_OK},
5887             {URLZONE_INVALID,E_NOTIMPL}
5888         }
5889     },
5890     /* Can't set the scheme name to an empty string. */
5891     {   "zip://google.com/",0,S_OK,FALSE,
5892         {
5893             {TRUE,"","zip",Uri_PROPERTY_SCHEME_NAME,E_INVALIDARG,FALSE}
5894         },
5895         {FALSE},
5896         0,S_OK,FALSE,
5897         0,S_OK,FALSE,
5898         0,0,0,S_OK,FALSE,
5899         {
5900             {"zip://google.com/",S_OK},
5901             {"google.com",S_OK},
5902             {"zip://google.com/",S_OK},
5903             {"google.com",S_OK},
5904             {"",S_FALSE},
5905             {"",S_FALSE},
5906             {"google.com",S_OK},
5907             {"",S_FALSE},
5908             {"/",S_OK},
5909             {"/",S_OK},
5910             {"",S_FALSE},
5911             {"zip://google.com/",S_OK},
5912             {"zip",S_OK},
5913             {"",S_FALSE},
5914             {"",S_FALSE}
5915         },
5916         {
5917             {Uri_HOST_DNS,S_OK},
5918             {0,S_FALSE},
5919             {URL_SCHEME_UNKNOWN,S_OK},
5920             {URLZONE_INVALID,E_NOTIMPL}
5921         }
5922     },
5923     /* -1 to CreateUri makes it use the same flags as the base IUri was created with.
5924      * CreateUriSimple always uses the flags the base IUri was created with (if any).
5925      */
5926     {   "http://google.com/../../",Uri_CREATE_NO_CANONICALIZE,S_OK,FALSE,
5927         {{FALSE}},
5928         {FALSE},
5929         -1,S_OK,FALSE,
5930         0,S_OK,FALSE,
5931         0,UriBuilder_USE_ORIGINAL_FLAGS,0,S_OK,FALSE,
5932         {
5933             {"http://google.com/../../",S_OK},
5934             {"google.com",S_OK},
5935             {"http://google.com/../../",S_OK},
5936             {"google.com",S_OK},
5937             {"",S_FALSE},
5938             {"",S_FALSE},
5939             {"google.com",S_OK},
5940             {"",S_FALSE},
5941             {"/../../",S_OK},
5942             {"/../../",S_OK},
5943             {"",S_FALSE},
5944             {"http://google.com/../../",S_OK},
5945             {"http",S_OK},
5946             {"",S_FALSE},
5947             {"",S_FALSE}
5948         },
5949         {
5950             {Uri_HOST_DNS,S_OK},
5951             {80,S_OK},
5952             {URL_SCHEME_HTTP,S_OK},
5953             {URLZONE_INVALID,E_NOTIMPL}
5954         }
5955     },
5956     {   "http://google.com/",0,S_OK,FALSE,
5957         {
5958             {TRUE,"#Fr<|>g",NULL,Uri_PROPERTY_FRAGMENT,S_OK,FALSE}
5959         },
5960         {FALSE},
5961         -1,S_OK,FALSE,
5962         0,S_OK,FALSE,
5963         Uri_CREATE_NO_DECODE_EXTRA_INFO,UriBuilder_USE_ORIGINAL_FLAGS,0,S_OK,FALSE,
5964         {
5965             {"http://google.com/#Fr%3C%7C%3Eg",S_OK},
5966             {"google.com",S_OK},
5967             {"http://google.com/#Fr%3C%7C%3Eg",S_OK},
5968             {"google.com",S_OK},
5969             {"",S_FALSE},
5970             {"#Fr%3C%7C%3Eg",S_OK},
5971             {"google.com",S_OK},
5972             {"",S_FALSE},
5973             {"/",S_OK},
5974             {"/",S_OK},
5975             {"",S_FALSE},
5976             {"http://google.com/#Fr<|>g",S_OK},
5977             {"http",S_OK},
5978             {"",S_FALSE},
5979             {"",S_FALSE}
5980         },
5981         {
5982             {Uri_HOST_DNS,S_OK},
5983             {80,S_OK},
5984             {URL_SCHEME_HTTP,S_OK},
5985             {URLZONE_INVALID,E_NOTIMPL}
5986         }
5987     },
5988     {   "http://google.com/",0,S_OK,FALSE,
5989         {
5990             {TRUE,"#Fr<|>g",NULL,Uri_PROPERTY_FRAGMENT,S_OK,FALSE}
5991         },
5992         {FALSE},
5993         Uri_CREATE_CANONICALIZE|Uri_CREATE_NO_CANONICALIZE,E_INVALIDARG,FALSE,
5994         0,S_OK,FALSE,
5995         Uri_CREATE_CANONICALIZE|Uri_CREATE_NO_CANONICALIZE,UriBuilder_USE_ORIGINAL_FLAGS,0,S_OK,FALSE,
5996         {
5997             {"http://google.com/#Fr%3C%7C%3Eg",S_OK},
5998             {"google.com",S_OK},
5999             {"http://google.com/#Fr%3C%7C%3Eg",S_OK},
6000             {"google.com",S_OK},
6001             {"",S_FALSE},
6002             {"#Fr%3C%7C%3Eg",S_OK},
6003             {"google.com",S_OK},
6004             {"",S_FALSE},
6005             {"/",S_OK},
6006             {"/",S_OK},
6007             {"",S_FALSE},
6008             {"http://google.com/#Fr<|>g",S_OK},
6009             {"http",S_OK},
6010             {"",S_FALSE},
6011             {"",S_FALSE}
6012         },
6013         {
6014             {Uri_HOST_DNS,S_OK},
6015             {80,S_OK},
6016             {URL_SCHEME_HTTP,S_OK},
6017             {URLZONE_INVALID,E_NOTIMPL}
6018         }
6019     },
6020     {   NULL,0,S_OK,FALSE,
6021         {
6022             {TRUE,"/test/test/",NULL,Uri_PROPERTY_PATH,S_OK,FALSE},
6023             {TRUE,"#Fr<|>g",NULL,Uri_PROPERTY_FRAGMENT,S_OK,FALSE}
6024         },
6025         {FALSE},
6026         0,INET_E_INVALID_URL,FALSE,
6027         0,INET_E_INVALID_URL,FALSE,
6028         0,0,0,INET_E_INVALID_URL,FALSE
6029     },
6030     {   "http://google.com/",0,S_OK,FALSE,
6031         {
6032             {TRUE,"ht%xxtp",NULL,Uri_PROPERTY_SCHEME_NAME,S_OK,FALSE}
6033         },
6034         {FALSE},
6035         0,INET_E_INVALID_URL,FALSE,
6036         0,INET_E_INVALID_URL,FALSE,
6037         0,0,0,INET_E_INVALID_URL,FALSE
6038     },
6039     /* File scheme's can't have a username set. */
6040     {   "file://google.com/",0,S_OK,FALSE,
6041         {
6042             {TRUE,"username",NULL,Uri_PROPERTY_USER_NAME,S_OK,FALSE}
6043         },
6044         {FALSE},
6045         0,INET_E_INVALID_URL,FALSE,
6046         0,INET_E_INVALID_URL,FALSE,
6047         0,0,0,INET_E_INVALID_URL,FALSE
6048     },
6049     /* File schemes can't have a password set. */
6050     {   "file://google.com/",0,S_OK,FALSE,
6051         {
6052             {TRUE,"password",NULL,Uri_PROPERTY_PASSWORD,S_OK,FALSE}
6053         },
6054         {FALSE},
6055         0,INET_E_INVALID_URL,FALSE,
6056         0,INET_E_INVALID_URL,FALSE,
6057         0,0,0,INET_E_INVALID_URL,FALSE
6058     },
6059     /* UserName can't contain any character that is a delimiter for another
6060      * component that appears after it in a normal URI.
6061      */
6062     {   "http://google.com/",0,S_OK,FALSE,
6063         {
6064             {TRUE,"user:pass",NULL,Uri_PROPERTY_USER_NAME,S_OK,FALSE}
6065         },
6066         {FALSE},
6067         0,INET_E_INVALID_URL,FALSE,
6068         0,INET_E_INVALID_URL,FALSE,
6069         0,0,0,INET_E_INVALID_URL,FALSE
6070     },
6071     {   "http://google.com/",0,S_OK,FALSE,
6072         {
6073             {TRUE,"user@google.com",NULL,Uri_PROPERTY_USER_NAME,S_OK,FALSE}
6074         },
6075         {FALSE},
6076         0,INET_E_INVALID_URL,FALSE,
6077         0,INET_E_INVALID_URL,FALSE,
6078         0,0,0,INET_E_INVALID_URL,FALSE
6079     },
6080     {   "http://google.com/",0,S_OK,FALSE,
6081         {
6082             {TRUE,"user/path",NULL,Uri_PROPERTY_USER_NAME,S_OK,FALSE}
6083         },
6084         {FALSE},
6085         0,INET_E_INVALID_URL,FALSE,
6086         0,INET_E_INVALID_URL,FALSE,
6087         0,0,0,INET_E_INVALID_URL,FALSE
6088     },
6089     {   "http://google.com/",0,S_OK,FALSE,
6090         {
6091             {TRUE,"user?Query",NULL,Uri_PROPERTY_USER_NAME,S_OK,FALSE}
6092         },
6093         {FALSE},
6094         0,INET_E_INVALID_URL,FALSE,
6095         0,INET_E_INVALID_URL,FALSE,
6096         0,0,0,INET_E_INVALID_URL,FALSE
6097     },
6098     {   "http://google.com/",0,S_OK,FALSE,
6099         {
6100             {TRUE,"user#Frag",NULL,Uri_PROPERTY_USER_NAME,S_OK,FALSE}
6101         },
6102         {FALSE},
6103         0,INET_E_INVALID_URL,FALSE,
6104         0,INET_E_INVALID_URL,FALSE,
6105         0,0,0,INET_E_INVALID_URL,FALSE
6106     },
6107     {   "http://google.com/",0,S_OK,FALSE,
6108         {
6109             {TRUE,"pass@google.com",NULL,Uri_PROPERTY_PASSWORD,S_OK,FALSE}
6110         },
6111         {FALSE},
6112         0,INET_E_INVALID_URL,FALSE,
6113         0,INET_E_INVALID_URL,FALSE,
6114         0,0,0,INET_E_INVALID_URL,FALSE
6115     },
6116     {   "http://google.com/",0,S_OK,FALSE,
6117         {
6118             {TRUE,"pass/path",NULL,Uri_PROPERTY_PASSWORD,S_OK,FALSE}
6119         },
6120         {FALSE},
6121         0,INET_E_INVALID_URL,FALSE,
6122         0,INET_E_INVALID_URL,FALSE,
6123         0,0,0,INET_E_INVALID_URL,FALSE
6124     },
6125     {   "http://google.com/",0,S_OK,FALSE,
6126         {
6127             {TRUE,"pass?query",NULL,Uri_PROPERTY_PASSWORD,S_OK,FALSE}
6128         },
6129         {FALSE},
6130         0,INET_E_INVALID_URL,FALSE,
6131         0,INET_E_INVALID_URL,FALSE,
6132        0,0,0,INET_E_INVALID_URL,FALSE
6133     },
6134     {   "http://google.com/",0,S_OK,FALSE,
6135         {
6136             {TRUE,"pass#frag",NULL,Uri_PROPERTY_PASSWORD,S_OK,FALSE}
6137         },
6138         {FALSE},
6139         0,INET_E_INVALID_URL,FALSE,
6140         0,INET_E_INVALID_URL,FALSE,
6141         0,0,0,INET_E_INVALID_URL,FALSE
6142     },
6143     {   "http://google.com/",0,S_OK,FALSE,
6144         {
6145             {TRUE,"winehq.org/test",NULL,Uri_PROPERTY_HOST,S_OK,FALSE}
6146         },
6147         {FALSE},
6148         0,INET_E_INVALID_URL,FALSE,
6149         0,INET_E_INVALID_URL,FALSE,
6150         0,0,0,INET_E_INVALID_URL,FALSE
6151     },
6152     {   "http://google.com/",0,S_OK,FALSE,
6153         {
6154             {TRUE,"winehq.org?test",NULL,Uri_PROPERTY_HOST,S_OK,FALSE}
6155         },
6156         {FALSE},
6157         0,INET_E_INVALID_URL,FALSE,
6158         0,INET_E_INVALID_URL,FALSE,
6159         0,0,0,INET_E_INVALID_URL,FALSE
6160     },
6161     {   "http://google.com/",0,S_OK,FALSE,
6162         {
6163             {TRUE,"winehq.org#test",NULL,Uri_PROPERTY_HOST,S_OK,FALSE}
6164         },
6165         {FALSE},
6166         0,INET_E_INVALID_URL,FALSE,
6167         0,INET_E_INVALID_URL,FALSE,
6168         0,0,0,INET_E_INVALID_URL,FALSE
6169     },
6170     /* Hostname is allowed to contain a ':' (even for known scheme types). */
6171     {   "http://google.com/",0,S_OK,FALSE,
6172         {
6173             {TRUE,"winehq.org:test",NULL,Uri_PROPERTY_HOST,S_OK,FALSE},
6174         },
6175         {FALSE},
6176         0,S_OK,FALSE,
6177         0,S_OK,FALSE,
6178         0,0,0,S_OK,FALSE,
6179         {
6180             {"http://winehq.org:test/",S_OK},
6181             {"winehq.org:test",S_OK},
6182             {"http://winehq.org:test/",S_OK},
6183             {"winehq.org:test",S_OK},
6184             {"",S_FALSE},
6185             {"",S_FALSE},
6186             {"winehq.org:test",S_OK},
6187             {"",S_FALSE},
6188             {"/",S_OK},
6189             {"/",S_OK},
6190             {"",S_FALSE},
6191             {"http://winehq.org:test/",S_OK},
6192             {"http",S_OK},
6193             {"",S_FALSE},
6194             {"",S_FALSE}
6195         },
6196         {
6197             {Uri_HOST_DNS,S_OK},
6198             {80,S_OK},
6199             {URL_SCHEME_HTTP,S_OK},
6200             {URLZONE_INVALID,E_NOTIMPL}
6201         }
6202     },
6203     /* Can't set the host name to NULL. */
6204     {   "http://google.com/",0,S_OK,FALSE,
6205         {
6206             {TRUE,NULL,"google.com",Uri_PROPERTY_HOST,E_INVALIDARG,FALSE}
6207         },
6208         {FALSE},
6209         0,S_OK,FALSE,
6210         0,S_OK,FALSE,
6211         0,0,0,S_OK,FALSE,
6212         {
6213             {"http://google.com/",S_OK},
6214             {"google.com",S_OK},
6215             {"http://google.com/",S_OK},
6216             {"google.com",S_OK},
6217             {"",S_FALSE},
6218             {"",S_FALSE},
6219             {"google.com",S_OK},
6220             {"",S_FALSE},
6221             {"/",S_OK},
6222             {"/",S_OK},
6223             {"",S_FALSE},
6224             {"http://google.com/",S_OK},
6225             {"http",S_OK},
6226             {"",S_FALSE},
6227             {"",S_FALSE}
6228         },
6229         {
6230             {Uri_HOST_DNS,S_OK},
6231             {80,S_OK},
6232             {URL_SCHEME_HTTP,S_OK},
6233             {URLZONE_INVALID,E_NOTIMPL}
6234         }
6235     },
6236     /* Can set the host name to an empty string. */
6237     {   "http://google.com/",0,S_OK,FALSE,
6238         {
6239             {TRUE,"",NULL,Uri_PROPERTY_HOST,S_OK,FALSE}
6240         },
6241         {FALSE},
6242         0,S_OK,FALSE,
6243         0,S_OK,FALSE,
6244         0,0,0,S_OK,FALSE,
6245         {
6246             {"http:///",S_OK},
6247             {"",S_OK},
6248             {"http:///",S_OK},
6249             {"",S_FALSE},
6250             {"",S_FALSE},
6251             {"",S_FALSE},
6252             {"",S_OK},
6253             {"",S_FALSE},
6254             {"/",S_OK},
6255             {"/",S_OK},
6256             {"",S_FALSE},
6257             {"http:///",S_OK},
6258             {"http",S_OK},
6259             {"",S_FALSE},
6260             {"",S_FALSE}
6261         },
6262         {
6263             {Uri_HOST_UNKNOWN,S_OK},
6264             {80,S_OK},
6265             {URL_SCHEME_HTTP,S_OK},
6266             {URLZONE_INVALID,E_NOTIMPL}
6267         }
6268     },
6269     {   "http://google.com/",0,S_OK,FALSE,
6270         {
6271             {TRUE,"/path?query",NULL,Uri_PROPERTY_PATH,S_OK,FALSE}
6272         },
6273         {FALSE},
6274         0,INET_E_INVALID_URL,FALSE,
6275         0,INET_E_INVALID_URL,FALSE,
6276         0,0,0,INET_E_INVALID_URL,FALSE
6277     },
6278     {   "http://google.com/",0,S_OK,FALSE,
6279         {
6280             {TRUE,"/path#test",NULL,Uri_PROPERTY_PATH,S_OK,FALSE}
6281         },
6282         {FALSE},
6283         0,INET_E_INVALID_URL,FALSE,
6284         0,INET_E_INVALID_URL,FALSE,
6285         0,0,0,INET_E_INVALID_URL,FALSE
6286     },
6287     {   "http://google.com/",0,S_OK,FALSE,
6288         {
6289             {TRUE,"?path#test",NULL,Uri_PROPERTY_QUERY,S_OK,FALSE}
6290         },
6291         {FALSE},
6292         0,INET_E_INVALID_URL,FALSE,
6293         0,INET_E_INVALID_URL,FALSE,
6294         0,0,0,INET_E_INVALID_URL,FALSE
6295     },
6296     {   "file:///c:/dir/file.html",0,S_OK,FALSE,
6297         {
6298             {TRUE,NULL,NULL,Uri_PROPERTY_FRAGMENT,S_OK},
6299         },
6300         {FALSE},
6301         0,S_OK,FALSE,
6302         0,S_OK,FALSE,
6303         0,0,0,S_OK,FALSE,
6304         {
6305             {"file:///c:/dir/file.html",S_OK},
6306             {"",S_FALSE},
6307             {"file:///c:/dir/file.html",S_OK},
6308             {"",S_FALSE},
6309             {".html",S_OK},
6310             {"",S_FALSE},
6311             {"",S_FALSE},
6312             {"",S_FALSE},
6313             {"/c:/dir/file.html",S_OK},
6314             {"/c:/dir/file.html",S_OK},
6315             {"",S_FALSE},
6316             {"file:///c:/dir/file.html",S_OK},
6317             {"file",S_OK},
6318             {"",S_FALSE},
6319             {"",S_FALSE}
6320         },
6321         {
6322             {Uri_HOST_UNKNOWN,S_OK},
6323             {0,S_FALSE},
6324             {URL_SCHEME_FILE,S_OK},
6325             {URLZONE_INVALID,E_NOTIMPL}
6326         }
6327     },
6328     {   "file:///c:/dir/file.html",0,S_OK,FALSE,
6329         {
6330             {TRUE,"#",NULL,Uri_PROPERTY_FRAGMENT,S_OK},
6331         },
6332         {FALSE},
6333         0,S_OK,FALSE,
6334         0,S_OK,FALSE,
6335         0,0,0,S_OK,FALSE,
6336         {
6337             {"file:///c:/dir/file.html#",S_OK},
6338             {"",S_FALSE},
6339             {"file:///c:/dir/file.html#",S_OK},
6340             {"",S_FALSE},
6341             {".html",S_OK},
6342             {"#",S_OK},
6343             {"",S_FALSE},
6344             {"",S_FALSE},
6345             {"/c:/dir/file.html",S_OK},
6346             {"/c:/dir/file.html",S_OK},
6347             {"",S_FALSE},
6348             {"file:///c:/dir/file.html#",S_OK},
6349             {"file",S_OK},
6350             {"",S_FALSE},
6351             {"",S_FALSE}
6352         },
6353         {
6354             {Uri_HOST_UNKNOWN,S_OK},
6355             {0,S_FALSE},
6356             {URL_SCHEME_FILE,S_OK},
6357             {URLZONE_INVALID,E_NOTIMPL}
6358         }
6359     }
6360 };
6361 
6362 typedef struct _uri_builder_remove_test {
6363     const char  *uri;
6364     DWORD       create_flags;
6365     HRESULT     create_builder_expected;
6366     BOOL        create_builder_todo;
6367 
6368     DWORD       remove_properties;
6369     HRESULT     remove_expected;
6370     BOOL        remove_todo;
6371 
6372     const char  *expected_uri;
6373     DWORD       expected_flags;
6374     HRESULT     expected_hres;
6375     BOOL        expected_todo;
6376 } uri_builder_remove_test;
6377 
6378 static const uri_builder_remove_test uri_builder_remove_tests[] = {
6379     {   "http://google.com/test?test=y#Frag",0,S_OK,FALSE,
6380         Uri_HAS_FRAGMENT|Uri_HAS_PATH|Uri_HAS_QUERY,S_OK,FALSE,
6381         "http://google.com/",0,S_OK,FALSE
6382     },
6383     {   "http://user:pass@winehq.org/",0,S_OK,FALSE,
6384         Uri_HAS_USER_NAME|Uri_HAS_PASSWORD,S_OK,FALSE,
6385         "http://winehq.org/",0,S_OK,FALSE
6386     },
6387     {   "zip://google.com?Test=x",0,S_OK,FALSE,
6388         Uri_HAS_HOST,S_OK,FALSE,
6389         "zip:/?Test=x",0,S_OK,FALSE
6390     },
6391     /* Doesn't remove the whole userinfo component. */
6392     {   "http://username:pass@google.com/",0,S_OK,FALSE,
6393         Uri_HAS_USER_INFO,S_OK,FALSE,
6394         "http://username:pass@google.com/",0,S_OK,FALSE
6395     },
6396     /* Doesn't remove the domain. */
6397     {   "http://google.com/",0,S_OK,FALSE,
6398         Uri_HAS_DOMAIN,S_OK,FALSE,
6399         "http://google.com/",0,S_OK,FALSE
6400     },
6401     {   "http://google.com:120/",0,S_OK,FALSE,
6402         Uri_HAS_AUTHORITY,S_OK,FALSE,
6403         "http://google.com:120/",0,S_OK,FALSE
6404     },
6405     {   "http://google.com/test.com/",0,S_OK,FALSE,
6406         Uri_HAS_EXTENSION,S_OK,FALSE,
6407         "http://google.com/test.com/",0,S_OK,FALSE
6408     },
6409     {   "http://google.com/?test=x",0,S_OK,FALSE,
6410         Uri_HAS_PATH_AND_QUERY,S_OK,FALSE,
6411         "http://google.com/?test=x",0,S_OK,FALSE
6412     },
6413     /* Can't remove the scheme name. */
6414     {   "http://google.com/?test=x",0,S_OK,FALSE,
6415         Uri_HAS_SCHEME_NAME|Uri_HAS_QUERY,E_INVALIDARG,FALSE,
6416         "http://google.com/?test=x",0,S_OK,FALSE
6417     }
6418 };
6419 
6420 typedef struct _uri_combine_str_property {
6421     const char  *value;
6422     HRESULT     expected;
6423     BOOL        todo;
6424     const char  *broken_value;
6425     const char  *value_ex;
6426 } uri_combine_str_property;
6427 
6428 typedef struct _uri_combine_test {
6429     const char  *base_uri;
6430     DWORD       base_create_flags;
6431     const char  *relative_uri;
6432     DWORD       relative_create_flags;
6433     DWORD       combine_flags;
6434     HRESULT     expected;
6435     BOOL        todo;
6436 
6437     uri_combine_str_property    str_props[URI_STR_PROPERTY_COUNT];
6438     uri_dword_property          dword_props[URI_DWORD_PROPERTY_COUNT];
6439 } uri_combine_test;
6440 
6441 static const uri_combine_test uri_combine_tests[] = {
6442     {   "http://google.com/fun/stuff",0,
6443         "../not/fun/stuff",Uri_CREATE_ALLOW_RELATIVE,
6444         0,S_OK,FALSE,
6445         {
6446             {"http://google.com/not/fun/stuff",S_OK},
6447             {"google.com",S_OK},
6448             {"http://google.com/not/fun/stuff",S_OK},
6449             {"google.com",S_OK},
6450             {"",S_FALSE},
6451             {"",S_FALSE},
6452             {"google.com",S_OK},
6453             {"",S_FALSE},
6454             {"/not/fun/stuff",S_OK},
6455             {"/not/fun/stuff",S_OK},
6456             {"",S_FALSE},
6457             {"http://google.com/not/fun/stuff",S_OK},
6458             {"http",S_OK},
6459             {"",S_FALSE},
6460             {"",S_FALSE}
6461         },
6462         {
6463             {Uri_HOST_DNS,S_OK},
6464             {80,S_OK},
6465             {URL_SCHEME_HTTP,S_OK},
6466             {URLZONE_INVALID,E_NOTIMPL}
6467         }
6468     },
6469     {   "http://google.com/test",0,
6470         "zip://test.com/cool",0,
6471         0,S_OK,FALSE,
6472         {
6473             {"zip://test.com/cool",S_OK},
6474             {"test.com",S_OK},
6475             {"zip://test.com/cool",S_OK},
6476             {"test.com",S_OK},
6477             {"",S_FALSE},
6478             {"",S_FALSE},
6479             {"test.com",S_OK},
6480             {"",S_FALSE},
6481             {"/cool",S_OK},
6482             {"/cool",S_OK},
6483             {"",S_FALSE},
6484             {"zip://test.com/cool",S_OK},
6485             {"zip",S_OK},
6486             {"",S_FALSE},
6487             {"",S_FALSE}
6488         },
6489         {
6490             {Uri_HOST_DNS,S_OK},
6491             {0,S_FALSE},
6492             {URL_SCHEME_UNKNOWN,S_OK},
6493             {URLZONE_INVALID,E_NOTIMPL}
6494         }
6495     },
6496     {   "http://google.com/use/base/path",0,
6497         "?relative",Uri_CREATE_ALLOW_RELATIVE,
6498         0,S_OK,FALSE,
6499         {
6500             {"http://google.com/use/base/path?relative",S_OK},
6501             {"google.com",S_OK},
6502             {"http://google.com/use/base/path?relative",S_OK},
6503             {"google.com",S_OK},
6504             {"",S_FALSE},
6505             {"",S_FALSE},
6506             {"google.com",S_OK},
6507             {"",S_FALSE},
6508             {"/use/base/path",S_OK},
6509             {"/use/base/path?relative",S_OK},
6510             {"?relative",S_OK},
6511             {"http://google.com/use/base/path?relative",S_OK},
6512             {"http",S_OK},
6513             {"",S_FALSE},
6514             {"",S_FALSE}
6515         },
6516         {
6517             {Uri_HOST_DNS,S_OK},
6518             {80,S_OK},
6519             {URL_SCHEME_HTTP,S_OK},
6520             {URLZONE_INVALID,E_NOTIMPL}
6521         }
6522     },
6523     {   "http://google.com/path",0,
6524         "/test/../test/.././testing",Uri_CREATE_ALLOW_RELATIVE,
6525         0,S_OK,FALSE,
6526         {
6527             {"http://google.com/testing",S_OK},
6528             {"google.com",S_OK},
6529             {"http://google.com/testing",S_OK},
6530             {"google.com",S_OK},
6531             {"",S_FALSE},
6532             {"",S_FALSE},
6533             {"google.com",S_OK},
6534             {"",S_FALSE},
6535             {"/testing",S_OK},
6536             {"/testing",S_OK},
6537             {"",S_FALSE},
6538             {"http://google.com/testing",S_OK},
6539             {"http",S_OK},
6540             {"",S_FALSE},
6541             {"",S_FALSE}
6542         },
6543         {
6544             {Uri_HOST_DNS,S_OK},
6545             {80,S_OK},
6546             {URL_SCHEME_HTTP,S_OK},
6547             {URLZONE_INVALID,E_NOTIMPL}
6548         }
6549     },
6550     {   "http://google.com/path",0,
6551         "/test/../test/.././testing",Uri_CREATE_ALLOW_RELATIVE,
6552         URL_DONT_SIMPLIFY,S_OK,FALSE,
6553         {
6554             {"http://google.com:80/test/../test/.././testing",S_OK},
6555             {"google.com",S_OK},
6556             {"http://google.com:80/test/../test/.././testing",S_OK},
6557             {"google.com",S_OK},
6558             {"",S_FALSE},
6559             {"",S_FALSE},
6560             {"google.com",S_OK},
6561             {"",S_FALSE},
6562             {"/test/../test/.././testing",S_OK},
6563             {"/test/../test/.././testing",S_OK},
6564             {"",S_FALSE},
6565             {"http://google.com:80/test/../test/.././testing",S_OK},
6566             {"http",S_OK},
6567             {"",S_FALSE},
6568             {"",S_FALSE}
6569         },
6570         {
6571             {Uri_HOST_DNS,S_OK},
6572             {80,S_OK},
6573             {URL_SCHEME_HTTP,S_OK},
6574             {URLZONE_INVALID,E_NOTIMPL}
6575         }
6576     },
6577     {   "http://winehq.org/test/abc",0,
6578         "testing/abc/../test",Uri_CREATE_ALLOW_RELATIVE,
6579         0,S_OK,FALSE,
6580         {
6581             {"http://winehq.org/test/testing/test",S_OK},
6582             {"winehq.org",S_OK},
6583             {"http://winehq.org/test/testing/test",S_OK},
6584             {"winehq.org",S_OK},
6585             {"",S_FALSE},
6586             {"",S_FALSE},
6587             {"winehq.org",S_OK},
6588             {"",S_FALSE},
6589             {"/test/testing/test",S_OK},
6590             {"/test/testing/test",S_OK},
6591             {"",S_FALSE},
6592             {"http://winehq.org/test/testing/test",S_OK},
6593             {"http",S_OK},
6594             {"",S_FALSE},
6595             {"",S_FALSE}
6596         },
6597         {
6598             {Uri_HOST_DNS,S_OK},
6599             {80,S_OK},
6600             {URL_SCHEME_HTTP,S_OK},
6601             {URLZONE_INVALID,E_NOTIMPL}
6602         }
6603     },
6604     {   "http://winehq.org/test/abc",0,
6605         "testing/abc/../test",Uri_CREATE_ALLOW_RELATIVE,
6606         URL_DONT_SIMPLIFY,S_OK,FALSE,
6607         {
6608             {"http://winehq.org:80/test/testing/abc/../test",S_OK},
6609             /* Default port is hidden in the authority. */
6610             {"winehq.org",S_OK},
6611             {"http://winehq.org:80/test/testing/abc/../test",S_OK},
6612             {"winehq.org",S_OK},
6613             {"",S_FALSE},
6614             {"",S_FALSE},
6615             {"winehq.org",S_OK},
6616             {"",S_FALSE},
6617             {"/test/testing/abc/../test",S_OK},
6618             {"/test/testing/abc/../test",S_OK},
6619             {"",S_FALSE},
6620             {"http://winehq.org:80/test/testing/abc/../test",S_OK},
6621             {"http",S_OK},
6622             {"",S_FALSE},
6623             {"",S_FALSE}
6624         },
6625         {
6626             {Uri_HOST_DNS,S_OK},
6627             {80,S_OK},
6628             {URL_SCHEME_HTTP,S_OK},
6629             {URLZONE_INVALID,E_NOTIMPL}
6630         }
6631     },
6632     {   "http://winehq.org/test?query",0,
6633         "testing",Uri_CREATE_ALLOW_RELATIVE,
6634         0,S_OK,FALSE,
6635         {
6636             {"http://winehq.org/testing",S_OK},
6637             {"winehq.org",S_OK},
6638             {"http://winehq.org/testing",S_OK},
6639             {"winehq.org",S_OK},
6640             {"",S_FALSE},
6641             {"",S_FALSE},
6642             {"winehq.org",S_OK},
6643             {"",S_FALSE},
6644             {"/testing",S_OK},
6645             {"/testing",S_OK},
6646             {"",S_FALSE},
6647             {"http://winehq.org/testing",S_OK},
6648             {"http",S_OK},
6649             {"",S_FALSE},
6650             {"",S_FALSE}
6651         },
6652         {
6653             {Uri_HOST_DNS,S_OK},
6654             {80,S_OK},
6655             {URL_SCHEME_HTTP,S_OK},
6656             {URLZONE_INVALID,E_NOTIMPL}
6657         }
6658     },
6659     {   "http://winehq.org/test#frag",0,
6660         "testing",Uri_CREATE_ALLOW_RELATIVE,
6661         0,S_OK,FALSE,
6662         {
6663             {"http://winehq.org/testing",S_OK},
6664             {"winehq.org",S_OK},
6665             {"http://winehq.org/testing",S_OK},
6666             {"winehq.org",S_OK},
6667             {"",S_FALSE},
6668             {"",S_FALSE},
6669             {"winehq.org",S_OK},
6670             {"",S_FALSE},
6671             {"/testing",S_OK},
6672             {"/testing",S_OK},
6673             {"",S_FALSE},
6674             {"http://winehq.org/testing",S_OK},
6675             {"http",S_OK},
6676             {"",S_FALSE},
6677             {"",S_FALSE}
6678         },
6679         {
6680             {Uri_HOST_DNS,S_OK},
6681             {80,S_OK},
6682             {URL_SCHEME_HTTP,S_OK},
6683             {URLZONE_INVALID,E_NOTIMPL}
6684         }
6685     },
6686     {   "testing?query#frag",Uri_CREATE_ALLOW_RELATIVE,
6687         "test",Uri_CREATE_ALLOW_RELATIVE,
6688         0,S_OK,FALSE,
6689         {
6690             {"test",S_OK},
6691             {"",S_FALSE},
6692             {"test",S_OK},
6693             {"",S_FALSE},
6694             {"",S_FALSE},
6695             {"",S_FALSE},
6696             {"",S_FALSE},
6697             {"",S_FALSE},
6698             {"test",S_OK},
6699             {"test",S_OK},
6700             {"",S_FALSE},
6701             {"test",S_OK},
6702             {"",S_FALSE},
6703             {"",S_FALSE},
6704             {"",S_FALSE}
6705         },
6706         {
6707             {Uri_HOST_UNKNOWN,S_OK},
6708             {0,S_FALSE},
6709             {URL_SCHEME_UNKNOWN,S_OK},
6710             {URLZONE_INVALID,E_NOTIMPL}
6711         }
6712     },
6713     {   "file:///c:/test/test",0,
6714         "/testing.mp3",Uri_CREATE_ALLOW_RELATIVE,
6715         URL_FILE_USE_PATHURL,S_OK,FALSE,
6716         {
6717             {"file://c:\\testing.mp3",S_OK},
6718             {"",S_FALSE},
6719             {"file://c:\\testing.mp3",S_OK},
6720             {"",S_FALSE},
6721             {".mp3",S_OK},
6722             {"",S_FALSE},
6723             {"",S_FALSE},
6724             {"",S_FALSE},
6725             {"c:\\testing.mp3",S_OK},
6726             {"c:\\testing.mp3",S_OK},
6727             {"",S_FALSE},
6728             {"file://c:\\testing.mp3",S_OK},
6729             {"file",S_OK},
6730             {"",S_FALSE},
6731             {"",S_FALSE}
6732         },
6733         {
6734             {Uri_HOST_UNKNOWN,S_OK},
6735             {0,S_FALSE},
6736             {URL_SCHEME_FILE,S_OK},
6737             {URLZONE_INVALID,E_NOTIMPL}
6738         }
6739     },
6740     {   "file:///c:/test/test",0,
6741         "/testing.mp3",Uri_CREATE_ALLOW_RELATIVE,
6742         0,S_OK,FALSE,
6743         {
6744             {"file:///c:/testing.mp3",S_OK},
6745             {"",S_FALSE},
6746             {"file:///c:/testing.mp3",S_OK},
6747             {"",S_FALSE},
6748             {".mp3",S_OK},
6749             {"",S_FALSE},
6750             {"",S_FALSE},
6751             {"",S_FALSE},
6752             {"/c:/testing.mp3",S_OK},
6753             {"/c:/testing.mp3",S_OK},
6754             {"",S_FALSE},
6755             {"file:///c:/testing.mp3",S_OK},
6756             {"file",S_OK},
6757             {"",S_FALSE},
6758             {"",S_FALSE}
6759         },
6760         {
6761             {Uri_HOST_UNKNOWN,S_OK},
6762             {0,S_FALSE},
6763             {URL_SCHEME_FILE,S_OK},
6764             {URLZONE_INVALID,E_NOTIMPL}
6765         }
6766     },
6767     {   "file://test.com/test/test",0,
6768         "/testing.mp3",Uri_CREATE_ALLOW_RELATIVE,
6769         URL_FILE_USE_PATHURL,S_OK,FALSE,
6770         {
6771             {"file://\\\\test.com\\testing.mp3",S_OK},
6772             {"test.com",S_OK},
6773             {"file://\\\\test.com\\testing.mp3",S_OK},
6774             {"test.com",S_OK},
6775             {".mp3",S_OK},
6776             {"",S_FALSE},
6777             {"test.com",S_OK},
6778             {"",S_FALSE},
6779             {"\\testing.mp3",S_OK},
6780             {"\\testing.mp3",S_OK},
6781             {"",S_FALSE},
6782             {"file://\\\\test.com\\testing.mp3",S_OK},
6783             {"file",S_OK},
6784             {"",S_FALSE},
6785             {"",S_FALSE}
6786         },
6787         {
6788             {Uri_HOST_DNS,S_OK},
6789             {0,S_FALSE},
6790             {URL_SCHEME_FILE,S_OK},
6791             {URLZONE_INVALID,E_NOTIMPL}
6792         }
6793     },
6794     /* URL_DONT_SIMPLIFY has no effect. */
6795     {   "http://google.com/test",0,
6796         "zip://test.com/cool/../cool/test",0,
6797         URL_DONT_SIMPLIFY,S_OK,FALSE,
6798         {
6799             {"zip://test.com/cool/test",S_OK,FALSE,NULL,"zip://test.com/cool/../cool/test"},
6800             {"test.com",S_OK},
6801             {"zip://test.com/cool/test",S_OK,FALSE,NULL,"zip://test.com/cool/../cool/test"},
6802             {"test.com",S_OK},
6803             {"",S_FALSE},
6804             {"",S_FALSE},
6805             {"test.com",S_OK},
6806             {"",S_FALSE},
6807             {"/cool/test",S_OK,FALSE,NULL,"/cool/../cool/test"},
6808             {"/cool/test",S_OK,FALSE,NULL,"/cool/../cool/test"},
6809             {"",S_FALSE},
6810             /* The resulting IUri has the same Raw URI as the relative URI (only IE 8).
6811              * On IE 7 it reduces the path in the Raw URI.
6812              */
6813             {"zip://test.com/cool/../cool/test",S_OK,FALSE,"zip://test.com/cool/test"},
6814             {"zip",S_OK},
6815             {"",S_FALSE},
6816             {"",S_FALSE}
6817         },
6818         {
6819             {Uri_HOST_DNS,S_OK},
6820             {0,S_FALSE},
6821             {URL_SCHEME_UNKNOWN,S_OK},
6822             {URLZONE_INVALID,E_NOTIMPL}
6823         }
6824     },
6825     /* FILE_USE_PATHURL has no effect in IE 8, in IE 7 the
6826      * resulting URI is converted into a dos path.
6827      */
6828     {   "http://google.com/test",0,
6829         "file:///c:/test/",0,
6830         URL_FILE_USE_PATHURL,S_OK,FALSE,
6831         {
6832             {"file:///c:/test/",S_OK,FALSE,"file://c:\\test\\"},
6833             {"",S_FALSE},
6834             {"file:///c:/test/",S_OK,FALSE,"file://c:\\test\\"},
6835             {"",S_FALSE},
6836             {"",S_FALSE},
6837             {"",S_FALSE},
6838             {"",S_FALSE},
6839             {"",S_FALSE},
6840             {"/c:/test/",S_OK,FALSE,"c:\\test\\"},
6841             {"/c:/test/",S_OK,FALSE,"c:\\test\\"},
6842             {"",S_FALSE},
6843             {"file:///c:/test/",S_OK,FALSE,"file://c:\\test\\"},
6844             {"file",S_OK},
6845             {"",S_FALSE},
6846             {"",S_FALSE}
6847         },
6848         {
6849             {Uri_HOST_UNKNOWN,S_OK},
6850             {0,S_FALSE},
6851             {URL_SCHEME_FILE,S_OK},
6852             {URLZONE_INVALID,E_NOTIMPL}
6853         }
6854     },
6855     {   "http://google.com/test",0,
6856         "http://test.com/test#%30test",0,
6857         URL_DONT_UNESCAPE_EXTRA_INFO,S_OK,FALSE,
6858         {
6859             {"http://test.com/test#0test",S_OK,FALSE,NULL,"http://test.com/test#%30test"},
6860             {"test.com",S_OK},
6861             {"http://test.com/test#0test",S_OK,FALSE,NULL,"http://test.com/test#%30test"},
6862             {"test.com",S_OK},
6863             {"",S_FALSE},
6864             {"#0test",S_OK,FALSE,NULL,"#%30test"},
6865             {"test.com",S_OK},
6866             {"",S_FALSE},
6867             {"/test",S_OK},
6868             {"/test",S_OK},
6869             {"",S_FALSE},
6870             /* IE 7 decodes the %30 to a 0 in the Raw URI. */
6871             {"http://test.com/test#%30test",S_OK,FALSE,"http://test.com/test#0test"},
6872             {"http",S_OK},
6873             {"",S_FALSE},
6874             {"",S_FALSE}
6875         },
6876         {
6877             {Uri_HOST_DNS,S_OK},
6878             {80,S_OK},
6879             {URL_SCHEME_HTTP,S_OK},
6880             {URLZONE_INVALID,E_NOTIMPL}
6881         }
6882     },
6883     /* Windows validates the path component from the relative Uri. */
6884     {   "http://google.com/test",0,
6885         "/Te%XXst",Uri_CREATE_ALLOW_RELATIVE,
6886         0,E_INVALIDARG,FALSE
6887     },
6888     /* Windows doesn't validate the query from the relative Uri. */
6889     {   "http://google.com/test",0,
6890         "?Tes%XXt",Uri_CREATE_ALLOW_RELATIVE,
6891         0,S_OK,FALSE,
6892         {
6893             {"http://google.com/test?Tes%XXt",S_OK},
6894             {"google.com",S_OK},
6895             {"http://google.com/test?Tes%XXt",S_OK},
6896             {"google.com",S_OK},
6897             {"",S_FALSE},
6898             {"",S_FALSE},
6899             {"google.com",S_OK},
6900             {"",S_FALSE},
6901             {"/test",S_OK},
6902             {"/test?Tes%XXt",S_OK},
6903             {"?Tes%XXt",S_OK},
6904             {"http://google.com/test?Tes%XXt",S_OK},
6905             {"http",S_OK},
6906             {"",S_FALSE},
6907             {"",S_FALSE}
6908         },
6909         {
6910             {Uri_HOST_DNS,S_OK},
6911             {80,S_OK},
6912             {URL_SCHEME_HTTP,S_OK},
6913             {URLZONE_INVALID,E_NOTIMPL}
6914         }
6915     },
6916     /* Windows doesn't validate the fragment from the relative Uri. */
6917     {   "http://google.com/test",0,
6918         "#Tes%XXt",Uri_CREATE_ALLOW_RELATIVE,
6919         0,S_OK,FALSE,
6920         {
6921             {"http://google.com/test#Tes%XXt",S_OK},
6922             {"google.com",S_OK},
6923             {"http://google.com/test#Tes%XXt",S_OK},
6924             {"google.com",S_OK},
6925             {"",S_FALSE},
6926             {"#Tes%XXt",S_OK},
6927             {"google.com",S_OK},
6928             {"",S_FALSE},
6929             {"/test",S_OK},
6930             {"/test",S_OK},
6931             {"",S_FALSE},
6932             {"http://google.com/test#Tes%XXt",S_OK},
6933             {"http",S_OK},
6934             {"",S_FALSE},
6935             {"",S_FALSE}
6936         },
6937         {
6938             {Uri_HOST_DNS,S_OK},
6939             {80,S_OK},
6940             {URL_SCHEME_HTTP,S_OK},
6941             {URLZONE_INVALID,E_NOTIMPL}
6942         }
6943     },
6944     /* Creates an IUri which contains an invalid dos path char. */
6945     {   "file:///c:/test",0,
6946         "/test<ing",Uri_CREATE_ALLOW_RELATIVE,
6947         URL_FILE_USE_PATHURL,S_OK,FALSE,
6948         {
6949             {"file://c:\\test<ing",S_OK},
6950             {"",S_FALSE},
6951             {"file://c:\\test<ing",S_OK},
6952             {"",S_FALSE},
6953             {"",S_FALSE},
6954             {"",S_FALSE},
6955             {"",S_FALSE},
6956             {"",S_FALSE},
6957             {"c:\\test<ing",S_OK},
6958             {"c:\\test<ing",S_OK},
6959             {"",S_FALSE},
6960             {"file://c:\\test<ing",S_OK},
6961             {"file",S_OK},
6962             {"",S_FALSE},
6963             {"",S_FALSE}
6964         },
6965         {
6966             {Uri_HOST_UNKNOWN,S_OK},
6967             {0,S_FALSE},
6968             {URL_SCHEME_FILE,S_OK},
6969             {URLZONE_INVALID,E_NOTIMPL}
6970         }
6971     },
6972     /* Appends the path after the drive letter (if any). */
6973     {   "file:///c:/test",0,
6974         "/c:/testing",Uri_CREATE_ALLOW_RELATIVE,
6975         0,S_OK,FALSE,
6976         {
6977             {"file:///c:/c:/testing",S_OK},
6978             {"",S_FALSE},
6979             {"file:///c:/c:/testing",S_OK},
6980             {"",S_FALSE},
6981             {"",S_FALSE},
6982             {"",S_FALSE},
6983             {"",S_FALSE},
6984             {"",S_FALSE},
6985             {"/c:/c:/testing",S_OK},
6986             {"/c:/c:/testing",S_OK},
6987             {"",S_FALSE},
6988             {"file:///c:/c:/testing",S_OK},
6989             {"file",S_OK},
6990             {"",S_FALSE},
6991             {"",S_FALSE}
6992         },
6993         {
6994             {Uri_HOST_UNKNOWN,S_OK},
6995             {0,S_FALSE},
6996             {URL_SCHEME_FILE,S_OK},
6997             {URLZONE_INVALID,E_NOTIMPL}
6998         }
6999     },
7000     /* A '/' is added if the base URI doesn't have a path and the
7001      * relative URI doesn't contain a path (since the base URI is
7002      * hierarchical.
7003      */
7004     {   "http://google.com",Uri_CREATE_NO_CANONICALIZE,
7005         "?test",Uri_CREATE_ALLOW_RELATIVE,
7006         0,S_OK,FALSE,
7007         {
7008             {"http://google.com/?test",S_OK},
7009             {"google.com",S_OK},
7010             {"http://google.com/?test",S_OK},
7011             {"google.com",S_OK},
7012             {"",S_FALSE},
7013             {"",S_FALSE},
7014             {"google.com",S_OK},
7015             {"",S_FALSE},
7016             {"/",S_OK},
7017             {"/?test",S_OK},
7018             {"?test",S_OK},
7019             {"http://google.com/?test",S_OK},
7020             {"http",S_OK},
7021             {"",S_FALSE},
7022             {"",S_FALSE}
7023         },
7024         {
7025             {Uri_HOST_DNS,S_OK},
7026             {80,S_OK},
7027             {URL_SCHEME_HTTP,S_OK},
7028             {URLZONE_INVALID,E_NOTIMPL}
7029         }
7030     },
7031     {   "zip://google.com",Uri_CREATE_NO_CANONICALIZE,
7032         "?test",Uri_CREATE_ALLOW_RELATIVE,
7033         0,S_OK,FALSE,
7034         {
7035             {"zip://google.com/?test",S_OK},
7036             {"google.com",S_OK},
7037             {"zip://google.com/?test",S_OK},
7038             {"google.com",S_OK},
7039             {"",S_FALSE},
7040             {"",S_FALSE},
7041             {"google.com",S_OK},
7042             {"",S_FALSE},
7043             {"/",S_OK},
7044             {"/?test",S_OK},
7045             {"?test",S_OK},
7046             {"zip://google.com/?test",S_OK},
7047             {"zip",S_OK},
7048             {"",S_FALSE},
7049             {"",S_FALSE}
7050         },
7051         {
7052             {Uri_HOST_DNS,S_OK},
7053             {0,S_FALSE},
7054             {URL_SCHEME_UNKNOWN,S_OK},
7055             {URLZONE_INVALID,E_NOTIMPL}
7056         }
7057     },
7058     /* No path is appended since the base URI is opaque. */
7059     {   "zip:?testing",0,
7060         "?test",Uri_CREATE_ALLOW_RELATIVE,
7061         0,S_OK,FALSE,
7062         {
7063             {"zip:?test",S_OK},
7064             {"",S_FALSE},
7065             {"zip:?test",S_OK},
7066             {"",S_FALSE},
7067             {"",S_FALSE},
7068             {"",S_FALSE},
7069             {"",S_FALSE},
7070             {"",S_FALSE},
7071             {"",S_OK},
7072             {"?test",S_OK},
7073             {"?test",S_OK},
7074             {"zip:?test",S_OK},
7075             {"zip",S_OK},
7076             {"",S_FALSE},
7077             {"",S_FALSE}
7078         },
7079         {
7080             {Uri_HOST_UNKNOWN,S_OK},
7081             {0,S_FALSE},
7082             {URL_SCHEME_UNKNOWN,S_OK},
7083             {URLZONE_INVALID,E_NOTIMPL}
7084         }
7085     },
7086     {   "file:///c:/",0,
7087         "../testing/test",Uri_CREATE_ALLOW_RELATIVE,
7088         0,S_OK,FALSE,
7089         {
7090             {"file:///c:/testing/test",S_OK},
7091             {"",S_FALSE},
7092             {"file:///c:/testing/test",S_OK},
7093             {"",S_FALSE},
7094             {"",S_FALSE},
7095             {"",S_FALSE},
7096             {"",S_FALSE},
7097             {"",S_FALSE},
7098             {"/c:/testing/test",S_OK},
7099             {"/c:/testing/test",S_OK},
7100             {"",S_FALSE},
7101             {"file:///c:/testing/test",S_OK},
7102             {"file",S_OK},
7103             {"",S_FALSE},
7104             {"",S_FALSE}
7105         },
7106         {
7107             {Uri_HOST_UNKNOWN,S_OK},
7108             {0,S_FALSE},
7109             {URL_SCHEME_FILE,S_OK},
7110             {URLZONE_INVALID,E_NOTIMPL}
7111         }
7112     },
7113     {   "http://winehq.org/dir/testfile",0,
7114         "test?querystring",Uri_CREATE_ALLOW_RELATIVE,
7115         0,S_OK,FALSE,
7116         {
7117             {"http://winehq.org/dir/test?querystring",S_OK},
7118             {"winehq.org",S_OK},
7119             {"http://winehq.org/dir/test?querystring",S_OK},
7120             {"winehq.org",S_OK},
7121             {"",S_FALSE},
7122             {"",S_FALSE},
7123             {"winehq.org",S_OK},
7124             {"",S_FALSE},
7125             {"/dir/test",S_OK},
7126             {"/dir/test?querystring",S_OK},
7127             {"?querystring",S_OK},
7128             {"http://winehq.org/dir/test?querystring",S_OK},
7129             {"http",S_OK},
7130             {"",S_FALSE},
7131             {"",S_FALSE}
7132         },
7133         {
7134             {Uri_HOST_DNS,S_OK},
7135             {80,S_OK},
7136             {URL_SCHEME_HTTP,S_OK},
7137             {URLZONE_INVALID,E_NOTIMPL}
7138         }
7139     },
7140     {   "http://winehq.org/dir/test",0,
7141         "test?querystring",Uri_CREATE_ALLOW_RELATIVE,
7142         0,S_OK,FALSE,
7143         {
7144             {"http://winehq.org/dir/test?querystring",S_OK},
7145             {"winehq.org",S_OK},
7146             {"http://winehq.org/dir/test?querystring",S_OK},
7147             {"winehq.org",S_OK},
7148             {"",S_FALSE},
7149             {"",S_FALSE},
7150             {"winehq.org",S_OK},
7151             {"",S_FALSE},
7152             {"/dir/test",S_OK},
7153             {"/dir/test?querystring",S_OK},
7154             {"?querystring",S_OK},
7155             {"http://winehq.org/dir/test?querystring",S_OK},
7156             {"http",S_OK},
7157             {"",S_FALSE},
7158             {"",S_FALSE}
7159         },
7160         {
7161             {Uri_HOST_DNS,S_OK},
7162             {80,S_OK},
7163             {URL_SCHEME_HTTP,S_OK},
7164             {URLZONE_INVALID,E_NOTIMPL}
7165         }
7166     },
7167     {   "http://winehq.org/dir/test?querystring",0,
7168         "#hash",Uri_CREATE_ALLOW_RELATIVE,
7169         0,S_OK,FALSE,
7170         {
7171             {"http://winehq.org/dir/test?querystring#hash",S_OK},
7172             {"winehq.org",S_OK},
7173             {"http://winehq.org/dir/test?querystring#hash",S_OK},
7174             {"winehq.org",S_OK},
7175             {"",S_FALSE},
7176             {"#hash",S_OK},
7177             {"winehq.org",S_OK},
7178             {"",S_FALSE},
7179             {"/dir/test",S_OK},
7180             {"/dir/test?querystring",S_OK},
7181             {"?querystring",S_OK},
7182             {"http://winehq.org/dir/test?querystring#hash",S_OK},
7183             {"http",S_OK},
7184             {"",S_FALSE},
7185             {"",S_FALSE}
7186         },
7187         {
7188             {Uri_HOST_DNS,S_OK},
7189             {80,S_OK},
7190             {URL_SCHEME_HTTP,S_OK},
7191             {URLZONE_INVALID,E_NOTIMPL}
7192         }
7193     },
7194     {   "mk:@MSITSTORE:C:\\Some\\Bogus\\Path.chm::/subdir\\file.txt",0,
7195         "relative/path.txt",Uri_CREATE_ALLOW_RELATIVE,
7196         0,S_OK,FALSE,
7197         {
7198             {"mk:@MSITSTORE:C:\\Some\\Bogus\\Path.chm::/subdir/relative/path.txt",S_OK},
7199             {"",S_FALSE},
7200             {"mk:@MSITSTORE:C:\\Some\\Bogus\\Path.chm::/subdir/relative/path.txt",S_OK},
7201             {"",S_FALSE},
7202             {".txt",S_OK},
7203             {"",S_FALSE},
7204             {"",S_FALSE},
7205             {"",S_FALSE},
7206             {"@MSITSTORE:C:\\Some\\Bogus\\Path.chm::/subdir/relative/path.txt",S_OK},
7207             {"@MSITSTORE:C:\\Some\\Bogus\\Path.chm::/subdir/relative/path.txt",S_OK},
7208             {"",S_FALSE},
7209             {"mk:@MSITSTORE:C:\\Some\\Bogus\\Path.chm::/subdir/relative/path.txt",S_OK},
7210             {"mk",S_OK},
7211             {"",S_FALSE},
7212             {"",S_FALSE}
7213         },
7214         {
7215             {Uri_HOST_UNKNOWN,S_OK},
7216             {0,S_FALSE},
7217             {URL_SCHEME_MK,S_OK},
7218             {URLZONE_INVALID,E_NOTIMPL}
7219         }
7220     },
7221     {   "mk:@MSITSTORE:C:\\Some\\Bogus\\Path.chm::\\subdir\\file.txt",0,
7222         "relative/path.txt",Uri_CREATE_ALLOW_RELATIVE,
7223         0,S_OK,FALSE,
7224         {
7225             {"mk:@MSITSTORE:C:\\Some\\Bogus\\Path.chm::/subdir/relative/path.txt",S_OK},
7226             {"",S_FALSE},
7227             {"mk:@MSITSTORE:C:\\Some\\Bogus\\Path.chm::/subdir/relative/path.txt",S_OK},
7228             {"",S_FALSE},
7229             {".txt",S_OK},
7230             {"",S_FALSE},
7231             {"",S_FALSE},
7232             {"",S_FALSE},
7233             {"@MSITSTORE:C:\\Some\\Bogus\\Path.chm::/subdir/relative/path.txt",S_OK},
7234             {"@MSITSTORE:C:\\Some\\Bogus\\Path.chm::/subdir/relative/path.txt",S_OK},
7235             {"",S_FALSE},
7236             {"mk:@MSITSTORE:C:\\Some\\Bogus\\Path.chm::/subdir/relative/path.txt",S_OK},
7237             {"mk",S_OK},
7238             {"",S_FALSE},
7239             {"",S_FALSE}
7240         },
7241         {
7242             {Uri_HOST_UNKNOWN,S_OK},
7243             {0,S_FALSE},
7244             {URL_SCHEME_MK,S_OK},
7245             {URLZONE_INVALID,E_NOTIMPL}
7246         }
7247     },
7248     {   "mk:@MSITSTORE:C:/Some\\Bogus/Path.chm::/subdir\\file.txt",0,
7249         "relative\\path.txt",Uri_CREATE_ALLOW_RELATIVE,
7250         0,S_OK,FALSE,
7251         {
7252             {"mk:@MSITSTORE:C:/Some\\Bogus/Path.chm::/subdir/relative/path.txt",S_OK},
7253             {"",S_FALSE},
7254             {"mk:@MSITSTORE:C:/Some\\Bogus/Path.chm::/subdir/relative/path.txt",S_OK},
7255             {"",S_FALSE},
7256             {".txt",S_OK},
7257             {"",S_FALSE},
7258             {"",S_FALSE},
7259             {"",S_FALSE},
7260             {"@MSITSTORE:C:/Some\\Bogus/Path.chm::/subdir/relative/path.txt",S_OK},
7261             {"@MSITSTORE:C:/Some\\Bogus/Path.chm::/subdir/relative/path.txt",S_OK},
7262             {"",S_FALSE},
7263             {"mk:@MSITSTORE:C:/Some\\Bogus/Path.chm::/subdir/relative/path.txt",S_OK},
7264             {"mk",S_OK},
7265             {"",S_FALSE},
7266             {"",S_FALSE}
7267         },
7268         {
7269             {Uri_HOST_UNKNOWN,S_OK},
7270             {0,S_FALSE},
7271             {URL_SCHEME_MK,S_OK},
7272             {URLZONE_INVALID,E_NOTIMPL}
7273         }
7274     },
7275     {   "mk:@MSITSTORE:C:\\dir\\file.chm::/subdir/file.txt",0,
7276         "/relative/path.txt",Uri_CREATE_ALLOW_RELATIVE,
7277         0,S_OK,FALSE,
7278         {
7279             {"mk:@MSITSTORE:C:\\dir\\file.chm::/relative/path.txt",S_OK},
7280             {"",S_FALSE},
7281             {"mk:@MSITSTORE:C:\\dir\\file.chm::/relative/path.txt",S_OK},
7282             {"",S_FALSE},
7283             {".txt",S_OK},
7284             {"",S_FALSE},
7285             {"",S_FALSE},
7286             {"",S_FALSE},
7287             {"@MSITSTORE:C:\\dir\\file.chm::/relative/path.txt",S_OK},
7288             {"@MSITSTORE:C:\\dir\\file.chm::/relative/path.txt",S_OK},
7289             {"",S_FALSE},
7290             {"mk:@MSITSTORE:C:\\dir\\file.chm::/relative/path.txt",S_OK},
7291             {"mk",S_OK},
7292             {"",S_FALSE},
7293             {"",S_FALSE}
7294         },
7295         {
7296             {Uri_HOST_UNKNOWN,S_OK},
7297             {0,S_FALSE},
7298             {URL_SCHEME_MK,S_OK},
7299             {URLZONE_INVALID,E_NOTIMPL}
7300         }
7301     },
7302     {   "mk:MSITSTORE:C:\\dir\\file.chm::/subdir/file.txt",0,
7303         "/relative/path.txt",Uri_CREATE_ALLOW_RELATIVE,
7304         0,S_OK,FALSE,
7305         {
7306             {"mk:MSITSTORE:C:\\dir\\file.chm::/relative/path.txt",S_OK},
7307             {"",S_FALSE},
7308             {"mk:MSITSTORE:C:\\dir\\file.chm::/relative/path.txt",S_OK},
7309             {"",S_FALSE},
7310             {".txt",S_OK},
7311             {"",S_FALSE},
7312             {"",S_FALSE},
7313             {"",S_FALSE},
7314             {"MSITSTORE:C:\\dir\\file.chm::/relative/path.txt",S_OK},
7315             {"MSITSTORE:C:\\dir\\file.chm::/relative/path.txt",S_OK},
7316             {"",S_FALSE},
7317             {"mk:MSITSTORE:C:\\dir\\file.chm::/relative/path.txt",S_OK},
7318             {"mk",S_OK},
7319             {"",S_FALSE},
7320             {"",S_FALSE}
7321         },
7322         {
7323             {Uri_HOST_UNKNOWN,S_OK},
7324             {0,S_FALSE},
7325             {URL_SCHEME_MK,S_OK},
7326             {URLZONE_INVALID,E_NOTIMPL}
7327         }
7328     },
7329     {   "mk:@MSITSTORE:C:\\dir\\file.chm::/subdir/../../file.txt",0,
7330         "/relative/path.txt",Uri_CREATE_ALLOW_RELATIVE,
7331         0,S_OK,FALSE,
7332         {
7333             {"mk:@MSITSTORE:/relative/path.txt",S_OK},
7334             {"",S_FALSE},
7335             {"mk:@MSITSTORE:/relative/path.txt",S_OK},
7336             {"",S_FALSE},
7337             {".txt",S_OK},
7338             {"",S_FALSE},
7339             {"",S_FALSE},
7340             {"",S_FALSE},
7341             {"@MSITSTORE:/relative/path.txt",S_OK},
7342             {"@MSITSTORE:/relative/path.txt",S_OK},
7343             {"",S_FALSE},
7344             {"mk:@MSITSTORE:/relative/path.txt",S_OK},
7345             {"mk",S_OK},
7346             {"",S_FALSE},
7347             {"",S_FALSE}
7348         },
7349         {
7350             {Uri_HOST_UNKNOWN,S_OK},
7351             {0,S_FALSE},
7352             {URL_SCHEME_MK,S_OK},
7353             {URLZONE_INVALID,E_NOTIMPL}
7354         }
7355     },
7356     {   "mk:@xxx:C:\\dir\\file.chm::/subdir/../../file.txt",0,
7357         "/relative/path.txt",Uri_CREATE_ALLOW_RELATIVE,
7358         0,S_OK,FALSE,
7359         {
7360             {"mk:@xxx:/relative/path.txt",S_OK},
7361             {"",S_FALSE},
7362             {"mk:@xxx:/relative/path.txt",S_OK},
7363             {"",S_FALSE},
7364             {".txt",S_OK},
7365             {"",S_FALSE},
7366             {"",S_FALSE},
7367             {"",S_FALSE},
7368             {"@xxx:/relative/path.txt",S_OK},
7369             {"@xxx:/relative/path.txt",S_OK},
7370             {"",S_FALSE},
7371             {"mk:@xxx:/relative/path.txt",S_OK},
7372             {"mk",S_OK},
7373             {"",S_FALSE},
7374             {"",S_FALSE}
7375         },
7376         {
7377             {Uri_HOST_UNKNOWN,S_OK},
7378             {0,S_FALSE},
7379             {URL_SCHEME_MK,S_OK},
7380             {URLZONE_INVALID,E_NOTIMPL}
7381         }
7382     },
7383     {   "mk:xxx:C:\\dir\\file.chm::/subdir/../../file.txt",0,
7384         "/relative/path.txt",Uri_CREATE_ALLOW_RELATIVE,
7385         0,S_OK,FALSE,
7386         {
7387             {"mk:/relative/path.txt",S_OK},
7388             {"",S_FALSE},
7389             {"mk:/relative/path.txt",S_OK},
7390             {"",S_FALSE},
7391             {".txt",S_OK},
7392             {"",S_FALSE},
7393             {"",S_FALSE},
7394             {"",S_FALSE},
7395             {"/relative/path.txt",S_OK},
7396             {"/relative/path.txt",S_OK},
7397             {"",S_FALSE},
7398             {"mk:/relative/path.txt",S_OK},
7399             {"mk",S_OK},
7400             {"",S_FALSE},
7401             {"",S_FALSE}
7402         },
7403         {
7404             {Uri_HOST_UNKNOWN,S_OK},
7405             {0,S_FALSE},
7406             {URL_SCHEME_MK,S_OK},
7407             {URLZONE_INVALID,E_NOTIMPL}
7408         }
7409     },
7410     {   "ml:@MSITSTORE:C:\\dir\\file.chm::/subdir/file.txt",0,
7411         "/relative/path.txt",Uri_CREATE_ALLOW_RELATIVE,
7412         0,S_OK,FALSE,
7413         {
7414             {"ml:/relative/path.txt",S_OK},
7415             {"",S_FALSE},
7416             {"ml:/relative/path.txt",S_OK},
7417             {"",S_FALSE},
7418             {".txt",S_OK},
7419             {"",S_FALSE},
7420             {"",S_FALSE},
7421             {"",S_FALSE},
7422             {"/relative/path.txt",S_OK},
7423             {"/relative/path.txt",S_OK},
7424             {"",S_FALSE},
7425             {"ml:/relative/path.txt",S_OK},
7426             {"ml",S_OK},
7427             {"",S_FALSE},
7428             {"",S_FALSE}
7429         },
7430         {
7431             {Uri_HOST_UNKNOWN,S_OK},
7432             {0,S_FALSE},
7433             {URL_SCHEME_UNKNOWN,S_OK},
7434             {URLZONE_INVALID,E_NOTIMPL}
7435         }
7436     },
7437     {   "http://winehq.org/dir/test?querystring",0,
7438         "//winehq.com/#hash",Uri_CREATE_ALLOW_RELATIVE,
7439         0,S_OK,FALSE,
7440         {
7441             {"http://winehq.com/#hash",S_OK},
7442             {"winehq.com",S_OK},
7443             {"http://winehq.com/#hash",S_OK},
7444             {"winehq.com",S_OK},
7445             {"",S_FALSE},
7446             {"#hash",S_OK},
7447             {"winehq.com",S_OK},
7448             {"",S_FALSE},
7449             {"/",S_OK},
7450             {"/",S_OK},
7451             {"",S_FALSE},
7452             {"http://winehq.com/#hash",S_OK},
7453             {"http",S_OK},
7454             {"",S_FALSE},
7455             {"",S_FALSE}
7456         },
7457         {
7458             {Uri_HOST_DNS,S_OK},
7459             {80,S_OK,FALSE,TRUE},
7460             {URL_SCHEME_HTTP,S_OK},
7461             {URLZONE_INVALID,E_NOTIMPL}
7462         }
7463     },
7464     {   "http://winehq.org/dir/test?querystring",0,
7465         "//winehq.com/dir2/../dir/file.txt?query#hash",Uri_CREATE_ALLOW_RELATIVE,
7466         0,S_OK,FALSE,
7467         {
7468             {"http://winehq.com/dir/file.txt?query#hash",S_OK},
7469             {"winehq.com",S_OK},
7470             {"http://winehq.com/dir/file.txt?query#hash",S_OK},
7471             {"winehq.com",S_OK},
7472             {".txt",S_OK},
7473             {"#hash",S_OK},
7474             {"winehq.com",S_OK},
7475             {"",S_FALSE},
7476             {"/dir/file.txt",S_OK},
7477             {"/dir/file.txt?query",S_OK},
7478             {"?query",S_OK},
7479             {"http://winehq.com/dir/file.txt?query#hash",S_OK},
7480             {"http",S_OK},
7481             {"",S_FALSE},
7482             {"",S_FALSE}
7483         },
7484         {
7485             {Uri_HOST_DNS,S_OK},
7486             {80,S_OK,FALSE,TRUE},
7487             {URL_SCHEME_HTTP,S_OK},
7488             {URLZONE_INVALID,E_NOTIMPL}
7489         }
7490     },
7491     {   "http://google.com/test",0,
7492         "c:\\test\\", Uri_CREATE_ALLOW_IMPLICIT_FILE_SCHEME,
7493         0,S_OK,FALSE,
7494         {
7495             {"file:///c:/test/",S_OK},
7496             {"",S_FALSE},
7497             {"file:///c:/test/",S_OK},
7498             {"",S_FALSE},
7499             {"",S_FALSE},
7500             {"",S_FALSE},
7501             {"",S_FALSE},
7502             {"",S_FALSE},
7503             {"/c:/test/",S_OK},
7504             {"/c:/test/",S_OK},
7505             {"",S_FALSE},
7506             {"c:\\test\\",S_OK,FALSE,"file:///c:/test/"},
7507             {"file",S_OK},
7508             {"",S_FALSE},
7509             {"",S_FALSE}
7510         },
7511         {
7512             {Uri_HOST_UNKNOWN,S_OK},
7513             {0,S_FALSE},
7514             {URL_SCHEME_FILE,S_OK},
7515             {URLZONE_INVALID,E_NOTIMPL}
7516         }
7517     },
7518     {   "http://google.com/test",0,
7519         "c:\\test\\", Uri_CREATE_ALLOW_IMPLICIT_FILE_SCHEME,
7520         0,S_OK,FALSE,
7521         {
7522             {"file:///c:/test/",S_OK},
7523             {"",S_FALSE},
7524             {"file:///c:/test/",S_OK},
7525             {"",S_FALSE},
7526             {"",S_FALSE},
7527             {"",S_FALSE},
7528             {"",S_FALSE},
7529             {"",S_FALSE},
7530             {"/c:/test/",S_OK},
7531             {"/c:/test/",S_OK},
7532             {"",S_FALSE},
7533             {"c:\\test\\",S_OK,FALSE,"file:///c:/test/"},
7534             {"file",S_OK},
7535             {"",S_FALSE},
7536             {"",S_FALSE}
7537         },
7538         {
7539             {Uri_HOST_UNKNOWN,S_OK},
7540             {0,S_FALSE},
7541             {URL_SCHEME_FILE,S_OK},
7542             {URLZONE_INVALID,E_NOTIMPL}
7543         }
7544     },
7545     {   "http://winehq.org",0,
7546         "mailto://",Uri_CREATE_NO_CANONICALIZE,
7547         0,S_OK,FALSE,
7548         {
7549             {"mailto:",S_OK},
7550             {"",S_FALSE},
7551             {"mailto:",S_OK},
7552             {"",S_FALSE},
7553             {"",S_FALSE},
7554             {"",S_FALSE},
7555             {"",S_FALSE},
7556             {"",S_FALSE},
7557             {"",S_FALSE},
7558             {"",S_FALSE},
7559             {"",S_FALSE},
7560             {"mailto://",S_OK,FALSE,"mailto:"},
7561             {"mailto",S_OK},
7562             {"",S_FALSE},
7563             {"",S_FALSE}
7564         },
7565         {
7566             {Uri_HOST_UNKNOWN,S_OK},
7567             {0,S_FALSE},
7568             {URL_SCHEME_MAILTO,S_OK},
7569             {URLZONE_INVALID,E_NOTIMPL}
7570         }
7571     },
7572     {   "http://winehq.org",0,
7573         "mailto://a@b.com",Uri_CREATE_NO_CANONICALIZE,
7574         0,S_OK,FALSE,
7575         {
7576             {"mailto:a@b.com",S_OK},
7577             {"",S_FALSE},
7578             {"mailto:a@b.com",S_OK},
7579             {"",S_FALSE},
7580             {".com",S_OK},
7581             {"",S_FALSE},
7582             {"",S_FALSE},
7583             {"",S_FALSE},
7584             {"a@b.com",S_OK},
7585             {"a@b.com",S_OK},
7586             {"",S_FALSE},
7587             {"mailto://a@b.com",S_OK,FALSE,"mailto:a@b.com"},
7588             {"mailto",S_OK},
7589             {"",S_FALSE},
7590             {"",S_FALSE}
7591         },
7592         {
7593             {Uri_HOST_UNKNOWN,S_OK},
7594             {0,S_FALSE},
7595             {URL_SCHEME_MAILTO,S_OK},
7596             {URLZONE_INVALID,E_NOTIMPL}
7597         }
7598     }
7599 };
7600 
7601 typedef struct _uri_parse_test {
7602     const char  *uri;
7603     DWORD       uri_flags;
7604     PARSEACTION action;
7605     DWORD       flags;
7606     const char  *property;
7607     HRESULT     expected;
7608     BOOL        todo;
7609     const char  *property2;
7610 } uri_parse_test;
7611 
7612 static const uri_parse_test uri_parse_tests[] = {
7613     /* PARSE_CANONICALIZE tests. */
7614     {"zip://google.com/test<|>",0,PARSE_CANONICALIZE,0,"zip://google.com/test<|>",S_OK,FALSE},
7615     {"http://google.com/test<|>",0,PARSE_CANONICALIZE,0,"http://google.com/test%3C%7C%3E",S_OK,FALSE},
7616     {"http://google.com/%30%23%3F",0,PARSE_CANONICALIZE,URL_UNESCAPE,"http://google.com/0#?",S_OK,FALSE},
7617     {"test <|>",Uri_CREATE_ALLOW_RELATIVE,PARSE_CANONICALIZE,URL_ESCAPE_UNSAFE,"test %3C%7C%3E",S_OK,FALSE},
7618     {"test <|>",Uri_CREATE_ALLOW_RELATIVE,PARSE_CANONICALIZE,URL_ESCAPE_SPACES_ONLY,"test%20<|>",S_OK,FALSE},
7619     {"test%20<|>",Uri_CREATE_ALLOW_RELATIVE,PARSE_CANONICALIZE,URL_UNESCAPE|URL_ESCAPE_UNSAFE,"test%20%3C%7C%3E",S_OK,FALSE},
7620     {"http://google.com/%20",0,PARSE_CANONICALIZE,URL_ESCAPE_PERCENT,"http://google.com/%2520",S_OK,FALSE},
7621     {"http://google.com/test/../",Uri_CREATE_NO_CANONICALIZE,PARSE_CANONICALIZE,URL_DONT_SIMPLIFY,"http://google.com/test/../",S_OK,FALSE},
7622     {"http://google.com/test/../",Uri_CREATE_NO_CANONICALIZE,PARSE_CANONICALIZE,URL_NO_META,"http://google.com/test/../",S_OK,FALSE},
7623     {"http://google.com/test/../",Uri_CREATE_NO_CANONICALIZE,PARSE_CANONICALIZE,0,"http://google.com/",S_OK,FALSE},
7624     {"zip://google.com/test/../",Uri_CREATE_NO_CANONICALIZE,PARSE_CANONICALIZE,0,"zip://google.com/",S_OK,FALSE},
7625     {"file:///c:/test/../test",Uri_CREATE_NO_CANONICALIZE,PARSE_CANONICALIZE,URL_DONT_SIMPLIFY,"file:///c:/test/../test",S_OK,FALSE},
7626 
7627     /* PARSE_FRIENDLY tests. */
7628     {"http://test@google.com/test#test",0,PARSE_FRIENDLY,0,"http://google.com/test#test",S_OK,FALSE},
7629     {"zip://test@google.com/test",0,PARSE_FRIENDLY,0,"zip://test@google.com/test",S_OK,FALSE},
7630 
7631     /* PARSE_ROOTDOCUMENT tests. */
7632     {"http://google.com:200/test/test",0,PARSE_ROOTDOCUMENT,0,"http://google.com:200/",S_OK,FALSE},
7633     {"http://google.com",Uri_CREATE_NO_CANONICALIZE,PARSE_ROOTDOCUMENT,0,"http://google.com/",S_OK,FALSE},
7634     {"zip://google.com/",0,PARSE_ROOTDOCUMENT,0,"",S_OK,FALSE},
7635     {"file:///c:/testing/",0,PARSE_ROOTDOCUMENT,0,"",S_OK,FALSE},
7636     {"file://server/test",0,PARSE_ROOTDOCUMENT,0,"",S_OK,FALSE},
7637     {"zip:test/test",0,PARSE_ROOTDOCUMENT,0,"",S_OK,FALSE},
7638 
7639     /* PARSE_DOCUMENT tests. */
7640     {"http://test@google.com/test?query#frag",0,PARSE_DOCUMENT,0,"http://test@google.com/test?query",S_OK,FALSE},
7641     {"http:testing#frag",0,PARSE_DOCUMENT,0,"",S_OK,FALSE},
7642     {"file:///c:/test#frag",0,PARSE_DOCUMENT,0,"",S_OK,FALSE},
7643     {"zip://google.com/#frag",0,PARSE_DOCUMENT,0,"",S_OK,FALSE},
7644     {"zip:test#frag",0,PARSE_DOCUMENT,0,"",S_OK,FALSE},
7645     {"testing#frag",Uri_CREATE_ALLOW_RELATIVE,PARSE_DOCUMENT,0,"",S_OK,FALSE},
7646 
7647     /* PARSE_PATH_FROM_URL tests. */
7648     {"file:///c:/test.mp3",0,PARSE_PATH_FROM_URL,0,"c:\\test.mp3",S_OK,FALSE},
7649     {"file:///c:/t<|>est.mp3",0,PARSE_PATH_FROM_URL,0,"c:\\t<|>est.mp3",S_OK,FALSE},
7650     {"file:///c:/te%XX t/",0,PARSE_PATH_FROM_URL,0,"c:\\te%XX t\\",S_OK,FALSE},
7651     {"file://server/test",0,PARSE_PATH_FROM_URL,0,"\\\\server\\test",S_OK,FALSE},
7652     {"http://google.com/",0,PARSE_PATH_FROM_URL,0,"",E_INVALIDARG,FALSE},
7653     {"file:/c:/dir/test.mp3",0,PARSE_PATH_FROM_URL,0,"c:\\dir\\test.mp3",S_OK},
7654     {"file:/c:/test.mp3",0,PARSE_PATH_FROM_URL,0,"c:\\test.mp3",S_OK},
7655     {"file://c:\\test.mp3",0,PARSE_PATH_FROM_URL,0,"c:\\test.mp3",S_OK},
7656 
7657     /* PARSE_URL_FROM_PATH tests. */
7658     /* This function almost seems to useless (just returns the absolute uri). */
7659     {"test.com",Uri_CREATE_ALLOW_RELATIVE,PARSE_URL_FROM_PATH,0,"test.com",S_OK,FALSE},
7660     {"/test/test",Uri_CREATE_ALLOW_RELATIVE,PARSE_URL_FROM_PATH,0,"/test/test",S_OK,FALSE},
7661     {"file://c:\\test\\test",Uri_CREATE_FILE_USE_DOS_PATH,PARSE_URL_FROM_PATH,0,"file://c:\\test\\test",S_OK,FALSE},
7662     {"file:c:/test",0,PARSE_URL_FROM_PATH,0,"",S_OK,FALSE},
7663     {"http:google.com/",0,PARSE_URL_FROM_PATH,0,"",S_OK,FALSE},
7664 
7665     /* PARSE_SCHEMA tests. */
7666     {"http://google.com/test",0,PARSE_SCHEMA,0,"http",S_OK,FALSE},
7667     {"test",Uri_CREATE_ALLOW_RELATIVE,PARSE_SCHEMA,0,"",S_OK,FALSE},
7668 
7669     /* PARSE_SITE tests. */
7670     {"http://google.uk.com/",0,PARSE_SITE,0,"google.uk.com",S_OK,FALSE},
7671     {"http://google.com.com/",0,PARSE_SITE,0,"google.com.com",S_OK,FALSE},
7672     {"google.com",Uri_CREATE_ALLOW_RELATIVE,PARSE_SITE,0,"",S_OK,FALSE},
7673     {"file://server/test",0,PARSE_SITE,0,"server",S_OK,FALSE},
7674 
7675     /* PARSE_DOMAIN tests. */
7676     {"http://google.com.uk/",0,PARSE_DOMAIN,0,"google.com.uk",S_OK,FALSE,"com.uk"},
7677     {"http://google.com.com/",0,PARSE_DOMAIN,0,"com.com",S_OK,FALSE},
7678     {"test/test",Uri_CREATE_ALLOW_RELATIVE,PARSE_DOMAIN,0,"",S_OK,FALSE},
7679     {"file://server/test",0,PARSE_DOMAIN,0,"",S_OK,FALSE},
7680 
7681     /* PARSE_LOCATION and PARSE_ANCHOR tests. */
7682     {"http://google.com/test#Test",0,PARSE_ANCHOR,0,"#Test",S_OK,FALSE},
7683     {"http://google.com/test#Test",0,PARSE_LOCATION,0,"#Test",S_OK,FALSE},
7684     {"test",Uri_CREATE_ALLOW_RELATIVE,PARSE_ANCHOR,0,"",S_OK,FALSE},
7685     {"test",Uri_CREATE_ALLOW_RELATIVE,PARSE_LOCATION,0,"",S_OK,FALSE}
7686 };
7687 
7688 static inline LPWSTR a2w(LPCSTR str) {
7689     LPWSTR ret = NULL;
7690 
7691     if(str) {
7692         DWORD len = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0);
7693         ret = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
7694         MultiByteToWideChar(CP_UTF8, 0, str, -1, ret, len);
7695     }
7696 
7697     return ret;
7698 }
7699 
7700 static inline DWORD strcmp_aw(LPCSTR strA, LPCWSTR strB) {
7701     LPWSTR strAW = a2w(strA);
7702     DWORD ret = lstrcmpW(strAW, strB);
7703     heap_free(strAW);
7704     return ret;
7705 }
7706 
7707 static inline ULONG get_refcnt(IUri *uri) {
7708     IUri_AddRef(uri);
7709     return IUri_Release(uri);
7710 }
7711 
7712 static void change_property(IUriBuilder *builder, const uri_builder_property *prop,
7713                             DWORD test_index) {
7714     HRESULT hr;
7715     LPWSTR valueW;
7716 
7717     valueW = a2w(prop->value);
7718     switch(prop->property) {
7719     case Uri_PROPERTY_FRAGMENT:
7720         hr = IUriBuilder_SetFragment(builder, valueW);
7721         todo_wine_if(prop->todo) {
7722             ok(hr == prop->expected,
7723                 "Error: IUriBuilder_SetFragment returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7724                 hr, prop->expected, test_index);
7725         }
7726         break;
7727     case Uri_PROPERTY_HOST:
7728         hr = IUriBuilder_SetHost(builder, valueW);
7729         todo_wine_if(prop->todo) {
7730             ok(hr == prop->expected,
7731                 "Error: IUriBuilder_SetHost returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7732                 hr, prop->expected, test_index);
7733         }
7734         break;
7735     case Uri_PROPERTY_PASSWORD:
7736         hr = IUriBuilder_SetPassword(builder, valueW);
7737         todo_wine_if(prop->todo) {
7738             ok(hr == prop->expected,
7739                 "Error: IUriBuilder_SetPassword returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7740                 hr, prop->expected, test_index);
7741         }
7742         break;
7743     case Uri_PROPERTY_PATH:
7744         hr = IUriBuilder_SetPath(builder, valueW);
7745         todo_wine_if(prop->todo) {
7746             ok(hr == prop->expected,
7747                 "Error: IUriBuilder_SetPath returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7748                 hr, prop->expected, test_index);
7749         }
7750         break;
7751     case Uri_PROPERTY_QUERY:
7752         hr = IUriBuilder_SetQuery(builder, valueW);
7753         todo_wine_if(prop->todo) {
7754             ok(hr == prop->expected,
7755                 "Error: IUriBuilder_SetQuery returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7756                 hr, prop->expected, test_index);
7757         }
7758         break;
7759     case Uri_PROPERTY_SCHEME_NAME:
7760         hr = IUriBuilder_SetSchemeName(builder, valueW);
7761         todo_wine_if(prop->todo) {
7762             ok(hr == prop->expected,
7763                 "Error: IUriBuilder_SetSchemeName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7764                 hr, prop->expected, test_index);
7765         }
7766         break;
7767     case Uri_PROPERTY_USER_NAME:
7768         hr = IUriBuilder_SetUserName(builder, valueW);
7769         todo_wine_if(prop->todo) {
7770             ok(hr == prop->expected,
7771                 "Error: IUriBuilder_SetUserName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7772                 hr, prop->expected, test_index);
7773         }
7774         break;
7775     default:
7776         trace("Unsupported operation for %d on uri_builder_tests[%d].\n", prop->property, test_index);
7777     }
7778 
7779     heap_free(valueW);
7780 }
7781 
7782 /*
7783  * Simple tests to make sure the CreateUri function handles invalid flag combinations
7784  * correctly.
7785  */
7786 static void test_CreateUri_InvalidFlags(void) {
7787     DWORD i;
7788 
7789     for(i = 0; i < sizeof(invalid_flag_tests)/sizeof(invalid_flag_tests[0]); ++i) {
7790         HRESULT hr;
7791         IUri *uri = (void*) 0xdeadbeef;
7792 
7793         hr = pCreateUri(http_urlW, invalid_flag_tests[i].flags, 0, &uri);
7794         ok(hr == invalid_flag_tests[i].expected, "Error: CreateUri returned 0x%08x, expected 0x%08x, flags=0x%08x\n",
7795                 hr, invalid_flag_tests[i].expected, invalid_flag_tests[i].flags);
7796         ok(uri == NULL, "Error: expected the IUri to be NULL, but it was %p instead\n", uri);
7797     }
7798 }
7799 
7800 static void test_CreateUri_InvalidArgs(void) {
7801     HRESULT hr;
7802     IUri *uri = (void*) 0xdeadbeef;
7803 
7804     const WCHAR invalidW[] = {'i','n','v','a','l','i','d',0};
7805     static const WCHAR emptyW[] = {0};
7806 
7807     hr = pCreateUri(http_urlW, 0, 0, NULL);
7808     ok(hr == E_INVALIDARG, "Error: CreateUri returned 0x%08x, expected 0x%08x\n", hr, E_INVALIDARG);
7809 
7810     hr = pCreateUri(NULL, 0, 0, &uri);
7811     ok(hr == E_INVALIDARG, "Error: CreateUri returned 0x%08x, expected 0x%08x\n", hr, E_INVALIDARG);
7812     ok(uri == NULL, "Error: Expected the IUri to be NULL, but it was %p instead\n", uri);
7813 
7814     uri = (void*) 0xdeadbeef;
7815     hr = pCreateUri(invalidW, 0, 0, &uri);
7816     ok(hr == E_INVALIDARG, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
7817     ok(uri == NULL, "Error: Expected the IUri to be NULL, but it was %p instead\n", uri);
7818 
7819     uri = (void*) 0xdeadbeef;
7820     hr = pCreateUri(emptyW, 0, 0, &uri);
7821     ok(hr == E_INVALIDARG, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
7822     ok(uri == NULL, "Error: Expected the IUri to be NULL, but it was %p instead\n", uri);
7823 }
7824 
7825 static void test_CreateUri_InvalidUri(void) {
7826     DWORD i;
7827 
7828     for(i = 0; i < sizeof(invalid_uri_tests)/sizeof(invalid_uri_tests[0]); ++i) {
7829         invalid_uri test = invalid_uri_tests[i];
7830         IUri *uri = NULL;
7831         LPWSTR uriW;
7832         HRESULT hr;
7833 
7834         uriW = a2w(test.uri);
7835         hr = pCreateUri(uriW, test.flags, 0, &uri);
7836         todo_wine_if(test.todo)
7837             ok(hr == E_INVALIDARG, "Error: CreateUri returned 0x%08x, expected 0x%08x on invalid_uri_tests[%d].\n",
7838                 hr, E_INVALIDARG, i);
7839         if(uri) IUri_Release(uri);
7840 
7841         heap_free(uriW);
7842     }
7843 }
7844 
7845 static void test_IUri_GetPropertyBSTR(void) {
7846     IUri *uri = NULL;
7847     HRESULT hr;
7848     DWORD i;
7849 
7850     /* Make sure GetPropertyBSTR handles invalid args correctly. */
7851     hr = pCreateUri(http_urlW, 0, 0, &uri);
7852     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7853     if(SUCCEEDED(hr)) {
7854         BSTR received = NULL;
7855 
7856         hr = IUri_GetPropertyBSTR(uri, Uri_PROPERTY_RAW_URI, NULL, 0);
7857         ok(hr == E_POINTER, "Error: GetPropertyBSTR returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
7858 
7859         /* Make sure it handles an invalid Uri_PROPERTY correctly. */
7860         hr = IUri_GetPropertyBSTR(uri, Uri_PROPERTY_PORT, &received, 0);
7861         ok(hr == E_INVALIDARG /* IE10 */ || broken(hr == S_OK), "Error: GetPropertyBSTR returned 0x%08x, expected E_INVALIDARG or S_OK.\n", hr);
7862         if(SUCCEEDED(hr)) {
7863             ok(received != NULL, "Error: Expected the string not to be NULL.\n");
7864             ok(!SysStringLen(received), "Error: Expected the string to be of len=0 but it was %d instead.\n", SysStringLen(received));
7865             SysFreeString(received);
7866         }else {
7867             ok(!received, "received = %s\n", wine_dbgstr_w(received));
7868         }
7869 
7870         /* Make sure it handles the ZONE property correctly. */
7871         received = NULL;
7872         hr = IUri_GetPropertyBSTR(uri, Uri_PROPERTY_ZONE, &received, 0);
7873         ok(hr == S_FALSE, "Error: GetPropertyBSTR returned 0x%08x, expected 0x%08x.\n", hr, S_FALSE);
7874         ok(received != NULL, "Error: Expected the string not to be NULL.\n");
7875         ok(!SysStringLen(received), "Error: Expected the string to be of len=0 but it was %d instead.\n", SysStringLen(received));
7876         SysFreeString(received);
7877     }
7878     if(uri) IUri_Release(uri);
7879 
7880     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
7881         uri_properties test = uri_tests[i];
7882         LPWSTR uriW;
7883         uri = NULL;
7884 
7885         uriW = a2w(test.uri);
7886         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
7887         todo_wine_if(test.create_todo)
7888             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x. Failed on uri_tests[%d].\n",
7889                     hr, test.create_expected, i);
7890 
7891         if(SUCCEEDED(hr)) {
7892             DWORD j;
7893 
7894             /* Checks all the string properties of the uri. */
7895             for(j = Uri_PROPERTY_STRING_START; j <= Uri_PROPERTY_STRING_LAST; ++j) {
7896                 BSTR received = NULL;
7897                 uri_str_property prop = test.str_props[j];
7898 
7899                 hr = IUri_GetPropertyBSTR(uri, j, &received, 0);
7900                 todo_wine_if(prop.todo) {
7901                     ok(hr == prop.expected ||
7902                        (prop.value2 && hr == prop.expected2),
7903                        "GetPropertyBSTR returned 0x%08x, expected 0x%08x. On uri_tests[%d].str_props[%d].\n",
7904                             hr, prop.expected, i, j);
7905                     ok(!strcmp_aw(prop.value, received) || (prop.value2 && !strcmp_aw(prop.value2, received)) ||
7906                        broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
7907                             "Expected %s but got %s on uri_tests[%d].str_props[%d].\n",
7908                             prop.value, wine_dbgstr_w(received), i, j);
7909                 }
7910 
7911                 SysFreeString(received);
7912             }
7913         }
7914 
7915         if(uri) IUri_Release(uri);
7916 
7917         heap_free(uriW);
7918     }
7919 }
7920 
7921 static void test_IUri_GetPropertyDWORD(void) {
7922     IUri *uri = NULL;
7923     HRESULT hr;
7924     DWORD i;
7925 
7926     hr = pCreateUri(http_urlW, 0, 0, &uri);
7927     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7928     if(SUCCEEDED(hr)) {
7929         DWORD received = 0xdeadbeef;
7930 
7931         hr = IUri_GetPropertyDWORD(uri, Uri_PROPERTY_DWORD_START, NULL, 0);
7932         ok(hr == E_INVALIDARG, "Error: GetPropertyDWORD returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
7933 
7934         hr = IUri_GetPropertyDWORD(uri, Uri_PROPERTY_ABSOLUTE_URI, &received, 0);
7935         ok(hr == E_INVALIDARG, "Error: GetPropertyDWORD returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
7936         ok(received == 0, "Error: Expected received=%d but instead received=%d.\n", 0, received);
7937     }
7938     if(uri) IUri_Release(uri);
7939 
7940     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
7941         uri_properties test = uri_tests[i];
7942         LPWSTR uriW;
7943         uri = NULL;
7944 
7945         uriW = a2w(test.uri);
7946         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
7947         todo_wine_if(test.create_todo)
7948             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x. Failed on uri_tests[%d].\n",
7949                     hr, test.create_expected, i);
7950 
7951         if(SUCCEEDED(hr)) {
7952             DWORD j;
7953 
7954             /* Checks all the DWORD properties of the uri. */
7955             for(j = 0; j < sizeof(test.dword_props)/sizeof(test.dword_props[0]); ++j) {
7956                 DWORD received;
7957                 uri_dword_property prop = test.dword_props[j];
7958 
7959                 hr = IUri_GetPropertyDWORD(uri, j+Uri_PROPERTY_DWORD_START, &received, 0);
7960                 todo_wine_if(prop.todo) {
7961                     ok(hr == prop.expected, "GetPropertyDWORD returned 0x%08x, expected 0x%08x. On uri_tests[%d].dword_props[%d].\n",
7962                             hr, prop.expected, i, j);
7963                     ok(prop.value == received, "Expected %d but got %d on uri_tests[%d].dword_props[%d].\n",
7964                             prop.value, received, i, j);
7965                 }
7966             }
7967         }
7968 
7969         if(uri) IUri_Release(uri);
7970 
7971         heap_free(uriW);
7972     }
7973 }
7974 
7975 /* Tests all the 'Get*' property functions which deal with strings. */
7976 static void test_IUri_GetStrProperties(void) {
7977     IUri *uri = NULL;
7978     HRESULT hr;
7979     DWORD i;
7980 
7981     /* Make sure all the 'Get*' string property functions handle invalid args correctly. */
7982     hr = pCreateUri(http_urlW, 0, 0, &uri);
7983     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7984     if(SUCCEEDED(hr)) {
7985         hr = IUri_GetAbsoluteUri(uri, NULL);
7986         ok(hr == E_POINTER, "Error: GetAbsoluteUri returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
7987 
7988         hr = IUri_GetAuthority(uri, NULL);
7989         ok(hr == E_POINTER, "Error: GetAuthority returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
7990 
7991         hr = IUri_GetDisplayUri(uri, NULL);
7992         ok(hr == E_POINTER, "Error: GetDisplayUri returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
7993 
7994         hr = IUri_GetDomain(uri, NULL);
7995         ok(hr == E_POINTER, "Error: GetDomain returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
7996 
7997         hr = IUri_GetExtension(uri, NULL);
7998         ok(hr == E_POINTER, "Error: GetExtension returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
7999 
8000         hr = IUri_GetFragment(uri, NULL);
8001         ok(hr == E_POINTER, "Error: GetFragment returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
8002 
8003         hr = IUri_GetHost(uri, NULL);
8004         ok(hr == E_POINTER, "Error: GetHost returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
8005 
8006         hr = IUri_GetPassword(uri, NULL);
8007         ok(hr == E_POINTER, "Error: GetPassword returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
8008 
8009         hr = IUri_GetPath(uri, NULL);
8010         ok(hr == E_POINTER, "Error: GetPath returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
8011 
8012         hr = IUri_GetPathAndQuery(uri, NULL);
8013         ok(hr == E_POINTER, "Error: GetPathAndQuery returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
8014 
8015         hr = IUri_GetQuery(uri, NULL);
8016         ok(hr == E_POINTER, "Error: GetQuery returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
8017 
8018         hr = IUri_GetRawUri(uri, NULL);
8019         ok(hr == E_POINTER, "Error: GetRawUri returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
8020 
8021         hr = IUri_GetSchemeName(uri, NULL);
8022         ok(hr == E_POINTER, "Error: GetSchemeName returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
8023 
8024         hr = IUri_GetUserInfo(uri, NULL);
8025         ok(hr == E_POINTER, "Error: GetUserInfo returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
8026 
8027         hr = IUri_GetUserName(uri, NULL);
8028         ok(hr == E_POINTER, "Error: GetUserName returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
8029     }
8030     if(uri) IUri_Release(uri);
8031 
8032     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
8033         uri_properties test = uri_tests[i];
8034         LPWSTR uriW;
8035         uri = NULL;
8036 
8037         uriW = a2w(test.uri);
8038         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
8039         todo_wine_if(test.create_todo)
8040             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
8041                     hr, test.create_expected, i);
8042 
8043         if(SUCCEEDED(hr)) {
8044             uri_str_property prop;
8045             BSTR received = NULL;
8046 
8047             /* GetAbsoluteUri() tests. */
8048             prop = test.str_props[Uri_PROPERTY_ABSOLUTE_URI];
8049             hr = IUri_GetAbsoluteUri(uri, &received);
8050             todo_wine_if(prop.todo) {
8051                 ok(hr == prop.expected, "Error: GetAbsoluteUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
8052                         hr, prop.expected, i);
8053                 ok(!strcmp_aw(prop.value, received) || broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
8054                         "Error: Expected %s but got %s on uri_tests[%d].\n",
8055                         prop.value, wine_dbgstr_w(received), i);
8056             }
8057             SysFreeString(received);
8058             received = NULL;
8059 
8060             /* GetAuthority() tests. */
8061             prop = test.str_props[Uri_PROPERTY_AUTHORITY];
8062             hr = IUri_GetAuthority(uri, &received);
8063             todo_wine_if(prop.todo) {
8064                 ok(hr == prop.expected, "Error: GetAuthority returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
8065                         hr, prop.expected, i);
8066                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
8067                         prop.value, wine_dbgstr_w(received), i);
8068             }
8069             SysFreeString(received);
8070             received = NULL;
8071 
8072             /* GetDisplayUri() tests. */
8073             prop = test.str_props[Uri_PROPERTY_DISPLAY_URI];
8074             hr = IUri_GetDisplayUri(uri, &received);
8075             todo_wine_if(prop.todo) {
8076                 ok(hr == prop.expected, "Error: GetDisplayUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
8077                         hr, prop.expected, i);
8078                 ok(!strcmp_aw(prop.value, received) || broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
8079                         "Error: Expected %s but got %s on uri_tests[%d].\n",
8080                         prop.value, wine_dbgstr_w(received), i);
8081             }
8082             SysFreeString(received);
8083             received = NULL;
8084 
8085             /* GetDomain() tests. */
8086             prop = test.str_props[Uri_PROPERTY_DOMAIN];
8087             hr = IUri_GetDomain(uri, &received);
8088             todo_wine_if(prop.todo) {
8089                 ok(hr == prop.expected || (prop.value2 && hr == prop.expected2),
8090                    "Error: GetDomain returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
8091                         hr, prop.expected, i);
8092                 ok(!strcmp_aw(prop.value, received) || (prop.value2 && !strcmp_aw(prop.value2, received)),
8093                    "Error: Expected %s but got %s on uri_tests[%d].\n",
8094                         prop.value, wine_dbgstr_w(received), i);
8095             }
8096             SysFreeString(received);
8097             received = NULL;
8098 
8099             /* GetExtension() tests. */
8100             prop = test.str_props[Uri_PROPERTY_EXTENSION];
8101             hr = IUri_GetExtension(uri, &received);
8102             todo_wine_if(prop.todo) {
8103                 ok(hr == prop.expected, "Error: GetExtension returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
8104                         hr, prop.expected, i);
8105                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
8106                         prop.value, wine_dbgstr_w(received), i);
8107             }
8108             SysFreeString(received);
8109             received = NULL;
8110 
8111             /* GetFragment() tests. */
8112             prop = test.str_props[Uri_PROPERTY_FRAGMENT];
8113             hr = IUri_GetFragment(uri, &received);
8114             todo_wine_if(prop.todo) {
8115                 ok(hr == prop.expected, "Error: GetFragment returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
8116                         hr, prop.expected, i);
8117                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
8118                         prop.value, wine_dbgstr_w(received), i);
8119             }
8120             SysFreeString(received);
8121             received = NULL;
8122 
8123             /* GetHost() tests. */
8124             prop = test.str_props[Uri_PROPERTY_HOST];
8125             hr = IUri_GetHost(uri, &received);
8126             todo_wine_if(prop.todo) {
8127                 ok(hr == prop.expected, "Error: GetHost returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
8128                         hr, prop.expected, i);
8129                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
8130                         prop.value, wine_dbgstr_w(received), i);
8131             }
8132             SysFreeString(received);
8133             received = NULL;
8134 
8135             /* GetPassword() tests. */
8136             prop = test.str_props[Uri_PROPERTY_PASSWORD];
8137             hr = IUri_GetPassword(uri, &received);
8138             todo_wine_if(prop.todo) {
8139                 ok(hr == prop.expected, "Error: GetPassword returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
8140                         hr, prop.expected, i);
8141                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
8142                         prop.value, wine_dbgstr_w(received), i);
8143             }
8144             SysFreeString(received);
8145             received = NULL;
8146 
8147             /* GetPath() tests. */
8148             prop = test.str_props[Uri_PROPERTY_PATH];
8149             hr = IUri_GetPath(uri, &received);
8150             todo_wine_if(prop.todo) {
8151                 ok(hr == prop.expected, "Error: GetPath returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
8152                         hr, prop.expected, i);
8153                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
8154                         prop.value, wine_dbgstr_w(received), i);
8155             }
8156             SysFreeString(received);
8157             received = NULL;
8158 
8159             /* GetPathAndQuery() tests. */
8160             prop = test.str_props[Uri_PROPERTY_PATH_AND_QUERY];
8161             hr = IUri_GetPathAndQuery(uri, &received);
8162             todo_wine_if(prop.todo) {
8163                 ok(hr == prop.expected, "Error: GetPathAndQuery returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
8164                         hr, prop.expected, i);
8165                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
8166                         prop.value, wine_dbgstr_w(received), i);
8167             }
8168             SysFreeString(received);
8169             received = NULL;
8170 
8171             /* GetQuery() tests. */
8172             prop = test.str_props[Uri_PROPERTY_QUERY];
8173             hr = IUri_GetQuery(uri, &received);
8174             todo_wine_if(prop.todo) {
8175                 ok(hr == prop.expected, "Error: GetQuery returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
8176                         hr, prop.expected, i);
8177                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
8178                         prop.value, wine_dbgstr_w(received), i);
8179             }
8180             SysFreeString(received);
8181             received = NULL;
8182 
8183             /* GetRawUri() tests. */
8184             prop = test.str_props[Uri_PROPERTY_RAW_URI];
8185             hr = IUri_GetRawUri(uri, &received);
8186             todo_wine_if(prop.todo) {
8187                 ok(hr == prop.expected, "Error: GetRawUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
8188                         hr, prop.expected, i);
8189                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
8190                         prop.value, wine_dbgstr_w(received), i);
8191             }
8192             SysFreeString(received);
8193             received = NULL;
8194 
8195             /* GetSchemeName() tests. */
8196             prop = test.str_props[Uri_PROPERTY_SCHEME_NAME];
8197             hr = IUri_GetSchemeName(uri, &received);
8198             todo_wine_if(prop.todo) {
8199                 ok(hr == prop.expected, "Error: GetSchemeName returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
8200                         hr, prop.expected, i);
8201                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
8202                         prop.value, wine_dbgstr_w(received), i);
8203             }
8204             SysFreeString(received);
8205             received = NULL;
8206 
8207             /* GetUserInfo() tests. */
8208             prop = test.str_props[Uri_PROPERTY_USER_INFO];
8209             hr = IUri_GetUserInfo(uri, &received);
8210             todo_wine_if(prop.todo) {
8211                 ok(hr == prop.expected, "Error: GetUserInfo returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
8212                         hr, prop.expected, i);
8213                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
8214                         prop.value, wine_dbgstr_w(received), i);
8215             }
8216             SysFreeString(received);
8217             received = NULL;
8218 
8219             /* GetUserName() tests. */
8220             prop = test.str_props[Uri_PROPERTY_USER_NAME];
8221             hr = IUri_GetUserName(uri, &received);
8222             todo_wine_if(prop.todo) {
8223                 ok(hr == prop.expected, "Error: GetUserName returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
8224                         hr, prop.expected, i);
8225                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
8226                         prop.value, wine_dbgstr_w(received), i);
8227             }
8228             SysFreeString(received);
8229         }
8230 
8231         if(uri) IUri_Release(uri);
8232 
8233         heap_free(uriW);
8234     }
8235 }
8236 
8237 static void test_IUri_GetDwordProperties(void) {
8238     IUri *uri = NULL;
8239     HRESULT hr;
8240     DWORD i;
8241 
8242     /* Make sure all the 'Get*' dword property functions handle invalid args correctly. */
8243     hr = pCreateUri(http_urlW, 0, 0, &uri);
8244     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8245     if(SUCCEEDED(hr)) {
8246         hr = IUri_GetHostType(uri, NULL);
8247         ok(hr == E_INVALIDARG, "Error: GetHostType returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
8248 
8249         hr = IUri_GetPort(uri, NULL);
8250         ok(hr == E_INVALIDARG, "Error: GetPort returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
8251 
8252         hr = IUri_GetScheme(uri, NULL);
8253         ok(hr == E_INVALIDARG, "Error: GetScheme returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
8254 
8255         hr = IUri_GetZone(uri, NULL);
8256         ok(hr == E_INVALIDARG, "Error: GetZone returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
8257     }
8258     if(uri) IUri_Release(uri);
8259 
8260     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
8261         uri_properties test = uri_tests[i];
8262         LPWSTR uriW;
8263         uri = NULL;
8264 
8265         uriW = a2w(test.uri);
8266         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
8267         todo_wine_if(test.create_todo)
8268             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
8269                     hr, test.create_expected, i);
8270 
8271         if(SUCCEEDED(hr)) {
8272             uri_dword_property prop;
8273             DWORD received;
8274 
8275             /* Assign an insane value so tests don't accidentally pass when
8276              * they shouldn't!
8277              */
8278             received = -9999999;
8279 
8280             /* GetHostType() tests. */
8281             prop = test.dword_props[Uri_PROPERTY_HOST_TYPE-Uri_PROPERTY_DWORD_START];
8282             hr = IUri_GetHostType(uri, &received);
8283             todo_wine_if(prop.todo) {
8284                 ok(hr == prop.expected, "Error: GetHostType returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
8285                         hr, prop.expected, i);
8286                 ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
8287             }
8288             received = -9999999;
8289 
8290             /* GetPort() tests. */
8291             prop = test.dword_props[Uri_PROPERTY_PORT-Uri_PROPERTY_DWORD_START];
8292             hr = IUri_GetPort(uri, &received);
8293             todo_wine_if(prop.todo) {
8294                 ok(hr == prop.expected, "Error: GetPort returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
8295                         hr, prop.expected, i);
8296                 ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
8297             }
8298             received = -9999999;
8299 
8300             /* GetScheme() tests. */
8301             prop = test.dword_props[Uri_PROPERTY_SCHEME-Uri_PROPERTY_DWORD_START];
8302             hr = IUri_GetScheme(uri, &received);
8303             todo_wine_if(prop.todo) {
8304                 ok(hr == prop.expected, "Error: GetScheme returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
8305                         hr, prop.expected, i);
8306                 ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
8307             }
8308             received = -9999999;
8309 
8310             /* GetZone() tests. */
8311             prop = test.dword_props[Uri_PROPERTY_ZONE-Uri_PROPERTY_DWORD_START];
8312             hr = IUri_GetZone(uri, &received);
8313             todo_wine_if(prop.todo) {
8314                 ok(hr == prop.expected, "Error: GetZone returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
8315                         hr, prop.expected, i);
8316                 ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
8317             }
8318         }
8319 
8320         if(uri) IUri_Release(uri);
8321 
8322         heap_free(uriW);
8323     }
8324 }
8325 
8326 static void test_IUri_GetPropertyLength(void) {
8327     IUri *uri = NULL;
8328     HRESULT hr;
8329     DWORD i;
8330 
8331     /* Make sure it handles invalid args correctly. */
8332     hr = pCreateUri(http_urlW, 0, 0, &uri);
8333     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8334     if(SUCCEEDED(hr)) {
8335         DWORD received = 0xdeadbeef;
8336 
8337         hr = IUri_GetPropertyLength(uri, Uri_PROPERTY_STRING_START, NULL, 0);
8338         ok(hr == E_INVALIDARG, "Error: GetPropertyLength returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
8339 
8340         hr = IUri_GetPropertyLength(uri, Uri_PROPERTY_DWORD_START, &received, 0);
8341         ok(hr == E_INVALIDARG, "Error: GetPropertyLength return 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
8342         ok(received == 0xdeadbeef, "Error: Expected 0xdeadbeef but got 0x%08x.\n", received);
8343     }
8344     if(uri) IUri_Release(uri);
8345 
8346     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
8347         uri_properties test = uri_tests[i];
8348         LPWSTR uriW;
8349         uri = NULL;
8350 
8351         uriW = a2w(test.uri);
8352         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
8353         todo_wine_if(test.create_todo)
8354             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_test[%d].\n",
8355                     hr, test.create_expected, i);
8356 
8357         if(SUCCEEDED(hr)) {
8358             DWORD j;
8359 
8360             for(j = Uri_PROPERTY_STRING_START; j <= Uri_PROPERTY_STRING_LAST; ++j) {
8361                 DWORD expectedLen, receivedLen;
8362                 uri_str_property prop = test.str_props[j];
8363                 LPWSTR expectedValueW;
8364 
8365                 expectedLen = lstrlenA(prop.value);
8366                 /* Value may be unicode encoded */
8367                 expectedValueW = a2w(prop.value);
8368                 expectedLen = lstrlenW(expectedValueW);
8369 
8370                 /* This won't be necessary once GetPropertyLength is implemented. */
8371                 receivedLen = -1;
8372 
8373                 hr = IUri_GetPropertyLength(uri, j, &receivedLen, 0);
8374                 todo_wine_if(prop.todo) {
8375                     ok(hr == prop.expected || (prop.value2 && hr == prop.expected2),
8376                        "Error: GetPropertyLength returned 0x%08x, expected 0x%08x on uri_tests[%d].str_props[%d].\n",
8377                             hr, prop.expected, i, j);
8378                     ok(receivedLen == expectedLen || (prop.value2 && receivedLen == lstrlenA(prop.value2)) ||
8379                        broken(prop.broken_value && receivedLen == lstrlenA(prop.broken_value)),
8380                             "Error: Expected a length of %d but got %d on uri_tests[%d].str_props[%d].\n",
8381                             expectedLen, receivedLen, i, j);
8382                 }
8383             }
8384         }
8385 
8386         if(uri) IUri_Release(uri);
8387 
8388         heap_free(uriW);
8389     }
8390 }
8391 
8392 static DWORD compute_expected_props(uri_properties *test, DWORD *mask)
8393 {
8394     DWORD ret = 0, i;
8395 
8396     *mask = 0;
8397 
8398     for(i=Uri_PROPERTY_STRING_START; i <= Uri_PROPERTY_STRING_LAST; i++) {
8399         if(test->str_props[i-Uri_PROPERTY_STRING_START].expected == S_OK)
8400             ret |= 1<<i;
8401         if(test->str_props[i-Uri_PROPERTY_STRING_START].value2 == NULL ||
8402            test->str_props[i-Uri_PROPERTY_STRING_START].expected ==
8403            test->str_props[i-Uri_PROPERTY_STRING_START].expected2)
8404             *mask |= 1<<i;
8405     }
8406 
8407     for(i=Uri_PROPERTY_DWORD_START; i <= Uri_PROPERTY_DWORD_LAST; i++) {
8408         if(test->dword_props[i-Uri_PROPERTY_DWORD_START].expected == S_OK)
8409             ret |= 1<<i;
8410         *mask |= 1<<i;
8411     }
8412 
8413     return ret;
8414 }
8415 
8416 static void test_IUri_GetProperties(void) {
8417     IUri *uri = NULL;
8418     HRESULT hr;
8419     DWORD i;
8420 
8421     hr = pCreateUri(http_urlW, 0, 0, &uri);
8422     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8423     if(SUCCEEDED(hr)) {
8424         hr = IUri_GetProperties(uri, NULL);
8425         ok(hr == E_INVALIDARG, "Error: GetProperties returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
8426     }
8427     if(uri) IUri_Release(uri);
8428 
8429     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
8430         uri_properties test = uri_tests[i];
8431         LPWSTR uriW;
8432         uri = NULL;
8433 
8434         uriW = a2w(test.uri);
8435         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
8436         todo_wine_if(test.create_todo)
8437             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, test.create_expected);
8438 
8439         if(SUCCEEDED(hr)) {
8440             DWORD received = 0, expected_props, mask;
8441             DWORD j;
8442 
8443             hr = IUri_GetProperties(uri, &received);
8444             ok(hr == S_OK, "Error: GetProperties returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8445 
8446             expected_props = compute_expected_props(&test, &mask);
8447 
8448             for(j = 0; j <= Uri_PROPERTY_DWORD_LAST; ++j) {
8449                 /* (1 << j) converts a Uri_PROPERTY to its corresponding Uri_HAS_* flag mask. */
8450                 if(mask & (1 << j)) {
8451                     if(expected_props & (1 << j))
8452                         ok(received & (1 << j), "Error: Expected flag for property %d on uri_tests[%d].\n", j, i);
8453                     else
8454                         ok(!(received & (1 << j)), "Error: Received flag for property %d when not expected on uri_tests[%d].\n", j, i);
8455                 }
8456             }
8457         }
8458 
8459         if(uri) IUri_Release(uri);
8460 
8461         heap_free(uriW);
8462     }
8463 }
8464 
8465 static void test_IUri_HasProperty(void) {
8466     IUri *uri = NULL;
8467     HRESULT hr;
8468     DWORD i;
8469 
8470     hr = pCreateUri(http_urlW, 0, 0, &uri);
8471     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8472     if(SUCCEEDED(hr)) {
8473         hr = IUri_HasProperty(uri, Uri_PROPERTY_RAW_URI, NULL);
8474         ok(hr == E_INVALIDARG, "Error: HasProperty returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
8475     }
8476     if(uri) IUri_Release(uri);
8477 
8478     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
8479         uri_properties test = uri_tests[i];
8480         LPWSTR uriW;
8481         uri = NULL;
8482 
8483         uriW = a2w(test.uri);
8484 
8485         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
8486         todo_wine_if(test.create_todo)
8487             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, test.create_expected);
8488 
8489         if(SUCCEEDED(hr)) {
8490             DWORD expected_props, j, mask;
8491 
8492             expected_props = compute_expected_props(&test, &mask);
8493 
8494             for(j = 0; j <= Uri_PROPERTY_DWORD_LAST; ++j) {
8495                 /* Assign -1, then explicitly test for TRUE or FALSE later. */
8496                 BOOL received = -1;
8497 
8498                 hr = IUri_HasProperty(uri, j, &received);
8499                 ok(hr == S_OK, "Error: HasProperty returned 0x%08x, expected 0x%08x for property %d on uri_tests[%d].\n",
8500                         hr, S_OK, j, i);
8501 
8502                 if(mask & (1 << j)) {
8503                     if(expected_props & (1 << j)) {
8504                         ok(received == TRUE, "Error: Expected to have property %d on uri_tests[%d].\n", j, i);
8505                     } else {
8506                         ok(received == FALSE, "Error: Wasn't expecting to have property %d on uri_tests[%d].\n", j, i);
8507                     }
8508                 }
8509             }
8510         }
8511 
8512         if(uri) IUri_Release(uri);
8513 
8514         heap_free(uriW);
8515     }
8516 }
8517 
8518 static void test_IUri_IsEqual(void) {
8519     IUri *uriA, *uriB;
8520     BOOL equal;
8521     HRESULT hres;
8522     DWORD i;
8523 
8524     uriA = uriB = NULL;
8525 
8526     /* Make sure IsEqual handles invalid args correctly. */
8527     hres = pCreateUri(http_urlW, 0, 0, &uriA);
8528     ok(hres == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hres, S_OK);
8529     hres = pCreateUri(http_urlW, 0, 0, &uriB);
8530     ok(hres == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hres, S_OK);
8531 
8532     equal = -1;
8533     hres = IUri_IsEqual(uriA, NULL, &equal);
8534     ok(hres == S_OK, "Error: IsEqual returned 0x%08x, expected 0x%08x.\n", hres, S_OK);
8535     ok(!equal, "Error: Expected equal to be FALSE, but was %d instead.\n", equal);
8536 
8537     hres = IUri_IsEqual(uriA, uriB, NULL);
8538     ok(hres == E_POINTER, "Error: IsEqual returned 0x%08x, expected 0x%08x.\n", hres, E_POINTER);
8539 
8540     IUri_Release(uriA);
8541     IUri_Release(uriB);
8542 
8543     for(i = 0; i < sizeof(equality_tests)/sizeof(equality_tests[0]); ++i) {
8544         uri_equality test = equality_tests[i];
8545         LPWSTR uriA_W, uriB_W;
8546 
8547         uriA = uriB = NULL;
8548 
8549         uriA_W = a2w(test.a);
8550         uriB_W = a2w(test.b);
8551 
8552         hres = pCreateUri(uriA_W, test.create_flags_a, 0, &uriA);
8553         ok(hres == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x on equality_tests[%d].a\n", hres, S_OK, i);
8554 
8555         hres = pCreateUri(uriB_W, test.create_flags_b, 0, &uriB);
8556         ok(hres == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x on equality_tests[%d].b\n", hres, S_OK, i);
8557 
8558         equal = -1;
8559         hres = IUri_IsEqual(uriA, uriB, &equal);
8560         todo_wine_if(test.todo) {
8561             ok(hres == S_OK, "Error: IsEqual returned 0x%08x, expected 0x%08x on equality_tests[%d].\n", hres, S_OK, i);
8562             ok(equal == test.equal, "Error: Expected the comparison to be %d on equality_tests[%d].\n", test.equal, i);
8563         }
8564         if(uriA) IUri_Release(uriA);
8565         if(uriB) IUri_Release(uriB);
8566 
8567         heap_free(uriA_W);
8568         heap_free(uriB_W);
8569     }
8570 }
8571 
8572 static void test_CreateUriWithFragment_InvalidArgs(void) {
8573     HRESULT hr;
8574     IUri *uri = (void*) 0xdeadbeef;
8575     const WCHAR fragmentW[] = {'#','f','r','a','g','m','e','n','t',0};
8576 
8577     hr = pCreateUriWithFragment(NULL, fragmentW, 0, 0, &uri);
8578     ok(hr == E_INVALIDARG, "Error: CreateUriWithFragment returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
8579     ok(uri == NULL, "Error: Expected uri to be NULL, but was %p instead.\n", uri);
8580 
8581     hr = pCreateUriWithFragment(http_urlW, fragmentW, 0, 0, NULL);
8582     ok(hr == E_INVALIDARG, "Error: CreateUriWithFragment returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
8583 
8584     /* Original URI can't already contain a fragment component. */
8585     uri = (void*) 0xdeadbeef;
8586     hr = pCreateUriWithFragment(http_url_fragW, fragmentW, 0, 0, &uri);
8587     ok(hr == E_INVALIDARG, "Error: CreateUriWithFragment returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
8588     ok(uri == NULL, "Error: Expected uri to be NULL, but was %p instead.\n", uri);
8589 }
8590 
8591 /* CreateUriWithFragment has the same invalid flag combinations as CreateUri. */
8592 static void test_CreateUriWithFragment_InvalidFlags(void) {
8593     DWORD i;
8594 
8595     for(i = 0; i < sizeof(invalid_flag_tests)/sizeof(invalid_flag_tests[0]); ++i) {
8596         HRESULT hr;
8597         IUri *uri = (void*) 0xdeadbeef;
8598 
8599         hr = pCreateUriWithFragment(http_urlW, NULL, invalid_flag_tests[i].flags, 0, &uri);
8600         ok(hr == invalid_flag_tests[i].expected, "Error: CreateUriWithFragment returned 0x%08x, expected 0x%08x. flags=0x%08x.\n",
8601             hr, invalid_flag_tests[i].expected, invalid_flag_tests[i].flags);
8602         ok(uri == NULL, "Error: Expected uri to be NULL, but was %p instead.\n", uri);
8603     }
8604 }
8605 
8606 static void test_CreateUriWithFragment(void) {
8607     DWORD i;
8608 
8609     for(i = 0; i < sizeof(uri_fragment_tests)/sizeof(uri_fragment_tests[0]); ++i) {
8610         HRESULT hr;
8611         IUri *uri = NULL;
8612         LPWSTR uriW, fragW;
8613         uri_with_fragment test = uri_fragment_tests[i];
8614 
8615         uriW = a2w(test.uri);
8616         fragW = a2w(test.fragment);
8617 
8618         hr = pCreateUriWithFragment(uriW, fragW, test.create_flags, 0, &uri);
8619         todo_wine_if(test.expected_todo)
8620             ok(hr == test.create_expected,
8621                 "Error: CreateUriWithFragment returned 0x%08x, expected 0x%08x on uri_fragment_tests[%d].\n",
8622                 hr, test.create_expected, i);
8623 
8624         if(SUCCEEDED(hr)) {
8625             BSTR received = NULL;
8626 
8627             hr = IUri_GetAbsoluteUri(uri, &received);
8628             todo_wine_if(test.expected_todo) {
8629                 ok(hr == S_OK, "Error: GetAbsoluteUri returned 0x%08x, expected 0x%08x on uri_fragment_tests[%d].\n",
8630                     hr, S_OK, i);
8631                 ok(!strcmp_aw(test.expected_uri, received), "Error: Expected %s but got %s on uri_fragment_tests[%d].\n",
8632                     test.expected_uri, wine_dbgstr_w(received), i);
8633             }
8634 
8635             SysFreeString(received);
8636         }
8637 
8638         if(uri) IUri_Release(uri);
8639         heap_free(uriW);
8640         heap_free(fragW);
8641     }
8642 }
8643 
8644 static void test_CreateIUriBuilder(void) {
8645     HRESULT hr;
8646     IUriBuilder *builder = NULL;
8647     IUri *uri;
8648 
8649     hr = pCreateIUriBuilder(NULL, 0, 0, NULL);
8650     ok(hr == E_POINTER, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x\n",
8651         hr, E_POINTER);
8652 
8653     /* CreateIUriBuilder increases the ref count of the IUri it receives. */
8654     hr = pCreateUri(http_urlW, 0, 0, &uri);
8655     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8656     if(SUCCEEDED(hr)) {
8657         ULONG cur_count, orig_count;
8658 
8659         orig_count = get_refcnt(uri);
8660         hr = pCreateIUriBuilder(uri, 0, 0, &builder);
8661         ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8662         ok(builder != NULL, "Error: Expecting builder not to be NULL\n");
8663 
8664         cur_count = get_refcnt(uri);
8665         ok(cur_count == orig_count+1, "Error: Expected the ref count to be %u, but was %u instead.\n", orig_count+1, cur_count);
8666 
8667         if(builder) IUriBuilder_Release(builder);
8668         cur_count = get_refcnt(uri);
8669         ok(cur_count == orig_count, "Error: Expected the ref count to be %u, but was %u instead.\n", orig_count, cur_count);
8670     }
8671     if(uri) IUri_Release(uri);
8672 }
8673 
8674 static void test_IUriBuilder_CreateUri(IUriBuilder *builder, const uri_builder_test *test,
8675                                        DWORD test_index) {
8676     HRESULT hr;
8677     IUri *uri = NULL;
8678 
8679     hr = IUriBuilder_CreateUri(builder, test->uri_flags, 0, 0, &uri);
8680     todo_wine_if(test->uri_todo)
8681         ok(hr == test->uri_hres,
8682             "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8683             hr, test->uri_hres, test_index);
8684 
8685     if(SUCCEEDED(hr)) {
8686         DWORD i;
8687 
8688         for(i = 0; i < sizeof(test->expected_str_props)/sizeof(test->expected_str_props[0]); ++i) {
8689             uri_builder_str_property prop = test->expected_str_props[i];
8690             BSTR received = NULL;
8691 
8692             hr = IUri_GetPropertyBSTR(uri, i, &received, 0);
8693             todo_wine_if(prop.todo)
8694                 ok(hr == prop.result,
8695                     "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_str_props[%d].\n",
8696                     hr, prop.result, test_index, i);
8697             if(SUCCEEDED(hr)) {
8698                 todo_wine_if(prop.todo)
8699                     ok(!strcmp_aw(prop.expected, received),
8700                         "Error: Expected %s but got %s instead on uri_builder_tests[%d].expected_str_props[%d].\n",
8701                         prop.expected, wine_dbgstr_w(received), test_index, i);
8702             }
8703             SysFreeString(received);
8704         }
8705 
8706         for(i = 0; i < sizeof(test->expected_dword_props)/sizeof(test->expected_dword_props[0]); ++i) {
8707             uri_builder_dword_property prop = test->expected_dword_props[i];
8708             DWORD received = -2;
8709 
8710             hr = IUri_GetPropertyDWORD(uri, i+Uri_PROPERTY_DWORD_START, &received, 0);
8711             todo_wine_if(prop.todo)
8712                 ok(hr == prop.result,
8713                     "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_dword_props[%d].\n",
8714                     hr, prop.result, test_index, i);
8715             if(SUCCEEDED(hr)) {
8716                 todo_wine_if(prop.todo)
8717                     ok(received == prop.expected,
8718                         "Error: Expected %d but got %d instead on uri_builder_tests[%d].expected_dword_props[%d].\n",
8719                         prop.expected, received, test_index, i);
8720             }
8721         }
8722     }
8723     if(uri) IUri_Release(uri);
8724 }
8725 
8726 static void test_IUriBuilder_CreateUriSimple(IUriBuilder *builder, const uri_builder_test *test,
8727                                        DWORD test_index) {
8728     HRESULT hr;
8729     IUri *uri = NULL;
8730 
8731     hr = IUriBuilder_CreateUriSimple(builder, test->uri_simple_encode_flags, 0, &uri);
8732     todo_wine_if(test->uri_simple_todo)
8733         ok(hr == test->uri_simple_hres,
8734             "Error: IUriBuilder_CreateUriSimple returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8735             hr, test->uri_simple_hres, test_index);
8736 
8737     if(SUCCEEDED(hr)) {
8738         DWORD i;
8739 
8740         for(i = 0; i < sizeof(test->expected_str_props)/sizeof(test->expected_str_props[0]); ++i) {
8741             uri_builder_str_property prop = test->expected_str_props[i];
8742             BSTR received = NULL;
8743 
8744             hr = IUri_GetPropertyBSTR(uri, i, &received, 0);
8745             todo_wine_if(prop.todo)
8746                 ok(hr == prop.result,
8747                     "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_str_props[%d].\n",
8748                     hr, prop.result, test_index, i);
8749             if(SUCCEEDED(hr)) {
8750                 todo_wine_if(prop.todo)
8751                     ok(!strcmp_aw(prop.expected, received),
8752                         "Error: Expected %s but got %s instead on uri_builder_tests[%d].expected_str_props[%d].\n",
8753                         prop.expected, wine_dbgstr_w(received), test_index, i);
8754             }
8755             SysFreeString(received);
8756         }
8757 
8758         for(i = 0; i < sizeof(test->expected_dword_props)/sizeof(test->expected_dword_props[0]); ++i) {
8759             uri_builder_dword_property prop = test->expected_dword_props[i];
8760             DWORD received = -2;
8761 
8762             hr = IUri_GetPropertyDWORD(uri, i+Uri_PROPERTY_DWORD_START, &received, 0);
8763             todo_wine_if(prop.todo)
8764                 ok(hr == prop.result,
8765                     "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_dword_props[%d].\n",
8766                     hr, prop.result, test_index, i);
8767             if(SUCCEEDED(hr)) {
8768                 todo_wine_if(prop.todo)
8769                     ok(received == prop.expected,
8770                         "Error: Expected %d but got %d instead on uri_builder_tests[%d].expected_dword_props[%d].\n",
8771                         prop.expected, received, test_index, i);
8772             }
8773         }
8774     }
8775     if(uri) IUri_Release(uri);
8776 }
8777 
8778 static void test_IUriBuilder_CreateUriWithFlags(IUriBuilder *builder, const uri_builder_test *test,
8779                                                 DWORD test_index) {
8780     HRESULT hr;
8781     IUri *uri = NULL;
8782 
8783     hr = IUriBuilder_CreateUriWithFlags(builder, test->uri_with_flags, test->uri_with_builder_flags,
8784                                         test->uri_with_encode_flags, 0, &uri);
8785     todo_wine_if(test->uri_with_todo)
8786         ok(hr == test->uri_with_hres,
8787             "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8788             hr, test->uri_with_hres, test_index);
8789 
8790     if(SUCCEEDED(hr)) {
8791         DWORD i;
8792 
8793         for(i = 0; i < sizeof(test->expected_str_props)/sizeof(test->expected_str_props[0]); ++i) {
8794             uri_builder_str_property prop = test->expected_str_props[i];
8795             BSTR received = NULL;
8796 
8797             hr = IUri_GetPropertyBSTR(uri, i, &received, 0);
8798             todo_wine_if(prop.todo)
8799                 ok(hr == prop.result,
8800                     "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_str_props[%d].\n",
8801                     hr, prop.result, test_index, i);
8802             if(SUCCEEDED(hr)) {
8803                 todo_wine_if(prop.todo)
8804                     ok(!strcmp_aw(prop.expected, received),
8805                         "Error: Expected %s but got %s instead on uri_builder_tests[%d].expected_str_props[%d].\n",
8806                         prop.expected, wine_dbgstr_w(received), test_index, i);
8807             }
8808             SysFreeString(received);
8809         }
8810 
8811         for(i = 0; i < sizeof(test->expected_dword_props)/sizeof(test->expected_dword_props[0]); ++i) {
8812             uri_builder_dword_property prop = test->expected_dword_props[i];
8813             DWORD received = -2;
8814 
8815             hr = IUri_GetPropertyDWORD(uri, i+Uri_PROPERTY_DWORD_START, &received, 0);
8816             todo_wine_if(prop.todo)
8817                 ok(hr == prop.result,
8818                     "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_dword_props[%d].\n",
8819                     hr, prop.result, test_index, i);
8820             if(SUCCEEDED(hr)) {
8821                 todo_wine_if(prop.todo)
8822                     ok(received == prop.expected,
8823                         "Error: Expected %d but got %d instead on uri_builder_tests[%d].expected_dword_props[%d].\n",
8824                         prop.expected, received, test_index, i);
8825             }
8826         }
8827     }
8828     if(uri) IUri_Release(uri);
8829 }
8830 
8831 static void test_IUriBuilder_CreateInvalidArgs(void) {
8832     IUriBuilder *builder;
8833     HRESULT hr;
8834 
8835     hr = pCreateIUriBuilder(NULL, 0, 0, &builder);
8836     ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8837     if(SUCCEEDED(hr)) {
8838         IUri *test = NULL, *uri = (void*) 0xdeadbeef;
8839 
8840         /* Test what happens if the IUriBuilder doesn't have a IUri set. */
8841         hr = IUriBuilder_CreateUri(builder, 0, 0, 0, NULL);
8842         ok(hr == E_POINTER, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
8843 
8844         uri = (void*) 0xdeadbeef;
8845         hr = IUriBuilder_CreateUri(builder, 0, Uri_HAS_USER_NAME, 0, &uri);
8846         ok(hr == E_NOTIMPL, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, E_NOTIMPL);
8847         ok(uri == NULL, "Error: expected uri to be NULL, but was %p instead.\n", uri);
8848 
8849         hr = IUriBuilder_CreateUriSimple(builder, 0, 0, NULL);
8850         ok(hr == E_POINTER, "Error: IUriBuilder_CreateUriSimple returned 0x%08x, expected 0x%08x.\n",
8851             hr, E_POINTER);
8852 
8853         uri = (void*) 0xdeadbeef;
8854         hr = IUriBuilder_CreateUriSimple(builder, Uri_HAS_USER_NAME, 0, &uri);
8855         ok(hr == E_NOTIMPL, "Error: IUriBuilder_CreateUriSimple returned 0x%08x, expected 0x%08x.\n",
8856             hr, E_NOTIMPL);
8857         ok(!uri, "Error: Expected uri to NULL, but was %p instead.\n", uri);
8858 
8859         hr = IUriBuilder_CreateUriWithFlags(builder, 0, 0, 0, 0, NULL);
8860         ok(hr == E_POINTER, "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x.\n",
8861             hr, E_POINTER);
8862 
8863         uri = (void*) 0xdeadbeef;
8864         hr = IUriBuilder_CreateUriWithFlags(builder, 0, 0, Uri_HAS_USER_NAME, 0, &uri);
8865         ok(hr == E_NOTIMPL, "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x.\n",
8866             hr, E_NOTIMPL);
8867         ok(!uri, "Error: Expected uri to be NULL, but was %p instead.\n", uri);
8868 
8869         hr = pCreateUri(http_urlW, 0, 0, &test);
8870         ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8871         if(SUCCEEDED(hr)) {
8872             hr = IUriBuilder_SetIUri(builder, test);
8873             ok(hr == S_OK, "Error: IUriBuilder_SetIUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8874 
8875             /* No longer returns E_NOTIMPL, since a IUri has been set and hasn't been modified. */
8876             uri = NULL;
8877             hr = IUriBuilder_CreateUri(builder, 0, Uri_HAS_USER_NAME, 0, &uri);
8878             ok(hr == S_OK, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8879             ok(uri != NULL, "Error: The uri was NULL.\n");
8880             if(uri) IUri_Release(uri);
8881 
8882             uri = NULL;
8883             hr = IUriBuilder_CreateUriSimple(builder, Uri_HAS_USER_NAME, 0, &uri);
8884             ok(hr == S_OK, "Error: IUriBuilder_CreateUriSimple returned 0x%08x, expected 0x%08x.\n",
8885                 hr, S_OK);
8886             ok(uri != NULL, "Error: uri was NULL.\n");
8887             if(uri) IUri_Release(uri);
8888 
8889             uri = NULL;
8890             hr = IUriBuilder_CreateUriWithFlags(builder, 0, 0, 0, 0, &uri);
8891             ok(hr == S_OK, "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x.\n",
8892                 hr, S_OK);
8893             ok(uri != NULL, "Error: uri was NULL.\n");
8894             if(uri) IUri_Release(uri);
8895 
8896             hr = IUriBuilder_SetFragment(builder, NULL);
8897             ok(hr == S_OK, "Error: IUriBuilder_SetFragment returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8898 
8899             /* The IUriBuilder is changed, so it returns E_NOTIMPL again. */
8900             uri = (void*) 0xdeadbeef;
8901             hr = IUriBuilder_CreateUri(builder, 0, Uri_HAS_USER_NAME, 0, &uri);
8902             ok(hr == E_NOTIMPL, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8903             ok(!uri, "Error: Expected uri to be NULL but was %p instead.\n", uri);
8904 
8905             uri = (void*) 0xdeadbeef;
8906             hr = IUriBuilder_CreateUriSimple(builder, Uri_HAS_USER_NAME, 0, &uri);
8907             ok(hr == E_NOTIMPL, "Error: IUriBuilder_CreateUriSimple returned 0x%08x, expected 0x%08x.\n",
8908                 hr, S_OK);
8909             ok(!uri, "Error: Expected uri to be NULL, but was %p instead.\n", uri);
8910 
8911             uri = (void*) 0xdeadbeef;
8912             hr = IUriBuilder_CreateUriWithFlags(builder, 0, 0, Uri_HAS_USER_NAME, 0, &uri);
8913             ok(hr == E_NOTIMPL, "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x.\n",
8914                 hr, E_NOTIMPL);
8915             ok(!uri, "Error: Expected uri to be NULL, but was %p instead.\n", uri);
8916         }
8917         if(test) IUri_Release(test);
8918     }
8919     if(builder) IUriBuilder_Release(builder);
8920 }
8921 
8922 /* Tests invalid args to the "Get*" functions. */
8923 static void test_IUriBuilder_GetInvalidArgs(void) {
8924     IUriBuilder *builder = NULL;
8925     HRESULT hr;
8926 
8927     hr = pCreateIUriBuilder(NULL, 0, 0, &builder);
8928     ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8929     if(SUCCEEDED(hr)) {
8930         LPCWSTR received = (void*) 0xdeadbeef;
8931         DWORD len = -1, port = -1;
8932         BOOL set = -1;
8933 
8934         hr = IUriBuilder_GetFragment(builder, NULL, NULL);
8935         ok(hr == E_POINTER, "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x.\n",
8936             hr, E_POINTER);
8937         hr = IUriBuilder_GetFragment(builder, NULL, &received);
8938         ok(hr == E_POINTER, "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x.\n",
8939             hr, E_POINTER);
8940         ok(!received, "Error: Expected received to be NULL, but was %p instead.\n", received);
8941         hr = IUriBuilder_GetFragment(builder, &len, NULL);
8942         ok(hr == E_POINTER, "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x.\n",
8943             hr, E_POINTER);
8944         ok(!len, "Error: Expected len to be 0, but was %d instead.\n", len);
8945 
8946         hr = IUriBuilder_GetHost(builder, NULL, NULL);
8947         ok(hr == E_POINTER, "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x.\n",
8948             hr, E_POINTER);
8949         received = (void*) 0xdeadbeef;
8950         hr = IUriBuilder_GetHost(builder, NULL, &received);
8951         ok(hr == E_POINTER, "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x.\n",
8952             hr, E_POINTER);
8953         ok(!received, "Error: Expected received to be NULL, but was %p instead.\n", received);
8954         len = -1;
8955         hr = IUriBuilder_GetHost(builder, &len, NULL);
8956         ok(hr == E_POINTER, "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x.\n",
8957             hr, E_POINTER);
8958         ok(!len, "Error: Expected len to be 0, but was %d instead.\n", len);
8959 
8960         hr = IUriBuilder_GetPassword(builder, NULL, NULL);
8961         ok(hr == E_POINTER, "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x.\n",
8962             hr, E_POINTER);
8963         received = (void*) 0xdeadbeef;
8964         hr = IUriBuilder_GetPassword(builder, NULL, &received);
8965         ok(hr == E_POINTER, "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x.\n",
8966             hr, E_POINTER);
8967         ok(!received, "Error: Expected received to be NULL, but was %p instead.\n", received);
8968         len = -1;
8969         hr = IUriBuilder_GetPassword(builder, &len, NULL);
8970         ok(hr == E_POINTER, "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x.\n",
8971             hr, E_POINTER);
8972         ok(!len, "Error: Expected len to be 0, but was %d instead.\n", len);
8973 
8974         hr = IUriBuilder_GetPath(builder, NULL, NULL);
8975         ok(hr == E_POINTER, "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x.\n",
8976             hr, E_POINTER);
8977         received = (void*) 0xdeadbeef;
8978         hr = IUriBuilder_GetPath(builder, NULL, &received);
8979         ok(hr == E_POINTER, "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x.\n",
8980             hr, E_POINTER);
8981         ok(!received, "Error: Expected received to be NULL, but was %p instead.\n", received);
8982         len = -1;
8983         hr = IUriBuilder_GetPath(builder, &len, NULL);
8984         ok(hr == E_POINTER, "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x.\n",
8985             hr, E_POINTER);
8986         ok(!len, "Error: Expected len to be 0, but was %d instead.\n", len);
8987 
8988         hr = IUriBuilder_GetPort(builder, NULL, NULL);
8989         ok(hr == E_POINTER, "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x.\n",
8990             hr, E_POINTER);
8991         hr = IUriBuilder_GetPort(builder, NULL, &port);
8992         ok(hr == E_POINTER, "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x.\n",
8993             hr, E_POINTER);
8994         ok(!port, "Error: Expected port to be 0, but was %d instead.\n", port);
8995         hr = IUriBuilder_GetPort(builder, &set, NULL);
8996         ok(hr == E_POINTER, "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x.\n",
8997             hr, E_POINTER);
8998         ok(!set, "Error: Expected set to be FALSE, but was %d instead.\n", set);
8999 
9000         hr = IUriBuilder_GetQuery(builder, NULL, NULL);
9001         ok(hr == E_POINTER, "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x.\n",
9002             hr, E_POINTER);
9003         received = (void*) 0xdeadbeef;
9004         hr = IUriBuilder_GetQuery(builder, NULL, &received);
9005         ok(hr == E_POINTER, "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x.\n",
9006             hr, E_POINTER);
9007         ok(!received, "Error: Expected received to be NULL, but was %p instead.\n", received);
9008         len = -1;
9009         hr = IUriBuilder_GetQuery(builder, &len, NULL);
9010         ok(hr == E_POINTER, "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x.\n",
9011             hr, E_POINTER);
9012         ok(!len, "Error: Expected len to be 0, but was %d instead.\n", len);
9013 
9014         hr = IUriBuilder_GetSchemeName(builder, NULL, NULL);
9015         ok(hr == E_POINTER, "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x.\n",
9016             hr, E_POINTER);
9017         received = (void*) 0xdeadbeef;
9018         hr = IUriBuilder_GetSchemeName(builder, NULL, &received);
9019         ok(hr == E_POINTER, "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x.\n",
9020             hr, E_POINTER);
9021         ok(!received, "Error: Expected received to be NULL, but was %p instead.\n", received);
9022         len = -1;
9023         hr = IUriBuilder_GetSchemeName(builder, &len, NULL);
9024         ok(hr == E_POINTER, "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x.\n",
9025             hr, E_POINTER);
9026         ok(!len, "Error: Expected len to be 0, but was %d instead.\n", len);
9027 
9028         hr = IUriBuilder_GetUserName(builder, NULL, NULL);
9029         ok(hr == E_POINTER, "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x.\n",
9030             hr, E_POINTER);
9031         received = (void*) 0xdeadbeef;
9032         hr = IUriBuilder_GetUserName(builder, NULL, &received);
9033         ok(hr == E_POINTER, "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x.\n",
9034             hr, E_POINTER);
9035         ok(!received, "Error: Expected received to be NULL, but was %p instead.\n", received);
9036         len = -1;
9037         hr = IUriBuilder_GetUserName(builder, &len, NULL);
9038         ok(hr == E_POINTER, "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x.\n",
9039             hr, E_POINTER);
9040         ok(!len, "Error: Expected len to be 0, but was %d instead.\n", len);
9041     }
9042     if(builder) IUriBuilder_Release(builder);
9043 }
9044 
9045 static void test_IUriBuilder_GetFragment(IUriBuilder *builder, const uri_builder_test *test,
9046                                          DWORD test_index) {
9047     HRESULT hr;
9048     DWORD i;
9049     LPCWSTR received = NULL;
9050     DWORD len = -1;
9051     const uri_builder_property *prop = NULL;
9052 
9053     /* Check if the property was set earlier. */
9054     for(i = 0; i < sizeof(test->properties)/sizeof(test->properties[0]); ++i) {
9055         if(test->properties[i].change && test->properties[i].property == Uri_PROPERTY_FRAGMENT)
9056             prop = &(test->properties[i]);
9057     }
9058 
9059     if(prop) {
9060         /* Use expected_value unless it's NULL, then use value. */
9061         LPCSTR expected = prop->expected_value ? prop->expected_value : prop->value;
9062         DWORD expected_len = expected ? strlen(expected) : 0;
9063         hr = IUriBuilder_GetFragment(builder, &len, &received);
9064         todo_wine_if(prop->todo) {
9065             ok(hr == (expected ? S_OK : S_FALSE),
9066                 "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9067                 hr, (expected ? S_OK : S_FALSE), test_index);
9068             if(SUCCEEDED(hr)) {
9069                 ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
9070                    expected, wine_dbgstr_w(received), test_index);
9071                 ok(expected_len == len,
9072                    "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
9073                    expected_len, len, test_index);
9074             }
9075         }
9076     } else {
9077         /* The property wasn't set earlier, so it should return whatever
9078          * the base IUri contains (if anything).
9079          */
9080         IUri *uri = NULL;
9081         hr = IUriBuilder_GetIUri(builder, &uri);
9082         ok(hr == S_OK,
9083             "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9084             hr, S_OK, test_index);
9085         if(SUCCEEDED(hr)) {
9086             if(!uri) {
9087                 received = (void*) 0xdeadbeef;
9088                 len = -1;
9089 
9090                 hr = IUriBuilder_GetFragment(builder, &len, &received);
9091                 ok(hr == S_FALSE,
9092                     "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9093                     hr, S_FALSE, test_index);
9094                 if(SUCCEEDED(hr)) {
9095                     ok(!len, "Error: Expected len to be 0, but was %d instead on uri_builder_tests[%d].\n",
9096                         len, test_index);
9097                     ok(!received, "Error: Expected received to be NULL, but was %p instead on uri_builder_tests[%d].\n",
9098                         received, test_index);
9099                 }
9100             } else {
9101                 BOOL has_prop = FALSE;
9102                 BSTR expected = NULL;
9103 
9104                 hr = IUri_GetFragment(uri, &expected);
9105                 ok(SUCCEEDED(hr),
9106                     "Error: Expected IUri_GetFragment to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
9107                     hr, test_index);
9108                 has_prop = hr == S_OK;
9109 
9110                 hr = IUriBuilder_GetFragment(builder, &len, &received);
9111                 if(has_prop) {
9112                     ok(hr == S_OK,
9113                         "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9114                         hr, S_OK, test_index);
9115                     if(SUCCEEDED(hr)) {
9116                         ok(!lstrcmpW(expected, received),
9117                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].\n",
9118                             wine_dbgstr_w(expected), wine_dbgstr_w(received), test_index);
9119                         ok(lstrlenW(expected) == len,
9120                             "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
9121                             lstrlenW(expected), len, test_index);
9122                     }
9123                 } else {
9124                     ok(hr == S_FALSE,
9125                         "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9126                         hr, S_FALSE, test_index);
9127                     if(SUCCEEDED(hr)) {
9128                         ok(!received, "Error: Expected received to be NULL on uri_builder_tests[%d].\n", test_index);
9129                         ok(!len, "Error: Expected the length to be 0, but was %d instead on uri_builder_tests[%d].\n",
9130                             len, test_index);
9131                     }
9132                 }
9133                 SysFreeString(expected);
9134             }
9135         }
9136         if(uri) IUri_Release(uri);
9137     }
9138 }
9139 
9140 static void test_IUriBuilder_GetHost(IUriBuilder *builder, const uri_builder_test *test,
9141                                      DWORD test_index) {
9142     HRESULT hr;
9143     DWORD i;
9144     LPCWSTR received = NULL;
9145     DWORD len = -1;
9146     const uri_builder_property *prop = NULL;
9147 
9148     /* Check if the property was set earlier. */
9149     for(i = 0; i < sizeof(test->properties)/sizeof(test->properties[0]); ++i) {
9150         if(test->properties[i].change && test->properties[i].property == Uri_PROPERTY_HOST)
9151             prop = &(test->properties[i]);
9152     }
9153 
9154     if(prop) {
9155         /* Use expected_value unless it's NULL, then use value. */
9156         LPCSTR expected = prop->expected_value ? prop->expected_value : prop->value;
9157         DWORD expected_len = expected ? strlen(expected) : 0;
9158         hr = IUriBuilder_GetHost(builder, &len, &received);
9159         todo_wine_if(prop->todo) {
9160             ok(hr == (expected ? S_OK : S_FALSE),
9161                 "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9162                 hr, (expected ? S_OK : S_FALSE), test_index);
9163             if(SUCCEEDED(hr)) {
9164                 ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
9165                    expected, wine_dbgstr_w(received), test_index);
9166                 ok(expected_len == len,
9167                    "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
9168                    expected_len, len, test_index);
9169             }
9170         }
9171     } else {
9172         /* The property wasn't set earlier, so it should return whatever
9173          * the base IUri contains (if anything).
9174          */
9175         IUri *uri = NULL;
9176         hr = IUriBuilder_GetIUri(builder, &uri);
9177         ok(hr == S_OK,
9178             "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9179             hr, S_OK, test_index);
9180         if(SUCCEEDED(hr)) {
9181             if(!uri) {
9182                 received = (void*) 0xdeadbeef;
9183                 len = -1;
9184 
9185                 hr = IUriBuilder_GetHost(builder, &len, &received);
9186                 ok(hr == S_FALSE,
9187                     "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9188                     hr, S_FALSE, test_index);
9189                 if(SUCCEEDED(hr)) {
9190                     ok(!len, "Error: Expected len to be 0, but was %d instead on uri_builder_tests[%d].\n",
9191                         len, test_index);
9192                     ok(!received, "Error: Expected received to be NULL, but was %p instead on uri_builder_tests[%d].\n",
9193                         received, test_index);
9194                 }
9195             } else {
9196                 BOOL has_prop = FALSE;
9197                 BSTR expected = NULL;
9198 
9199                 hr = IUri_GetHost(uri, &expected);
9200                 ok(SUCCEEDED(hr),
9201                     "Error: Expected IUri_GetHost to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
9202                     hr, test_index);
9203                 has_prop = hr == S_OK;
9204 
9205                 hr = IUriBuilder_GetHost(builder, &len, &received);
9206                 if(has_prop) {
9207                     ok(hr == S_OK,
9208                         "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9209                         hr, S_OK, test_index);
9210                     if(SUCCEEDED(hr)) {
9211                         ok(!lstrcmpW(expected, received),
9212                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].\n",
9213                             wine_dbgstr_w(expected), wine_dbgstr_w(received), test_index);
9214                         ok(lstrlenW(expected) == len,
9215                             "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
9216                             lstrlenW(expected), len, test_index);
9217                     }
9218                 } else {
9219                     ok(hr == S_FALSE,
9220                         "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9221                         hr, S_FALSE, test_index);
9222                     if(SUCCEEDED(hr)) {
9223                         ok(!received, "Error: Expected received to be NULL on uri_builder_tests[%d].\n", test_index);
9224                         ok(!len, "Error: Expected the length to be 0, but was %d instead on uri_builder_tests[%d].\n",
9225                             len, test_index);
9226                     }
9227                 }
9228                 SysFreeString(expected);
9229             }
9230         }
9231         if(uri) IUri_Release(uri);
9232     }
9233 }
9234 
9235 static void test_IUriBuilder_GetPassword(IUriBuilder *builder, const uri_builder_test *test,
9236                                          DWORD test_index) {
9237     HRESULT hr;
9238     DWORD i;
9239     LPCWSTR received = NULL;
9240     DWORD len = -1;
9241     const uri_builder_property *prop = NULL;
9242 
9243     /* Check if the property was set earlier. */
9244     for(i = 0; i < sizeof(test->properties)/sizeof(test->properties[0]); ++i) {
9245         if(test->properties[i].change && test->properties[i].property == Uri_PROPERTY_PASSWORD)
9246             prop = &(test->properties[i]);
9247     }
9248 
9249     if(prop) {
9250         /* Use expected_value unless it's NULL, then use value. */
9251         LPCSTR expected = prop->expected_value ? prop->expected_value : prop->value;
9252         DWORD expected_len = expected ? strlen(expected) : 0;
9253         hr = IUriBuilder_GetPassword(builder, &len, &received);
9254         todo_wine_if(prop->todo) {
9255             ok(hr == (expected ? S_OK : S_FALSE),
9256                 "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9257                 hr, (expected ? S_OK : S_FALSE), test_index);
9258             if(SUCCEEDED(hr)) {
9259                 ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
9260                    expected, wine_dbgstr_w(received), test_index);
9261                 ok(expected_len == len,
9262                    "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
9263                    expected_len, len, test_index);
9264             }
9265         }
9266     } else {
9267         /* The property wasn't set earlier, so it should return whatever
9268          * the base IUri contains (if anything).
9269          */
9270         IUri *uri = NULL;
9271         hr = IUriBuilder_GetIUri(builder, &uri);
9272         ok(hr == S_OK,
9273             "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9274             hr, S_OK, test_index);
9275         if(SUCCEEDED(hr)) {
9276             if(!uri) {
9277                 received = (void*) 0xdeadbeef;
9278                 len = -1;
9279 
9280                 hr = IUriBuilder_GetPassword(builder, &len, &received);
9281                 ok(hr == S_FALSE,
9282                     "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9283                     hr, S_FALSE, test_index);
9284                 if(SUCCEEDED(hr)) {
9285                     ok(!len, "Error: Expected len to be 0, but was %d instead on uri_builder_tests[%d].\n",
9286                         len, test_index);
9287                     ok(!received, "Error: Expected received to be NULL, but was %p instead on uri_builder_tests[%d].\n",
9288                         received, test_index);
9289                 }
9290             } else {
9291                 BOOL has_prop = FALSE;
9292                 BSTR expected = NULL;
9293 
9294                 hr = IUri_GetPassword(uri, &expected);
9295                 ok(SUCCEEDED(hr),
9296                     "Error: Expected IUri_GetPassword to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
9297                     hr, test_index);
9298                 has_prop = hr == S_OK;
9299 
9300                 hr = IUriBuilder_GetPassword(builder, &len, &received);
9301                 if(has_prop) {
9302                     ok(hr == S_OK,
9303                         "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9304                         hr, S_OK, test_index);
9305                     if(SUCCEEDED(hr)) {
9306                         ok(!lstrcmpW(expected, received),
9307                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].\n",
9308                             wine_dbgstr_w(expected), wine_dbgstr_w(received), test_index);
9309                         ok(lstrlenW(expected) == len,
9310                             "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
9311                             lstrlenW(expected), len, test_index);
9312                     }
9313                 } else {
9314                     ok(hr == S_FALSE,
9315                         "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9316                         hr, S_FALSE, test_index);
9317                     if(SUCCEEDED(hr)) {
9318                         ok(!received, "Error: Expected received to be NULL on uri_builder_tests[%d].\n", test_index);
9319                         ok(!len, "Error: Expected the length to be 0, but was %d instead on uri_builder_tests[%d].\n",
9320                             len, test_index);
9321                     }
9322                 }
9323                 SysFreeString(expected);
9324             }
9325         }
9326         if(uri) IUri_Release(uri);
9327     }
9328 }
9329 
9330 static void test_IUriBuilder_GetPath(IUriBuilder *builder, const uri_builder_test *test,
9331                                      DWORD test_index) {
9332     HRESULT hr;
9333     DWORD i;
9334     LPCWSTR received = NULL;
9335     DWORD len = -1;
9336     const uri_builder_property *prop = NULL;
9337 
9338     /* Check if the property was set earlier. */
9339     for(i = 0; i < sizeof(test->properties)/sizeof(test->properties[0]); ++i) {
9340         if(test->properties[i].change && test->properties[i].property == Uri_PROPERTY_PATH)
9341             prop = &(test->properties[i]);
9342     }
9343 
9344     if(prop) {
9345         /* Use expected_value unless it's NULL, then use value. */
9346         LPCSTR expected = prop->expected_value ? prop->expected_value : prop->value;
9347         DWORD expected_len = expected ? strlen(expected) : 0;
9348         hr = IUriBuilder_GetPath(builder, &len, &received);
9349         todo_wine_if(prop->todo) {
9350             ok(hr == (expected ? S_OK : S_FALSE),
9351                 "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9352                 hr, (expected ? S_OK : S_FALSE), test_index);
9353             if(SUCCEEDED(hr)) {
9354                 ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
9355                    expected, wine_dbgstr_w(received), test_index);
9356                 ok(expected_len == len,
9357                    "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
9358                    expected_len, len, test_index);
9359             }
9360         }
9361     } else {
9362         /* The property wasn't set earlier, so it should return whatever
9363          * the base IUri contains (if anything).
9364          */
9365         IUri *uri = NULL;
9366         hr = IUriBuilder_GetIUri(builder, &uri);
9367         ok(hr == S_OK,
9368             "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9369             hr, S_OK, test_index);
9370         if(SUCCEEDED(hr)) {
9371             if(!uri) {
9372                 received = (void*) 0xdeadbeef;
9373                 len = -1;
9374 
9375                 hr = IUriBuilder_GetPath(builder, &len, &received);
9376                 ok(hr == S_FALSE,
9377                     "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9378                     hr, S_FALSE, test_index);
9379                 if(SUCCEEDED(hr)) {
9380                     ok(!len, "Error: Expected len to be 0, but was %d instead on uri_builder_tests[%d].\n",
9381                         len, test_index);
9382                     ok(!received, "Error: Expected received to be NULL, but was %p instead on uri_builder_tests[%d].\n",
9383                         received, test_index);
9384                 }
9385             } else {
9386                 BOOL has_prop = FALSE;
9387                 BSTR expected = NULL;
9388 
9389                 hr = IUri_GetPath(uri, &expected);
9390                 ok(SUCCEEDED(hr),
9391                     "Error: Expected IUri_GetPath to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
9392                     hr, test_index);
9393                 has_prop = hr == S_OK;
9394 
9395                 hr = IUriBuilder_GetPath(builder, &len, &received);
9396                 if(has_prop) {
9397                     ok(hr == S_OK,
9398                         "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9399                         hr, S_OK, test_index);
9400                     if(SUCCEEDED(hr)) {
9401                         ok(!lstrcmpW(expected, received),
9402                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].\n",
9403                             wine_dbgstr_w(expected), wine_dbgstr_w(received), test_index);
9404                         ok(lstrlenW(expected) == len,
9405                             "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
9406                             lstrlenW(expected), len, test_index);
9407                     }
9408                 } else {
9409                     ok(hr == S_FALSE,
9410                         "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9411                         hr, S_FALSE, test_index);
9412                     if(SUCCEEDED(hr)) {
9413                         ok(!received, "Error: Expected received to be NULL on uri_builder_tests[%d].\n", test_index);
9414                         ok(!len, "Error: Expected the length to be 0, but was %d instead on uri_builder_tests[%d].\n",
9415                             len, test_index);
9416                     }
9417                 }
9418                 SysFreeString(expected);
9419             }
9420         }
9421         if(uri) IUri_Release(uri);
9422     }
9423 }
9424 
9425 static void test_IUriBuilder_GetPort(IUriBuilder *builder, const uri_builder_test *test,
9426                                      DWORD test_index) {
9427     HRESULT hr;
9428     BOOL has_port = FALSE;
9429     DWORD received = -1;
9430 
9431     if(test->port_prop.change) {
9432         hr = IUriBuilder_GetPort(builder, &has_port, &received);
9433         todo_wine_if(test->port_prop.todo) {
9434             ok(hr == S_OK,
9435                 "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9436                 hr, S_OK, test_index);
9437             if(SUCCEEDED(hr)) {
9438                 ok(has_port == test->port_prop.set,
9439                    "Error: Expected has_port to be %d, but was %d instead on uri_builder_tests[%d].\n",
9440                    test->port_prop.set, has_port, test_index);
9441                 ok(received == test->port_prop.value,
9442                    "Error: Expected port to be %d, but was %d instead on uri_builder_tests[%d].\n",
9443                    test->port_prop.value, received, test_index);
9444             }
9445         }
9446     } else {
9447         IUri *uri = NULL;
9448 
9449         hr = IUriBuilder_GetIUri(builder, &uri);
9450         ok(hr == S_OK,
9451             "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9452             hr, S_OK, test_index);
9453         if(SUCCEEDED(hr)) {
9454             if(!uri) {
9455                 hr = IUriBuilder_GetPort(builder, &has_port, &received);
9456                 ok(hr == S_OK,
9457                     "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9458                     hr, S_OK, test_index);
9459                 if(SUCCEEDED(hr)) {
9460                     ok(has_port == FALSE,
9461                         "Error: Expected has_port to be FALSE, but was %d instead on uri_builder_tests[%d].\n",
9462                         has_port, test_index);
9463                     ok(!received, "Error: Expected received to be 0, but was %d instead on uri_builder_tests[%d].\n",
9464                         received, test_index);
9465                 }
9466             } else {
9467                 DWORD expected;
9468 
9469                 hr = IUri_GetPort(uri, &expected);
9470                 ok(SUCCEEDED(hr),
9471                     "Error: Expected IUri_Port to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
9472                     hr, test_index);
9473 
9474                 hr = IUriBuilder_GetPort(builder, &has_port, &received);
9475                 ok(hr == S_OK,
9476                     "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9477                     hr, S_OK, test_index);
9478                 if(SUCCEEDED(hr)) {
9479                     ok(!has_port,
9480                         "Error: Expected has_port to be FALSE but was TRUE instead on uri_builder_tests[%d].\n",
9481                         test_index);
9482                     ok(received == expected,
9483                         "Error: Expected received to be %d, but was %d instead on uri_builder_tests[%d].\n",
9484                         expected, received, test_index);
9485                 }
9486             }
9487         }
9488         if(uri) IUri_Release(uri);
9489     }
9490 }
9491 
9492 static void test_IUriBuilder_GetQuery(IUriBuilder *builder, const uri_builder_test *test,
9493                                       DWORD test_index) {
9494     HRESULT hr;
9495     DWORD i;
9496     LPCWSTR received = NULL;
9497     DWORD len = -1;
9498     const uri_builder_property *prop = NULL;
9499 
9500     /* Check if the property was set earlier. */
9501     for(i = 0; i < sizeof(test->properties)/sizeof(test->properties[0]); ++i) {
9502         if(test->properties[i].change && test->properties[i].property == Uri_PROPERTY_QUERY)
9503             prop = &(test->properties[i]);
9504     }
9505 
9506     if(prop) {
9507         /* Use expected_value unless it's NULL, then use value. */
9508         LPCSTR expected = prop->expected_value ? prop->expected_value : prop->value;
9509         DWORD expected_len = expected ? strlen(expected) : 0;
9510         hr = IUriBuilder_GetQuery(builder, &len, &received);
9511         todo_wine_if(prop->todo) {
9512             ok(hr == (expected ? S_OK : S_FALSE),
9513                 "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9514                 hr, (expected ? S_OK : S_FALSE), test_index);
9515             if(SUCCEEDED(hr)) {
9516                 ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
9517                    expected, wine_dbgstr_w(received), test_index);
9518                 ok(expected_len == len,
9519                    "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
9520                    expected_len, len, test_index);
9521             }
9522         }
9523     } else {
9524         /* The property wasn't set earlier, so it should return whatever
9525          * the base IUri contains (if anything).
9526          */
9527         IUri *uri = NULL;
9528         hr = IUriBuilder_GetIUri(builder, &uri);
9529         ok(hr == S_OK,
9530             "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9531             hr, S_OK, test_index);
9532         if(SUCCEEDED(hr)) {
9533             if(!uri) {
9534                 received = (void*) 0xdeadbeef;
9535                 len = -1;
9536 
9537                 hr = IUriBuilder_GetQuery(builder, &len, &received);
9538                 ok(hr == S_FALSE,
9539                     "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9540                     hr, S_FALSE, test_index);
9541                 if(SUCCEEDED(hr)) {
9542                     ok(!len, "Error: Expected len to be 0, but was %d instead on uri_builder_tests[%d].\n",
9543                         len, test_index);
9544                     ok(!received, "Error: Expected received to be NULL, but was %p instead on uri_builder_tests[%d].\n",
9545                         received, test_index);
9546                 }
9547             } else {
9548                 BOOL has_prop = FALSE;
9549                 BSTR expected = NULL;
9550 
9551                 hr = IUri_GetQuery(uri, &expected);
9552                 ok(SUCCEEDED(hr),
9553                     "Error: Expected IUri_GetQuery to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
9554                     hr, test_index);
9555                 has_prop = hr == S_OK;
9556 
9557                 hr = IUriBuilder_GetQuery(builder, &len, &received);
9558                 if(has_prop) {
9559                     ok(hr == S_OK,
9560                         "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9561                         hr, S_OK, test_index);
9562                     if(SUCCEEDED(hr)) {
9563                         ok(!lstrcmpW(expected, received),
9564                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].\n",
9565                             wine_dbgstr_w(expected), wine_dbgstr_w(received), test_index);
9566                         ok(lstrlenW(expected) == len,
9567                             "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
9568                             lstrlenW(expected), len, test_index);
9569                     }
9570                 } else {
9571                     ok(hr == S_FALSE,
9572                         "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9573                         hr, S_FALSE, test_index);
9574                     if(SUCCEEDED(hr)) {
9575                         ok(!received, "Error: Expected received to be NULL on uri_builder_tests[%d].\n", test_index);
9576                         ok(!len, "Error: Expected the length to be 0, but was %d instead on uri_builder_tests[%d].\n",
9577                             len, test_index);
9578                     }
9579                 }
9580                 SysFreeString(expected);
9581             }
9582         }
9583         if(uri) IUri_Release(uri);
9584     }
9585 }
9586 
9587 static void test_IUriBuilder_GetSchemeName(IUriBuilder *builder, const uri_builder_test *test,
9588                                            DWORD test_index) {
9589     HRESULT hr;
9590     DWORD i;
9591     LPCWSTR received = NULL;
9592     DWORD len = -1;
9593     const uri_builder_property *prop = NULL;
9594 
9595     /* Check if the property was set earlier. */
9596     for(i = 0; i < sizeof(test->properties)/sizeof(test->properties[0]); ++i) {
9597         if(test->properties[i].change && test->properties[i].property == Uri_PROPERTY_SCHEME_NAME)
9598             prop = &(test->properties[i]);
9599     }
9600 
9601     if(prop) {
9602         /* Use expected_value unless it's NULL, then use value. */
9603         LPCSTR expected = prop->expected_value ? prop->expected_value : prop->value;
9604         DWORD expected_len = expected ? strlen(expected) : 0;
9605         hr = IUriBuilder_GetSchemeName(builder, &len, &received);
9606         todo_wine_if(prop->todo) {
9607             ok(hr == (expected ? S_OK : S_FALSE),
9608                 "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9609                 hr, (expected ? S_OK : S_FALSE), test_index);
9610             if(SUCCEEDED(hr)) {
9611                 ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
9612                    expected, wine_dbgstr_w(received), test_index);
9613                 ok(expected_len == len,
9614                    "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
9615                    expected_len, len, test_index);
9616             }
9617         }
9618     } else {
9619         /* The property wasn't set earlier, so it should return whatever
9620          * the base IUri contains (if anything).
9621          */
9622         IUri *uri = NULL;
9623         hr = IUriBuilder_GetIUri(builder, &uri);
9624         ok(hr == S_OK,
9625             "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9626             hr, S_OK, test_index);
9627         if(SUCCEEDED(hr)) {
9628             if(!uri) {
9629                 received = (void*) 0xdeadbeef;
9630                 len = -1;
9631 
9632                 hr = IUriBuilder_GetSchemeName(builder, &len, &received);
9633                 ok(hr == S_FALSE,
9634                     "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9635                     hr, S_FALSE, test_index);
9636                 if(SUCCEEDED(hr)) {
9637                     ok(!len, "Error: Expected len to be 0, but was %d instead on uri_builder_tests[%d].\n",
9638                         len, test_index);
9639                     ok(!received, "Error: Expected received to be NULL, but was %p instead on uri_builder_tests[%d].\n",
9640                         received, test_index);
9641                 }
9642             } else {
9643                 BOOL has_prop = FALSE;
9644                 BSTR expected = NULL;
9645 
9646                 hr = IUri_GetSchemeName(uri, &expected);
9647                 ok(SUCCEEDED(hr),
9648                     "Error: Expected IUri_GetSchemeName to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
9649                     hr, test_index);
9650                 has_prop = hr == S_OK;
9651 
9652                 hr = IUriBuilder_GetSchemeName(builder, &len, &received);
9653                 if(has_prop) {
9654                     ok(hr == S_OK,
9655                         "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9656                         hr, S_OK, test_index);
9657                     if(SUCCEEDED(hr)) {
9658                         ok(!lstrcmpW(expected, received),
9659                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].\n",
9660                             wine_dbgstr_w(expected), wine_dbgstr_w(received), test_index);
9661                         ok(lstrlenW(expected) == len,
9662                             "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
9663                             lstrlenW(expected), len, test_index);
9664                     }
9665                 } else {
9666                     ok(hr == S_FALSE,
9667                         "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9668                         hr, S_FALSE, test_index);
9669                     if(SUCCEEDED(hr)) {
9670                         ok(!received, "Error: Expected received to be NULL on uri_builder_tests[%d].\n", test_index);
9671                         ok(!len, "Error: Expected the length to be 0, but was %d instead on uri_builder_tests[%d].\n",
9672                             len, test_index);
9673                     }
9674                 }
9675                 SysFreeString(expected);
9676             }
9677         }
9678         if(uri) IUri_Release(uri);
9679     }
9680 }
9681 
9682 static void test_IUriBuilder_GetUserName(IUriBuilder *builder, const uri_builder_test *test,
9683                                          DWORD test_index) {
9684     HRESULT hr;
9685     DWORD i;
9686     LPCWSTR received = NULL;
9687     DWORD len = -1;
9688     const uri_builder_property *prop = NULL;
9689 
9690     /* Check if the property was set earlier. */
9691     for(i = 0; i < sizeof(test->properties)/sizeof(test->properties[0]); ++i) {
9692         if(test->properties[i].change && test->properties[i].property == Uri_PROPERTY_USER_NAME)
9693             prop = &(test->properties[i]);
9694     }
9695 
9696     if(prop && prop->value && *prop->value) {
9697         /* Use expected_value unless it's NULL, then use value. */
9698         LPCSTR expected = prop->expected_value ? prop->expected_value : prop->value;
9699         DWORD expected_len = expected ? strlen(expected) : 0;
9700         hr = IUriBuilder_GetUserName(builder, &len, &received);
9701         todo_wine_if(prop->todo) {
9702             ok(hr == (expected ? S_OK : S_FALSE),
9703                 "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9704                 hr, (expected ? S_OK : S_FALSE), test_index);
9705             if(SUCCEEDED(hr)) {
9706                 ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
9707                    expected, wine_dbgstr_w(received), test_index);
9708                 ok(expected_len == len,
9709                    "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
9710                    expected_len, len, test_index);
9711             }
9712         }
9713     } else {
9714         /* The property wasn't set earlier, so it should return whatever
9715          * the base IUri contains (if anything).
9716          */
9717         IUri *uri = NULL;
9718         hr = IUriBuilder_GetIUri(builder, &uri);
9719         ok(hr == S_OK,
9720             "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9721             hr, S_OK, test_index);
9722         if(SUCCEEDED(hr)) {
9723             if(!uri) {
9724                 received = (void*) 0xdeadbeef;
9725                 len = -1;
9726 
9727                 hr = IUriBuilder_GetUserName(builder, &len, &received);
9728                 ok(hr == S_FALSE,
9729                     "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9730                     hr, S_FALSE, test_index);
9731                 if(SUCCEEDED(hr)) {
9732                     ok(!len, "Error: Expected len to be 0, but was %d instead on uri_builder_tests[%d].\n",
9733                         len, test_index);
9734                     ok(!received, "Error: Expected received to be NULL, but was %p instead on uri_builder_tests[%d].\n",
9735                         received, test_index);
9736                 }
9737             } else {
9738                 BSTR expected = NULL;
9739                 BOOL has_prop = FALSE;
9740 
9741                 hr = IUri_GetUserName(uri, &expected);
9742                 ok(SUCCEEDED(hr),
9743                     "Error: Expected IUri_GetUserName to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
9744                     hr, test_index);
9745                 has_prop = hr == S_OK;
9746 
9747                 hr = IUriBuilder_GetUserName(builder, &len, &received);
9748                 if(has_prop) {
9749                     ok(hr == S_OK,
9750                         "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9751                         hr, S_OK, test_index);
9752                     if(SUCCEEDED(hr)) {
9753                         ok(!lstrcmpW(expected, received),
9754                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].\n",
9755                             wine_dbgstr_w(expected), wine_dbgstr_w(received), test_index);
9756                         ok(lstrlenW(expected) == len,
9757                             "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
9758                             lstrlenW(expected), len, test_index);
9759                     }
9760                 } else {
9761                     ok(hr == S_FALSE,
9762                         "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9763                         hr, S_FALSE, test_index);
9764                     if(SUCCEEDED(hr)) {
9765                         ok(!received, "Error: Expected received to be NULL on uri_builder_tests[%d].\n", test_index);
9766                         ok(!len, "Error: Expected the length to be 0, but was %d instead on uri_builder_tests[%d].\n",
9767                             len, test_index);
9768                     }
9769                 }
9770                 SysFreeString(expected);
9771             }
9772         }
9773         if(uri) IUri_Release(uri);
9774     }
9775 }
9776 
9777 /* Tests IUriBuilder functions. */
9778 static void test_IUriBuilder(void) {
9779     HRESULT hr;
9780     IUriBuilder *builder;
9781     DWORD i;
9782 
9783     for(i = 0; i < sizeof(uri_builder_tests)/sizeof(uri_builder_tests[0]); ++i) {
9784         IUri *uri = NULL;
9785         uri_builder_test test = uri_builder_tests[i];
9786         LPWSTR uriW = NULL;
9787 
9788         if(test.uri) {
9789             uriW = a2w(test.uri);
9790             hr = pCreateUri(uriW, test.create_flags, 0, &uri);
9791             ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9792                 hr, S_OK, i);
9793             if(FAILED(hr)) continue;
9794         }
9795         hr = pCreateIUriBuilder(uri, 0, 0, &builder);
9796         todo_wine_if(test.create_builder_todo)
9797             ok(hr == test.create_builder_expected,
9798                 "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9799                 hr, test.create_builder_expected, i);
9800         if(SUCCEEDED(hr)) {
9801             DWORD j;
9802             BOOL modified = FALSE, received = FALSE;
9803 
9804             /* Perform all the string property changes. */
9805             for(j = 0; j < URI_BUILDER_STR_PROPERTY_COUNT; ++j) {
9806                 uri_builder_property prop = test.properties[j];
9807                 if(prop.change) {
9808                     change_property(builder, &prop, i);
9809                     if(prop.property != Uri_PROPERTY_SCHEME_NAME &&
9810                        prop.property != Uri_PROPERTY_HOST)
9811                         modified = TRUE;
9812                     else if(prop.value && *prop.value)
9813                         modified = TRUE;
9814                     else if(prop.value && !*prop.value && prop.property == Uri_PROPERTY_HOST)
9815                         /* Host name property can't be NULL, but it can be empty. */
9816                         modified = TRUE;
9817                 }
9818             }
9819 
9820             if(test.port_prop.change) {
9821                 hr = IUriBuilder_SetPort(builder, test.port_prop.set, test.port_prop.value);
9822                 modified = TRUE;
9823                 todo_wine_if(test.port_prop.todo)
9824                     ok(hr == test.port_prop.expected,
9825                         "Error: IUriBuilder_SetPort returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9826                         hr, test.port_prop.expected, i);
9827             }
9828 
9829             hr = IUriBuilder_HasBeenModified(builder, &received);
9830             ok(hr == S_OK,
9831                 "Error IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9832                 hr, S_OK, i);
9833             if(SUCCEEDED(hr))
9834                 ok(received == modified,
9835                     "Error: Expected received to be %d but was %d instead on uri_builder_tests[%d].\n",
9836                     modified, received, i);
9837 
9838             /* Test the "Get*" functions. */
9839             test_IUriBuilder_GetFragment(builder, &test, i);
9840             test_IUriBuilder_GetHost(builder, &test, i);
9841             test_IUriBuilder_GetPassword(builder, &test, i);
9842             test_IUriBuilder_GetPath(builder, &test, i);
9843             test_IUriBuilder_GetPort(builder, &test, i);
9844             test_IUriBuilder_GetQuery(builder, &test, i);
9845             test_IUriBuilder_GetSchemeName(builder, &test, i);
9846             test_IUriBuilder_GetUserName(builder, &test, i);
9847 
9848             test_IUriBuilder_CreateUri(builder, &test, i);
9849             test_IUriBuilder_CreateUriSimple(builder, &test, i);
9850             test_IUriBuilder_CreateUriWithFlags(builder, &test, i);
9851         }
9852         if(builder) IUriBuilder_Release(builder);
9853         if(uri) IUri_Release(uri);
9854         heap_free(uriW);
9855     }
9856 }
9857 
9858 static void test_IUriBuilder_HasBeenModified(void) {
9859     HRESULT hr;
9860     IUriBuilder *builder = NULL;
9861 
9862     hr = pCreateIUriBuilder(NULL, 0, 0, &builder);
9863     ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9864     if(SUCCEEDED(hr)) {
9865         static const WCHAR hostW[] = {'g','o','o','g','l','e','.','c','o','m',0};
9866         IUri *uri = NULL;
9867         BOOL received;
9868 
9869         hr = IUriBuilder_HasBeenModified(builder, NULL);
9870         ok(hr == E_POINTER, "Error: IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x.\n",
9871             hr, E_POINTER);
9872 
9873         hr = IUriBuilder_SetHost(builder, hostW);
9874         ok(hr == S_OK, "Error: IUriBuilder_SetHost returned 0x%08x, expected 0x%08x.\n",
9875             hr, S_OK);
9876 
9877         hr = IUriBuilder_HasBeenModified(builder, &received);
9878         ok(hr == S_OK, "Error: IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x.\n",
9879             hr, S_OK);
9880         if(SUCCEEDED(hr))
9881             ok(received == TRUE, "Error: Expected received to be TRUE.\n");
9882 
9883         hr = pCreateUri(http_urlW, 0, 0, &uri);
9884         ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9885         if(SUCCEEDED(hr)) {
9886             LPCWSTR prop;
9887             DWORD len = -1;
9888 
9889             hr = IUriBuilder_SetIUri(builder, uri);
9890             ok(hr == S_OK, "Error: IUriBuilder_SetIUri returned 0x%08x, expected 0x%08x.\n",
9891                 hr, S_OK);
9892 
9893             hr = IUriBuilder_HasBeenModified(builder, &received);
9894             ok(hr == S_OK, "Error: IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x.\n",
9895                 hr, S_OK);
9896             if(SUCCEEDED(hr))
9897                 ok(received == FALSE, "Error: Expected received to be FALSE.\n");
9898 
9899             /* Test what happens with you call SetIUri with the same IUri again. */
9900             hr = IUriBuilder_SetHost(builder, hostW);
9901             ok(hr == S_OK, "Error: IUriBuilder_SetHost returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9902 
9903             hr = IUriBuilder_HasBeenModified(builder, &received);
9904             ok(hr == S_OK, "Error: IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x.\n",
9905                 hr, S_OK);
9906             if(SUCCEEDED(hr))
9907                 ok(received == TRUE, "Error: Expected received to be TRUE.\n");
9908 
9909             hr = IUriBuilder_SetIUri(builder, uri);
9910             ok(hr == S_OK, "Error: IUriBuilder_SetIUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9911 
9912             /* IUriBuilder already had 'uri' as its IUri property and so Windows doesn't
9913              * reset any of the changes that were made to the IUriBuilder.
9914              */
9915             hr = IUriBuilder_HasBeenModified(builder, &received);
9916             ok(hr == S_OK, "Error: IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9917             if(SUCCEEDED(hr))
9918                 ok(received == TRUE, "Error: Expected received to be TRUE.\n");
9919 
9920             hr = IUriBuilder_GetHost(builder, &len, &prop);
9921             ok(hr == S_OK, "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9922             if(SUCCEEDED(hr)) {
9923                 ok(!lstrcmpW(prop, hostW), "Error: Expected %s but got %s instead.\n",
9924                     wine_dbgstr_w(hostW), wine_dbgstr_w(prop));
9925                 ok(len == lstrlenW(hostW), "Error: Expected len to be %d, but was %d instead.\n",
9926                     lstrlenW(hostW), len);
9927             }
9928 
9929             hr = IUriBuilder_SetIUri(builder, NULL);
9930             ok(hr == S_OK, "Error: IUriBuilder_SetIUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9931 
9932             hr = IUriBuilder_SetHost(builder, hostW);
9933             ok(hr == S_OK, "Error: IUriBuilder_SetHost returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9934             hr = IUriBuilder_HasBeenModified(builder, &received);
9935             ok(hr == S_OK, "Error: IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x.\n",
9936                 hr, S_OK);
9937             if(SUCCEEDED(hr))
9938                 ok(received == TRUE, "Error: Expected received to be TRUE.\n");
9939 
9940             hr = IUriBuilder_SetIUri(builder, NULL);
9941             ok(hr == S_OK, "Error: IUriBuilder_SetIUri returned 0x%08x, expected 0x%09x.\n", hr, S_OK);
9942 
9943             hr = IUriBuilder_HasBeenModified(builder, &received);
9944             ok(hr == S_OK, "Error: IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x.\n",
9945                 hr, S_OK);
9946             if(SUCCEEDED(hr))
9947                 ok(received == TRUE, "Error: Expected received to be TRUE.\n");
9948 
9949             hr = IUriBuilder_GetHost(builder, &len, &prop);
9950             ok(hr == S_OK, "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9951             if(SUCCEEDED(hr)) {
9952                 ok(!lstrcmpW(prop, hostW), "Error: Expected %s but got %s instead.\n",
9953                     wine_dbgstr_w(hostW), wine_dbgstr_w(prop));
9954                 ok(len == lstrlenW(hostW), "Error: Expected len to %d, but was %d instead.\n",
9955                     lstrlenW(hostW), len);
9956             }
9957         }
9958         if(uri) IUri_Release(uri);
9959     }
9960     if(builder) IUriBuilder_Release(builder);
9961 }
9962 
9963 /* Test IUriBuilder {Get,Set}IUri functions. */
9964 static void test_IUriBuilder_IUriProperty(void) {
9965     IUriBuilder *builder = NULL;
9966     HRESULT hr;
9967 
9968     hr = pCreateIUriBuilder(NULL, 0, 0, &builder);
9969     ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9970     if(SUCCEEDED(hr)) {
9971         IUri *uri = NULL;
9972 
9973         hr = IUriBuilder_GetIUri(builder, NULL);
9974         ok(hr == E_POINTER, "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x.\n",
9975             hr, E_POINTER);
9976 
9977         hr = pCreateUri(http_urlW, 0, 0, &uri);
9978         if(SUCCEEDED(hr)) {
9979             IUri *test = NULL;
9980             ULONG cur_count, orig_count;
9981 
9982             /* IUriBuilder doesn't clone the IUri, it use the same IUri. */
9983             orig_count = get_refcnt(uri);
9984             hr = IUriBuilder_SetIUri(builder, uri);
9985             cur_count = get_refcnt(uri);
9986             if(SUCCEEDED(hr))
9987                 ok(cur_count == orig_count+1, "Error: Expected uri ref count to be %d, but was %d instead.\n",
9988                     orig_count+1, cur_count);
9989 
9990             hr = IUriBuilder_SetIUri(builder, NULL);
9991             cur_count = get_refcnt(uri);
9992             if(SUCCEEDED(hr))
9993                 ok(cur_count == orig_count, "Error: Expected uri ref count to be %d, but was %d instead.\n",
9994                     orig_count, cur_count);
9995 
9996             /* CreateUri* functions will return back the same IUri if nothing has changed. */
9997             hr = IUriBuilder_SetIUri(builder, uri);
9998             ok(hr == S_OK, "Error: IUriBuilder_SetIUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9999             orig_count = get_refcnt(uri);
10000 
10001             hr = IUriBuilder_CreateUri(builder, 0, 0, 0, &test);
10002             ok(hr == S_OK, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
10003             if(SUCCEEDED(hr)) {
10004                 cur_count = get_refcnt(uri);
10005                 ok(cur_count == orig_count+1, "Error: Expected uri ref count to be %d, but was %d instead.\n",
10006                     orig_count+1, cur_count);
10007                 ok(test == uri, "Error: Expected test to be %p, but was %p instead.\n",
10008                     uri, test);
10009             }
10010             if(test) IUri_Release(test);
10011 
10012             test = NULL;
10013             hr = IUriBuilder_CreateUri(builder, -1, 0, 0, &test);
10014             ok(hr == S_OK, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
10015             if(SUCCEEDED(hr)) {
10016                 cur_count = get_refcnt(uri);
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                 ok(test == uri, "Error: Expected test to be %p, but was %p instead.\n", uri, test);
10020             }
10021             if(test) IUri_Release(test);
10022 
10023             /* Doesn't return the same IUri, if the flag combination is different then the one that created
10024              * the base IUri.
10025              */
10026             test = NULL;
10027             hr = IUriBuilder_CreateUri(builder, Uri_CREATE_ALLOW_RELATIVE, 0, 0, &test);
10028             ok(hr == S_OK, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
10029             if(SUCCEEDED(hr))
10030                 ok(test != uri, "Error: Wasn't expecting 'test' to be 'uri'\n");
10031 
10032             if(test) IUri_Release(test);
10033 
10034             /* Still returns the same IUri, even though the base one wasn't created with CREATE_CANONICALIZE
10035              * explicitly set (because it's a default flag).
10036              */
10037             test = NULL;
10038             hr = IUriBuilder_CreateUri(builder, Uri_CREATE_CANONICALIZE, 0, 0, &test);
10039             ok(hr == S_OK, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
10040             if(SUCCEEDED(hr)) {
10041                 cur_count = get_refcnt(uri);
10042                 ok(cur_count == orig_count+1, "Error: Expected uri ref count to be %d, but was %d instead.\n",
10043                     orig_count+1, cur_count);
10044                 ok(test == uri, "Error: Expected 'test' to be %p, but was %p instead.\n", uri, test);
10045             }
10046             if(test) IUri_Release(test);
10047 
10048             test = NULL;
10049             hr = IUriBuilder_CreateUriSimple(builder, 0, 0, &test);
10050             ok(hr == S_OK, "Error: IUriBuilder_CreateUriSimple returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
10051             if(SUCCEEDED(hr)) {
10052                 cur_count = get_refcnt(uri);
10053                 ok(cur_count == orig_count+1, "Error: Expected uri ref count to be %d, but was %d instead.\n",
10054                     orig_count+1, cur_count);
10055                 ok(test == uri, "Error: Expected test to be %p, but was %p instead.\n", uri, test);
10056             }
10057             if(test) IUri_Release(test);
10058 
10059             test = NULL;
10060             hr = IUriBuilder_CreateUriWithFlags(builder, 0, 0, 0, 0, &test);
10061             ok(hr == S_OK, "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x.\n",
10062                 hr, S_OK);
10063             if(SUCCEEDED(hr)) {
10064                 cur_count = get_refcnt(uri);
10065                 ok(cur_count == orig_count+1, "Error: Expected uri ref count to be %d, but was %d instead.\n",
10066                     orig_count+1, cur_count);
10067                 ok(test == uri, "Error: Expected test to be %p, but was %p instead.\n", uri, test);
10068             }
10069             if(test) IUri_Release(test);
10070 
10071             /* Doesn't return the same IUri, if the flag combination is different then the one that created
10072              * the base IUri.
10073              */
10074             test = NULL;
10075             hr = IUriBuilder_CreateUriWithFlags(builder, Uri_CREATE_ALLOW_RELATIVE, 0, 0, 0, &test);
10076             ok(hr == S_OK, "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
10077             if(SUCCEEDED(hr))
10078                 ok(test != uri, "Error: Wasn't expecting 'test' to be 'uri'\n");
10079 
10080             if(test) IUri_Release(test);
10081 
10082             /* Still returns the same IUri, even though the base one wasn't created with CREATE_CANONICALIZE
10083              * explicitly set (because it's a default flag).
10084              */
10085             test = NULL;
10086             hr = IUriBuilder_CreateUriWithFlags(builder, Uri_CREATE_CANONICALIZE, 0, 0, 0, &test);
10087             ok(hr == S_OK, "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
10088             if(SUCCEEDED(hr)) {
10089                 cur_count = get_refcnt(uri);
10090                 ok(cur_count == orig_count+1, "Error: Expected uri ref count to be %d, but was %d instead.\n",
10091                     orig_count+1, cur_count);
10092                 ok(test == uri, "Error: Expected 'test' to be %p, but was %p instead.\n", uri, test);
10093             }
10094             if(test) IUri_Release(test);
10095         }
10096         if(uri) IUri_Release(uri);
10097     }
10098     if(builder) IUriBuilder_Release(builder);
10099 }
10100 
10101 static void test_IUriBuilder_RemoveProperties(void) {
10102     IUriBuilder *builder = NULL;
10103     HRESULT hr;
10104     DWORD i;
10105 
10106     hr = pCreateIUriBuilder(NULL, 0, 0, &builder);
10107     ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
10108     if(SUCCEEDED(hr)) {
10109         /* Properties that can't be removed. */
10110         const DWORD invalid = Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_RAW_URI|Uri_HAS_HOST_TYPE|
10111                               Uri_HAS_SCHEME|Uri_HAS_ZONE;
10112 
10113         for(i = Uri_PROPERTY_STRING_START; i <= Uri_PROPERTY_DWORD_LAST; ++i) {
10114             hr = IUriBuilder_RemoveProperties(builder, i << 1);
10115             if((i << 1) & invalid) {
10116                 ok(hr == E_INVALIDARG,
10117                     "Error: IUriBuilder_RemoveProperties returned 0x%08x, expected 0x%08x with prop=%d.\n",
10118                     hr, E_INVALIDARG, i);
10119             } else {
10120                 ok(hr == S_OK,
10121                     "Error: IUriBuilder_RemoveProperties returned 0x%08x, expected 0x%08x with prop=%d.\n",
10122                     hr, S_OK, i);
10123             }
10124         }
10125 
10126         /* Also doesn't accept anything that's outside the range of the
10127          * Uri_HAS flags.
10128          */
10129         hr = IUriBuilder_RemoveProperties(builder, (Uri_PROPERTY_DWORD_LAST+1) << 1);
10130         ok(hr == E_INVALIDARG, "Error: IUriBuilder_RemoveProperties returned 0x%08x, expected 0x%08x.\n",
10131             hr, E_INVALIDARG);
10132     }
10133     if(builder) IUriBuilder_Release(builder);
10134 
10135     for(i = 0; i < sizeof(uri_builder_remove_tests)/sizeof(uri_builder_remove_tests[0]); ++i) {
10136         uri_builder_remove_test test = uri_builder_remove_tests[i];
10137         IUri *uri = NULL;
10138         LPWSTR uriW;
10139 
10140         uriW = a2w(test.uri);
10141         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
10142         if(SUCCEEDED(hr)) {
10143             builder = NULL;
10144 
10145             hr = pCreateIUriBuilder(uri, 0, 0, &builder);
10146             todo_wine_if(test.create_builder_todo)
10147                 ok(hr == test.create_builder_expected,
10148                     "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x on test %d.\n",
10149                     hr, test.create_builder_expected, i);
10150 
10151             if(SUCCEEDED(hr)) {
10152                 hr = IUriBuilder_RemoveProperties(builder, test.remove_properties);
10153                 todo_wine_if(test.remove_todo)
10154                     ok(hr == test.remove_expected,
10155                         "Error: IUriBuilder returned 0x%08x, expected 0x%08x on test %d.\n",
10156                         hr, test.remove_expected, i);
10157                 if(SUCCEEDED(hr)) {
10158                     IUri *result = NULL;
10159 
10160                     hr = IUriBuilder_CreateUri(builder, test.expected_flags, 0, 0, &result);
10161                     todo_wine_if(test.expected_todo)
10162                         ok(hr == test.expected_hres,
10163                             "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x on test %d.\n",
10164                             hr, test.expected_hres, i);
10165                     if(SUCCEEDED(hr)) {
10166                         BSTR received = NULL;
10167 
10168                         hr = IUri_GetAbsoluteUri(result, &received);
10169                         ok(hr == S_OK, "Error: Expected S_OK, but got 0x%08x instead.\n", hr);
10170                         ok(!strcmp_aw(test.expected_uri, received),
10171                             "Error: Expected %s but got %s instead on test %d.\n",
10172                             test.expected_uri, wine_dbgstr_w(received), i);
10173                         SysFreeString(received);
10174                     }
10175                     if(result) IUri_Release(result);
10176                 }
10177             }
10178             if(builder) IUriBuilder_Release(builder);
10179         }
10180         if(uri) IUri_Release(uri);
10181         heap_free(uriW);
10182     }
10183 }
10184 
10185 static void test_IUriBuilder_Misc(void) {
10186     HRESULT hr;
10187     IUri *uri;
10188 
10189     hr = pCreateUri(http_urlW, 0, 0, &uri);
10190     if(SUCCEEDED(hr)) {
10191         IUriBuilder *builder;
10192 
10193         hr = pCreateIUriBuilder(uri, 0, 0, &builder);
10194         ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
10195         if(SUCCEEDED(hr)) {
10196             BOOL has = -1;
10197             DWORD port = -1;
10198 
10199             hr = IUriBuilder_GetPort(builder, &has, &port);
10200             ok(hr == S_OK, "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
10201             if(SUCCEEDED(hr)) {
10202                 /* 'has' will be set to FALSE, even though uri had a port. */
10203                 ok(has == FALSE, "Error: Expected 'has' to be FALSE, was %d instead.\n", has);
10204                 /* Still sets 'port' to 80. */
10205                 ok(port == 80, "Error: Expected the port to be 80, but, was %d instead.\n", port);
10206             }
10207         }
10208         if(builder) IUriBuilder_Release(builder);
10209     }
10210     if(uri) IUri_Release(uri);
10211 }
10212 
10213 static void test_IUriBuilderFactory(void) {
10214     HRESULT hr;
10215     IUri *uri;
10216     IUriBuilderFactory *factory;
10217     IUriBuilder *builder;
10218 
10219     hr = pCreateUri(http_urlW, 0, 0, &uri);
10220     ok(SUCCEEDED(hr), "Error: CreateUri returned 0x%08x.\n", hr);
10221     if(SUCCEEDED(hr)) {
10222         factory = NULL;
10223         hr = IUri_QueryInterface(uri, &IID_IUriBuilderFactory, (void**)&factory);
10224         ok(hr == S_OK, "Error: Expected S_OK, but got 0x%08x.\n", hr);
10225         ok(factory != NULL, "Error: Expected 'factory' to not be NULL.\n");
10226 
10227         if(SUCCEEDED(hr)) {
10228             builder = (void*) 0xdeadbeef;
10229             hr = IUriBuilderFactory_CreateIUriBuilder(factory, 10, 0, &builder);
10230             ok(hr == E_INVALIDARG, "Error: CreateInitializedIUriBuilder returned 0x%08x, expected 0x%08x.\n",
10231                 hr, E_INVALIDARG);
10232             ok(!builder, "Error: Expected 'builder' to be NULL, but was %p.\n", builder);
10233 
10234             builder = (void*) 0xdeadbeef;
10235             hr = IUriBuilderFactory_CreateIUriBuilder(factory, 0, 10, &builder);
10236             ok(hr == E_INVALIDARG, "Error: CreateInitializedIUriBuilder returned 0x%08x, expected 0x%08x.\n",
10237                 hr, E_INVALIDARG);
10238             ok(!builder, "Error: Expected 'builder' to be NULL, but was %p.\n", builder);
10239 
10240             hr = IUriBuilderFactory_CreateIUriBuilder(factory, 0, 0, NULL);
10241             ok(hr == E_POINTER, "Error: CreateInitializedIUriBuilder returned 0x%08x, expected 0x%08x.\n",
10242                 hr, E_POINTER);
10243 
10244             builder = NULL;
10245             hr = IUriBuilderFactory_CreateIUriBuilder(factory, 0, 0, &builder);
10246             ok(hr == S_OK, "Error: CreateInitializedIUriBuilder returned 0x%08x, expected 0x%08x.\n",
10247                 hr, S_OK);
10248             if(SUCCEEDED(hr)) {
10249                 IUri *tmp = (void*) 0xdeadbeef;
10250                 LPCWSTR result;
10251                 DWORD result_len;
10252 
10253                 hr = IUriBuilder_GetIUri(builder, &tmp);
10254                 ok(hr == S_OK, "Error: GetIUri returned 0x%08x, expected 0x%08x.\n",
10255                     hr, S_OK);
10256                 ok(!tmp, "Error: Expected 'tmp' to be NULL, but was %p instead.\n", tmp);
10257 
10258                 hr = IUriBuilder_GetHost(builder, &result_len, &result);
10259                 ok(hr == S_FALSE, "Error: GetHost returned 0x%08x, expected 0x%08x.\n",
10260                     hr, S_FALSE);
10261             }
10262             if(builder) IUriBuilder_Release(builder);
10263 
10264             builder = (void*) 0xdeadbeef;
10265             hr = IUriBuilderFactory_CreateInitializedIUriBuilder(factory, 10, 0, &builder);
10266             ok(hr == E_INVALIDARG, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n",
10267                 hr, E_INVALIDARG);
10268             ok(!builder, "Error: Expected 'builder' to be NULL, but was %p.\n", builder);
10269 
10270             builder = (void*) 0xdeadbeef;
10271             hr = IUriBuilderFactory_CreateInitializedIUriBuilder(factory, 0, 10, &builder);
10272             ok(hr == E_INVALIDARG, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n",
10273                 hr, E_INVALIDARG);
10274             ok(!builder, "Error: Expected 'builder' to be NULL, but was %p.\n", builder);
10275 
10276             hr = IUriBuilderFactory_CreateInitializedIUriBuilder(factory, 0, 0, NULL);
10277             ok(hr == E_POINTER, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n",
10278                 hr, E_POINTER);
10279 
10280             builder = NULL;
10281             hr = IUriBuilderFactory_CreateInitializedIUriBuilder(factory, 0, 0, &builder);
10282             ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n",
10283                 hr, S_OK);
10284             if(SUCCEEDED(hr)) {
10285                 IUri *tmp = NULL;
10286 
10287                 hr = IUriBuilder_GetIUri(builder, &tmp);
10288                 ok(hr == S_OK, "Error: GetIUri return 0x%08x, expected 0x%08x.\n",
10289                     hr, S_OK);
10290                 ok(tmp == uri, "Error: Expected tmp to be %p, but was %p.\n", uri, tmp);
10291                 if(uri) IUri_Release(uri);
10292             }
10293             if(builder) IUriBuilder_Release(builder);
10294         }
10295         if(factory) IUriBuilderFactory_Release(factory);
10296     }
10297     if(uri) IUri_Release(uri);
10298 }
10299 
10300 static void test_CoInternetCombineIUri(void) {
10301     HRESULT hr;
10302     IUri *base, *relative, *result;
10303     DWORD i;
10304 
10305     base = NULL;
10306     hr = pCreateUri(http_urlW, 0, 0, &base);
10307     ok(SUCCEEDED(hr), "Error: Expected CreateUri to succeed, got 0x%08x.\n", hr);
10308     if(SUCCEEDED(hr)) {
10309         result = (void*) 0xdeadbeef;
10310         hr = pCoInternetCombineIUri(base, NULL, 0, &result, 0);
10311         ok(hr == E_INVALIDARG, "Error: CoInternetCombineIUri returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
10312         ok(!result, "Error: Expected 'result' to be NULL, was %p.\n", result);
10313     }
10314 
10315     relative = NULL;
10316     hr = pCreateUri(http_urlW, 0, 0, &relative);
10317     ok(SUCCEEDED(hr), "Error: Expected CreateUri to succeed, got 0x%08x.\n", hr);
10318     if(SUCCEEDED(hr)) {
10319         result = (void*) 0xdeadbeef;
10320         hr = pCoInternetCombineIUri(NULL, relative, 0, &result, 0);
10321         ok(hr == E_INVALIDARG, "Error: CoInternetCombineIUri returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
10322         ok(!result, "Error: Expected 'result' to be NULL, was %p.\n", result);
10323     }
10324 
10325     hr = pCoInternetCombineIUri(base, relative, 0, NULL, 0);
10326     ok(hr == E_INVALIDARG, "Error: CoInternetCombineIUri returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
10327 
10328     if(base) IUri_Release(base);
10329     if(relative) IUri_Release(relative);
10330 
10331     for(i = 0; i < sizeof(uri_combine_tests)/sizeof(uri_combine_tests[0]); ++i) {
10332         LPWSTR baseW = a2w(uri_combine_tests[i].base_uri);
10333 
10334         hr = pCreateUri(baseW, uri_combine_tests[i].base_create_flags, 0, &base);
10335         ok(SUCCEEDED(hr), "Error: Expected CreateUri to succeed, got 0x%08x on uri_combine_tests[%d].\n", hr, i);
10336         if(SUCCEEDED(hr)) {
10337             LPWSTR relativeW = a2w(uri_combine_tests[i].relative_uri);
10338 
10339             hr = pCreateUri(relativeW, uri_combine_tests[i].relative_create_flags, 0, &relative);
10340             ok(SUCCEEDED(hr), "Error: Expected CreateUri to succeed, got 0x%08x on uri_combine_tests[%d].\n", hr, i);
10341             if(SUCCEEDED(hr)) {
10342                 result = NULL;
10343 
10344                 hr = pCoInternetCombineIUri(base, relative, uri_combine_tests[i].combine_flags, &result, 0);
10345                 todo_wine_if(uri_combine_tests[i].todo)
10346                     ok(hr == uri_combine_tests[i].expected,
10347                         "Error: CoInternetCombineIUri returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].\n",
10348                         hr, uri_combine_tests[i]. expected, i);
10349                 if(SUCCEEDED(hr)) {
10350                     DWORD j;
10351 
10352                     for(j = 0; j < sizeof(uri_combine_tests[i].str_props)/sizeof(uri_combine_tests[i].str_props[0]); ++j) {
10353                         uri_combine_str_property prop = uri_combine_tests[i].str_props[j];
10354                         BSTR received;
10355 
10356                         hr = IUri_GetPropertyBSTR(result, j, &received, 0);
10357                         todo_wine_if(prop.todo) {
10358                             ok(hr == prop.expected,
10359                                 "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].str_props[%d].\n",
10360                                 hr, prop.expected, i, j);
10361                             ok(!strcmp_aw(prop.value, received) ||
10362                                broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
10363                                 "Error: Expected \"%s\" but got %s instead on uri_combine_tests[%d].str_props[%d].\n",
10364                                 prop.value, wine_dbgstr_w(received), i, j);
10365                         }
10366                         SysFreeString(received);
10367                     }
10368 
10369                     for(j = 0; j < sizeof(uri_combine_tests[i].dword_props)/sizeof(uri_combine_tests[i].dword_props[0]); ++j) {
10370                         uri_dword_property prop = uri_combine_tests[i].dword_props[j];
10371                         DWORD received;
10372 
10373                         hr = IUri_GetPropertyDWORD(result, j+Uri_PROPERTY_DWORD_START, &received, 0);
10374                         todo_wine_if(prop.todo) {
10375                             ok(hr == prop.expected || broken(prop.broken_combine_hres && hr == S_FALSE),
10376                                 "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].dword_props[%d].\n",
10377                                 hr, prop.expected, i, j);
10378                             if(!prop.broken_combine_hres || hr != S_FALSE)
10379                                 ok(prop.value == received, "Error: Expected %d, but got %d instead on uri_combine_tests[%d].dword_props[%d].\n",
10380                                     prop.value, received, i, j);
10381                         }
10382                     }
10383                 }
10384                 if(result) IUri_Release(result);
10385             }
10386             if(relative) IUri_Release(relative);
10387             heap_free(relativeW);
10388         }
10389         if(base) IUri_Release(base);
10390         heap_free(baseW);
10391     }
10392 }
10393 
10394 static HRESULT WINAPI InternetProtocolInfo_QueryInterface(IInternetProtocolInfo *iface,
10395                                                           REFIID riid, void **ppv)
10396 {
10397     ok(0, "unexpected call\n");
10398     return E_NOINTERFACE;
10399 }
10400 
10401 static ULONG WINAPI InternetProtocolInfo_AddRef(IInternetProtocolInfo *iface)
10402 {
10403     return 2;
10404 }
10405 
10406 static ULONG WINAPI InternetProtocolInfo_Release(IInternetProtocolInfo *iface)
10407 {
10408     return 1;
10409 }
10410 
10411 static HRESULT WINAPI InternetProtocolInfo_ParseUrl(IInternetProtocolInfo *iface, LPCWSTR pwzUrl,
10412         PARSEACTION ParseAction, DWORD dwParseFlags, LPWSTR pwzResult, DWORD cchResult,
10413         DWORD *pcchResult, DWORD dwReserved)
10414 {
10415     CHECK_EXPECT(ParseUrl);
10416     ok(!lstrcmpW(pwzUrl, parse_urlW), "Error: Expected %s, but got %s instead.\n",
10417         wine_dbgstr_w(parse_urlW), wine_dbgstr_w(pwzUrl));
10418     ok(ParseAction == parse_action, "Error: Expected %d, but got %d.\n", parse_action, ParseAction);
10419     ok(dwParseFlags == parse_flags, "Error: Expected 0x%08x, but got 0x%08x.\n", parse_flags, dwParseFlags);
10420     ok(cchResult == 200, "Error: Got %d.\n", cchResult);
10421 
10422     memcpy(pwzResult, parse_resultW, sizeof(parse_resultW));
10423     *pcchResult = lstrlenW(parse_resultW);
10424 
10425     return S_OK;
10426 }
10427 
10428 static HRESULT WINAPI InternetProtocolInfo_CombineUrl(IInternetProtocolInfo *iface,
10429         LPCWSTR pwzBaseUrl, LPCWSTR pwzRelativeUrl, DWORD dwCombineFlags,
10430         LPWSTR pwzResult, DWORD cchResult, DWORD *pcchResult, DWORD dwReserved)
10431 {
10432     CHECK_EXPECT(CombineUrl);
10433     ok(!lstrcmpW(pwzBaseUrl, combine_baseW), "Error: Expected %s, but got %s instead.\n",
10434         wine_dbgstr_w(combine_baseW), wine_dbgstr_w(pwzBaseUrl));
10435     ok(!lstrcmpW(pwzRelativeUrl, combine_relativeW), "Error: Expected %s, but got %s instead.\n",
10436         wine_dbgstr_w(combine_relativeW), wine_dbgstr_w(pwzRelativeUrl));
10437     ok(dwCombineFlags == (URL_DONT_SIMPLIFY|URL_FILE_USE_PATHURL|URL_DONT_UNESCAPE_EXTRA_INFO),
10438         "Error: Expected 0, but got 0x%08x.\n", dwCombineFlags);
10439     ok(cchResult == INTERNET_MAX_URL_LENGTH+1, "Error: Got %d.\n", cchResult);
10440 
10441     memcpy(pwzResult, combine_resultW, sizeof(combine_resultW));
10442     *pcchResult = lstrlenW(combine_resultW);
10443 
10444     return S_OK;
10445 }
10446 
10447 static HRESULT WINAPI InternetProtocolInfo_CompareUrl(IInternetProtocolInfo *iface,
10448         LPCWSTR pwzUrl1, LPCWSTR pwzUrl2, DWORD dwCompareFlags)
10449 {
10450     ok(0, "unexpected call\n");
10451     return E_NOTIMPL;
10452 }
10453 
10454 static HRESULT WINAPI InternetProtocolInfo_QueryInfo(IInternetProtocolInfo *iface,
10455         LPCWSTR pwzUrl, QUERYOPTION OueryOption, DWORD dwQueryFlags, LPVOID pBuffer,
10456         DWORD cbBuffer, DWORD *pcbBuf, DWORD dwReserved)
10457 {
10458     ok(0, "unexpected call\n");
10459     return E_NOTIMPL;
10460 }
10461 
10462 static const IInternetProtocolInfoVtbl InternetProtocolInfoVtbl = {
10463     InternetProtocolInfo_QueryInterface,
10464     InternetProtocolInfo_AddRef,
10465     InternetProtocolInfo_Release,
10466     InternetProtocolInfo_ParseUrl,
10467     InternetProtocolInfo_CombineUrl,
10468     InternetProtocolInfo_CompareUrl,
10469     InternetProtocolInfo_QueryInfo
10470 };
10471 
10472 static IInternetProtocolInfo protocol_info = { &InternetProtocolInfoVtbl };
10473 
10474 static HRESULT WINAPI ClassFactory_QueryInterface(IClassFactory *iface, REFIID riid, void **ppv)
10475 {
10476     if(IsEqualGUID(&IID_IInternetProtocolInfo, riid)) {
10477         *ppv = &protocol_info;
10478         return S_OK;
10479     }
10480 
10481     ok(0, "unexpected call\n");
10482     return E_NOINTERFACE;
10483 }
10484 
10485 static ULONG WINAPI ClassFactory_AddRef(IClassFactory *iface)
10486 {
10487     return 2;
10488 }
10489 
10490 static ULONG WINAPI ClassFactory_Release(IClassFactory *iface)
10491 {
10492     return 1;
10493 }
10494 
10495 static HRESULT WINAPI ClassFactory_CreateInstance(IClassFactory *iface, IUnknown *pOuter,
10496                                         REFIID riid, void **ppv)
10497 {
10498     ok(0, "unexpected call\n");
10499     return E_NOTIMPL;
10500 }
10501 
10502 static HRESULT WINAPI ClassFactory_LockServer(IClassFactory *iface, BOOL dolock)
10503 {
10504     ok(0, "unexpected call\n");
10505     return S_OK;
10506 }
10507 
10508 static const IClassFactoryVtbl ClassFactoryVtbl = {
10509     ClassFactory_QueryInterface,
10510     ClassFactory_AddRef,
10511     ClassFactory_Release,
10512     ClassFactory_CreateInstance,
10513     ClassFactory_LockServer
10514 };
10515 
10516 static IClassFactory protocol_cf = { &ClassFactoryVtbl };
10517 
10518 static void register_protocols(void)
10519 {
10520     IInternetSession *session;
10521     HRESULT hres;
10522 
10523     hres = pCoInternetGetSession(0, &session, 0);
10524     ok(hres == S_OK, "CoInternetGetSession failed: %08x\n", hres);
10525     if(FAILED(hres))
10526         return;
10527 
10528     hres = IInternetSession_RegisterNameSpace(session, &protocol_cf, &IID_NULL,
10529             winetestW, 0, NULL, 0);
10530     ok(hres == S_OK, "RegisterNameSpace failed: %08x\n", hres);
10531 
10532     IInternetSession_Release(session);
10533 }
10534 
10535 static void unregister_protocols(void) {
10536     IInternetSession *session;
10537     HRESULT hr;
10538 
10539     hr = pCoInternetGetSession(0, &session, 0);
10540     ok(hr == S_OK, "CoInternetGetSession failed: 0x%08x\n", hr);
10541     if(FAILED(hr))
10542         return;
10543 
10544     hr = IInternetSession_UnregisterNameSpace(session, &protocol_cf, winetestW);
10545     ok(hr == S_OK, "UnregisterNameSpace failed: 0x%08x\n", hr);
10546 
10547     IInternetSession_Release(session);
10548 }
10549 
10550 static void test_CoInternetCombineIUri_Pluggable(void) {
10551     HRESULT hr;
10552     IUri *base = NULL;
10553 
10554     hr = pCreateUri(combine_baseW, 0, 0, &base);
10555     ok(SUCCEEDED(hr), "Error: CreateUri returned 0x%08x.\n", hr);
10556     if(SUCCEEDED(hr)) {
10557         IUri *relative = NULL;
10558 
10559         hr = pCreateUri(combine_relativeW, Uri_CREATE_ALLOW_RELATIVE, 0, &relative);
10560         ok(SUCCEEDED(hr), "Error: CreateUri returned 0x%08x.\n", hr);
10561         if(SUCCEEDED(hr)) {
10562             IUri *result = NULL;
10563 
10564             SET_EXPECT(CombineUrl);
10565 
10566             hr = pCoInternetCombineIUri(base, relative, URL_DONT_SIMPLIFY|URL_FILE_USE_PATHURL|URL_DONT_UNESCAPE_EXTRA_INFO,
10567                                         &result, 0);
10568             ok(hr == S_OK, "Error: CoInternetCombineIUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
10569 
10570             CHECK_CALLED(CombineUrl);
10571 
10572             if(SUCCEEDED(hr)) {
10573                 BSTR received = NULL;
10574                 hr = IUri_GetAbsoluteUri(result, &received);
10575                 ok(hr == S_OK, "Error: Expected S_OK, but got 0x%08x instead.\n", hr);
10576                 if(SUCCEEDED(hr)) {
10577                     ok(!lstrcmpW(combine_resultW, received), "Error: Expected %s, but got %s.\n",
10578                         wine_dbgstr_w(combine_resultW), wine_dbgstr_w(received));
10579                 }
10580                 SysFreeString(received);
10581             }
10582             if(result) IUri_Release(result);
10583         }
10584         if(relative) IUri_Release(relative);
10585     }
10586     if(base) IUri_Release(base);
10587 }
10588 
10589 static void test_CoInternetCombineUrlEx(void) {
10590     HRESULT hr;
10591     IUri *base, *result;
10592     DWORD i;
10593 
10594     base = NULL;
10595     hr = pCreateUri(http_urlW, 0, 0, &base);
10596     ok(SUCCEEDED(hr), "Error: CreateUri returned 0x%08x.\n", hr);
10597     if(SUCCEEDED(hr)) {
10598         result = (void*) 0xdeadbeef;
10599         hr = pCoInternetCombineUrlEx(base, NULL, 0, &result, 0);
10600         ok(hr == E_UNEXPECTED, "Error: CoInternetCombineUrlEx returned 0x%08x, expected 0x%08x.\n",
10601             hr, E_UNEXPECTED);
10602         ok(!result, "Error: Expected 'result' to be NULL was %p instead.\n", result);
10603     }
10604 
10605     result = (void*) 0xdeadbeef;
10606     hr = pCoInternetCombineUrlEx(NULL, http_urlW, 0, &result, 0);
10607     ok(hr == E_INVALIDARG, "Error: CoInternetCombineUrlEx returned 0x%08x, expected 0x%08x.\n",
10608         hr, E_INVALIDARG);
10609     ok(!result, "Error: Expected 'result' to be NULL, but was %p instead.\n", result);
10610 
10611     result = (void*) 0xdeadbeef;
10612     hr = pCoInternetCombineUrlEx(NULL, NULL, 0, &result, 0);
10613     ok(hr == E_UNEXPECTED, "Error: CoInternetCombineUrlEx returned 0x%08x, expected 0x%08x.\n",
10614         hr, E_UNEXPECTED);
10615     ok(!result, "Error: Expected 'result' to be NULL, but was %p instead.\n", result);
10616 
10617     hr = pCoInternetCombineUrlEx(base, http_urlW, 0, NULL, 0);
10618     ok(hr == E_POINTER, "Error: CoInternetCombineUrlEx returned 0x%08x, expected 0x%08x.\n",
10619         hr, E_POINTER);
10620     if(base) IUri_Release(base);
10621 
10622     for(i = 0; i < sizeof(uri_combine_tests)/sizeof(uri_combine_tests[0]); ++i) {
10623         LPWSTR baseW = a2w(uri_combine_tests[i].base_uri);
10624 
10625         hr = pCreateUri(baseW, uri_combine_tests[i].base_create_flags, 0, &base);
10626         ok(SUCCEEDED(hr), "Error: CreateUri returned 0x%08x on uri_combine_tests[%d].\n", hr, i);
10627         if(SUCCEEDED(hr)) {
10628             LPWSTR relativeW = a2w(uri_combine_tests[i].relative_uri);
10629 
10630             hr = pCoInternetCombineUrlEx(base, relativeW, uri_combine_tests[i].combine_flags,
10631                                          &result, 0);
10632             todo_wine_if(uri_combine_tests[i].todo)
10633                 ok(hr == uri_combine_tests[i].expected,
10634                     "Error: CoInternetCombineUrlEx returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].\n",
10635                     hr, uri_combine_tests[i]. expected, i);
10636             if(SUCCEEDED(hr)) {
10637                 DWORD j;
10638 
10639                 for(j = 0; j < sizeof(uri_combine_tests[i].str_props)/sizeof(uri_combine_tests[i].str_props[0]); ++j) {
10640                     uri_combine_str_property prop = uri_combine_tests[i].str_props[j];
10641                     BSTR received;
10642                     LPCSTR value = (prop.value_ex) ? prop.value_ex : prop.value;
10643 
10644                     hr = IUri_GetPropertyBSTR(result, j, &received, 0);
10645                     todo_wine_if(prop.todo) {
10646                         ok(hr == prop.expected,
10647                             "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].str_props[%d].\n",
10648                             hr, prop.expected, i, j);
10649                         ok(!strcmp_aw(value, received) ||
10650                            broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
10651                             "Error: Expected \"%s\" but got %s instead on uri_combine_tests[%d].str_props[%d].\n",
10652                             value, wine_dbgstr_w(received), i, j);
10653                     }
10654                     SysFreeString(received);
10655                 }
10656 
10657                 for(j = 0; j < sizeof(uri_combine_tests[i].dword_props)/sizeof(uri_combine_tests[i].dword_props[0]); ++j) {
10658                     uri_dword_property prop = uri_combine_tests[i].dword_props[j];
10659                     DWORD received;
10660 
10661                     hr = IUri_GetPropertyDWORD(result, j+Uri_PROPERTY_DWORD_START, &received, 0);
10662                     todo_wine_if(prop.todo) {
10663                         ok(hr == prop.expected || broken(prop.broken_combine_hres && hr == S_FALSE),
10664                             "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].dword_props[%d].\n",
10665                             hr, prop.expected, i, j);
10666                         if(!prop.broken_combine_hres || hr != S_FALSE)
10667                             ok(prop.value == received, "Error: Expected %d, but got %d instead on uri_combine_tests[%d].dword_props[%d].\n",
10668                                 prop.value, received, i, j);
10669                     }
10670                 }
10671             }
10672             if(result) IUri_Release(result);
10673             heap_free(relativeW);
10674         }
10675         if(base) IUri_Release(base);
10676         heap_free(baseW);
10677     }
10678 }
10679 
10680 static void test_CoInternetCombineUrlEx_Pluggable(void) {
10681     HRESULT hr;
10682     IUri *base = NULL;
10683 
10684     hr = pCreateUri(combine_baseW, 0, 0, &base);
10685     ok(SUCCEEDED(hr), "Error: CreateUri returned 0x%08x.\n", hr);
10686     if(SUCCEEDED(hr)) {
10687         IUri *result = NULL;
10688 
10689         SET_EXPECT(CombineUrl);
10690 
10691         hr = pCoInternetCombineUrlEx(base, combine_relativeW, URL_DONT_SIMPLIFY|URL_FILE_USE_PATHURL|URL_DONT_UNESCAPE_EXTRA_INFO,
10692                                      &result, 0);
10693         ok(hr == S_OK, "Error: CoInternetCombineUrlEx returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
10694 
10695         CHECK_CALLED(CombineUrl);
10696 
10697         if(SUCCEEDED(hr)) {
10698             BSTR received = NULL;
10699             hr = IUri_GetAbsoluteUri(result, &received);
10700             ok(hr == S_OK, "Error: Expected S_OK, but got 0x%08x instead.\n", hr);
10701             if(SUCCEEDED(hr)) {
10702                 ok(!lstrcmpW(combine_resultW, received), "Error: Expected %s, but got %s.\n",
10703                     wine_dbgstr_w(combine_resultW), wine_dbgstr_w(received));
10704             }
10705             SysFreeString(received);
10706         }
10707         if(result) IUri_Release(result);
10708     }
10709     if(base) IUri_Release(base);
10710 }
10711 
10712 static void test_CoInternetParseIUri_InvalidArgs(void) {
10713     HRESULT hr;
10714     IUri *uri = NULL;
10715     WCHAR tmp[3];
10716     WCHAR *longurl, *copy;
10717     DWORD result = -1;
10718     DWORD i, len;
10719 
10720     hr = pCoInternetParseIUri(NULL, PARSE_CANONICALIZE, 0, tmp, 3, &result, 0);
10721     ok(hr == E_INVALIDARG, "Error: CoInternetParseIUri returned 0x%08x, expected 0x%08x.\n",
10722         hr, E_INVALIDARG);
10723     ok(!result, "Error: Expected 'result' to be 0, but was %d.\n", result);
10724 
10725     hr = pCreateUri(http_urlW, 0, 0, &uri);
10726     ok(SUCCEEDED(hr), "Error: CreateUri returned 0x%08x.\n", hr);
10727     if(SUCCEEDED(hr)) {
10728         DWORD expected_len;
10729 
10730         result = -1;
10731         hr = pCoInternetParseIUri(uri, PARSE_CANONICALIZE, 0, NULL, 0, &result, 0);
10732         ok(hr == E_INVALIDARG, "Error: CoInternetParseIUri returned 0x%08x, expected 0x%08x.\n",
10733             hr, E_INVALIDARG);
10734         ok(!result, "Error: Expected 'result' to be 0, but was %d.\n", result);
10735 
10736         hr = pCoInternetParseIUri(uri, PARSE_CANONICALIZE, 0, tmp, 3, NULL, 0);
10737         ok(hr == E_POINTER, "Error: CoInternetParseIUri returned 0x%08x, expected 0x%08x.\n",
10738             hr, E_POINTER);
10739 
10740         result = -1;
10741         hr = pCoInternetParseIUri(uri, PARSE_SECURITY_URL, 0, tmp, 3, &result, 0);
10742         ok(hr == E_FAIL, "Error: CoInternetParseIUri returned 0x%08x expected 0x%08x.\n",
10743             hr, E_FAIL);
10744         ok(!result, "Error: Expected 'result' to be 0, but was %d.\n", result);
10745 
10746         result = -1;
10747         hr = pCoInternetParseIUri(uri, PARSE_MIME, 0, tmp, 3, &result, 0);
10748         ok(hr == E_FAIL, "Error: CoInternetParseIUri returned 0x%08x, expected 0x%08x.\n",
10749             hr, E_FAIL);
10750         ok(!result, "Error: Expected 'result' to be 0, but was %d.\n", result);
10751 
10752         result = -1;
10753         hr = pCoInternetParseIUri(uri, PARSE_SERVER, 0, tmp, 3, &result, 0);
10754         ok(hr == E_FAIL, "Error: CoInternetParseIUri returned 0x%08x, expected 0x%08x.\n",
10755             hr, E_FAIL);
10756         ok(!result, "Error: Expected 'result' to be 0, but was %d.\n", result);
10757 
10758         result = -1;
10759         hr = pCoInternetParseIUri(uri, PARSE_SECURITY_DOMAIN, 0, tmp, 3, &result, 0);
10760         ok(hr == E_FAIL, "Error: CoInternetParseIUri returned 0x%08x, expected 0x%08x.\n",
10761             hr, E_FAIL);
10762         ok(!result, "Error: Expected 'result' to be 0, but was %d.\n", result);
10763 
10764         expected_len = lstrlenW(http_urlW);
10765         result = -1;
10766         hr = pCoInternetParseIUri(uri, PARSE_CANONICALIZE, 0, tmp, 3, &result, 0);
10767         ok(hr == STRSAFE_E_INSUFFICIENT_BUFFER,
10768             "Error: CoInternetParseIUri returned 0x%08x, expected 0x%08x.\n",
10769             hr, STRSAFE_E_INSUFFICIENT_BUFFER);
10770         ok(result == expected_len, "Error: Expected 'result' to be %d, but was %d instead.\n",
10771             expected_len, result);
10772     }
10773     if(uri) IUri_Release(uri);
10774 
10775     /* a long url that causes a crash on Wine */
10776     len = INTERNET_MAX_URL_LENGTH*2;
10777     longurl = heap_alloc((len+1)*sizeof(WCHAR));
10778     memcpy(longurl, http_urlW, sizeof(http_urlW));
10779     for(i = sizeof(http_urlW)/sizeof(WCHAR)-1; i < len; i++)
10780         longurl[i] = 'x';
10781     longurl[len] = 0;
10782 
10783     copy = heap_alloc((len+1)*sizeof(WCHAR));
10784     memcpy(copy, longurl, (len+1)*sizeof(WCHAR));
10785 
10786     hr = pCreateUri(longurl, 0, 0, &uri);
10787     ok(SUCCEEDED(hr), "Error: CreateUri returned 0x%08x.\n", hr);
10788     if(SUCCEEDED(hr)) {
10789         result = -1;
10790         memset(longurl, 0xcc, len*sizeof(WCHAR));
10791         hr = pCoInternetParseIUri(uri, PARSE_CANONICALIZE, 0, longurl, len+1, &result, 0);
10792         ok(SUCCEEDED(hr), "Error: CoInternetParseIUri returned 0x%08x.\n", hr);
10793         ok(!lstrcmpW(longurl, copy), "Error: expected long url '%s' but was '%s'.\n",
10794             wine_dbgstr_w(copy), wine_dbgstr_w(longurl));
10795         ok(result == len, "Error: Expected 'result' to be %d, but was %d instead.\n",
10796             len, result);
10797     }
10798     heap_free(longurl);
10799     heap_free(copy);
10800     if(uri) IUri_Release(uri);
10801 }
10802 
10803 static void test_CoInternetParseIUri(void) {
10804     DWORD i;
10805 
10806     for(i = 0; i < sizeof(uri_parse_tests)/sizeof(uri_parse_tests[0]); ++i) {
10807         HRESULT hr;
10808         IUri *uri;
10809         LPWSTR uriW;
10810         uri_parse_test test = uri_parse_tests[i];
10811 
10812         uriW = a2w(test.uri);
10813         hr = pCreateUri(uriW, test.uri_flags, 0, &uri);
10814         ok(SUCCEEDED(hr), "Error: CreateUri returned 0x%08x on uri_parse_tests[%d].\n", hr, i);
10815         if(SUCCEEDED(hr)) {
10816             WCHAR result[INTERNET_MAX_URL_LENGTH+1];
10817             DWORD result_len = -1;
10818 
10819             hr = pCoInternetParseIUri(uri, test.action, test.flags, result, INTERNET_MAX_URL_LENGTH+1, &result_len, 0);
10820             todo_wine_if(test.todo)
10821                 ok(hr == test.expected,
10822                     "Error: CoInternetParseIUri returned 0x%08x, expected 0x%08x on uri_parse_tests[%d].\n",
10823                     hr, test.expected, i);
10824             if(SUCCEEDED(hr)) {
10825                 DWORD len = lstrlenA(test.property);
10826                 ok(!strcmp_aw(test.property, result) || (test.property2 && !strcmp_aw(test.property2, result)),
10827                     "Error: Expected %s but got %s instead on uri_parse_tests[%d] - %s.\n",
10828                     test.property, wine_dbgstr_w(result), i, wine_dbgstr_w(uriW));
10829                 ok(len == result_len || (test.property2 && lstrlenA(test.property2) == result_len),
10830                     "Error: Expected %d, but got %d instead on uri_parse_tests[%d] - %s.\n",
10831                     len, result_len, i, wine_dbgstr_w(uriW));
10832             } else {
10833                 ok(!result_len,
10834                     "Error: Expected 'result_len' to be 0, but was %d on uri_parse_tests[%d].\n",
10835                     result_len, i);
10836             }
10837         }
10838         if(uri) IUri_Release(uri);
10839         heap_free(uriW);
10840     }
10841 }
10842 
10843 static void test_CoInternetParseIUri_Pluggable(void) {
10844     HRESULT hr;
10845     IUri *uri = NULL;
10846 
10847     hr = pCreateUri(parse_urlW, 0, 0, &uri);
10848     ok(SUCCEEDED(hr), "Error: Expected CreateUri to succeed, but got 0x%08x.\n", hr);
10849     if(SUCCEEDED(hr)) {
10850         WCHAR result[200];
10851         DWORD result_len;
10852 
10853         SET_EXPECT(ParseUrl);
10854 
10855         parse_action = PARSE_CANONICALIZE;
10856         parse_flags = URL_UNESCAPE|URL_ESCAPE_UNSAFE;
10857 
10858         hr = pCoInternetParseIUri(uri, parse_action, parse_flags, result, 200, &result_len, 0);
10859         ok(hr == S_OK, "Error: CoInternetParseIUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
10860 
10861         CHECK_CALLED(ParseUrl);
10862 
10863         if(SUCCEEDED(hr)) {
10864             ok(result_len == lstrlenW(parse_resultW), "Error: Expected %d, but got %d.\n",
10865                 lstrlenW(parse_resultW), result_len);
10866             ok(!lstrcmpW(result, parse_resultW), "Error: Expected %s, but got %s.\n",
10867                 wine_dbgstr_w(parse_resultW), wine_dbgstr_w(result));
10868         }
10869     }
10870     if(uri) IUri_Release(uri);
10871 }
10872 
10873 typedef struct {
10874     const char *url;
10875     DWORD uri_flags;
10876     const char *base_url;
10877     DWORD base_uri_flags;
10878     const char *legacy_url;
10879     const char *uniform_url;
10880     const char *no_canon_url;
10881     const char *uri_url;
10882 } create_urlmon_test_t;
10883 
10884 static const create_urlmon_test_t create_urlmon_tests[] = {
10885     {
10886         "http://www.winehq.org",Uri_CREATE_NO_CANONICALIZE,
10887         NULL,0,
10888         "http://www.winehq.org/",
10889         "http://www.winehq.org/",
10890         "http://www.winehq.org",
10891         "http://www.winehq.org"
10892     },
10893     {
10894         "file://c:\\dir\\file.txt",Uri_CREATE_NO_CANONICALIZE,
10895         NULL,0,
10896         "file://c:\\dir\\file.txt",
10897         "file:///c:/dir/file.txt",
10898         "file:///c:/dir/file.txt",
10899         "file:///c:/dir/file.txt"
10900     },
10901     {
10902         "file://c:\\dir\\file.txt",Uri_CREATE_FILE_USE_DOS_PATH,
10903         NULL,0,
10904         "file://c:\\dir\\file.txt",
10905         "file:///c:/dir/file.txt",
10906         "file:///c:/dir/file.txt",
10907         "file://c:\\dir\\file.txt"
10908     },
10909     {
10910         "dat%61",Uri_CREATE_ALLOW_RELATIVE,
10911         "http://www.winehq.org",0,
10912         "http://www.winehq.org/data",
10913         "http://www.winehq.org/data",
10914         "http://www.winehq.org:80/data",
10915     },
10916     {
10917         "file.txt",Uri_CREATE_ALLOW_RELATIVE,
10918         "file://c:\\dir\\x.txt",Uri_CREATE_NO_CANONICALIZE,
10919         "file://c:\\dir\\file.txt",
10920         "file:///c:/dir/file.txt",
10921         "file:///c:/dir/file.txt",
10922     },
10923     {
10924         "",Uri_CREATE_ALLOW_RELATIVE,
10925         NULL,0,
10926         "",
10927         "",
10928         "",
10929         ""
10930     },
10931     {
10932         "test",Uri_CREATE_ALLOW_RELATIVE,
10933         NULL,0,
10934         "test",
10935         "test",
10936         "test",
10937         "test"
10938     },
10939     {
10940         "c:\\dir\\file.txt",Uri_CREATE_ALLOW_IMPLICIT_FILE_SCHEME,
10941         NULL,0,
10942         "file://c:\\dir\\file.txt",
10943         "file:///c:/dir/file.txt",
10944         "file:///c:/dir/file.txt",
10945         "file:///c:/dir/file.txt",
10946     },
10947     {
10948         "c:\\dir\\file.txt#frag|part",Uri_CREATE_ALLOW_IMPLICIT_FILE_SCHEME,
10949         NULL,0,
10950         "file://c:\\dir\\file.txt#frag|part",
10951         "file:///c:/dir/file.txt#frag%7Cpart",
10952         "file:///c:/dir/file.txt#frag%7Cpart",
10953         "file:///c:/dir/file.txt#frag%7Cpart",
10954     }
10955 };
10956 
10957 #define test_urlmon_display_name(a,b) _test_urlmon_display_name(__LINE__,a,b)
10958 static void _test_urlmon_display_name(unsigned line, IMoniker *mon, const char *exurl)
10959 {
10960     WCHAR *display_name;
10961     HRESULT hres;
10962 
10963     hres = IMoniker_GetDisplayName(mon, NULL, NULL, &display_name);
10964     ok_(__FILE__,line)(hres == S_OK, "GetDisplayName failed: %08x\n", hres);
10965     ok_(__FILE__,line)(!strcmp_aw(exurl, display_name), "unexpected display name: %s, expected %s\n",
10966             wine_dbgstr_w(display_name), exurl);
10967 
10968     CoTaskMemFree(display_name);
10969 }
10970 
10971 #define test_display_uri(a,b) _test_display_uri(__LINE__,a,b)
10972 static void _test_display_uri(unsigned line, IMoniker *mon, const char *exurl)
10973 {
10974     IUriContainer *uri_container;
10975     IUri *uri;
10976     BSTR display_uri;
10977     HRESULT hres;
10978 
10979     hres = IMoniker_QueryInterface(mon, &IID_IUriContainer, (void**)&uri_container);
10980     ok(hres == S_OK, "Could not get IUriContainer iface: %08x\n", hres);
10981 
10982     uri = NULL;
10983     hres = IUriContainer_GetIUri(uri_container, &uri);
10984     IUriContainer_Release(uri_container);
10985     ok(hres == S_OK, "GetIUri failed: %08x\n", hres);
10986     ok(uri != NULL, "uri == NULL\n");
10987 
10988     hres = IUri_GetDisplayUri(uri, &display_uri);
10989     IUri_Release(uri);
10990     ok(hres == S_OK, "GetDisplayUri failed: %08x\n", hres);
10991     ok_(__FILE__,line)(!strcmp_aw(exurl, display_uri), "unexpected display uri: %s, expected %s\n",
10992             wine_dbgstr_w(display_uri), exurl);
10993     SysFreeString(display_uri);
10994 }
10995 
10996 static void test_CreateURLMoniker(void)
10997 {
10998     const create_urlmon_test_t *test;
10999     IMoniker *mon, *base_mon;
11000     WCHAR *url, *base_url;
11001     IUri *uri, *base_uri;
11002     HRESULT hres;
11003 
11004     for(test = create_urlmon_tests; test < create_urlmon_tests + sizeof(create_urlmon_tests)/sizeof(*create_urlmon_tests); test++) {
11005         url = a2w(test->url);
11006         base_url = a2w(test->base_url);
11007 
11008         if(base_url) {
11009             hres = pCreateUri(base_url, test->base_uri_flags, 0, &base_uri);
11010             ok(hres == S_OK, "CreateUri failed: %08x\n", hres);
11011 
11012             hres = pCreateURLMonikerEx2(NULL, base_uri, &base_mon, URL_MK_NO_CANONICALIZE);
11013             ok(hres == S_OK, "CreateURLMonikerEx2 failed: %08x\n", hres);
11014         }else {
11015             base_uri = NULL;
11016             base_mon = NULL;
11017         }
11018 
11019         hres = CreateURLMoniker(base_mon, url, &mon);
11020         ok(hres == S_OK, "CreateURLMoniker failed: %08x\n", hres);
11021         test_urlmon_display_name(mon, test->legacy_url);
11022         test_display_uri(mon, test->legacy_url);
11023         IMoniker_Release(mon);
11024 
11025         hres = pCreateURLMonikerEx(base_mon, url, &mon, URL_MK_LEGACY);
11026         ok(hres == S_OK, "CreateURLMoniker failed: %08x\n", hres);
11027         test_urlmon_display_name(mon, test->legacy_url);
11028         test_display_uri(mon, test->legacy_url);
11029         IMoniker_Release(mon);
11030 
11031         hres = pCreateURLMonikerEx(base_mon, url, &mon, URL_MK_UNIFORM);
11032         ok(hres == S_OK, "CreateURLMoniker failed: %08x\n", hres);
11033         test_urlmon_display_name(mon, test->uniform_url);
11034         test_display_uri(mon, test->uniform_url);
11035         IMoniker_Release(mon);
11036 
11037         hres = pCreateURLMonikerEx(base_mon, url, &mon, URL_MK_NO_CANONICALIZE);
11038         ok(hres == S_OK, "CreateURLMoniker failed: %08x\n", hres);
11039         test_urlmon_display_name(mon, test->no_canon_url);
11040         test_display_uri(mon, test->no_canon_url);
11041         IMoniker_Release(mon);
11042 
11043         hres = pCreateUri(url, test->uri_flags, 0, &uri);
11044         ok(hres == S_OK, "CreateUri failed: %08x\n", hres);
11045 
11046         hres = pCreateURLMonikerEx2(base_mon, uri, &mon, URL_MK_LEGACY);
11047         ok(hres == S_OK, "CreateURLMonikerEx2 failed: %08x\n", hres);
11048         test_urlmon_display_name(mon, base_url ? test->legacy_url : test->uri_url);
11049         test_display_uri(mon, base_url ? test->legacy_url : test->uri_url);
11050         IMoniker_Release(mon);
11051 
11052         hres = pCreateURLMonikerEx2(base_mon, uri, &mon, URL_MK_UNIFORM);
11053         ok(hres == S_OK, "CreateURLMonikerEx2 failed: %08x\n", hres);
11054         test_urlmon_display_name(mon, base_url ? test->uniform_url : test->uri_url);
11055         test_display_uri(mon, base_url ? test->uniform_url : test->uri_url);
11056         IMoniker_Release(mon);
11057 
11058         hres = pCreateURLMonikerEx2(base_mon, uri, &mon, URL_MK_NO_CANONICALIZE);
11059         ok(hres == S_OK, "CreateURLMonikerEx2 failed: %08x\n", hres);
11060         test_urlmon_display_name(mon, base_url ? test->no_canon_url : test->uri_url);
11061         test_display_uri(mon, base_url ? test->no_canon_url : test->uri_url);
11062         IMoniker_Release(mon);
11063 
11064         IUri_Release(uri);
11065         heap_free(url);
11066         heap_free(base_url);
11067         if(base_uri)
11068             IUri_Release(base_uri);
11069         if(base_mon)
11070             IMoniker_Release(base_mon);
11071     }
11072 }
11073 
11074 static int add_default_flags(DWORD flags) {
11075     if(!(flags & Uri_CREATE_NO_CANONICALIZE))
11076         flags |= Uri_CREATE_CANONICALIZE;
11077     if(!(flags & Uri_CREATE_NO_DECODE_EXTRA_INFO))
11078         flags |= Uri_CREATE_DECODE_EXTRA_INFO;
11079     if(!(flags & Uri_CREATE_NO_CRACK_UNKNOWN_SCHEMES))
11080         flags |= Uri_CREATE_CRACK_UNKNOWN_SCHEMES;
11081     if(!(flags & Uri_CREATE_NO_PRE_PROCESS_HTML_URI))
11082         flags |= Uri_CREATE_PRE_PROCESS_HTML_URI;
11083     if(!(flags & Uri_CREATE_IE_SETTINGS))
11084         flags |= Uri_CREATE_NO_IE_SETTINGS;
11085 
11086     return flags;
11087 }
11088 
11089 static void test_IPersistStream(void)
11090 {
11091     int i, props_order[Uri_PROPERTY_DWORD_LAST+1] = { 0 };
11092 
11093     props_order[Uri_PROPERTY_RAW_URI] = 1;
11094     props_order[Uri_PROPERTY_FRAGMENT] = 2;
11095     props_order[Uri_PROPERTY_HOST] = 3;
11096     props_order[Uri_PROPERTY_PASSWORD] = 4;
11097     props_order[Uri_PROPERTY_PATH] = 5;
11098     props_order[Uri_PROPERTY_PORT] = 6;
11099     props_order[Uri_PROPERTY_QUERY] = 7;
11100     props_order[Uri_PROPERTY_SCHEME_NAME] = 8;
11101     props_order[Uri_PROPERTY_USER_NAME] = 9;
11102 
11103     for(i=0; i<sizeof(uri_tests)/sizeof(*uri_tests); i++) {
11104         const uri_properties *test = uri_tests+i;
11105         LPWSTR uriW;
11106         IUri *uri;
11107         IPersistStream *persist_stream;
11108         IStream *stream;
11109         IMarshal *marshal;
11110         DWORD props, props_no, dw_data[6];
11111         WCHAR str_data[1024];
11112         ULARGE_INTEGER size, max_size;
11113         LARGE_INTEGER no_off;
11114         CLSID curi;
11115         BSTR raw_uri;
11116         HRESULT hr;
11117 
11118         if(test->create_todo || test->create_expected!=S_OK)
11119             continue;
11120 
11121         uriW = a2w(test->uri);
11122         hr = pCreateUri(uriW, test->create_flags, 0, &uri);
11123         ok(hr == S_OK, "%d) CreateUri failed 0x%08x, expected S_OK..\n", i, hr);
11124 
11125         hr = IUri_QueryInterface(uri, &IID_IPersistStream, (void**)&persist_stream);
11126         ok(hr == S_OK, "%d) QueryInterface failed 0x%08x, expected S_OK.\n", i, hr);
11127 
11128         hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
11129         ok(hr == S_OK, "CreateStreamOnHGlobal failed 0x%08x.\n", hr);
11130         hr = IPersistStream_IsDirty(persist_stream);
11131         ok(hr == S_FALSE, "%d) IsDirty returned 0x%08x, expected S_FALSE.\n", i, hr);
11132         hr = IPersistStream_Save(persist_stream, stream, FALSE);
11133         ok(hr == S_OK, "%d) Save failed 0x%08x, expected S_OK.\n", i, hr);
11134         hr = IPersistStream_IsDirty(persist_stream);
11135         ok(hr == S_FALSE, "%d) IsDirty returned 0x%08x, expected S_FALSE.\n", i, hr);
11136         no_off.QuadPart = 0;
11137         hr = IStream_Seek(stream, no_off, STREAM_SEEK_CUR, &size);
11138         ok(hr == S_OK, "%d) Seek failed 0x%08x, expected S_OK.\n", i, hr);
11139         hr = IStream_Seek(stream, no_off, STREAM_SEEK_SET, NULL);
11140         ok(hr == S_OK, "%d) Seek failed 0x%08x, expected S_OK.\n", i, hr);
11141         hr = IPersistStream_GetSizeMax(persist_stream, &max_size);
11142         ok(hr == S_OK, "%d) GetSizeMax failed 0x%08x, expected S_OK.\n", i, hr);
11143         ok(U(size).LowPart+2 == U(max_size).LowPart,
11144                 "%d) Written data size is %d, max_size %d.\n",
11145                 i, U(size).LowPart, U(max_size).LowPart);
11146 
11147         hr = IStream_Read(stream, (void*)dw_data, sizeof(DWORD), NULL);
11148         ok(hr == S_OK, "%d) Read failed 0x%08x, expected S_OK.\n", i, hr);
11149         ok(dw_data[0]-2 == U(size).LowPart, "%d) Structure size is %d, expected %d\n",
11150                 i, dw_data[0]-2, U(size).LowPart);
11151         hr = IStream_Read(stream, (void*)dw_data, 6*sizeof(DWORD), NULL);
11152         ok(hr == S_OK, "%d) Read failed 0x%08x, expected S_OK.\n", i, hr);
11153         ok(dw_data[0] == 0, "%d) Incorrect value %x, expected 0 (unknown).\n", i, dw_data[0]);
11154         ok(dw_data[1] == 0, "%d) Incorrect value %x, expected 0 (unknown).\n", i, dw_data[1]);
11155         ok(dw_data[2] == add_default_flags(test->create_flags),
11156                 "%d) Incorrect value %x, expected %x (creation flags).\n",
11157                 i, dw_data[2], add_default_flags(test->create_flags));
11158         ok(dw_data[3] == 0, "%d) Incorrect value %x, expected 0 (unknown).\n", i, dw_data[3]);
11159         ok(dw_data[4] == 0, "%d) Incorrect value %x, expected 0 (unknown).\n", i, dw_data[4]);
11160         ok(dw_data[5] == 0, "%d) Incorrect value %x, expected 0 (unknown).\n", i, dw_data[5]);
11161 
11162         props_no = 0;
11163         for(props=0; props<=Uri_PROPERTY_DWORD_LAST; props++) {
11164             if(!props_order[props])
11165                 continue;
11166 
11167             if(props <= Uri_PROPERTY_STRING_LAST) {
11168                 if(test->str_props[props].expected == S_OK)
11169                     props_no++;
11170             } else {
11171                 if(test->dword_props[props-Uri_PROPERTY_DWORD_START].expected == S_OK)
11172                     props_no++;
11173             }
11174         }
11175         if(test->dword_props[Uri_PROPERTY_SCHEME-Uri_PROPERTY_DWORD_START].value != URL_SCHEME_HTTP
11176                 && test->dword_props[Uri_PROPERTY_SCHEME-Uri_PROPERTY_DWORD_START].value != URL_SCHEME_FTP
11177                 && test->dword_props[Uri_PROPERTY_SCHEME-Uri_PROPERTY_DWORD_START].value != URL_SCHEME_HTTPS)
11178             props_no = 1;
11179 
11180         hr = IStream_Read(stream, (void*)&props, sizeof(DWORD), NULL);
11181         ok(hr == S_OK, "%d) Read failed 0x%08x, expected S_OK.\n", i, hr);
11182         ok(props == props_no, "%d) Properties no is %d, expected %d.\n", i, props, props_no);
11183 
11184         dw_data[2] = 0;
11185         dw_data[3] = -1;
11186         while(props) {
11187             hr = IStream_Read(stream, (void*)dw_data, 2*sizeof(DWORD), NULL);
11188             ok(hr == S_OK, "%d) Read failed 0x%08x, expected S_OK.\n", i, hr);
11189             props--;
11190             ok(dw_data[2]<props_order[dw_data[0]],
11191                     "%d) Incorrect properties order (%d, %d)\n",
11192                     i, dw_data[0], dw_data[3]);
11193             dw_data[2] = props_order[dw_data[0]];
11194             dw_data[3] = dw_data[0];
11195 
11196             if(dw_data[0]<=Uri_PROPERTY_STRING_LAST) {
11197                 const uri_str_property *prop = test->str_props+dw_data[0];
11198                 hr = IStream_Read(stream, (void*)str_data, dw_data[1], NULL);
11199                 ok(hr == S_OK, "%d) Read failed 0x%08x, expected S_OK.\n", i, hr);
11200                 ok(!strcmp_aw(prop->value, str_data) || broken(prop->broken_value && !strcmp_aw(prop->broken_value, str_data)),
11201                         "%d) Expected %s but got %s (%d).\n", i, prop->value, wine_dbgstr_w(str_data), dw_data[0]);
11202             } else if(dw_data[0]>=Uri_PROPERTY_DWORD_START && dw_data[0]<=Uri_PROPERTY_DWORD_LAST) {
11203                 const uri_dword_property *prop = test->dword_props+dw_data[0]-Uri_PROPERTY_DWORD_START;
11204                 ok(dw_data[1] == sizeof(DWORD), "%d) Size of dword property is %d (%d)\n", i, dw_data[1], dw_data[0]);
11205                 hr = IStream_Read(stream, (void*)&dw_data[1], sizeof(DWORD), NULL);
11206                 ok(hr == S_OK, "%d) Read failed 0x%08x, expected S_OK.\n", i, hr);
11207                 ok(prop->value == dw_data[1], "%d) Expected %d but got %d (%d).\n", i, prop->value, dw_data[1], dw_data[0]);
11208             } else {
11209                 ok(FALSE, "%d) Incorrect property type (%d)\n", i, dw_data[0]);
11210                 break;
11211             }
11212         }
11213         ok(props == 0, "%d) Not all properties were processed %d. Next property type: %d\n",
11214                 i, props, dw_data[0]);
11215 
11216         IUri_Release(uri);
11217 
11218         hr = IStream_Seek(stream, no_off, STREAM_SEEK_SET, NULL);
11219         ok(hr == S_OK, "%d) Seek failed 0x%08x, expected S_OK.\n", i, hr);
11220         hr = IPersistStream_GetClassID(persist_stream, &curi);
11221         ok(hr == S_OK, "%d) GetClassID failed 0x%08x, expected S_OK.\n", i, hr);
11222         ok(IsEqualCLSID(&curi, &CLSID_CUri), "%d) GetClassID returned incorrect CLSID.\n", i);
11223         IPersistStream_Release(persist_stream);
11224 
11225         hr = CoCreateInstance(&curi, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
11226                 &IID_IUri, (void**)&uri);
11227         ok(hr == S_OK, "%d) Error creating uninitialized Uri: 0x%08x.\n", i, hr);
11228         hr = IUri_QueryInterface(uri, &IID_IPersistStream, (void**)&persist_stream);
11229         ok(hr == S_OK, "%d) QueryInterface failed 0x%08x, expected S_OK.\n", i, hr);
11230         hr = IPersistStream_Load(persist_stream, stream);
11231         ok(hr == S_OK, "%d) Load failed 0x%08x, expected S_OK.\n", i, hr);
11232         hr = IUri_GetRawUri(uri, &raw_uri);
11233         ok(hr == S_OK, "%d) GetRawUri failed 0x%08x, expected S_OK.\n", i, hr);
11234         ok(!strcmp_aw(test->str_props[Uri_PROPERTY_RAW_URI].value, raw_uri)
11235                 || broken(test->str_props[Uri_PROPERTY_RAW_URI].broken_value
11236                     && !strcmp_aw(test->str_props[Uri_PROPERTY_RAW_URI].broken_value, raw_uri)),
11237                 "%d) Expected %s but got %s.\n", i, test->str_props[Uri_PROPERTY_RAW_URI].value,
11238                 wine_dbgstr_w(raw_uri));
11239         SysFreeString(raw_uri);
11240         IPersistStream_Release(persist_stream);
11241 
11242         hr = IUri_QueryInterface(uri, &IID_IMarshal, (void**)&marshal);
11243         ok(hr == S_OK, "%d) QueryInterface(IID_IMarshal) failed 0x%08x, expected S_OK.\n", i, hr);
11244         hr = IStream_Seek(stream, no_off, STREAM_SEEK_SET, NULL);
11245         ok(hr == S_OK, "%d) Seek failed 0x%08x, expected S_OK.\n", i, hr);
11246         hr = IMarshal_MarshalInterface(marshal, stream, &IID_IUri, (void*)uri,
11247                 MSHCTX_DIFFERENTMACHINE, NULL, MSHLFLAGS_NORMAL);
11248         ok(hr == E_INVALIDARG, "%d) MarshalInterface returned 0x%08x, expected E_INVALIDARG.\n", i, hr);
11249         hr = IMarshal_MarshalInterface(marshal, stream, &IID_IUri, (void*)uri,
11250                 MSHCTX_CROSSCTX, NULL, MSHLFLAGS_NORMAL);
11251         ok(hr == E_INVALIDARG, "%d) MarshalInterface returned 0x%08x, expected E_INVALIDARG.\n", i, hr);
11252         hr = IMarshal_MarshalInterface(marshal, stream, &IID_IUri, (void*)uri,
11253                 MSHCTX_LOCAL, NULL, MSHLFLAGS_TABLESTRONG);
11254         ok(hr == E_INVALIDARG, "%d) MarshalInterface returned 0x%08x, expected E_INVALIDARG.\n", i, hr);
11255         hr = IMarshal_MarshalInterface(marshal, stream, &IID_IUri, (void*)uri,
11256                 MSHCTX_LOCAL, NULL, MSHLFLAGS_TABLEWEAK);
11257         ok(hr == E_INVALIDARG, "%d) MarshalInterface returned 0x%08x, expected E_INVALIDARG.\n", i, hr);
11258         hr = IMarshal_MarshalInterface(marshal, stream, &IID_IUri, (void*)uri,
11259                 MSHCTX_LOCAL, NULL, MSHLFLAGS_NOPING);
11260         ok(hr == E_INVALIDARG, "%d) MarshalInterface returned 0x%08x, expected E_INVALIDARG.\n", i, hr);
11261         hr = IMarshal_MarshalInterface(marshal, stream, &IID_IUri, (void*)uri,
11262                 MSHCTX_LOCAL, NULL, MSHLFLAGS_NORMAL);
11263         ok(hr == S_OK, "%d) MarshalInterface failed 0x%08x, expected S_OK.\n", i, hr);
11264         hr = IMarshal_GetUnmarshalClass(marshal, &IID_IUri, (void*)uri,
11265                 MSHCTX_CROSSCTX, NULL, MSHLFLAGS_NORMAL, &curi);
11266         ok(hr == E_INVALIDARG, "%d) GetUnmarshalClass returned 0x%08x, expected E_INVALIDARG.\n", i, hr);
11267         hr = IMarshal_GetUnmarshalClass(marshal, &IID_IUri, (void*)uri,
11268                 MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL, &curi);
11269         ok(hr == S_OK, "%d) GetUnmarshalClass failed 0x%08x, expected S_OK.\n", i, hr);
11270         ok(IsEqualCLSID(&curi, &CLSID_CUri), "%d) GetUnmarshalClass returned incorrect CLSID.\n", i);
11271 
11272         hr = IStream_Seek(stream, no_off, STREAM_SEEK_CUR, &size);
11273         ok(hr == S_OK, "%d) Seek failed 0x%08x, expected S_OK.\n", i, hr);
11274         hr = IStream_Seek(stream, no_off, STREAM_SEEK_SET, NULL);
11275         ok(hr == S_OK, "%d) Seek failed 0x%08x, expected S_OK.\n", i, hr);
11276         hr = IStream_Read(stream, (void*)dw_data, 3*sizeof(DWORD), NULL);
11277         ok(hr == S_OK, "%d) Read failed 0x%08x, expected S_OK.\n", i, hr);
11278         ok(dw_data[0]-2 == U(size).LowPart, "%d) Structure size is %d, expected %d\n",
11279                 i, dw_data[0]-2, U(size).LowPart);
11280         ok(dw_data[1] == MSHCTX_LOCAL, "%d) Incorrect value %d, expected MSHCTX_LOCAL.\n",
11281                 i, dw_data[1]);
11282         ok(dw_data[2] == dw_data[0]-8, "%d) Incorrect value %d, expected %d (PersistStream size).\n",
11283                 i, dw_data[2], dw_data[0]-8);
11284         if(!test->str_props[Uri_PROPERTY_PATH].value[0] &&
11285                 (test->dword_props[Uri_PROPERTY_SCHEME-Uri_PROPERTY_DWORD_START].value == URL_SCHEME_HTTP
11286                  || test->dword_props[Uri_PROPERTY_SCHEME-Uri_PROPERTY_DWORD_START].value == URL_SCHEME_FTP
11287                  || test->dword_props[Uri_PROPERTY_SCHEME-Uri_PROPERTY_DWORD_START].value == URL_SCHEME_HTTPS))
11288             U(max_size).LowPart += 3*sizeof(DWORD);
11289         ok(dw_data[2] == U(max_size).LowPart, "%d) Incorrect value %d, expected %d (PersistStream size).\n",
11290                 i, dw_data[2], U(max_size).LowPart);
11291         IMarshal_Release(marshal);
11292         IUri_Release(uri);
11293 
11294         hr = IStream_Seek(stream, no_off, STREAM_SEEK_SET, NULL);
11295         ok(hr == S_OK, "%d) Seek failed 0x%08x, expected S_OK.\n", i, hr);
11296         hr = CoCreateInstance(&curi, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
11297                 &IID_IUri, (void**)&uri);
11298         ok(hr == S_OK, "%d) Error creating uninitialized Uri: 0x%08x.\n", i, hr);
11299         hr = IUri_QueryInterface(uri, &IID_IMarshal, (void**)&marshal);
11300         ok(hr == S_OK, "%d) QueryInterface failed 0x%08x, expected S_OK.\n", i, hr);
11301         hr = IMarshal_UnmarshalInterface(marshal, stream, &IID_IUri, (void**)&uri);
11302         ok(hr == S_OK, "%d) UnmarshalInterface failed 0x%08x, expected S_OK.\n", i, hr);
11303         hr = IUri_GetRawUri(uri, &raw_uri);
11304         ok(hr == S_OK, "%d) GetRawUri failed 0x%08x, expected S_OK.\n", i, hr);
11305         ok(!strcmp_aw(test->str_props[Uri_PROPERTY_RAW_URI].value, raw_uri)
11306                 || broken(test->str_props[Uri_PROPERTY_RAW_URI].broken_value
11307                     && !strcmp_aw(test->str_props[Uri_PROPERTY_RAW_URI].broken_value, raw_uri)),
11308                 "%d) Expected %s but got %s.\n", i, test->str_props[Uri_PROPERTY_RAW_URI].value,
11309                 wine_dbgstr_w(raw_uri));
11310         SysFreeString(raw_uri);
11311 
11312         IMarshal_Release(marshal);
11313         IStream_Release(stream);
11314         IUri_Release(uri);
11315         heap_free(uriW);
11316     }
11317 }
11318 
11319 static void test_UninitializedUri(void)
11320 {
11321     IUri *uri;
11322     IUriBuilderFactory *ubf;
11323     IPersistStream *ps;
11324     IUriBuilder *ub;
11325     BSTR bstr;
11326     DWORD dword;
11327     BOOL eq;
11328     ULARGE_INTEGER ui;
11329     HRESULT hr;
11330 
11331     hr = CoCreateInstance(&CLSID_CUri, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
11332             &IID_IUri, (void**)&uri);
11333     if(FAILED(hr)) {
11334         win_skip("Skipping uninitialized Uri tests.\n");
11335         return;
11336     }
11337 
11338     hr = IUri_QueryInterface(uri, &IID_IUriBuilderFactory, (void**)&ubf);
11339     ok(hr == S_OK, "QueryInterface(IID_IUriBuillderFactory) failed: %x.\n", hr);
11340     hr = IUri_QueryInterface(uri, &IID_IPersistStream, (void**)&ps);
11341     ok(hr == S_OK, "QueryInterface(IID_IPersistStream) failed: %x.\n", hr);
11342 
11343     hr = IUri_GetAbsoluteUri(uri, NULL);
11344     ok(hr == E_UNEXPECTED, "GetAbsoluteUri returned %x, expected E_UNEXPECTED.\n", hr);
11345     hr = IUri_GetAbsoluteUri(uri, &bstr);
11346     ok(hr == E_UNEXPECTED, "GetAbsoluteUri returned %x, expected E_UNEXPECTED.\n", hr);
11347     hr = IUri_GetAuthority(uri, &bstr);
11348     ok(hr == E_UNEXPECTED, "GetAuthority returned %x, expected E_UNEXPECTED.\n", hr);
11349     hr = IUri_GetDisplayUri(uri, &bstr);
11350     ok(hr == E_UNEXPECTED, "GetDisplayUri returned %x, expected E_UNEXPECTED.\n", hr);
11351     hr = IUri_GetDomain(uri, &bstr);
11352     ok(hr == E_UNEXPECTED, "GetDomain returned %x, expected E_UNEXPECTED.\n", hr);
11353     hr = IUri_GetExtension(uri, &bstr);
11354     ok(hr == E_UNEXPECTED, "GetExtension returned %x, expected E_UNEXPECTED.\n", hr);
11355     hr = IUri_GetFragment(uri, &bstr);
11356     ok(hr == E_UNEXPECTED, "GetFragment returned %x, expected E_UNEXPECTED.\n", hr);
11357     hr = IUri_GetHost(uri, &bstr);
11358     ok(hr == E_UNEXPECTED, "GetHost returned %x, expected E_UNEXPECTED.\n", hr);
11359     hr = IUri_GetHostType(uri, &dword);
11360     ok(hr == E_UNEXPECTED, "GetHostType returned %x, expected E_UNEXPECTED.\n", hr);
11361     hr = IUri_GetPassword(uri, &bstr);
11362     ok(hr == E_UNEXPECTED, "GetPassword returned %x, expected E_UNEXPECTED.\n", hr);
11363     hr = IUri_GetPassword(uri, &bstr);
11364     ok(hr == E_UNEXPECTED, "GetPassword returned %x, expected E_UNEXPECTED.\n", hr);
11365     hr = IUri_GetPathAndQuery(uri, &bstr);
11366     ok(hr == E_UNEXPECTED, "GetPathAndQuery returned %x, expected E_UNEXPECTED.\n", hr);
11367     hr = IUri_GetPort(uri, &dword);
11368     ok(hr == E_UNEXPECTED, "GetPort returned %x, expected E_UNEXPECTED.\n", hr);
11369     hr = IUri_GetProperties(uri, &dword);
11370     ok(hr == E_UNEXPECTED, "GetProperties returned %x, expected E_UNEXPECTED.\n", hr);
11371     hr = IUri_GetPropertyBSTR(uri, Uri_PROPERTY_RAW_URI, &bstr, 0);
11372     ok(hr == E_UNEXPECTED, "GetPropertyBSTR returned %x, expected E_UNEXPECTED.\n", hr);
11373     hr = IUri_GetPropertyDWORD(uri, Uri_PROPERTY_PORT, &dword, 0);
11374     ok(hr == E_UNEXPECTED, "GetPropertyDWORD returned %x, expected E_UNEXPECTED.\n", hr);
11375     hr = IUri_GetPropertyLength(uri, Uri_PROPERTY_RAW_URI, &dword, 0);
11376     ok(hr == E_UNEXPECTED, "GetPropertyLength returned %x, expected E_UNEXPECTED.\n", hr);
11377     hr = IUri_GetQuery(uri, &bstr);
11378     ok(hr == E_UNEXPECTED, "GetQuery returned %x, expected E_UNEXPECTED.\n", hr);
11379     hr = IUri_GetRawUri(uri, &bstr);
11380     ok(hr == E_UNEXPECTED, "GetRawUri returned %x, expected E_UNEXPECTED.\n", hr);
11381     hr = IUri_GetScheme(uri, &dword);
11382     ok(hr == E_UNEXPECTED, "GetScheme returned %x, expected E_UNEXPECTED.\n", hr);
11383     hr = IUri_GetSchemeName(uri, &bstr);
11384     ok(hr == E_UNEXPECTED, "GetSchemeName returned %x, expected E_UNEXPECTED.\n", hr);
11385     hr = IUri_GetUserInfo(uri, &bstr);
11386     ok(hr == E_UNEXPECTED, "GetUserInfo returned %x, expected E_UNEXPECTED.\n", hr);
11387     hr = IUri_GetUserName(uri, &bstr);
11388     ok(hr == E_UNEXPECTED, "GetUserName returned %x, expected E_UNEXPECTED.\n", hr);
11389     hr = IUri_GetZone(uri, &dword);
11390     ok(hr == E_UNEXPECTED, "GetZone returned %x, expected E_UNEXPECTED.\n", hr);
11391     hr = IUri_IsEqual(uri, uri, &eq);
11392     ok(hr == E_UNEXPECTED, "IsEqual returned %x, expected E_UNEXPECTED.\n", hr);
11393 
11394     hr = IUriBuilderFactory_CreateInitializedIUriBuilder(ubf, 0, 0, &ub);
11395     ok(hr == E_UNEXPECTED, "CreateInitializedIUriBuilder returned %x, expected E_UNEXPECTED.\n", hr);
11396     hr = IUriBuilderFactory_CreateIUriBuilder(ubf, 0, 0, &ub);
11397     ok(hr == S_OK, "CreateIUriBuilder returned %x, expected S_OK.\n", hr);
11398     IUriBuilder_Release(ub);
11399 
11400     hr = IPersistStream_GetSizeMax(ps, &ui);
11401     ok(hr == S_OK, "GetSizeMax returned %x, expected S_OK.\n", hr);
11402     ok(ui.u.LowPart == 34, "ui.LowPart = %d, expected 34.\n", ui.u.LowPart);
11403     hr = IPersistStream_IsDirty(ps);
11404     ok(hr == S_FALSE, "IsDirty returned %x, expected S_FALSE.\n", hr);
11405 
11406     IPersistStream_Release(ps);
11407     IUriBuilderFactory_Release(ubf);
11408     IUri_Release(uri);
11409 }
11410 
11411 START_TEST(uri) {
11412     HMODULE hurlmon;
11413 
11414     hurlmon = GetModuleHandleA("urlmon.dll");
11415     pCoInternetGetSession = (void*) GetProcAddress(hurlmon, "CoInternetGetSession");
11416     pCreateUri = (void*) GetProcAddress(hurlmon, "CreateUri");
11417     pCreateUriWithFragment = (void*) GetProcAddress(hurlmon, "CreateUriWithFragment");
11418     pCreateIUriBuilder = (void*) GetProcAddress(hurlmon, "CreateIUriBuilder");
11419     pCoInternetCombineIUri = (void*) GetProcAddress(hurlmon, "CoInternetCombineIUri");
11420     pCoInternetCombineUrlEx = (void*) GetProcAddress(hurlmon, "CoInternetCombineUrlEx");
11421     pCoInternetParseIUri = (void*) GetProcAddress(hurlmon, "CoInternetParseIUri");
11422     pCreateURLMonikerEx = (void*) GetProcAddress(hurlmon, "CreateURLMonikerEx");
11423     pCreateURLMonikerEx2 = (void*) GetProcAddress(hurlmon, "CreateURLMonikerEx2");
11424 
11425     if(!pCreateUri) {
11426         win_skip("CreateUri is not present, skipping tests.\n");
11427         return;
11428     }
11429 
11430     trace("test CreateUri invalid flags...\n");
11431     test_CreateUri_InvalidFlags();
11432 
11433     trace("test CreateUri invalid args...\n");
11434     test_CreateUri_InvalidArgs();
11435 
11436     trace("test CreateUri invalid URIs...\n");
11437     test_CreateUri_InvalidUri();
11438 
11439     trace("test IUri_GetPropertyBSTR...\n");
11440     test_IUri_GetPropertyBSTR();
11441 
11442     trace("test IUri_GetPropertyDWORD...\n");
11443     test_IUri_GetPropertyDWORD();
11444 
11445     trace("test IUri_GetStrProperties...\n");
11446     test_IUri_GetStrProperties();
11447 
11448     trace("test IUri_GetDwordProperties...\n");
11449     test_IUri_GetDwordProperties();
11450 
11451     trace("test IUri_GetPropertyLength...\n");
11452     test_IUri_GetPropertyLength();
11453 
11454     trace("test IUri_GetProperties...\n");
11455     test_IUri_GetProperties();
11456 
11457     trace("test IUri_HasProperty...\n");
11458     test_IUri_HasProperty();
11459 
11460     trace("test IUri_IsEqual...\n");
11461     test_IUri_IsEqual();
11462 
11463     trace("test CreateUriWithFragment invalid args...\n");
11464     test_CreateUriWithFragment_InvalidArgs();
11465 
11466     trace("test CreateUriWithFragment invalid flags...\n");
11467     test_CreateUriWithFragment_InvalidFlags();
11468 
11469     trace("test CreateUriWithFragment...\n");
11470     test_CreateUriWithFragment();
11471 
11472     trace("test CreateIUriBuilder...\n");
11473     test_CreateIUriBuilder();
11474 
11475     trace("test IUriBuilder_CreateInvalidArgs...\n");
11476     test_IUriBuilder_CreateInvalidArgs();
11477 
11478     trace("test IUriBuilder...\n");
11479     test_IUriBuilder();
11480 
11481     trace("test IUriBuilder_GetInvalidArgs...\n");
11482     test_IUriBuilder_GetInvalidArgs();
11483 
11484     trace("test IUriBuilder_HasBeenModified...\n");
11485     test_IUriBuilder_HasBeenModified();
11486 
11487     trace("test IUriBuilder_IUriProperty...\n");
11488     test_IUriBuilder_IUriProperty();
11489 
11490     trace("test IUriBuilder_RemoveProperties...\n");
11491     test_IUriBuilder_RemoveProperties();
11492 
11493     trace("test IUriBuilder miscellaneous...\n");
11494     test_IUriBuilder_Misc();
11495 
11496     trace("test IUriBuilderFactory...\n");
11497     test_IUriBuilderFactory();
11498 
11499     trace("test CoInternetCombineIUri...\n");
11500     test_CoInternetCombineIUri();
11501 
11502     trace("test CoInternetCombineUrlEx...\n");
11503     test_CoInternetCombineUrlEx();
11504 
11505     trace("test CoInternetParseIUri Invalid Args...\n");
11506     test_CoInternetParseIUri_InvalidArgs();
11507 
11508     trace("test CoInternetParseIUri...\n");
11509     test_CoInternetParseIUri();
11510 
11511     register_protocols();
11512 
11513     trace("test CoInternetCombineIUri pluggable...\n");
11514     test_CoInternetCombineIUri_Pluggable();
11515 
11516     trace("test CoInternetCombineUrlEx Pluggable...\n");
11517     test_CoInternetCombineUrlEx_Pluggable();
11518 
11519     trace("test CoInternetParseIUri pluggable...\n");
11520     test_CoInternetParseIUri_Pluggable();
11521 
11522     trace("test CreateURLMoniker...\n");
11523     test_CreateURLMoniker();
11524 
11525     CoInitialize(NULL);
11526 
11527     trace("test IPersistStream...\n");
11528     test_IPersistStream();
11529 
11530     trace("test uninitialized Uri...\n");
11531     test_UninitializedUri();
11532 
11533     CoUninitialize();
11534     unregister_protocols();
11535 }
11536