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 
a2w(LPCSTR str)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 
strcmp_aw(LPCSTR strA,LPCWSTR strB)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 
get_refcnt(IUri * uri)7707 static inline ULONG get_refcnt(IUri *uri) {
7708     IUri_AddRef(uri);
7709     return IUri_Release(uri);
7710 }
7711 
change_property(IUriBuilder * builder,const uri_builder_property * prop,DWORD test_index)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  */
test_CreateUri_InvalidFlags(void)7786 static void test_CreateUri_InvalidFlags(void) {
7787     DWORD i;
7788 
7789     for(i = 0; i < ARRAY_SIZE(invalid_flag_tests); ++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 
test_CreateUri_InvalidArgs(void)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 
test_CreateUri_InvalidUri(void)7825 static void test_CreateUri_InvalidUri(void) {
7826     DWORD i;
7827 
7828     for(i = 0; i < ARRAY_SIZE(invalid_uri_tests); ++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 
test_IUri_GetPropertyBSTR(void)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 < ARRAY_SIZE(uri_tests); ++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 
test_IUri_GetPropertyDWORD(void)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 < ARRAY_SIZE(uri_tests); ++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 < ARRAY_SIZE(test.dword_props); ++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. */
test_IUri_GetStrProperties(void)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 < ARRAY_SIZE(uri_tests); ++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 
test_IUri_GetDwordProperties(void)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 < ARRAY_SIZE(uri_tests); ++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 
test_IUri_GetPropertyLength(void)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 < ARRAY_SIZE(uri_tests); ++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                 heap_free(expectedValueW);
8370 
8371                 /* This won't be necessary once GetPropertyLength is implemented. */
8372                 receivedLen = -1;
8373 
8374                 hr = IUri_GetPropertyLength(uri, j, &receivedLen, 0);
8375                 todo_wine_if(prop.todo) {
8376                     ok(hr == prop.expected || (prop.value2 && hr == prop.expected2),
8377                        "Error: GetPropertyLength returned 0x%08x, expected 0x%08x on uri_tests[%d].str_props[%d].\n",
8378                             hr, prop.expected, i, j);
8379                     ok(receivedLen == expectedLen || (prop.value2 && receivedLen == lstrlenA(prop.value2)) ||
8380                        broken(prop.broken_value && receivedLen == lstrlenA(prop.broken_value)),
8381                             "Error: Expected a length of %d but got %d on uri_tests[%d].str_props[%d].\n",
8382                             expectedLen, receivedLen, i, j);
8383                 }
8384             }
8385         }
8386 
8387         if(uri) IUri_Release(uri);
8388 
8389         heap_free(uriW);
8390     }
8391 }
8392 
compute_expected_props(uri_properties * test,DWORD * mask)8393 static DWORD compute_expected_props(uri_properties *test, DWORD *mask)
8394 {
8395     DWORD ret = 0, i;
8396 
8397     *mask = 0;
8398 
8399     for(i=Uri_PROPERTY_STRING_START; i <= Uri_PROPERTY_STRING_LAST; i++) {
8400         if(test->str_props[i-Uri_PROPERTY_STRING_START].expected == S_OK)
8401             ret |= 1<<i;
8402         if(test->str_props[i-Uri_PROPERTY_STRING_START].value2 == NULL ||
8403            test->str_props[i-Uri_PROPERTY_STRING_START].expected ==
8404            test->str_props[i-Uri_PROPERTY_STRING_START].expected2)
8405             *mask |= 1<<i;
8406     }
8407 
8408     for(i=Uri_PROPERTY_DWORD_START; i <= Uri_PROPERTY_DWORD_LAST; i++) {
8409         if(test->dword_props[i-Uri_PROPERTY_DWORD_START].expected == S_OK)
8410             ret |= 1<<i;
8411         *mask |= 1<<i;
8412     }
8413 
8414     return ret;
8415 }
8416 
test_IUri_GetProperties(void)8417 static void test_IUri_GetProperties(void) {
8418     IUri *uri = NULL;
8419     HRESULT hr;
8420     DWORD i;
8421 
8422     hr = pCreateUri(http_urlW, 0, 0, &uri);
8423     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8424     if(SUCCEEDED(hr)) {
8425         hr = IUri_GetProperties(uri, NULL);
8426         ok(hr == E_INVALIDARG, "Error: GetProperties returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
8427     }
8428     if(uri) IUri_Release(uri);
8429 
8430     for(i = 0; i < ARRAY_SIZE(uri_tests); ++i) {
8431         uri_properties test = uri_tests[i];
8432         LPWSTR uriW;
8433         uri = NULL;
8434 
8435         uriW = a2w(test.uri);
8436         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
8437         todo_wine_if(test.create_todo)
8438             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, test.create_expected);
8439 
8440         if(SUCCEEDED(hr)) {
8441             DWORD received = 0, expected_props, mask;
8442             DWORD j;
8443 
8444             hr = IUri_GetProperties(uri, &received);
8445             ok(hr == S_OK, "Error: GetProperties returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8446 
8447             expected_props = compute_expected_props(&test, &mask);
8448 
8449             for(j = 0; j <= Uri_PROPERTY_DWORD_LAST; ++j) {
8450                 /* (1 << j) converts a Uri_PROPERTY to its corresponding Uri_HAS_* flag mask. */
8451                 if(mask & (1 << j)) {
8452                     if(expected_props & (1 << j))
8453                         ok(received & (1 << j), "Error: Expected flag for property %d on uri_tests[%d].\n", j, i);
8454                     else
8455                         ok(!(received & (1 << j)), "Error: Received flag for property %d when not expected on uri_tests[%d].\n", j, i);
8456                 }
8457             }
8458         }
8459 
8460         if(uri) IUri_Release(uri);
8461 
8462         heap_free(uriW);
8463     }
8464 }
8465 
test_IUri_HasProperty(void)8466 static void test_IUri_HasProperty(void) {
8467     IUri *uri = NULL;
8468     HRESULT hr;
8469     DWORD i;
8470 
8471     hr = pCreateUri(http_urlW, 0, 0, &uri);
8472     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8473     if(SUCCEEDED(hr)) {
8474         hr = IUri_HasProperty(uri, Uri_PROPERTY_RAW_URI, NULL);
8475         ok(hr == E_INVALIDARG, "Error: HasProperty returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
8476     }
8477     if(uri) IUri_Release(uri);
8478 
8479     for(i = 0; i < ARRAY_SIZE(uri_tests); ++i) {
8480         uri_properties test = uri_tests[i];
8481         LPWSTR uriW;
8482         uri = NULL;
8483 
8484         uriW = a2w(test.uri);
8485 
8486         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
8487         todo_wine_if(test.create_todo)
8488             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, test.create_expected);
8489 
8490         if(SUCCEEDED(hr)) {
8491             DWORD expected_props, j, mask;
8492 
8493             expected_props = compute_expected_props(&test, &mask);
8494 
8495             for(j = 0; j <= Uri_PROPERTY_DWORD_LAST; ++j) {
8496                 /* Assign -1, then explicitly test for TRUE or FALSE later. */
8497                 BOOL received = -1;
8498 
8499                 hr = IUri_HasProperty(uri, j, &received);
8500                 ok(hr == S_OK, "Error: HasProperty returned 0x%08x, expected 0x%08x for property %d on uri_tests[%d].\n",
8501                         hr, S_OK, j, i);
8502 
8503                 if(mask & (1 << j)) {
8504                     if(expected_props & (1 << j)) {
8505                         ok(received == TRUE, "Error: Expected to have property %d on uri_tests[%d].\n", j, i);
8506                     } else {
8507                         ok(received == FALSE, "Error: Wasn't expecting to have property %d on uri_tests[%d].\n", j, i);
8508                     }
8509                 }
8510             }
8511         }
8512 
8513         if(uri) IUri_Release(uri);
8514 
8515         heap_free(uriW);
8516     }
8517 }
8518 
8519 struct custom_uri {
8520     IUri IUri_iface;
8521     IUri *uri;
8522 };
8523 
impl_from_IUri(IUri * iface)8524 static inline struct custom_uri* impl_from_IUri(IUri *iface)
8525 {
8526     return CONTAINING_RECORD(iface, struct custom_uri, IUri_iface);
8527 }
8528 
custom_uri_QueryInterface(IUri * iface,REFIID iid,void ** out)8529 static HRESULT WINAPI custom_uri_QueryInterface(IUri *iface, REFIID iid, void **out)
8530 {
8531     if (IsEqualIID(iid, &IID_IUri) || IsEqualIID(iid, &IID_IUnknown))
8532     {
8533        *out = iface;
8534        IUri_AddRef(iface);
8535        return S_OK;
8536     }
8537 
8538     *out = NULL;
8539     return E_NOINTERFACE;
8540 }
8541 
custom_uri_AddRef(IUri * iface)8542 static ULONG WINAPI custom_uri_AddRef(IUri *iface)
8543 {
8544     struct custom_uri *uri = impl_from_IUri(iface);
8545     return IUri_AddRef(uri->uri);
8546 }
8547 
custom_uri_Release(IUri * iface)8548 static ULONG WINAPI custom_uri_Release(IUri *iface)
8549 {
8550     struct custom_uri *uri = impl_from_IUri(iface);
8551     return IUri_Release(uri->uri);
8552 }
8553 
custom_uri_GetPropertyBSTR(IUri * iface,Uri_PROPERTY property,BSTR * value,DWORD flags)8554 static HRESULT WINAPI custom_uri_GetPropertyBSTR(IUri *iface, Uri_PROPERTY property, BSTR *value, DWORD flags)
8555 {
8556     struct custom_uri *uri = impl_from_IUri(iface);
8557     return IUri_GetPropertyBSTR(uri->uri, property, value, flags);
8558 }
8559 
custom_uri_GetPropertyLength(IUri * iface,Uri_PROPERTY property,DWORD * length,DWORD flags)8560 static HRESULT WINAPI custom_uri_GetPropertyLength(IUri *iface, Uri_PROPERTY property, DWORD *length, DWORD flags)
8561 {
8562     struct custom_uri *uri = impl_from_IUri(iface);
8563     return IUri_GetPropertyLength(uri->uri, property, length, flags);
8564 }
8565 
custom_uri_GetPropertyDWORD(IUri * iface,Uri_PROPERTY property,DWORD * value,DWORD flags)8566 static HRESULT WINAPI custom_uri_GetPropertyDWORD(IUri *iface, Uri_PROPERTY property, DWORD *value, DWORD flags)
8567 {
8568     struct custom_uri *uri = impl_from_IUri(iface);
8569     return IUri_GetPropertyDWORD(uri->uri, property, value, flags);
8570 }
8571 
custom_uri_HasProperty(IUri * iface,Uri_PROPERTY property,BOOL * has_property)8572 static HRESULT WINAPI custom_uri_HasProperty(IUri *iface, Uri_PROPERTY property, BOOL *has_property)
8573 {
8574     struct custom_uri *uri = impl_from_IUri(iface);
8575     return IUri_HasProperty(uri->uri, property, has_property);
8576 }
8577 
custom_uri_GetAbsoluteUri(IUri * iface,BSTR * value)8578 static HRESULT WINAPI custom_uri_GetAbsoluteUri(IUri *iface, BSTR *value)
8579 {
8580     struct custom_uri *uri = impl_from_IUri(iface);
8581     return IUri_GetAbsoluteUri(uri->uri, value);
8582 }
8583 
custom_uri_GetAuthority(IUri * iface,BSTR * value)8584 static HRESULT WINAPI custom_uri_GetAuthority(IUri *iface, BSTR *value)
8585 {
8586     struct custom_uri *uri = impl_from_IUri(iface);
8587     return IUri_GetAbsoluteUri(uri->uri, value);
8588 }
8589 
custom_uri_GetDisplayUri(IUri * iface,BSTR * value)8590 static HRESULT WINAPI custom_uri_GetDisplayUri(IUri *iface, BSTR *value)
8591 {
8592     struct custom_uri *uri = impl_from_IUri(iface);
8593     return IUri_GetAbsoluteUri(uri->uri, value);
8594 }
8595 
custom_uri_GetDomain(IUri * iface,BSTR * value)8596 static HRESULT WINAPI custom_uri_GetDomain(IUri *iface, BSTR *value)
8597 {
8598     struct custom_uri *uri = impl_from_IUri(iface);
8599     return IUri_GetAbsoluteUri(uri->uri, value);
8600 }
8601 
custom_uri_GetExtension(IUri * iface,BSTR * value)8602 static HRESULT WINAPI custom_uri_GetExtension(IUri *iface, BSTR *value)
8603 {
8604     struct custom_uri *uri = impl_from_IUri(iface);
8605     return IUri_GetAbsoluteUri(uri->uri, value);
8606 }
8607 
custom_uri_GetFragment(IUri * iface,BSTR * value)8608 static HRESULT WINAPI custom_uri_GetFragment(IUri *iface, BSTR *value)
8609 {
8610     struct custom_uri *uri = impl_from_IUri(iface);
8611     return IUri_GetAbsoluteUri(uri->uri, value);
8612 }
8613 
custom_uri_GetHost(IUri * iface,BSTR * value)8614 static HRESULT WINAPI custom_uri_GetHost(IUri *iface, BSTR *value)
8615 {
8616     struct custom_uri *uri = impl_from_IUri(iface);
8617     return IUri_GetAbsoluteUri(uri->uri, value);
8618 }
8619 
custom_uri_GetPassword(IUri * iface,BSTR * value)8620 static HRESULT WINAPI custom_uri_GetPassword(IUri *iface, BSTR *value)
8621 {
8622     struct custom_uri *uri = impl_from_IUri(iface);
8623     return IUri_GetAbsoluteUri(uri->uri, value);
8624 }
8625 
custom_uri_GetPath(IUri * iface,BSTR * value)8626 static HRESULT WINAPI custom_uri_GetPath(IUri *iface, BSTR *value)
8627 {
8628     struct custom_uri *uri = impl_from_IUri(iface);
8629     return IUri_GetAbsoluteUri(uri->uri, value);
8630 }
8631 
custom_uri_GetPathAndQuery(IUri * iface,BSTR * value)8632 static HRESULT WINAPI custom_uri_GetPathAndQuery(IUri *iface, BSTR *value)
8633 {
8634     struct custom_uri *uri = impl_from_IUri(iface);
8635     return IUri_GetAbsoluteUri(uri->uri, value);
8636 }
8637 
custom_uri_GetQuery(IUri * iface,BSTR * value)8638 static HRESULT WINAPI custom_uri_GetQuery(IUri *iface, BSTR *value)
8639 {
8640     struct custom_uri *uri = impl_from_IUri(iface);
8641     return IUri_GetAbsoluteUri(uri->uri, value);
8642 }
8643 
custom_uri_GetRawUri(IUri * iface,BSTR * value)8644 static HRESULT WINAPI custom_uri_GetRawUri(IUri *iface, BSTR *value)
8645 {
8646     struct custom_uri *uri = impl_from_IUri(iface);
8647     return IUri_GetAbsoluteUri(uri->uri, value);
8648 }
8649 
custom_uri_GetSchemeName(IUri * iface,BSTR * value)8650 static HRESULT WINAPI custom_uri_GetSchemeName(IUri *iface, BSTR *value)
8651 {
8652     struct custom_uri *uri = impl_from_IUri(iface);
8653     return IUri_GetSchemeName(uri->uri, value);
8654 }
8655 
custom_uri_GetUserInfo(IUri * iface,BSTR * value)8656 static HRESULT WINAPI custom_uri_GetUserInfo(IUri *iface, BSTR *value)
8657 {
8658     struct custom_uri *uri = impl_from_IUri(iface);
8659     return IUri_GetUserInfo(uri->uri, value);
8660 }
8661 
custom_uri_GetUserName(IUri * iface,BSTR * value)8662 static HRESULT WINAPI custom_uri_GetUserName(IUri *iface, BSTR *value)
8663 {
8664     struct custom_uri *uri = impl_from_IUri(iface);
8665     return IUri_GetUserName(uri->uri, value);
8666 }
8667 
custom_uri_GetHostType(IUri * iface,DWORD * value)8668 static HRESULT WINAPI custom_uri_GetHostType(IUri *iface, DWORD *value)
8669 {
8670     struct custom_uri *uri = impl_from_IUri(iface);
8671     return IUri_GetHostType(uri->uri, value);
8672 }
8673 
custom_uri_GetPort(IUri * iface,DWORD * value)8674 static HRESULT WINAPI custom_uri_GetPort(IUri *iface, DWORD *value)
8675 {
8676     struct custom_uri *uri = impl_from_IUri(iface);
8677     return IUri_GetPort(uri->uri, value);
8678 }
8679 
custom_uri_GetScheme(IUri * iface,DWORD * value)8680 static HRESULT WINAPI custom_uri_GetScheme(IUri *iface, DWORD *value)
8681 {
8682     struct custom_uri *uri = impl_from_IUri(iface);
8683     return IUri_GetScheme(uri->uri, value);
8684 }
8685 
custom_uri_GetZone(IUri * iface,DWORD * value)8686 static HRESULT WINAPI custom_uri_GetZone(IUri *iface, DWORD *value)
8687 {
8688     struct custom_uri *uri = impl_from_IUri(iface);
8689     return IUri_GetZone(uri->uri, value);
8690 }
8691 
custom_uri_GetProperties(IUri * iface,DWORD * flags)8692 static HRESULT WINAPI custom_uri_GetProperties(IUri *iface, DWORD *flags)
8693 {
8694     struct custom_uri *uri = impl_from_IUri(iface);
8695     return IUri_GetProperties(uri->uri, flags);
8696 }
8697 
custom_uri_IsEqual(IUri * iface,IUri * pUri,BOOL * is_equal)8698 static HRESULT WINAPI custom_uri_IsEqual(IUri *iface, IUri *pUri, BOOL *is_equal)
8699 {
8700     struct custom_uri *uri = impl_from_IUri(iface);
8701     return IUri_IsEqual(uri->uri, pUri, is_equal);
8702 }
8703 
8704 static const IUriVtbl custom_uri_vtbl =
8705 {
8706     custom_uri_QueryInterface,
8707     custom_uri_AddRef,
8708     custom_uri_Release,
8709     custom_uri_GetPropertyBSTR,
8710     custom_uri_GetPropertyLength,
8711     custom_uri_GetPropertyDWORD,
8712     custom_uri_HasProperty,
8713     custom_uri_GetAbsoluteUri,
8714     custom_uri_GetAuthority,
8715     custom_uri_GetDisplayUri,
8716     custom_uri_GetDomain,
8717     custom_uri_GetExtension,
8718     custom_uri_GetFragment,
8719     custom_uri_GetHost,
8720     custom_uri_GetPassword,
8721     custom_uri_GetPath,
8722     custom_uri_GetPathAndQuery,
8723     custom_uri_GetQuery,
8724     custom_uri_GetRawUri,
8725     custom_uri_GetSchemeName,
8726     custom_uri_GetUserInfo,
8727     custom_uri_GetUserName,
8728     custom_uri_GetHostType,
8729     custom_uri_GetPort,
8730     custom_uri_GetScheme,
8731     custom_uri_GetZone,
8732     custom_uri_GetProperties,
8733     custom_uri_IsEqual,
8734 };
8735 
test_IUri_IsEqual(void)8736 static void test_IUri_IsEqual(void) {
8737     struct custom_uri custom_uri;
8738     IUri *uriA, *uriB;
8739     BOOL equal;
8740     HRESULT hres;
8741     DWORD i;
8742 
8743     uriA = uriB = NULL;
8744 
8745     /* Make sure IsEqual handles invalid args correctly. */
8746     hres = pCreateUri(http_urlW, 0, 0, &uriA);
8747     ok(hres == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hres, S_OK);
8748     hres = pCreateUri(http_urlW, 0, 0, &uriB);
8749     ok(hres == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hres, S_OK);
8750 
8751     equal = -1;
8752     hres = IUri_IsEqual(uriA, NULL, &equal);
8753     ok(hres == S_OK, "Error: IsEqual returned 0x%08x, expected 0x%08x.\n", hres, S_OK);
8754     ok(!equal, "Error: Expected equal to be FALSE, but was %d instead.\n", equal);
8755 
8756     hres = IUri_IsEqual(uriA, uriB, NULL);
8757     ok(hres == E_POINTER, "Error: IsEqual returned 0x%08x, expected 0x%08x.\n", hres, E_POINTER);
8758 
8759     equal = FALSE;
8760     hres = IUri_IsEqual(uriA, uriA, &equal);
8761     ok(hres == S_OK, "Error: IsEqual returned 0x%08x, expected 0x%08x.\n", hres, S_OK);
8762     ok(equal, "Error: Expected equal URIs.\n");
8763 
8764     equal = FALSE;
8765     hres = IUri_IsEqual(uriA, uriB, &equal);
8766     ok(hres == S_OK, "Error: IsEqual returned 0x%08x, expected 0x%08x.\n", hres, S_OK);
8767     ok(equal, "Error: Expected equal URIs.\n");
8768 
8769     IUri_Release(uriA);
8770     IUri_Release(uriB);
8771 
8772     custom_uri.IUri_iface.lpVtbl = &custom_uri_vtbl;
8773 
8774     for(i = 0; i < ARRAY_SIZE(equality_tests); ++i) {
8775         uri_equality test = equality_tests[i];
8776         LPWSTR uriA_W, uriB_W;
8777 
8778         uriA = uriB = NULL;
8779 
8780         uriA_W = a2w(test.a);
8781         uriB_W = a2w(test.b);
8782 
8783         hres = pCreateUri(uriA_W, test.create_flags_a, 0, &uriA);
8784         ok(hres == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x on equality_tests[%d].a\n", hres, S_OK, i);
8785 
8786         hres = pCreateUri(uriB_W, test.create_flags_b, 0, &uriB);
8787         ok(hres == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x on equality_tests[%d].b\n", hres, S_OK, i);
8788 
8789         equal = -1;
8790         hres = IUri_IsEqual(uriA, uriB, &equal);
8791         todo_wine_if(test.todo) {
8792             ok(hres == S_OK, "Error: IsEqual returned 0x%08x, expected 0x%08x on equality_tests[%d].\n", hres, S_OK, i);
8793             ok(equal == test.equal, "Error: Expected the comparison to be %d on equality_tests[%d].\n", test.equal, i);
8794         }
8795 
8796         custom_uri.uri = uriB;
8797 
8798         equal = -1;
8799         hres = IUri_IsEqual(uriA, &custom_uri.IUri_iface, &equal);
8800         todo_wine {
8801             ok(hres == S_OK, "Error: IsEqual returned 0x%08x, expected 0x%08x on equality_tests[%d].\n", hres, S_OK, i);
8802             ok(equal == test.equal, "Error: Expected the comparison to be %d on equality_tests[%d].\n", test.equal, i);
8803         }
8804 
8805         if(uriA) IUri_Release(uriA);
8806         if(uriB) IUri_Release(uriB);
8807 
8808         heap_free(uriA_W);
8809         heap_free(uriB_W);
8810     }
8811 }
8812 
test_CreateUriWithFragment_InvalidArgs(void)8813 static void test_CreateUriWithFragment_InvalidArgs(void) {
8814     HRESULT hr;
8815     IUri *uri = (void*) 0xdeadbeef;
8816     const WCHAR fragmentW[] = {'#','f','r','a','g','m','e','n','t',0};
8817 
8818     hr = pCreateUriWithFragment(NULL, fragmentW, 0, 0, &uri);
8819     ok(hr == E_INVALIDARG, "Error: CreateUriWithFragment returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
8820     ok(uri == NULL, "Error: Expected uri to be NULL, but was %p instead.\n", uri);
8821 
8822     hr = pCreateUriWithFragment(http_urlW, fragmentW, 0, 0, NULL);
8823     ok(hr == E_INVALIDARG, "Error: CreateUriWithFragment returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
8824 
8825     /* Original URI can't already contain a fragment component. */
8826     uri = (void*) 0xdeadbeef;
8827     hr = pCreateUriWithFragment(http_url_fragW, fragmentW, 0, 0, &uri);
8828     ok(hr == E_INVALIDARG, "Error: CreateUriWithFragment returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
8829     ok(uri == NULL, "Error: Expected uri to be NULL, but was %p instead.\n", uri);
8830 }
8831 
8832 /* CreateUriWithFragment has the same invalid flag combinations as CreateUri. */
test_CreateUriWithFragment_InvalidFlags(void)8833 static void test_CreateUriWithFragment_InvalidFlags(void) {
8834     DWORD i;
8835 
8836     for(i = 0; i < ARRAY_SIZE(invalid_flag_tests); ++i) {
8837         HRESULT hr;
8838         IUri *uri = (void*) 0xdeadbeef;
8839 
8840         hr = pCreateUriWithFragment(http_urlW, NULL, invalid_flag_tests[i].flags, 0, &uri);
8841         ok(hr == invalid_flag_tests[i].expected, "Error: CreateUriWithFragment returned 0x%08x, expected 0x%08x. flags=0x%08x.\n",
8842             hr, invalid_flag_tests[i].expected, invalid_flag_tests[i].flags);
8843         ok(uri == NULL, "Error: Expected uri to be NULL, but was %p instead.\n", uri);
8844     }
8845 }
8846 
test_CreateUriWithFragment(void)8847 static void test_CreateUriWithFragment(void) {
8848     DWORD i;
8849 
8850     for(i = 0; i < ARRAY_SIZE(uri_fragment_tests); ++i) {
8851         HRESULT hr;
8852         IUri *uri = NULL;
8853         LPWSTR uriW, fragW;
8854         uri_with_fragment test = uri_fragment_tests[i];
8855 
8856         uriW = a2w(test.uri);
8857         fragW = a2w(test.fragment);
8858 
8859         hr = pCreateUriWithFragment(uriW, fragW, test.create_flags, 0, &uri);
8860         todo_wine_if(test.expected_todo)
8861             ok(hr == test.create_expected,
8862                 "Error: CreateUriWithFragment returned 0x%08x, expected 0x%08x on uri_fragment_tests[%d].\n",
8863                 hr, test.create_expected, i);
8864 
8865         if(SUCCEEDED(hr)) {
8866             BSTR received = NULL;
8867 
8868             hr = IUri_GetAbsoluteUri(uri, &received);
8869             todo_wine_if(test.expected_todo) {
8870                 ok(hr == S_OK, "Error: GetAbsoluteUri returned 0x%08x, expected 0x%08x on uri_fragment_tests[%d].\n",
8871                     hr, S_OK, i);
8872                 ok(!strcmp_aw(test.expected_uri, received), "Error: Expected %s but got %s on uri_fragment_tests[%d].\n",
8873                     test.expected_uri, wine_dbgstr_w(received), i);
8874             }
8875 
8876             SysFreeString(received);
8877         }
8878 
8879         if(uri) IUri_Release(uri);
8880         heap_free(uriW);
8881         heap_free(fragW);
8882     }
8883 }
8884 
test_CreateIUriBuilder(void)8885 static void test_CreateIUriBuilder(void) {
8886     HRESULT hr;
8887     IUriBuilder *builder = NULL;
8888     IUri *uri;
8889 
8890     hr = pCreateIUriBuilder(NULL, 0, 0, NULL);
8891     ok(hr == E_POINTER, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x\n",
8892         hr, E_POINTER);
8893 
8894     /* CreateIUriBuilder increases the ref count of the IUri it receives. */
8895     hr = pCreateUri(http_urlW, 0, 0, &uri);
8896     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8897     if(SUCCEEDED(hr)) {
8898         ULONG cur_count, orig_count;
8899 
8900         orig_count = get_refcnt(uri);
8901         hr = pCreateIUriBuilder(uri, 0, 0, &builder);
8902         ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8903         ok(builder != NULL, "Error: Expecting builder not to be NULL\n");
8904 
8905         cur_count = get_refcnt(uri);
8906         ok(cur_count == orig_count+1, "Error: Expected the ref count to be %u, but was %u instead.\n", orig_count+1, cur_count);
8907 
8908         if(builder) IUriBuilder_Release(builder);
8909         cur_count = get_refcnt(uri);
8910         ok(cur_count == orig_count, "Error: Expected the ref count to be %u, but was %u instead.\n", orig_count, cur_count);
8911     }
8912     if(uri) IUri_Release(uri);
8913 }
8914 
test_IUriBuilder_CreateUri(IUriBuilder * builder,const uri_builder_test * test,DWORD test_index)8915 static void test_IUriBuilder_CreateUri(IUriBuilder *builder, const uri_builder_test *test,
8916                                        DWORD test_index) {
8917     HRESULT hr;
8918     IUri *uri = NULL;
8919 
8920     hr = IUriBuilder_CreateUri(builder, test->uri_flags, 0, 0, &uri);
8921     todo_wine_if(test->uri_todo)
8922         ok(hr == test->uri_hres,
8923             "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8924             hr, test->uri_hres, test_index);
8925 
8926     if(SUCCEEDED(hr)) {
8927         DWORD i;
8928 
8929         for(i = 0; i < ARRAY_SIZE(test->expected_str_props); ++i) {
8930             uri_builder_str_property prop = test->expected_str_props[i];
8931             BSTR received = NULL;
8932 
8933             hr = IUri_GetPropertyBSTR(uri, i, &received, 0);
8934             todo_wine_if(prop.todo)
8935                 ok(hr == prop.result,
8936                     "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_str_props[%d].\n",
8937                     hr, prop.result, test_index, i);
8938             if(SUCCEEDED(hr)) {
8939                 todo_wine_if(prop.todo)
8940                     ok(!strcmp_aw(prop.expected, received),
8941                         "Error: Expected %s but got %s instead on uri_builder_tests[%d].expected_str_props[%d].\n",
8942                         prop.expected, wine_dbgstr_w(received), test_index, i);
8943             }
8944             SysFreeString(received);
8945         }
8946 
8947         for(i = 0; i < ARRAY_SIZE(test->expected_dword_props); ++i) {
8948             uri_builder_dword_property prop = test->expected_dword_props[i];
8949             DWORD received = -2;
8950 
8951             hr = IUri_GetPropertyDWORD(uri, i+Uri_PROPERTY_DWORD_START, &received, 0);
8952             todo_wine_if(prop.todo)
8953                 ok(hr == prop.result,
8954                     "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_dword_props[%d].\n",
8955                     hr, prop.result, test_index, i);
8956             if(SUCCEEDED(hr)) {
8957                 todo_wine_if(prop.todo)
8958                     ok(received == prop.expected,
8959                         "Error: Expected %d but got %d instead on uri_builder_tests[%d].expected_dword_props[%d].\n",
8960                         prop.expected, received, test_index, i);
8961             }
8962         }
8963     }
8964     if(uri) IUri_Release(uri);
8965 }
8966 
test_IUriBuilder_CreateUriSimple(IUriBuilder * builder,const uri_builder_test * test,DWORD test_index)8967 static void test_IUriBuilder_CreateUriSimple(IUriBuilder *builder, const uri_builder_test *test,
8968                                        DWORD test_index) {
8969     HRESULT hr;
8970     IUri *uri = NULL;
8971 
8972     hr = IUriBuilder_CreateUriSimple(builder, test->uri_simple_encode_flags, 0, &uri);
8973     todo_wine_if(test->uri_simple_todo)
8974         ok(hr == test->uri_simple_hres,
8975             "Error: IUriBuilder_CreateUriSimple returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8976             hr, test->uri_simple_hres, test_index);
8977 
8978     if(SUCCEEDED(hr)) {
8979         DWORD i;
8980 
8981         for(i = 0; i < ARRAY_SIZE(test->expected_str_props); ++i) {
8982             uri_builder_str_property prop = test->expected_str_props[i];
8983             BSTR received = NULL;
8984 
8985             hr = IUri_GetPropertyBSTR(uri, i, &received, 0);
8986             todo_wine_if(prop.todo)
8987                 ok(hr == prop.result,
8988                     "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_str_props[%d].\n",
8989                     hr, prop.result, test_index, i);
8990             if(SUCCEEDED(hr)) {
8991                 todo_wine_if(prop.todo)
8992                     ok(!strcmp_aw(prop.expected, received),
8993                         "Error: Expected %s but got %s instead on uri_builder_tests[%d].expected_str_props[%d].\n",
8994                         prop.expected, wine_dbgstr_w(received), test_index, i);
8995             }
8996             SysFreeString(received);
8997         }
8998 
8999         for(i = 0; i < ARRAY_SIZE(test->expected_dword_props); ++i) {
9000             uri_builder_dword_property prop = test->expected_dword_props[i];
9001             DWORD received = -2;
9002 
9003             hr = IUri_GetPropertyDWORD(uri, i+Uri_PROPERTY_DWORD_START, &received, 0);
9004             todo_wine_if(prop.todo)
9005                 ok(hr == prop.result,
9006                     "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_dword_props[%d].\n",
9007                     hr, prop.result, test_index, i);
9008             if(SUCCEEDED(hr)) {
9009                 todo_wine_if(prop.todo)
9010                     ok(received == prop.expected,
9011                         "Error: Expected %d but got %d instead on uri_builder_tests[%d].expected_dword_props[%d].\n",
9012                         prop.expected, received, test_index, i);
9013             }
9014         }
9015     }
9016     if(uri) IUri_Release(uri);
9017 }
9018 
test_IUriBuilder_CreateUriWithFlags(IUriBuilder * builder,const uri_builder_test * test,DWORD test_index)9019 static void test_IUriBuilder_CreateUriWithFlags(IUriBuilder *builder, const uri_builder_test *test,
9020                                                 DWORD test_index) {
9021     HRESULT hr;
9022     IUri *uri = NULL;
9023 
9024     hr = IUriBuilder_CreateUriWithFlags(builder, test->uri_with_flags, test->uri_with_builder_flags,
9025                                         test->uri_with_encode_flags, 0, &uri);
9026     todo_wine_if(test->uri_with_todo)
9027         ok(hr == test->uri_with_hres,
9028             "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9029             hr, test->uri_with_hres, test_index);
9030 
9031     if(SUCCEEDED(hr)) {
9032         DWORD i;
9033 
9034         for(i = 0; i < ARRAY_SIZE(test->expected_str_props); ++i) {
9035             uri_builder_str_property prop = test->expected_str_props[i];
9036             BSTR received = NULL;
9037 
9038             hr = IUri_GetPropertyBSTR(uri, i, &received, 0);
9039             todo_wine_if(prop.todo)
9040                 ok(hr == prop.result,
9041                     "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_str_props[%d].\n",
9042                     hr, prop.result, test_index, i);
9043             if(SUCCEEDED(hr)) {
9044                 todo_wine_if(prop.todo)
9045                     ok(!strcmp_aw(prop.expected, received),
9046                         "Error: Expected %s but got %s instead on uri_builder_tests[%d].expected_str_props[%d].\n",
9047                         prop.expected, wine_dbgstr_w(received), test_index, i);
9048             }
9049             SysFreeString(received);
9050         }
9051 
9052         for(i = 0; i < ARRAY_SIZE(test->expected_dword_props); ++i) {
9053             uri_builder_dword_property prop = test->expected_dword_props[i];
9054             DWORD received = -2;
9055 
9056             hr = IUri_GetPropertyDWORD(uri, i+Uri_PROPERTY_DWORD_START, &received, 0);
9057             todo_wine_if(prop.todo)
9058                 ok(hr == prop.result,
9059                     "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_dword_props[%d].\n",
9060                     hr, prop.result, test_index, i);
9061             if(SUCCEEDED(hr)) {
9062                 todo_wine_if(prop.todo)
9063                     ok(received == prop.expected,
9064                         "Error: Expected %d but got %d instead on uri_builder_tests[%d].expected_dword_props[%d].\n",
9065                         prop.expected, received, test_index, i);
9066             }
9067         }
9068     }
9069     if(uri) IUri_Release(uri);
9070 }
9071 
test_IUriBuilder_CreateInvalidArgs(void)9072 static void test_IUriBuilder_CreateInvalidArgs(void) {
9073     IUriBuilder *builder;
9074     HRESULT hr;
9075 
9076     hr = pCreateIUriBuilder(NULL, 0, 0, &builder);
9077     ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9078     if(SUCCEEDED(hr)) {
9079         IUri *test = NULL, *uri = (void*) 0xdeadbeef;
9080 
9081         /* Test what happens if the IUriBuilder doesn't have a IUri set. */
9082         hr = IUriBuilder_CreateUri(builder, 0, 0, 0, NULL);
9083         ok(hr == E_POINTER, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
9084 
9085         uri = (void*) 0xdeadbeef;
9086         hr = IUriBuilder_CreateUri(builder, 0, Uri_HAS_USER_NAME, 0, &uri);
9087         ok(hr == E_NOTIMPL, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, E_NOTIMPL);
9088         ok(uri == NULL, "Error: expected uri to be NULL, but was %p instead.\n", uri);
9089 
9090         hr = IUriBuilder_CreateUriSimple(builder, 0, 0, NULL);
9091         ok(hr == E_POINTER, "Error: IUriBuilder_CreateUriSimple returned 0x%08x, expected 0x%08x.\n",
9092             hr, E_POINTER);
9093 
9094         uri = (void*) 0xdeadbeef;
9095         hr = IUriBuilder_CreateUriSimple(builder, Uri_HAS_USER_NAME, 0, &uri);
9096         ok(hr == E_NOTIMPL, "Error: IUriBuilder_CreateUriSimple returned 0x%08x, expected 0x%08x.\n",
9097             hr, E_NOTIMPL);
9098         ok(!uri, "Error: Expected uri to NULL, but was %p instead.\n", uri);
9099 
9100         hr = IUriBuilder_CreateUriWithFlags(builder, 0, 0, 0, 0, NULL);
9101         ok(hr == E_POINTER, "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x.\n",
9102             hr, E_POINTER);
9103 
9104         uri = (void*) 0xdeadbeef;
9105         hr = IUriBuilder_CreateUriWithFlags(builder, 0, 0, Uri_HAS_USER_NAME, 0, &uri);
9106         ok(hr == E_NOTIMPL, "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x.\n",
9107             hr, E_NOTIMPL);
9108         ok(!uri, "Error: Expected uri to be NULL, but was %p instead.\n", uri);
9109 
9110         hr = pCreateUri(http_urlW, 0, 0, &test);
9111         ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9112         if(SUCCEEDED(hr)) {
9113             hr = IUriBuilder_SetIUri(builder, test);
9114             ok(hr == S_OK, "Error: IUriBuilder_SetIUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9115 
9116             /* No longer returns E_NOTIMPL, since a IUri has been set and hasn't been modified. */
9117             uri = NULL;
9118             hr = IUriBuilder_CreateUri(builder, 0, Uri_HAS_USER_NAME, 0, &uri);
9119             ok(hr == S_OK, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9120             ok(uri != NULL, "Error: The uri was NULL.\n");
9121             if(uri) IUri_Release(uri);
9122 
9123             uri = NULL;
9124             hr = IUriBuilder_CreateUriSimple(builder, Uri_HAS_USER_NAME, 0, &uri);
9125             ok(hr == S_OK, "Error: IUriBuilder_CreateUriSimple returned 0x%08x, expected 0x%08x.\n",
9126                 hr, S_OK);
9127             ok(uri != NULL, "Error: uri was NULL.\n");
9128             if(uri) IUri_Release(uri);
9129 
9130             uri = NULL;
9131             hr = IUriBuilder_CreateUriWithFlags(builder, 0, 0, 0, 0, &uri);
9132             ok(hr == S_OK, "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x.\n",
9133                 hr, S_OK);
9134             ok(uri != NULL, "Error: uri was NULL.\n");
9135             if(uri) IUri_Release(uri);
9136 
9137             hr = IUriBuilder_SetFragment(builder, NULL);
9138             ok(hr == S_OK, "Error: IUriBuilder_SetFragment returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9139 
9140             /* The IUriBuilder is changed, so it returns E_NOTIMPL again. */
9141             uri = (void*) 0xdeadbeef;
9142             hr = IUriBuilder_CreateUri(builder, 0, Uri_HAS_USER_NAME, 0, &uri);
9143             ok(hr == E_NOTIMPL, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9144             ok(!uri, "Error: Expected uri to be NULL but was %p instead.\n", uri);
9145 
9146             uri = (void*) 0xdeadbeef;
9147             hr = IUriBuilder_CreateUriSimple(builder, Uri_HAS_USER_NAME, 0, &uri);
9148             ok(hr == E_NOTIMPL, "Error: IUriBuilder_CreateUriSimple returned 0x%08x, expected 0x%08x.\n",
9149                 hr, S_OK);
9150             ok(!uri, "Error: Expected uri to be NULL, but was %p instead.\n", uri);
9151 
9152             uri = (void*) 0xdeadbeef;
9153             hr = IUriBuilder_CreateUriWithFlags(builder, 0, 0, Uri_HAS_USER_NAME, 0, &uri);
9154             ok(hr == E_NOTIMPL, "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x.\n",
9155                 hr, E_NOTIMPL);
9156             ok(!uri, "Error: Expected uri to be NULL, but was %p instead.\n", uri);
9157         }
9158         if(test) IUri_Release(test);
9159     }
9160     if(builder) IUriBuilder_Release(builder);
9161 }
9162 
9163 /* Tests invalid args to the "Get*" functions. */
test_IUriBuilder_GetInvalidArgs(void)9164 static void test_IUriBuilder_GetInvalidArgs(void) {
9165     IUriBuilder *builder = NULL;
9166     HRESULT hr;
9167 
9168     hr = pCreateIUriBuilder(NULL, 0, 0, &builder);
9169     ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9170     if(SUCCEEDED(hr)) {
9171         LPCWSTR received = (void*) 0xdeadbeef;
9172         DWORD len = -1, port = -1;
9173         BOOL set = -1;
9174 
9175         hr = IUriBuilder_GetFragment(builder, NULL, NULL);
9176         ok(hr == E_POINTER, "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x.\n",
9177             hr, E_POINTER);
9178         hr = IUriBuilder_GetFragment(builder, NULL, &received);
9179         ok(hr == E_POINTER, "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x.\n",
9180             hr, E_POINTER);
9181         ok(!received, "Error: Expected received to be NULL, but was %p instead.\n", received);
9182         hr = IUriBuilder_GetFragment(builder, &len, NULL);
9183         ok(hr == E_POINTER, "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x.\n",
9184             hr, E_POINTER);
9185         ok(!len, "Error: Expected len to be 0, but was %d instead.\n", len);
9186 
9187         hr = IUriBuilder_GetHost(builder, NULL, NULL);
9188         ok(hr == E_POINTER, "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x.\n",
9189             hr, E_POINTER);
9190         received = (void*) 0xdeadbeef;
9191         hr = IUriBuilder_GetHost(builder, NULL, &received);
9192         ok(hr == E_POINTER, "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x.\n",
9193             hr, E_POINTER);
9194         ok(!received, "Error: Expected received to be NULL, but was %p instead.\n", received);
9195         len = -1;
9196         hr = IUriBuilder_GetHost(builder, &len, NULL);
9197         ok(hr == E_POINTER, "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x.\n",
9198             hr, E_POINTER);
9199         ok(!len, "Error: Expected len to be 0, but was %d instead.\n", len);
9200 
9201         hr = IUriBuilder_GetPassword(builder, NULL, NULL);
9202         ok(hr == E_POINTER, "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x.\n",
9203             hr, E_POINTER);
9204         received = (void*) 0xdeadbeef;
9205         hr = IUriBuilder_GetPassword(builder, NULL, &received);
9206         ok(hr == E_POINTER, "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x.\n",
9207             hr, E_POINTER);
9208         ok(!received, "Error: Expected received to be NULL, but was %p instead.\n", received);
9209         len = -1;
9210         hr = IUriBuilder_GetPassword(builder, &len, NULL);
9211         ok(hr == E_POINTER, "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x.\n",
9212             hr, E_POINTER);
9213         ok(!len, "Error: Expected len to be 0, but was %d instead.\n", len);
9214 
9215         hr = IUriBuilder_GetPath(builder, NULL, NULL);
9216         ok(hr == E_POINTER, "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x.\n",
9217             hr, E_POINTER);
9218         received = (void*) 0xdeadbeef;
9219         hr = IUriBuilder_GetPath(builder, NULL, &received);
9220         ok(hr == E_POINTER, "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x.\n",
9221             hr, E_POINTER);
9222         ok(!received, "Error: Expected received to be NULL, but was %p instead.\n", received);
9223         len = -1;
9224         hr = IUriBuilder_GetPath(builder, &len, NULL);
9225         ok(hr == E_POINTER, "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x.\n",
9226             hr, E_POINTER);
9227         ok(!len, "Error: Expected len to be 0, but was %d instead.\n", len);
9228 
9229         hr = IUriBuilder_GetPort(builder, NULL, NULL);
9230         ok(hr == E_POINTER, "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x.\n",
9231             hr, E_POINTER);
9232         hr = IUriBuilder_GetPort(builder, NULL, &port);
9233         ok(hr == E_POINTER, "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x.\n",
9234             hr, E_POINTER);
9235         ok(!port, "Error: Expected port to be 0, but was %d instead.\n", port);
9236         hr = IUriBuilder_GetPort(builder, &set, NULL);
9237         ok(hr == E_POINTER, "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x.\n",
9238             hr, E_POINTER);
9239         ok(!set, "Error: Expected set to be FALSE, but was %d instead.\n", set);
9240 
9241         hr = IUriBuilder_GetQuery(builder, NULL, NULL);
9242         ok(hr == E_POINTER, "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x.\n",
9243             hr, E_POINTER);
9244         received = (void*) 0xdeadbeef;
9245         hr = IUriBuilder_GetQuery(builder, NULL, &received);
9246         ok(hr == E_POINTER, "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x.\n",
9247             hr, E_POINTER);
9248         ok(!received, "Error: Expected received to be NULL, but was %p instead.\n", received);
9249         len = -1;
9250         hr = IUriBuilder_GetQuery(builder, &len, NULL);
9251         ok(hr == E_POINTER, "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x.\n",
9252             hr, E_POINTER);
9253         ok(!len, "Error: Expected len to be 0, but was %d instead.\n", len);
9254 
9255         hr = IUriBuilder_GetSchemeName(builder, NULL, NULL);
9256         ok(hr == E_POINTER, "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x.\n",
9257             hr, E_POINTER);
9258         received = (void*) 0xdeadbeef;
9259         hr = IUriBuilder_GetSchemeName(builder, NULL, &received);
9260         ok(hr == E_POINTER, "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x.\n",
9261             hr, E_POINTER);
9262         ok(!received, "Error: Expected received to be NULL, but was %p instead.\n", received);
9263         len = -1;
9264         hr = IUriBuilder_GetSchemeName(builder, &len, NULL);
9265         ok(hr == E_POINTER, "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x.\n",
9266             hr, E_POINTER);
9267         ok(!len, "Error: Expected len to be 0, but was %d instead.\n", len);
9268 
9269         hr = IUriBuilder_GetUserName(builder, NULL, NULL);
9270         ok(hr == E_POINTER, "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x.\n",
9271             hr, E_POINTER);
9272         received = (void*) 0xdeadbeef;
9273         hr = IUriBuilder_GetUserName(builder, NULL, &received);
9274         ok(hr == E_POINTER, "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x.\n",
9275             hr, E_POINTER);
9276         ok(!received, "Error: Expected received to be NULL, but was %p instead.\n", received);
9277         len = -1;
9278         hr = IUriBuilder_GetUserName(builder, &len, NULL);
9279         ok(hr == E_POINTER, "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x.\n",
9280             hr, E_POINTER);
9281         ok(!len, "Error: Expected len to be 0, but was %d instead.\n", len);
9282     }
9283     if(builder) IUriBuilder_Release(builder);
9284 }
9285 
test_IUriBuilder_GetFragment(IUriBuilder * builder,const uri_builder_test * test,DWORD test_index)9286 static void test_IUriBuilder_GetFragment(IUriBuilder *builder, const uri_builder_test *test,
9287                                          DWORD test_index) {
9288     HRESULT hr;
9289     DWORD i;
9290     LPCWSTR received = NULL;
9291     DWORD len = -1;
9292     const uri_builder_property *prop = NULL;
9293 
9294     /* Check if the property was set earlier. */
9295     for(i = 0; i < ARRAY_SIZE(test->properties); ++i) {
9296         if(test->properties[i].change && test->properties[i].property == Uri_PROPERTY_FRAGMENT)
9297             prop = &(test->properties[i]);
9298     }
9299 
9300     if(prop) {
9301         /* Use expected_value unless it's NULL, then use value. */
9302         LPCSTR expected = prop->expected_value ? prop->expected_value : prop->value;
9303         DWORD expected_len = expected ? strlen(expected) : 0;
9304         hr = IUriBuilder_GetFragment(builder, &len, &received);
9305         todo_wine_if(prop->todo) {
9306             ok(hr == (expected ? S_OK : S_FALSE),
9307                 "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9308                 hr, (expected ? S_OK : S_FALSE), test_index);
9309             if(SUCCEEDED(hr)) {
9310                 ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
9311                    expected, wine_dbgstr_w(received), test_index);
9312                 ok(expected_len == len,
9313                    "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
9314                    expected_len, len, test_index);
9315             }
9316         }
9317     } else {
9318         /* The property wasn't set earlier, so it should return whatever
9319          * the base IUri contains (if anything).
9320          */
9321         IUri *uri = NULL;
9322         hr = IUriBuilder_GetIUri(builder, &uri);
9323         ok(hr == S_OK,
9324             "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9325             hr, S_OK, test_index);
9326         if(SUCCEEDED(hr)) {
9327             if(!uri) {
9328                 received = (void*) 0xdeadbeef;
9329                 len = -1;
9330 
9331                 hr = IUriBuilder_GetFragment(builder, &len, &received);
9332                 ok(hr == S_FALSE,
9333                     "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9334                     hr, S_FALSE, test_index);
9335                 if(SUCCEEDED(hr)) {
9336                     ok(!len, "Error: Expected len to be 0, but was %d instead on uri_builder_tests[%d].\n",
9337                         len, test_index);
9338                     ok(!received, "Error: Expected received to be NULL, but was %p instead on uri_builder_tests[%d].\n",
9339                         received, test_index);
9340                 }
9341             } else {
9342                 BOOL has_prop = FALSE;
9343                 BSTR expected = NULL;
9344 
9345                 hr = IUri_GetFragment(uri, &expected);
9346                 ok(SUCCEEDED(hr),
9347                     "Error: Expected IUri_GetFragment to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
9348                     hr, test_index);
9349                 has_prop = hr == S_OK;
9350 
9351                 hr = IUriBuilder_GetFragment(builder, &len, &received);
9352                 if(has_prop) {
9353                     ok(hr == S_OK,
9354                         "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9355                         hr, S_OK, test_index);
9356                     if(SUCCEEDED(hr)) {
9357                         ok(!lstrcmpW(expected, received),
9358                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].\n",
9359                             wine_dbgstr_w(expected), wine_dbgstr_w(received), test_index);
9360                         ok(lstrlenW(expected) == len,
9361                             "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
9362                             lstrlenW(expected), len, test_index);
9363                     }
9364                 } else {
9365                     ok(hr == S_FALSE,
9366                         "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9367                         hr, S_FALSE, test_index);
9368                     if(SUCCEEDED(hr)) {
9369                         ok(!received, "Error: Expected received to be NULL on uri_builder_tests[%d].\n", test_index);
9370                         ok(!len, "Error: Expected the length to be 0, but was %d instead on uri_builder_tests[%d].\n",
9371                             len, test_index);
9372                     }
9373                 }
9374                 SysFreeString(expected);
9375             }
9376         }
9377         if(uri) IUri_Release(uri);
9378     }
9379 }
9380 
test_IUriBuilder_GetHost(IUriBuilder * builder,const uri_builder_test * test,DWORD test_index)9381 static void test_IUriBuilder_GetHost(IUriBuilder *builder, const uri_builder_test *test,
9382                                      DWORD test_index) {
9383     HRESULT hr;
9384     DWORD i;
9385     LPCWSTR received = NULL;
9386     DWORD len = -1;
9387     const uri_builder_property *prop = NULL;
9388 
9389     /* Check if the property was set earlier. */
9390     for(i = 0; i < ARRAY_SIZE(test->properties); ++i) {
9391         if(test->properties[i].change && test->properties[i].property == Uri_PROPERTY_HOST)
9392             prop = &(test->properties[i]);
9393     }
9394 
9395     if(prop) {
9396         /* Use expected_value unless it's NULL, then use value. */
9397         LPCSTR expected = prop->expected_value ? prop->expected_value : prop->value;
9398         DWORD expected_len = expected ? strlen(expected) : 0;
9399         hr = IUriBuilder_GetHost(builder, &len, &received);
9400         todo_wine_if(prop->todo) {
9401             ok(hr == (expected ? S_OK : S_FALSE),
9402                 "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9403                 hr, (expected ? S_OK : S_FALSE), test_index);
9404             if(SUCCEEDED(hr)) {
9405                 ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
9406                    expected, wine_dbgstr_w(received), test_index);
9407                 ok(expected_len == len,
9408                    "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
9409                    expected_len, len, test_index);
9410             }
9411         }
9412     } else {
9413         /* The property wasn't set earlier, so it should return whatever
9414          * the base IUri contains (if anything).
9415          */
9416         IUri *uri = NULL;
9417         hr = IUriBuilder_GetIUri(builder, &uri);
9418         ok(hr == S_OK,
9419             "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9420             hr, S_OK, test_index);
9421         if(SUCCEEDED(hr)) {
9422             if(!uri) {
9423                 received = (void*) 0xdeadbeef;
9424                 len = -1;
9425 
9426                 hr = IUriBuilder_GetHost(builder, &len, &received);
9427                 ok(hr == S_FALSE,
9428                     "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9429                     hr, S_FALSE, test_index);
9430                 if(SUCCEEDED(hr)) {
9431                     ok(!len, "Error: Expected len to be 0, but was %d instead on uri_builder_tests[%d].\n",
9432                         len, test_index);
9433                     ok(!received, "Error: Expected received to be NULL, but was %p instead on uri_builder_tests[%d].\n",
9434                         received, test_index);
9435                 }
9436             } else {
9437                 BOOL has_prop = FALSE;
9438                 BSTR expected = NULL;
9439 
9440                 hr = IUri_GetHost(uri, &expected);
9441                 ok(SUCCEEDED(hr),
9442                     "Error: Expected IUri_GetHost to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
9443                     hr, test_index);
9444                 has_prop = hr == S_OK;
9445 
9446                 hr = IUriBuilder_GetHost(builder, &len, &received);
9447                 if(has_prop) {
9448                     ok(hr == S_OK,
9449                         "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9450                         hr, S_OK, test_index);
9451                     if(SUCCEEDED(hr)) {
9452                         ok(!lstrcmpW(expected, received),
9453                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].\n",
9454                             wine_dbgstr_w(expected), wine_dbgstr_w(received), test_index);
9455                         ok(lstrlenW(expected) == len,
9456                             "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
9457                             lstrlenW(expected), len, test_index);
9458                     }
9459                 } else {
9460                     ok(hr == S_FALSE,
9461                         "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9462                         hr, S_FALSE, test_index);
9463                     if(SUCCEEDED(hr)) {
9464                         ok(!received, "Error: Expected received to be NULL on uri_builder_tests[%d].\n", test_index);
9465                         ok(!len, "Error: Expected the length to be 0, but was %d instead on uri_builder_tests[%d].\n",
9466                             len, test_index);
9467                     }
9468                 }
9469                 SysFreeString(expected);
9470             }
9471         }
9472         if(uri) IUri_Release(uri);
9473     }
9474 }
9475 
test_IUriBuilder_GetPassword(IUriBuilder * builder,const uri_builder_test * test,DWORD test_index)9476 static void test_IUriBuilder_GetPassword(IUriBuilder *builder, const uri_builder_test *test,
9477                                          DWORD test_index) {
9478     HRESULT hr;
9479     DWORD i;
9480     LPCWSTR received = NULL;
9481     DWORD len = -1;
9482     const uri_builder_property *prop = NULL;
9483 
9484     /* Check if the property was set earlier. */
9485     for(i = 0; i < ARRAY_SIZE(test->properties); ++i) {
9486         if(test->properties[i].change && test->properties[i].property == Uri_PROPERTY_PASSWORD)
9487             prop = &(test->properties[i]);
9488     }
9489 
9490     if(prop) {
9491         /* Use expected_value unless it's NULL, then use value. */
9492         LPCSTR expected = prop->expected_value ? prop->expected_value : prop->value;
9493         DWORD expected_len = expected ? strlen(expected) : 0;
9494         hr = IUriBuilder_GetPassword(builder, &len, &received);
9495         todo_wine_if(prop->todo) {
9496             ok(hr == (expected ? S_OK : S_FALSE),
9497                 "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9498                 hr, (expected ? S_OK : S_FALSE), test_index);
9499             if(SUCCEEDED(hr)) {
9500                 ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
9501                    expected, wine_dbgstr_w(received), test_index);
9502                 ok(expected_len == len,
9503                    "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
9504                    expected_len, len, test_index);
9505             }
9506         }
9507     } else {
9508         /* The property wasn't set earlier, so it should return whatever
9509          * the base IUri contains (if anything).
9510          */
9511         IUri *uri = NULL;
9512         hr = IUriBuilder_GetIUri(builder, &uri);
9513         ok(hr == S_OK,
9514             "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9515             hr, S_OK, test_index);
9516         if(SUCCEEDED(hr)) {
9517             if(!uri) {
9518                 received = (void*) 0xdeadbeef;
9519                 len = -1;
9520 
9521                 hr = IUriBuilder_GetPassword(builder, &len, &received);
9522                 ok(hr == S_FALSE,
9523                     "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9524                     hr, S_FALSE, test_index);
9525                 if(SUCCEEDED(hr)) {
9526                     ok(!len, "Error: Expected len to be 0, but was %d instead on uri_builder_tests[%d].\n",
9527                         len, test_index);
9528                     ok(!received, "Error: Expected received to be NULL, but was %p instead on uri_builder_tests[%d].\n",
9529                         received, test_index);
9530                 }
9531             } else {
9532                 BOOL has_prop = FALSE;
9533                 BSTR expected = NULL;
9534 
9535                 hr = IUri_GetPassword(uri, &expected);
9536                 ok(SUCCEEDED(hr),
9537                     "Error: Expected IUri_GetPassword to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
9538                     hr, test_index);
9539                 has_prop = hr == S_OK;
9540 
9541                 hr = IUriBuilder_GetPassword(builder, &len, &received);
9542                 if(has_prop) {
9543                     ok(hr == S_OK,
9544                         "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9545                         hr, S_OK, test_index);
9546                     if(SUCCEEDED(hr)) {
9547                         ok(!lstrcmpW(expected, received),
9548                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].\n",
9549                             wine_dbgstr_w(expected), wine_dbgstr_w(received), test_index);
9550                         ok(lstrlenW(expected) == len,
9551                             "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
9552                             lstrlenW(expected), len, test_index);
9553                     }
9554                 } else {
9555                     ok(hr == S_FALSE,
9556                         "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9557                         hr, S_FALSE, test_index);
9558                     if(SUCCEEDED(hr)) {
9559                         ok(!received, "Error: Expected received to be NULL on uri_builder_tests[%d].\n", test_index);
9560                         ok(!len, "Error: Expected the length to be 0, but was %d instead on uri_builder_tests[%d].\n",
9561                             len, test_index);
9562                     }
9563                 }
9564                 SysFreeString(expected);
9565             }
9566         }
9567         if(uri) IUri_Release(uri);
9568     }
9569 }
9570 
test_IUriBuilder_GetPath(IUriBuilder * builder,const uri_builder_test * test,DWORD test_index)9571 static void test_IUriBuilder_GetPath(IUriBuilder *builder, const uri_builder_test *test,
9572                                      DWORD test_index) {
9573     HRESULT hr;
9574     DWORD i;
9575     LPCWSTR received = NULL;
9576     DWORD len = -1;
9577     const uri_builder_property *prop = NULL;
9578 
9579     /* Check if the property was set earlier. */
9580     for(i = 0; i < ARRAY_SIZE(test->properties); ++i) {
9581         if(test->properties[i].change && test->properties[i].property == Uri_PROPERTY_PATH)
9582             prop = &(test->properties[i]);
9583     }
9584 
9585     if(prop) {
9586         /* Use expected_value unless it's NULL, then use value. */
9587         LPCSTR expected = prop->expected_value ? prop->expected_value : prop->value;
9588         DWORD expected_len = expected ? strlen(expected) : 0;
9589         hr = IUriBuilder_GetPath(builder, &len, &received);
9590         todo_wine_if(prop->todo) {
9591             ok(hr == (expected ? S_OK : S_FALSE),
9592                 "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9593                 hr, (expected ? S_OK : S_FALSE), test_index);
9594             if(SUCCEEDED(hr)) {
9595                 ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
9596                    expected, wine_dbgstr_w(received), test_index);
9597                 ok(expected_len == len,
9598                    "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
9599                    expected_len, len, test_index);
9600             }
9601         }
9602     } else {
9603         /* The property wasn't set earlier, so it should return whatever
9604          * the base IUri contains (if anything).
9605          */
9606         IUri *uri = NULL;
9607         hr = IUriBuilder_GetIUri(builder, &uri);
9608         ok(hr == S_OK,
9609             "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9610             hr, S_OK, test_index);
9611         if(SUCCEEDED(hr)) {
9612             if(!uri) {
9613                 received = (void*) 0xdeadbeef;
9614                 len = -1;
9615 
9616                 hr = IUriBuilder_GetPath(builder, &len, &received);
9617                 ok(hr == S_FALSE,
9618                     "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9619                     hr, S_FALSE, test_index);
9620                 if(SUCCEEDED(hr)) {
9621                     ok(!len, "Error: Expected len to be 0, but was %d instead on uri_builder_tests[%d].\n",
9622                         len, test_index);
9623                     ok(!received, "Error: Expected received to be NULL, but was %p instead on uri_builder_tests[%d].\n",
9624                         received, test_index);
9625                 }
9626             } else {
9627                 BOOL has_prop = FALSE;
9628                 BSTR expected = NULL;
9629 
9630                 hr = IUri_GetPath(uri, &expected);
9631                 ok(SUCCEEDED(hr),
9632                     "Error: Expected IUri_GetPath to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
9633                     hr, test_index);
9634                 has_prop = hr == S_OK;
9635 
9636                 hr = IUriBuilder_GetPath(builder, &len, &received);
9637                 if(has_prop) {
9638                     ok(hr == S_OK,
9639                         "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9640                         hr, S_OK, test_index);
9641                     if(SUCCEEDED(hr)) {
9642                         ok(!lstrcmpW(expected, received),
9643                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].\n",
9644                             wine_dbgstr_w(expected), wine_dbgstr_w(received), test_index);
9645                         ok(lstrlenW(expected) == len,
9646                             "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
9647                             lstrlenW(expected), len, test_index);
9648                     }
9649                 } else {
9650                     ok(hr == S_FALSE,
9651                         "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9652                         hr, S_FALSE, test_index);
9653                     if(SUCCEEDED(hr)) {
9654                         ok(!received, "Error: Expected received to be NULL on uri_builder_tests[%d].\n", test_index);
9655                         ok(!len, "Error: Expected the length to be 0, but was %d instead on uri_builder_tests[%d].\n",
9656                             len, test_index);
9657                     }
9658                 }
9659                 SysFreeString(expected);
9660             }
9661         }
9662         if(uri) IUri_Release(uri);
9663     }
9664 }
9665 
test_IUriBuilder_GetPort(IUriBuilder * builder,const uri_builder_test * test,DWORD test_index)9666 static void test_IUriBuilder_GetPort(IUriBuilder *builder, const uri_builder_test *test,
9667                                      DWORD test_index) {
9668     HRESULT hr;
9669     BOOL has_port = FALSE;
9670     DWORD received = -1;
9671 
9672     if(test->port_prop.change) {
9673         hr = IUriBuilder_GetPort(builder, &has_port, &received);
9674         todo_wine_if(test->port_prop.todo) {
9675             ok(hr == S_OK,
9676                 "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9677                 hr, S_OK, test_index);
9678             if(SUCCEEDED(hr)) {
9679                 ok(has_port == test->port_prop.set,
9680                    "Error: Expected has_port to be %d, but was %d instead on uri_builder_tests[%d].\n",
9681                    test->port_prop.set, has_port, test_index);
9682                 ok(received == test->port_prop.value,
9683                    "Error: Expected port to be %d, but was %d instead on uri_builder_tests[%d].\n",
9684                    test->port_prop.value, received, test_index);
9685             }
9686         }
9687     } else {
9688         IUri *uri = NULL;
9689 
9690         hr = IUriBuilder_GetIUri(builder, &uri);
9691         ok(hr == S_OK,
9692             "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9693             hr, S_OK, test_index);
9694         if(SUCCEEDED(hr)) {
9695             if(!uri) {
9696                 hr = IUriBuilder_GetPort(builder, &has_port, &received);
9697                 ok(hr == S_OK,
9698                     "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9699                     hr, S_OK, test_index);
9700                 if(SUCCEEDED(hr)) {
9701                     ok(has_port == FALSE,
9702                         "Error: Expected has_port to be FALSE, but was %d instead on uri_builder_tests[%d].\n",
9703                         has_port, test_index);
9704                     ok(!received, "Error: Expected received to be 0, but was %d instead on uri_builder_tests[%d].\n",
9705                         received, test_index);
9706                 }
9707             } else {
9708                 DWORD expected;
9709 
9710                 hr = IUri_GetPort(uri, &expected);
9711                 ok(SUCCEEDED(hr),
9712                     "Error: Expected IUri_Port to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
9713                     hr, test_index);
9714 
9715                 hr = IUriBuilder_GetPort(builder, &has_port, &received);
9716                 ok(hr == S_OK,
9717                     "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9718                     hr, S_OK, test_index);
9719                 if(SUCCEEDED(hr)) {
9720                     ok(!has_port,
9721                         "Error: Expected has_port to be FALSE but was TRUE instead on uri_builder_tests[%d].\n",
9722                         test_index);
9723                     ok(received == expected,
9724                         "Error: Expected received to be %d, but was %d instead on uri_builder_tests[%d].\n",
9725                         expected, received, test_index);
9726                 }
9727             }
9728         }
9729         if(uri) IUri_Release(uri);
9730     }
9731 }
9732 
test_IUriBuilder_GetQuery(IUriBuilder * builder,const uri_builder_test * test,DWORD test_index)9733 static void test_IUriBuilder_GetQuery(IUriBuilder *builder, const uri_builder_test *test,
9734                                       DWORD test_index) {
9735     HRESULT hr;
9736     DWORD i;
9737     LPCWSTR received = NULL;
9738     DWORD len = -1;
9739     const uri_builder_property *prop = NULL;
9740 
9741     /* Check if the property was set earlier. */
9742     for(i = 0; i < ARRAY_SIZE(test->properties); ++i) {
9743         if(test->properties[i].change && test->properties[i].property == Uri_PROPERTY_QUERY)
9744             prop = &(test->properties[i]);
9745     }
9746 
9747     if(prop) {
9748         /* Use expected_value unless it's NULL, then use value. */
9749         LPCSTR expected = prop->expected_value ? prop->expected_value : prop->value;
9750         DWORD expected_len = expected ? strlen(expected) : 0;
9751         hr = IUriBuilder_GetQuery(builder, &len, &received);
9752         todo_wine_if(prop->todo) {
9753             ok(hr == (expected ? S_OK : S_FALSE),
9754                 "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9755                 hr, (expected ? S_OK : S_FALSE), test_index);
9756             if(SUCCEEDED(hr)) {
9757                 ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
9758                    expected, wine_dbgstr_w(received), test_index);
9759                 ok(expected_len == len,
9760                    "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
9761                    expected_len, len, test_index);
9762             }
9763         }
9764     } else {
9765         /* The property wasn't set earlier, so it should return whatever
9766          * the base IUri contains (if anything).
9767          */
9768         IUri *uri = NULL;
9769         hr = IUriBuilder_GetIUri(builder, &uri);
9770         ok(hr == S_OK,
9771             "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9772             hr, S_OK, test_index);
9773         if(SUCCEEDED(hr)) {
9774             if(!uri) {
9775                 received = (void*) 0xdeadbeef;
9776                 len = -1;
9777 
9778                 hr = IUriBuilder_GetQuery(builder, &len, &received);
9779                 ok(hr == S_FALSE,
9780                     "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9781                     hr, S_FALSE, test_index);
9782                 if(SUCCEEDED(hr)) {
9783                     ok(!len, "Error: Expected len to be 0, but was %d instead on uri_builder_tests[%d].\n",
9784                         len, test_index);
9785                     ok(!received, "Error: Expected received to be NULL, but was %p instead on uri_builder_tests[%d].\n",
9786                         received, test_index);
9787                 }
9788             } else {
9789                 BOOL has_prop = FALSE;
9790                 BSTR expected = NULL;
9791 
9792                 hr = IUri_GetQuery(uri, &expected);
9793                 ok(SUCCEEDED(hr),
9794                     "Error: Expected IUri_GetQuery to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
9795                     hr, test_index);
9796                 has_prop = hr == S_OK;
9797 
9798                 hr = IUriBuilder_GetQuery(builder, &len, &received);
9799                 if(has_prop) {
9800                     ok(hr == S_OK,
9801                         "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9802                         hr, S_OK, test_index);
9803                     if(SUCCEEDED(hr)) {
9804                         ok(!lstrcmpW(expected, received),
9805                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].\n",
9806                             wine_dbgstr_w(expected), wine_dbgstr_w(received), test_index);
9807                         ok(lstrlenW(expected) == len,
9808                             "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
9809                             lstrlenW(expected), len, test_index);
9810                     }
9811                 } else {
9812                     ok(hr == S_FALSE,
9813                         "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9814                         hr, S_FALSE, test_index);
9815                     if(SUCCEEDED(hr)) {
9816                         ok(!received, "Error: Expected received to be NULL on uri_builder_tests[%d].\n", test_index);
9817                         ok(!len, "Error: Expected the length to be 0, but was %d instead on uri_builder_tests[%d].\n",
9818                             len, test_index);
9819                     }
9820                 }
9821                 SysFreeString(expected);
9822             }
9823         }
9824         if(uri) IUri_Release(uri);
9825     }
9826 }
9827 
test_IUriBuilder_GetSchemeName(IUriBuilder * builder,const uri_builder_test * test,DWORD test_index)9828 static void test_IUriBuilder_GetSchemeName(IUriBuilder *builder, const uri_builder_test *test,
9829                                            DWORD test_index) {
9830     HRESULT hr;
9831     DWORD i;
9832     LPCWSTR received = NULL;
9833     DWORD len = -1;
9834     const uri_builder_property *prop = NULL;
9835 
9836     /* Check if the property was set earlier. */
9837     for(i = 0; i < ARRAY_SIZE(test->properties); ++i) {
9838         if(test->properties[i].change && test->properties[i].property == Uri_PROPERTY_SCHEME_NAME)
9839             prop = &(test->properties[i]);
9840     }
9841 
9842     if(prop) {
9843         /* Use expected_value unless it's NULL, then use value. */
9844         LPCSTR expected = prop->expected_value ? prop->expected_value : prop->value;
9845         DWORD expected_len = expected ? strlen(expected) : 0;
9846         hr = IUriBuilder_GetSchemeName(builder, &len, &received);
9847         todo_wine_if(prop->todo) {
9848             ok(hr == (expected ? S_OK : S_FALSE),
9849                 "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9850                 hr, (expected ? S_OK : S_FALSE), test_index);
9851             if(SUCCEEDED(hr)) {
9852                 ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
9853                    expected, wine_dbgstr_w(received), test_index);
9854                 ok(expected_len == len,
9855                    "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
9856                    expected_len, len, test_index);
9857             }
9858         }
9859     } else {
9860         /* The property wasn't set earlier, so it should return whatever
9861          * the base IUri contains (if anything).
9862          */
9863         IUri *uri = NULL;
9864         hr = IUriBuilder_GetIUri(builder, &uri);
9865         ok(hr == S_OK,
9866             "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9867             hr, S_OK, test_index);
9868         if(SUCCEEDED(hr)) {
9869             if(!uri) {
9870                 received = (void*) 0xdeadbeef;
9871                 len = -1;
9872 
9873                 hr = IUriBuilder_GetSchemeName(builder, &len, &received);
9874                 ok(hr == S_FALSE,
9875                     "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9876                     hr, S_FALSE, test_index);
9877                 if(SUCCEEDED(hr)) {
9878                     ok(!len, "Error: Expected len to be 0, but was %d instead on uri_builder_tests[%d].\n",
9879                         len, test_index);
9880                     ok(!received, "Error: Expected received to be NULL, but was %p instead on uri_builder_tests[%d].\n",
9881                         received, test_index);
9882                 }
9883             } else {
9884                 BOOL has_prop = FALSE;
9885                 BSTR expected = NULL;
9886 
9887                 hr = IUri_GetSchemeName(uri, &expected);
9888                 ok(SUCCEEDED(hr),
9889                     "Error: Expected IUri_GetSchemeName to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
9890                     hr, test_index);
9891                 has_prop = hr == S_OK;
9892 
9893                 hr = IUriBuilder_GetSchemeName(builder, &len, &received);
9894                 if(has_prop) {
9895                     ok(hr == S_OK,
9896                         "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9897                         hr, S_OK, test_index);
9898                     if(SUCCEEDED(hr)) {
9899                         ok(!lstrcmpW(expected, received),
9900                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].\n",
9901                             wine_dbgstr_w(expected), wine_dbgstr_w(received), test_index);
9902                         ok(lstrlenW(expected) == len,
9903                             "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
9904                             lstrlenW(expected), len, test_index);
9905                     }
9906                 } else {
9907                     ok(hr == S_FALSE,
9908                         "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9909                         hr, S_FALSE, test_index);
9910                     if(SUCCEEDED(hr)) {
9911                         ok(!received, "Error: Expected received to be NULL on uri_builder_tests[%d].\n", test_index);
9912                         ok(!len, "Error: Expected the length to be 0, but was %d instead on uri_builder_tests[%d].\n",
9913                             len, test_index);
9914                     }
9915                 }
9916                 SysFreeString(expected);
9917             }
9918         }
9919         if(uri) IUri_Release(uri);
9920     }
9921 }
9922 
test_IUriBuilder_GetUserName(IUriBuilder * builder,const uri_builder_test * test,DWORD test_index)9923 static void test_IUriBuilder_GetUserName(IUriBuilder *builder, const uri_builder_test *test,
9924                                          DWORD test_index) {
9925     HRESULT hr;
9926     DWORD i;
9927     LPCWSTR received = NULL;
9928     DWORD len = -1;
9929     const uri_builder_property *prop = NULL;
9930 
9931     /* Check if the property was set earlier. */
9932     for(i = 0; i < ARRAY_SIZE(test->properties); ++i) {
9933         if(test->properties[i].change && test->properties[i].property == Uri_PROPERTY_USER_NAME)
9934             prop = &(test->properties[i]);
9935     }
9936 
9937     if(prop && prop->value && *prop->value) {
9938         /* Use expected_value unless it's NULL, then use value. */
9939         LPCSTR expected = prop->expected_value ? prop->expected_value : prop->value;
9940         DWORD expected_len = expected ? strlen(expected) : 0;
9941         hr = IUriBuilder_GetUserName(builder, &len, &received);
9942         todo_wine_if(prop->todo) {
9943             ok(hr == (expected ? S_OK : S_FALSE),
9944                 "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9945                 hr, (expected ? S_OK : S_FALSE), test_index);
9946             if(SUCCEEDED(hr)) {
9947                 ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
9948                    expected, wine_dbgstr_w(received), test_index);
9949                 ok(expected_len == len,
9950                    "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
9951                    expected_len, len, test_index);
9952             }
9953         }
9954     } else {
9955         /* The property wasn't set earlier, so it should return whatever
9956          * the base IUri contains (if anything).
9957          */
9958         IUri *uri = NULL;
9959         hr = IUriBuilder_GetIUri(builder, &uri);
9960         ok(hr == S_OK,
9961             "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9962             hr, S_OK, test_index);
9963         if(SUCCEEDED(hr)) {
9964             if(!uri) {
9965                 received = (void*) 0xdeadbeef;
9966                 len = -1;
9967 
9968                 hr = IUriBuilder_GetUserName(builder, &len, &received);
9969                 ok(hr == S_FALSE,
9970                     "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9971                     hr, S_FALSE, test_index);
9972                 if(SUCCEEDED(hr)) {
9973                     ok(!len, "Error: Expected len to be 0, but was %d instead on uri_builder_tests[%d].\n",
9974                         len, test_index);
9975                     ok(!received, "Error: Expected received to be NULL, but was %p instead on uri_builder_tests[%d].\n",
9976                         received, test_index);
9977                 }
9978             } else {
9979                 BSTR expected = NULL;
9980                 BOOL has_prop = FALSE;
9981 
9982                 hr = IUri_GetUserName(uri, &expected);
9983                 ok(SUCCEEDED(hr),
9984                     "Error: Expected IUri_GetUserName to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
9985                     hr, test_index);
9986                 has_prop = hr == S_OK;
9987 
9988                 hr = IUriBuilder_GetUserName(builder, &len, &received);
9989                 if(has_prop) {
9990                     ok(hr == S_OK,
9991                         "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9992                         hr, S_OK, test_index);
9993                     if(SUCCEEDED(hr)) {
9994                         ok(!lstrcmpW(expected, received),
9995                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].\n",
9996                             wine_dbgstr_w(expected), wine_dbgstr_w(received), test_index);
9997                         ok(lstrlenW(expected) == len,
9998                             "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
9999                             lstrlenW(expected), len, test_index);
10000                     }
10001                 } else {
10002                     ok(hr == S_FALSE,
10003                         "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
10004                         hr, S_FALSE, test_index);
10005                     if(SUCCEEDED(hr)) {
10006                         ok(!received, "Error: Expected received to be NULL on uri_builder_tests[%d].\n", test_index);
10007                         ok(!len, "Error: Expected the length to be 0, but was %d instead on uri_builder_tests[%d].\n",
10008                             len, test_index);
10009                     }
10010                 }
10011                 SysFreeString(expected);
10012             }
10013         }
10014         if(uri) IUri_Release(uri);
10015     }
10016 }
10017 
10018 /* Tests IUriBuilder functions. */
test_IUriBuilder(void)10019 static void test_IUriBuilder(void) {
10020     HRESULT hr;
10021     IUriBuilder *builder;
10022     DWORD i;
10023 
10024     for(i = 0; i < ARRAY_SIZE(uri_builder_tests); ++i) {
10025         IUri *uri = NULL;
10026         uri_builder_test test = uri_builder_tests[i];
10027         LPWSTR uriW = NULL;
10028 
10029         if(test.uri) {
10030             uriW = a2w(test.uri);
10031             hr = pCreateUri(uriW, test.create_flags, 0, &uri);
10032             ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
10033                 hr, S_OK, i);
10034             if(FAILED(hr)) continue;
10035         }
10036         hr = pCreateIUriBuilder(uri, 0, 0, &builder);
10037         todo_wine_if(test.create_builder_todo)
10038             ok(hr == test.create_builder_expected,
10039                 "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
10040                 hr, test.create_builder_expected, i);
10041         if(SUCCEEDED(hr)) {
10042             DWORD j;
10043             BOOL modified = FALSE, received = FALSE;
10044 
10045             /* Perform all the string property changes. */
10046             for(j = 0; j < URI_BUILDER_STR_PROPERTY_COUNT; ++j) {
10047                 uri_builder_property prop = test.properties[j];
10048                 if(prop.change) {
10049                     change_property(builder, &prop, i);
10050                     if(prop.property != Uri_PROPERTY_SCHEME_NAME &&
10051                        prop.property != Uri_PROPERTY_HOST)
10052                         modified = TRUE;
10053                     else if(prop.value && *prop.value)
10054                         modified = TRUE;
10055                     else if(prop.value && !*prop.value && prop.property == Uri_PROPERTY_HOST)
10056                         /* Host name property can't be NULL, but it can be empty. */
10057                         modified = TRUE;
10058                 }
10059             }
10060 
10061             if(test.port_prop.change) {
10062                 hr = IUriBuilder_SetPort(builder, test.port_prop.set, test.port_prop.value);
10063                 modified = TRUE;
10064                 todo_wine_if(test.port_prop.todo)
10065                     ok(hr == test.port_prop.expected,
10066                         "Error: IUriBuilder_SetPort returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
10067                         hr, test.port_prop.expected, i);
10068             }
10069 
10070             hr = IUriBuilder_HasBeenModified(builder, &received);
10071             ok(hr == S_OK,
10072                 "Error IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
10073                 hr, S_OK, i);
10074             if(SUCCEEDED(hr))
10075                 ok(received == modified,
10076                     "Error: Expected received to be %d but was %d instead on uri_builder_tests[%d].\n",
10077                     modified, received, i);
10078 
10079             /* Test the "Get*" functions. */
10080             test_IUriBuilder_GetFragment(builder, &test, i);
10081             test_IUriBuilder_GetHost(builder, &test, i);
10082             test_IUriBuilder_GetPassword(builder, &test, i);
10083             test_IUriBuilder_GetPath(builder, &test, i);
10084             test_IUriBuilder_GetPort(builder, &test, i);
10085             test_IUriBuilder_GetQuery(builder, &test, i);
10086             test_IUriBuilder_GetSchemeName(builder, &test, i);
10087             test_IUriBuilder_GetUserName(builder, &test, i);
10088 
10089             test_IUriBuilder_CreateUri(builder, &test, i);
10090             test_IUriBuilder_CreateUriSimple(builder, &test, i);
10091             test_IUriBuilder_CreateUriWithFlags(builder, &test, i);
10092         }
10093         if(builder) IUriBuilder_Release(builder);
10094         if(uri) IUri_Release(uri);
10095         heap_free(uriW);
10096     }
10097 }
10098 
test_IUriBuilder_HasBeenModified(void)10099 static void test_IUriBuilder_HasBeenModified(void) {
10100     HRESULT hr;
10101     IUriBuilder *builder = NULL;
10102 
10103     hr = pCreateIUriBuilder(NULL, 0, 0, &builder);
10104     ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
10105     if(SUCCEEDED(hr)) {
10106         static const WCHAR hostW[] = {'g','o','o','g','l','e','.','c','o','m',0};
10107         IUri *uri = NULL;
10108         BOOL received;
10109 
10110         hr = IUriBuilder_HasBeenModified(builder, NULL);
10111         ok(hr == E_POINTER, "Error: IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x.\n",
10112             hr, E_POINTER);
10113 
10114         hr = IUriBuilder_SetHost(builder, hostW);
10115         ok(hr == S_OK, "Error: IUriBuilder_SetHost returned 0x%08x, expected 0x%08x.\n",
10116             hr, S_OK);
10117 
10118         hr = IUriBuilder_HasBeenModified(builder, &received);
10119         ok(hr == S_OK, "Error: IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x.\n",
10120             hr, S_OK);
10121         if(SUCCEEDED(hr))
10122             ok(received == TRUE, "Error: Expected received to be TRUE.\n");
10123 
10124         hr = pCreateUri(http_urlW, 0, 0, &uri);
10125         ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
10126         if(SUCCEEDED(hr)) {
10127             LPCWSTR prop;
10128             DWORD len = -1;
10129 
10130             hr = IUriBuilder_SetIUri(builder, uri);
10131             ok(hr == S_OK, "Error: IUriBuilder_SetIUri returned 0x%08x, expected 0x%08x.\n",
10132                 hr, S_OK);
10133 
10134             hr = IUriBuilder_HasBeenModified(builder, &received);
10135             ok(hr == S_OK, "Error: IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x.\n",
10136                 hr, S_OK);
10137             if(SUCCEEDED(hr))
10138                 ok(received == FALSE, "Error: Expected received to be FALSE.\n");
10139 
10140             /* Test what happens with you call SetIUri with the same IUri again. */
10141             hr = IUriBuilder_SetHost(builder, hostW);
10142             ok(hr == S_OK, "Error: IUriBuilder_SetHost returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
10143 
10144             hr = IUriBuilder_HasBeenModified(builder, &received);
10145             ok(hr == S_OK, "Error: IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x.\n",
10146                 hr, S_OK);
10147             if(SUCCEEDED(hr))
10148                 ok(received == TRUE, "Error: Expected received to be TRUE.\n");
10149 
10150             hr = IUriBuilder_SetIUri(builder, uri);
10151             ok(hr == S_OK, "Error: IUriBuilder_SetIUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
10152 
10153             /* IUriBuilder already had 'uri' as its IUri property and so Windows doesn't
10154              * reset any of the changes that were made to the IUriBuilder.
10155              */
10156             hr = IUriBuilder_HasBeenModified(builder, &received);
10157             ok(hr == S_OK, "Error: IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
10158             if(SUCCEEDED(hr))
10159                 ok(received == TRUE, "Error: Expected received to be TRUE.\n");
10160 
10161             hr = IUriBuilder_GetHost(builder, &len, &prop);
10162             ok(hr == S_OK, "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
10163             if(SUCCEEDED(hr)) {
10164                 ok(!lstrcmpW(prop, hostW), "Error: Expected %s but got %s instead.\n",
10165                     wine_dbgstr_w(hostW), wine_dbgstr_w(prop));
10166                 ok(len == lstrlenW(hostW), "Error: Expected len to be %d, but was %d instead.\n",
10167                     lstrlenW(hostW), len);
10168             }
10169 
10170             hr = IUriBuilder_SetIUri(builder, NULL);
10171             ok(hr == S_OK, "Error: IUriBuilder_SetIUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
10172 
10173             hr = IUriBuilder_SetHost(builder, hostW);
10174             ok(hr == S_OK, "Error: IUriBuilder_SetHost returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
10175             hr = IUriBuilder_HasBeenModified(builder, &received);
10176             ok(hr == S_OK, "Error: IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x.\n",
10177                 hr, S_OK);
10178             if(SUCCEEDED(hr))
10179                 ok(received == TRUE, "Error: Expected received to be TRUE.\n");
10180 
10181             hr = IUriBuilder_SetIUri(builder, NULL);
10182             ok(hr == S_OK, "Error: IUriBuilder_SetIUri returned 0x%08x, expected 0x%09x.\n", hr, S_OK);
10183 
10184             hr = IUriBuilder_HasBeenModified(builder, &received);
10185             ok(hr == S_OK, "Error: IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x.\n",
10186                 hr, S_OK);
10187             if(SUCCEEDED(hr))
10188                 ok(received == TRUE, "Error: Expected received to be TRUE.\n");
10189 
10190             hr = IUriBuilder_GetHost(builder, &len, &prop);
10191             ok(hr == S_OK, "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
10192             if(SUCCEEDED(hr)) {
10193                 ok(!lstrcmpW(prop, hostW), "Error: Expected %s but got %s instead.\n",
10194                     wine_dbgstr_w(hostW), wine_dbgstr_w(prop));
10195                 ok(len == lstrlenW(hostW), "Error: Expected len to %d, but was %d instead.\n",
10196                     lstrlenW(hostW), len);
10197             }
10198         }
10199         if(uri) IUri_Release(uri);
10200     }
10201     if(builder) IUriBuilder_Release(builder);
10202 }
10203 
10204 /* Test IUriBuilder {Get,Set}IUri functions. */
test_IUriBuilder_IUriProperty(void)10205 static void test_IUriBuilder_IUriProperty(void) {
10206     IUriBuilder *builder = NULL;
10207     HRESULT hr;
10208 
10209     hr = pCreateIUriBuilder(NULL, 0, 0, &builder);
10210     ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
10211     if(SUCCEEDED(hr)) {
10212         IUri *uri = NULL;
10213 
10214         hr = IUriBuilder_GetIUri(builder, NULL);
10215         ok(hr == E_POINTER, "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x.\n",
10216             hr, E_POINTER);
10217 
10218         hr = pCreateUri(http_urlW, 0, 0, &uri);
10219         if(SUCCEEDED(hr)) {
10220             IUri *test = NULL;
10221             ULONG cur_count, orig_count;
10222 
10223             /* IUriBuilder doesn't clone the IUri, it use the same IUri. */
10224             orig_count = get_refcnt(uri);
10225             hr = IUriBuilder_SetIUri(builder, uri);
10226             cur_count = get_refcnt(uri);
10227             if(SUCCEEDED(hr))
10228                 ok(cur_count == orig_count+1, "Error: Expected uri ref count to be %d, but was %d instead.\n",
10229                     orig_count+1, cur_count);
10230 
10231             hr = IUriBuilder_SetIUri(builder, NULL);
10232             cur_count = get_refcnt(uri);
10233             if(SUCCEEDED(hr))
10234                 ok(cur_count == orig_count, "Error: Expected uri ref count to be %d, but was %d instead.\n",
10235                     orig_count, cur_count);
10236 
10237             /* CreateUri* functions will return back the same IUri if nothing has changed. */
10238             hr = IUriBuilder_SetIUri(builder, uri);
10239             ok(hr == S_OK, "Error: IUriBuilder_SetIUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
10240             orig_count = get_refcnt(uri);
10241 
10242             hr = IUriBuilder_CreateUri(builder, 0, 0, 0, &test);
10243             ok(hr == S_OK, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
10244             if(SUCCEEDED(hr)) {
10245                 cur_count = get_refcnt(uri);
10246                 ok(cur_count == orig_count+1, "Error: Expected uri ref count to be %d, but was %d instead.\n",
10247                     orig_count+1, cur_count);
10248                 ok(test == uri, "Error: Expected test to be %p, but was %p instead.\n",
10249                     uri, test);
10250             }
10251             if(test) IUri_Release(test);
10252 
10253             test = NULL;
10254             hr = IUriBuilder_CreateUri(builder, -1, 0, 0, &test);
10255             ok(hr == S_OK, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
10256             if(SUCCEEDED(hr)) {
10257                 cur_count = get_refcnt(uri);
10258                 ok(cur_count == orig_count+1, "Error: Expected uri ref count to be %d, but was %d instead.\n",
10259                     orig_count+1, cur_count);
10260                 ok(test == uri, "Error: Expected test to be %p, but was %p instead.\n", uri, test);
10261             }
10262             if(test) IUri_Release(test);
10263 
10264             /* Doesn't return the same IUri, if the flag combination is different then the one that created
10265              * the base IUri.
10266              */
10267             test = NULL;
10268             hr = IUriBuilder_CreateUri(builder, Uri_CREATE_ALLOW_RELATIVE, 0, 0, &test);
10269             ok(hr == S_OK, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
10270             if(SUCCEEDED(hr))
10271                 ok(test != uri, "Error: Wasn't expecting 'test' to be 'uri'\n");
10272 
10273             if(test) IUri_Release(test);
10274 
10275             /* Still returns the same IUri, even though the base one wasn't created with CREATE_CANONICALIZE
10276              * explicitly set (because it's a default flag).
10277              */
10278             test = NULL;
10279             hr = IUriBuilder_CreateUri(builder, Uri_CREATE_CANONICALIZE, 0, 0, &test);
10280             ok(hr == S_OK, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
10281             if(SUCCEEDED(hr)) {
10282                 cur_count = get_refcnt(uri);
10283                 ok(cur_count == orig_count+1, "Error: Expected uri ref count to be %d, but was %d instead.\n",
10284                     orig_count+1, cur_count);
10285                 ok(test == uri, "Error: Expected 'test' to be %p, but was %p instead.\n", uri, test);
10286             }
10287             if(test) IUri_Release(test);
10288 
10289             test = NULL;
10290             hr = IUriBuilder_CreateUriSimple(builder, 0, 0, &test);
10291             ok(hr == S_OK, "Error: IUriBuilder_CreateUriSimple returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
10292             if(SUCCEEDED(hr)) {
10293                 cur_count = get_refcnt(uri);
10294                 ok(cur_count == orig_count+1, "Error: Expected uri ref count to be %d, but was %d instead.\n",
10295                     orig_count+1, cur_count);
10296                 ok(test == uri, "Error: Expected test to be %p, but was %p instead.\n", uri, test);
10297             }
10298             if(test) IUri_Release(test);
10299 
10300             test = NULL;
10301             hr = IUriBuilder_CreateUriWithFlags(builder, 0, 0, 0, 0, &test);
10302             ok(hr == S_OK, "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x.\n",
10303                 hr, S_OK);
10304             if(SUCCEEDED(hr)) {
10305                 cur_count = get_refcnt(uri);
10306                 ok(cur_count == orig_count+1, "Error: Expected uri ref count to be %d, but was %d instead.\n",
10307                     orig_count+1, cur_count);
10308                 ok(test == uri, "Error: Expected test to be %p, but was %p instead.\n", uri, test);
10309             }
10310             if(test) IUri_Release(test);
10311 
10312             /* Doesn't return the same IUri, if the flag combination is different then the one that created
10313              * the base IUri.
10314              */
10315             test = NULL;
10316             hr = IUriBuilder_CreateUriWithFlags(builder, Uri_CREATE_ALLOW_RELATIVE, 0, 0, 0, &test);
10317             ok(hr == S_OK, "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
10318             if(SUCCEEDED(hr))
10319                 ok(test != uri, "Error: Wasn't expecting 'test' to be 'uri'\n");
10320 
10321             if(test) IUri_Release(test);
10322 
10323             /* Still returns the same IUri, even though the base one wasn't created with CREATE_CANONICALIZE
10324              * explicitly set (because it's a default flag).
10325              */
10326             test = NULL;
10327             hr = IUriBuilder_CreateUriWithFlags(builder, Uri_CREATE_CANONICALIZE, 0, 0, 0, &test);
10328             ok(hr == S_OK, "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
10329             if(SUCCEEDED(hr)) {
10330                 cur_count = get_refcnt(uri);
10331                 ok(cur_count == orig_count+1, "Error: Expected uri ref count to be %d, but was %d instead.\n",
10332                     orig_count+1, cur_count);
10333                 ok(test == uri, "Error: Expected 'test' to be %p, but was %p instead.\n", uri, test);
10334             }
10335             if(test) IUri_Release(test);
10336         }
10337         if(uri) IUri_Release(uri);
10338     }
10339     if(builder) IUriBuilder_Release(builder);
10340 }
10341 
test_IUriBuilder_RemoveProperties(void)10342 static void test_IUriBuilder_RemoveProperties(void) {
10343     IUriBuilder *builder = NULL;
10344     HRESULT hr;
10345     DWORD i;
10346 
10347     hr = pCreateIUriBuilder(NULL, 0, 0, &builder);
10348     ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
10349     if(SUCCEEDED(hr)) {
10350         /* Properties that can't be removed. */
10351         const DWORD invalid = Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_RAW_URI|Uri_HAS_HOST_TYPE|
10352                               Uri_HAS_SCHEME|Uri_HAS_ZONE;
10353 
10354         for(i = Uri_PROPERTY_STRING_START; i <= Uri_PROPERTY_DWORD_LAST; ++i) {
10355             hr = IUriBuilder_RemoveProperties(builder, i << 1);
10356             if((i << 1) & invalid) {
10357                 ok(hr == E_INVALIDARG,
10358                     "Error: IUriBuilder_RemoveProperties returned 0x%08x, expected 0x%08x with prop=%d.\n",
10359                     hr, E_INVALIDARG, i);
10360             } else {
10361                 ok(hr == S_OK,
10362                     "Error: IUriBuilder_RemoveProperties returned 0x%08x, expected 0x%08x with prop=%d.\n",
10363                     hr, S_OK, i);
10364             }
10365         }
10366 
10367         /* Also doesn't accept anything that's outside the range of the
10368          * Uri_HAS flags.
10369          */
10370         hr = IUriBuilder_RemoveProperties(builder, (Uri_PROPERTY_DWORD_LAST+1) << 1);
10371         ok(hr == E_INVALIDARG, "Error: IUriBuilder_RemoveProperties returned 0x%08x, expected 0x%08x.\n",
10372             hr, E_INVALIDARG);
10373     }
10374     if(builder) IUriBuilder_Release(builder);
10375 
10376     for(i = 0; i < ARRAY_SIZE(uri_builder_remove_tests); ++i) {
10377         uri_builder_remove_test test = uri_builder_remove_tests[i];
10378         IUri *uri = NULL;
10379         LPWSTR uriW;
10380 
10381         uriW = a2w(test.uri);
10382         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
10383         if(SUCCEEDED(hr)) {
10384             builder = NULL;
10385 
10386             hr = pCreateIUriBuilder(uri, 0, 0, &builder);
10387             todo_wine_if(test.create_builder_todo)
10388                 ok(hr == test.create_builder_expected,
10389                     "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x on test %d.\n",
10390                     hr, test.create_builder_expected, i);
10391 
10392             if(SUCCEEDED(hr)) {
10393                 hr = IUriBuilder_RemoveProperties(builder, test.remove_properties);
10394                 todo_wine_if(test.remove_todo)
10395                     ok(hr == test.remove_expected,
10396                         "Error: IUriBuilder returned 0x%08x, expected 0x%08x on test %d.\n",
10397                         hr, test.remove_expected, i);
10398                 if(SUCCEEDED(hr)) {
10399                     IUri *result = NULL;
10400 
10401                     hr = IUriBuilder_CreateUri(builder, test.expected_flags, 0, 0, &result);
10402                     todo_wine_if(test.expected_todo)
10403                         ok(hr == test.expected_hres,
10404                             "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x on test %d.\n",
10405                             hr, test.expected_hres, i);
10406                     if(SUCCEEDED(hr)) {
10407                         BSTR received = NULL;
10408 
10409                         hr = IUri_GetAbsoluteUri(result, &received);
10410                         ok(hr == S_OK, "Error: Expected S_OK, but got 0x%08x instead.\n", hr);
10411                         ok(!strcmp_aw(test.expected_uri, received),
10412                             "Error: Expected %s but got %s instead on test %d.\n",
10413                             test.expected_uri, wine_dbgstr_w(received), i);
10414                         SysFreeString(received);
10415                     }
10416                     if(result) IUri_Release(result);
10417                 }
10418             }
10419             if(builder) IUriBuilder_Release(builder);
10420         }
10421         if(uri) IUri_Release(uri);
10422         heap_free(uriW);
10423     }
10424 }
10425 
test_IUriBuilder_Misc(void)10426 static void test_IUriBuilder_Misc(void) {
10427     HRESULT hr;
10428     IUri *uri;
10429 
10430     hr = pCreateUri(http_urlW, 0, 0, &uri);
10431     if(SUCCEEDED(hr)) {
10432         IUriBuilder *builder;
10433 
10434         hr = pCreateIUriBuilder(uri, 0, 0, &builder);
10435         ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
10436         if(SUCCEEDED(hr)) {
10437             BOOL has = -1;
10438             DWORD port = -1;
10439 
10440             hr = IUriBuilder_GetPort(builder, &has, &port);
10441             ok(hr == S_OK, "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
10442             if(SUCCEEDED(hr)) {
10443                 /* 'has' will be set to FALSE, even though uri had a port. */
10444                 ok(has == FALSE, "Error: Expected 'has' to be FALSE, was %d instead.\n", has);
10445                 /* Still sets 'port' to 80. */
10446                 ok(port == 80, "Error: Expected the port to be 80, but, was %d instead.\n", port);
10447             }
10448         }
10449         if(builder) IUriBuilder_Release(builder);
10450     }
10451     if(uri) IUri_Release(uri);
10452 }
10453 
test_IUriBuilderFactory(void)10454 static void test_IUriBuilderFactory(void) {
10455     HRESULT hr;
10456     IUri *uri;
10457     IUriBuilderFactory *factory;
10458     IUriBuilder *builder;
10459 
10460     hr = pCreateUri(http_urlW, 0, 0, &uri);
10461     ok(SUCCEEDED(hr), "Error: CreateUri returned 0x%08x.\n", hr);
10462     if(SUCCEEDED(hr)) {
10463         factory = NULL;
10464         hr = IUri_QueryInterface(uri, &IID_IUriBuilderFactory, (void**)&factory);
10465         ok(hr == S_OK, "Error: Expected S_OK, but got 0x%08x.\n", hr);
10466         ok(factory != NULL, "Error: Expected 'factory' to not be NULL.\n");
10467 
10468         if(SUCCEEDED(hr)) {
10469             builder = (void*) 0xdeadbeef;
10470             hr = IUriBuilderFactory_CreateIUriBuilder(factory, 10, 0, &builder);
10471             ok(hr == E_INVALIDARG, "Error: CreateInitializedIUriBuilder returned 0x%08x, expected 0x%08x.\n",
10472                 hr, E_INVALIDARG);
10473             ok(!builder, "Error: Expected 'builder' to be NULL, but was %p.\n", builder);
10474 
10475             builder = (void*) 0xdeadbeef;
10476             hr = IUriBuilderFactory_CreateIUriBuilder(factory, 0, 10, &builder);
10477             ok(hr == E_INVALIDARG, "Error: CreateInitializedIUriBuilder returned 0x%08x, expected 0x%08x.\n",
10478                 hr, E_INVALIDARG);
10479             ok(!builder, "Error: Expected 'builder' to be NULL, but was %p.\n", builder);
10480 
10481             hr = IUriBuilderFactory_CreateIUriBuilder(factory, 0, 0, NULL);
10482             ok(hr == E_POINTER, "Error: CreateInitializedIUriBuilder returned 0x%08x, expected 0x%08x.\n",
10483                 hr, E_POINTER);
10484 
10485             builder = NULL;
10486             hr = IUriBuilderFactory_CreateIUriBuilder(factory, 0, 0, &builder);
10487             ok(hr == S_OK, "Error: CreateInitializedIUriBuilder returned 0x%08x, expected 0x%08x.\n",
10488                 hr, S_OK);
10489             if(SUCCEEDED(hr)) {
10490                 IUri *tmp = (void*) 0xdeadbeef;
10491                 LPCWSTR result;
10492                 DWORD result_len;
10493 
10494                 hr = IUriBuilder_GetIUri(builder, &tmp);
10495                 ok(hr == S_OK, "Error: GetIUri returned 0x%08x, expected 0x%08x.\n",
10496                     hr, S_OK);
10497                 ok(!tmp, "Error: Expected 'tmp' to be NULL, but was %p instead.\n", tmp);
10498 
10499                 hr = IUriBuilder_GetHost(builder, &result_len, &result);
10500                 ok(hr == S_FALSE, "Error: GetHost returned 0x%08x, expected 0x%08x.\n",
10501                     hr, S_FALSE);
10502             }
10503             if(builder) IUriBuilder_Release(builder);
10504 
10505             builder = (void*) 0xdeadbeef;
10506             hr = IUriBuilderFactory_CreateInitializedIUriBuilder(factory, 10, 0, &builder);
10507             ok(hr == E_INVALIDARG, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n",
10508                 hr, E_INVALIDARG);
10509             ok(!builder, "Error: Expected 'builder' to be NULL, but was %p.\n", builder);
10510 
10511             builder = (void*) 0xdeadbeef;
10512             hr = IUriBuilderFactory_CreateInitializedIUriBuilder(factory, 0, 10, &builder);
10513             ok(hr == E_INVALIDARG, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n",
10514                 hr, E_INVALIDARG);
10515             ok(!builder, "Error: Expected 'builder' to be NULL, but was %p.\n", builder);
10516 
10517             hr = IUriBuilderFactory_CreateInitializedIUriBuilder(factory, 0, 0, NULL);
10518             ok(hr == E_POINTER, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n",
10519                 hr, E_POINTER);
10520 
10521             builder = NULL;
10522             hr = IUriBuilderFactory_CreateInitializedIUriBuilder(factory, 0, 0, &builder);
10523             ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n",
10524                 hr, S_OK);
10525             if(SUCCEEDED(hr)) {
10526                 IUri *tmp = NULL;
10527 
10528                 hr = IUriBuilder_GetIUri(builder, &tmp);
10529                 ok(hr == S_OK, "Error: GetIUri return 0x%08x, expected 0x%08x.\n",
10530                     hr, S_OK);
10531                 ok(tmp == uri, "Error: Expected tmp to be %p, but was %p.\n", uri, tmp);
10532                 if(tmp) IUri_Release(tmp);
10533             }
10534             if(builder) IUriBuilder_Release(builder);
10535         }
10536         if(factory) IUriBuilderFactory_Release(factory);
10537     }
10538     if(uri) IUri_Release(uri);
10539 }
10540 
test_CoInternetCombineIUri(void)10541 static void test_CoInternetCombineIUri(void) {
10542     HRESULT hr;
10543     IUri *base, *relative, *result;
10544     DWORD i;
10545 
10546     base = NULL;
10547     hr = pCreateUri(http_urlW, 0, 0, &base);
10548     ok(SUCCEEDED(hr), "Error: Expected CreateUri to succeed, got 0x%08x.\n", hr);
10549     if(SUCCEEDED(hr)) {
10550         result = (void*) 0xdeadbeef;
10551         hr = pCoInternetCombineIUri(base, NULL, 0, &result, 0);
10552         ok(hr == E_INVALIDARG, "Error: CoInternetCombineIUri returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
10553         ok(!result, "Error: Expected 'result' to be NULL, was %p.\n", result);
10554     }
10555 
10556     relative = NULL;
10557     hr = pCreateUri(http_urlW, 0, 0, &relative);
10558     ok(SUCCEEDED(hr), "Error: Expected CreateUri to succeed, got 0x%08x.\n", hr);
10559     if(SUCCEEDED(hr)) {
10560         result = (void*) 0xdeadbeef;
10561         hr = pCoInternetCombineIUri(NULL, relative, 0, &result, 0);
10562         ok(hr == E_INVALIDARG, "Error: CoInternetCombineIUri returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
10563         ok(!result, "Error: Expected 'result' to be NULL, was %p.\n", result);
10564     }
10565 
10566     hr = pCoInternetCombineIUri(base, relative, 0, NULL, 0);
10567     ok(hr == E_INVALIDARG, "Error: CoInternetCombineIUri returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
10568 
10569     if(base) IUri_Release(base);
10570     if(relative) IUri_Release(relative);
10571 
10572     for(i = 0; i < ARRAY_SIZE(uri_combine_tests); ++i) {
10573         LPWSTR baseW = a2w(uri_combine_tests[i].base_uri);
10574 
10575         hr = pCreateUri(baseW, uri_combine_tests[i].base_create_flags, 0, &base);
10576         ok(SUCCEEDED(hr), "Error: Expected CreateUri to succeed, got 0x%08x on uri_combine_tests[%d].\n", hr, i);
10577         if(SUCCEEDED(hr)) {
10578             LPWSTR relativeW = a2w(uri_combine_tests[i].relative_uri);
10579 
10580             hr = pCreateUri(relativeW, uri_combine_tests[i].relative_create_flags, 0, &relative);
10581             ok(SUCCEEDED(hr), "Error: Expected CreateUri to succeed, got 0x%08x on uri_combine_tests[%d].\n", hr, i);
10582             if(SUCCEEDED(hr)) {
10583                 result = NULL;
10584 
10585                 hr = pCoInternetCombineIUri(base, relative, uri_combine_tests[i].combine_flags, &result, 0);
10586                 todo_wine_if(uri_combine_tests[i].todo)
10587                     ok(hr == uri_combine_tests[i].expected,
10588                         "Error: CoInternetCombineIUri returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].\n",
10589                         hr, uri_combine_tests[i]. expected, i);
10590                 if(SUCCEEDED(hr)) {
10591                     DWORD j;
10592 
10593                     for(j = 0; j < ARRAY_SIZE(uri_combine_tests[i].str_props); ++j) {
10594                         uri_combine_str_property prop = uri_combine_tests[i].str_props[j];
10595                         BSTR received;
10596 
10597                         hr = IUri_GetPropertyBSTR(result, j, &received, 0);
10598                         todo_wine_if(prop.todo) {
10599                             ok(hr == prop.expected,
10600                                 "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].str_props[%d].\n",
10601                                 hr, prop.expected, i, j);
10602                             ok(!strcmp_aw(prop.value, received) ||
10603                                broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
10604                                 "Error: Expected \"%s\" but got %s instead on uri_combine_tests[%d].str_props[%d].\n",
10605                                 prop.value, wine_dbgstr_w(received), i, j);
10606                         }
10607                         SysFreeString(received);
10608                     }
10609 
10610                     for(j = 0; j < ARRAY_SIZE(uri_combine_tests[i].dword_props); ++j) {
10611                         uri_dword_property prop = uri_combine_tests[i].dword_props[j];
10612                         DWORD received;
10613 
10614                         hr = IUri_GetPropertyDWORD(result, j+Uri_PROPERTY_DWORD_START, &received, 0);
10615                         todo_wine_if(prop.todo) {
10616                             ok(hr == prop.expected || broken(prop.broken_combine_hres && hr == S_FALSE),
10617                                 "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].dword_props[%d].\n",
10618                                 hr, prop.expected, i, j);
10619                             if(!prop.broken_combine_hres || hr != S_FALSE)
10620                                 ok(prop.value == received, "Error: Expected %d, but got %d instead on uri_combine_tests[%d].dword_props[%d].\n",
10621                                     prop.value, received, i, j);
10622                         }
10623                     }
10624                 }
10625                 if(result) IUri_Release(result);
10626             }
10627             if(relative) IUri_Release(relative);
10628             heap_free(relativeW);
10629         }
10630         if(base) IUri_Release(base);
10631         heap_free(baseW);
10632     }
10633 }
10634 
InternetProtocolInfo_QueryInterface(IInternetProtocolInfo * iface,REFIID riid,void ** ppv)10635 static HRESULT WINAPI InternetProtocolInfo_QueryInterface(IInternetProtocolInfo *iface,
10636                                                           REFIID riid, void **ppv)
10637 {
10638     ok(0, "unexpected call\n");
10639     return E_NOINTERFACE;
10640 }
10641 
InternetProtocolInfo_AddRef(IInternetProtocolInfo * iface)10642 static ULONG WINAPI InternetProtocolInfo_AddRef(IInternetProtocolInfo *iface)
10643 {
10644     return 2;
10645 }
10646 
InternetProtocolInfo_Release(IInternetProtocolInfo * iface)10647 static ULONG WINAPI InternetProtocolInfo_Release(IInternetProtocolInfo *iface)
10648 {
10649     return 1;
10650 }
10651 
InternetProtocolInfo_ParseUrl(IInternetProtocolInfo * iface,LPCWSTR pwzUrl,PARSEACTION ParseAction,DWORD dwParseFlags,LPWSTR pwzResult,DWORD cchResult,DWORD * pcchResult,DWORD dwReserved)10652 static HRESULT WINAPI InternetProtocolInfo_ParseUrl(IInternetProtocolInfo *iface, LPCWSTR pwzUrl,
10653         PARSEACTION ParseAction, DWORD dwParseFlags, LPWSTR pwzResult, DWORD cchResult,
10654         DWORD *pcchResult, DWORD dwReserved)
10655 {
10656     CHECK_EXPECT(ParseUrl);
10657     ok(!lstrcmpW(pwzUrl, parse_urlW), "Error: Expected %s, but got %s instead.\n",
10658         wine_dbgstr_w(parse_urlW), wine_dbgstr_w(pwzUrl));
10659     ok(ParseAction == parse_action, "Error: Expected %d, but got %d.\n", parse_action, ParseAction);
10660     ok(dwParseFlags == parse_flags, "Error: Expected 0x%08x, but got 0x%08x.\n", parse_flags, dwParseFlags);
10661     ok(cchResult == 200, "Error: Got %d.\n", cchResult);
10662 
10663     memcpy(pwzResult, parse_resultW, sizeof(parse_resultW));
10664     *pcchResult = lstrlenW(parse_resultW);
10665 
10666     return S_OK;
10667 }
10668 
InternetProtocolInfo_CombineUrl(IInternetProtocolInfo * iface,LPCWSTR pwzBaseUrl,LPCWSTR pwzRelativeUrl,DWORD dwCombineFlags,LPWSTR pwzResult,DWORD cchResult,DWORD * pcchResult,DWORD dwReserved)10669 static HRESULT WINAPI InternetProtocolInfo_CombineUrl(IInternetProtocolInfo *iface,
10670         LPCWSTR pwzBaseUrl, LPCWSTR pwzRelativeUrl, DWORD dwCombineFlags,
10671         LPWSTR pwzResult, DWORD cchResult, DWORD *pcchResult, DWORD dwReserved)
10672 {
10673     CHECK_EXPECT(CombineUrl);
10674     ok(!lstrcmpW(pwzBaseUrl, combine_baseW), "Error: Expected %s, but got %s instead.\n",
10675         wine_dbgstr_w(combine_baseW), wine_dbgstr_w(pwzBaseUrl));
10676     ok(!lstrcmpW(pwzRelativeUrl, combine_relativeW), "Error: Expected %s, but got %s instead.\n",
10677         wine_dbgstr_w(combine_relativeW), wine_dbgstr_w(pwzRelativeUrl));
10678     ok(dwCombineFlags == (URL_DONT_SIMPLIFY|URL_FILE_USE_PATHURL|URL_DONT_UNESCAPE_EXTRA_INFO),
10679         "Error: Expected 0, but got 0x%08x.\n", dwCombineFlags);
10680     ok(cchResult == INTERNET_MAX_URL_LENGTH+1, "Error: Got %d.\n", cchResult);
10681 
10682     memcpy(pwzResult, combine_resultW, sizeof(combine_resultW));
10683     *pcchResult = lstrlenW(combine_resultW);
10684 
10685     return S_OK;
10686 }
10687 
InternetProtocolInfo_CompareUrl(IInternetProtocolInfo * iface,LPCWSTR pwzUrl1,LPCWSTR pwzUrl2,DWORD dwCompareFlags)10688 static HRESULT WINAPI InternetProtocolInfo_CompareUrl(IInternetProtocolInfo *iface,
10689         LPCWSTR pwzUrl1, LPCWSTR pwzUrl2, DWORD dwCompareFlags)
10690 {
10691     ok(0, "unexpected call\n");
10692     return E_NOTIMPL;
10693 }
10694 
InternetProtocolInfo_QueryInfo(IInternetProtocolInfo * iface,LPCWSTR pwzUrl,QUERYOPTION OueryOption,DWORD dwQueryFlags,LPVOID pBuffer,DWORD cbBuffer,DWORD * pcbBuf,DWORD dwReserved)10695 static HRESULT WINAPI InternetProtocolInfo_QueryInfo(IInternetProtocolInfo *iface,
10696         LPCWSTR pwzUrl, QUERYOPTION OueryOption, DWORD dwQueryFlags, LPVOID pBuffer,
10697         DWORD cbBuffer, DWORD *pcbBuf, DWORD dwReserved)
10698 {
10699     ok(0, "unexpected call\n");
10700     return E_NOTIMPL;
10701 }
10702 
10703 static const IInternetProtocolInfoVtbl InternetProtocolInfoVtbl = {
10704     InternetProtocolInfo_QueryInterface,
10705     InternetProtocolInfo_AddRef,
10706     InternetProtocolInfo_Release,
10707     InternetProtocolInfo_ParseUrl,
10708     InternetProtocolInfo_CombineUrl,
10709     InternetProtocolInfo_CompareUrl,
10710     InternetProtocolInfo_QueryInfo
10711 };
10712 
10713 static IInternetProtocolInfo protocol_info = { &InternetProtocolInfoVtbl };
10714 
ClassFactory_QueryInterface(IClassFactory * iface,REFIID riid,void ** ppv)10715 static HRESULT WINAPI ClassFactory_QueryInterface(IClassFactory *iface, REFIID riid, void **ppv)
10716 {
10717     if(IsEqualGUID(&IID_IInternetProtocolInfo, riid)) {
10718         *ppv = &protocol_info;
10719         return S_OK;
10720     }
10721 
10722     ok(0, "unexpected call\n");
10723     return E_NOINTERFACE;
10724 }
10725 
ClassFactory_AddRef(IClassFactory * iface)10726 static ULONG WINAPI ClassFactory_AddRef(IClassFactory *iface)
10727 {
10728     return 2;
10729 }
10730 
ClassFactory_Release(IClassFactory * iface)10731 static ULONG WINAPI ClassFactory_Release(IClassFactory *iface)
10732 {
10733     return 1;
10734 }
10735 
ClassFactory_CreateInstance(IClassFactory * iface,IUnknown * pOuter,REFIID riid,void ** ppv)10736 static HRESULT WINAPI ClassFactory_CreateInstance(IClassFactory *iface, IUnknown *pOuter,
10737                                         REFIID riid, void **ppv)
10738 {
10739     ok(0, "unexpected call\n");
10740     return E_NOTIMPL;
10741 }
10742 
ClassFactory_LockServer(IClassFactory * iface,BOOL dolock)10743 static HRESULT WINAPI ClassFactory_LockServer(IClassFactory *iface, BOOL dolock)
10744 {
10745     ok(0, "unexpected call\n");
10746     return S_OK;
10747 }
10748 
10749 static const IClassFactoryVtbl ClassFactoryVtbl = {
10750     ClassFactory_QueryInterface,
10751     ClassFactory_AddRef,
10752     ClassFactory_Release,
10753     ClassFactory_CreateInstance,
10754     ClassFactory_LockServer
10755 };
10756 
10757 static IClassFactory protocol_cf = { &ClassFactoryVtbl };
10758 
register_protocols(void)10759 static void register_protocols(void)
10760 {
10761     IInternetSession *session;
10762     HRESULT hres;
10763 
10764     hres = pCoInternetGetSession(0, &session, 0);
10765     ok(hres == S_OK, "CoInternetGetSession failed: %08x\n", hres);
10766     if(FAILED(hres))
10767         return;
10768 
10769     hres = IInternetSession_RegisterNameSpace(session, &protocol_cf, &IID_NULL,
10770             winetestW, 0, NULL, 0);
10771     ok(hres == S_OK, "RegisterNameSpace failed: %08x\n", hres);
10772 
10773     IInternetSession_Release(session);
10774 }
10775 
unregister_protocols(void)10776 static void unregister_protocols(void) {
10777     IInternetSession *session;
10778     HRESULT hr;
10779 
10780     hr = pCoInternetGetSession(0, &session, 0);
10781     ok(hr == S_OK, "CoInternetGetSession failed: 0x%08x\n", hr);
10782     if(FAILED(hr))
10783         return;
10784 
10785     hr = IInternetSession_UnregisterNameSpace(session, &protocol_cf, winetestW);
10786     ok(hr == S_OK, "UnregisterNameSpace failed: 0x%08x\n", hr);
10787 
10788     IInternetSession_Release(session);
10789 }
10790 
test_CoInternetCombineIUri_Pluggable(void)10791 static void test_CoInternetCombineIUri_Pluggable(void) {
10792     HRESULT hr;
10793     IUri *base = NULL;
10794 
10795     hr = pCreateUri(combine_baseW, 0, 0, &base);
10796     ok(SUCCEEDED(hr), "Error: CreateUri returned 0x%08x.\n", hr);
10797     if(SUCCEEDED(hr)) {
10798         IUri *relative = NULL;
10799 
10800         hr = pCreateUri(combine_relativeW, Uri_CREATE_ALLOW_RELATIVE, 0, &relative);
10801         ok(SUCCEEDED(hr), "Error: CreateUri returned 0x%08x.\n", hr);
10802         if(SUCCEEDED(hr)) {
10803             IUri *result = NULL;
10804 
10805             SET_EXPECT(CombineUrl);
10806 
10807             hr = pCoInternetCombineIUri(base, relative, URL_DONT_SIMPLIFY|URL_FILE_USE_PATHURL|URL_DONT_UNESCAPE_EXTRA_INFO,
10808                                         &result, 0);
10809             ok(hr == S_OK, "Error: CoInternetCombineIUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
10810 
10811             CHECK_CALLED(CombineUrl);
10812 
10813             if(SUCCEEDED(hr)) {
10814                 BSTR received = NULL;
10815                 hr = IUri_GetAbsoluteUri(result, &received);
10816                 ok(hr == S_OK, "Error: Expected S_OK, but got 0x%08x instead.\n", hr);
10817                 if(SUCCEEDED(hr)) {
10818                     ok(!lstrcmpW(combine_resultW, received), "Error: Expected %s, but got %s.\n",
10819                         wine_dbgstr_w(combine_resultW), wine_dbgstr_w(received));
10820                 }
10821                 SysFreeString(received);
10822             }
10823             if(result) IUri_Release(result);
10824         }
10825         if(relative) IUri_Release(relative);
10826     }
10827     if(base) IUri_Release(base);
10828 }
10829 
test_CoInternetCombineUrlEx(void)10830 static void test_CoInternetCombineUrlEx(void) {
10831     HRESULT hr;
10832     IUri *base, *result;
10833     DWORD i;
10834 
10835     base = NULL;
10836     hr = pCreateUri(http_urlW, 0, 0, &base);
10837     ok(SUCCEEDED(hr), "Error: CreateUri returned 0x%08x.\n", hr);
10838     if(SUCCEEDED(hr)) {
10839         result = (void*) 0xdeadbeef;
10840         hr = pCoInternetCombineUrlEx(base, NULL, 0, &result, 0);
10841         ok(hr == E_UNEXPECTED, "Error: CoInternetCombineUrlEx returned 0x%08x, expected 0x%08x.\n",
10842             hr, E_UNEXPECTED);
10843         ok(!result, "Error: Expected 'result' to be NULL was %p instead.\n", result);
10844     }
10845 
10846     result = (void*) 0xdeadbeef;
10847     hr = pCoInternetCombineUrlEx(NULL, http_urlW, 0, &result, 0);
10848     ok(hr == E_INVALIDARG, "Error: CoInternetCombineUrlEx returned 0x%08x, expected 0x%08x.\n",
10849         hr, E_INVALIDARG);
10850     ok(!result, "Error: Expected 'result' to be NULL, but was %p instead.\n", result);
10851 
10852     result = (void*) 0xdeadbeef;
10853     hr = pCoInternetCombineUrlEx(NULL, NULL, 0, &result, 0);
10854     ok(hr == E_UNEXPECTED, "Error: CoInternetCombineUrlEx returned 0x%08x, expected 0x%08x.\n",
10855         hr, E_UNEXPECTED);
10856     ok(!result, "Error: Expected 'result' to be NULL, but was %p instead.\n", result);
10857 
10858     hr = pCoInternetCombineUrlEx(base, http_urlW, 0, NULL, 0);
10859     ok(hr == E_POINTER, "Error: CoInternetCombineUrlEx returned 0x%08x, expected 0x%08x.\n",
10860         hr, E_POINTER);
10861     if(base) IUri_Release(base);
10862 
10863     for(i = 0; i < ARRAY_SIZE(uri_combine_tests); ++i) {
10864         LPWSTR baseW = a2w(uri_combine_tests[i].base_uri);
10865 
10866         hr = pCreateUri(baseW, uri_combine_tests[i].base_create_flags, 0, &base);
10867         ok(SUCCEEDED(hr), "Error: CreateUri returned 0x%08x on uri_combine_tests[%d].\n", hr, i);
10868         if(SUCCEEDED(hr)) {
10869             LPWSTR relativeW = a2w(uri_combine_tests[i].relative_uri);
10870 
10871             hr = pCoInternetCombineUrlEx(base, relativeW, uri_combine_tests[i].combine_flags,
10872                                          &result, 0);
10873             todo_wine_if(uri_combine_tests[i].todo)
10874                 ok(hr == uri_combine_tests[i].expected,
10875                     "Error: CoInternetCombineUrlEx returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].\n",
10876                     hr, uri_combine_tests[i]. expected, i);
10877             if(SUCCEEDED(hr)) {
10878                 DWORD j;
10879 
10880                 for(j = 0; j < ARRAY_SIZE(uri_combine_tests[i].str_props); ++j) {
10881                     uri_combine_str_property prop = uri_combine_tests[i].str_props[j];
10882                     BSTR received;
10883                     LPCSTR value = (prop.value_ex) ? prop.value_ex : prop.value;
10884 
10885                     hr = IUri_GetPropertyBSTR(result, j, &received, 0);
10886                     todo_wine_if(prop.todo) {
10887                         ok(hr == prop.expected,
10888                             "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].str_props[%d].\n",
10889                             hr, prop.expected, i, j);
10890                         ok(!strcmp_aw(value, received) ||
10891                            broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
10892                             "Error: Expected \"%s\" but got %s instead on uri_combine_tests[%d].str_props[%d].\n",
10893                             value, wine_dbgstr_w(received), i, j);
10894                     }
10895                     SysFreeString(received);
10896                 }
10897 
10898                 for(j = 0; j < ARRAY_SIZE(uri_combine_tests[i].dword_props); ++j) {
10899                     uri_dword_property prop = uri_combine_tests[i].dword_props[j];
10900                     DWORD received;
10901 
10902                     hr = IUri_GetPropertyDWORD(result, j+Uri_PROPERTY_DWORD_START, &received, 0);
10903                     todo_wine_if(prop.todo) {
10904                         ok(hr == prop.expected || broken(prop.broken_combine_hres && hr == S_FALSE),
10905                             "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].dword_props[%d].\n",
10906                             hr, prop.expected, i, j);
10907                         if(!prop.broken_combine_hres || hr != S_FALSE)
10908                             ok(prop.value == received, "Error: Expected %d, but got %d instead on uri_combine_tests[%d].dword_props[%d].\n",
10909                                 prop.value, received, i, j);
10910                     }
10911                 }
10912             }
10913             if(result) IUri_Release(result);
10914             heap_free(relativeW);
10915         }
10916         if(base) IUri_Release(base);
10917         heap_free(baseW);
10918     }
10919 }
10920 
test_CoInternetCombineUrlEx_Pluggable(void)10921 static void test_CoInternetCombineUrlEx_Pluggable(void) {
10922     HRESULT hr;
10923     IUri *base = NULL;
10924 
10925     hr = pCreateUri(combine_baseW, 0, 0, &base);
10926     ok(SUCCEEDED(hr), "Error: CreateUri returned 0x%08x.\n", hr);
10927     if(SUCCEEDED(hr)) {
10928         IUri *result = NULL;
10929 
10930         SET_EXPECT(CombineUrl);
10931 
10932         hr = pCoInternetCombineUrlEx(base, combine_relativeW, URL_DONT_SIMPLIFY|URL_FILE_USE_PATHURL|URL_DONT_UNESCAPE_EXTRA_INFO,
10933                                      &result, 0);
10934         ok(hr == S_OK, "Error: CoInternetCombineUrlEx returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
10935 
10936         CHECK_CALLED(CombineUrl);
10937 
10938         if(SUCCEEDED(hr)) {
10939             BSTR received = NULL;
10940             hr = IUri_GetAbsoluteUri(result, &received);
10941             ok(hr == S_OK, "Error: Expected S_OK, but got 0x%08x instead.\n", hr);
10942             if(SUCCEEDED(hr)) {
10943                 ok(!lstrcmpW(combine_resultW, received), "Error: Expected %s, but got %s.\n",
10944                     wine_dbgstr_w(combine_resultW), wine_dbgstr_w(received));
10945             }
10946             SysFreeString(received);
10947         }
10948         if(result) IUri_Release(result);
10949     }
10950     if(base) IUri_Release(base);
10951 }
10952 
test_CoInternetParseIUri_InvalidArgs(void)10953 static void test_CoInternetParseIUri_InvalidArgs(void) {
10954     HRESULT hr;
10955     IUri *uri = NULL;
10956     WCHAR tmp[3];
10957     WCHAR *longurl, *copy;
10958     DWORD result = -1;
10959     DWORD i, len;
10960 
10961     hr = pCoInternetParseIUri(NULL, PARSE_CANONICALIZE, 0, tmp, 3, &result, 0);
10962     ok(hr == E_INVALIDARG, "Error: CoInternetParseIUri returned 0x%08x, expected 0x%08x.\n",
10963         hr, E_INVALIDARG);
10964     ok(!result, "Error: Expected 'result' to be 0, but was %d.\n", result);
10965 
10966     hr = pCreateUri(http_urlW, 0, 0, &uri);
10967     ok(SUCCEEDED(hr), "Error: CreateUri returned 0x%08x.\n", hr);
10968     if(SUCCEEDED(hr)) {
10969         DWORD expected_len;
10970 
10971         result = -1;
10972         hr = pCoInternetParseIUri(uri, PARSE_CANONICALIZE, 0, NULL, 0, &result, 0);
10973         ok(hr == E_INVALIDARG, "Error: CoInternetParseIUri returned 0x%08x, expected 0x%08x.\n",
10974             hr, E_INVALIDARG);
10975         ok(!result, "Error: Expected 'result' to be 0, but was %d.\n", result);
10976 
10977         hr = pCoInternetParseIUri(uri, PARSE_CANONICALIZE, 0, tmp, 3, NULL, 0);
10978         ok(hr == E_POINTER, "Error: CoInternetParseIUri returned 0x%08x, expected 0x%08x.\n",
10979             hr, E_POINTER);
10980 
10981         result = -1;
10982         hr = pCoInternetParseIUri(uri, PARSE_SECURITY_URL, 0, tmp, 3, &result, 0);
10983         ok(hr == E_FAIL, "Error: CoInternetParseIUri returned 0x%08x expected 0x%08x.\n",
10984             hr, E_FAIL);
10985         ok(!result, "Error: Expected 'result' to be 0, but was %d.\n", result);
10986 
10987         result = -1;
10988         hr = pCoInternetParseIUri(uri, PARSE_MIME, 0, tmp, 3, &result, 0);
10989         ok(hr == E_FAIL, "Error: CoInternetParseIUri returned 0x%08x, expected 0x%08x.\n",
10990             hr, E_FAIL);
10991         ok(!result, "Error: Expected 'result' to be 0, but was %d.\n", result);
10992 
10993         result = -1;
10994         hr = pCoInternetParseIUri(uri, PARSE_SERVER, 0, tmp, 3, &result, 0);
10995         ok(hr == E_FAIL, "Error: CoInternetParseIUri returned 0x%08x, expected 0x%08x.\n",
10996             hr, E_FAIL);
10997         ok(!result, "Error: Expected 'result' to be 0, but was %d.\n", result);
10998 
10999         result = -1;
11000         hr = pCoInternetParseIUri(uri, PARSE_SECURITY_DOMAIN, 0, tmp, 3, &result, 0);
11001         ok(hr == E_FAIL, "Error: CoInternetParseIUri returned 0x%08x, expected 0x%08x.\n",
11002             hr, E_FAIL);
11003         ok(!result, "Error: Expected 'result' to be 0, but was %d.\n", result);
11004 
11005         expected_len = lstrlenW(http_urlW);
11006         result = -1;
11007         hr = pCoInternetParseIUri(uri, PARSE_CANONICALIZE, 0, tmp, 3, &result, 0);
11008         ok(hr == STRSAFE_E_INSUFFICIENT_BUFFER,
11009             "Error: CoInternetParseIUri returned 0x%08x, expected 0x%08x.\n",
11010             hr, STRSAFE_E_INSUFFICIENT_BUFFER);
11011         ok(result == expected_len, "Error: Expected 'result' to be %d, but was %d instead.\n",
11012             expected_len, result);
11013     }
11014     if(uri) IUri_Release(uri);
11015 
11016     /* a long url that causes a crash on Wine */
11017     len = INTERNET_MAX_URL_LENGTH*2;
11018     longurl = heap_alloc((len+1)*sizeof(WCHAR));
11019     memcpy(longurl, http_urlW, sizeof(http_urlW));
11020     for(i = ARRAY_SIZE(http_urlW)-1; i < len; i++)
11021         longurl[i] = 'x';
11022     longurl[len] = 0;
11023 
11024     copy = heap_alloc((len+1)*sizeof(WCHAR));
11025     memcpy(copy, longurl, (len+1)*sizeof(WCHAR));
11026 
11027     hr = pCreateUri(longurl, 0, 0, &uri);
11028     ok(SUCCEEDED(hr), "Error: CreateUri returned 0x%08x.\n", hr);
11029     if(SUCCEEDED(hr)) {
11030         result = -1;
11031         memset(longurl, 0xcc, len*sizeof(WCHAR));
11032         hr = pCoInternetParseIUri(uri, PARSE_CANONICALIZE, 0, longurl, len+1, &result, 0);
11033         ok(SUCCEEDED(hr), "Error: CoInternetParseIUri returned 0x%08x.\n", hr);
11034         ok(!lstrcmpW(longurl, copy), "Error: expected long url '%s' but was '%s'.\n",
11035             wine_dbgstr_w(copy), wine_dbgstr_w(longurl));
11036         ok(result == len, "Error: Expected 'result' to be %d, but was %d instead.\n",
11037             len, result);
11038     }
11039     heap_free(longurl);
11040     heap_free(copy);
11041     if(uri) IUri_Release(uri);
11042 }
11043 
test_CoInternetParseIUri(void)11044 static void test_CoInternetParseIUri(void) {
11045     DWORD i;
11046 
11047     for(i = 0; i < ARRAY_SIZE(uri_parse_tests); ++i) {
11048         HRESULT hr;
11049         IUri *uri;
11050         LPWSTR uriW;
11051         uri_parse_test test = uri_parse_tests[i];
11052 
11053         uriW = a2w(test.uri);
11054         hr = pCreateUri(uriW, test.uri_flags, 0, &uri);
11055         ok(SUCCEEDED(hr), "Error: CreateUri returned 0x%08x on uri_parse_tests[%d].\n", hr, i);
11056         if(SUCCEEDED(hr)) {
11057             WCHAR result[INTERNET_MAX_URL_LENGTH+1];
11058             DWORD result_len = -1;
11059 
11060             hr = pCoInternetParseIUri(uri, test.action, test.flags, result, INTERNET_MAX_URL_LENGTH+1, &result_len, 0);
11061             todo_wine_if(test.todo)
11062                 ok(hr == test.expected,
11063                     "Error: CoInternetParseIUri returned 0x%08x, expected 0x%08x on uri_parse_tests[%d].\n",
11064                     hr, test.expected, i);
11065             if(SUCCEEDED(hr)) {
11066                 DWORD len = lstrlenA(test.property);
11067                 ok(!strcmp_aw(test.property, result) || (test.property2 && !strcmp_aw(test.property2, result)),
11068                     "Error: Expected %s but got %s instead on uri_parse_tests[%d] - %s.\n",
11069                     test.property, wine_dbgstr_w(result), i, wine_dbgstr_w(uriW));
11070                 ok(len == result_len || (test.property2 && lstrlenA(test.property2) == result_len),
11071                     "Error: Expected %d, but got %d instead on uri_parse_tests[%d] - %s.\n",
11072                     len, result_len, i, wine_dbgstr_w(uriW));
11073             } else {
11074                 ok(!result_len,
11075                     "Error: Expected 'result_len' to be 0, but was %d on uri_parse_tests[%d].\n",
11076                     result_len, i);
11077             }
11078         }
11079         if(uri) IUri_Release(uri);
11080         heap_free(uriW);
11081     }
11082 }
11083 
test_CoInternetParseIUri_Pluggable(void)11084 static void test_CoInternetParseIUri_Pluggable(void) {
11085     HRESULT hr;
11086     IUri *uri = NULL;
11087 
11088     hr = pCreateUri(parse_urlW, 0, 0, &uri);
11089     ok(SUCCEEDED(hr), "Error: Expected CreateUri to succeed, but got 0x%08x.\n", hr);
11090     if(SUCCEEDED(hr)) {
11091         WCHAR result[200];
11092         DWORD result_len;
11093 
11094         SET_EXPECT(ParseUrl);
11095 
11096         parse_action = PARSE_CANONICALIZE;
11097         parse_flags = URL_UNESCAPE|URL_ESCAPE_UNSAFE;
11098 
11099         hr = pCoInternetParseIUri(uri, parse_action, parse_flags, result, 200, &result_len, 0);
11100         ok(hr == S_OK, "Error: CoInternetParseIUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
11101 
11102         CHECK_CALLED(ParseUrl);
11103 
11104         if(SUCCEEDED(hr)) {
11105             ok(result_len == lstrlenW(parse_resultW), "Error: Expected %d, but got %d.\n",
11106                 lstrlenW(parse_resultW), result_len);
11107             ok(!lstrcmpW(result, parse_resultW), "Error: Expected %s, but got %s.\n",
11108                 wine_dbgstr_w(parse_resultW), wine_dbgstr_w(result));
11109         }
11110     }
11111     if(uri) IUri_Release(uri);
11112 }
11113 
11114 typedef struct {
11115     const char *url;
11116     DWORD uri_flags;
11117     const char *base_url;
11118     DWORD base_uri_flags;
11119     const char *legacy_url;
11120     const char *uniform_url;
11121     const char *no_canon_url;
11122     const char *uri_url;
11123 } create_urlmon_test_t;
11124 
11125 static const create_urlmon_test_t create_urlmon_tests[] = {
11126     {
11127         "http://www.winehq.org",Uri_CREATE_NO_CANONICALIZE,
11128         NULL,0,
11129         "http://www.winehq.org/",
11130         "http://www.winehq.org/",
11131         "http://www.winehq.org",
11132         "http://www.winehq.org"
11133     },
11134     {
11135         "file://c:\\dir\\file.txt",Uri_CREATE_NO_CANONICALIZE,
11136         NULL,0,
11137         "file://c:\\dir\\file.txt",
11138         "file:///c:/dir/file.txt",
11139         "file:///c:/dir/file.txt",
11140         "file:///c:/dir/file.txt"
11141     },
11142     {
11143         "file://c:\\dir\\file.txt",Uri_CREATE_FILE_USE_DOS_PATH,
11144         NULL,0,
11145         "file://c:\\dir\\file.txt",
11146         "file:///c:/dir/file.txt",
11147         "file:///c:/dir/file.txt",
11148         "file://c:\\dir\\file.txt"
11149     },
11150     {
11151         "dat%61",Uri_CREATE_ALLOW_RELATIVE,
11152         "http://www.winehq.org",0,
11153         "http://www.winehq.org/data",
11154         "http://www.winehq.org/data",
11155         "http://www.winehq.org:80/data",
11156     },
11157     {
11158         "file.txt",Uri_CREATE_ALLOW_RELATIVE,
11159         "file://c:\\dir\\x.txt",Uri_CREATE_NO_CANONICALIZE,
11160         "file://c:\\dir\\file.txt",
11161         "file:///c:/dir/file.txt",
11162         "file:///c:/dir/file.txt",
11163     },
11164     {
11165         "",Uri_CREATE_ALLOW_RELATIVE,
11166         NULL,0,
11167         "",
11168         "",
11169         "",
11170         ""
11171     },
11172     {
11173         "test",Uri_CREATE_ALLOW_RELATIVE,
11174         NULL,0,
11175         "test",
11176         "test",
11177         "test",
11178         "test"
11179     },
11180     {
11181         "c:\\dir\\file.txt",Uri_CREATE_ALLOW_IMPLICIT_FILE_SCHEME,
11182         NULL,0,
11183         "file://c:\\dir\\file.txt",
11184         "file:///c:/dir/file.txt",
11185         "file:///c:/dir/file.txt",
11186         "file:///c:/dir/file.txt",
11187     },
11188     {
11189         "c:\\dir\\file.txt#frag|part",Uri_CREATE_ALLOW_IMPLICIT_FILE_SCHEME,
11190         NULL,0,
11191         "file://c:\\dir\\file.txt#frag|part",
11192         "file:///c:/dir/file.txt#frag%7Cpart",
11193         "file:///c:/dir/file.txt#frag%7Cpart",
11194         "file:///c:/dir/file.txt#frag%7Cpart",
11195     }
11196 };
11197 
11198 #define test_urlmon_display_name(a,b) _test_urlmon_display_name(__LINE__,a,b)
_test_urlmon_display_name(unsigned line,IMoniker * mon,const char * exurl)11199 static void _test_urlmon_display_name(unsigned line, IMoniker *mon, const char *exurl)
11200 {
11201     WCHAR *display_name;
11202     HRESULT hres;
11203 
11204     hres = IMoniker_GetDisplayName(mon, NULL, NULL, &display_name);
11205     ok_(__FILE__,line)(hres == S_OK, "GetDisplayName failed: %08x\n", hres);
11206     ok_(__FILE__,line)(!strcmp_aw(exurl, display_name), "unexpected display name: %s, expected %s\n",
11207             wine_dbgstr_w(display_name), exurl);
11208 
11209     CoTaskMemFree(display_name);
11210 }
11211 
11212 #define test_display_uri(a,b) _test_display_uri(__LINE__,a,b)
_test_display_uri(unsigned line,IMoniker * mon,const char * exurl)11213 static void _test_display_uri(unsigned line, IMoniker *mon, const char *exurl)
11214 {
11215     IUriContainer *uri_container;
11216     IUri *uri;
11217     BSTR display_uri;
11218     HRESULT hres;
11219 
11220     hres = IMoniker_QueryInterface(mon, &IID_IUriContainer, (void**)&uri_container);
11221     ok(hres == S_OK, "Could not get IUriContainer iface: %08x\n", hres);
11222 
11223     uri = NULL;
11224     hres = IUriContainer_GetIUri(uri_container, &uri);
11225     IUriContainer_Release(uri_container);
11226     ok(hres == S_OK, "GetIUri failed: %08x\n", hres);
11227     ok(uri != NULL, "uri == NULL\n");
11228 
11229     hres = IUri_GetDisplayUri(uri, &display_uri);
11230     IUri_Release(uri);
11231     ok(hres == S_OK, "GetDisplayUri failed: %08x\n", hres);
11232     ok_(__FILE__,line)(!strcmp_aw(exurl, display_uri), "unexpected display uri: %s, expected %s\n",
11233             wine_dbgstr_w(display_uri), exurl);
11234     SysFreeString(display_uri);
11235 }
11236 
test_CreateURLMoniker(void)11237 static void test_CreateURLMoniker(void)
11238 {
11239     const create_urlmon_test_t *test;
11240     IMoniker *mon, *base_mon;
11241     WCHAR *url, *base_url;
11242     IUri *uri, *base_uri;
11243     HRESULT hres;
11244 
11245     for(test = create_urlmon_tests; test < create_urlmon_tests + ARRAY_SIZE(create_urlmon_tests); test++) {
11246         url = a2w(test->url);
11247         base_url = a2w(test->base_url);
11248 
11249         if(base_url) {
11250             hres = pCreateUri(base_url, test->base_uri_flags, 0, &base_uri);
11251             ok(hres == S_OK, "CreateUri failed: %08x\n", hres);
11252 
11253             hres = pCreateURLMonikerEx2(NULL, base_uri, &base_mon, URL_MK_NO_CANONICALIZE);
11254             ok(hres == S_OK, "CreateURLMonikerEx2 failed: %08x\n", hres);
11255         }else {
11256             base_uri = NULL;
11257             base_mon = NULL;
11258         }
11259 
11260         hres = CreateURLMoniker(base_mon, url, &mon);
11261         ok(hres == S_OK, "CreateURLMoniker failed: %08x\n", hres);
11262         test_urlmon_display_name(mon, test->legacy_url);
11263         test_display_uri(mon, test->legacy_url);
11264         IMoniker_Release(mon);
11265 
11266         hres = pCreateURLMonikerEx(base_mon, url, &mon, URL_MK_LEGACY);
11267         ok(hres == S_OK, "CreateURLMoniker failed: %08x\n", hres);
11268         test_urlmon_display_name(mon, test->legacy_url);
11269         test_display_uri(mon, test->legacy_url);
11270         IMoniker_Release(mon);
11271 
11272         hres = pCreateURLMonikerEx(base_mon, url, &mon, URL_MK_UNIFORM);
11273         ok(hres == S_OK, "CreateURLMoniker failed: %08x\n", hres);
11274         test_urlmon_display_name(mon, test->uniform_url);
11275         test_display_uri(mon, test->uniform_url);
11276         IMoniker_Release(mon);
11277 
11278         hres = pCreateURLMonikerEx(base_mon, url, &mon, URL_MK_NO_CANONICALIZE);
11279         ok(hres == S_OK, "CreateURLMoniker failed: %08x\n", hres);
11280         test_urlmon_display_name(mon, test->no_canon_url);
11281         test_display_uri(mon, test->no_canon_url);
11282         IMoniker_Release(mon);
11283 
11284         hres = pCreateUri(url, test->uri_flags, 0, &uri);
11285         ok(hres == S_OK, "CreateUri failed: %08x\n", hres);
11286 
11287         hres = pCreateURLMonikerEx2(base_mon, uri, &mon, URL_MK_LEGACY);
11288         ok(hres == S_OK, "CreateURLMonikerEx2 failed: %08x\n", hres);
11289         test_urlmon_display_name(mon, base_url ? test->legacy_url : test->uri_url);
11290         test_display_uri(mon, base_url ? test->legacy_url : test->uri_url);
11291         IMoniker_Release(mon);
11292 
11293         hres = pCreateURLMonikerEx2(base_mon, uri, &mon, URL_MK_UNIFORM);
11294         ok(hres == S_OK, "CreateURLMonikerEx2 failed: %08x\n", hres);
11295         test_urlmon_display_name(mon, base_url ? test->uniform_url : test->uri_url);
11296         test_display_uri(mon, base_url ? test->uniform_url : test->uri_url);
11297         IMoniker_Release(mon);
11298 
11299         hres = pCreateURLMonikerEx2(base_mon, uri, &mon, URL_MK_NO_CANONICALIZE);
11300         ok(hres == S_OK, "CreateURLMonikerEx2 failed: %08x\n", hres);
11301         test_urlmon_display_name(mon, base_url ? test->no_canon_url : test->uri_url);
11302         test_display_uri(mon, base_url ? test->no_canon_url : test->uri_url);
11303         IMoniker_Release(mon);
11304 
11305         IUri_Release(uri);
11306         heap_free(url);
11307         heap_free(base_url);
11308         if(base_uri)
11309             IUri_Release(base_uri);
11310         if(base_mon)
11311             IMoniker_Release(base_mon);
11312     }
11313 }
11314 
add_default_flags(DWORD flags)11315 static int add_default_flags(DWORD flags) {
11316     if(!(flags & Uri_CREATE_NO_CANONICALIZE))
11317         flags |= Uri_CREATE_CANONICALIZE;
11318     if(!(flags & Uri_CREATE_NO_DECODE_EXTRA_INFO))
11319         flags |= Uri_CREATE_DECODE_EXTRA_INFO;
11320     if(!(flags & Uri_CREATE_NO_CRACK_UNKNOWN_SCHEMES))
11321         flags |= Uri_CREATE_CRACK_UNKNOWN_SCHEMES;
11322     if(!(flags & Uri_CREATE_NO_PRE_PROCESS_HTML_URI))
11323         flags |= Uri_CREATE_PRE_PROCESS_HTML_URI;
11324     if(!(flags & Uri_CREATE_IE_SETTINGS))
11325         flags |= Uri_CREATE_NO_IE_SETTINGS;
11326 
11327     return flags;
11328 }
11329 
test_IPersistStream(void)11330 static void test_IPersistStream(void)
11331 {
11332     int i, props_order[Uri_PROPERTY_DWORD_LAST+1] = { 0 };
11333 
11334     props_order[Uri_PROPERTY_RAW_URI] = 1;
11335     props_order[Uri_PROPERTY_FRAGMENT] = 2;
11336     props_order[Uri_PROPERTY_HOST] = 3;
11337     props_order[Uri_PROPERTY_PASSWORD] = 4;
11338     props_order[Uri_PROPERTY_PATH] = 5;
11339     props_order[Uri_PROPERTY_PORT] = 6;
11340     props_order[Uri_PROPERTY_QUERY] = 7;
11341     props_order[Uri_PROPERTY_SCHEME_NAME] = 8;
11342     props_order[Uri_PROPERTY_USER_NAME] = 9;
11343 
11344     for(i = 0; i < ARRAY_SIZE(uri_tests); i++) {
11345         const uri_properties *test = uri_tests+i;
11346         LPWSTR uriW;
11347         IUri *uri;
11348         IPersistStream *persist_stream;
11349         IStream *stream;
11350         IMarshal *marshal;
11351         DWORD props, props_no, dw_data[6];
11352         WCHAR str_data[1024];
11353         ULARGE_INTEGER size, max_size;
11354         LARGE_INTEGER no_off;
11355         CLSID curi;
11356         BSTR raw_uri;
11357         HRESULT hr;
11358 
11359         if(test->create_todo || test->create_expected!=S_OK)
11360             continue;
11361 
11362         uriW = a2w(test->uri);
11363         hr = pCreateUri(uriW, test->create_flags, 0, &uri);
11364         ok(hr == S_OK, "%d) CreateUri failed 0x%08x, expected S_OK..\n", i, hr);
11365 
11366         hr = IUri_QueryInterface(uri, &IID_IPersistStream, (void**)&persist_stream);
11367         ok(hr == S_OK, "%d) QueryInterface failed 0x%08x, expected S_OK.\n", i, hr);
11368 
11369         hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
11370         ok(hr == S_OK, "CreateStreamOnHGlobal failed 0x%08x.\n", hr);
11371         hr = IPersistStream_IsDirty(persist_stream);
11372         ok(hr == S_FALSE, "%d) IsDirty returned 0x%08x, expected S_FALSE.\n", i, hr);
11373         hr = IPersistStream_Save(persist_stream, stream, FALSE);
11374         ok(hr == S_OK, "%d) Save failed 0x%08x, expected S_OK.\n", i, hr);
11375         hr = IPersistStream_IsDirty(persist_stream);
11376         ok(hr == S_FALSE, "%d) IsDirty returned 0x%08x, expected S_FALSE.\n", i, hr);
11377         no_off.QuadPart = 0;
11378         hr = IStream_Seek(stream, no_off, STREAM_SEEK_CUR, &size);
11379         ok(hr == S_OK, "%d) Seek failed 0x%08x, expected S_OK.\n", i, hr);
11380         hr = IStream_Seek(stream, no_off, STREAM_SEEK_SET, NULL);
11381         ok(hr == S_OK, "%d) Seek failed 0x%08x, expected S_OK.\n", i, hr);
11382         hr = IPersistStream_GetSizeMax(persist_stream, &max_size);
11383         ok(hr == S_OK, "%d) GetSizeMax failed 0x%08x, expected S_OK.\n", i, hr);
11384         ok(U(size).LowPart+2 == U(max_size).LowPart,
11385                 "%d) Written data size is %d, max_size %d.\n",
11386                 i, U(size).LowPart, U(max_size).LowPart);
11387 
11388         hr = IStream_Read(stream, (void*)dw_data, sizeof(DWORD), NULL);
11389         ok(hr == S_OK, "%d) Read failed 0x%08x, expected S_OK.\n", i, hr);
11390         ok(dw_data[0]-2 == U(size).LowPart, "%d) Structure size is %d, expected %d\n",
11391                 i, dw_data[0]-2, U(size).LowPart);
11392         hr = IStream_Read(stream, (void*)dw_data, 6*sizeof(DWORD), NULL);
11393         ok(hr == S_OK, "%d) Read failed 0x%08x, expected S_OK.\n", i, hr);
11394         ok(dw_data[0] == 0, "%d) Incorrect value %x, expected 0 (unknown).\n", i, dw_data[0]);
11395         ok(dw_data[1] == 0, "%d) Incorrect value %x, expected 0 (unknown).\n", i, dw_data[1]);
11396         ok(dw_data[2] == add_default_flags(test->create_flags),
11397                 "%d) Incorrect value %x, expected %x (creation flags).\n",
11398                 i, dw_data[2], add_default_flags(test->create_flags));
11399         ok(dw_data[3] == 0, "%d) Incorrect value %x, expected 0 (unknown).\n", i, dw_data[3]);
11400         ok(dw_data[4] == 0, "%d) Incorrect value %x, expected 0 (unknown).\n", i, dw_data[4]);
11401         ok(dw_data[5] == 0, "%d) Incorrect value %x, expected 0 (unknown).\n", i, dw_data[5]);
11402 
11403         props_no = 0;
11404         for(props=0; props<=Uri_PROPERTY_DWORD_LAST; props++) {
11405             if(!props_order[props])
11406                 continue;
11407 
11408             if(props <= Uri_PROPERTY_STRING_LAST) {
11409                 if(test->str_props[props].expected == S_OK)
11410                     props_no++;
11411             } else {
11412                 if(test->dword_props[props-Uri_PROPERTY_DWORD_START].expected == S_OK)
11413                     props_no++;
11414             }
11415         }
11416         if(test->dword_props[Uri_PROPERTY_SCHEME-Uri_PROPERTY_DWORD_START].value != URL_SCHEME_HTTP
11417                 && test->dword_props[Uri_PROPERTY_SCHEME-Uri_PROPERTY_DWORD_START].value != URL_SCHEME_FTP
11418                 && test->dword_props[Uri_PROPERTY_SCHEME-Uri_PROPERTY_DWORD_START].value != URL_SCHEME_HTTPS)
11419             props_no = 1;
11420 
11421         hr = IStream_Read(stream, (void*)&props, sizeof(DWORD), NULL);
11422         ok(hr == S_OK, "%d) Read failed 0x%08x, expected S_OK.\n", i, hr);
11423         ok(props == props_no, "%d) Properties no is %d, expected %d.\n", i, props, props_no);
11424 
11425         dw_data[2] = 0;
11426         dw_data[3] = -1;
11427         while(props) {
11428             hr = IStream_Read(stream, (void*)dw_data, 2*sizeof(DWORD), NULL);
11429             ok(hr == S_OK, "%d) Read failed 0x%08x, expected S_OK.\n", i, hr);
11430             props--;
11431             ok(dw_data[2]<props_order[dw_data[0]],
11432                     "%d) Incorrect properties order (%d, %d)\n",
11433                     i, dw_data[0], dw_data[3]);
11434             dw_data[2] = props_order[dw_data[0]];
11435             dw_data[3] = dw_data[0];
11436 
11437             if(dw_data[0]<=Uri_PROPERTY_STRING_LAST) {
11438                 const uri_str_property *prop = test->str_props+dw_data[0];
11439                 hr = IStream_Read(stream, (void*)str_data, dw_data[1], NULL);
11440                 ok(hr == S_OK, "%d) Read failed 0x%08x, expected S_OK.\n", i, hr);
11441                 ok(!strcmp_aw(prop->value, str_data) || broken(prop->broken_value && !strcmp_aw(prop->broken_value, str_data)),
11442                         "%d) Expected %s but got %s (%d).\n", i, prop->value, wine_dbgstr_w(str_data), dw_data[0]);
11443             } else if(dw_data[0]>=Uri_PROPERTY_DWORD_START && dw_data[0]<=Uri_PROPERTY_DWORD_LAST) {
11444                 const uri_dword_property *prop = test->dword_props+dw_data[0]-Uri_PROPERTY_DWORD_START;
11445                 ok(dw_data[1] == sizeof(DWORD), "%d) Size of dword property is %d (%d)\n", i, dw_data[1], dw_data[0]);
11446                 hr = IStream_Read(stream, (void*)&dw_data[1], sizeof(DWORD), NULL);
11447                 ok(hr == S_OK, "%d) Read failed 0x%08x, expected S_OK.\n", i, hr);
11448                 ok(prop->value == dw_data[1], "%d) Expected %d but got %d (%d).\n", i, prop->value, dw_data[1], dw_data[0]);
11449             } else {
11450                 ok(FALSE, "%d) Incorrect property type (%d)\n", i, dw_data[0]);
11451                 break;
11452             }
11453         }
11454         ok(props == 0, "%d) Not all properties were processed %d. Next property type: %d\n",
11455                 i, props, dw_data[0]);
11456 
11457         IUri_Release(uri);
11458 
11459         hr = IStream_Seek(stream, no_off, STREAM_SEEK_SET, NULL);
11460         ok(hr == S_OK, "%d) Seek failed 0x%08x, expected S_OK.\n", i, hr);
11461         hr = IPersistStream_GetClassID(persist_stream, &curi);
11462         ok(hr == S_OK, "%d) GetClassID failed 0x%08x, expected S_OK.\n", i, hr);
11463         ok(IsEqualCLSID(&curi, &CLSID_CUri), "%d) GetClassID returned incorrect CLSID.\n", i);
11464         IPersistStream_Release(persist_stream);
11465 
11466         hr = CoCreateInstance(&curi, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
11467                 &IID_IUri, (void**)&uri);
11468         ok(hr == S_OK, "%d) Error creating uninitialized Uri: 0x%08x.\n", i, hr);
11469         hr = IUri_QueryInterface(uri, &IID_IPersistStream, (void**)&persist_stream);
11470         ok(hr == S_OK, "%d) QueryInterface failed 0x%08x, expected S_OK.\n", i, hr);
11471         hr = IPersistStream_Load(persist_stream, stream);
11472         ok(hr == S_OK, "%d) Load failed 0x%08x, expected S_OK.\n", i, hr);
11473         hr = IUri_GetRawUri(uri, &raw_uri);
11474         ok(hr == S_OK, "%d) GetRawUri failed 0x%08x, expected S_OK.\n", i, hr);
11475         ok(!strcmp_aw(test->str_props[Uri_PROPERTY_RAW_URI].value, raw_uri)
11476                 || broken(test->str_props[Uri_PROPERTY_RAW_URI].broken_value
11477                     && !strcmp_aw(test->str_props[Uri_PROPERTY_RAW_URI].broken_value, raw_uri)),
11478                 "%d) Expected %s but got %s.\n", i, test->str_props[Uri_PROPERTY_RAW_URI].value,
11479                 wine_dbgstr_w(raw_uri));
11480         SysFreeString(raw_uri);
11481         IPersistStream_Release(persist_stream);
11482 
11483         hr = IUri_QueryInterface(uri, &IID_IMarshal, (void**)&marshal);
11484         ok(hr == S_OK, "%d) QueryInterface(IID_IMarshal) failed 0x%08x, expected S_OK.\n", i, hr);
11485         hr = IStream_Seek(stream, no_off, STREAM_SEEK_SET, NULL);
11486         ok(hr == S_OK, "%d) Seek failed 0x%08x, expected S_OK.\n", i, hr);
11487         hr = IMarshal_MarshalInterface(marshal, stream, &IID_IUri, (void*)uri,
11488                 MSHCTX_DIFFERENTMACHINE, NULL, MSHLFLAGS_NORMAL);
11489         ok(hr == E_INVALIDARG, "%d) MarshalInterface returned 0x%08x, expected E_INVALIDARG.\n", i, hr);
11490         hr = IMarshal_MarshalInterface(marshal, stream, &IID_IUri, (void*)uri,
11491                 MSHCTX_CROSSCTX, NULL, MSHLFLAGS_NORMAL);
11492         ok(hr == E_INVALIDARG, "%d) MarshalInterface returned 0x%08x, expected E_INVALIDARG.\n", i, hr);
11493         hr = IMarshal_MarshalInterface(marshal, stream, &IID_IUri, (void*)uri,
11494                 MSHCTX_LOCAL, NULL, MSHLFLAGS_TABLESTRONG);
11495         ok(hr == E_INVALIDARG, "%d) MarshalInterface returned 0x%08x, expected E_INVALIDARG.\n", i, hr);
11496         hr = IMarshal_MarshalInterface(marshal, stream, &IID_IUri, (void*)uri,
11497                 MSHCTX_LOCAL, NULL, MSHLFLAGS_TABLEWEAK);
11498         ok(hr == E_INVALIDARG, "%d) MarshalInterface returned 0x%08x, expected E_INVALIDARG.\n", i, hr);
11499         hr = IMarshal_MarshalInterface(marshal, stream, &IID_IUri, (void*)uri,
11500                 MSHCTX_LOCAL, NULL, MSHLFLAGS_NOPING);
11501         ok(hr == E_INVALIDARG, "%d) MarshalInterface returned 0x%08x, expected E_INVALIDARG.\n", i, hr);
11502         hr = IMarshal_MarshalInterface(marshal, stream, &IID_IUri, (void*)uri,
11503                 MSHCTX_LOCAL, NULL, MSHLFLAGS_NORMAL);
11504         ok(hr == S_OK, "%d) MarshalInterface failed 0x%08x, expected S_OK.\n", i, hr);
11505         hr = IMarshal_GetUnmarshalClass(marshal, &IID_IUri, (void*)uri,
11506                 MSHCTX_CROSSCTX, NULL, MSHLFLAGS_NORMAL, &curi);
11507         ok(hr == E_INVALIDARG, "%d) GetUnmarshalClass returned 0x%08x, expected E_INVALIDARG.\n", i, hr);
11508         hr = IMarshal_GetUnmarshalClass(marshal, &IID_IUri, (void*)uri,
11509                 MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL, &curi);
11510         ok(hr == S_OK, "%d) GetUnmarshalClass failed 0x%08x, expected S_OK.\n", i, hr);
11511         ok(IsEqualCLSID(&curi, &CLSID_CUri), "%d) GetUnmarshalClass returned incorrect CLSID.\n", i);
11512 
11513         hr = IStream_Seek(stream, no_off, STREAM_SEEK_CUR, &size);
11514         ok(hr == S_OK, "%d) Seek failed 0x%08x, expected S_OK.\n", i, hr);
11515         hr = IStream_Seek(stream, no_off, STREAM_SEEK_SET, NULL);
11516         ok(hr == S_OK, "%d) Seek failed 0x%08x, expected S_OK.\n", i, hr);
11517         hr = IStream_Read(stream, (void*)dw_data, 3*sizeof(DWORD), NULL);
11518         ok(hr == S_OK, "%d) Read failed 0x%08x, expected S_OK.\n", i, hr);
11519         ok(dw_data[0]-2 == U(size).LowPart, "%d) Structure size is %d, expected %d\n",
11520                 i, dw_data[0]-2, U(size).LowPart);
11521         ok(dw_data[1] == MSHCTX_LOCAL, "%d) Incorrect value %d, expected MSHCTX_LOCAL.\n",
11522                 i, dw_data[1]);
11523         ok(dw_data[2] == dw_data[0]-8, "%d) Incorrect value %d, expected %d (PersistStream size).\n",
11524                 i, dw_data[2], dw_data[0]-8);
11525         if(!test->str_props[Uri_PROPERTY_PATH].value[0] &&
11526                 (test->dword_props[Uri_PROPERTY_SCHEME-Uri_PROPERTY_DWORD_START].value == URL_SCHEME_HTTP
11527                  || test->dword_props[Uri_PROPERTY_SCHEME-Uri_PROPERTY_DWORD_START].value == URL_SCHEME_FTP
11528                  || test->dword_props[Uri_PROPERTY_SCHEME-Uri_PROPERTY_DWORD_START].value == URL_SCHEME_HTTPS))
11529             U(max_size).LowPart += 3*sizeof(DWORD);
11530         ok(dw_data[2] == U(max_size).LowPart, "%d) Incorrect value %d, expected %d (PersistStream size).\n",
11531                 i, dw_data[2], U(max_size).LowPart);
11532         IMarshal_Release(marshal);
11533         IUri_Release(uri);
11534 
11535         hr = IStream_Seek(stream, no_off, STREAM_SEEK_SET, NULL);
11536         ok(hr == S_OK, "%d) Seek failed 0x%08x, expected S_OK.\n", i, hr);
11537         hr = CoCreateInstance(&curi, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
11538                 &IID_IUri, (void**)&uri);
11539         ok(hr == S_OK, "%d) Error creating uninitialized Uri: 0x%08x.\n", i, hr);
11540         hr = IUri_QueryInterface(uri, &IID_IMarshal, (void**)&marshal);
11541         ok(hr == S_OK, "%d) QueryInterface failed 0x%08x, expected S_OK.\n", i, hr);
11542         IUri_Release(uri);
11543         hr = IMarshal_UnmarshalInterface(marshal, stream, &IID_IUri, (void**)&uri);
11544         ok(hr == S_OK, "%d) UnmarshalInterface failed 0x%08x, expected S_OK.\n", i, hr);
11545         hr = IUri_GetRawUri(uri, &raw_uri);
11546         ok(hr == S_OK, "%d) GetRawUri failed 0x%08x, expected S_OK.\n", i, hr);
11547         ok(!strcmp_aw(test->str_props[Uri_PROPERTY_RAW_URI].value, raw_uri)
11548                 || broken(test->str_props[Uri_PROPERTY_RAW_URI].broken_value
11549                     && !strcmp_aw(test->str_props[Uri_PROPERTY_RAW_URI].broken_value, raw_uri)),
11550                 "%d) Expected %s but got %s.\n", i, test->str_props[Uri_PROPERTY_RAW_URI].value,
11551                 wine_dbgstr_w(raw_uri));
11552         SysFreeString(raw_uri);
11553 
11554         IMarshal_Release(marshal);
11555         IStream_Release(stream);
11556         IUri_Release(uri);
11557         heap_free(uriW);
11558     }
11559 }
11560 
test_UninitializedUri(void)11561 static void test_UninitializedUri(void)
11562 {
11563     IUri *uri;
11564     IUriBuilderFactory *ubf;
11565     IPersistStream *ps;
11566     IUriBuilder *ub;
11567     BSTR bstr;
11568     DWORD dword;
11569     BOOL eq;
11570     ULARGE_INTEGER ui;
11571     HRESULT hr;
11572 
11573     hr = CoCreateInstance(&CLSID_CUri, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
11574             &IID_IUri, (void**)&uri);
11575     if(FAILED(hr)) {
11576         win_skip("Skipping uninitialized Uri tests.\n");
11577         return;
11578     }
11579 
11580     hr = IUri_QueryInterface(uri, &IID_IUriBuilderFactory, (void**)&ubf);
11581     ok(hr == S_OK, "QueryInterface(IID_IUriBuillderFactory) failed: %x.\n", hr);
11582     hr = IUri_QueryInterface(uri, &IID_IPersistStream, (void**)&ps);
11583     ok(hr == S_OK, "QueryInterface(IID_IPersistStream) failed: %x.\n", hr);
11584 
11585     hr = IUri_GetAbsoluteUri(uri, NULL);
11586     ok(hr == E_UNEXPECTED, "GetAbsoluteUri returned %x, expected E_UNEXPECTED.\n", hr);
11587     hr = IUri_GetAbsoluteUri(uri, &bstr);
11588     ok(hr == E_UNEXPECTED, "GetAbsoluteUri returned %x, expected E_UNEXPECTED.\n", hr);
11589     hr = IUri_GetAuthority(uri, &bstr);
11590     ok(hr == E_UNEXPECTED, "GetAuthority returned %x, expected E_UNEXPECTED.\n", hr);
11591     hr = IUri_GetDisplayUri(uri, &bstr);
11592     ok(hr == E_UNEXPECTED, "GetDisplayUri returned %x, expected E_UNEXPECTED.\n", hr);
11593     hr = IUri_GetDomain(uri, &bstr);
11594     ok(hr == E_UNEXPECTED, "GetDomain returned %x, expected E_UNEXPECTED.\n", hr);
11595     hr = IUri_GetExtension(uri, &bstr);
11596     ok(hr == E_UNEXPECTED, "GetExtension returned %x, expected E_UNEXPECTED.\n", hr);
11597     hr = IUri_GetFragment(uri, &bstr);
11598     ok(hr == E_UNEXPECTED, "GetFragment returned %x, expected E_UNEXPECTED.\n", hr);
11599     hr = IUri_GetHost(uri, &bstr);
11600     ok(hr == E_UNEXPECTED, "GetHost returned %x, expected E_UNEXPECTED.\n", hr);
11601     hr = IUri_GetHostType(uri, &dword);
11602     ok(hr == E_UNEXPECTED, "GetHostType returned %x, expected E_UNEXPECTED.\n", hr);
11603     hr = IUri_GetPassword(uri, &bstr);
11604     ok(hr == E_UNEXPECTED, "GetPassword returned %x, expected E_UNEXPECTED.\n", hr);
11605     hr = IUri_GetPassword(uri, &bstr);
11606     ok(hr == E_UNEXPECTED, "GetPassword returned %x, expected E_UNEXPECTED.\n", hr);
11607     hr = IUri_GetPathAndQuery(uri, &bstr);
11608     ok(hr == E_UNEXPECTED, "GetPathAndQuery returned %x, expected E_UNEXPECTED.\n", hr);
11609     hr = IUri_GetPort(uri, &dword);
11610     ok(hr == E_UNEXPECTED, "GetPort returned %x, expected E_UNEXPECTED.\n", hr);
11611     hr = IUri_GetProperties(uri, &dword);
11612     ok(hr == E_UNEXPECTED, "GetProperties returned %x, expected E_UNEXPECTED.\n", hr);
11613     hr = IUri_GetPropertyBSTR(uri, Uri_PROPERTY_RAW_URI, &bstr, 0);
11614     ok(hr == E_UNEXPECTED, "GetPropertyBSTR returned %x, expected E_UNEXPECTED.\n", hr);
11615     hr = IUri_GetPropertyDWORD(uri, Uri_PROPERTY_PORT, &dword, 0);
11616     ok(hr == E_UNEXPECTED, "GetPropertyDWORD returned %x, expected E_UNEXPECTED.\n", hr);
11617     hr = IUri_GetPropertyLength(uri, Uri_PROPERTY_RAW_URI, &dword, 0);
11618     ok(hr == E_UNEXPECTED, "GetPropertyLength returned %x, expected E_UNEXPECTED.\n", hr);
11619     hr = IUri_GetQuery(uri, &bstr);
11620     ok(hr == E_UNEXPECTED, "GetQuery returned %x, expected E_UNEXPECTED.\n", hr);
11621     hr = IUri_GetRawUri(uri, &bstr);
11622     ok(hr == E_UNEXPECTED, "GetRawUri returned %x, expected E_UNEXPECTED.\n", hr);
11623     hr = IUri_GetScheme(uri, &dword);
11624     ok(hr == E_UNEXPECTED, "GetScheme returned %x, expected E_UNEXPECTED.\n", hr);
11625     hr = IUri_GetSchemeName(uri, &bstr);
11626     ok(hr == E_UNEXPECTED, "GetSchemeName returned %x, expected E_UNEXPECTED.\n", hr);
11627     hr = IUri_GetUserInfo(uri, &bstr);
11628     ok(hr == E_UNEXPECTED, "GetUserInfo returned %x, expected E_UNEXPECTED.\n", hr);
11629     hr = IUri_GetUserName(uri, &bstr);
11630     ok(hr == E_UNEXPECTED, "GetUserName returned %x, expected E_UNEXPECTED.\n", hr);
11631     hr = IUri_GetZone(uri, &dword);
11632     ok(hr == E_UNEXPECTED, "GetZone returned %x, expected E_UNEXPECTED.\n", hr);
11633     hr = IUri_IsEqual(uri, uri, &eq);
11634     ok(hr == E_UNEXPECTED, "IsEqual returned %x, expected E_UNEXPECTED.\n", hr);
11635 
11636     hr = IUriBuilderFactory_CreateInitializedIUriBuilder(ubf, 0, 0, &ub);
11637     ok(hr == E_UNEXPECTED, "CreateInitializedIUriBuilder returned %x, expected E_UNEXPECTED.\n", hr);
11638     hr = IUriBuilderFactory_CreateIUriBuilder(ubf, 0, 0, &ub);
11639     ok(hr == S_OK, "CreateIUriBuilder returned %x, expected S_OK.\n", hr);
11640     IUriBuilder_Release(ub);
11641 
11642     hr = IPersistStream_GetSizeMax(ps, &ui);
11643     ok(hr == S_OK, "GetSizeMax returned %x, expected S_OK.\n", hr);
11644     ok(ui.u.LowPart == 34, "ui.LowPart = %d, expected 34.\n", ui.u.LowPart);
11645     hr = IPersistStream_IsDirty(ps);
11646     ok(hr == S_FALSE, "IsDirty returned %x, expected S_FALSE.\n", hr);
11647 
11648     IPersistStream_Release(ps);
11649     IUriBuilderFactory_Release(ubf);
11650     IUri_Release(uri);
11651 }
11652 
START_TEST(uri)11653 START_TEST(uri) {
11654     HMODULE hurlmon;
11655 
11656     hurlmon = GetModuleHandleA("urlmon.dll");
11657     pCoInternetGetSession = (void*) GetProcAddress(hurlmon, "CoInternetGetSession");
11658     pCreateUri = (void*) GetProcAddress(hurlmon, "CreateUri");
11659     pCreateUriWithFragment = (void*) GetProcAddress(hurlmon, "CreateUriWithFragment");
11660     pCreateIUriBuilder = (void*) GetProcAddress(hurlmon, "CreateIUriBuilder");
11661     pCoInternetCombineIUri = (void*) GetProcAddress(hurlmon, "CoInternetCombineIUri");
11662     pCoInternetCombineUrlEx = (void*) GetProcAddress(hurlmon, "CoInternetCombineUrlEx");
11663     pCoInternetParseIUri = (void*) GetProcAddress(hurlmon, "CoInternetParseIUri");
11664     pCreateURLMonikerEx = (void*) GetProcAddress(hurlmon, "CreateURLMonikerEx");
11665     pCreateURLMonikerEx2 = (void*) GetProcAddress(hurlmon, "CreateURLMonikerEx2");
11666 
11667     if(!pCreateUri) {
11668         win_skip("CreateUri is not present, skipping tests.\n");
11669         return;
11670     }
11671 
11672     trace("test CreateUri invalid flags...\n");
11673     test_CreateUri_InvalidFlags();
11674 
11675     trace("test CreateUri invalid args...\n");
11676     test_CreateUri_InvalidArgs();
11677 
11678     trace("test CreateUri invalid URIs...\n");
11679     test_CreateUri_InvalidUri();
11680 
11681     trace("test IUri_GetPropertyBSTR...\n");
11682     test_IUri_GetPropertyBSTR();
11683 
11684     trace("test IUri_GetPropertyDWORD...\n");
11685     test_IUri_GetPropertyDWORD();
11686 
11687     trace("test IUri_GetStrProperties...\n");
11688     test_IUri_GetStrProperties();
11689 
11690     trace("test IUri_GetDwordProperties...\n");
11691     test_IUri_GetDwordProperties();
11692 
11693     trace("test IUri_GetPropertyLength...\n");
11694     test_IUri_GetPropertyLength();
11695 
11696     trace("test IUri_GetProperties...\n");
11697     test_IUri_GetProperties();
11698 
11699     trace("test IUri_HasProperty...\n");
11700     test_IUri_HasProperty();
11701 
11702     trace("test IUri_IsEqual...\n");
11703     test_IUri_IsEqual();
11704 
11705     trace("test CreateUriWithFragment invalid args...\n");
11706     test_CreateUriWithFragment_InvalidArgs();
11707 
11708     trace("test CreateUriWithFragment invalid flags...\n");
11709     test_CreateUriWithFragment_InvalidFlags();
11710 
11711     trace("test CreateUriWithFragment...\n");
11712     test_CreateUriWithFragment();
11713 
11714     trace("test CreateIUriBuilder...\n");
11715     test_CreateIUriBuilder();
11716 
11717     trace("test IUriBuilder_CreateInvalidArgs...\n");
11718     test_IUriBuilder_CreateInvalidArgs();
11719 
11720     trace("test IUriBuilder...\n");
11721     test_IUriBuilder();
11722 
11723     trace("test IUriBuilder_GetInvalidArgs...\n");
11724     test_IUriBuilder_GetInvalidArgs();
11725 
11726     trace("test IUriBuilder_HasBeenModified...\n");
11727     test_IUriBuilder_HasBeenModified();
11728 
11729     trace("test IUriBuilder_IUriProperty...\n");
11730     test_IUriBuilder_IUriProperty();
11731 
11732     trace("test IUriBuilder_RemoveProperties...\n");
11733     test_IUriBuilder_RemoveProperties();
11734 
11735     trace("test IUriBuilder miscellaneous...\n");
11736     test_IUriBuilder_Misc();
11737 
11738     trace("test IUriBuilderFactory...\n");
11739     test_IUriBuilderFactory();
11740 
11741     trace("test CoInternetCombineIUri...\n");
11742     test_CoInternetCombineIUri();
11743 
11744     trace("test CoInternetCombineUrlEx...\n");
11745     test_CoInternetCombineUrlEx();
11746 
11747     trace("test CoInternetParseIUri Invalid Args...\n");
11748     test_CoInternetParseIUri_InvalidArgs();
11749 
11750     trace("test CoInternetParseIUri...\n");
11751     test_CoInternetParseIUri();
11752 
11753     register_protocols();
11754 
11755     trace("test CoInternetCombineIUri pluggable...\n");
11756     test_CoInternetCombineIUri_Pluggable();
11757 
11758     trace("test CoInternetCombineUrlEx Pluggable...\n");
11759     test_CoInternetCombineUrlEx_Pluggable();
11760 
11761     trace("test CoInternetParseIUri pluggable...\n");
11762     test_CoInternetParseIUri_Pluggable();
11763 
11764     trace("test CreateURLMoniker...\n");
11765     test_CreateURLMoniker();
11766 
11767     CoInitialize(NULL);
11768 
11769     trace("test IPersistStream...\n");
11770     test_IPersistStream();
11771 
11772     trace("test uninitialized Uri...\n");
11773     test_UninitializedUri();
11774 
11775     CoUninitialize();
11776     unregister_protocols();
11777 }
11778