winealsa: Map ALSA errors to AUDCLNT_E_*.
[wine] / dlls / urlmon / tests / uri.c
1 /*
2  * UrlMon IUri tests
3  *
4  * Copyright 2010 Thomas Mullaly
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #include <wine/test.h>
22 #include <stdarg.h>
23 #include <stddef.h>
24
25 #define COBJMACROS
26 #define CONST_VTABLE
27 #define WIN32_LEAN_AND_MEAN
28
29 #include "windef.h"
30 #include "winbase.h"
31 #include "urlmon.h"
32 #include "shlwapi.h"
33 #include "wininet.h"
34 #include "strsafe.h"
35 #include "initguid.h"
36
37 DEFINE_GUID(CLSID_CUri, 0xDF2FCE13, 0x25EC, 0x45BB, 0x9D,0x4C, 0xCE,0xCD,0x47,0xC2,0x43,0x0C);
38
39 #define URI_STR_PROPERTY_COUNT Uri_PROPERTY_STRING_LAST+1
40 #define URI_DWORD_PROPERTY_COUNT (Uri_PROPERTY_DWORD_LAST - Uri_PROPERTY_DWORD_START)+1
41 #define URI_BUILDER_STR_PROPERTY_COUNT 7
42
43 #define DEFINE_EXPECT(func) \
44     static BOOL expect_ ## func = FALSE, called_ ## func = FALSE
45
46 #define SET_EXPECT(func) \
47     expect_ ## func = TRUE
48
49 #define CHECK_EXPECT(func) \
50     do { \
51         ok(expect_ ##func, "unexpected call " #func "\n"); \
52         expect_ ## func = FALSE; \
53         called_ ## func = TRUE; \
54     }while(0)
55
56 #define CHECK_EXPECT2(func) \
57     do { \
58         ok(expect_ ##func, "unexpected call " #func "\n"); \
59         called_ ## func = TRUE; \
60     }while(0)
61
62 #define CHECK_CALLED(func) \
63     do { \
64         ok(called_ ## func, "expected " #func "\n"); \
65         expect_ ## func = called_ ## func = FALSE; \
66     }while(0)
67
68 DEFINE_EXPECT(CombineUrl);
69 DEFINE_EXPECT(ParseUrl);
70
71 static HRESULT (WINAPI *pCreateUri)(LPCWSTR, DWORD, DWORD_PTR, IUri**);
72 static HRESULT (WINAPI *pCreateUriWithFragment)(LPCWSTR, LPCWSTR, DWORD, DWORD_PTR, IUri**);
73 static HRESULT (WINAPI *pCreateIUriBuilder)(IUri*, DWORD, DWORD_PTR, IUriBuilder**);
74 static HRESULT (WINAPI *pCoInternetCombineIUri)(IUri*,IUri*,DWORD,IUri**,DWORD_PTR);
75 static HRESULT (WINAPI *pCoInternetGetSession)(DWORD,IInternetSession**,DWORD);
76 static HRESULT (WINAPI *pCoInternetCombineUrlEx)(IUri*,LPCWSTR,DWORD,IUri**,DWORD_PTR);
77 static HRESULT (WINAPI *pCoInternetParseIUri)(IUri*,PARSEACTION,DWORD,LPWSTR,DWORD,DWORD*,DWORD_PTR);
78 static HRESULT (WINAPI *pCreateURLMonikerEx)(IMoniker*,LPCWSTR,IMoniker**,DWORD);
79 static HRESULT (WINAPI *pCreateURLMonikerEx2)(IMoniker*,IUri*,IMoniker**,DWORD);
80
81 static const WCHAR http_urlW[] = { 'h','t','t','p',':','/','/','w','w','w','.','w','i','n','e','h','q',
82         '.','o','r','g','/',0};
83 static const WCHAR http_url_fragW[] = { 'h','t','t','p',':','/','/','w','w','w','.','w','i','n','e','h','q',
84         '.','o','r','g','/','#','F','r','a','g',0};
85
86 static const WCHAR combine_baseW[] = {'w','i','n','e','t','e','s','t',':','?','t',
87         'e','s','t','i','n','g',0};
88 static const WCHAR combine_relativeW[] = {'?','t','e','s','t',0};
89 static const WCHAR combine_resultW[] = {'z','i','p',':','t','e','s','t',0};
90
91 static const WCHAR winetestW[] = {'w','i','n','e','t','e','s','t',0};
92
93 static const WCHAR parse_urlW[] = {'w','i','n','e','t','e','s','t',':','t','e','s','t',0};
94 static const WCHAR parse_resultW[] = {'z','i','p',':','t','e','s','t',0};
95
96 static PARSEACTION parse_action;
97 static DWORD parse_flags;
98
99 typedef struct _uri_create_flag_test {
100     DWORD   flags;
101     HRESULT expected;
102 } uri_create_flag_test;
103
104 static const uri_create_flag_test invalid_flag_tests[] = {
105     /* Set of invalid flag combinations to test for. */
106     {Uri_CREATE_DECODE_EXTRA_INFO | Uri_CREATE_NO_DECODE_EXTRA_INFO, E_INVALIDARG},
107     {Uri_CREATE_CANONICALIZE | Uri_CREATE_NO_CANONICALIZE, E_INVALIDARG},
108     {Uri_CREATE_CRACK_UNKNOWN_SCHEMES | Uri_CREATE_NO_CRACK_UNKNOWN_SCHEMES, E_INVALIDARG},
109     {Uri_CREATE_PRE_PROCESS_HTML_URI | Uri_CREATE_NO_PRE_PROCESS_HTML_URI, E_INVALIDARG},
110     {Uri_CREATE_IE_SETTINGS | Uri_CREATE_NO_IE_SETTINGS, E_INVALIDARG}
111 };
112
113 typedef struct _uri_str_property {
114     const char* value;
115     HRESULT     expected;
116     BOOL        todo;
117     const char* broken_value;
118 } uri_str_property;
119
120 typedef struct _uri_dword_property {
121     DWORD   value;
122     HRESULT expected;
123     BOOL    todo;
124 } uri_dword_property;
125
126 typedef struct _uri_properties {
127     const char*         uri;
128     DWORD               create_flags;
129     HRESULT             create_expected;
130     BOOL                create_todo;
131
132     uri_str_property    str_props[URI_STR_PROPERTY_COUNT];
133     uri_dword_property  dword_props[URI_DWORD_PROPERTY_COUNT];
134 } uri_properties;
135
136 static const uri_properties uri_tests[] = {
137     {   "http://www.winehq.org/tests/../tests/../..", 0, S_OK, FALSE,
138         {
139             {"http://www.winehq.org/",S_OK,FALSE},                      /* ABSOLUTE_URI */
140             {"www.winehq.org",S_OK,FALSE},                              /* AUTHORITY */
141             {"http://www.winehq.org/",S_OK,FALSE},                      /* DISPLAY_URI */
142             {"winehq.org",S_OK,FALSE},                                  /* DOMAIN */
143             {"",S_FALSE,FALSE},                                         /* EXTENSION */
144             {"",S_FALSE,FALSE},                                         /* FRAGMENT */
145             {"www.winehq.org",S_OK,FALSE},                              /* HOST */
146             {"",S_FALSE,FALSE},                                         /* PASSWORD */
147             {"/",S_OK,FALSE},                                           /* PATH */
148             {"/",S_OK,FALSE},                                           /* PATH_AND_QUERY */
149             {"",S_FALSE,FALSE},                                         /* QUERY */
150             {"http://www.winehq.org/tests/../tests/../..",S_OK,FALSE},  /* RAW_URI */
151             {"http",S_OK,FALSE},                                        /* SCHEME_NAME */
152             {"",S_FALSE,FALSE},                                         /* USER_INFO */
153             {"",S_FALSE,FALSE}                                          /* USER_NAME */
154         },
155         {
156             {Uri_HOST_DNS,S_OK,FALSE},                                  /* HOST_TYPE */
157             {80,S_OK,FALSE},                                            /* PORT */
158             {URL_SCHEME_HTTP,S_OK,FALSE},                               /* SCHEME */
159             {URLZONE_INVALID,E_NOTIMPL,FALSE}                           /* ZONE */
160         }
161     },
162     {   "http://winehq.org/tests/.././tests", 0, S_OK, FALSE,
163         {
164             {"http://winehq.org/tests",S_OK,FALSE},
165             {"winehq.org",S_OK,FALSE},
166             {"http://winehq.org/tests",S_OK,FALSE},
167             {"winehq.org",S_OK,FALSE},
168             {"",S_FALSE,FALSE},
169             {"",S_FALSE,FALSE},
170             {"winehq.org",S_OK,FALSE},
171             {"",S_FALSE,FALSE},
172             {"/tests",S_OK,FALSE},
173             {"/tests",S_OK,FALSE},
174             {"",S_FALSE,FALSE},
175             {"http://winehq.org/tests/.././tests",S_OK,FALSE},
176             {"http",S_OK,FALSE},
177             {"",S_FALSE,FALSE},
178             {"",S_FALSE,FALSE}
179         },
180         {
181             {Uri_HOST_DNS,S_OK,FALSE},
182             {80,S_OK,FALSE},
183             {URL_SCHEME_HTTP,S_OK,FALSE},
184             {URLZONE_INVALID,E_NOTIMPL,FALSE}
185         }
186     },
187     {   "HtTp://www.winehq.org/tests/..?query=x&return=y", 0, S_OK, FALSE,
188         {
189             {"http://www.winehq.org/?query=x&return=y",S_OK,FALSE},
190             {"www.winehq.org",S_OK,FALSE},
191             {"http://www.winehq.org/?query=x&return=y",S_OK,FALSE},
192             {"winehq.org",S_OK,FALSE},
193             {"",S_FALSE,FALSE},
194             {"",S_FALSE,FALSE},
195             {"www.winehq.org",S_OK,FALSE},
196             {"",S_FALSE,FALSE},
197             {"/",S_OK,FALSE},
198             {"/?query=x&return=y",S_OK,FALSE},
199             {"?query=x&return=y",S_OK,FALSE},
200             {"HtTp://www.winehq.org/tests/..?query=x&return=y",S_OK,FALSE},
201             {"http",S_OK,FALSE},
202             {"",S_FALSE,FALSE},
203             {"",S_FALSE,FALSE}
204         },
205         {
206             {Uri_HOST_DNS,S_OK,FALSE},
207             {80,S_OK,FALSE},
208             {URL_SCHEME_HTTP,S_OK,FALSE},
209             {URLZONE_INVALID,E_NOTIMPL,FALSE},
210         }
211     },
212     {   "HtTpS://www.winehq.org/tests/..?query=x&return=y", 0, S_OK, FALSE,
213         {
214             {"https://www.winehq.org/?query=x&return=y",S_OK,FALSE},
215             {"www.winehq.org",S_OK,FALSE},
216             {"https://www.winehq.org/?query=x&return=y",S_OK,FALSE},
217             {"winehq.org",S_OK,FALSE},
218             {"",S_FALSE,FALSE},
219             {"",S_FALSE,FALSE},
220             {"www.winehq.org",S_OK,FALSE},
221             {"",S_FALSE,FALSE},
222             {"/",S_OK,FALSE},
223             {"/?query=x&return=y",S_OK,FALSE},
224             {"?query=x&return=y",S_OK,FALSE},
225             {"HtTpS://www.winehq.org/tests/..?query=x&return=y",S_OK,FALSE},
226             {"https",S_OK,FALSE},
227             {"",S_FALSE,FALSE},
228             {"",S_FALSE,FALSE}
229         },
230         {
231             {Uri_HOST_DNS,S_OK,FALSE},
232             {443,S_OK,FALSE},
233             {URL_SCHEME_HTTPS,S_OK,FALSE},
234             {URLZONE_INVALID,E_NOTIMPL,FALSE},
235         }
236     },
237     {   "hTTp://us%45r%3Ainfo@examp%4CE.com:80/path/a/b/./c/../%2E%2E/Forbidden'<|> Characters", 0, S_OK, FALSE,
238         {
239             {"http://usEr%3Ainfo@example.com/path/a/Forbidden'%3C%7C%3E%20Characters",S_OK,FALSE},
240             {"usEr%3Ainfo@example.com",S_OK,FALSE},
241             {"http://example.com/path/a/Forbidden'%3C%7C%3E%20Characters",S_OK,FALSE},
242             {"example.com",S_OK,FALSE},
243             {"",S_FALSE,FALSE},
244             {"",S_FALSE,FALSE},
245             {"example.com",S_OK,FALSE},
246             {"",S_FALSE,FALSE},
247             {"/path/a/Forbidden'%3C%7C%3E%20Characters",S_OK,FALSE},
248             {"/path/a/Forbidden'%3C%7C%3E%20Characters",S_OK,FALSE},
249             {"",S_FALSE,FALSE},
250             {"hTTp://us%45r%3Ainfo@examp%4CE.com:80/path/a/b/./c/../%2E%2E/Forbidden'<|> Characters",S_OK,FALSE},
251             {"http",S_OK,FALSE},
252             {"usEr%3Ainfo",S_OK,FALSE},
253             {"usEr%3Ainfo",S_OK,FALSE}
254         },
255         {
256             {Uri_HOST_DNS,S_OK,FALSE},
257             {80,S_OK,FALSE},
258             {URL_SCHEME_HTTP,S_OK,FALSE},
259             {URLZONE_INVALID,E_NOTIMPL,FALSE},
260         }
261     },
262     {   "ftp://winepass:wine@ftp.winehq.org:9999/dir/foo bar.txt", 0, S_OK, FALSE,
263         {
264             {"ftp://winepass:wine@ftp.winehq.org:9999/dir/foo%20bar.txt",S_OK,FALSE},
265             {"winepass:wine@ftp.winehq.org:9999",S_OK,FALSE},
266             {"ftp://ftp.winehq.org:9999/dir/foo%20bar.txt",S_OK,FALSE},
267             {"winehq.org",S_OK,FALSE},
268             {".txt",S_OK,FALSE},
269             {"",S_FALSE,FALSE},
270             {"ftp.winehq.org",S_OK,FALSE},
271             {"wine",S_OK,FALSE},
272             {"/dir/foo%20bar.txt",S_OK,FALSE},
273             {"/dir/foo%20bar.txt",S_OK,FALSE},
274             {"",S_FALSE,FALSE},
275             {"ftp://winepass:wine@ftp.winehq.org:9999/dir/foo bar.txt",S_OK,FALSE},
276             {"ftp",S_OK,FALSE},
277             {"winepass:wine",S_OK,FALSE},
278             {"winepass",S_OK,FALSE}
279         },
280         {
281             {Uri_HOST_DNS,S_OK,FALSE},
282             {9999,S_OK,FALSE},
283             {URL_SCHEME_FTP,S_OK,FALSE},
284             {URLZONE_INVALID,E_NOTIMPL,FALSE}
285         }
286     },
287     {   "file://c:\\tests\\../tests/foo%20bar.mp3", 0, S_OK, FALSE,
288         {
289             {"file:///c:/tests/foo%2520bar.mp3",S_OK,FALSE},
290             {"",S_FALSE,FALSE},
291             {"file:///c:/tests/foo%2520bar.mp3",S_OK,FALSE},
292             {"",S_FALSE,FALSE},
293             {".mp3",S_OK,FALSE},
294             {"",S_FALSE,FALSE},
295             {"",S_FALSE,FALSE},
296             {"",S_FALSE,FALSE},
297             {"/c:/tests/foo%2520bar.mp3",S_OK,FALSE},
298             {"/c:/tests/foo%2520bar.mp3",S_OK,FALSE},
299             {"",S_FALSE,FALSE},
300             {"file://c:\\tests\\../tests/foo%20bar.mp3",S_OK,FALSE},
301             {"file",S_OK,FALSE},
302             {"",S_FALSE,FALSE},
303             {"",S_FALSE,FALSE}
304         },
305         {
306             {Uri_HOST_UNKNOWN,S_OK,FALSE},
307             {0,S_FALSE,FALSE},
308             {URL_SCHEME_FILE,S_OK,FALSE},
309             {URLZONE_INVALID,E_NOTIMPL,FALSE}
310         }
311     },
312     {   "file://c:\\tests\\../tests/foo%20bar.mp3", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
313         {
314             {"file:///c:/tests/../tests/foo%2520bar.mp3",S_OK,FALSE},
315             {"",S_FALSE,FALSE},
316             {"file:///c:/tests/../tests/foo%2520bar.mp3",S_OK,FALSE},
317             {"",S_FALSE,FALSE},
318             {".mp3",S_OK,FALSE},
319             {"",S_FALSE,FALSE},
320             {"",S_FALSE,FALSE},
321             {"",S_FALSE,FALSE},
322             {"/c:/tests/../tests/foo%2520bar.mp3",S_OK,FALSE},
323             {"/c:/tests/../tests/foo%2520bar.mp3",S_OK,FALSE},
324             {"",S_FALSE,FALSE},
325             {"file://c:\\tests\\../tests/foo%20bar.mp3",S_OK,FALSE},
326             {"file",S_OK,FALSE},
327             {"",S_FALSE,FALSE},
328             {"",S_FALSE,FALSE}
329         },
330         {
331             {Uri_HOST_UNKNOWN,S_OK,FALSE},
332             {0,S_FALSE,FALSE},
333             {URL_SCHEME_FILE,S_OK,FALSE},
334             {URLZONE_INVALID,E_NOTIMPL,FALSE}
335         }
336     },
337     {   "FILE://localhost/test dir\\../tests/test%20file.README.txt", 0, S_OK, FALSE,
338         {
339             {"file:///tests/test%20file.README.txt",S_OK,FALSE},
340             {"",S_FALSE,FALSE},
341             {"file:///tests/test%20file.README.txt",S_OK,FALSE},
342             {"",S_FALSE,FALSE},
343             {".txt",S_OK,FALSE},
344             {"",S_FALSE,FALSE},
345             {"",S_FALSE,FALSE},
346             {"",S_FALSE,FALSE},
347             {"/tests/test%20file.README.txt",S_OK,FALSE},
348             {"/tests/test%20file.README.txt",S_OK,FALSE},
349             {"",S_FALSE,FALSE},
350             {"FILE://localhost/test dir\\../tests/test%20file.README.txt",S_OK,FALSE},
351             {"file",S_OK,FALSE},
352             {"",S_FALSE,FALSE},
353             {"",S_FALSE,FALSE}
354         },
355         {
356             {Uri_HOST_UNKNOWN,S_OK,FALSE},
357             {0,S_FALSE,FALSE},
358             {URL_SCHEME_FILE,S_OK,FALSE},
359             {URLZONE_INVALID,E_NOTIMPL,FALSE}
360         }
361     },
362     {   "urn:nothing:should:happen here", 0, S_OK, FALSE,
363         {
364             {"urn:nothing:should:happen here",S_OK,FALSE},
365             {"",S_FALSE,FALSE},
366             {"urn:nothing:should:happen here",S_OK,FALSE},
367             {"",S_FALSE,FALSE},
368             {"",S_FALSE,FALSE},
369             {"",S_FALSE,FALSE},
370             {"",S_FALSE,FALSE},
371             {"",S_FALSE,FALSE},
372             {"nothing:should:happen here",S_OK,FALSE},
373             {"nothing:should:happen here",S_OK,FALSE},
374             {"",S_FALSE,FALSE},
375             {"urn:nothing:should:happen here",S_OK,FALSE},
376             {"urn",S_OK,FALSE},
377             {"",S_FALSE,FALSE},
378             {"",S_FALSE,FALSE}
379         },
380         {
381             {Uri_HOST_UNKNOWN,S_OK,FALSE},
382             {0,S_FALSE,FALSE},
383             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
384             {URLZONE_INVALID,E_NOTIMPL,FALSE}
385         }
386     },
387     {   "http://127.0.0.1/tests/../test dir/./test.txt", 0, S_OK, FALSE,
388         {
389             {"http://127.0.0.1/test%20dir/test.txt",S_OK,FALSE},
390             {"127.0.0.1",S_OK,FALSE},
391             {"http://127.0.0.1/test%20dir/test.txt",S_OK,FALSE},
392             {"",S_FALSE,FALSE},
393             {".txt",S_OK,FALSE},
394             {"",S_FALSE,FALSE},
395             {"127.0.0.1",S_OK,FALSE},
396             {"",S_FALSE,FALSE},
397             {"/test%20dir/test.txt",S_OK,FALSE},
398             {"/test%20dir/test.txt",S_OK,FALSE},
399             {"",S_FALSE,FALSE},
400             {"http://127.0.0.1/tests/../test dir/./test.txt",S_OK,FALSE},
401             {"http",S_OK,FALSE},
402             {"",S_FALSE,FALSE},
403             {"",S_FALSE,FALSE}
404         },
405         {
406             {Uri_HOST_IPV4,S_OK,FALSE},
407             {80,S_OK,FALSE},
408             {URL_SCHEME_HTTP,S_OK,FALSE},
409             {URLZONE_INVALID,E_NOTIMPL,FALSE}
410         }
411     },
412     {   "http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]", 0, S_OK, FALSE,
413         {
414             {"http://[fedc:ba98:7654:3210:fedc:ba98:7654:3210]/",S_OK,FALSE},
415             {"[fedc:ba98:7654:3210:fedc:ba98:7654:3210]",S_OK,FALSE},
416             {"http://[fedc:ba98:7654:3210:fedc:ba98:7654:3210]/",S_OK,FALSE},
417             {"",S_FALSE,FALSE},
418             {"",S_FALSE,FALSE},
419             {"",S_FALSE,FALSE},
420             {"fedc:ba98:7654:3210:fedc:ba98:7654:3210",S_OK,FALSE},
421             {"",S_FALSE,FALSE},
422             {"/",S_OK,FALSE},
423             {"/",S_OK,FALSE},
424             {"",S_FALSE,FALSE},
425             {"http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]",S_OK,FALSE},
426             {"http",S_OK,FALSE},
427             {"",S_FALSE,FALSE},
428             {"",S_FALSE,FALSE}
429         },
430         {
431             {Uri_HOST_IPV6,S_OK,FALSE},
432             {80,S_OK,FALSE},
433             {URL_SCHEME_HTTP,S_OK,FALSE},
434             {URLZONE_INVALID,E_NOTIMPL,FALSE}
435         }
436     },
437     {   "ftp://[::13.1.68.3]", 0, S_OK, FALSE,
438         {
439             {"ftp://[::13.1.68.3]/",S_OK,FALSE},
440             {"[::13.1.68.3]",S_OK,FALSE},
441             {"ftp://[::13.1.68.3]/",S_OK,FALSE},
442             {"",S_FALSE,FALSE},
443             {"",S_FALSE,FALSE},
444             {"",S_FALSE,FALSE},
445             {"::13.1.68.3",S_OK,FALSE},
446             {"",S_FALSE,FALSE},
447             {"/",S_OK,FALSE},
448             {"/",S_OK,FALSE},
449             {"",S_FALSE,FALSE},
450             {"ftp://[::13.1.68.3]",S_OK,FALSE},
451             {"ftp",S_OK,FALSE},
452             {"",S_FALSE,FALSE},
453             {"",S_FALSE,FALSE}
454         },
455         {
456             {Uri_HOST_IPV6,S_OK,FALSE},
457             {21,S_OK,FALSE},
458             {URL_SCHEME_FTP,S_OK,FALSE},
459             {URLZONE_INVALID,E_NOTIMPL,FALSE}
460         }
461     },
462     {   "http://[FEDC:BA98:0:0:0:0:0:3210]", 0, S_OK, FALSE,
463         {
464             {"http://[fedc:ba98::3210]/",S_OK,FALSE},
465             {"[fedc:ba98::3210]",S_OK,FALSE},
466             {"http://[fedc:ba98::3210]/",S_OK,FALSE},
467             {"",S_FALSE,FALSE},
468             {"",S_FALSE,FALSE},
469             {"",S_FALSE,FALSE},
470             {"fedc:ba98::3210",S_OK,FALSE},
471             {"",S_FALSE,FALSE},
472             {"/",S_OK,FALSE},
473             {"/",S_OK,FALSE},
474             {"",S_FALSE,FALSE},
475             {"http://[FEDC:BA98:0:0:0:0:0:3210]",S_OK,FALSE},
476             {"http",S_OK,FALSE},
477             {"",S_FALSE,FALSE},
478             {"",S_FALSE,FALSE},
479         },
480         {
481             {Uri_HOST_IPV6,S_OK,FALSE},
482             {80,S_OK,FALSE},
483             {URL_SCHEME_HTTP,S_OK,FALSE},
484             {URLZONE_INVALID,E_NOTIMPL,FALSE}
485         }
486     },
487     {   "1234://www.winehq.org", 0, S_OK, FALSE,
488         {
489             {"1234://www.winehq.org/",S_OK,FALSE},
490             {"www.winehq.org",S_OK,FALSE},
491             {"1234://www.winehq.org/",S_OK,FALSE},
492             {"winehq.org",S_OK,FALSE},
493             {"",S_FALSE,FALSE},
494             {"",S_FALSE,FALSE},
495             {"www.winehq.org",S_OK,FALSE},
496             {"",S_FALSE,FALSE},
497             {"/",S_OK,FALSE},
498             {"/",S_OK,FALSE},
499             {"",S_FALSE,FALSE},
500             {"1234://www.winehq.org",S_OK,FALSE},
501             {"1234",S_OK,FALSE},
502             {"",S_FALSE,FALSE},
503             {"",S_FALSE,FALSE}
504         },
505         {
506             {Uri_HOST_DNS,S_OK,FALSE},
507             {0,S_FALSE,FALSE},
508             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
509             {URLZONE_INVALID,E_NOTIMPL,FALSE}
510         }
511     },
512     /* Test's to make sure the parser/canonicalizer handles implicit file schemes correctly. */
513     {   "C:/test/test.mp3", Uri_CREATE_ALLOW_IMPLICIT_FILE_SCHEME, S_OK, FALSE,
514         {
515             {"file:///C:/test/test.mp3",S_OK,FALSE},
516             {"",S_FALSE,FALSE},
517             {"file:///C:/test/test.mp3",S_OK,FALSE},
518             {"",S_FALSE,FALSE},
519             {".mp3",S_OK,FALSE},
520             {"",S_FALSE,FALSE},
521             {"",S_FALSE,FALSE},
522             {"",S_FALSE,FALSE},
523             {"/C:/test/test.mp3",S_OK,FALSE},
524             {"/C:/test/test.mp3",S_OK,FALSE},
525             {"",S_FALSE,FALSE},
526             {"C:/test/test.mp3",S_OK,FALSE},
527             {"file",S_OK,FALSE},
528             {"",S_FALSE,FALSE},
529             {"",S_FALSE,FALSE}
530         },
531         {
532             {Uri_HOST_UNKNOWN,S_OK,FALSE},
533             {0,S_FALSE,FALSE},
534             {URL_SCHEME_FILE,S_OK,FALSE},
535             {URLZONE_INVALID,E_NOTIMPL,FALSE}
536         }
537     },
538     /* Test's to make sure the parser/canonicalizer handles implicit file schemes correctly. */
539     {   "\\\\Server/test.mp3", Uri_CREATE_ALLOW_IMPLICIT_FILE_SCHEME, S_OK, FALSE,
540         {
541             {"file://server/test.mp3",S_OK,FALSE},
542             {"server",S_OK,FALSE},
543             {"file://server/test.mp3",S_OK,FALSE},
544             {"",S_FALSE,FALSE},
545             {".mp3",S_OK,FALSE},
546             {"",S_FALSE,FALSE},
547             {"server",S_OK,FALSE},
548             {"",S_FALSE,FALSE},
549             {"/test.mp3",S_OK,FALSE},
550             {"/test.mp3",S_OK,FALSE},
551             {"",S_FALSE,FALSE},
552             {"\\\\Server/test.mp3",S_OK,FALSE},
553             {"file",S_OK,FALSE},
554             {"",S_FALSE,FALSE},
555             {"",S_FALSE,FALSE}
556         },
557         {
558             {Uri_HOST_DNS,S_OK,FALSE},
559             {0,S_FALSE,FALSE},
560             {URL_SCHEME_FILE,S_OK,FALSE},
561             {URLZONE_INVALID,E_NOTIMPL,FALSE}
562         }
563     },
564     {   "www.winehq.org/test", Uri_CREATE_ALLOW_IMPLICIT_WILDCARD_SCHEME, S_OK, FALSE,
565         {
566             {"*:www.winehq.org/test",S_OK,FALSE},
567             {"www.winehq.org",S_OK,FALSE},
568             {"*:www.winehq.org/test",S_OK,FALSE},
569             {"winehq.org",S_OK,FALSE},
570             {"",S_FALSE,FALSE},
571             {"",S_FALSE,FALSE},
572             {"www.winehq.org",S_OK,FALSE},
573             {"",S_FALSE,FALSE},
574             {"/test",S_OK,FALSE},
575             {"/test",S_OK,FALSE},
576             {"",S_FALSE,FALSE},
577             {"www.winehq.org/test",S_OK,FALSE},
578             {"*",S_OK,FALSE},
579             {"",S_FALSE,FALSE},
580             {"",S_FALSE,FALSE}
581         },
582         {
583             {Uri_HOST_DNS,S_OK,FALSE},
584             {0,S_FALSE,FALSE},
585             {URL_SCHEME_WILDCARD,S_OK,FALSE},
586             {URLZONE_INVALID,E_NOTIMPL,FALSE}
587         }
588     },
589     /* Valid since the '*' is the only character in the scheme name. */
590     {   "*:www.winehq.org/test", 0, S_OK, FALSE,
591         {
592             {"*:www.winehq.org/test",S_OK,FALSE},
593             {"www.winehq.org",S_OK,FALSE},
594             {"*:www.winehq.org/test",S_OK,FALSE},
595             {"winehq.org",S_OK,FALSE},
596             {"",S_FALSE,FALSE},
597             {"",S_FALSE,FALSE},
598             {"www.winehq.org",S_OK,FALSE},
599             {"",S_FALSE,FALSE},
600             {"/test",S_OK,FALSE},
601             {"/test",S_OK,FALSE},
602             {"",S_FALSE,FALSE},
603             {"*:www.winehq.org/test",S_OK,FALSE},
604             {"*",S_OK,FALSE},
605             {"",S_FALSE,FALSE},
606             {"",S_FALSE,FALSE}
607         },
608         {
609             {Uri_HOST_DNS,S_OK,FALSE},
610             {0,S_FALSE,FALSE},
611             {URL_SCHEME_WILDCARD,S_OK,FALSE},
612             {URLZONE_INVALID,E_NOTIMPL,FALSE}
613         }
614     },
615     {   "/../some dir/test.ext", Uri_CREATE_ALLOW_RELATIVE, S_OK, FALSE,
616         {
617             {"/../some dir/test.ext",S_OK,FALSE},
618             {"",S_FALSE,FALSE},
619             {"/../some dir/test.ext",S_OK,FALSE},
620             {"",S_FALSE,FALSE},
621             {".ext",S_OK,FALSE},
622             {"",S_FALSE,FALSE},
623             {"",S_FALSE,FALSE},
624             {"",S_FALSE,FALSE},
625             {"/../some dir/test.ext",S_OK,FALSE},
626             {"/../some dir/test.ext",S_OK,FALSE},
627             {"",S_FALSE,FALSE},
628             {"/../some dir/test.ext",S_OK,FALSE},
629             {"",S_FALSE,FALSE},
630             {"",S_FALSE,FALSE},
631             {"",S_FALSE,FALSE}
632         },
633         {
634             {Uri_HOST_UNKNOWN,S_OK,FALSE},
635             {0,S_FALSE,FALSE},
636             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
637             {URLZONE_INVALID,E_NOTIMPL,FALSE}
638         }
639     },
640     {   "//implicit/wildcard/uri scheme", Uri_CREATE_ALLOW_RELATIVE|Uri_CREATE_ALLOW_IMPLICIT_WILDCARD_SCHEME, S_OK, FALSE,
641         {
642             {"*://implicit/wildcard/uri%20scheme",S_OK,FALSE},
643             {"",S_OK,FALSE},
644             {"*://implicit/wildcard/uri%20scheme",S_OK,FALSE},
645             {"",S_FALSE,FALSE},
646             {"",S_FALSE,FALSE},
647             {"",S_FALSE,FALSE},
648             {"",S_OK,FALSE},
649             {"",S_FALSE,FALSE},
650             {"//implicit/wildcard/uri%20scheme",S_OK,FALSE},
651             {"//implicit/wildcard/uri%20scheme",S_OK,FALSE},
652             {"",S_FALSE,FALSE},
653             {"//implicit/wildcard/uri scheme",S_OK,FALSE},
654             {"*",S_OK,FALSE},
655             {"",S_FALSE,FALSE},
656             {"",S_FALSE,FALSE},
657         },
658         {
659             {Uri_HOST_UNKNOWN,S_OK,FALSE},
660             {0,S_FALSE,FALSE},
661             {URL_SCHEME_WILDCARD,S_OK,FALSE},
662             {URLZONE_INVALID,E_NOTIMPL,FALSE}
663         }
664     },
665     /* URI is considered opaque since CREATE_NO_CRACK_UNKNOWN_SCHEMES is set and its an unknown scheme. */
666     {   "zip://google.com", Uri_CREATE_NO_CRACK_UNKNOWN_SCHEMES, S_OK, FALSE,
667         {
668             {"zip:/.//google.com",S_OK,FALSE},
669             {"",S_FALSE,FALSE},
670             {"zip:/.//google.com",S_OK,FALSE},
671             {"",S_FALSE,FALSE},
672             {".com",S_OK,FALSE},
673             {"",S_FALSE,FALSE},
674             {"",S_FALSE,FALSE},
675             {"",S_FALSE,FALSE},
676             {"/.//google.com",S_OK,FALSE},
677             {"/.//google.com",S_OK,FALSE},
678             {"",S_FALSE,FALSE},
679             {"zip://google.com",S_OK,FALSE},
680             {"zip",S_OK,FALSE},
681             {"",S_FALSE,FALSE},
682             {"",S_FALSE,FALSE}
683         },
684         {
685             {Uri_HOST_UNKNOWN,S_OK,FALSE},
686             {0,S_FALSE,FALSE},
687             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
688             {URLZONE_INVALID,E_NOTIMPL,FALSE}
689         }
690     },
691     /* Windows uses the first occurrence of ':' to delimit the userinfo. */
692     {   "ftp://user:pass:word@winehq.org/", 0, S_OK, FALSE,
693         {
694             {"ftp://user:pass:word@winehq.org/",S_OK,FALSE},
695             {"user:pass:word@winehq.org",S_OK,FALSE},
696             {"ftp://winehq.org/",S_OK,FALSE},
697             {"winehq.org",S_OK,FALSE},
698             {"",S_FALSE,FALSE},
699             {"",S_FALSE,FALSE},
700             {"winehq.org",S_OK,FALSE},
701             {"pass:word",S_OK,FALSE},
702             {"/",S_OK,FALSE},
703             {"/",S_OK,FALSE},
704             {"",S_FALSE,FALSE},
705             {"ftp://user:pass:word@winehq.org/",S_OK,FALSE},
706             {"ftp",S_OK,FALSE},
707             {"user:pass:word",S_OK,FALSE},
708             {"user",S_OK,FALSE}
709         },
710         {
711             {Uri_HOST_DNS,S_OK,FALSE},
712             {21,S_OK,FALSE},
713             {URL_SCHEME_FTP,S_OK,FALSE},
714             {URLZONE_INVALID,E_NOTIMPL,FALSE}
715         }
716     },
717     /* Make sure % encoded unreserved characters are decoded. */
718     {   "ftp://w%49%4Ee:PA%53%53@ftp.google.com/", 0, S_OK, FALSE,
719         {
720             {"ftp://wINe:PASS@ftp.google.com/",S_OK,FALSE},
721             {"wINe:PASS@ftp.google.com",S_OK,FALSE},
722             {"ftp://ftp.google.com/",S_OK,FALSE},
723             {"google.com",S_OK,FALSE},
724             {"",S_FALSE,FALSE},
725             {"",S_FALSE,FALSE},
726             {"ftp.google.com",S_OK,FALSE},
727             {"PASS",S_OK,FALSE},
728             {"/",S_OK,FALSE},
729             {"/",S_OK,FALSE},
730             {"",S_FALSE,FALSE},
731             {"ftp://w%49%4Ee:PA%53%53@ftp.google.com/",S_OK,FALSE},
732             {"ftp",S_OK,FALSE},
733             {"wINe:PASS",S_OK,FALSE},
734             {"wINe",S_OK,FALSE}
735         },
736         {
737             {Uri_HOST_DNS,S_OK,FALSE},
738             {21,S_OK,FALSE},
739             {URL_SCHEME_FTP,S_OK,FALSE},
740             {URLZONE_INVALID,E_NOTIMPL,FALSE}
741         }
742     },
743     /* Make sure % encoded characters which are NOT unreserved are NOT decoded. */
744     {   "ftp://w%5D%5Be:PA%7B%7D@ftp.google.com/", 0, S_OK, FALSE,
745         {
746             {"ftp://w%5D%5Be:PA%7B%7D@ftp.google.com/",S_OK,FALSE},
747             {"w%5D%5Be:PA%7B%7D@ftp.google.com",S_OK,FALSE},
748             {"ftp://ftp.google.com/",S_OK,FALSE},
749             {"google.com",S_OK,FALSE},
750             {"",S_FALSE,FALSE},
751             {"",S_FALSE,FALSE},
752             {"ftp.google.com",S_OK,FALSE},
753             {"PA%7B%7D",S_OK,FALSE},
754             {"/",S_OK,FALSE},
755             {"/",S_OK,FALSE},
756             {"",S_FALSE,FALSE},
757             {"ftp://w%5D%5Be:PA%7B%7D@ftp.google.com/",S_OK,FALSE},
758             {"ftp",S_OK,FALSE},
759             {"w%5D%5Be:PA%7B%7D",S_OK,FALSE},
760             {"w%5D%5Be",S_OK,FALSE}
761         },
762         {
763             {Uri_HOST_DNS,S_OK,FALSE},
764             {21,S_OK,FALSE},
765             {URL_SCHEME_FTP,S_OK,FALSE},
766             {URLZONE_INVALID,E_NOTIMPL,FALSE}
767         }
768     },
769     /* You're allowed to have an empty password portion in the userinfo section. */
770     {   "ftp://empty:@ftp.google.com/", 0, S_OK, FALSE,
771         {
772             {"ftp://empty:@ftp.google.com/",S_OK,FALSE},
773             {"empty:@ftp.google.com",S_OK,FALSE},
774             {"ftp://ftp.google.com/",S_OK,FALSE},
775             {"google.com",S_OK,FALSE},
776             {"",S_FALSE,FALSE},
777             {"",S_FALSE,FALSE},
778             {"ftp.google.com",S_OK,FALSE},
779             {"",S_OK,FALSE},
780             {"/",S_OK,FALSE},
781             {"/",S_OK,FALSE},
782             {"",S_FALSE,FALSE},
783             {"ftp://empty:@ftp.google.com/",S_OK,FALSE},
784             {"ftp",S_OK,FALSE},
785             {"empty:",S_OK,FALSE},
786             {"empty",S_OK,FALSE}
787         },
788         {
789             {Uri_HOST_DNS,S_OK,FALSE},
790             {21,S_OK,FALSE},
791             {URL_SCHEME_FTP,S_OK,FALSE},
792             {URLZONE_INVALID,E_NOTIMPL,FALSE}
793         }
794     },
795     /* Make sure forbidden characters in "userinfo" get encoded. */
796     {   "ftp://\" \"weird@ftp.google.com/", 0, S_OK, FALSE,
797         {
798             {"ftp://%22%20%22weird@ftp.google.com/",S_OK,FALSE},
799             {"%22%20%22weird@ftp.google.com",S_OK,FALSE},
800             {"ftp://ftp.google.com/",S_OK,FALSE},
801             {"google.com",S_OK,FALSE},
802             {"",S_FALSE,FALSE},
803             {"",S_FALSE,FALSE},
804             {"ftp.google.com",S_OK,FALSE},
805             {"",S_FALSE,FALSE},
806             {"/",S_OK,FALSE},
807             {"/",S_OK,FALSE},
808             {"",S_FALSE,FALSE},
809             {"ftp://\" \"weird@ftp.google.com/",S_OK,FALSE},
810             {"ftp",S_OK,FALSE},
811             {"%22%20%22weird",S_OK,FALSE},
812             {"%22%20%22weird",S_OK,FALSE}
813         },
814         {
815             {Uri_HOST_DNS,S_OK,FALSE},
816             {21,S_OK,FALSE},
817             {URL_SCHEME_FTP,S_OK,FALSE},
818             {URLZONE_INVALID,E_NOTIMPL,FALSE}
819         }
820     },
821     /* Make sure the forbidden characters don't get percent encoded. */
822     {   "ftp://\" \"weird@ftp.google.com/", Uri_CREATE_NO_ENCODE_FORBIDDEN_CHARACTERS, S_OK, FALSE,
823         {
824             {"ftp://\" \"weird@ftp.google.com/",S_OK,FALSE},
825             {"\" \"weird@ftp.google.com",S_OK,FALSE},
826             {"ftp://ftp.google.com/",S_OK,FALSE},
827             {"google.com",S_OK,FALSE},
828             {"",S_FALSE,FALSE},
829             {"",S_FALSE,FALSE},
830             {"ftp.google.com",S_OK,FALSE},
831             {"",S_FALSE,FALSE},
832             {"/",S_OK,FALSE},
833             {"/",S_OK,FALSE},
834             {"",S_FALSE,FALSE},
835             {"ftp://\" \"weird@ftp.google.com/",S_OK,FALSE},
836             {"ftp",S_OK,FALSE},
837             {"\" \"weird",S_OK,FALSE},
838             {"\" \"weird",S_OK,FALSE}
839         },
840         {
841             {Uri_HOST_DNS,S_OK,FALSE},
842             {21,S_OK,FALSE},
843             {URL_SCHEME_FTP,S_OK,FALSE},
844             {URLZONE_INVALID,E_NOTIMPL,FALSE}
845         }
846     },
847     /* Make sure already percent encoded characters don't get unencoded. */
848     {   "ftp://\"%20\"weird@ftp.google.com/\"%20\"weird", Uri_CREATE_NO_ENCODE_FORBIDDEN_CHARACTERS, S_OK, FALSE,
849         {
850             {"ftp://\"%20\"weird@ftp.google.com/\"%20\"weird",S_OK,FALSE},
851             {"\"%20\"weird@ftp.google.com",S_OK,FALSE},
852             {"ftp://ftp.google.com/\"%20\"weird",S_OK,FALSE},
853             {"google.com",S_OK,FALSE},
854             {"",S_FALSE,FALSE},
855             {"",S_FALSE,FALSE},
856             {"ftp.google.com",S_OK,FALSE},
857             {"",S_FALSE,FALSE},
858             {"/\"%20\"weird",S_OK,FALSE},
859             {"/\"%20\"weird",S_OK,FALSE},
860             {"",S_FALSE,FALSE},
861             {"ftp://\"%20\"weird@ftp.google.com/\"%20\"weird",S_OK,FALSE},
862             {"ftp",S_OK,FALSE},
863             {"\"%20\"weird",S_OK,FALSE},
864             {"\"%20\"weird",S_OK,FALSE}
865         },
866         {
867             {Uri_HOST_DNS,S_OK,FALSE},
868             {21,S_OK,FALSE},
869             {URL_SCHEME_FTP,S_OK,FALSE},
870             {URLZONE_INVALID,E_NOTIMPL,FALSE}
871         }
872     },
873     /* Allowed to have invalid % encoded because its an unknown scheme type. */
874     {   "zip://%xy:word@winehq.org/", 0, S_OK, FALSE,
875         {
876             {"zip://%xy:word@winehq.org/",S_OK,FALSE},
877             {"%xy:word@winehq.org",S_OK,FALSE},
878             {"zip://%xy:word@winehq.org/",S_OK,FALSE},
879             {"winehq.org",S_OK,FALSE},
880             {"",S_FALSE,FALSE},
881             {"",S_FALSE,FALSE},
882             {"winehq.org",S_OK,FALSE},
883             {"word",S_OK,FALSE},
884             {"/",S_OK,FALSE},
885             {"/",S_OK,FALSE},
886             {"",S_FALSE,FALSE},
887             {"zip://%xy:word@winehq.org/",S_OK,FALSE},
888             {"zip",S_OK,FALSE},
889             {"%xy:word",S_OK,FALSE},
890             {"%xy",S_OK,FALSE}
891         },
892         {
893             {Uri_HOST_DNS,S_OK,FALSE},
894             {0,S_FALSE,FALSE},
895             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
896             {URLZONE_INVALID,E_NOTIMPL,FALSE}
897         }
898     },
899     /* Unreserved, percent encoded characters aren't decoded in the userinfo because the scheme
900      * isn't known.
901      */
902     {   "zip://%2E:%52%53ord@winehq.org/", 0, S_OK, FALSE,
903         {
904             {"zip://%2E:%52%53ord@winehq.org/",S_OK,FALSE},
905             {"%2E:%52%53ord@winehq.org",S_OK,FALSE},
906             {"zip://%2E:%52%53ord@winehq.org/",S_OK,FALSE},
907             {"winehq.org",S_OK,FALSE},
908             {"",S_FALSE,FALSE},
909             {"",S_FALSE,FALSE},
910             {"winehq.org",S_OK,FALSE},
911             {"%52%53ord",S_OK,FALSE},
912             {"/",S_OK,FALSE},
913             {"/",S_OK,FALSE},
914             {"",S_FALSE,FALSE},
915             {"zip://%2E:%52%53ord@winehq.org/",S_OK,FALSE},
916             {"zip",S_OK,FALSE},
917             {"%2E:%52%53ord",S_OK,FALSE},
918             {"%2E",S_OK,FALSE}
919         },
920         {
921             {Uri_HOST_DNS,S_OK,FALSE},
922             {0,S_FALSE,FALSE},
923             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
924             {URLZONE_INVALID,E_NOTIMPL,FALSE}
925         }
926     },
927     {   "ftp://[](),'test':word@winehq.org/", 0, S_OK, FALSE,
928         {
929             {"ftp://[](),'test':word@winehq.org/",S_OK,FALSE},
930             {"[](),'test':word@winehq.org",S_OK,FALSE},
931             {"ftp://winehq.org/",S_OK,FALSE},
932             {"winehq.org",S_OK,FALSE},
933             {"",S_FALSE,FALSE},
934             {"",S_FALSE,FALSE},
935             {"winehq.org",S_OK,FALSE},
936             {"word",S_OK,FALSE},
937             {"/",S_OK,FALSE},
938             {"/",S_OK,FALSE},
939             {"",S_FALSE,FALSE},
940             {"ftp://[](),'test':word@winehq.org/",S_OK,FALSE},
941             {"ftp",S_OK,FALSE},
942             {"[](),'test':word",S_OK,FALSE},
943             {"[](),'test'",S_OK,FALSE}
944         },
945         {
946             {Uri_HOST_DNS,S_OK,FALSE},
947             {21,S_OK,FALSE},
948             {URL_SCHEME_FTP,S_OK,FALSE},
949             {URLZONE_INVALID,E_NOTIMPL,FALSE}
950         }
951     },
952     {   "ftp://test?:word@winehq.org/", 0, S_OK, FALSE,
953         {
954             {"ftp://test/?:word@winehq.org/",S_OK,FALSE},
955             {"test",S_OK,FALSE},
956             {"ftp://test/?:word@winehq.org/",S_OK,FALSE},
957             {"",S_FALSE,FALSE},
958             {"",S_FALSE,FALSE},
959             {"",S_FALSE,FALSE},
960             {"test",S_OK,FALSE},
961             {"",S_FALSE,FALSE},
962             {"/",S_OK,FALSE},
963             {"/?:word@winehq.org/",S_OK,FALSE},
964             {"?:word@winehq.org/",S_OK,FALSE},
965             {"ftp://test?:word@winehq.org/",S_OK,FALSE},
966             {"ftp",S_OK,FALSE},
967             {"",S_FALSE,FALSE},
968             {"",S_FALSE,FALSE}
969         },
970         {
971             {Uri_HOST_DNS,S_OK,FALSE},
972             {21,S_OK,FALSE},
973             {URL_SCHEME_FTP,S_OK,FALSE},
974             {URLZONE_INVALID,E_NOTIMPL,FALSE}
975         }
976     },
977     {   "ftp://test#:word@winehq.org/", 0, S_OK, FALSE,
978         {
979             {"ftp://test/#:word@winehq.org/",S_OK,FALSE},
980             {"test",S_OK,FALSE},
981             {"ftp://test/#:word@winehq.org/",S_OK,FALSE},
982             {"",S_FALSE,FALSE},
983             {"",S_FALSE,FALSE},
984             {"#:word@winehq.org/",S_OK,FALSE},
985             {"test",S_OK,FALSE},
986             {"",S_FALSE,FALSE},
987             {"/",S_OK,FALSE},
988             {"/",S_OK,FALSE},
989             {"",S_FALSE,FALSE},
990             {"ftp://test#:word@winehq.org/",S_OK,FALSE},
991             {"ftp",S_OK,FALSE},
992             {"",S_FALSE,FALSE},
993             {"",S_FALSE,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 a backslash in the userinfo since it's an unknown scheme. */
1003     {   "zip://test\\:word@winehq.org/", 0, S_OK, FALSE,
1004         {
1005             {"zip://test\\:word@winehq.org/",S_OK,FALSE},
1006             {"test\\:word@winehq.org",S_OK,FALSE},
1007             {"zip://test\\: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://test\\:word@winehq.org/",S_OK,FALSE},
1017             {"zip",S_OK,FALSE},
1018             {"test\\:word",S_OK,FALSE},
1019             {"test\\",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     /* It normalizes IPv4 addresses correctly. */
1029     {   "http://127.000.000.100/", 0, S_OK, FALSE,
1030         {
1031             {"http://127.0.0.100/",S_OK,FALSE},
1032             {"127.0.0.100",S_OK,FALSE},
1033             {"http://127.0.0.100/",S_OK,FALSE},
1034             {"",S_FALSE,FALSE},
1035             {"",S_FALSE,FALSE},
1036             {"",S_FALSE,FALSE},
1037             {"127.0.0.100",S_OK,FALSE},
1038             {"",S_FALSE,FALSE},
1039             {"/",S_OK,FALSE},
1040             {"/",S_OK,FALSE},
1041             {"",S_FALSE,FALSE},
1042             {"http://127.000.000.100/",S_OK,FALSE},
1043             {"http",S_OK,FALSE},
1044             {"",S_FALSE,FALSE},
1045             {"",S_FALSE,FALSE}
1046         },
1047         {
1048             {Uri_HOST_IPV4,S_OK,FALSE},
1049             {80,S_OK,FALSE},
1050             {URL_SCHEME_HTTP,S_OK,FALSE},
1051             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1052         }
1053     },
1054     {   "http://127.0.0.1:8000", 0, S_OK, FALSE,
1055         {
1056             {"http://127.0.0.1:8000/",S_OK},
1057             {"127.0.0.1:8000",S_OK},
1058             {"http://127.0.0.1:8000/",S_OK},
1059             {"",S_FALSE},
1060             {"",S_FALSE},
1061             {"",S_FALSE},
1062             {"127.0.0.1",S_OK},
1063             {"",S_FALSE},
1064             {"/",S_OK},
1065             {"/",S_OK},
1066             {"",S_FALSE},
1067             {"http://127.0.0.1:8000",S_OK},
1068             {"http",S_OK},
1069             {"",S_FALSE},
1070             {"",S_FALSE}
1071         },
1072         {
1073             {Uri_HOST_IPV4,S_OK,FALSE},
1074             {8000,S_OK,FALSE},
1075             {URL_SCHEME_HTTP,S_OK,FALSE},
1076             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1077         }
1078     },
1079     /* Make sure it normalizes partial IPv4 addresses correctly. */
1080     {   "http://127.0/", 0, S_OK, FALSE,
1081         {
1082             {"http://127.0.0.0/",S_OK,FALSE},
1083             {"127.0.0.0",S_OK,FALSE},
1084             {"http://127.0.0.0/",S_OK,FALSE},
1085             {"",S_FALSE,FALSE},
1086             {"",S_FALSE,FALSE},
1087             {"",S_FALSE,FALSE},
1088             {"127.0.0.0",S_OK,FALSE},
1089             {"",S_FALSE,FALSE},
1090             {"/",S_OK,FALSE},
1091             {"/",S_OK,FALSE},
1092             {"",S_FALSE,FALSE},
1093             {"http://127.0/",S_OK,FALSE},
1094             {"http",S_OK,FALSE},
1095             {"",S_FALSE,FALSE},
1096             {"",S_FALSE,FALSE}
1097         },
1098         {
1099             {Uri_HOST_IPV4,S_OK,FALSE},
1100             {80,S_OK,FALSE},
1101             {URL_SCHEME_HTTP,S_OK,FALSE},
1102             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1103         }
1104     },
1105     /* Make sure it converts implicit IPv4's correctly. */
1106     {   "http://123456/", 0, S_OK, FALSE,
1107         {
1108             {"http://0.1.226.64/",S_OK,FALSE},
1109             {"0.1.226.64",S_OK,FALSE},
1110             {"http://0.1.226.64/",S_OK,FALSE},
1111             {"",S_FALSE,FALSE},
1112             {"",S_FALSE,FALSE},
1113             {"",S_FALSE,FALSE},
1114             {"0.1.226.64",S_OK,FALSE},
1115             {"",S_FALSE,FALSE},
1116             {"/",S_OK,FALSE},
1117             {"/",S_OK,FALSE},
1118             {"",S_FALSE,FALSE},
1119             {"http://123456/",S_OK,FALSE},
1120             {"http",S_OK,FALSE},
1121             {"",S_FALSE,FALSE},
1122             {"",S_FALSE,FALSE}
1123         },
1124         {
1125             {Uri_HOST_IPV4,S_OK,FALSE},
1126             {80,S_OK,FALSE},
1127             {URL_SCHEME_HTTP,S_OK,FALSE},
1128             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1129         }
1130     },
1131     /* UINT_MAX */
1132     {   "http://4294967295/", 0, S_OK, FALSE,
1133         {
1134             {"http://255.255.255.255/",S_OK,FALSE},
1135             {"255.255.255.255",S_OK,FALSE},
1136             {"http://255.255.255.255/",S_OK,FALSE},
1137             {"",S_FALSE,FALSE},
1138             {"",S_FALSE,FALSE},
1139             {"",S_FALSE,FALSE},
1140             {"255.255.255.255",S_OK,FALSE},
1141             {"",S_FALSE,FALSE},
1142             {"/",S_OK,FALSE},
1143             {"/",S_OK,FALSE},
1144             {"",S_FALSE,FALSE},
1145             {"http://4294967295/",S_OK,FALSE},
1146             {"http",S_OK,FALSE},
1147             {"",S_FALSE,FALSE},
1148             {"",S_FALSE,FALSE}
1149         },
1150         {
1151             {Uri_HOST_IPV4,S_OK,FALSE},
1152             {80,S_OK,FALSE},
1153             {URL_SCHEME_HTTP,S_OK,FALSE},
1154             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1155         }
1156     },
1157     /* UINT_MAX+1 */
1158     {   "http://4294967296/", 0, S_OK, FALSE,
1159         {
1160             {"http://4294967296/",S_OK,FALSE},
1161             {"4294967296",S_OK,FALSE},
1162             {"http://4294967296/",S_OK,FALSE},
1163             {"",S_FALSE,FALSE},
1164             {"",S_FALSE,FALSE},
1165             {"",S_FALSE,FALSE},
1166             {"4294967296",S_OK,FALSE},
1167             {"",S_FALSE,FALSE},
1168             {"/",S_OK,FALSE},
1169             {"/",S_OK,FALSE},
1170             {"",S_FALSE,FALSE},
1171             {"http://4294967296/",S_OK,FALSE},
1172             {"http",S_OK,FALSE},
1173             {"",S_FALSE,FALSE},
1174             {"",S_FALSE,FALSE}
1175         },
1176         {
1177             {Uri_HOST_DNS,S_OK,FALSE},
1178             {80,S_OK,FALSE},
1179             {URL_SCHEME_HTTP,S_OK,FALSE},
1180             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1181         }
1182     },
1183     /* Window's doesn't normalize IP address for unknown schemes. */
1184     {   "1234://4294967295/", 0, S_OK, FALSE,
1185         {
1186             {"1234://4294967295/",S_OK,FALSE},
1187             {"4294967295",S_OK,FALSE},
1188             {"1234://4294967295/",S_OK,FALSE},
1189             {"",S_FALSE,FALSE},
1190             {"",S_FALSE,FALSE},
1191             {"",S_FALSE,FALSE},
1192             {"4294967295",S_OK,FALSE},
1193             {"",S_FALSE,FALSE},
1194             {"/",S_OK,FALSE},
1195             {"/",S_OK,FALSE},
1196             {"",S_FALSE,FALSE},
1197             {"1234://4294967295/",S_OK,FALSE},
1198             {"1234",S_OK,FALSE},
1199             {"",S_FALSE,FALSE},
1200             {"",S_FALSE,FALSE}
1201         },
1202         {
1203             {Uri_HOST_IPV4,S_OK,FALSE},
1204             {0,S_FALSE,FALSE},
1205             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1206             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1207         }
1208     },
1209     /* Window's doesn't normalize IP address for unknown schemes. */
1210     {   "1234://127.001/", 0, S_OK, FALSE,
1211         {
1212             {"1234://127.001/",S_OK,FALSE},
1213             {"127.001",S_OK,FALSE},
1214             {"1234://127.001/",S_OK,FALSE},
1215             {"",S_FALSE,FALSE},
1216             {"",S_FALSE,FALSE},
1217             {"",S_FALSE,FALSE},
1218             {"127.001",S_OK,FALSE},
1219             {"",S_FALSE,FALSE},
1220             {"/",S_OK,FALSE},
1221             {"/",S_OK,FALSE},
1222             {"",S_FALSE,FALSE},
1223             {"1234://127.001/",S_OK,FALSE},
1224             {"1234",S_OK,FALSE},
1225             {"",S_FALSE,FALSE},
1226             {"",S_FALSE,FALSE}
1227         },
1228         {
1229             {Uri_HOST_IPV4,S_OK,FALSE},
1230             {0,S_FALSE,FALSE},
1231             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1232             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1233         }
1234     },
1235     {   "http://[FEDC:BA98::3210]", 0, S_OK, FALSE,
1236         {
1237             {"http://[fedc:ba98::3210]/",S_OK,FALSE},
1238             {"[fedc:ba98::3210]",S_OK,FALSE},
1239             {"http://[fedc:ba98::3210]/",S_OK,FALSE},
1240             {"",S_FALSE,FALSE},
1241             {"",S_FALSE,FALSE},
1242             {"",S_FALSE,FALSE},
1243             {"fedc:ba98::3210",S_OK,FALSE},
1244             {"",S_FALSE,FALSE},
1245             {"/",S_OK,FALSE},
1246             {"/",S_OK,FALSE},
1247             {"",S_FALSE,FALSE},
1248             {"http://[FEDC:BA98::3210]",S_OK,FALSE},
1249             {"http",S_OK,FALSE},
1250             {"",S_FALSE,FALSE},
1251             {"",S_FALSE,FALSE},
1252         },
1253         {
1254             {Uri_HOST_IPV6,S_OK,FALSE},
1255             {80,S_OK,FALSE},
1256             {URL_SCHEME_HTTP,S_OK,FALSE},
1257             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1258         }
1259     },
1260     {   "http://[::]", 0, S_OK, FALSE,
1261         {
1262             {"http://[::]/",S_OK,FALSE},
1263             {"[::]",S_OK,FALSE},
1264             {"http://[::]/",S_OK,FALSE},
1265             {"",S_FALSE,FALSE},
1266             {"",S_FALSE,FALSE},
1267             {"",S_FALSE,FALSE},
1268             {"::",S_OK,FALSE},
1269             {"",S_FALSE,FALSE},
1270             {"/",S_OK,FALSE},
1271             {"/",S_OK,FALSE},
1272             {"",S_FALSE,FALSE},
1273             {"http://[::]",S_OK,FALSE},
1274             {"http",S_OK,FALSE},
1275             {"",S_FALSE,FALSE},
1276             {"",S_FALSE,FALSE},
1277         },
1278         {
1279             {Uri_HOST_IPV6,S_OK,FALSE},
1280             {80,S_OK,FALSE},
1281             {URL_SCHEME_HTTP,S_OK,FALSE},
1282             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1283         }
1284     },
1285     {   "http://[FEDC:BA98::]", 0, S_OK, FALSE,
1286         {
1287             {"http://[fedc:ba98::]/",S_OK,FALSE},
1288             {"[fedc:ba98::]",S_OK,FALSE},
1289             {"http://[fedc:ba98::]/",S_OK,FALSE},
1290             {"",S_FALSE,FALSE},
1291             {"",S_FALSE,FALSE},
1292             {"",S_FALSE,FALSE},
1293             {"fedc:ba98::",S_OK,FALSE},
1294             {"",S_FALSE,FALSE},
1295             {"/",S_OK,FALSE},
1296             {"/",S_OK,FALSE},
1297             {"",S_FALSE,FALSE},
1298             {"http://[FEDC:BA98::]",S_OK,FALSE},
1299             {"http",S_OK,FALSE},
1300             {"",S_FALSE,FALSE},
1301             {"",S_FALSE,FALSE},
1302         },
1303         {
1304             {Uri_HOST_IPV6,S_OK,FALSE},
1305             {80,S_OK,FALSE},
1306             {URL_SCHEME_HTTP,S_OK,FALSE},
1307             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1308         }
1309     },
1310     /* Valid even with 2 byte elision because it doesn't appear the beginning or end. */
1311     {   "http://[1::3:4:5:6:7:8]", 0, S_OK, FALSE,
1312         {
1313             {"http://[1:0:3:4:5:6:7:8]/",S_OK,FALSE},
1314             {"[1:0:3:4:5:6:7:8]",S_OK,FALSE},
1315             {"http://[1:0:3:4:5:6:7:8]/",S_OK,FALSE},
1316             {"",S_FALSE,FALSE},
1317             {"",S_FALSE,FALSE},
1318             {"",S_FALSE,FALSE},
1319             {"1:0:3:4:5:6:7:8",S_OK,FALSE},
1320             {"",S_FALSE,FALSE},
1321             {"/",S_OK,FALSE},
1322             {"/",S_OK,FALSE},
1323             {"",S_FALSE,FALSE},
1324             {"http://[1::3:4:5:6:7:8]",S_OK,FALSE},
1325             {"http",S_OK,FALSE},
1326             {"",S_FALSE,FALSE},
1327             {"",S_FALSE,FALSE},
1328         },
1329         {
1330             {Uri_HOST_IPV6,S_OK,FALSE},
1331             {80,S_OK,FALSE},
1332             {URL_SCHEME_HTTP,S_OK,FALSE},
1333             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1334         }
1335     },
1336     {   "http://[v2.34]/", 0, S_OK, FALSE,
1337         {
1338             {"http://[v2.34]/",S_OK,FALSE},
1339             {"[v2.34]",S_OK,FALSE},
1340             {"http://[v2.34]/",S_OK,FALSE},
1341             {"",S_FALSE,FALSE},
1342             {"",S_FALSE,FALSE},
1343             {"",S_FALSE,FALSE},
1344             {"[v2.34]",S_OK,FALSE},
1345             {"",S_FALSE,FALSE},
1346             {"/",S_OK,FALSE},
1347             {"/",S_OK,FALSE},
1348             {"",S_FALSE,FALSE},
1349             {"http://[v2.34]/",S_OK,FALSE},
1350             {"http",S_OK,FALSE},
1351             {"",S_FALSE,FALSE},
1352             {"",S_FALSE,FALSE}
1353         },
1354         {
1355             {Uri_HOST_UNKNOWN,S_OK,FALSE},
1356             {80,S_OK,FALSE},
1357             {URL_SCHEME_HTTP,S_OK,FALSE},
1358             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1359         }
1360     },
1361     /* Windows ignores ':' if they appear after a '[' on a non-IPLiteral host. */
1362     {   "http://[xyz:12345.com/test", 0, S_OK, FALSE,
1363         {
1364             {"http://[xyz:12345.com/test",S_OK,FALSE},
1365             {"[xyz:12345.com",S_OK,FALSE},
1366             {"http://[xyz:12345.com/test",S_OK,FALSE},
1367             {"[xyz:12345.com",S_OK,FALSE},
1368             {"",S_FALSE,FALSE},
1369             {"",S_FALSE,FALSE},
1370             {"[xyz:12345.com",S_OK,FALSE},
1371             {"",S_FALSE,FALSE},
1372             {"/test",S_OK,FALSE},
1373             {"/test",S_OK,FALSE},
1374             {"",S_FALSE,FALSE},
1375             {"http://[xyz:12345.com/test",S_OK,FALSE},
1376             {"http",S_OK,FALSE},
1377             {"",S_FALSE,FALSE},
1378             {"",S_FALSE,FALSE}
1379         },
1380         {
1381             {Uri_HOST_DNS,S_OK,FALSE},
1382             {80,S_OK,FALSE},
1383             {URL_SCHEME_HTTP,S_OK,FALSE},
1384             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1385         }
1386     },
1387     /* Valid URI since the '[' and ']' don't appear at the beginning and end
1388      * of the host name (respectively).
1389      */
1390     {   "ftp://www.[works].com/", 0, S_OK, FALSE,
1391         {
1392             {"ftp://www.[works].com/",S_OK,FALSE},
1393             {"www.[works].com",S_OK,FALSE},
1394             {"ftp://www.[works].com/",S_OK,FALSE},
1395             {"[works].com",S_OK,FALSE},
1396             {"",S_FALSE,FALSE},
1397             {"",S_FALSE,FALSE},
1398             {"www.[works].com",S_OK,FALSE},
1399             {"",S_FALSE,FALSE},
1400             {"/",S_OK,FALSE},
1401             {"/",S_OK,FALSE},
1402             {"",S_FALSE,FALSE},
1403             {"ftp://www.[works].com/",S_OK,FALSE},
1404             {"ftp",S_OK,FALSE},
1405             {"",S_FALSE,FALSE},
1406             {"",S_FALSE,FALSE}
1407         },
1408         {
1409             {Uri_HOST_DNS,S_OK,FALSE},
1410             {21,S_OK,FALSE},
1411             {URL_SCHEME_FTP,S_OK,FALSE},
1412             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1413         }
1414     },
1415     /* Considers ':' a delimiter since it appears after the ']'. */
1416     {   "http://www.google.com]:12345/", 0, S_OK, FALSE,
1417         {
1418             {"http://www.google.com]:12345/",S_OK,FALSE},
1419             {"www.google.com]:12345",S_OK,FALSE},
1420             {"http://www.google.com]:12345/",S_OK,FALSE},
1421             {"google.com]",S_OK,FALSE},
1422             {"",S_FALSE,FALSE},
1423             {"",S_FALSE,FALSE},
1424             {"www.google.com]",S_OK,FALSE},
1425             {"",S_FALSE,FALSE},
1426             {"/",S_OK,FALSE},
1427             {"/",S_OK,FALSE},
1428             {"",S_FALSE,FALSE},
1429             {"http://www.google.com]:12345/",S_OK,FALSE},
1430             {"http",S_OK,FALSE},
1431             {"",S_FALSE,FALSE},
1432             {"",S_FALSE,FALSE}
1433         },
1434         {
1435             {Uri_HOST_DNS,S_OK,FALSE},
1436             {12345,S_OK,FALSE},
1437             {URL_SCHEME_HTTP,S_OK,FALSE},
1438             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1439         }
1440     },
1441     /* Unknown scheme types can have invalid % encoded data in the hostname. */
1442     {   "zip://w%XXw%GEw.google.com/", 0, S_OK, FALSE,
1443         {
1444             {"zip://w%XXw%GEw.google.com/",S_OK,FALSE},
1445             {"w%XXw%GEw.google.com",S_OK,FALSE},
1446             {"zip://w%XXw%GEw.google.com/",S_OK,FALSE},
1447             {"google.com",S_OK,FALSE},
1448             {"",S_FALSE,FALSE},
1449             {"",S_FALSE,FALSE},
1450             {"w%XXw%GEw.google.com",S_OK,FALSE},
1451             {"",S_FALSE,FALSE},
1452             {"/",S_OK,FALSE},
1453             {"/",S_OK,FALSE},
1454             {"",S_FALSE,FALSE},
1455             {"zip://w%XXw%GEw.google.com/",S_OK,FALSE},
1456             {"zip",S_OK,FALSE},
1457             {"",S_FALSE,FALSE},
1458             {"",S_FALSE,FALSE}
1459         },
1460         {
1461             {Uri_HOST_DNS,S_OK,FALSE},
1462             {0,S_FALSE,FALSE},
1463             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1464             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1465         }
1466     },
1467     /* Unknown scheme types hostname doesn't get lower cased. */
1468     {   "zip://GOOGLE.com/", 0, S_OK, FALSE,
1469         {
1470             {"zip://GOOGLE.com/",S_OK,FALSE},
1471             {"GOOGLE.com",S_OK,FALSE},
1472             {"zip://GOOGLE.com/",S_OK,FALSE},
1473             {"GOOGLE.com",S_OK,FALSE},
1474             {"",S_FALSE,FALSE},
1475             {"",S_FALSE,FALSE},
1476             {"GOOGLE.com",S_OK,FALSE},
1477             {"",S_FALSE,FALSE},
1478             {"/",S_OK,FALSE},
1479             {"/",S_OK,FALSE},
1480             {"",S_FALSE,FALSE},
1481             {"zip://GOOGLE.com/",S_OK,FALSE},
1482             {"zip",S_OK,FALSE},
1483             {"",S_FALSE,FALSE},
1484             {"",S_FALSE,FALSE}
1485         },
1486         {
1487             {Uri_HOST_DNS,S_OK,FALSE},
1488             {0,S_FALSE,FALSE},
1489             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1490             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1491         }
1492     },
1493     /* Hostname gets lower-cased for known scheme types. */
1494     {   "http://WWW.GOOGLE.com/", 0, S_OK, FALSE,
1495         {
1496             {"http://www.google.com/",S_OK,FALSE},
1497             {"www.google.com",S_OK,FALSE},
1498             {"http://www.google.com/",S_OK,FALSE},
1499             {"google.com",S_OK,FALSE},
1500             {"",S_FALSE,FALSE},
1501             {"",S_FALSE,FALSE},
1502             {"www.google.com",S_OK,FALSE},
1503             {"",S_FALSE,FALSE},
1504             {"/",S_OK,FALSE},
1505             {"/",S_OK,FALSE},
1506             {"",S_FALSE,FALSE},
1507             {"http://WWW.GOOGLE.com/",S_OK,FALSE},
1508             {"http",S_OK,FALSE},
1509             {"",S_FALSE,FALSE},
1510             {"",S_FALSE,FALSE}
1511         },
1512         {
1513             {Uri_HOST_DNS,S_OK,FALSE},
1514             {80,S_OK,FALSE},
1515             {URL_SCHEME_HTTP,S_OK,FALSE},
1516             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1517         }
1518     },
1519     /* Characters that get % encoded in the hostname also have their percent
1520      * encoded forms lower cased.
1521      */
1522     {   "http://www.%7Cgoogle|.com/", 0, S_OK, FALSE,
1523         {
1524             {"http://www.%7cgoogle%7c.com/",S_OK,FALSE},
1525             {"www.%7cgoogle%7c.com",S_OK,FALSE},
1526             {"http://www.%7cgoogle%7c.com/",S_OK,FALSE},
1527             {"%7cgoogle%7c.com",S_OK,FALSE},
1528             {"",S_FALSE,FALSE},
1529             {"",S_FALSE,FALSE},
1530             {"www.%7cgoogle%7c.com",S_OK,FALSE},
1531             {"",S_FALSE,FALSE},
1532             {"/",S_OK,FALSE},
1533             {"/",S_OK,FALSE},
1534             {"",S_FALSE,FALSE},
1535             {"http://www.%7Cgoogle|.com/",S_OK,FALSE},
1536             {"http",S_OK,FALSE},
1537             {"",S_FALSE,FALSE},
1538             {"",S_FALSE,FALSE}
1539         },
1540         {
1541             {Uri_HOST_DNS,S_OK,FALSE},
1542             {80,S_OK,FALSE},
1543             {URL_SCHEME_HTTP,S_OK,FALSE},
1544             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1545         }
1546     },
1547     /* IPv4 addresses attached to IPv6 can be included in elisions. */
1548     {   "http://[1:2:3:4:5:6:0.0.0.0]", 0, S_OK, FALSE,
1549         {
1550             {"http://[1:2:3:4:5:6::]/",S_OK,FALSE},
1551             {"[1:2:3:4:5:6::]",S_OK,FALSE},
1552             {"http://[1:2:3:4:5:6::]/",S_OK,FALSE},
1553             {"",S_FALSE,FALSE},
1554             {"",S_FALSE,FALSE},
1555             {"",S_FALSE,FALSE},
1556             {"1:2:3:4:5:6::",S_OK,FALSE},
1557             {"",S_FALSE,FALSE},
1558             {"/",S_OK,FALSE},
1559             {"/",S_OK,FALSE},
1560             {"",S_FALSE,FALSE},
1561             {"http://[1:2:3:4:5:6:0.0.0.0]",S_OK,FALSE},
1562             {"http",S_OK,FALSE},
1563             {"",S_FALSE,FALSE},
1564             {"",S_FALSE,FALSE},
1565         },
1566         {
1567             {Uri_HOST_IPV6,S_OK,FALSE},
1568             {80,S_OK,FALSE},
1569             {URL_SCHEME_HTTP,S_OK,FALSE},
1570             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1571         }
1572     },
1573     /* IPv4 addresses get normalized. */
1574     {   "http://[::001.002.003.000]", 0, S_OK, FALSE,
1575         {
1576             {"http://[::1.2.3.0]/",S_OK,FALSE},
1577             {"[::1.2.3.0]",S_OK,FALSE},
1578             {"http://[::1.2.3.0]/",S_OK,FALSE},
1579             {"",S_FALSE,FALSE},
1580             {"",S_FALSE,FALSE},
1581             {"",S_FALSE,FALSE},
1582             {"::1.2.3.0",S_OK,FALSE},
1583             {"",S_FALSE,FALSE},
1584             {"/",S_OK,FALSE},
1585             {"/",S_OK,FALSE},
1586             {"",S_FALSE,FALSE},
1587             {"http://[::001.002.003.000]",S_OK,FALSE},
1588             {"http",S_OK,FALSE},
1589             {"",S_FALSE,FALSE},
1590             {"",S_FALSE,FALSE},
1591         },
1592         {
1593             {Uri_HOST_IPV6,S_OK,FALSE},
1594             {80,S_OK,FALSE},
1595             {URL_SCHEME_HTTP,S_OK,FALSE},
1596             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1597         }
1598     },
1599     /* Windows doesn't do anything to IPv6's in unknown schemes. */
1600     {   "zip://[0001:0:000:0004:0005:0006:001.002.003.000]", 0, S_OK, FALSE,
1601         {
1602             {"zip://[0001:0:000:0004:0005:0006:001.002.003.000]/",S_OK,FALSE},
1603             {"[0001:0:000:0004:0005:0006:001.002.003.000]",S_OK,FALSE},
1604             {"zip://[0001:0:000:0004:0005:0006:001.002.003.000]/",S_OK,FALSE},
1605             {"",S_FALSE,FALSE},
1606             {"",S_FALSE,FALSE},
1607             {"",S_FALSE,FALSE},
1608             {"0001:0:000:0004:0005:0006:001.002.003.000",S_OK,FALSE},
1609             {"",S_FALSE,FALSE},
1610             {"/",S_OK,FALSE},
1611             {"/",S_OK,FALSE},
1612             {"",S_FALSE,FALSE},
1613             {"zip://[0001:0:000:0004:0005:0006:001.002.003.000]",S_OK,FALSE},
1614             {"zip",S_OK,FALSE},
1615             {"",S_FALSE,FALSE},
1616             {"",S_FALSE,FALSE},
1617         },
1618         {
1619             {Uri_HOST_IPV6,S_OK,FALSE},
1620             {0,S_FALSE,FALSE},
1621             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1622             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1623         }
1624     },
1625     /* IPv4 address is converted into 2 h16 components. */
1626     {   "http://[ffff::192.222.111.32]", 0, S_OK, FALSE,
1627         {
1628             {"http://[ffff::c0de:6f20]/",S_OK,FALSE},
1629             {"[ffff::c0de:6f20]",S_OK,FALSE},
1630             {"http://[ffff::c0de:6f20]/",S_OK,FALSE},
1631             {"",S_FALSE,FALSE},
1632             {"",S_FALSE,FALSE},
1633             {"",S_FALSE,FALSE},
1634             {"ffff::c0de:6f20",S_OK,FALSE},
1635             {"",S_FALSE,FALSE},
1636             {"/",S_OK,FALSE},
1637             {"/",S_OK,FALSE},
1638             {"",S_FALSE,FALSE},
1639             {"http://[ffff::192.222.111.32]",S_OK,FALSE},
1640             {"http",S_OK,FALSE},
1641             {"",S_FALSE,FALSE},
1642             {"",S_FALSE,FALSE},
1643         },
1644         {
1645             {Uri_HOST_IPV6,S_OK,FALSE},
1646             {80,S_OK,FALSE},
1647             {URL_SCHEME_HTTP,S_OK,FALSE},
1648             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1649         }
1650     },
1651     /* Max value for a port. */
1652     {   "http://google.com:65535", 0, S_OK, FALSE,
1653         {
1654             {"http://google.com:65535/",S_OK,FALSE},
1655             {"google.com:65535",S_OK,FALSE},
1656             {"http://google.com:65535/",S_OK,FALSE},
1657             {"google.com",S_OK,FALSE},
1658             {"",S_FALSE,FALSE},
1659             {"",S_FALSE,FALSE},
1660             {"google.com",S_OK,FALSE},
1661             {"",S_FALSE,FALSE},
1662             {"/",S_OK,FALSE},
1663             {"/",S_OK,FALSE},
1664             {"",S_FALSE,FALSE},
1665             {"http://google.com:65535",S_OK,FALSE},
1666             {"http",S_OK,FALSE},
1667             {"",S_FALSE,FALSE},
1668             {"",S_FALSE,FALSE}
1669         },
1670         {
1671             {Uri_HOST_DNS,S_OK,FALSE},
1672             {65535,S_OK,FALSE},
1673             {URL_SCHEME_HTTP,S_OK,FALSE},
1674             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1675         }
1676     },
1677     {   "zip://google.com:65536", 0, S_OK, FALSE,
1678         {
1679             {"zip://google.com:65536/",S_OK,FALSE},
1680             {"google.com:65536",S_OK,FALSE},
1681             {"zip://google.com:65536/",S_OK,FALSE},
1682             {"google.com:65536",S_OK,FALSE},
1683             {"",S_FALSE,FALSE},
1684             {"",S_FALSE,FALSE},
1685             {"google.com:65536",S_OK,FALSE},
1686             {"",S_FALSE,FALSE},
1687             {"/",S_OK,FALSE},
1688             {"/",S_OK,FALSE},
1689             {"",S_FALSE,FALSE},
1690             {"zip://google.com:65536",S_OK,FALSE},
1691             {"zip",S_OK,FALSE},
1692             {"",S_FALSE,FALSE},
1693             {"",S_FALSE,FALSE}
1694         },
1695         {
1696             {Uri_HOST_DNS,S_OK,FALSE},
1697             {0,S_FALSE,FALSE},
1698             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1699             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1700         }
1701     },
1702     {   "zip://google.com:65536:25", 0, S_OK, FALSE,
1703         {
1704             {"zip://google.com:65536:25/",S_OK,FALSE},
1705             {"google.com:65536:25",S_OK,FALSE},
1706             {"zip://google.com:65536:25/",S_OK,FALSE},
1707             {"google.com:65536:25",S_OK,FALSE},
1708             {"",S_FALSE,FALSE},
1709             {"",S_FALSE,FALSE},
1710             {"google.com:65536:25",S_OK,FALSE},
1711             {"",S_FALSE,FALSE},
1712             {"/",S_OK,FALSE},
1713             {"/",S_OK,FALSE},
1714             {"",S_FALSE,FALSE},
1715             {"zip://google.com:65536:25",S_OK,FALSE},
1716             {"zip",S_OK,FALSE},
1717             {"",S_FALSE,FALSE},
1718             {"",S_FALSE,FALSE}
1719         },
1720         {
1721             {Uri_HOST_DNS,S_OK,FALSE},
1722             {0,S_FALSE,FALSE},
1723             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1724             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1725         }
1726     },
1727     {   "zip://[::ffff]:abcd", 0, S_OK, FALSE,
1728         {
1729             {"zip://[::ffff]:abcd/",S_OK,FALSE},
1730             {"[::ffff]:abcd",S_OK,FALSE},
1731             {"zip://[::ffff]:abcd/",S_OK,FALSE},
1732             {"",S_FALSE,FALSE},
1733             {"",S_FALSE,FALSE},
1734             {"",S_FALSE,FALSE},
1735             {"[::ffff]:abcd",S_OK,FALSE},
1736             {"",S_FALSE,FALSE},
1737             {"/",S_OK,FALSE},
1738             {"/",S_OK,FALSE},
1739             {"",S_FALSE,FALSE},
1740             {"zip://[::ffff]:abcd",S_OK,FALSE},
1741             {"zip",S_OK,FALSE},
1742             {"",S_FALSE,FALSE},
1743             {"",S_FALSE,FALSE}
1744         },
1745         {
1746             {Uri_HOST_DNS,S_OK,FALSE},
1747             {0,S_FALSE,FALSE},
1748             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1749             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1750         }
1751     },
1752     {   "zip://127.0.0.1:abcd", 0, S_OK, FALSE,
1753         {
1754             {"zip://127.0.0.1:abcd/",S_OK,FALSE},
1755             {"127.0.0.1:abcd",S_OK,FALSE},
1756             {"zip://127.0.0.1:abcd/",S_OK,FALSE},
1757             {"0.1:abcd",S_OK,FALSE},
1758             {"",S_FALSE,FALSE},
1759             {"",S_FALSE,FALSE},
1760             {"127.0.0.1:abcd",S_OK,FALSE},
1761             {"",S_FALSE,FALSE},
1762             {"/",S_OK,FALSE},
1763             {"/",S_OK,FALSE},
1764             {"",S_FALSE,FALSE},
1765             {"zip://127.0.0.1:abcd",S_OK,FALSE},
1766             {"zip",S_OK,FALSE},
1767             {"",S_FALSE,FALSE},
1768             {"",S_FALSE,FALSE}
1769         },
1770         {
1771             {Uri_HOST_DNS,S_OK,FALSE},
1772             {0,S_FALSE,FALSE},
1773             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1774             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1775         }
1776     },
1777     /* Port is just copied over. */
1778     {   "http://google.com:00035", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
1779         {
1780             {"http://google.com:00035",S_OK,FALSE},
1781             {"google.com:00035",S_OK,FALSE},
1782             {"http://google.com:00035",S_OK,FALSE,"http://google.com:35"},
1783             {"google.com",S_OK,FALSE},
1784             {"",S_FALSE,FALSE},
1785             {"",S_FALSE,FALSE},
1786             {"google.com",S_OK,FALSE},
1787             {"",S_FALSE,FALSE},
1788             {"",S_FALSE,FALSE},
1789             {"",S_FALSE,FALSE},
1790             {"",S_FALSE,FALSE},
1791             {"http://google.com:00035",S_OK,FALSE},
1792             {"http",S_OK,FALSE},
1793             {"",S_FALSE,FALSE},
1794             {"",S_FALSE,FALSE}
1795         },
1796         {
1797             {Uri_HOST_DNS,S_OK,FALSE},
1798             {35,S_OK,FALSE},
1799             {URL_SCHEME_HTTP,S_OK,FALSE},
1800             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1801         }
1802     },
1803     /* Default port is copied over. */
1804     {   "http://google.com:80", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
1805         {
1806             {"http://google.com:80",S_OK,FALSE},
1807             {"google.com:80",S_OK,FALSE},
1808             {"http://google.com:80",S_OK,FALSE},
1809             {"google.com",S_OK,FALSE},
1810             {"",S_FALSE,FALSE},
1811             {"",S_FALSE,FALSE},
1812             {"google.com",S_OK,FALSE},
1813             {"",S_FALSE,FALSE},
1814             {"",S_FALSE,FALSE},
1815             {"",S_FALSE,FALSE},
1816             {"",S_FALSE,FALSE},
1817             {"http://google.com:80",S_OK,FALSE},
1818             {"http",S_OK,FALSE},
1819             {"",S_FALSE,FALSE},
1820             {"",S_FALSE,FALSE}
1821         },
1822         {
1823             {Uri_HOST_DNS,S_OK,FALSE},
1824             {80,S_OK,FALSE},
1825             {URL_SCHEME_HTTP,S_OK,FALSE},
1826             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1827         }
1828     },
1829     {   "http://google.com.uk", 0, S_OK, FALSE,
1830         {
1831             {"http://google.com.uk/",S_OK,FALSE},
1832             {"google.com.uk",S_OK,FALSE},
1833             {"http://google.com.uk/",S_OK,FALSE},
1834             {"google.com.uk",S_OK,FALSE},
1835             {"",S_FALSE,FALSE},
1836             {"",S_FALSE,FALSE},
1837             {"google.com.uk",S_OK,FALSE},
1838             {"",S_FALSE,FALSE},
1839             {"/",S_OK,FALSE},
1840             {"/",S_OK,FALSE},
1841             {"",S_FALSE,FALSE},
1842             {"http://google.com.uk",S_OK,FALSE},
1843             {"http",S_OK,FALSE},
1844             {"",S_FALSE,FALSE},
1845             {"",S_FALSE,FALSE}
1846         },
1847         {
1848             {Uri_HOST_DNS,S_OK,FALSE},
1849             {80,S_OK,FALSE},
1850             {URL_SCHEME_HTTP,S_OK,FALSE},
1851             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1852         }
1853     },
1854     {   "http://google.com.com", 0, S_OK, FALSE,
1855         {
1856             {"http://google.com.com/",S_OK,FALSE},
1857             {"google.com.com",S_OK,FALSE},
1858             {"http://google.com.com/",S_OK,FALSE},
1859             {"com.com",S_OK,FALSE},
1860             {"",S_FALSE,FALSE},
1861             {"",S_FALSE,FALSE},
1862             {"google.com.com",S_OK,FALSE},
1863             {"",S_FALSE,FALSE},
1864             {"/",S_OK,FALSE},
1865             {"/",S_OK,FALSE},
1866             {"",S_FALSE,FALSE},
1867             {"http://google.com.com",S_OK,FALSE},
1868             {"http",S_OK,FALSE},
1869             {"",S_FALSE,FALSE},
1870             {"",S_FALSE,FALSE}
1871         },
1872         {
1873             {Uri_HOST_DNS,S_OK,FALSE},
1874             {80,S_OK,FALSE},
1875             {URL_SCHEME_HTTP,S_OK,FALSE},
1876             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1877         }
1878     },
1879     {   "http://google.uk.1", 0, S_OK, FALSE,
1880         {
1881             {"http://google.uk.1/",S_OK,FALSE},
1882             {"google.uk.1",S_OK,FALSE},
1883             {"http://google.uk.1/",S_OK,FALSE},
1884             {"google.uk.1",S_OK,FALSE},
1885             {"",S_FALSE,FALSE},
1886             {"",S_FALSE,FALSE},
1887             {"google.uk.1",S_OK,FALSE},
1888             {"",S_FALSE,FALSE},
1889             {"/",S_OK,FALSE},
1890             {"/",S_OK,FALSE},
1891             {"",S_FALSE,FALSE},
1892             {"http://google.uk.1",S_OK,FALSE},
1893             {"http",S_OK,FALSE},
1894             {"",S_FALSE,FALSE},
1895             {"",S_FALSE,FALSE}
1896         },
1897         {
1898             {Uri_HOST_DNS,S_OK,FALSE},
1899             {80,S_OK,FALSE},
1900             {URL_SCHEME_HTTP,S_OK,FALSE},
1901             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1902         }
1903     },
1904     /* Since foo isn't a recognized 3 character TLD its considered the domain name. */
1905     {   "http://google.foo.uk", 0, S_OK, FALSE,
1906         {
1907             {"http://google.foo.uk/",S_OK,FALSE},
1908             {"google.foo.uk",S_OK,FALSE},
1909             {"http://google.foo.uk/",S_OK,FALSE},
1910             {"foo.uk",S_OK,FALSE},
1911             {"",S_FALSE,FALSE},
1912             {"",S_FALSE,FALSE},
1913             {"google.foo.uk",S_OK,FALSE},
1914             {"",S_FALSE,FALSE},
1915             {"/",S_OK,FALSE},
1916             {"/",S_OK,FALSE},
1917             {"",S_FALSE,FALSE},
1918             {"http://google.foo.uk",S_OK,FALSE},
1919             {"http",S_OK,FALSE},
1920             {"",S_FALSE,FALSE},
1921             {"",S_FALSE,FALSE}
1922         },
1923         {
1924             {Uri_HOST_DNS,S_OK,FALSE},
1925             {80,S_OK,FALSE},
1926             {URL_SCHEME_HTTP,S_OK,FALSE},
1927             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1928         }
1929     },
1930     {   "http://.com", 0, S_OK, FALSE,
1931         {
1932             {"http://.com/",S_OK,FALSE},
1933             {".com",S_OK,FALSE},
1934             {"http://.com/",S_OK,FALSE},
1935             {".com",S_OK,FALSE},
1936             {"",S_FALSE,FALSE},
1937             {"",S_FALSE,FALSE},
1938             {".com",S_OK,FALSE},
1939             {"",S_FALSE,FALSE},
1940             {"/",S_OK,FALSE},
1941             {"/",S_OK,FALSE},
1942             {"",S_FALSE,FALSE},
1943             {"http://.com",S_OK,FALSE},
1944             {"http",S_OK,FALSE},
1945             {"",S_FALSE,FALSE},
1946             {"",S_FALSE,FALSE}
1947         },
1948         {
1949             {Uri_HOST_DNS,S_OK,FALSE},
1950             {80,S_OK,FALSE},
1951             {URL_SCHEME_HTTP,S_OK,FALSE},
1952             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1953         }
1954     },
1955     {   "http://.uk", 0, S_OK, FALSE,
1956         {
1957             {"http://.uk/",S_OK,FALSE},
1958             {".uk",S_OK,FALSE},
1959             {"http://.uk/",S_OK,FALSE},
1960             {"",S_FALSE,FALSE},
1961             {"",S_FALSE,FALSE},
1962             {"",S_FALSE,FALSE},
1963             {".uk",S_OK,FALSE},
1964             {"",S_FALSE,FALSE},
1965             {"/",S_OK,FALSE},
1966             {"/",S_OK,FALSE},
1967             {"",S_FALSE,FALSE},
1968             {"http://.uk",S_OK,FALSE},
1969             {"http",S_OK,FALSE},
1970             {"",S_FALSE,FALSE},
1971             {"",S_FALSE,FALSE}
1972         },
1973         {
1974             {Uri_HOST_DNS,S_OK,FALSE},
1975             {80,S_OK,FALSE},
1976             {URL_SCHEME_HTTP,S_OK,FALSE},
1977             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1978         }
1979     },
1980     {   "http://www.co.google.com.[]", 0, S_OK, FALSE,
1981         {
1982             {"http://www.co.google.com.[]/",S_OK,FALSE},
1983             {"www.co.google.com.[]",S_OK,FALSE},
1984             {"http://www.co.google.com.[]/",S_OK,FALSE},
1985             {"google.com.[]",S_OK,FALSE},
1986             {"",S_FALSE,FALSE},
1987             {"",S_FALSE,FALSE},
1988             {"www.co.google.com.[]",S_OK,FALSE},
1989             {"",S_FALSE,FALSE},
1990             {"/",S_OK,FALSE},
1991             {"/",S_OK,FALSE},
1992             {"",S_FALSE,FALSE},
1993             {"http://www.co.google.com.[]",S_OK,FALSE},
1994             {"http",S_OK,FALSE},
1995             {"",S_FALSE,FALSE},
1996             {"",S_FALSE,FALSE}
1997         },
1998         {
1999             {Uri_HOST_DNS,S_OK,FALSE},
2000             {80,S_OK,FALSE},
2001             {URL_SCHEME_HTTP,S_OK,FALSE},
2002             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2003         }
2004     },
2005     {   "http://co.uk", 0, S_OK, FALSE,
2006         {
2007             {"http://co.uk/",S_OK,FALSE},
2008             {"co.uk",S_OK,FALSE},
2009             {"http://co.uk/",S_OK,FALSE},
2010             {"",S_FALSE,FALSE},
2011             {"",S_FALSE,FALSE},
2012             {"",S_FALSE,FALSE},
2013             {"co.uk",S_OK,FALSE},
2014             {"",S_FALSE,FALSE},
2015             {"/",S_OK,FALSE},
2016             {"/",S_OK,FALSE},
2017             {"",S_FALSE,FALSE},
2018             {"http://co.uk",S_OK,FALSE},
2019             {"http",S_OK,FALSE},
2020             {"",S_FALSE,FALSE},
2021             {"",S_FALSE,FALSE}
2022         },
2023         {
2024             {Uri_HOST_DNS,S_OK,FALSE},
2025             {80,S_OK,FALSE},
2026             {URL_SCHEME_HTTP,S_OK,FALSE},
2027             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2028         }
2029     },
2030     {   "http://www.co.google.us.test", 0, S_OK, FALSE,
2031         {
2032             {"http://www.co.google.us.test/",S_OK,FALSE},
2033             {"www.co.google.us.test",S_OK,FALSE},
2034             {"http://www.co.google.us.test/",S_OK,FALSE},
2035             {"us.test",S_OK,FALSE},
2036             {"",S_FALSE,FALSE},
2037             {"",S_FALSE,FALSE},
2038             {"www.co.google.us.test",S_OK,FALSE},
2039             {"",S_FALSE,FALSE},
2040             {"/",S_OK,FALSE},
2041             {"/",S_OK,FALSE},
2042             {"",S_FALSE,FALSE},
2043             {"http://www.co.google.us.test",S_OK,FALSE},
2044             {"http",S_OK,FALSE},
2045             {"",S_FALSE,FALSE},
2046             {"",S_FALSE,FALSE}
2047         },
2048         {
2049             {Uri_HOST_DNS,S_OK,FALSE},
2050             {80,S_OK,FALSE},
2051             {URL_SCHEME_HTTP,S_OK,FALSE},
2052             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2053         }
2054     },
2055     {   "http://gov.uk", 0, S_OK, FALSE,
2056         {
2057             {"http://gov.uk/",S_OK,FALSE},
2058             {"gov.uk",S_OK,FALSE},
2059             {"http://gov.uk/",S_OK,FALSE},
2060             {"",S_FALSE,FALSE},
2061             {"",S_FALSE,FALSE},
2062             {"",S_FALSE,FALSE},
2063             {"gov.uk",S_OK,FALSE},
2064             {"",S_FALSE,FALSE},
2065             {"/",S_OK,FALSE},
2066             {"/",S_OK,FALSE},
2067             {"",S_FALSE,FALSE},
2068             {"http://gov.uk",S_OK,FALSE},
2069             {"http",S_OK,FALSE},
2070             {"",S_FALSE,FALSE},
2071             {"",S_FALSE,FALSE}
2072         },
2073         {
2074             {Uri_HOST_DNS,S_OK,FALSE},
2075             {80,S_OK,FALSE},
2076             {URL_SCHEME_HTTP,S_OK,FALSE},
2077             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2078         }
2079     },
2080     {   "zip://www.google.com\\test", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
2081         {
2082             {"zip://www.google.com\\test",S_OK,FALSE},
2083             {"www.google.com\\test",S_OK,FALSE},
2084             {"zip://www.google.com\\test",S_OK,FALSE},
2085             {"google.com\\test",S_OK,FALSE},
2086             {"",S_FALSE,FALSE},
2087             {"",S_FALSE,FALSE},
2088             {"www.google.com\\test",S_OK,FALSE},
2089             {"",S_FALSE,FALSE},
2090             {"",S_FALSE,FALSE},
2091             {"",S_FALSE,FALSE},
2092             {"",S_FALSE,FALSE},
2093             {"zip://www.google.com\\test",S_OK,FALSE},
2094             {"zip",S_OK,FALSE},
2095             {"",S_FALSE,FALSE},
2096             {"",S_FALSE,FALSE}
2097         },
2098         {
2099             {Uri_HOST_DNS,S_OK,FALSE},
2100             {0,S_FALSE,FALSE},
2101             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2102             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2103         }
2104     },
2105     {   "urn:excepts:bad:%XY:encoded", 0, S_OK, FALSE,
2106         {
2107             {"urn:excepts:bad:%XY:encoded",S_OK,FALSE},
2108             {"",S_FALSE,FALSE},
2109             {"urn:excepts:bad:%XY:encoded",S_OK,FALSE},
2110             {"",S_FALSE,FALSE},
2111             {"",S_FALSE,FALSE},
2112             {"",S_FALSE,FALSE},
2113             {"",S_FALSE,FALSE},
2114             {"",S_FALSE,FALSE},
2115             {"excepts:bad:%XY:encoded",S_OK,FALSE},
2116             {"excepts:bad:%XY:encoded",S_OK,FALSE},
2117             {"",S_FALSE,FALSE},
2118             {"urn:excepts:bad:%XY:encoded",S_OK,FALSE},
2119             {"urn",S_OK,FALSE},
2120             {"",S_FALSE,FALSE},
2121             {"",S_FALSE,FALSE}
2122         },
2123         {
2124             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2125             {0,S_FALSE,FALSE},
2126             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2127             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2128         }
2129     },
2130     /* Since the original URI doesn't contain an extra '/' before the path no % encoded values
2131      * are decoded and all '%' are encoded.
2132      */
2133     {   "file://C:/te%3Es%2Et/tes%t.mp3", 0, S_OK, FALSE,
2134         {
2135             {"file:///C:/te%253Es%252Et/tes%25t.mp3",S_OK,FALSE},
2136             {"",S_FALSE,FALSE},
2137             {"file:///C:/te%253Es%252Et/tes%25t.mp3",S_OK,FALSE},
2138             {"",S_FALSE,FALSE},
2139             {".mp3",S_OK,FALSE},
2140             {"",S_FALSE,FALSE},
2141             {"",S_FALSE,FALSE},
2142             {"",S_FALSE,FALSE},
2143             {"/C:/te%253Es%252Et/tes%25t.mp3",S_OK,FALSE},
2144             {"/C:/te%253Es%252Et/tes%25t.mp3",S_OK,FALSE},
2145             {"",S_FALSE,FALSE},
2146             {"file://C:/te%3Es%2Et/tes%t.mp3",S_OK,FALSE},
2147             {"file",S_OK,FALSE},
2148             {"",S_FALSE,FALSE},
2149             {"",S_FALSE,FALSE}
2150         },
2151         {
2152             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2153             {0,S_FALSE,FALSE},
2154             {URL_SCHEME_FILE,S_OK,FALSE},
2155             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2156         }
2157     },
2158     /* Since there's a '/' in front of the drive letter, any percent encoded, non-forbidden character
2159      * is decoded and only %'s in front of invalid hex digits are encoded.
2160      */
2161     {   "file:///C:/te%3Es%2Et/t%23es%t.mp3", 0, S_OK, FALSE,
2162         {
2163             {"file:///C:/te%3Es.t/t#es%25t.mp3",S_OK,FALSE},
2164             {"",S_FALSE,FALSE},
2165             {"file:///C:/te%3Es.t/t#es%25t.mp3",S_OK,FALSE},
2166             {"",S_FALSE,FALSE},
2167             {".mp3",S_OK,FALSE},
2168             {"",S_FALSE,FALSE},
2169             {"",S_FALSE,FALSE},
2170             {"",S_FALSE,FALSE},
2171             {"/C:/te%3Es.t/t#es%25t.mp3",S_OK,FALSE},
2172             {"/C:/te%3Es.t/t#es%25t.mp3",S_OK,FALSE},
2173             {"",S_FALSE,FALSE},
2174             {"file:///C:/te%3Es%2Et/t%23es%t.mp3",S_OK,FALSE},
2175             {"file",S_OK,FALSE},
2176             {"",S_FALSE,FALSE},
2177             {"",S_FALSE,FALSE}
2178         },
2179         {
2180             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2181             {0,S_FALSE,FALSE},
2182             {URL_SCHEME_FILE,S_OK,FALSE},
2183             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2184         }
2185     },
2186     /* Only unreserved percent encoded characters are decoded for known schemes that aren't file. */
2187     {   "http://[::001.002.003.000]/%3F%23%2E%54/test", 0, S_OK, FALSE,
2188         {
2189             {"http://[::1.2.3.0]/%3F%23.T/test",S_OK,FALSE},
2190             {"[::1.2.3.0]",S_OK,FALSE},
2191             {"http://[::1.2.3.0]/%3F%23.T/test",S_OK,FALSE},
2192             {"",S_FALSE,FALSE},
2193             {"",S_FALSE,FALSE},
2194             {"",S_FALSE,FALSE},
2195             {"::1.2.3.0",S_OK,FALSE},
2196             {"",S_FALSE,FALSE},
2197             {"/%3F%23.T/test",S_OK,FALSE},
2198             {"/%3F%23.T/test",S_OK,FALSE},
2199             {"",S_FALSE,FALSE},
2200             {"http://[::001.002.003.000]/%3F%23%2E%54/test",S_OK,FALSE},
2201             {"http",S_OK,FALSE},
2202             {"",S_FALSE,FALSE},
2203             {"",S_FALSE,FALSE},
2204         },
2205         {
2206             {Uri_HOST_IPV6,S_OK,FALSE},
2207             {80,S_OK,FALSE},
2208             {URL_SCHEME_HTTP,S_OK,FALSE},
2209             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2210         }
2211     },
2212     /* Forbidden characters are always encoded for file URIs. */
2213     {   "file:///C:/\"test\"/test.mp3", Uri_CREATE_NO_ENCODE_FORBIDDEN_CHARACTERS, S_OK, FALSE,
2214         {
2215             {"file:///C:/%22test%22/test.mp3",S_OK,FALSE},
2216             {"",S_FALSE,FALSE},
2217             {"file:///C:/%22test%22/test.mp3",S_OK,FALSE},
2218             {"",S_FALSE,FALSE},
2219             {".mp3",S_OK,FALSE},
2220             {"",S_FALSE,FALSE},
2221             {"",S_FALSE,FALSE},
2222             {"",S_FALSE,FALSE},
2223             {"/C:/%22test%22/test.mp3",S_OK,FALSE},
2224             {"/C:/%22test%22/test.mp3",S_OK,FALSE},
2225             {"",S_FALSE,FALSE},
2226             {"file:///C:/\"test\"/test.mp3",S_OK,FALSE},
2227             {"file",S_OK,FALSE},
2228             {"",S_FALSE,FALSE},
2229             {"",S_FALSE,FALSE}
2230         },
2231         {
2232             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2233             {0,S_FALSE,FALSE},
2234             {URL_SCHEME_FILE,S_OK,FALSE},
2235             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2236         }
2237     },
2238     /* Forbidden characters are never encoded for unknown scheme types. */
2239     {   "1234://4294967295/<|>\" test<|>", 0, S_OK, FALSE,
2240         {
2241             {"1234://4294967295/<|>\" test<|>",S_OK,FALSE},
2242             {"4294967295",S_OK,FALSE},
2243             {"1234://4294967295/<|>\" test<|>",S_OK,FALSE},
2244             {"",S_FALSE,FALSE},
2245             {"",S_FALSE,FALSE},
2246             {"",S_FALSE,FALSE},
2247             {"4294967295",S_OK,FALSE},
2248             {"",S_FALSE,FALSE},
2249             {"/<|>\" test<|>",S_OK,FALSE},
2250             {"/<|>\" test<|>",S_OK,FALSE},
2251             {"",S_FALSE,FALSE},
2252             {"1234://4294967295/<|>\" test<|>",S_OK,FALSE},
2253             {"1234",S_OK,FALSE},
2254             {"",S_FALSE,FALSE},
2255             {"",S_FALSE,FALSE}
2256         },
2257         {
2258             {Uri_HOST_IPV4,S_OK,FALSE},
2259             {0,S_FALSE,FALSE},
2260             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2261             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2262         }
2263     },
2264     /* Make sure forbidden characters are percent encoded. */
2265     {   "http://gov.uk/<|> test<|>", 0, S_OK, FALSE,
2266         {
2267             {"http://gov.uk/%3C%7C%3E%20test%3C%7C%3E",S_OK,FALSE},
2268             {"gov.uk",S_OK,FALSE},
2269             {"http://gov.uk/%3C%7C%3E%20test%3C%7C%3E",S_OK,FALSE},
2270             {"",S_FALSE,FALSE},
2271             {"",S_FALSE,FALSE},
2272             {"",S_FALSE,FALSE},
2273             {"gov.uk",S_OK,FALSE},
2274             {"",S_FALSE,FALSE},
2275             {"/%3C%7C%3E%20test%3C%7C%3E",S_OK,FALSE},
2276             {"/%3C%7C%3E%20test%3C%7C%3E",S_OK,FALSE},
2277             {"",S_FALSE,FALSE},
2278             {"http://gov.uk/<|> test<|>",S_OK,FALSE},
2279             {"http",S_OK,FALSE},
2280             {"",S_FALSE,FALSE},
2281             {"",S_FALSE,FALSE}
2282         },
2283         {
2284             {Uri_HOST_DNS,S_OK,FALSE},
2285             {80,S_OK,FALSE},
2286             {URL_SCHEME_HTTP,S_OK,FALSE},
2287             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2288         }
2289     },
2290     {   "http://gov.uk/test/../test2/././../test3/.././././", 0, S_OK, FALSE,
2291         {
2292             {"http://gov.uk/",S_OK,FALSE},
2293             {"gov.uk",S_OK,FALSE},
2294             {"http://gov.uk/",S_OK,FALSE},
2295             {"",S_FALSE,FALSE},
2296             {"",S_FALSE,FALSE},
2297             {"",S_FALSE,FALSE},
2298             {"gov.uk",S_OK,FALSE},
2299             {"",S_FALSE,FALSE},
2300             {"/",S_OK,FALSE},
2301             {"/",S_OK,FALSE},
2302             {"",S_FALSE,FALSE},
2303             {"http://gov.uk/test/../test2/././../test3/.././././",S_OK,FALSE},
2304             {"http",S_OK,FALSE},
2305             {"",S_FALSE,FALSE},
2306             {"",S_FALSE,FALSE}
2307         },
2308         {
2309             {Uri_HOST_DNS,S_OK,FALSE},
2310             {80,S_OK,FALSE},
2311             {URL_SCHEME_HTTP,S_OK,FALSE},
2312             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2313         }
2314     },
2315     {   "http://gov.uk/test/test2/../../..", 0, S_OK, FALSE,
2316         {
2317             {"http://gov.uk/",S_OK,FALSE},
2318             {"gov.uk",S_OK,FALSE},
2319             {"http://gov.uk/",S_OK,FALSE},
2320             {"",S_FALSE,FALSE},
2321             {"",S_FALSE,FALSE},
2322             {"",S_FALSE,FALSE},
2323             {"gov.uk",S_OK,FALSE},
2324             {"",S_FALSE,FALSE},
2325             {"/",S_OK,FALSE},
2326             {"/",S_OK,FALSE},
2327             {"",S_FALSE,FALSE},
2328             {"http://gov.uk/test/test2/../../..",S_OK,FALSE},
2329             {"http",S_OK,FALSE},
2330             {"",S_FALSE,FALSE},
2331             {"",S_FALSE,FALSE}
2332         },
2333         {
2334             {Uri_HOST_DNS,S_OK,FALSE},
2335             {80,S_OK,FALSE},
2336             {URL_SCHEME_HTTP,S_OK,FALSE},
2337             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2338         }
2339     },
2340     {   "http://gov.uk/test/test2/../../.", 0, S_OK, FALSE,
2341         {
2342             {"http://gov.uk/",S_OK,FALSE},
2343             {"gov.uk",S_OK,FALSE},
2344             {"http://gov.uk/",S_OK,FALSE},
2345             {"",S_FALSE,FALSE},
2346             {"",S_FALSE,FALSE},
2347             {"",S_FALSE,FALSE},
2348             {"gov.uk",S_OK,FALSE},
2349             {"",S_FALSE,FALSE},
2350             {"/",S_OK,FALSE},
2351             {"/",S_OK,FALSE},
2352             {"",S_FALSE,FALSE},
2353             {"http://gov.uk/test/test2/../../.",S_OK,FALSE},
2354             {"http",S_OK,FALSE},
2355             {"",S_FALSE,FALSE},
2356             {"",S_FALSE,FALSE}
2357         },
2358         {
2359             {Uri_HOST_DNS,S_OK,FALSE},
2360             {80,S_OK,FALSE},
2361             {URL_SCHEME_HTTP,S_OK,FALSE},
2362             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2363         }
2364     },
2365     {   "file://c:\\tests\\../tests\\./.\\..\\foo%20bar.mp3", 0, S_OK, FALSE,
2366         {
2367             {"file:///c:/foo%2520bar.mp3",S_OK,FALSE},
2368             {"",S_FALSE,FALSE},
2369             {"file:///c:/foo%2520bar.mp3",S_OK,FALSE},
2370             {"",S_FALSE,FALSE},
2371             {".mp3",S_OK,FALSE},
2372             {"",S_FALSE,FALSE},
2373             {"",S_FALSE,FALSE},
2374             {"",S_FALSE,FALSE},
2375             {"/c:/foo%2520bar.mp3",S_OK,FALSE},
2376             {"/c:/foo%2520bar.mp3",S_OK,FALSE},
2377             {"",S_FALSE,FALSE},
2378             {"file://c:\\tests\\../tests\\./.\\..\\foo%20bar.mp3",S_OK,FALSE},
2379             {"file",S_OK,FALSE},
2380             {"",S_FALSE,FALSE},
2381             {"",S_FALSE,FALSE}
2382         },
2383         {
2384             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2385             {0,S_FALSE,FALSE},
2386             {URL_SCHEME_FILE,S_OK,FALSE},
2387             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2388         }
2389     },
2390     /* Dot removal happens for unknown scheme types. */
2391     {   "zip://gov.uk/test/test2/../../.", 0, S_OK, FALSE,
2392         {
2393             {"zip://gov.uk/",S_OK,FALSE},
2394             {"gov.uk",S_OK,FALSE},
2395             {"zip://gov.uk/",S_OK,FALSE},
2396             {"",S_FALSE,FALSE},
2397             {"",S_FALSE,FALSE},
2398             {"",S_FALSE,FALSE},
2399             {"gov.uk",S_OK,FALSE},
2400             {"",S_FALSE,FALSE},
2401             {"/",S_OK,FALSE},
2402             {"/",S_OK,FALSE},
2403             {"",S_FALSE,FALSE},
2404             {"zip://gov.uk/test/test2/../../.",S_OK,FALSE},
2405             {"zip",S_OK,FALSE},
2406             {"",S_FALSE,FALSE},
2407             {"",S_FALSE,FALSE}
2408         },
2409         {
2410             {Uri_HOST_DNS,S_OK,FALSE},
2411             {0,S_FALSE,FALSE},
2412             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2413             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2414         }
2415     },
2416     /* Dot removal doesn't happen if NO_CANONICALIZE is set. */
2417     {   "http://gov.uk/test/test2/../../.", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
2418         {
2419             {"http://gov.uk/test/test2/../../.",S_OK,FALSE},
2420             {"gov.uk",S_OK,FALSE},
2421             {"http://gov.uk/test/test2/../../.",S_OK,FALSE},
2422             {"",S_FALSE,FALSE},
2423             {".",S_OK,FALSE},
2424             {"",S_FALSE,FALSE},
2425             {"gov.uk",S_OK,FALSE},
2426             {"",S_FALSE,FALSE},
2427             {"/test/test2/../../.",S_OK,FALSE},
2428             {"/test/test2/../../.",S_OK,FALSE},
2429             {"",S_FALSE,FALSE},
2430             {"http://gov.uk/test/test2/../../.",S_OK,FALSE},
2431             {"http",S_OK,FALSE},
2432             {"",S_FALSE,FALSE},
2433             {"",S_FALSE,FALSE}
2434         },
2435         {
2436             {Uri_HOST_DNS,S_OK,FALSE},
2437             {80,S_OK,FALSE},
2438             {URL_SCHEME_HTTP,S_OK,FALSE},
2439             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2440         }
2441     },
2442     /* Dot removal doesn't happen for wildcard scheme types. */
2443     {   "*:gov.uk/test/test2/../../.", 0, S_OK, FALSE,
2444         {
2445             {"*:gov.uk/test/test2/../../.",S_OK,FALSE},
2446             {"gov.uk",S_OK,FALSE},
2447             {"*:gov.uk/test/test2/../../.",S_OK,FALSE},
2448             {"",S_FALSE,FALSE},
2449             {".",S_OK,FALSE},
2450             {"",S_FALSE,FALSE},
2451             {"gov.uk",S_OK,FALSE},
2452             {"",S_FALSE,FALSE},
2453             {"/test/test2/../../.",S_OK,FALSE},
2454             {"/test/test2/../../.",S_OK,FALSE},
2455             {"",S_FALSE,FALSE},
2456             {"*:gov.uk/test/test2/../../.",S_OK,FALSE},
2457             {"*",S_OK,FALSE},
2458             {"",S_FALSE,FALSE},
2459             {"",S_FALSE,FALSE}
2460         },
2461         {
2462             {Uri_HOST_DNS,S_OK,FALSE},
2463             {0,S_FALSE,FALSE},
2464             {URL_SCHEME_WILDCARD,S_OK,FALSE},
2465             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2466         }
2467     },
2468     /* Forbidden characters are encoded for opaque known scheme types. */
2469     {   "mailto:\"acco<|>unt@example.com\"", 0, S_OK, FALSE,
2470         {
2471             {"mailto:%22acco%3C%7C%3Eunt@example.com%22",S_OK,FALSE},
2472             {"",S_FALSE,FALSE},
2473             {"mailto:%22acco%3C%7C%3Eunt@example.com%22",S_OK,FALSE},
2474             {"",S_FALSE,FALSE},
2475             {".com%22",S_OK,FALSE},
2476             {"",S_FALSE,FALSE},
2477             {"",S_FALSE,FALSE},
2478             {"",S_FALSE,FALSE},
2479             {"%22acco%3C%7C%3Eunt@example.com%22",S_OK,FALSE},
2480             {"%22acco%3C%7C%3Eunt@example.com%22",S_OK,FALSE},
2481             {"",S_FALSE,FALSE},
2482             {"mailto:\"acco<|>unt@example.com\"",S_OK,FALSE},
2483             {"mailto",S_OK,FALSE},
2484             {"",S_FALSE,FALSE},
2485             {"",S_FALSE,FALSE}
2486         },
2487         {
2488             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2489             {0,S_FALSE,FALSE},
2490             {URL_SCHEME_MAILTO,S_OK,FALSE},
2491             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2492         }
2493     },
2494     {   "news:test.tes<|>t.com", 0, S_OK, FALSE,
2495         {
2496             {"news:test.tes%3C%7C%3Et.com",S_OK,FALSE},
2497             {"",S_FALSE,FALSE},
2498             {"news:test.tes%3C%7C%3Et.com",S_OK,FALSE},
2499             {"",S_FALSE,FALSE},
2500             {".com",S_OK,FALSE},
2501             {"",S_FALSE,FALSE},
2502             {"",S_FALSE,FALSE},
2503             {"",S_FALSE,FALSE},
2504             {"test.tes%3C%7C%3Et.com",S_OK,FALSE},
2505             {"test.tes%3C%7C%3Et.com",S_OK,FALSE},
2506             {"",S_FALSE,FALSE},
2507             {"news:test.tes<|>t.com",S_OK,FALSE},
2508             {"news",S_OK,FALSE},
2509             {"",S_FALSE,FALSE},
2510             {"",S_FALSE,FALSE}
2511         },
2512         {
2513             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2514             {0,S_FALSE,FALSE},
2515             {URL_SCHEME_NEWS,S_OK,FALSE},
2516             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2517         }
2518     },
2519     /* Don't encode forbidden characters. */
2520     {   "news:test.tes<|>t.com", Uri_CREATE_NO_ENCODE_FORBIDDEN_CHARACTERS, S_OK, FALSE,
2521         {
2522             {"news:test.tes<|>t.com",S_OK,FALSE},
2523             {"",S_FALSE,FALSE},
2524             {"news:test.tes<|>t.com",S_OK,FALSE},
2525             {"",S_FALSE,FALSE},
2526             {".com",S_OK,FALSE},
2527             {"",S_FALSE,FALSE},
2528             {"",S_FALSE,FALSE},
2529             {"",S_FALSE,FALSE},
2530             {"test.tes<|>t.com",S_OK,FALSE},
2531             {"test.tes<|>t.com",S_OK,FALSE},
2532             {"",S_FALSE,FALSE},
2533             {"news:test.tes<|>t.com",S_OK,FALSE},
2534             {"news",S_OK,FALSE},
2535             {"",S_FALSE,FALSE},
2536             {"",S_FALSE,FALSE}
2537         },
2538         {
2539             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2540             {0,S_FALSE,FALSE},
2541             {URL_SCHEME_NEWS,S_OK,FALSE},
2542             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2543         }
2544     },
2545     /* Forbidden characters aren't encoded for unknown, opaque URIs. */
2546     {   "urn:test.tes<|>t.com", 0, S_OK, FALSE,
2547         {
2548             {"urn:test.tes<|>t.com",S_OK,FALSE},
2549             {"",S_FALSE,FALSE},
2550             {"urn:test.tes<|>t.com",S_OK,FALSE},
2551             {"",S_FALSE,FALSE},
2552             {".com",S_OK,FALSE},
2553             {"",S_FALSE,FALSE},
2554             {"",S_FALSE,FALSE},
2555             {"",S_FALSE,FALSE},
2556             {"test.tes<|>t.com",S_OK,FALSE},
2557             {"test.tes<|>t.com",S_OK,FALSE},
2558             {"",S_FALSE,FALSE},
2559             {"urn:test.tes<|>t.com",S_OK,FALSE},
2560             {"urn",S_OK,FALSE},
2561             {"",S_FALSE,FALSE},
2562             {"",S_FALSE,FALSE}
2563         },
2564         {
2565             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2566             {0,S_FALSE,FALSE},
2567             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2568             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2569         }
2570     },
2571     /* Percent encoded unreserved characters are decoded for known opaque URIs. */
2572     {   "news:test.%74%65%73%74.com", 0, S_OK, FALSE,
2573         {
2574             {"news:test.test.com",S_OK,FALSE},
2575             {"",S_FALSE,FALSE},
2576             {"news:test.test.com",S_OK,FALSE},
2577             {"",S_FALSE,FALSE},
2578             {".com",S_OK,FALSE},
2579             {"",S_FALSE,FALSE},
2580             {"",S_FALSE,FALSE},
2581             {"",S_FALSE,FALSE},
2582             {"test.test.com",S_OK,FALSE},
2583             {"test.test.com",S_OK,FALSE},
2584             {"",S_FALSE,FALSE},
2585             {"news:test.%74%65%73%74.com",S_OK,FALSE},
2586             {"news",S_OK,FALSE},
2587             {"",S_FALSE,FALSE},
2588             {"",S_FALSE,FALSE}
2589         },
2590         {
2591             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2592             {0,S_FALSE,FALSE},
2593             {URL_SCHEME_NEWS,S_OK,FALSE},
2594             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2595         }
2596     },
2597     /* Percent encoded characters are still decoded for known scheme types. */
2598     {   "news:test.%74%65%73%74.com", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
2599         {
2600             {"news:test.test.com",S_OK,FALSE},
2601             {"",S_FALSE,FALSE},
2602             {"news:test.test.com",S_OK,FALSE},
2603             {"",S_FALSE,FALSE},
2604             {".com",S_OK,FALSE},
2605             {"",S_FALSE,FALSE},
2606             {"",S_FALSE,FALSE},
2607             {"",S_FALSE,FALSE},
2608             {"test.test.com",S_OK,FALSE},
2609             {"test.test.com",S_OK,FALSE},
2610             {"",S_FALSE,FALSE},
2611             {"news:test.%74%65%73%74.com",S_OK,FALSE},
2612             {"news",S_OK,FALSE},
2613             {"",S_FALSE,FALSE},
2614             {"",S_FALSE,FALSE}
2615         },
2616         {
2617             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2618             {0,S_FALSE,FALSE},
2619             {URL_SCHEME_NEWS,S_OK,FALSE},
2620             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2621         }
2622     },
2623     /* Percent encoded characters aren't decoded for unknown scheme types. */
2624     {   "urn:test.%74%65%73%74.com", 0, S_OK, FALSE,
2625         {
2626             {"urn:test.%74%65%73%74.com",S_OK,FALSE},
2627             {"",S_FALSE,FALSE},
2628             {"urn:test.%74%65%73%74.com",S_OK,FALSE},
2629             {"",S_FALSE,FALSE},
2630             {".com",S_OK,FALSE},
2631             {"",S_FALSE,FALSE},
2632             {"",S_FALSE,FALSE},
2633             {"",S_FALSE,FALSE},
2634             {"test.%74%65%73%74.com",S_OK,FALSE},
2635             {"test.%74%65%73%74.com",S_OK,FALSE},
2636             {"",S_FALSE,FALSE},
2637             {"urn:test.%74%65%73%74.com",S_OK,FALSE},
2638             {"urn",S_OK,FALSE},
2639             {"",S_FALSE,FALSE},
2640             {"",S_FALSE,FALSE}
2641         },
2642         {
2643             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2644             {0,S_FALSE,FALSE},
2645             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2646             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2647         }
2648     },
2649     /* Unknown scheme types can have invalid % encoded data in query string. */
2650     {   "zip://www.winehq.org/tests/..?query=%xx&return=y", 0, S_OK, FALSE,
2651         {
2652             {"zip://www.winehq.org/?query=%xx&return=y",S_OK,FALSE},
2653             {"www.winehq.org",S_OK,FALSE},
2654             {"zip://www.winehq.org/?query=%xx&return=y",S_OK,FALSE},
2655             {"winehq.org",S_OK,FALSE},
2656             {"",S_FALSE,FALSE},
2657             {"",S_FALSE,FALSE},
2658             {"www.winehq.org",S_OK,FALSE},
2659             {"",S_FALSE,FALSE},
2660             {"/",S_OK,FALSE},
2661             {"/?query=%xx&return=y",S_OK,FALSE},
2662             {"?query=%xx&return=y",S_OK,FALSE},
2663             {"zip://www.winehq.org/tests/..?query=%xx&return=y",S_OK,FALSE},
2664             {"zip",S_OK,FALSE},
2665             {"",S_FALSE,FALSE},
2666             {"",S_FALSE,FALSE}
2667         },
2668         {
2669             {Uri_HOST_DNS,S_OK,FALSE},
2670             {0,S_FALSE,FALSE},
2671             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2672             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2673         }
2674     },
2675     /* Known scheme types can have invalid % encoded data with the right flags. */
2676     {   "http://www.winehq.org/tests/..?query=%xx&return=y", Uri_CREATE_NO_DECODE_EXTRA_INFO, S_OK, FALSE,
2677         {
2678             {"http://www.winehq.org/?query=%xx&return=y",S_OK,FALSE},
2679             {"www.winehq.org",S_OK,FALSE},
2680             {"http://www.winehq.org/?query=%xx&return=y",S_OK,FALSE},
2681             {"winehq.org",S_OK,FALSE},
2682             {"",S_FALSE,FALSE},
2683             {"",S_FALSE,FALSE},
2684             {"www.winehq.org",S_OK,FALSE},
2685             {"",S_FALSE,FALSE},
2686             {"/",S_OK,FALSE},
2687             {"/?query=%xx&return=y",S_OK,FALSE},
2688             {"?query=%xx&return=y",S_OK,FALSE},
2689             {"http://www.winehq.org/tests/..?query=%xx&return=y",S_OK,FALSE},
2690             {"http",S_OK,FALSE},
2691             {"",S_FALSE,FALSE},
2692             {"",S_FALSE,FALSE}
2693         },
2694         {
2695             {Uri_HOST_DNS,S_OK,FALSE},
2696             {80,S_OK,FALSE},
2697             {URL_SCHEME_HTTP,S_OK,FALSE},
2698             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2699         }
2700     },
2701     /* Forbidden characters in query aren't percent encoded for known scheme types with this flag. */
2702     {   "http://www.winehq.org/tests/..?query=<|>&return=y", Uri_CREATE_NO_DECODE_EXTRA_INFO, S_OK, FALSE,
2703         {
2704             {"http://www.winehq.org/?query=<|>&return=y",S_OK,FALSE},
2705             {"www.winehq.org",S_OK,FALSE},
2706             {"http://www.winehq.org/?query=<|>&return=y",S_OK,FALSE},
2707             {"winehq.org",S_OK,FALSE},
2708             {"",S_FALSE,FALSE},
2709             {"",S_FALSE,FALSE},
2710             {"www.winehq.org",S_OK,FALSE},
2711             {"",S_FALSE,FALSE},
2712             {"/",S_OK,FALSE},
2713             {"/?query=<|>&return=y",S_OK,FALSE},
2714             {"?query=<|>&return=y",S_OK,FALSE},
2715             {"http://www.winehq.org/tests/..?query=<|>&return=y",S_OK,FALSE},
2716             {"http",S_OK,FALSE},
2717             {"",S_FALSE,FALSE},
2718             {"",S_FALSE,FALSE}
2719         },
2720         {
2721             {Uri_HOST_DNS,S_OK,FALSE},
2722             {80,S_OK,FALSE},
2723             {URL_SCHEME_HTTP,S_OK,FALSE},
2724             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2725         }
2726     },
2727     /* Forbidden characters in query aren't percent encoded for known scheme types with this flag. */
2728     {   "http://www.winehq.org/tests/..?query=<|>&return=y", Uri_CREATE_NO_ENCODE_FORBIDDEN_CHARACTERS, S_OK, FALSE,
2729         {
2730             {"http://www.winehq.org/?query=<|>&return=y",S_OK,FALSE},
2731             {"www.winehq.org",S_OK,FALSE},
2732             {"http://www.winehq.org/?query=<|>&return=y",S_OK,FALSE},
2733             {"winehq.org",S_OK,FALSE},
2734             {"",S_FALSE,FALSE},
2735             {"",S_FALSE,FALSE},
2736             {"www.winehq.org",S_OK,FALSE},
2737             {"",S_FALSE,FALSE},
2738             {"/",S_OK,FALSE},
2739             {"/?query=<|>&return=y",S_OK,FALSE},
2740             {"?query=<|>&return=y",S_OK,FALSE},
2741             {"http://www.winehq.org/tests/..?query=<|>&return=y",S_OK,FALSE},
2742             {"http",S_OK,FALSE},
2743             {"",S_FALSE,FALSE},
2744             {"",S_FALSE,FALSE}
2745         },
2746         {
2747             {Uri_HOST_DNS,S_OK,FALSE},
2748             {80,S_OK,FALSE},
2749             {URL_SCHEME_HTTP,S_OK,FALSE},
2750             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2751         }
2752     },
2753     /* Forbidden characters are encoded for known scheme types. */
2754     {   "http://www.winehq.org/tests/..?query=<|>&return=y", 0, S_OK, FALSE,
2755         {
2756             {"http://www.winehq.org/?query=%3C%7C%3E&return=y",S_OK,FALSE},
2757             {"www.winehq.org",S_OK,FALSE},
2758             {"http://www.winehq.org/?query=%3C%7C%3E&return=y",S_OK,FALSE},
2759             {"winehq.org",S_OK,FALSE},
2760             {"",S_FALSE,FALSE},
2761             {"",S_FALSE,FALSE},
2762             {"www.winehq.org",S_OK,FALSE},
2763             {"",S_FALSE,FALSE},
2764             {"/",S_OK,FALSE},
2765             {"/?query=%3C%7C%3E&return=y",S_OK,FALSE},
2766             {"?query=%3C%7C%3E&return=y",S_OK,FALSE},
2767             {"http://www.winehq.org/tests/..?query=<|>&return=y",S_OK,FALSE},
2768             {"http",S_OK,FALSE},
2769             {"",S_FALSE,FALSE},
2770             {"",S_FALSE,FALSE}
2771         },
2772         {
2773             {Uri_HOST_DNS,S_OK,FALSE},
2774             {80,S_OK,FALSE},
2775             {URL_SCHEME_HTTP,S_OK,FALSE},
2776             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2777         }
2778     },
2779     /* Forbidden characters are not encoded for unknown scheme types. */
2780     {   "zip://www.winehq.org/tests/..?query=<|>&return=y", 0, S_OK, FALSE,
2781         {
2782             {"zip://www.winehq.org/?query=<|>&return=y",S_OK,FALSE},
2783             {"www.winehq.org",S_OK,FALSE},
2784             {"zip://www.winehq.org/?query=<|>&return=y",S_OK,FALSE},
2785             {"winehq.org",S_OK,FALSE},
2786             {"",S_FALSE,FALSE},
2787             {"",S_FALSE,FALSE},
2788             {"www.winehq.org",S_OK,FALSE},
2789             {"",S_FALSE,FALSE},
2790             {"/",S_OK,FALSE},
2791             {"/?query=<|>&return=y",S_OK,FALSE},
2792             {"?query=<|>&return=y",S_OK,FALSE},
2793             {"zip://www.winehq.org/tests/..?query=<|>&return=y",S_OK,FALSE},
2794             {"zip",S_OK,FALSE},
2795             {"",S_FALSE,FALSE},
2796             {"",S_FALSE,FALSE}
2797         },
2798         {
2799             {Uri_HOST_DNS,S_OK,FALSE},
2800             {0,S_FALSE,FALSE},
2801             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2802             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2803         }
2804     },
2805     /* Percent encoded, unreserved characters are decoded for known scheme types. */
2806     {   "http://www.winehq.org/tests/..?query=%30%31&return=y", 0, S_OK, FALSE,
2807         {
2808             {"http://www.winehq.org/?query=01&return=y",S_OK,FALSE},
2809             {"www.winehq.org",S_OK,FALSE},
2810             {"http://www.winehq.org/?query=01&return=y",S_OK,FALSE},
2811             {"winehq.org",S_OK,FALSE},
2812             {"",S_FALSE,FALSE},
2813             {"",S_FALSE,FALSE},
2814             {"www.winehq.org",S_OK,FALSE},
2815             {"",S_FALSE,FALSE},
2816             {"/",S_OK,FALSE},
2817             {"/?query=01&return=y",S_OK,FALSE},
2818             {"?query=01&return=y",S_OK,FALSE},
2819             {"http://www.winehq.org/tests/..?query=%30%31&return=y",S_OK,FALSE},
2820             {"http",S_OK,FALSE},
2821             {"",S_FALSE,FALSE},
2822             {"",S_FALSE,FALSE}
2823         },
2824         {
2825             {Uri_HOST_DNS,S_OK,FALSE},
2826             {80,S_OK,FALSE},
2827             {URL_SCHEME_HTTP,S_OK,FALSE},
2828             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2829         }
2830     },
2831     /* Percent encoded, unreserved characters aren't decoded for unknown scheme types. */
2832     {   "zip://www.winehq.org/tests/..?query=%30%31&return=y", 0, S_OK, FALSE,
2833         {
2834             {"zip://www.winehq.org/?query=%30%31&return=y",S_OK,FALSE},
2835             {"www.winehq.org",S_OK,FALSE},
2836             {"zip://www.winehq.org/?query=%30%31&return=y",S_OK,FALSE},
2837             {"winehq.org",S_OK,FALSE},
2838             {"",S_FALSE,FALSE},
2839             {"",S_FALSE,FALSE},
2840             {"www.winehq.org",S_OK,FALSE},
2841             {"",S_FALSE,FALSE},
2842             {"/",S_OK,FALSE},
2843             {"/?query=%30%31&return=y",S_OK,FALSE},
2844             {"?query=%30%31&return=y",S_OK,FALSE},
2845             {"zip://www.winehq.org/tests/..?query=%30%31&return=y",S_OK,FALSE},
2846             {"zip",S_OK,FALSE},
2847             {"",S_FALSE,FALSE},
2848             {"",S_FALSE,FALSE}
2849         },
2850         {
2851             {Uri_HOST_DNS,S_OK,FALSE},
2852             {0,S_FALSE,FALSE},
2853             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2854             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2855         }
2856     },
2857     /* Percent encoded characters aren't decoded when NO_DECODE_EXTRA_INFO is set. */
2858     {   "http://www.winehq.org/tests/..?query=%30%31&return=y", Uri_CREATE_NO_DECODE_EXTRA_INFO, S_OK, FALSE,
2859         {
2860             {"http://www.winehq.org/?query=%30%31&return=y",S_OK,FALSE},
2861             {"www.winehq.org",S_OK,FALSE},
2862             {"http://www.winehq.org/?query=%30%31&return=y",S_OK,FALSE},
2863             {"winehq.org",S_OK,FALSE},
2864             {"",S_FALSE,FALSE},
2865             {"",S_FALSE,FALSE},
2866             {"www.winehq.org",S_OK,FALSE},
2867             {"",S_FALSE,FALSE},
2868             {"/",S_OK,FALSE},
2869             {"/?query=%30%31&return=y",S_OK,FALSE},
2870             {"?query=%30%31&return=y",S_OK,FALSE},
2871             {"http://www.winehq.org/tests/..?query=%30%31&return=y",S_OK,FALSE},
2872             {"http",S_OK,FALSE},
2873             {"",S_FALSE,FALSE},
2874             {"",S_FALSE,FALSE}
2875         },
2876         {
2877             {Uri_HOST_DNS,S_OK,FALSE},
2878             {80,S_OK,FALSE},
2879             {URL_SCHEME_HTTP,S_OK,FALSE},
2880             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2881         }
2882     },
2883     {   "http://www.winehq.org?query=12&return=y", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
2884         {
2885             {"http://www.winehq.org?query=12&return=y",S_OK,FALSE},
2886             {"www.winehq.org",S_OK,FALSE},
2887             {"http://www.winehq.org?query=12&return=y",S_OK,FALSE},
2888             {"winehq.org",S_OK,FALSE},
2889             {"",S_FALSE,FALSE},
2890             {"",S_FALSE,FALSE},
2891             {"www.winehq.org",S_OK,FALSE},
2892             {"",S_FALSE,FALSE},
2893             {"",S_FALSE,FALSE},
2894             {"?query=12&return=y",S_OK,FALSE},
2895             {"?query=12&return=y",S_OK,FALSE},
2896             {"http://www.winehq.org?query=12&return=y",S_OK,FALSE},
2897             {"http",S_OK,FALSE},
2898             {"",S_FALSE,FALSE},
2899             {"",S_FALSE,FALSE}
2900         },
2901         {
2902             {Uri_HOST_DNS,S_OK,FALSE},
2903             {80,S_OK,FALSE},
2904             {URL_SCHEME_HTTP,S_OK,FALSE},
2905             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2906         }
2907     },
2908     /* Unknown scheme types can have invalid % encoded data in fragments. */
2909     {   "zip://www.winehq.org/tests/#Te%xx", 0, S_OK, FALSE,
2910         {
2911             {"zip://www.winehq.org/tests/#Te%xx",S_OK,FALSE},
2912             {"www.winehq.org",S_OK,FALSE},
2913             {"zip://www.winehq.org/tests/#Te%xx",S_OK,FALSE},
2914             {"winehq.org",S_OK,FALSE},
2915             {"",S_FALSE,FALSE},
2916             {"#Te%xx",S_OK,FALSE},
2917             {"www.winehq.org",S_OK,FALSE},
2918             {"",S_FALSE,FALSE},
2919             {"/tests/",S_OK,FALSE},
2920             {"/tests/",S_OK,FALSE},
2921             {"",S_FALSE,FALSE},
2922             {"zip://www.winehq.org/tests/#Te%xx",S_OK,FALSE},
2923             {"zip",S_OK,FALSE},
2924             {"",S_FALSE,FALSE},
2925             {"",S_FALSE,FALSE}
2926         },
2927         {
2928             {Uri_HOST_DNS,S_OK,FALSE},
2929             {0,S_FALSE,FALSE},
2930             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2931             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2932         }
2933     },
2934     /* Forbidden characters in fragment aren't encoded for unknown schemes. */
2935     {   "zip://www.winehq.org/tests/#Te<|>", 0, S_OK, FALSE,
2936         {
2937             {"zip://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
2938             {"www.winehq.org",S_OK,FALSE},
2939             {"zip://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
2940             {"winehq.org",S_OK,FALSE},
2941             {"",S_FALSE,FALSE},
2942             {"#Te<|>",S_OK,FALSE},
2943             {"www.winehq.org",S_OK,FALSE},
2944             {"",S_FALSE,FALSE},
2945             {"/tests/",S_OK,FALSE},
2946             {"/tests/",S_OK,FALSE},
2947             {"",S_FALSE,FALSE},
2948             {"zip://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
2949             {"zip",S_OK,FALSE},
2950             {"",S_FALSE,FALSE},
2951             {"",S_FALSE,FALSE}
2952         },
2953         {
2954             {Uri_HOST_DNS,S_OK,FALSE},
2955             {0,S_FALSE,FALSE},
2956             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2957             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2958         }
2959     },
2960     /* Forbidden characters in the fragment are percent encoded for known schemes. */
2961     {   "http://www.winehq.org/tests/#Te<|>", 0, S_OK, FALSE,
2962         {
2963             {"http://www.winehq.org/tests/#Te%3C%7C%3E",S_OK,FALSE},
2964             {"www.winehq.org",S_OK,FALSE},
2965             {"http://www.winehq.org/tests/#Te%3C%7C%3E",S_OK,FALSE},
2966             {"winehq.org",S_OK,FALSE},
2967             {"",S_FALSE,FALSE},
2968             {"#Te%3C%7C%3E",S_OK,FALSE},
2969             {"www.winehq.org",S_OK,FALSE},
2970             {"",S_FALSE,FALSE},
2971             {"/tests/",S_OK,FALSE},
2972             {"/tests/",S_OK,FALSE},
2973             {"",S_FALSE,FALSE},
2974             {"http://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
2975             {"http",S_OK,FALSE},
2976             {"",S_FALSE,FALSE},
2977             {"",S_FALSE,FALSE}
2978         },
2979         {
2980             {Uri_HOST_DNS,S_OK,FALSE},
2981             {80,S_OK,FALSE},
2982             {URL_SCHEME_HTTP,S_OK,FALSE},
2983             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2984         }
2985     },
2986     /* Forbidden characters aren't encoded in the fragment with this flag. */
2987     {   "http://www.winehq.org/tests/#Te<|>", Uri_CREATE_NO_DECODE_EXTRA_INFO, S_OK, FALSE,
2988         {
2989             {"http://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
2990             {"www.winehq.org",S_OK,FALSE},
2991             {"http://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
2992             {"winehq.org",S_OK,FALSE},
2993             {"",S_FALSE,FALSE},
2994             {"#Te<|>",S_OK,FALSE},
2995             {"www.winehq.org",S_OK,FALSE},
2996             {"",S_FALSE,FALSE},
2997             {"/tests/",S_OK,FALSE},
2998             {"/tests/",S_OK,FALSE},
2999             {"",S_FALSE,FALSE},
3000             {"http://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
3001             {"http",S_OK,FALSE},
3002             {"",S_FALSE,FALSE},
3003             {"",S_FALSE,FALSE}
3004         },
3005         {
3006             {Uri_HOST_DNS,S_OK,FALSE},
3007             {80,S_OK,FALSE},
3008             {URL_SCHEME_HTTP,S_OK,FALSE},
3009             {URLZONE_INVALID,E_NOTIMPL,FALSE},
3010         }
3011     },
3012     /* Forbidden characters aren't encoded in the fragment with this flag. */
3013     {   "http://www.winehq.org/tests/#Te<|>", Uri_CREATE_NO_ENCODE_FORBIDDEN_CHARACTERS, S_OK, FALSE,
3014         {
3015             {"http://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
3016             {"www.winehq.org",S_OK,FALSE},
3017             {"http://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
3018             {"winehq.org",S_OK,FALSE},
3019             {"",S_FALSE,FALSE},
3020             {"#Te<|>",S_OK,FALSE},
3021             {"www.winehq.org",S_OK,FALSE},
3022             {"",S_FALSE,FALSE},
3023             {"/tests/",S_OK,FALSE},
3024             {"/tests/",S_OK,FALSE},
3025             {"",S_FALSE,FALSE},
3026             {"http://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
3027             {"http",S_OK,FALSE},
3028             {"",S_FALSE,FALSE},
3029             {"",S_FALSE,FALSE}
3030         },
3031         {
3032             {Uri_HOST_DNS,S_OK,FALSE},
3033             {80,S_OK,FALSE},
3034             {URL_SCHEME_HTTP,S_OK,FALSE},
3035             {URLZONE_INVALID,E_NOTIMPL,FALSE},
3036         }
3037     },
3038     /* Percent encoded, unreserved characters aren't decoded for known scheme types. */
3039     {   "zip://www.winehq.org/tests/#Te%30%31%32", 0, S_OK, FALSE,
3040         {
3041             {"zip://www.winehq.org/tests/#Te%30%31%32",S_OK,FALSE},
3042             {"www.winehq.org",S_OK,FALSE},
3043             {"zip://www.winehq.org/tests/#Te%30%31%32",S_OK,FALSE},
3044             {"winehq.org",S_OK,FALSE},
3045             {"",S_FALSE,FALSE},
3046             {"#Te%30%31%32",S_OK,FALSE},
3047             {"www.winehq.org",S_OK,FALSE},
3048             {"",S_FALSE,FALSE},
3049             {"/tests/",S_OK,FALSE},
3050             {"/tests/",S_OK,FALSE},
3051             {"",S_FALSE,FALSE},
3052             {"zip://www.winehq.org/tests/#Te%30%31%32",S_OK,FALSE},
3053             {"zip",S_OK,FALSE},
3054             {"",S_FALSE,FALSE},
3055             {"",S_FALSE,FALSE}
3056         },
3057         {
3058             {Uri_HOST_DNS,S_OK,FALSE},
3059             {0,S_FALSE,FALSE},
3060             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
3061             {URLZONE_INVALID,E_NOTIMPL,FALSE},
3062         }
3063     },
3064     /* Percent encoded, unreserved characters are decoded for known schemes. */
3065     {   "http://www.winehq.org/tests/#Te%30%31%32", 0, S_OK, FALSE,
3066         {
3067             {"http://www.winehq.org/tests/#Te012",S_OK,FALSE},
3068             {"www.winehq.org",S_OK,FALSE},
3069             {"http://www.winehq.org/tests/#Te012",S_OK,FALSE},
3070             {"winehq.org",S_OK,FALSE},
3071             {"",S_FALSE,FALSE},
3072             {"#Te012",S_OK,FALSE},
3073             {"www.winehq.org",S_OK,FALSE},
3074             {"",S_FALSE,FALSE},
3075             {"/tests/",S_OK,FALSE},
3076             {"/tests/",S_OK,FALSE},
3077             {"",S_FALSE,FALSE},
3078             {"http://www.winehq.org/tests/#Te%30%31%32",S_OK,FALSE},
3079             {"http",S_OK,FALSE},
3080             {"",S_FALSE,FALSE},
3081             {"",S_FALSE,FALSE}
3082         },
3083         {
3084             {Uri_HOST_DNS,S_OK,FALSE},
3085             {80,S_OK,FALSE},
3086             {URL_SCHEME_HTTP,S_OK,FALSE},
3087             {URLZONE_INVALID,E_NOTIMPL,FALSE},
3088         }
3089     },
3090     /* Percent encoded, unreserved characters are decoded even if NO_CANONICALIZE is set. */
3091     {   "http://www.winehq.org/tests/#Te%30%31%32", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
3092         {
3093             {"http://www.winehq.org/tests/#Te012",S_OK,FALSE},
3094             {"www.winehq.org",S_OK,FALSE},
3095             {"http://www.winehq.org/tests/#Te012",S_OK,FALSE},
3096             {"winehq.org",S_OK,FALSE},
3097             {"",S_FALSE,FALSE},
3098             {"#Te012",S_OK,FALSE},
3099             {"www.winehq.org",S_OK,FALSE},
3100             {"",S_FALSE,FALSE},
3101             {"/tests/",S_OK,FALSE},
3102             {"/tests/",S_OK,FALSE},
3103             {"",S_FALSE,FALSE},
3104             {"http://www.winehq.org/tests/#Te%30%31%32",S_OK,FALSE},
3105             {"http",S_OK,FALSE},
3106             {"",S_FALSE,FALSE},
3107             {"",S_FALSE,FALSE}
3108         },
3109         {
3110             {Uri_HOST_DNS,S_OK,FALSE},
3111             {80,S_OK,FALSE},
3112             {URL_SCHEME_HTTP,S_OK,FALSE},
3113             {URLZONE_INVALID,E_NOTIMPL,FALSE},
3114         }
3115     },
3116     /* Percent encoded, unreserved characters aren't decoded when NO_DECODE_EXTRA is set. */
3117     {   "http://www.winehq.org/tests/#Te%30%31%32", Uri_CREATE_NO_DECODE_EXTRA_INFO, S_OK, FALSE,
3118         {
3119             {"http://www.winehq.org/tests/#Te%30%31%32",S_OK,FALSE},
3120             {"www.winehq.org",S_OK,FALSE},
3121             {"http://www.winehq.org/tests/#Te%30%31%32",S_OK,FALSE},
3122             {"winehq.org",S_OK,FALSE},
3123             {"",S_FALSE,FALSE},
3124             {"#Te%30%31%32",S_OK,FALSE},
3125             {"www.winehq.org",S_OK,FALSE},
3126             {"",S_FALSE,FALSE},
3127             {"/tests/",S_OK,FALSE},
3128             {"/tests/",S_OK,FALSE},
3129             {"",S_FALSE,FALSE},
3130             {"http://www.winehq.org/tests/#Te%30%31%32",S_OK,FALSE},
3131             {"http",S_OK,FALSE},
3132             {"",S_FALSE,FALSE},
3133             {"",S_FALSE,FALSE}
3134         },
3135         {
3136             {Uri_HOST_DNS,S_OK,FALSE},
3137             {80,S_OK,FALSE},
3138             {URL_SCHEME_HTTP,S_OK,FALSE},
3139             {URLZONE_INVALID,E_NOTIMPL,FALSE},
3140         }
3141     },
3142     /* Leading/Trailing whitespace is removed. */
3143     {   "    http://google.com/     ", 0, S_OK, FALSE,
3144         {
3145             {"http://google.com/",S_OK,FALSE},
3146             {"google.com",S_OK,FALSE},
3147             {"http://google.com/",S_OK,FALSE},
3148             {"google.com",S_OK,FALSE},
3149             {"",S_FALSE,FALSE},
3150             {"",S_FALSE,FALSE},
3151             {"google.com",S_OK,FALSE},
3152             {"",S_FALSE,FALSE},
3153             {"/",S_OK,FALSE},
3154             {"/",S_OK,FALSE},
3155             {"",S_FALSE,FALSE},
3156             {"http://google.com/",S_OK,FALSE},
3157             {"http",S_OK,FALSE},
3158             {"",S_FALSE,FALSE},
3159             {"",S_FALSE,FALSE}
3160         },
3161         {
3162             {Uri_HOST_DNS,S_OK,FALSE},
3163             {80,S_OK,FALSE},
3164             {URL_SCHEME_HTTP,S_OK,FALSE},
3165             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3166         }
3167     },
3168     {   "\t\t\r\nhttp\n://g\noogle.co\rm/\n\n\n", 0, S_OK, FALSE,
3169         {
3170             {"http://google.com/",S_OK,FALSE},
3171             {"google.com",S_OK,FALSE},
3172             {"http://google.com/",S_OK,FALSE},
3173             {"google.com",S_OK,FALSE},
3174             {"",S_FALSE,FALSE},
3175             {"",S_FALSE,FALSE},
3176             {"google.com",S_OK,FALSE},
3177             {"",S_FALSE,FALSE},
3178             {"/",S_OK,FALSE},
3179             {"/",S_OK,FALSE},
3180             {"",S_FALSE,FALSE},
3181             {"http://google.com/",S_OK,FALSE},
3182             {"http",S_OK,FALSE},
3183             {"",S_FALSE,FALSE},
3184             {"",S_FALSE,FALSE}
3185         },
3186         {
3187             {Uri_HOST_DNS,S_OK,FALSE},
3188             {80,S_OK,FALSE},
3189             {URL_SCHEME_HTTP,S_OK,FALSE},
3190             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3191         }
3192     },
3193     {   "http://g\noogle.co\rm/\n\n\n", Uri_CREATE_NO_PRE_PROCESS_HTML_URI, S_OK, FALSE,
3194         {
3195             {"http://g%0aoogle.co%0dm/%0A%0A%0A",S_OK,FALSE},
3196             {"g%0aoogle.co%0dm",S_OK,FALSE},
3197             {"http://g%0aoogle.co%0dm/%0A%0A%0A",S_OK,FALSE},
3198             {"g%0aoogle.co%0dm",S_OK,FALSE},
3199             {"",S_FALSE,FALSE},
3200             {"",S_FALSE,FALSE},
3201             {"g%0aoogle.co%0dm",S_OK,FALSE},
3202             {"",S_FALSE,FALSE},
3203             {"/%0A%0A%0A",S_OK,FALSE},
3204             {"/%0A%0A%0A",S_OK,FALSE},
3205             {"",S_FALSE,FALSE},
3206             {"http://g\noogle.co\rm/\n\n\n",S_OK,FALSE},
3207             {"http",S_OK,FALSE},
3208             {"",S_FALSE,FALSE},
3209             {"",S_FALSE,FALSE}
3210         },
3211         {
3212             {Uri_HOST_DNS,S_OK,FALSE},
3213             {80,S_OK,FALSE},
3214             {URL_SCHEME_HTTP,S_OK,FALSE},
3215             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3216         }
3217     },
3218     {   "zip://g\noogle.co\rm/\n\n\n", Uri_CREATE_NO_PRE_PROCESS_HTML_URI, S_OK, FALSE,
3219         {
3220             {"zip://g\noogle.co\rm/\n\n\n",S_OK,FALSE},
3221             {"g\noogle.co\rm",S_OK,FALSE},
3222             {"zip://g\noogle.co\rm/\n\n\n",S_OK,FALSE},
3223             {"g\noogle.co\rm",S_OK,FALSE},
3224             {"",S_FALSE,FALSE},
3225             {"",S_FALSE,FALSE},
3226             {"g\noogle.co\rm",S_OK,FALSE},
3227             {"",S_FALSE,FALSE},
3228             {"/\n\n\n",S_OK,FALSE},
3229             {"/\n\n\n",S_OK,FALSE},
3230             {"",S_FALSE,FALSE},
3231             {"zip://g\noogle.co\rm/\n\n\n",S_OK,FALSE},
3232             {"zip",S_OK,FALSE},
3233             {"",S_FALSE,FALSE},
3234             {"",S_FALSE,FALSE}
3235         },
3236         {
3237             {Uri_HOST_DNS,S_OK,FALSE},
3238             {0,S_FALSE,FALSE},
3239             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
3240             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3241         }
3242     },
3243     /* Since file URLs are usually hierarchical, it returns an empty string
3244      * for the absolute URI property since it was declared as an opaque URI.
3245      */
3246     {   "file:index.html", 0, S_OK, FALSE,
3247         {
3248             {"",S_FALSE,FALSE},
3249             {"",S_FALSE,FALSE},
3250             {"file:index.html",S_OK,FALSE},
3251             {"",S_FALSE,FALSE},
3252             {".html",S_OK,FALSE},
3253             {"",S_FALSE,FALSE},
3254             {"",S_FALSE,FALSE},
3255             {"",S_FALSE,FALSE},
3256             {"index.html",S_OK,FALSE},
3257             {"index.html",S_OK,FALSE},
3258             {"",S_FALSE,FALSE},
3259             {"file:index.html",S_OK,FALSE},
3260             {"file",S_OK,FALSE},
3261             {"",S_FALSE,FALSE},
3262             {"",S_FALSE,FALSE}
3263         },
3264         {
3265             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3266             {0,S_FALSE,FALSE},
3267             {URL_SCHEME_FILE,S_OK,FALSE},
3268             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3269         }
3270     },
3271     /* Doesn't have an absolute since it's opaque, but gets it port set. */
3272     {   "http:test.com/index.html", 0, S_OK, FALSE,
3273         {
3274             {"",S_FALSE,FALSE},
3275             {"",S_FALSE,FALSE},
3276             {"http:test.com/index.html",S_OK,FALSE},
3277             {"",S_FALSE,FALSE},
3278             {".html",S_OK,FALSE},
3279             {"",S_FALSE,FALSE},
3280             {"",S_FALSE,FALSE},
3281             {"",S_FALSE,FALSE},
3282             {"test.com/index.html",S_OK,FALSE},
3283             {"test.com/index.html",S_OK,FALSE},
3284             {"",S_FALSE,FALSE},
3285             {"http:test.com/index.html",S_OK,FALSE},
3286             {"http",S_OK,FALSE},
3287             {"",S_FALSE,FALSE},
3288             {"",S_FALSE,FALSE}
3289         },
3290         {
3291             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3292             {80,S_OK,FALSE},
3293             {URL_SCHEME_HTTP,S_OK,FALSE},
3294             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3295         }
3296     },
3297     {   "ftp:test.com/index.html", 0, S_OK, FALSE,
3298         {
3299             {"",S_FALSE,FALSE},
3300             {"",S_FALSE,FALSE},
3301             {"ftp:test.com/index.html",S_OK,FALSE},
3302             {"",S_FALSE,FALSE},
3303             {".html",S_OK,FALSE},
3304             {"",S_FALSE,FALSE},
3305             {"",S_FALSE,FALSE},
3306             {"",S_FALSE,FALSE},
3307             {"test.com/index.html",S_OK,FALSE},
3308             {"test.com/index.html",S_OK,FALSE},
3309             {"",S_FALSE,FALSE},
3310             {"ftp:test.com/index.html",S_OK,FALSE},
3311             {"ftp",S_OK,FALSE},
3312             {"",S_FALSE,FALSE},
3313             {"",S_FALSE,FALSE}
3314         },
3315         {
3316             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3317             {21,S_OK,FALSE},
3318             {URL_SCHEME_FTP,S_OK,FALSE},
3319             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3320         }
3321     },
3322     {   "file://C|/test.mp3", 0, S_OK, FALSE,
3323         {
3324             {"file:///C:/test.mp3",S_OK,FALSE},
3325             {"",S_FALSE,FALSE},
3326             {"file:///C:/test.mp3",S_OK,FALSE},
3327             {"",S_FALSE,FALSE},
3328             {".mp3",S_OK,FALSE},
3329             {"",S_FALSE,FALSE},
3330             {"",S_FALSE,FALSE},
3331             {"",S_FALSE,FALSE},
3332             {"/C:/test.mp3",S_OK,FALSE},
3333             {"/C:/test.mp3",S_OK,FALSE},
3334             {"",S_FALSE,FALSE},
3335             {"file://C|/test.mp3",S_OK,FALSE},
3336             {"file",S_OK,FALSE},
3337             {"",S_FALSE,FALSE},
3338             {"",S_FALSE,FALSE}
3339         },
3340         {
3341             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3342             {0,S_FALSE,FALSE},
3343             {URL_SCHEME_FILE,S_OK,FALSE},
3344             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3345         }
3346     },
3347     {   "file:///C|/test.mp3", 0, S_OK, FALSE,
3348         {
3349             {"file:///C:/test.mp3",S_OK,FALSE},
3350             {"",S_FALSE,FALSE},
3351             {"file:///C:/test.mp3",S_OK,FALSE},
3352             {"",S_FALSE,FALSE},
3353             {".mp3",S_OK,FALSE},
3354             {"",S_FALSE,FALSE},
3355             {"",S_FALSE,FALSE},
3356             {"",S_FALSE,FALSE},
3357             {"/C:/test.mp3",S_OK,FALSE},
3358             {"/C:/test.mp3",S_OK,FALSE},
3359             {"",S_FALSE,FALSE},
3360             {"file:///C|/test.mp3",S_OK,FALSE},
3361             {"file",S_OK,FALSE},
3362             {"",S_FALSE,FALSE},
3363             {"",S_FALSE,FALSE}
3364         },
3365         {
3366             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3367             {0,S_FALSE,FALSE},
3368             {URL_SCHEME_FILE,S_OK,FALSE},
3369             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3370         }
3371     },
3372     /* Extra '/' isn't added before "c:" since USE_DOS_PATH is set and '/' are converted
3373      * to '\\'.
3374      */
3375     {   "file://c:/dir/index.html", Uri_CREATE_FILE_USE_DOS_PATH, S_OK, FALSE,
3376         {
3377             {"file://c:\\dir\\index.html",S_OK,FALSE},
3378             {"",S_FALSE,FALSE},
3379             {"file://c:\\dir\\index.html",S_OK,FALSE},
3380             {"",S_FALSE,FALSE},
3381             {".html",S_OK,FALSE},
3382             {"",S_FALSE,FALSE},
3383             {"",S_FALSE,FALSE},
3384             {"",S_FALSE,FALSE},
3385             {"c:\\dir\\index.html",S_OK,FALSE},
3386             {"c:\\dir\\index.html",S_OK,FALSE},
3387             {"",S_FALSE,FALSE},
3388             {"file://c:/dir/index.html",S_OK,FALSE},
3389             {"file",S_OK,FALSE},
3390             {"",S_FALSE,FALSE},
3391             {"",S_FALSE,FALSE}
3392         },
3393         {
3394             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3395             {0,S_FALSE,FALSE},
3396             {URL_SCHEME_FILE,S_OK,FALSE},
3397             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3398         }
3399     },
3400     /* Extra '/' after "file://" is removed. */
3401     {   "file:///c:/dir/index.html", Uri_CREATE_FILE_USE_DOS_PATH, S_OK, FALSE,
3402         {
3403             {"file://c:\\dir\\index.html",S_OK,FALSE},
3404             {"",S_FALSE,FALSE},
3405             {"file://c:\\dir\\index.html",S_OK,FALSE},
3406             {"",S_FALSE,FALSE},
3407             {".html",S_OK,FALSE},
3408             {"",S_FALSE,FALSE},
3409             {"",S_FALSE,FALSE},
3410             {"",S_FALSE,FALSE},
3411             {"c:\\dir\\index.html",S_OK,FALSE},
3412             {"c:\\dir\\index.html",S_OK,FALSE},
3413             {"",S_FALSE,FALSE},
3414             {"file:///c:/dir/index.html",S_OK,FALSE},
3415             {"file",S_OK,FALSE},
3416             {"",S_FALSE,FALSE},
3417             {"",S_FALSE,FALSE}
3418         },
3419         {
3420             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3421             {0,S_FALSE,FALSE},
3422             {URL_SCHEME_FILE,S_OK,FALSE},
3423             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3424         }
3425     },
3426     /* Allow more characters when Uri_CREATE_FILE_USE_DOS_PATH is specified */
3427     {   "file:///c:/dir\\%%61%20%5Fname/file%2A.html", Uri_CREATE_FILE_USE_DOS_PATH, S_OK, FALSE,
3428         {
3429             {"file://c:\\dir\\%a _name\\file*.html",S_OK,FALSE},
3430             {"",S_FALSE,FALSE},
3431             {"file://c:\\dir\\%a _name\\file*.html",S_OK,FALSE},
3432             {"",S_FALSE,FALSE},
3433             {".html",S_OK,FALSE},
3434             {"",S_FALSE,FALSE},
3435             {"",S_FALSE,FALSE},
3436             {"",S_FALSE,FALSE},
3437             {"c:\\dir\\%a _name\\file*.html",S_OK,FALSE},
3438             {"c:\\dir\\%a _name\\file*.html",S_OK,FALSE},
3439             {"",S_FALSE,FALSE},
3440             {"file:///c:/dir\\%%61%20%5Fname/file%2A.html",S_OK,FALSE},
3441             {"file",S_OK,FALSE},
3442             {"",S_FALSE,FALSE},
3443             {"",S_FALSE,FALSE}
3444         },
3445         {
3446             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3447             {0,S_FALSE,FALSE},
3448             {URL_SCHEME_FILE,S_OK,FALSE},
3449             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3450         }
3451     },
3452     {   "file://c|/dir\\index.html", Uri_CREATE_FILE_USE_DOS_PATH, S_OK, FALSE,
3453         {
3454             {"file://c:\\dir\\index.html",S_OK,FALSE},
3455             {"",S_FALSE,FALSE},
3456             {"file://c:\\dir\\index.html",S_OK,FALSE},
3457             {"",S_FALSE,FALSE},
3458             {".html",S_OK,FALSE},
3459             {"",S_FALSE,FALSE},
3460             {"",S_FALSE,FALSE},
3461             {"",S_FALSE,FALSE},
3462             {"c:\\dir\\index.html",S_OK,FALSE},
3463             {"c:\\dir\\index.html",S_OK,FALSE},
3464             {"",S_FALSE,FALSE},
3465             {"file://c|/dir\\index.html",S_OK,FALSE},
3466             {"file",S_OK,FALSE},
3467             {"",S_FALSE,FALSE},
3468             {"",S_FALSE,FALSE}
3469         },
3470         {
3471             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3472             {0,S_FALSE,FALSE},
3473             {URL_SCHEME_FILE,S_OK,FALSE},
3474             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3475         }
3476     },
3477     /* The backslashes after the scheme name are converted to forward slashes. */
3478     {   "file:\\\\c:\\dir\\index.html", Uri_CREATE_FILE_USE_DOS_PATH, S_OK, FALSE,
3479         {
3480             {"file://c:\\dir\\index.html",S_OK,FALSE},
3481             {"",S_FALSE,FALSE},
3482             {"file://c:\\dir\\index.html",S_OK,FALSE},
3483             {"",S_FALSE,FALSE},
3484             {".html",S_OK,FALSE},
3485             {"",S_FALSE,FALSE},
3486             {"",S_FALSE,FALSE},
3487             {"",S_FALSE,FALSE},
3488             {"c:\\dir\\index.html",S_OK,FALSE},
3489             {"c:\\dir\\index.html",S_OK,FALSE},
3490             {"",S_FALSE,FALSE},
3491             {"file:\\\\c:\\dir\\index.html",S_OK,FALSE},
3492             {"file",S_OK,FALSE},
3493             {"",S_FALSE,FALSE},
3494             {"",S_FALSE,FALSE}
3495         },
3496         {
3497             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3498             {0,S_FALSE,FALSE},
3499             {URL_SCHEME_FILE,S_OK,FALSE},
3500             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3501         }
3502     },
3503     {   "file:\\\\c:/dir/index.html", 0, S_OK, FALSE,
3504         {
3505             {"file:///c:/dir/index.html",S_OK,FALSE},
3506             {"",S_FALSE,FALSE},
3507             {"file:///c:/dir/index.html",S_OK,FALSE},
3508             {"",S_FALSE,FALSE},
3509             {".html",S_OK,FALSE},
3510             {"",S_FALSE,FALSE},
3511             {"",S_FALSE,FALSE},
3512             {"",S_FALSE,FALSE},
3513             {"/c:/dir/index.html",S_OK,FALSE},
3514             {"/c:/dir/index.html",S_OK,FALSE},
3515             {"",S_FALSE,FALSE},
3516             {"file:\\\\c:/dir/index.html",S_OK,FALSE},
3517             {"file",S_OK,FALSE},
3518             {"",S_FALSE,FALSE},
3519             {"",S_FALSE,FALSE}
3520         },
3521         {
3522             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3523             {0,S_FALSE,FALSE},
3524             {URL_SCHEME_FILE,S_OK,FALSE},
3525             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3526         }
3527     },
3528     {   "http:\\\\google.com", 0, S_OK, FALSE,
3529         {
3530             {"http://google.com/",S_OK,FALSE},
3531             {"google.com",S_OK,FALSE},
3532             {"http://google.com/",S_OK,FALSE},
3533             {"google.com",S_OK,FALSE},
3534             {"",S_FALSE,FALSE},
3535             {"",S_FALSE,FALSE},
3536             {"google.com",S_OK,FALSE},
3537             {"",S_FALSE,FALSE},
3538             {"/",S_OK,FALSE},
3539             {"/",S_OK,FALSE},
3540             {"",S_FALSE,FALSE},
3541             {"http:\\\\google.com",S_OK,FALSE},
3542             {"http",S_OK,FALSE},
3543             {"",S_FALSE,FALSE},
3544             {"",S_FALSE,FALSE}
3545         },
3546         {
3547             {Uri_HOST_DNS,S_OK,FALSE},
3548             {80,S_OK,FALSE},
3549             {URL_SCHEME_HTTP,S_OK,FALSE},
3550             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3551         }
3552     },
3553     /* the "\\\\" aren't converted to "//" for unknown scheme types and it's considered opaque. */
3554     {   "zip:\\\\google.com", 0, S_OK, FALSE,
3555         {
3556             {"zip:\\\\google.com",S_OK,FALSE},
3557             {"",S_FALSE,FALSE},
3558             {"zip:\\\\google.com",S_OK,FALSE},
3559             {"",S_FALSE,FALSE},
3560             {".com",S_OK,FALSE},
3561             {"",S_FALSE,FALSE},
3562             {"",S_FALSE,FALSE},
3563             {"",S_FALSE,FALSE},
3564             {"\\\\google.com",S_OK,FALSE},
3565             {"\\\\google.com",S_OK,FALSE},
3566             {"",S_FALSE,FALSE},
3567             {"zip:\\\\google.com",S_OK,FALSE},
3568             {"zip",S_OK,FALSE},
3569             {"",S_FALSE,FALSE},
3570             {"",S_FALSE,FALSE}
3571         },
3572         {
3573             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3574             {0,S_FALSE,FALSE},
3575             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
3576             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3577         }
3578     },
3579     /* Dot segments aren't removed. */
3580     {   "file://c:\\dir\\../..\\./index.html", Uri_CREATE_FILE_USE_DOS_PATH, S_OK, FALSE,
3581         {
3582             {"file://c:\\dir\\..\\..\\.\\index.html",S_OK,FALSE},
3583             {"",S_FALSE,FALSE},
3584             {"file://c:\\dir\\..\\..\\.\\index.html",S_OK,FALSE},
3585             {"",S_FALSE,FALSE},
3586             {".html",S_OK,FALSE},
3587             {"",S_FALSE,FALSE},
3588             {"",S_FALSE,FALSE},
3589             {"",S_FALSE,FALSE},
3590             {"c:\\dir\\..\\..\\.\\index.html",S_OK,FALSE},
3591             {"c:\\dir\\..\\..\\.\\index.html",S_OK,FALSE},
3592             {"",S_FALSE,FALSE},
3593             {"file://c:\\dir\\../..\\./index.html",S_OK,FALSE},
3594             {"file",S_OK,FALSE},
3595             {"",S_FALSE,FALSE},
3596             {"",S_FALSE,FALSE}
3597         },
3598         {
3599             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3600             {0,S_FALSE,FALSE},
3601             {URL_SCHEME_FILE,S_OK,FALSE},
3602             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3603         }
3604     },
3605     /* Forbidden characters aren't percent encoded. */
3606     {   "file://c:\\dir\\i^|ndex.html", Uri_CREATE_FILE_USE_DOS_PATH, S_OK, FALSE,
3607         {
3608             {"file://c:\\dir\\i^|ndex.html",S_OK,FALSE},
3609             {"",S_FALSE,FALSE},
3610             {"file://c:\\dir\\i^|ndex.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\\i^|ndex.html",S_OK,FALSE},
3617             {"c:\\dir\\i^|ndex.html",S_OK,FALSE},
3618             {"",S_FALSE,FALSE},
3619             {"file://c:\\dir\\i^|ndex.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 '\' are still converted to '/' even though it's an opaque file URI. */
3632     {   "file:c:\\dir\\../..\\index.html", 0, S_OK, FALSE,
3633         {
3634             {"",S_FALSE,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     /* '/' are still converted to '\' even though it's an opaque URI. */
3658     {   "file:c:/dir\\../..\\index.html", Uri_CREATE_FILE_USE_DOS_PATH, S_OK, FALSE,
3659         {
3660             {"",S_FALSE,FALSE},
3661             {"",S_FALSE,FALSE},
3662             {"file:c:\\dir\\..\\..\\index.html",S_OK,FALSE},
3663             {"",S_FALSE,FALSE},
3664             {".html",S_OK,FALSE},
3665             {"",S_FALSE,FALSE},
3666             {"",S_FALSE,FALSE},
3667             {"",S_FALSE,FALSE},
3668             {"c:\\dir\\..\\..\\index.html",S_OK,FALSE},
3669             {"c:\\dir\\..\\..\\index.html",S_OK,FALSE},
3670             {"",S_FALSE,FALSE},
3671             {"file:c:/dir\\../..\\index.html",S_OK,FALSE},
3672             {"file",S_OK,FALSE},
3673             {"",S_FALSE,FALSE},
3674             {"",S_FALSE,FALSE}
3675         },
3676         {
3677             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3678             {0,S_FALSE,FALSE},
3679             {URL_SCHEME_FILE,S_OK,FALSE},
3680             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3681         }
3682     },
3683     /* Forbidden characters aren't percent encoded. */
3684     {   "file:c:\\in^|dex.html", Uri_CREATE_FILE_USE_DOS_PATH, S_OK, FALSE,
3685         {
3686             {"",S_FALSE,FALSE},
3687             {"",S_FALSE,FALSE},
3688             {"file:c:\\in^|dex.html",S_OK,FALSE},
3689             {"",S_FALSE,FALSE},
3690             {".html",S_OK,FALSE},
3691             {"",S_FALSE,FALSE},
3692             {"",S_FALSE,FALSE},
3693             {"",S_FALSE,FALSE},
3694             {"c:\\in^|dex.html",S_OK,FALSE},
3695             {"c:\\in^|dex.html",S_OK,FALSE},
3696             {"",S_FALSE,FALSE},
3697             {"file:c:\\in^|dex.html",S_OK,FALSE},
3698             {"file",S_OK,FALSE},
3699             {"",S_FALSE,FALSE},
3700             {"",S_FALSE,FALSE}
3701         },
3702         {
3703             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3704             {0,S_FALSE,FALSE},
3705             {URL_SCHEME_FILE,S_OK,FALSE},
3706             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3707         }
3708     },
3709     /* Doesn't have a UserName since the ':' appears at the beginning of the
3710      * userinfo section.
3711      */
3712     {   "http://:password@gov.uk", 0, S_OK, FALSE,
3713         {
3714             {"http://:password@gov.uk/",S_OK,FALSE},
3715             {":password@gov.uk",S_OK,FALSE},
3716             {"http://gov.uk/",S_OK,FALSE},
3717             {"",S_FALSE,FALSE},
3718             {"",S_FALSE,FALSE},
3719             {"",S_FALSE,FALSE},
3720             {"gov.uk",S_OK,FALSE},
3721             {"password",S_OK,FALSE},
3722             {"/",S_OK,FALSE},
3723             {"/",S_OK,FALSE},
3724             {"",S_FALSE,FALSE},
3725             {"http://:password@gov.uk",S_OK,FALSE},
3726             {"http",S_OK,FALSE},
3727             {":password",S_OK,FALSE},
3728             {"",S_FALSE,FALSE}
3729         },
3730         {
3731             {Uri_HOST_DNS,S_OK,FALSE},
3732             {80,S_OK,FALSE},
3733             {URL_SCHEME_HTTP,S_OK,FALSE},
3734             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3735         }
3736     },
3737     /* Has a UserName since the userinfo section doesn't contain a password. */
3738     {   "http://@gov.uk", 0, S_OK, FALSE,
3739         {
3740             {"http://gov.uk/",S_OK,FALSE,"http://@gov.uk/"},
3741             {"@gov.uk",S_OK,FALSE},
3742             {"http://gov.uk/",S_OK,FALSE},
3743             {"",S_FALSE,FALSE},
3744             {"",S_FALSE,FALSE},
3745             {"",S_FALSE,FALSE},
3746             {"gov.uk",S_OK,FALSE},
3747             {"",S_FALSE,FALSE},
3748             {"/",S_OK,FALSE},
3749             {"/",S_OK,FALSE},
3750             {"",S_FALSE,FALSE},
3751             {"http://@gov.uk",S_OK,FALSE},
3752             {"http",S_OK,FALSE},
3753             {"",S_OK,FALSE},
3754             {"",S_OK,FALSE}
3755         },
3756         {
3757             {Uri_HOST_DNS,S_OK,FALSE},
3758             {80,S_OK,FALSE},
3759             {URL_SCHEME_HTTP,S_OK,FALSE},
3760             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3761         }
3762     },
3763     /* ":@" not included in the absolute URI. */
3764     {   "http://:@gov.uk", 0, S_OK, FALSE,
3765         {
3766             {"http://gov.uk/",S_OK,FALSE,"http://:@gov.uk/"},
3767             {":@gov.uk",S_OK,FALSE},
3768             {"http://gov.uk/",S_OK,FALSE},
3769             {"",S_FALSE,FALSE},
3770             {"",S_FALSE,FALSE},
3771             {"",S_FALSE,FALSE},
3772             {"gov.uk",S_OK,FALSE},
3773             {"",S_OK,FALSE},
3774             {"/",S_OK,FALSE},
3775             {"/",S_OK,FALSE},
3776             {"",S_FALSE,FALSE},
3777             {"http://:@gov.uk",S_OK,FALSE},
3778             {"http",S_OK,FALSE},
3779             {":",S_OK,FALSE},
3780             {"",S_FALSE,FALSE}
3781         },
3782         {
3783             {Uri_HOST_DNS,S_OK,FALSE},
3784             {80,S_OK,FALSE},
3785             {URL_SCHEME_HTTP,S_OK,FALSE},
3786             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3787         }
3788     },
3789     /* '@' is included because it's an unknown scheme type. */
3790     {   "zip://@gov.uk", 0, S_OK, FALSE,
3791         {
3792             {"zip://@gov.uk/",S_OK,FALSE},
3793             {"@gov.uk",S_OK,FALSE},
3794             {"zip://@gov.uk/",S_OK,FALSE},
3795             {"",S_FALSE,FALSE},
3796             {"",S_FALSE,FALSE},
3797             {"",S_FALSE,FALSE},
3798             {"gov.uk",S_OK,FALSE},
3799             {"",S_FALSE,FALSE},
3800             {"/",S_OK,FALSE},
3801             {"/",S_OK,FALSE},
3802             {"",S_FALSE,FALSE},
3803             {"zip://@gov.uk",S_OK,FALSE},
3804             {"zip",S_OK,FALSE},
3805             {"",S_OK,FALSE},
3806             {"",S_OK,FALSE}
3807         },
3808         {
3809             {Uri_HOST_DNS,S_OK,FALSE},
3810             {0,S_FALSE,FALSE},
3811             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
3812             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3813         }
3814     },
3815     /* ":@" are included because it's an unknown scheme type. */
3816     {   "zip://:@gov.uk", 0, S_OK, FALSE,
3817         {
3818             {"zip://:@gov.uk/",S_OK,FALSE},
3819             {":@gov.uk",S_OK,FALSE},
3820             {"zip://:@gov.uk/",S_OK,FALSE},
3821             {"",S_FALSE,FALSE},
3822             {"",S_FALSE,FALSE},
3823             {"",S_FALSE,FALSE},
3824             {"gov.uk",S_OK,FALSE},
3825             {"",S_OK,FALSE},
3826             {"/",S_OK,FALSE},
3827             {"/",S_OK,FALSE},
3828             {"",S_FALSE,FALSE},
3829             {"zip://:@gov.uk",S_OK,FALSE},
3830             {"zip",S_OK,FALSE},
3831             {":",S_OK,FALSE},
3832             {"",S_FALSE,FALSE}
3833         },
3834         {
3835             {Uri_HOST_DNS,S_OK,FALSE},
3836             {0,S_FALSE,FALSE},
3837             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
3838             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3839         }
3840     },
3841     {   "about:blank", 0, S_OK, FALSE,
3842         {
3843             {"about:blank",S_OK,FALSE},
3844             {"",S_FALSE,FALSE},
3845             {"about:blank",S_OK,FALSE},
3846             {"",S_FALSE,FALSE},
3847             {"",S_FALSE,FALSE},
3848             {"",S_FALSE,FALSE},
3849             {"",S_FALSE,FALSE},
3850             {"",S_FALSE,FALSE},
3851             {"blank",S_OK,FALSE},
3852             {"blank",S_OK,FALSE},
3853             {"",S_FALSE,FALSE},
3854             {"about:blank",S_OK,FALSE},
3855             {"about",S_OK,FALSE},
3856             {"",S_FALSE,FALSE},
3857             {"",S_FALSE,FALSE}
3858         },
3859         {
3860             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3861             {0,S_FALSE,FALSE},
3862             {URL_SCHEME_ABOUT,S_OK,FALSE},
3863             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3864         }
3865     },
3866     {   "mk:@MSITStore:C:\\Program Files/AutoCAD 2008\\Help/acad_acg.chm::/WSfacf1429558a55de1a7524c1004e616f8b-322b.htm",0,S_OK,FALSE,
3867         {
3868             {"mk:@MSITStore:C:\\Program%20Files/AutoCAD%202008\\Help/acad_acg.chm::/WSfacf1429558a55de1a7524c1004e616f8b-322b.htm",S_OK,FALSE},
3869             {"",S_FALSE,FALSE},
3870             {"mk:@MSITStore:C:\\Program%20Files/AutoCAD%202008\\Help/acad_acg.chm::/WSfacf1429558a55de1a7524c1004e616f8b-322b.htm",S_OK,FALSE},
3871             {"",S_FALSE,FALSE},
3872             {".htm",S_OK,FALSE},
3873             {"",S_FALSE,FALSE},
3874             {"",S_FALSE,FALSE},
3875             {"",S_FALSE,FALSE},
3876             {"@MSITStore:C:\\Program%20Files/AutoCAD%202008\\Help/acad_acg.chm::/WSfacf1429558a55de1a7524c1004e616f8b-322b.htm",S_OK,FALSE},
3877             {"@MSITStore:C:\\Program%20Files/AutoCAD%202008\\Help/acad_acg.chm::/WSfacf1429558a55de1a7524c1004e616f8b-322b.htm",S_OK,FALSE},
3878             {"",S_FALSE,FALSE},
3879             {"mk:@MSITStore:C:\\Program Files/AutoCAD 2008\\Help/acad_acg.chm::/WSfacf1429558a55de1a7524c1004e616f8b-322b.htm",S_OK,FALSE},
3880             {"mk",S_OK,FALSE},
3881             {"",S_FALSE,FALSE},
3882             {"",S_FALSE,FALSE}
3883         },
3884         {
3885             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3886             {0,S_FALSE,FALSE},
3887             {URL_SCHEME_MK,S_OK,FALSE},
3888             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3889         }
3890     },
3891     {   "mk:@MSITStore:Z:\\home\\test\\chm\\silqhelp.chm::/thesilqquickstartguide.htm",0,S_OK,FALSE,
3892         {
3893             {"mk:@MSITStore:Z:\\home\\test\\chm\\silqhelp.chm::/thesilqquickstartguide.htm",S_OK,FALSE},
3894             {"",S_FALSE,FALSE},
3895             {"mk:@MSITStore:Z:\\home\\test\\chm\\silqhelp.chm::/thesilqquickstartguide.htm",S_OK,FALSE},
3896             {"",S_FALSE,FALSE},
3897             {".htm",S_OK,FALSE},
3898             {"",S_FALSE,FALSE},
3899             {"",S_FALSE,FALSE},
3900             {"",S_FALSE,FALSE},
3901             {"@MSITStore:Z:\\home\\test\\chm\\silqhelp.chm::/thesilqquickstartguide.htm",S_OK,FALSE},
3902             {"@MSITStore:Z:\\home\\test\\chm\\silqhelp.chm::/thesilqquickstartguide.htm",S_OK,FALSE},
3903             {"",S_FALSE,FALSE},
3904             {"mk:@MSITStore:Z:\\home\\test\\chm\\silqhelp.chm::/thesilqquickstartguide.htm",S_OK,FALSE},
3905             {"mk",S_OK,FALSE},
3906             {"",S_FALSE,FALSE},
3907             {"",S_FALSE,FALSE}
3908         },
3909         {
3910             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3911             {0,S_FALSE,FALSE},
3912             {URL_SCHEME_MK,S_OK,FALSE},
3913             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3914         }
3915     },
3916     /* Two '\' are added to the URI when USE_DOS_PATH is set, and it's a UNC path. */
3917     {   "file://server/dir/index.html", Uri_CREATE_FILE_USE_DOS_PATH, S_OK, FALSE,
3918         {
3919             {"file://\\\\server\\dir\\index.html",S_OK,FALSE},
3920             {"server",S_OK,FALSE},
3921             {"file://\\\\server\\dir\\index.html",S_OK,FALSE},
3922             {"",S_FALSE,FALSE},
3923             {".html",S_OK,FALSE},
3924             {"",S_FALSE,FALSE},
3925             {"server",S_OK,FALSE},
3926             {"",S_FALSE,FALSE},
3927             {"\\dir\\index.html",S_OK,FALSE},
3928             {"\\dir\\index.html",S_OK,FALSE},
3929             {"",S_FALSE,FALSE},
3930             {"file://server/dir/index.html",S_OK,FALSE},
3931             {"file",S_OK,FALSE},
3932             {"",S_FALSE,FALSE},
3933             {"",S_FALSE,FALSE}
3934         },
3935         {
3936             {Uri_HOST_DNS,S_OK,FALSE},
3937             {0,S_FALSE,FALSE},
3938             {URL_SCHEME_FILE,S_OK,FALSE},
3939             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3940         }
3941     },
3942     /* When CreateUri generates an IUri, it still displays the default port in the
3943      * authority.
3944      */
3945     {   "http://google.com:80/", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
3946         {
3947             {"http://google.com:80/",S_OK,FALSE},
3948             {"google.com:80",S_OK,FALSE},
3949             {"http://google.com:80/",S_OK,FALSE},
3950             {"google.com",S_OK,FALSE},
3951             {"",S_FALSE,FALSE},
3952             {"",S_FALSE,FALSE},
3953             {"google.com",S_OK,FALSE},
3954             {"",S_FALSE,FALSE},
3955             {"/",S_OK,FALSE},
3956             {"/",S_OK,FALSE},
3957             {"",S_FALSE,FALSE},
3958             {"http://google.com:80/",S_OK,FALSE},
3959             {"http",S_OK,FALSE},
3960             {"",S_FALSE,FALSE},
3961             {"",S_FALSE,FALSE}
3962         },
3963         {
3964             {Uri_HOST_DNS,S_OK,FALSE},
3965             {80,S_OK,FALSE},
3966             {URL_SCHEME_HTTP,S_OK,FALSE},
3967             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3968         }
3969     },
3970     /* For res URIs the host is everything up until the first '/'. */
3971     {   "res://C:\\dir\\file.exe/DATA/test.html", 0, S_OK, FALSE,
3972         {
3973             {"res://C:\\dir\\file.exe/DATA/test.html",S_OK,FALSE},
3974             {"C:\\dir\\file.exe",S_OK,FALSE},
3975             {"res://C:\\dir\\file.exe/DATA/test.html",S_OK,FALSE},
3976             {"",S_FALSE,FALSE},
3977             {".html",S_OK,FALSE},
3978             {"",S_FALSE,FALSE},
3979             {"C:\\dir\\file.exe",S_OK,FALSE},
3980             {"",S_FALSE,FALSE},
3981             {"/DATA/test.html",S_OK,FALSE},
3982             {"/DATA/test.html",S_OK,FALSE},
3983             {"",S_FALSE,FALSE},
3984             {"res://C:\\dir\\file.exe/DATA/test.html",S_OK,FALSE},
3985             {"res",S_OK,FALSE},
3986             {"",S_FALSE,FALSE},
3987             {"",S_FALSE,FALSE}
3988         },
3989         {
3990             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3991             {0,S_FALSE,FALSE},
3992             {URL_SCHEME_RES,S_OK,FALSE},
3993             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3994         }
3995     },
3996     /* Res URI can contain a '|' in the host name. */
3997     {   "res://c:\\di|r\\file.exe/test", 0, S_OK, FALSE,
3998         {
3999             {"res://c:\\di|r\\file.exe/test",S_OK,FALSE},
4000             {"c:\\di|r\\file.exe",S_OK,FALSE},
4001             {"res://c:\\di|r\\file.exe/test",S_OK,FALSE},
4002             {"",S_FALSE,FALSE},
4003             {"",S_FALSE,FALSE},
4004             {"",S_FALSE,FALSE},
4005             {"c:\\di|r\\file.exe",S_OK,FALSE},
4006             {"",S_FALSE,FALSE},
4007             {"/test",S_OK,FALSE},
4008             {"/test",S_OK,FALSE},
4009             {"",S_FALSE,FALSE},
4010             {"res://c:\\di|r\\file.exe/test",S_OK,FALSE},
4011             {"res",S_OK,FALSE},
4012             {"",S_FALSE,FALSE},
4013             {"",S_FALSE,FALSE}
4014         },
4015         {
4016             {Uri_HOST_UNKNOWN,S_OK,FALSE},
4017             {0,S_FALSE,FALSE},
4018             {URL_SCHEME_RES,S_OK,FALSE},
4019             {URLZONE_INVALID,E_NOTIMPL,FALSE},
4020         }
4021     },
4022     /* Res URIs can have invalid percent encoded values. */
4023     {   "res://c:\\dir%xx\\file.exe/test", 0, S_OK, FALSE,
4024         {
4025             {"res://c:\\dir%xx\\file.exe/test",S_OK,FALSE},
4026             {"c:\\dir%xx\\file.exe",S_OK,FALSE},
4027             {"res://c:\\dir%xx\\file.exe/test",S_OK,FALSE},
4028             {"",S_FALSE,FALSE},
4029             {"",S_FALSE,FALSE},
4030             {"",S_FALSE,FALSE},
4031             {"c:\\dir%xx\\file.exe",S_OK,FALSE},
4032             {"",S_FALSE,FALSE},
4033             {"/test",S_OK,FALSE},
4034             {"/test",S_OK,FALSE},
4035             {"",S_FALSE,FALSE},
4036             {"res://c:\\dir%xx\\file.exe/test",S_OK,FALSE},
4037             {"res",S_OK,FALSE},
4038             {"",S_FALSE,FALSE},
4039             {"",S_FALSE,FALSE}
4040         },
4041         {
4042             {Uri_HOST_UNKNOWN,S_OK,FALSE},
4043             {0,S_FALSE,FALSE},
4044             {URL_SCHEME_RES,S_OK,FALSE},
4045             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4046         }
4047     },
4048     /* Res doesn't get forbidden characters percent encoded in it's path. */
4049     {   "res://c:\\test/tes<|>t", 0, S_OK, FALSE,
4050         {
4051             {"res://c:\\test/tes<|>t",S_OK,FALSE},
4052             {"c:\\test",S_OK,FALSE},
4053             {"res://c:\\test/tes<|>t",S_OK,FALSE},
4054             {"",S_FALSE,FALSE},
4055             {"",S_FALSE,FALSE},
4056             {"",S_FALSE,FALSE},
4057             {"c:\\test",S_OK,FALSE},
4058             {"",S_FALSE,FALSE},
4059             {"/tes<|>t",S_OK,FALSE},
4060             {"/tes<|>t",S_OK,FALSE},
4061             {"",S_FALSE,FALSE},
4062             {"res://c:\\test/tes<|>t",S_OK,FALSE},
4063             {"res",S_OK,FALSE},
4064             {"",S_FALSE,FALSE},
4065             {"",S_FALSE,FALSE}
4066         },
4067         {
4068             {Uri_HOST_UNKNOWN,S_OK,FALSE},
4069             {0,S_FALSE,FALSE},
4070             {URL_SCHEME_RES,S_OK,FALSE},
4071             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4072         }
4073     },
4074     {   "mk:@MSITStore:Z:\\dir\\test.chm::/html/../images/xxx.jpg", 0, S_OK, FALSE,
4075         {
4076             {"mk:@MSITStore:Z:\\dir\\test.chm::/images/xxx.jpg",S_OK,FALSE},
4077             {"",S_FALSE,FALSE},
4078             {"mk:@MSITStore:Z:\\dir\\test.chm::/images/xxx.jpg",S_OK,FALSE},
4079             {"",S_FALSE,FALSE},
4080             {".jpg",S_OK,FALSE},
4081             {"",S_FALSE,FALSE},
4082             {"",S_FALSE,FALSE},
4083             {"",S_FALSE,FALSE},
4084             {"@MSITStore:Z:\\dir\\test.chm::/images/xxx.jpg",S_OK,FALSE},
4085             {"@MSITStore:Z:\\dir\\test.chm::/images/xxx.jpg",S_OK,FALSE},
4086             {"",S_FALSE,FALSE},
4087             {"mk:@MSITStore:Z:\\dir\\test.chm::/html/../images/xxx.jpg",S_OK,FALSE},
4088             {"mk",S_OK,FALSE},
4089             {"",S_FALSE,FALSE},
4090             {"",S_FALSE,FALSE}
4091         },
4092         {
4093             {Uri_HOST_UNKNOWN,S_OK,FALSE},
4094             {0,S_FALSE,FALSE},
4095             {URL_SCHEME_MK,S_OK,FALSE},
4096             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4097         }
4098     },
4099     {   "mk:@MSITStore:Z:\\dir\\test.chm::/html/../images/xxx.jpg", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
4100         {
4101             {"mk:@MSITStore:Z:\\dir\\test.chm::/html/../images/xxx.jpg",S_OK,FALSE},
4102             {"",S_FALSE,FALSE},
4103             {"mk:@MSITStore:Z:\\dir\\test.chm::/html/../images/xxx.jpg",S_OK,FALSE},
4104             {"",S_FALSE,FALSE},
4105             {".jpg",S_OK,FALSE},
4106             {"",S_FALSE,FALSE},
4107             {"",S_FALSE,FALSE},
4108             {"",S_FALSE,FALSE},
4109             {"@MSITStore:Z:\\dir\\test.chm::/html/../images/xxx.jpg",S_OK,FALSE},
4110             {"@MSITStore:Z:\\dir\\test.chm::/html/../images/xxx.jpg",S_OK,FALSE},
4111             {"",S_FALSE,FALSE},
4112             {"mk:@MSITStore:Z:\\dir\\test.chm::/html/../images/xxx.jpg",S_OK,FALSE},
4113             {"mk",S_OK,FALSE},
4114             {"",S_FALSE,FALSE},
4115             {"",S_FALSE,FALSE}
4116         },
4117         {
4118             {Uri_HOST_UNKNOWN,S_OK,FALSE},
4119             {0,S_FALSE,FALSE},
4120             {URL_SCHEME_MK,S_OK,FALSE},
4121             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4122         }
4123     },
4124     {   "xx:@MSITStore:Z:\\dir\\test.chm::/html/../images/xxx.jpg", 0, S_OK, FALSE,
4125         {
4126             {"xx:@MSITStore:Z:\\dir\\test.chm::/html/../images/xxx.jpg",S_OK,FALSE},
4127             {"",S_FALSE,FALSE},
4128             {"xx:@MSITStore:Z:\\dir\\test.chm::/html/../images/xxx.jpg",S_OK,FALSE},
4129             {"",S_FALSE,FALSE},
4130             {".jpg",S_OK,FALSE},
4131             {"",S_FALSE,FALSE},
4132             {"",S_FALSE,FALSE},
4133             {"",S_FALSE,FALSE},
4134             {"@MSITStore:Z:\\dir\\test.chm::/html/../images/xxx.jpg",S_OK,FALSE},
4135             {"@MSITStore:Z:\\dir\\test.chm::/html/../images/xxx.jpg",S_OK,FALSE},
4136             {"",S_FALSE,FALSE},
4137             {"xx:@MSITStore:Z:\\dir\\test.chm::/html/../images/xxx.jpg",S_OK,FALSE},
4138             {"xx",S_OK,FALSE},
4139             {"",S_FALSE,FALSE},
4140             {"",S_FALSE,FALSE}
4141         },
4142         {
4143             {Uri_HOST_UNKNOWN,S_OK,FALSE},
4144             {0,S_FALSE,FALSE},
4145             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
4146             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4147         }
4148     },
4149     {   "mk:@MSITStore:Z:\\dir\\test.chm::/html/../../images/xxx.jpg", 0, S_OK, FALSE,
4150         {
4151             {"mk:@MSITStore:Z:\\dir\\images/xxx.jpg",S_OK,FALSE},
4152             {"",S_FALSE,FALSE},
4153             {"mk:@MSITStore:Z:\\dir\\images/xxx.jpg",S_OK,FALSE},
4154             {"",S_FALSE,FALSE},
4155             {".jpg",S_OK,FALSE},
4156             {"",S_FALSE,FALSE},
4157             {"",S_FALSE,FALSE},
4158             {"",S_FALSE,FALSE},
4159             {"@MSITStore:Z:\\dir\\images/xxx.jpg",S_OK,FALSE},
4160             {"@MSITStore:Z:\\dir\\images/xxx.jpg",S_OK,FALSE},
4161             {"",S_FALSE,FALSE},
4162             {"mk:@MSITStore:Z:\\dir\\test.chm::/html/../../images/xxx.jpg",S_OK,FALSE},
4163             {"mk",S_OK,FALSE},
4164             {"",S_FALSE,FALSE},
4165             {"",S_FALSE,FALSE}
4166         },
4167         {
4168             {Uri_HOST_UNKNOWN,S_OK,FALSE},
4169             {0,S_FALSE,FALSE},
4170             {URL_SCHEME_MK,S_OK,FALSE},
4171             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4172         }
4173     },
4174     {   "mk:@MSITStore:Z:\\dir\\dir2\\..\\test.chm::/html/../../images/xxx.jpg", 0, S_OK, FALSE,
4175         {
4176             {"mk:@MSITStore:Z:\\dir\\images/xxx.jpg",S_OK,FALSE},
4177             {"",S_FALSE,FALSE},
4178             {"mk:@MSITStore:Z:\\dir\\images/xxx.jpg",S_OK,FALSE},
4179             {"",S_FALSE,FALSE},
4180             {".jpg",S_OK,FALSE},
4181             {"",S_FALSE,FALSE},
4182             {"",S_FALSE,FALSE},
4183             {"",S_FALSE,FALSE},
4184             {"@MSITStore:Z:\\dir\\images/xxx.jpg",S_OK,FALSE},
4185             {"@MSITStore:Z:\\dir\\images/xxx.jpg",S_OK,FALSE},
4186             {"",S_FALSE,FALSE},
4187             {"mk:@MSITStore:Z:\\dir\\dir2\\..\\test.chm::/html/../../images/xxx.jpg",S_OK,FALSE},
4188             {"mk",S_OK,FALSE},
4189             {"",S_FALSE,FALSE},
4190             {"",S_FALSE,FALSE}
4191         },
4192         {
4193             {Uri_HOST_UNKNOWN,S_OK,FALSE},
4194             {0,S_FALSE,FALSE},
4195             {URL_SCHEME_MK,S_OK,FALSE},
4196             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4197         }
4198     },
4199     {   "mk:@MSITStore:Z:\\dir\\test.chm::/html/../../../../images/xxx.jpg", 0, S_OK, FALSE,
4200         {
4201             {"mk:images/xxx.jpg",S_OK,FALSE},
4202             {"",S_FALSE,FALSE},
4203             {"mk:images/xxx.jpg",S_OK,FALSE},
4204             {"",S_FALSE,FALSE},
4205             {".jpg",S_OK,FALSE},
4206             {"",S_FALSE,FALSE},
4207             {"",S_FALSE,FALSE},
4208             {"",S_FALSE,FALSE},
4209             {"images/xxx.jpg",S_OK,FALSE},
4210             {"images/xxx.jpg",S_OK,FALSE},
4211             {"",S_FALSE,FALSE},
4212             {"mk:@MSITStore:Z:\\dir\\test.chm::/html/../../../../images/xxx.jpg",S_OK,FALSE},
4213             {"mk",S_OK,FALSE},
4214             {"",S_FALSE,FALSE},
4215             {"",S_FALSE,FALSE}
4216         },
4217         {
4218             {Uri_HOST_UNKNOWN,S_OK,FALSE},
4219             {0,S_FALSE,FALSE},
4220             {URL_SCHEME_MK,S_OK,FALSE},
4221             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4222         }
4223     },
4224     {   "", Uri_CREATE_ALLOW_RELATIVE, S_OK, FALSE,
4225         {
4226             {"",S_OK,FALSE},
4227             {"",S_FALSE,FALSE},
4228             {"",S_OK,FALSE},
4229             {"",S_FALSE,FALSE},
4230             {"",S_FALSE,FALSE},
4231             {"",S_FALSE,FALSE},
4232             {"",S_FALSE,FALSE},
4233             {"",S_FALSE,FALSE},
4234             {"",S_OK,FALSE},
4235             {"",S_OK,FALSE},
4236             {"",S_FALSE,FALSE},
4237             {"",S_OK,FALSE},
4238             {"",S_FALSE,FALSE},
4239             {"",S_FALSE,FALSE},
4240             {"",S_FALSE,FALSE}
4241         },
4242         {
4243             {Uri_HOST_UNKNOWN,S_OK,FALSE},
4244             {0,S_FALSE,FALSE},
4245             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
4246             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4247         }
4248     },
4249     {   " \t ", Uri_CREATE_ALLOW_RELATIVE, S_OK, FALSE,
4250         {
4251             {"",S_OK,FALSE},
4252             {"",S_FALSE,FALSE},
4253             {"",S_OK,FALSE},
4254             {"",S_FALSE,FALSE},
4255             {"",S_FALSE,FALSE},
4256             {"",S_FALSE,FALSE},
4257             {"",S_FALSE,FALSE},
4258             {"",S_FALSE,FALSE},
4259             {"",S_OK,FALSE},
4260             {"",S_OK,FALSE},
4261             {"",S_FALSE,FALSE},
4262             {"",S_OK,FALSE},
4263             {"",S_FALSE,FALSE},
4264             {"",S_FALSE,FALSE},
4265             {"",S_FALSE,FALSE}
4266         },
4267         {
4268             {Uri_HOST_UNKNOWN,S_OK,FALSE},
4269             {0,S_FALSE,FALSE},
4270             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
4271             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4272         }
4273     },
4274     {   "javascript:void", 0, S_OK, FALSE,
4275         {
4276             {"javascript:void",S_OK},
4277             {"",S_FALSE},
4278             {"javascript:void",S_OK},
4279             {"",S_FALSE},
4280             {"",S_FALSE},
4281             {"",S_FALSE},
4282             {"",S_FALSE},
4283             {"",S_FALSE},
4284             {"void",S_OK},
4285             {"void",S_OK},
4286             {"",S_FALSE},
4287             {"javascript:void",S_OK},
4288             {"javascript",S_OK},
4289             {"",S_FALSE},
4290             {"",S_FALSE}
4291         },
4292         {
4293             {Uri_HOST_UNKNOWN,S_OK},
4294             {0,S_FALSE},
4295             {URL_SCHEME_JAVASCRIPT,S_OK},
4296             {URLZONE_INVALID,E_NOTIMPL}
4297         }
4298     },
4299     {   "javascript://undefined", 0, S_OK, FALSE,
4300         {
4301             {"javascript://undefined",S_OK},
4302             {"",S_FALSE},
4303             {"javascript://undefined",S_OK},
4304             {"",S_FALSE},
4305             {"",S_FALSE},
4306             {"",S_FALSE},
4307             {"",S_FALSE},
4308             {"",S_FALSE},
4309             {"//undefined",S_OK},
4310             {"//undefined",S_OK},
4311             {"",S_FALSE},
4312             {"javascript://undefined",S_OK},
4313             {"javascript",S_OK},
4314             {"",S_FALSE},
4315             {"",S_FALSE}
4316         },
4317         {
4318             {Uri_HOST_UNKNOWN,S_OK},
4319             {0,S_FALSE},
4320             {URL_SCHEME_JAVASCRIPT,S_OK},
4321             {URLZONE_INVALID,E_NOTIMPL}
4322         }
4323     },
4324     {   "JavaSCript:escape('/\\?#?')", 0, S_OK, FALSE,
4325         {
4326             {"javascript:escape('/\\?#?')",S_OK},
4327             {"",S_FALSE},
4328             {"javascript:escape('/\\?#?')",S_OK},
4329             {"",S_FALSE},
4330             {"",S_FALSE},
4331             {"",S_FALSE},
4332             {"",S_FALSE},
4333             {"",S_FALSE},
4334             {"escape('/\\?#?')",S_OK},
4335             {"escape('/\\?#?')",S_OK},
4336             {"",S_FALSE},
4337             {"JavaSCript:escape('/\\?#?')",S_OK},
4338             {"javascript",S_OK},
4339             {"",S_FALSE},
4340             {"",S_FALSE}
4341         },
4342         {
4343             {Uri_HOST_UNKNOWN,S_OK},
4344             {0,S_FALSE},
4345             {URL_SCHEME_JAVASCRIPT,S_OK},
4346             {URLZONE_INVALID,E_NOTIMPL}
4347         }
4348     },
4349     {   "*://google.com", 0, S_OK, FALSE,
4350         {
4351             {"*:google.com/",S_OK,FALSE},
4352             {"google.com",S_OK},
4353             {"*:google.com/",S_OK,FALSE},
4354             {"google.com",S_OK,FALSE},
4355             {"",S_FALSE,FALSE},
4356             {"",S_FALSE,FALSE},
4357             {"google.com",S_OK,FALSE},
4358             {"",S_FALSE,FALSE},
4359             {"/",S_OK,FALSE},
4360             {"/",S_OK,FALSE},
4361             {"",S_FALSE,FALSE},
4362             {"*://google.com",S_OK,FALSE},
4363             {"*",S_OK,FALSE},
4364             {"",S_FALSE,FALSE},
4365             {"",S_FALSE,FALSE}
4366         },
4367         {
4368             {Uri_HOST_DNS,S_OK,FALSE},
4369             {0,S_FALSE,FALSE},
4370             {URL_SCHEME_WILDCARD,S_OK,FALSE},
4371             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4372         }
4373     },
4374     {   "mk:@MSITSTORE:C:\\Some\\Bogus\\Path.chm::/subdir/file.txt",0,S_OK,FALSE,
4375         {
4376             {"mk:@MSITSTORE:C:\\Some\\Bogus\\Path.chm::/subdir/file.txt",S_OK},
4377             {"",S_FALSE},
4378             {"mk:@MSITSTORE:C:\\Some\\Bogus\\Path.chm::/subdir/file.txt",S_OK},
4379             {"",S_FALSE},
4380             {".txt",S_OK},
4381             {"",S_FALSE},
4382             {"",S_FALSE},
4383             {"",S_FALSE},
4384             {"@MSITSTORE:C:\\Some\\Bogus\\Path.chm::/subdir/file.txt",S_OK},
4385             {"@MSITSTORE:C:\\Some\\Bogus\\Path.chm::/subdir/file.txt",S_OK},
4386             {"",S_FALSE},
4387             {"mk:@MSITSTORE:C:\\Some\\Bogus\\Path.chm::/subdir/file.txt",S_OK},
4388             {"mk",S_OK},
4389             {"",S_FALSE},
4390             {"",S_FALSE}
4391         },
4392         {
4393             {Uri_HOST_UNKNOWN,S_OK},
4394             {0,S_FALSE},
4395             {URL_SCHEME_MK,S_OK},
4396             {URLZONE_INVALID,E_NOTIMPL}
4397         }
4398     },
4399     {   "gopher://test.winehq.org:151/file.txt",0,S_OK,FALSE,
4400         {
4401             {"gopher://test.winehq.org:151/file.txt",S_OK},
4402             {"test.winehq.org:151",S_OK},
4403             {"gopher://test.winehq.org:151/file.txt",S_OK},
4404             {"winehq.org",S_OK},
4405             {".txt",S_OK},
4406             {"",S_FALSE},
4407             {"test.winehq.org",S_OK},
4408             {"",S_FALSE},
4409             {"/file.txt",S_OK},
4410             {"/file.txt",S_OK},
4411             {"",S_FALSE},
4412             {"gopher://test.winehq.org:151/file.txt",S_OK},
4413             {"gopher",S_OK},
4414             {"",S_FALSE},
4415             {"",S_FALSE}
4416         },
4417         {
4418             {Uri_HOST_DNS,S_OK},
4419             {151,S_OK},
4420             {URL_SCHEME_GOPHER,S_OK},
4421             {URLZONE_INVALID,E_NOTIMPL}
4422         }
4423     },
4424 };
4425
4426 typedef struct _invalid_uri {
4427     const char* uri;
4428     DWORD       flags;
4429     BOOL        todo;
4430 } invalid_uri;
4431
4432 static const invalid_uri invalid_uri_tests[] = {
4433     /* Has to have a scheme name. */
4434     {"://www.winehq.org",0,FALSE},
4435     /* Window's doesn't like URI's which are implicitly file paths without the
4436      * ALLOW_IMPLICIT_FILE_SCHEME flag set.
4437      */
4438     {"C:/test/test.mp3",0,FALSE},
4439     {"\\\\Server/test/test.mp3",0,FALSE},
4440     {"C:/test/test.mp3",Uri_CREATE_ALLOW_IMPLICIT_WILDCARD_SCHEME,FALSE},
4441     {"\\\\Server/test/test.mp3",Uri_CREATE_ALLOW_RELATIVE,FALSE},
4442     /* Invalid schemes. */
4443     {"*abcd://not.valid.com",0,FALSE},
4444     {"*a*b*c*d://not.valid.com",0,FALSE},
4445     /* Not allowed to have invalid % encoded data. */
4446     {"ftp://google.co%XX/",0,FALSE},
4447     /* To many h16 components. */
4448     {"http://[1:2:3:4:5:6:7:8:9]",0,FALSE},
4449     /* Not enough room for IPv4 address. */
4450     {"http://[1:2:3:4:5:6:7:192.0.1.0]",0,FALSE},
4451     /* Not enough h16 components. */
4452     {"http://[1:2:3:4]",0,FALSE},
4453     /* Not enough components including IPv4. */
4454     {"http://[1:192.0.1.0]",0,FALSE},
4455     /* Not allowed to have partial IPv4 in IPv6. */
4456     {"http://[::192.0]",0,FALSE},
4457     /* Can't have elision of 1 h16 at beginning of address. */
4458     {"http://[::2:3:4:5:6:7:8]",0,FALSE},
4459     /* Can't have elision of 1 h16 at end of address. */
4460     {"http://[1:2:3:4:5:6:7::]",0,FALSE},
4461     /* Expects a valid IP Literal. */
4462     {"ftp://[not.valid.uri]/",0,FALSE},
4463     /* Expects valid port for a known scheme type. */
4464     {"ftp://www.winehq.org:123fgh",0,FALSE},
4465     /* Port exceeds USHORT_MAX for known scheme type. */
4466     {"ftp://www.winehq.org:65536",0,FALSE},
4467     /* Invalid port with IPv4 address. */
4468     {"http://www.winehq.org:1abcd",0,FALSE},
4469     /* Invalid port with IPv6 address. */
4470     {"http://[::ffff]:32xy",0,FALSE},
4471     /* Not allowed to have backslashes with NO_CANONICALIZE. */
4472     {"gopher://www.google.com\\test",Uri_CREATE_NO_CANONICALIZE,FALSE},
4473     /* Not allowed to have invalid % encoded data in opaque URI path. */
4474     {"news:test%XX",0,FALSE},
4475     {"mailto:wine@winehq%G8.com",0,FALSE},
4476     /* Known scheme types can't have invalid % encoded data in query string. */
4477     {"http://google.com/?query=te%xx",0,FALSE},
4478     /* Invalid % encoded data in fragment of know scheme type. */
4479     {"ftp://google.com/#Test%xx",0,FALSE},
4480     {"  http://google.com/",Uri_CREATE_NO_PRE_PROCESS_HTML_URI,FALSE},
4481     {"\n\nhttp://google.com/",Uri_CREATE_NO_PRE_PROCESS_HTML_URI,FALSE},
4482     {"file://c:\\test<test",Uri_CREATE_FILE_USE_DOS_PATH,FALSE},
4483     {"file://c:\\test>test",Uri_CREATE_FILE_USE_DOS_PATH,FALSE},
4484     {"file://c:\\test\"test",Uri_CREATE_FILE_USE_DOS_PATH,FALSE},
4485     {"file:c:\\test<test",Uri_CREATE_FILE_USE_DOS_PATH,FALSE},
4486     {"file:c:\\test>test",Uri_CREATE_FILE_USE_DOS_PATH,FALSE},
4487     {"file:c:\\test\"test",Uri_CREATE_FILE_USE_DOS_PATH,FALSE},
4488     /* res URIs aren't allowed to have forbidden dos path characters in the
4489      * hostname.
4490      */
4491     {"res://c:\\te<st\\test/test",0,FALSE},
4492     {"res://c:\\te>st\\test/test",0,FALSE},
4493     {"res://c:\\te\"st\\test/test",0,FALSE},
4494     {"res://c:\\test/te%xxst",0,FALSE}
4495 };
4496
4497 typedef struct _uri_equality {
4498     const char* a;
4499     DWORD       create_flags_a;
4500     const char* b;
4501     DWORD       create_flags_b;
4502     BOOL        equal;
4503     BOOL        todo;
4504 } uri_equality;
4505
4506 static const uri_equality equality_tests[] = {
4507     {
4508         "HTTP://www.winehq.org/test dir/./",0,
4509         "http://www.winehq.org/test dir/../test dir/",0,
4510         TRUE
4511     },
4512     {
4513         /* http://www.winehq.org/test%20dir */
4514         "http://%77%77%77%2E%77%69%6E%65%68%71%2E%6F%72%67/%74%65%73%74%20%64%69%72",0,
4515         "http://www.winehq.org/test dir",0,
4516         TRUE
4517     },
4518     {
4519         "c:\\test.mp3",Uri_CREATE_ALLOW_IMPLICIT_FILE_SCHEME,
4520         "file:///c:/test.mp3",0,
4521         TRUE
4522     },
4523     {
4524         "ftp://ftp.winehq.org/",0,
4525         "ftp://ftp.winehq.org",0,
4526         TRUE
4527     },
4528     {
4529         "ftp://ftp.winehq.org/test/test2/../../testB/",0,
4530         "ftp://ftp.winehq.org/t%45stB/",0,
4531         FALSE
4532     },
4533     {
4534         "http://google.com/TEST",0,
4535         "http://google.com/test",0,
4536         FALSE
4537     },
4538     {
4539         "http://GOOGLE.com/",0,
4540         "http://google.com/",0,
4541         TRUE
4542     },
4543     /* Performs case insensitive compare of host names (for known scheme types). */
4544     {
4545         "ftp://GOOGLE.com/",Uri_CREATE_NO_CANONICALIZE,
4546         "ftp://google.com/",0,
4547         TRUE
4548     },
4549     {
4550         "zip://GOOGLE.com/",0,
4551         "zip://google.com/",0,
4552         FALSE
4553     },
4554     {
4555         "file:///c:/TEST/TeST/",0,
4556         "file:///c:/test/test/",0,
4557         TRUE
4558     },
4559     {
4560         "file:///server/TEST",0,
4561         "file:///SERVER/TEST",0,
4562         TRUE
4563     },
4564     {
4565         "http://google.com",Uri_CREATE_NO_CANONICALIZE,
4566         "http://google.com/",0,
4567         TRUE
4568     },
4569     {
4570         "ftp://google.com:21/",0,
4571         "ftp://google.com/",0,
4572         TRUE
4573     },
4574     {
4575         "http://google.com:80/",Uri_CREATE_NO_CANONICALIZE,
4576         "http://google.com/",0,
4577         TRUE
4578     },
4579     {
4580         "http://google.com:70/",0,
4581         "http://google.com:71/",0,
4582         FALSE
4583     },
4584     {
4585         "file:///c:/dir/file.txt", 0,
4586         "file:///c:/dir/file.txt", Uri_CREATE_FILE_USE_DOS_PATH,
4587         TRUE
4588     },
4589     {
4590         "file:///c:/dir/file.txt", 0,
4591         "file:///c:\\dir\\file.txt", Uri_CREATE_NO_CANONICALIZE,
4592         TRUE
4593     },
4594     {
4595         "file:///c:/dir/file.txt", 0,
4596         "file:///c:\\dir2\\..\\dir\\file.txt", Uri_CREATE_NO_CANONICALIZE,
4597         TRUE
4598     },
4599     {
4600         "file:///c:\\dir2\\..\\ dir\\file.txt", Uri_CREATE_NO_CANONICALIZE,
4601         "file:///c:/%20dir/file.txt", 0,
4602         TRUE
4603     },
4604     {
4605         "file:///c:/Dir/file.txt", 0,
4606         "file:///C:/dir/file.TXT", Uri_CREATE_FILE_USE_DOS_PATH,
4607         TRUE
4608     },
4609     {
4610         "file:///c:/dir/file.txt", 0,
4611         "file:///c:\\dir\\file.txt", Uri_CREATE_FILE_USE_DOS_PATH,
4612         TRUE
4613     },
4614     {
4615         "file:///c:/dir/file.txt#a", 0,
4616         "file:///c:\\dir\\file.txt#b", Uri_CREATE_FILE_USE_DOS_PATH,
4617         FALSE
4618     }
4619 };
4620
4621 typedef struct _uri_with_fragment {
4622     const char* uri;
4623     const char* fragment;
4624     DWORD       create_flags;
4625     HRESULT     create_expected;
4626     BOOL        create_todo;
4627
4628     const char* expected_uri;
4629     BOOL        expected_todo;
4630 } uri_with_fragment;
4631
4632 static const uri_with_fragment uri_fragment_tests[] = {
4633     {
4634         "http://google.com/","#fragment",0,S_OK,FALSE,
4635         "http://google.com/#fragment",FALSE
4636     },
4637     {
4638         "http://google.com/","fragment",0,S_OK,FALSE,
4639         "http://google.com/#fragment",FALSE
4640     },
4641     {
4642         "zip://test.com/","?test",0,S_OK,FALSE,
4643         "zip://test.com/#?test",FALSE
4644     },
4645     /* The fragment can be empty. */
4646     {
4647         "ftp://ftp.google.com/","",0,S_OK,FALSE,
4648         "ftp://ftp.google.com/#",FALSE
4649     }
4650 };
4651
4652 typedef struct _uri_builder_property {
4653     BOOL            change;
4654     const char      *value;
4655     const char      *expected_value;
4656     Uri_PROPERTY    property;
4657     HRESULT         expected;
4658     BOOL            todo;
4659 } uri_builder_property;
4660
4661 typedef struct _uri_builder_port {
4662     BOOL    change;
4663     BOOL    set;
4664     DWORD   value;
4665     HRESULT expected;
4666     BOOL    todo;
4667 } uri_builder_port;
4668
4669 typedef struct _uri_builder_str_property {
4670     const char* expected;
4671     HRESULT     result;
4672     BOOL        todo;
4673 } uri_builder_str_property;
4674
4675 typedef struct _uri_builder_dword_property {
4676     DWORD   expected;
4677     HRESULT result;
4678     BOOL    todo;
4679 } uri_builder_dword_property;
4680
4681 typedef struct _uri_builder_test {
4682     const char                  *uri;
4683     DWORD                       create_flags;
4684     HRESULT                     create_builder_expected;
4685     BOOL                        create_builder_todo;
4686
4687     uri_builder_property        properties[URI_BUILDER_STR_PROPERTY_COUNT];
4688
4689     uri_builder_port            port_prop;
4690
4691     DWORD                       uri_flags;
4692     HRESULT                     uri_hres;
4693     BOOL                        uri_todo;
4694
4695     DWORD                       uri_simple_encode_flags;
4696     HRESULT                     uri_simple_hres;
4697     BOOL                        uri_simple_todo;
4698
4699     DWORD                       uri_with_flags;
4700     DWORD                       uri_with_builder_flags;
4701     DWORD                       uri_with_encode_flags;
4702     HRESULT                     uri_with_hres;
4703     BOOL                        uri_with_todo;
4704
4705     uri_builder_str_property    expected_str_props[URI_STR_PROPERTY_COUNT];
4706     uri_builder_dword_property  expected_dword_props[URI_DWORD_PROPERTY_COUNT];
4707 } uri_builder_test;
4708
4709 static const uri_builder_test uri_builder_tests[] = {
4710     {   "http://google.com/",0,S_OK,FALSE,
4711         {
4712             {TRUE,"#fragment",NULL,Uri_PROPERTY_FRAGMENT,S_OK,FALSE},
4713             {TRUE,"password",NULL,Uri_PROPERTY_PASSWORD,S_OK,FALSE},
4714             {TRUE,"?query=x",NULL,Uri_PROPERTY_QUERY,S_OK,FALSE},
4715             {TRUE,"username",NULL,Uri_PROPERTY_USER_NAME,S_OK,FALSE}
4716         },
4717         {FALSE},
4718         0,S_OK,FALSE,
4719         0,S_OK,FALSE,
4720         0,0,0,S_OK,FALSE,
4721         {
4722             {"http://username:password@google.com/?query=x#fragment",S_OK},
4723             {"username:password@google.com",S_OK},
4724             {"http://google.com/?query=x#fragment",S_OK},
4725             {"google.com",S_OK},
4726             {"",S_FALSE},
4727             {"#fragment",S_OK},
4728             {"google.com",S_OK},
4729             {"password",S_OK},
4730             {"/",S_OK},
4731             {"/?query=x",S_OK},
4732             {"?query=x",S_OK},
4733             {"http://username:password@google.com/?query=x#fragment",S_OK},
4734             {"http",S_OK},
4735             {"username:password",S_OK},
4736             {"username",S_OK}
4737         },
4738         {
4739             {Uri_HOST_DNS,S_OK},
4740             {80,S_OK},
4741             {URL_SCHEME_HTTP,S_OK},
4742             {URLZONE_INVALID,E_NOTIMPL}
4743         }
4744     },
4745     {   "http://google.com/",0,S_OK,FALSE,
4746         {
4747             {TRUE,"test",NULL,Uri_PROPERTY_SCHEME_NAME,S_OK,FALSE}
4748         },
4749         {TRUE,TRUE,120,S_OK,FALSE},
4750         0,S_OK,FALSE,
4751         0,S_OK,FALSE,
4752         0,0,0,S_OK,FALSE,
4753         {
4754             {"test://google.com:120/",S_OK},
4755             {"google.com:120",S_OK},
4756             {"test://google.com:120/",S_OK},
4757             {"google.com",S_OK},
4758             {"",S_FALSE},
4759             {"",S_FALSE},
4760             {"google.com",S_OK},
4761             {"",S_FALSE},
4762             {"/",S_OK},
4763             {"/",S_OK},
4764             {"",S_FALSE},
4765             {"test://google.com:120/",S_OK},
4766             {"test",S_OK},
4767             {"",S_FALSE},
4768             {"",S_FALSE}
4769         },
4770         {
4771             {Uri_HOST_DNS,S_OK},
4772             {120,S_OK},
4773             {URL_SCHEME_UNKNOWN,S_OK},
4774             {URLZONE_INVALID,E_NOTIMPL}
4775         }
4776     },
4777     {   "/Test/test dir",Uri_CREATE_ALLOW_RELATIVE,S_OK,FALSE,
4778         {
4779             {TRUE,"http",NULL,Uri_PROPERTY_SCHEME_NAME,S_OK,FALSE},
4780             {TRUE,"::192.2.3.4",NULL,Uri_PROPERTY_HOST,S_OK,FALSE},
4781             {TRUE,NULL,NULL,Uri_PROPERTY_PATH,S_OK,FALSE}
4782         },
4783         {FALSE},
4784         0,S_OK,FALSE,
4785         0,S_OK,FALSE,
4786         0,0,0,S_OK,FALSE,
4787         {
4788             {"http://[::192.2.3.4]/",S_OK},
4789             {"[::192.2.3.4]",S_OK},
4790             {"http://[::192.2.3.4]/",S_OK},
4791             {"",S_FALSE},
4792             {"",S_FALSE},
4793             {"",S_FALSE},
4794             {"::192.2.3.4",S_OK},
4795             {"",S_FALSE},
4796             {"/",S_OK},
4797             {"/",S_OK},
4798             {"",S_FALSE},
4799             {"http://[::192.2.3.4]/",S_OK},
4800             {"http",S_OK},
4801             {"",S_FALSE},
4802             {"",S_FALSE}
4803         },
4804         {
4805             {Uri_HOST_IPV6,S_OK},
4806             {80,S_OK},
4807             {URL_SCHEME_HTTP,S_OK},
4808             {URLZONE_INVALID,E_NOTIMPL}
4809         }
4810     },
4811     {   "http://google.com/",0,S_OK,FALSE,
4812         {
4813             {TRUE,"Frag","#Frag",Uri_PROPERTY_FRAGMENT,S_OK,FALSE}
4814         },
4815         {FALSE},
4816         0,S_OK,FALSE,
4817         0,S_OK,FALSE,
4818         0,0,0,S_OK,FALSE,
4819         {
4820             {"http://google.com/#Frag",S_OK},
4821             {"google.com",S_OK},
4822             {"http://google.com/#Frag",S_OK},
4823             {"google.com",S_OK},
4824             {"",S_FALSE},
4825             {"#Frag",S_OK},
4826             {"google.com",S_OK},
4827             {"",S_FALSE},
4828             {"/",S_OK},
4829             {"/",S_OK},
4830             {"",S_FALSE},
4831             {"http://google.com/#Frag",S_OK},
4832             {"http",S_OK},
4833             {"",S_FALSE},
4834             {"",S_FALSE}
4835         },
4836         {
4837             {Uri_HOST_DNS,S_OK},
4838             {80,S_OK},
4839             {URL_SCHEME_HTTP,S_OK},
4840             {URLZONE_INVALID,E_NOTIMPL}
4841         }
4842     },
4843     {   "http://google.com/",0,S_OK,FALSE,
4844         {
4845             {TRUE,"","#",Uri_PROPERTY_FRAGMENT,S_OK,FALSE},
4846         },
4847         {FALSE},
4848         0,S_OK,FALSE,
4849         0,S_OK,FALSE,
4850         0,0,0,S_OK,FALSE,
4851         {
4852             {"http://google.com/#",S_OK},
4853             {"google.com",S_OK},
4854             {"http://google.com/#",S_OK},
4855             {"google.com",S_OK},
4856             {"",S_FALSE},
4857             {"#",S_OK},
4858             {"google.com",S_OK},
4859             {"",S_FALSE},
4860             {"/",S_OK},
4861             {"/",S_OK},
4862             {"",S_FALSE},
4863             {"http://google.com/#",S_OK},
4864             {"http",S_OK},
4865             {"",S_FALSE},
4866             {"",S_FALSE}
4867         },
4868         {
4869             {Uri_HOST_DNS,S_OK},
4870             {80,S_OK},
4871             {URL_SCHEME_HTTP,S_OK},
4872             {URLZONE_INVALID,E_NOTIMPL}
4873         }
4874     },
4875     {   "http://google.com/",0,S_OK,FALSE,
4876         {
4877             {TRUE,":password",NULL,Uri_PROPERTY_PASSWORD,S_OK,FALSE}
4878         },
4879         {FALSE},
4880         0,S_OK,FALSE,
4881         0,S_OK,FALSE,
4882         0,0,0,S_OK,FALSE,
4883         {
4884             {"http://::password@google.com/",S_OK},
4885             {"::password@google.com",S_OK},
4886             {"http://google.com/",S_OK},
4887             {"google.com",S_OK},
4888             {"",S_FALSE},
4889             {"",S_FALSE},
4890             {"google.com",S_OK},
4891             {":password",S_OK},
4892             {"/",S_OK},
4893             {"/",S_OK},
4894             {"",S_FALSE},
4895             {"http://::password@google.com/",S_OK},
4896             {"http",S_OK},
4897             {"::password",S_OK},
4898             {"",S_FALSE}
4899         },
4900         {
4901             {Uri_HOST_DNS,S_OK},
4902             {80,S_OK},
4903             {URL_SCHEME_HTTP,S_OK},
4904             {URLZONE_INVALID,E_NOTIMPL}
4905         }
4906     },
4907     {   "test/test",Uri_CREATE_ALLOW_RELATIVE,S_OK,FALSE,
4908         {
4909             {TRUE,"password",NULL,Uri_PROPERTY_PASSWORD,S_OK,FALSE}
4910         },
4911         {FALSE},
4912         Uri_CREATE_ALLOW_RELATIVE,S_OK,FALSE,
4913         0,S_OK,FALSE,
4914         Uri_CREATE_ALLOW_RELATIVE,0,0,S_OK,FALSE,
4915         {
4916             {":password@test/test",S_OK},
4917             {":password@",S_OK},
4918             {":password@test/test",S_OK},
4919             {"",S_FALSE},
4920             {"",S_FALSE},
4921             {"",S_FALSE},
4922             {"",S_FALSE},
4923             {"password",S_OK},
4924             {"test/test",S_OK},
4925             {"test/test",S_OK},
4926             {"",S_FALSE},
4927             {":password@test/test",S_OK},
4928             {"",S_FALSE},
4929             {":password",S_OK},
4930             {"",S_FALSE}
4931         },
4932         {
4933             {Uri_HOST_UNKNOWN,S_OK},
4934             {0,S_FALSE},
4935             {URL_SCHEME_UNKNOWN,S_OK},
4936             {URLZONE_INVALID,E_NOTIMPL}
4937         }
4938     },
4939     {   "http://google.com/",0,S_OK,FALSE,
4940         {
4941             {TRUE,"test/test",NULL,Uri_PROPERTY_PATH,S_OK,FALSE},
4942         },
4943         {FALSE},
4944         0,S_OK,FALSE,
4945         0,S_OK,FALSE,
4946         0,0,0,S_OK,FALSE,
4947         {
4948             {"http://google.com/test/test",S_OK},
4949             {"google.com",S_OK},
4950             {"http://google.com/test/test",S_OK},
4951             {"google.com",S_OK},
4952             {"",S_FALSE},
4953             {"",S_FALSE},
4954             {"google.com",S_OK},
4955             {"",S_FALSE},
4956             {"/test/test",S_OK},
4957             {"/test/test",S_OK},
4958             {"",S_FALSE},
4959             {"http://google.com/test/test",S_OK},
4960             {"http",S_OK},
4961             {"",S_FALSE},
4962             {"",S_FALSE}
4963         },
4964         {
4965             {Uri_HOST_DNS,S_OK},
4966             {80,S_OK},
4967             {URL_SCHEME_HTTP,S_OK},
4968             {URLZONE_INVALID,E_NOTIMPL}
4969         }
4970     },
4971     {   "zip:testing/test",0,S_OK,FALSE,
4972         {
4973             {TRUE,"test",NULL,Uri_PROPERTY_PATH,S_OK,FALSE},
4974         },
4975         {FALSE},
4976         0,S_OK,FALSE,
4977         0,S_OK,FALSE,
4978         0,0,0,S_OK,FALSE,
4979         {
4980             {"zip:test",S_OK},
4981             {"",S_FALSE},
4982             {"zip:test",S_OK},
4983             {"",S_FALSE},
4984             {"",S_FALSE},
4985             {"",S_FALSE},
4986             {"",S_FALSE},
4987             {"",S_FALSE},
4988             {"test",S_OK},
4989             {"test",S_OK},
4990             {"",S_FALSE},
4991             {"zip:test",S_OK},
4992             {"zip",S_OK},
4993             {"",S_FALSE},
4994             {"",S_FALSE}
4995         },
4996         {
4997             {Uri_HOST_UNKNOWN,S_OK},
4998             {0,S_FALSE},
4999             {URL_SCHEME_UNKNOWN,S_OK},
5000             {URLZONE_INVALID,E_NOTIMPL}
5001         }
5002     },
5003     {   "http://google.com/",0,S_OK,FALSE,
5004         {
5005             {FALSE},
5006         },
5007         /* 555 will be returned from GetPort even though FALSE was passed as the hasPort parameter. */
5008         {TRUE,FALSE,555,S_OK,FALSE},
5009         0,S_OK,FALSE,
5010         0,S_OK,FALSE,
5011         0,0,0,S_OK,FALSE,
5012         {
5013             {"http://google.com/",S_OK},
5014             {"google.com",S_OK},
5015             {"http://google.com/",S_OK},
5016             {"google.com",S_OK},
5017             {"",S_FALSE},
5018             {"",S_FALSE},
5019             {"google.com",S_OK},
5020             {"",S_FALSE},
5021             {"/",S_OK},
5022             {"/",S_OK},
5023             {"",S_FALSE},
5024             {"http://google.com/",S_OK},
5025             {"http",S_OK},
5026             {"",S_FALSE},
5027             {"",S_FALSE}
5028         },
5029         {
5030             {Uri_HOST_DNS,S_OK},
5031             /* Still returns 80, even though earlier the port was disabled. */
5032             {80,S_OK},
5033             {URL_SCHEME_HTTP,S_OK},
5034             {URLZONE_INVALID,E_NOTIMPL}
5035         }
5036     },
5037     {   "http://google.com/",0,S_OK,FALSE,
5038         {
5039             {FALSE},
5040         },
5041         /* Instead of getting "TRUE" back as the "hasPort" parameter in GetPort,
5042          * you'll get 122345 instead.
5043          */
5044         {TRUE,122345,222,S_OK,FALSE},
5045         0,S_OK,FALSE,
5046         0,S_OK,FALSE,
5047         0,0,0,S_OK,FALSE,
5048         {
5049             {"http://google.com:222/",S_OK},
5050             {"google.com:222",S_OK},
5051             {"http://google.com:222/",S_OK},
5052             {"google.com",S_OK},
5053             {"",S_FALSE},
5054             {"",S_FALSE},
5055             {"google.com",S_OK},
5056             {"",S_FALSE},
5057             {"/",S_OK},
5058             {"/",S_OK},
5059             {"",S_FALSE},
5060             {"http://google.com:222/",S_OK},
5061             {"http",S_OK},
5062             {"",S_FALSE},
5063             {"",S_FALSE}
5064         },
5065         {
5066             {Uri_HOST_DNS,S_OK},
5067             {222,S_OK},
5068             {URL_SCHEME_HTTP,S_OK},
5069             {URLZONE_INVALID,E_NOTIMPL}
5070         }
5071     },
5072     /* IUri's created with the IUriBuilder can have ports that exceed USHORT_MAX. */
5073     {   "http://google.com/",0,S_OK,FALSE,
5074         {
5075             {FALSE},
5076         },
5077         {TRUE,TRUE,999999,S_OK,FALSE},
5078         0,S_OK,FALSE,
5079         0,S_OK,FALSE,
5080         0,0,0,S_OK,FALSE,
5081         {
5082             {"http://google.com:999999/",S_OK},
5083             {"google.com:999999",S_OK},
5084             {"http://google.com:999999/",S_OK},
5085             {"google.com",S_OK},
5086             {"",S_FALSE},
5087             {"",S_FALSE},
5088             {"google.com",S_OK},
5089             {"",S_FALSE},
5090             {"/",S_OK},
5091             {"/",S_OK},
5092             {"",S_FALSE},
5093             {"http://google.com:999999/",S_OK},
5094             {"http",S_OK},
5095             {"",S_FALSE},
5096             {"",S_FALSE}
5097         },
5098         {
5099             {Uri_HOST_DNS,S_OK},
5100             {999999,S_OK},
5101             {URL_SCHEME_HTTP,S_OK},
5102             {URLZONE_INVALID,E_NOTIMPL}
5103         }
5104     },
5105     {   "http://google.com/",0,S_OK,FALSE,
5106         {
5107             {TRUE,"test","?test",Uri_PROPERTY_QUERY,S_OK,FALSE},
5108         },
5109
5110         {FALSE},
5111         0,S_OK,FALSE,
5112         0,S_OK,FALSE,
5113         0,0,0,S_OK,FALSE,
5114         {
5115             {"http://google.com/?test",S_OK},
5116             {"google.com",S_OK},
5117             {"http://google.com/?test",S_OK},
5118             {"google.com",S_OK},
5119             {"",S_FALSE},
5120             {"",S_FALSE},
5121             {"google.com",S_OK},
5122             {"",S_FALSE},
5123             {"/",S_OK},
5124             {"/?test",S_OK},
5125             {"?test",S_OK},
5126             {"http://google.com/?test",S_OK},
5127             {"http",S_OK},
5128             {"",S_FALSE},
5129             {"",S_FALSE}
5130         },
5131         {
5132             {Uri_HOST_DNS,S_OK},
5133             {80,S_OK},
5134             {URL_SCHEME_HTTP,S_OK},
5135             {URLZONE_INVALID,E_NOTIMPL}
5136         }
5137     },
5138     {   "http://:password@google.com/",0,S_OK,FALSE,
5139         {
5140             {FALSE},
5141         },
5142         {FALSE},
5143         0,S_OK,FALSE,
5144         0,S_OK,FALSE,
5145         0,0,0,S_OK,FALSE,
5146         {
5147             {"http://:password@google.com/",S_OK},
5148             {":password@google.com",S_OK},
5149             {"http://google.com/",S_OK},
5150             {"google.com",S_OK},
5151             {"",S_FALSE},
5152             {"",S_FALSE},
5153             {"google.com",S_OK},
5154             {"password",S_OK},
5155             {"/",S_OK},
5156             {"/",S_OK},
5157             {"",S_FALSE},
5158             {"http://:password@google.com/",S_OK},
5159             {"http",S_OK},
5160             {":password",S_OK},
5161             {"",S_FALSE}
5162         },
5163         {
5164             {Uri_HOST_DNS,S_OK},
5165             {80,S_OK},
5166             {URL_SCHEME_HTTP,S_OK},
5167             {URLZONE_INVALID,E_NOTIMPL}
5168         }
5169     },
5170     /* IUriBuilder doesn't need a base IUri to build a IUri. */
5171     {   NULL,0,S_OK,FALSE,
5172         {
5173             {TRUE,"http",NULL,Uri_PROPERTY_SCHEME_NAME,S_OK,FALSE},
5174             {TRUE,"google.com",NULL,Uri_PROPERTY_HOST,S_OK,FALSE}
5175         },
5176         {FALSE},
5177         0,S_OK,FALSE,
5178         0,S_OK,FALSE,
5179         0,0,0,S_OK,FALSE,
5180         {
5181             {"http://google.com/",S_OK},
5182             {"google.com",S_OK},
5183             {"http://google.com/",S_OK},
5184             {"google.com",S_OK},
5185             {"",S_FALSE},
5186             {"",S_FALSE},
5187             {"google.com",S_OK},
5188             {"",S_FALSE},
5189             {"/",S_OK},
5190             {"/",S_OK},
5191             {"",S_FALSE},
5192             {"http://google.com/",S_OK},
5193             {"http",S_OK},
5194             {"",S_FALSE},
5195             {"",S_FALSE}
5196         },
5197         {
5198             {Uri_HOST_DNS,S_OK},
5199             {80,S_OK},
5200             {URL_SCHEME_HTTP,S_OK},
5201             {URLZONE_INVALID,E_NOTIMPL}
5202         }
5203     },
5204     /* Can't set the scheme name to NULL. */
5205     {   "zip://google.com/",0,S_OK,FALSE,
5206         {
5207             {TRUE,NULL,"zip",Uri_PROPERTY_SCHEME_NAME,E_INVALIDARG,FALSE}
5208         },
5209         {FALSE},
5210         0,S_OK,FALSE,
5211         0,S_OK,FALSE,
5212         0,0,0,S_OK,FALSE,
5213         {
5214             {"zip://google.com/",S_OK},
5215             {"google.com",S_OK},
5216             {"zip://google.com/",S_OK},
5217             {"google.com",S_OK},
5218             {"",S_FALSE},
5219             {"",S_FALSE},
5220             {"google.com",S_OK},
5221             {"",S_FALSE},
5222             {"/",S_OK},
5223             {"/",S_OK},
5224             {"",S_FALSE},
5225             {"zip://google.com/",S_OK},
5226             {"zip",S_OK},
5227             {"",S_FALSE},
5228             {"",S_FALSE}
5229         },
5230         {
5231             {Uri_HOST_DNS,S_OK},
5232             {0,S_FALSE},
5233             {URL_SCHEME_UNKNOWN,S_OK},
5234             {URLZONE_INVALID,E_NOTIMPL}
5235         }
5236     },
5237     /* Can't set the scheme name to an empty string. */
5238     {   "zip://google.com/",0,S_OK,FALSE,
5239         {
5240             {TRUE,"","zip",Uri_PROPERTY_SCHEME_NAME,E_INVALIDARG,FALSE}
5241         },
5242         {FALSE},
5243         0,S_OK,FALSE,
5244         0,S_OK,FALSE,
5245         0,0,0,S_OK,FALSE,
5246         {
5247             {"zip://google.com/",S_OK},
5248             {"google.com",S_OK},
5249             {"zip://google.com/",S_OK},
5250             {"google.com",S_OK},
5251             {"",S_FALSE},
5252             {"",S_FALSE},
5253             {"google.com",S_OK},
5254             {"",S_FALSE},
5255             {"/",S_OK},
5256             {"/",S_OK},
5257             {"",S_FALSE},
5258             {"zip://google.com/",S_OK},
5259             {"zip",S_OK},
5260             {"",S_FALSE},
5261             {"",S_FALSE}
5262         },
5263         {
5264             {Uri_HOST_DNS,S_OK},
5265             {0,S_FALSE},
5266             {URL_SCHEME_UNKNOWN,S_OK},
5267             {URLZONE_INVALID,E_NOTIMPL}
5268         }
5269     },
5270     /* -1 to CreateUri makes it use the same flags as the base IUri was created with.
5271      * CreateUriSimple always uses the flags the base IUri was created with (if any).
5272      */
5273     {   "http://google.com/../../",Uri_CREATE_NO_CANONICALIZE,S_OK,FALSE,
5274         {{FALSE}},
5275         {FALSE},
5276         -1,S_OK,FALSE,
5277         0,S_OK,FALSE,
5278         0,UriBuilder_USE_ORIGINAL_FLAGS,0,S_OK,FALSE,
5279         {
5280             {"http://google.com/../../",S_OK},
5281             {"google.com",S_OK},
5282             {"http://google.com/../../",S_OK},
5283             {"google.com",S_OK},
5284             {"",S_FALSE},
5285             {"",S_FALSE},
5286             {"google.com",S_OK},
5287             {"",S_FALSE},
5288             {"/../../",S_OK},
5289             {"/../../",S_OK},
5290             {"",S_FALSE},
5291             {"http://google.com/../../",S_OK},
5292             {"http",S_OK},
5293             {"",S_FALSE},
5294             {"",S_FALSE}
5295         },
5296         {
5297             {Uri_HOST_DNS,S_OK},
5298             {80,S_OK},
5299             {URL_SCHEME_HTTP,S_OK},
5300             {URLZONE_INVALID,E_NOTIMPL}
5301         }
5302     },
5303     {   "http://google.com/",0,S_OK,FALSE,
5304         {
5305             {TRUE,"#Fr<|>g",NULL,Uri_PROPERTY_FRAGMENT,S_OK,FALSE}
5306         },
5307         {FALSE},
5308         -1,S_OK,FALSE,
5309         0,S_OK,FALSE,
5310         Uri_CREATE_NO_DECODE_EXTRA_INFO,UriBuilder_USE_ORIGINAL_FLAGS,0,S_OK,FALSE,
5311         {
5312             {"http://google.com/#Fr%3C%7C%3Eg",S_OK},
5313             {"google.com",S_OK},
5314             {"http://google.com/#Fr%3C%7C%3Eg",S_OK},
5315             {"google.com",S_OK},
5316             {"",S_FALSE},
5317             {"#Fr%3C%7C%3Eg",S_OK},
5318             {"google.com",S_OK},
5319             {"",S_FALSE},
5320             {"/",S_OK},
5321             {"/",S_OK},
5322             {"",S_FALSE},
5323             {"http://google.com/#Fr<|>g",S_OK},
5324             {"http",S_OK},
5325             {"",S_FALSE},
5326             {"",S_FALSE}
5327         },
5328         {
5329             {Uri_HOST_DNS,S_OK},
5330             {80,S_OK},
5331             {URL_SCHEME_HTTP,S_OK},
5332             {URLZONE_INVALID,E_NOTIMPL}
5333         }
5334     },
5335     {   "http://google.com/",0,S_OK,FALSE,
5336         {
5337             {TRUE,"#Fr<|>g",NULL,Uri_PROPERTY_FRAGMENT,S_OK,FALSE}
5338         },
5339         {FALSE},
5340         Uri_CREATE_CANONICALIZE|Uri_CREATE_NO_CANONICALIZE,E_INVALIDARG,FALSE,
5341         0,S_OK,FALSE,
5342         Uri_CREATE_CANONICALIZE|Uri_CREATE_NO_CANONICALIZE,UriBuilder_USE_ORIGINAL_FLAGS,0,S_OK,FALSE,
5343         {
5344             {"http://google.com/#Fr%3C%7C%3Eg",S_OK},
5345             {"google.com",S_OK},
5346             {"http://google.com/#Fr%3C%7C%3Eg",S_OK},
5347             {"google.com",S_OK},
5348             {"",S_FALSE},
5349             {"#Fr%3C%7C%3Eg",S_OK},
5350             {"google.com",S_OK},
5351             {"",S_FALSE},
5352             {"/",S_OK},
5353             {"/",S_OK},
5354             {"",S_FALSE},
5355             {"http://google.com/#Fr<|>g",S_OK},
5356             {"http",S_OK},
5357             {"",S_FALSE},
5358             {"",S_FALSE}
5359         },
5360         {
5361             {Uri_HOST_DNS,S_OK},
5362             {80,S_OK},
5363             {URL_SCHEME_HTTP,S_OK},
5364             {URLZONE_INVALID,E_NOTIMPL}
5365         }
5366     },
5367     {   NULL,0,S_OK,FALSE,
5368         {
5369             {TRUE,"/test/test/",NULL,Uri_PROPERTY_PATH,S_OK,FALSE},
5370             {TRUE,"#Fr<|>g",NULL,Uri_PROPERTY_FRAGMENT,S_OK,FALSE}
5371         },
5372         {FALSE},
5373         0,INET_E_INVALID_URL,FALSE,
5374         0,INET_E_INVALID_URL,FALSE,
5375         0,0,0,INET_E_INVALID_URL,FALSE
5376     },
5377     {   "http://google.com/",0,S_OK,FALSE,
5378         {
5379             {TRUE,"ht%xxtp",NULL,Uri_PROPERTY_SCHEME_NAME,S_OK,FALSE}
5380         },
5381         {FALSE},
5382         0,INET_E_INVALID_URL,FALSE,
5383         0,INET_E_INVALID_URL,FALSE,
5384         0,0,0,INET_E_INVALID_URL,FALSE
5385     },
5386     /* File scheme's can't have a username set. */
5387     {   "file://google.com/",0,S_OK,FALSE,
5388         {
5389             {TRUE,"username",NULL,Uri_PROPERTY_USER_NAME,S_OK,FALSE}
5390         },
5391         {FALSE},
5392         0,INET_E_INVALID_URL,FALSE,
5393         0,INET_E_INVALID_URL,FALSE,
5394         0,0,0,INET_E_INVALID_URL,FALSE
5395     },
5396     /* File schemes can't have a password set. */
5397     {   "file://google.com/",0,S_OK,FALSE,
5398         {
5399             {TRUE,"password",NULL,Uri_PROPERTY_PASSWORD,S_OK,FALSE}
5400         },
5401         {FALSE},
5402         0,INET_E_INVALID_URL,FALSE,
5403         0,INET_E_INVALID_URL,FALSE,
5404         0,0,0,INET_E_INVALID_URL,FALSE
5405     },
5406     /* UserName can't contain any character that is a delimeter for another
5407      * component that appears after it in a normal URI.
5408      */
5409     {   "http://google.com/",0,S_OK,FALSE,
5410         {
5411             {TRUE,"user:pass",NULL,Uri_PROPERTY_USER_NAME,S_OK,FALSE}
5412         },
5413         {FALSE},
5414         0,INET_E_INVALID_URL,FALSE,
5415         0,INET_E_INVALID_URL,FALSE,
5416         0,0,0,INET_E_INVALID_URL,FALSE
5417     },
5418     {   "http://google.com/",0,S_OK,FALSE,
5419         {
5420             {TRUE,"user@google.com",NULL,Uri_PROPERTY_USER_NAME,S_OK,FALSE}
5421         },
5422         {FALSE},
5423         0,INET_E_INVALID_URL,FALSE,
5424         0,INET_E_INVALID_URL,FALSE,
5425         0,0,0,INET_E_INVALID_URL,FALSE
5426     },
5427     {   "http://google.com/",0,S_OK,FALSE,
5428         {
5429             {TRUE,"user/path",NULL,Uri_PROPERTY_USER_NAME,S_OK,FALSE}
5430         },
5431         {FALSE},
5432         0,INET_E_INVALID_URL,FALSE,
5433         0,INET_E_INVALID_URL,FALSE,
5434         0,0,0,INET_E_INVALID_URL,FALSE
5435     },
5436     {   "http://google.com/",0,S_OK,FALSE,
5437         {
5438             {TRUE,"user?Query",NULL,Uri_PROPERTY_USER_NAME,S_OK,FALSE}
5439         },
5440         {FALSE},
5441         0,INET_E_INVALID_URL,FALSE,
5442         0,INET_E_INVALID_URL,FALSE,
5443         0,0,0,INET_E_INVALID_URL,FALSE
5444     },
5445     {   "http://google.com/",0,S_OK,FALSE,
5446         {
5447             {TRUE,"user#Frag",NULL,Uri_PROPERTY_USER_NAME,S_OK,FALSE}
5448         },
5449         {FALSE},
5450         0,INET_E_INVALID_URL,FALSE,
5451         0,INET_E_INVALID_URL,FALSE,
5452         0,0,0,INET_E_INVALID_URL,FALSE
5453     },
5454     {   "http://google.com/",0,S_OK,FALSE,
5455         {
5456             {TRUE,"pass@google.com",NULL,Uri_PROPERTY_PASSWORD,S_OK,FALSE}
5457         },
5458         {FALSE},
5459         0,INET_E_INVALID_URL,FALSE,
5460         0,INET_E_INVALID_URL,FALSE,
5461         0,0,0,INET_E_INVALID_URL,FALSE
5462     },
5463     {   "http://google.com/",0,S_OK,FALSE,
5464         {
5465             {TRUE,"pass/path",NULL,Uri_PROPERTY_PASSWORD,S_OK,FALSE}
5466         },
5467         {FALSE},
5468         0,INET_E_INVALID_URL,FALSE,
5469         0,INET_E_INVALID_URL,FALSE,
5470         0,0,0,INET_E_INVALID_URL,FALSE
5471     },
5472     {   "http://google.com/",0,S_OK,FALSE,
5473         {
5474             {TRUE,"pass?query",NULL,Uri_PROPERTY_PASSWORD,S_OK,FALSE}
5475         },
5476         {FALSE},
5477         0,INET_E_INVALID_URL,FALSE,
5478         0,INET_E_INVALID_URL,FALSE,
5479        0,0,0,INET_E_INVALID_URL,FALSE
5480     },
5481     {   "http://google.com/",0,S_OK,FALSE,
5482         {
5483             {TRUE,"pass#frag",NULL,Uri_PROPERTY_PASSWORD,S_OK,FALSE}
5484         },
5485         {FALSE},
5486         0,INET_E_INVALID_URL,FALSE,
5487         0,INET_E_INVALID_URL,FALSE,
5488         0,0,0,INET_E_INVALID_URL,FALSE
5489     },
5490     {   "http://google.com/",0,S_OK,FALSE,
5491         {
5492             {TRUE,"winehq.org/test",NULL,Uri_PROPERTY_HOST,S_OK,FALSE}
5493         },
5494         {FALSE},
5495         0,INET_E_INVALID_URL,FALSE,
5496         0,INET_E_INVALID_URL,FALSE,
5497         0,0,0,INET_E_INVALID_URL,FALSE
5498     },
5499     {   "http://google.com/",0,S_OK,FALSE,
5500         {
5501             {TRUE,"winehq.org?test",NULL,Uri_PROPERTY_HOST,S_OK,FALSE}
5502         },
5503         {FALSE},
5504         0,INET_E_INVALID_URL,FALSE,
5505         0,INET_E_INVALID_URL,FALSE,
5506         0,0,0,INET_E_INVALID_URL,FALSE
5507     },
5508     {   "http://google.com/",0,S_OK,FALSE,
5509         {
5510             {TRUE,"winehq.org#test",NULL,Uri_PROPERTY_HOST,S_OK,FALSE}
5511         },
5512         {FALSE},
5513         0,INET_E_INVALID_URL,FALSE,
5514         0,INET_E_INVALID_URL,FALSE,
5515         0,0,0,INET_E_INVALID_URL,FALSE
5516     },
5517     /* Hostname is allowed to contain a ':' (even for known scheme types). */
5518     {   "http://google.com/",0,S_OK,FALSE,
5519         {
5520             {TRUE,"winehq.org:test",NULL,Uri_PROPERTY_HOST,S_OK,FALSE},
5521         },
5522         {FALSE},
5523         0,S_OK,FALSE,
5524         0,S_OK,FALSE,
5525         0,0,0,S_OK,FALSE,
5526         {
5527             {"http://winehq.org:test/",S_OK},
5528             {"winehq.org:test",S_OK},
5529             {"http://winehq.org:test/",S_OK},
5530             {"winehq.org:test",S_OK},
5531             {"",S_FALSE},
5532             {"",S_FALSE},
5533             {"winehq.org:test",S_OK},
5534             {"",S_FALSE},
5535             {"/",S_OK},
5536             {"/",S_OK},
5537             {"",S_FALSE},
5538             {"http://winehq.org:test/",S_OK},
5539             {"http",S_OK},
5540             {"",S_FALSE},
5541             {"",S_FALSE}
5542         },
5543         {
5544             {Uri_HOST_DNS,S_OK},
5545             {80,S_OK},
5546             {URL_SCHEME_HTTP,S_OK},
5547             {URLZONE_INVALID,E_NOTIMPL}
5548         }
5549     },
5550     /* Can't set the host name to NULL. */
5551     {   "http://google.com/",0,S_OK,FALSE,
5552         {
5553             {TRUE,NULL,"google.com",Uri_PROPERTY_HOST,E_INVALIDARG,FALSE}
5554         },
5555         {FALSE},
5556         0,S_OK,FALSE,
5557         0,S_OK,FALSE,
5558         0,0,0,S_OK,FALSE,
5559         {
5560             {"http://google.com/",S_OK},
5561             {"google.com",S_OK},
5562             {"http://google.com/",S_OK},
5563             {"google.com",S_OK},
5564             {"",S_FALSE},
5565             {"",S_FALSE},
5566             {"google.com",S_OK},
5567             {"",S_FALSE},
5568             {"/",S_OK},
5569             {"/",S_OK},
5570             {"",S_FALSE},
5571             {"http://google.com/",S_OK},
5572             {"http",S_OK},
5573             {"",S_FALSE},
5574             {"",S_FALSE}
5575         },
5576         {
5577             {Uri_HOST_DNS,S_OK},
5578             {80,S_OK},
5579             {URL_SCHEME_HTTP,S_OK},
5580             {URLZONE_INVALID,E_NOTIMPL}
5581         }
5582     },
5583     /* Can set the host name to an empty string. */
5584     {   "http://google.com/",0,S_OK,FALSE,
5585         {
5586             {TRUE,"",NULL,Uri_PROPERTY_HOST,S_OK,FALSE}
5587         },
5588         {FALSE},
5589         0,S_OK,FALSE,
5590         0,S_OK,FALSE,
5591         0,0,0,S_OK,FALSE,
5592         {
5593             {"http:///",S_OK},
5594             {"",S_OK},
5595             {"http:///",S_OK},
5596             {"",S_FALSE},
5597             {"",S_FALSE},
5598             {"",S_FALSE},
5599             {"",S_OK},
5600             {"",S_FALSE},
5601             {"/",S_OK},
5602             {"/",S_OK},
5603             {"",S_FALSE},
5604             {"http:///",S_OK},
5605             {"http",S_OK},
5606             {"",S_FALSE},
5607             {"",S_FALSE}
5608         },
5609         {
5610             {Uri_HOST_UNKNOWN,S_OK},
5611             {80,S_OK},
5612             {URL_SCHEME_HTTP,S_OK},
5613             {URLZONE_INVALID,E_NOTIMPL}
5614         }
5615     },
5616     {   "http://google.com/",0,S_OK,FALSE,
5617         {
5618             {TRUE,"/path?query",NULL,Uri_PROPERTY_PATH,S_OK,FALSE}
5619         },
5620         {FALSE},
5621         0,INET_E_INVALID_URL,FALSE,
5622         0,INET_E_INVALID_URL,FALSE,
5623         0,0,0,INET_E_INVALID_URL,FALSE
5624     },
5625     {   "http://google.com/",0,S_OK,FALSE,
5626         {
5627             {TRUE,"/path#test",NULL,Uri_PROPERTY_PATH,S_OK,FALSE}
5628         },
5629         {FALSE},
5630         0,INET_E_INVALID_URL,FALSE,
5631         0,INET_E_INVALID_URL,FALSE,
5632         0,0,0,INET_E_INVALID_URL,FALSE
5633     },
5634     {   "http://google.com/",0,S_OK,FALSE,
5635         {
5636             {TRUE,"?path#test",NULL,Uri_PROPERTY_QUERY,S_OK,FALSE}
5637         },
5638         {FALSE},
5639         0,INET_E_INVALID_URL,FALSE,
5640         0,INET_E_INVALID_URL,FALSE,
5641         0,0,0,INET_E_INVALID_URL,FALSE
5642     },
5643     {   "file:///c:/dir/file.html",0,S_OK,FALSE,
5644         {
5645             {TRUE,NULL,NULL,Uri_PROPERTY_FRAGMENT,S_OK},
5646         },
5647         {FALSE},
5648         0,S_OK,FALSE,
5649         0,S_OK,FALSE,
5650         0,0,0,S_OK,FALSE,
5651         {
5652             {"file:///c:/dir/file.html",S_OK},
5653             {"",S_FALSE},
5654             {"file:///c:/dir/file.html",S_OK},
5655             {"",S_FALSE},
5656             {".html",S_OK},
5657             {"",S_FALSE},
5658             {"",S_FALSE},
5659             {"",S_FALSE},
5660             {"/c:/dir/file.html",S_OK},
5661             {"/c:/dir/file.html",S_OK},
5662             {"",S_FALSE},
5663             {"file:///c:/dir/file.html",S_OK},
5664             {"file",S_OK},
5665             {"",S_FALSE},
5666             {"",S_FALSE}
5667         },
5668         {
5669             {Uri_HOST_UNKNOWN,S_OK},
5670             {0,S_FALSE},
5671             {URL_SCHEME_FILE,S_OK},
5672             {URLZONE_INVALID,E_NOTIMPL}
5673         }
5674     },
5675     {   "file:///c:/dir/file.html",0,S_OK,FALSE,
5676         {
5677             {TRUE,"#",NULL,Uri_PROPERTY_FRAGMENT,S_OK},
5678         },
5679         {FALSE},
5680         0,S_OK,FALSE,
5681         0,S_OK,FALSE,
5682         0,0,0,S_OK,FALSE,
5683         {
5684             {"file:///c:/dir/file.html#",S_OK},
5685             {"",S_FALSE},
5686             {"file:///c:/dir/file.html#",S_OK},
5687             {"",S_FALSE},
5688             {".html",S_OK},
5689             {"#",S_OK},
5690             {"",S_FALSE},
5691             {"",S_FALSE},
5692             {"/c:/dir/file.html",S_OK},
5693             {"/c:/dir/file.html",S_OK},
5694             {"",S_FALSE},
5695             {"file:///c:/dir/file.html#",S_OK},
5696             {"file",S_OK},
5697             {"",S_FALSE},
5698             {"",S_FALSE}
5699         },
5700         {
5701             {Uri_HOST_UNKNOWN,S_OK},
5702             {0,S_FALSE},
5703             {URL_SCHEME_FILE,S_OK},
5704             {URLZONE_INVALID,E_NOTIMPL}
5705         }
5706     }
5707 };
5708
5709 typedef struct _uri_builder_remove_test {
5710     const char  *uri;
5711     DWORD       create_flags;
5712     HRESULT     create_builder_expected;
5713     BOOL        create_builder_todo;
5714
5715     DWORD       remove_properties;
5716     HRESULT     remove_expected;
5717     BOOL        remove_todo;
5718
5719     const char  *expected_uri;
5720     DWORD       expected_flags;
5721     HRESULT     expected_hres;
5722     BOOL        expected_todo;
5723 } uri_builder_remove_test;
5724
5725 static const uri_builder_remove_test uri_builder_remove_tests[] = {
5726     {   "http://google.com/test?test=y#Frag",0,S_OK,FALSE,
5727         Uri_HAS_FRAGMENT|Uri_HAS_PATH|Uri_HAS_QUERY,S_OK,FALSE,
5728         "http://google.com/",0,S_OK,FALSE
5729     },
5730     {   "http://user:pass@winehq.org/",0,S_OK,FALSE,
5731         Uri_HAS_USER_NAME|Uri_HAS_PASSWORD,S_OK,FALSE,
5732         "http://winehq.org/",0,S_OK,FALSE
5733     },
5734     {   "zip://google.com?Test=x",0,S_OK,FALSE,
5735         Uri_HAS_HOST,S_OK,FALSE,
5736         "zip:/?Test=x",0,S_OK,FALSE
5737     },
5738     /* Doesn't remove the whole userinfo component. */
5739     {   "http://username:pass@google.com/",0,S_OK,FALSE,
5740         Uri_HAS_USER_INFO,S_OK,FALSE,
5741         "http://username:pass@google.com/",0,S_OK,FALSE
5742     },
5743     /* Doesn't remove the domain. */
5744     {   "http://google.com/",0,S_OK,FALSE,
5745         Uri_HAS_DOMAIN,S_OK,FALSE,
5746         "http://google.com/",0,S_OK,FALSE
5747     },
5748     {   "http://google.com:120/",0,S_OK,FALSE,
5749         Uri_HAS_AUTHORITY,S_OK,FALSE,
5750         "http://google.com:120/",0,S_OK,FALSE
5751     },
5752     {   "http://google.com/test.com/",0,S_OK,FALSE,
5753         Uri_HAS_EXTENSION,S_OK,FALSE,
5754         "http://google.com/test.com/",0,S_OK,FALSE
5755     },
5756     {   "http://google.com/?test=x",0,S_OK,FALSE,
5757         Uri_HAS_PATH_AND_QUERY,S_OK,FALSE,
5758         "http://google.com/?test=x",0,S_OK,FALSE
5759     },
5760     /* Can't remove the scheme name. */
5761     {   "http://google.com/?test=x",0,S_OK,FALSE,
5762         Uri_HAS_SCHEME_NAME|Uri_HAS_QUERY,E_INVALIDARG,FALSE,
5763         "http://google.com/?test=x",0,S_OK,FALSE
5764     }
5765 };
5766
5767 typedef struct _uri_combine_str_property {
5768     const char  *value;
5769     HRESULT     expected;
5770     BOOL        todo;
5771     const char  *broken_value;
5772     const char  *value_ex;
5773 } uri_combine_str_property;
5774
5775 typedef struct _uri_combine_test {
5776     const char  *base_uri;
5777     DWORD       base_create_flags;
5778     const char  *relative_uri;
5779     DWORD       relative_create_flags;
5780     DWORD       combine_flags;
5781     HRESULT     expected;
5782     BOOL        todo;
5783
5784     uri_combine_str_property    str_props[URI_STR_PROPERTY_COUNT];
5785     uri_dword_property          dword_props[URI_DWORD_PROPERTY_COUNT];
5786 } uri_combine_test;
5787
5788 static const uri_combine_test uri_combine_tests[] = {
5789     {   "http://google.com/fun/stuff",0,
5790         "../not/fun/stuff",Uri_CREATE_ALLOW_RELATIVE,
5791         0,S_OK,FALSE,
5792         {
5793             {"http://google.com/not/fun/stuff",S_OK},
5794             {"google.com",S_OK},
5795             {"http://google.com/not/fun/stuff",S_OK},
5796             {"google.com",S_OK},
5797             {"",S_FALSE},
5798             {"",S_FALSE},
5799             {"google.com",S_OK},
5800             {"",S_FALSE},
5801             {"/not/fun/stuff",S_OK},
5802             {"/not/fun/stuff",S_OK},
5803             {"",S_FALSE},
5804             {"http://google.com/not/fun/stuff",S_OK},
5805             {"http",S_OK},
5806             {"",S_FALSE},
5807             {"",S_FALSE}
5808         },
5809         {
5810             {Uri_HOST_DNS,S_OK},
5811             {80,S_OK},
5812             {URL_SCHEME_HTTP,S_OK},
5813             {URLZONE_INVALID,E_NOTIMPL}
5814         }
5815     },
5816     {   "http://google.com/test",0,
5817         "zip://test.com/cool",0,
5818         0,S_OK,FALSE,
5819         {
5820             {"zip://test.com/cool",S_OK},
5821             {"test.com",S_OK},
5822             {"zip://test.com/cool",S_OK},
5823             {"test.com",S_OK},
5824             {"",S_FALSE},
5825             {"",S_FALSE},
5826             {"test.com",S_OK},
5827             {"",S_FALSE},
5828             {"/cool",S_OK},
5829             {"/cool",S_OK},
5830             {"",S_FALSE},
5831             {"zip://test.com/cool",S_OK},
5832             {"zip",S_OK},
5833             {"",S_FALSE},
5834             {"",S_FALSE}
5835         },
5836         {
5837             {Uri_HOST_DNS,S_OK},
5838             {0,S_FALSE},
5839             {URL_SCHEME_UNKNOWN,S_OK},
5840             {URLZONE_INVALID,E_NOTIMPL}
5841         }
5842     },
5843     {   "http://google.com/use/base/path",0,
5844         "?relative",Uri_CREATE_ALLOW_RELATIVE,
5845         0,S_OK,FALSE,
5846         {
5847             {"http://google.com/use/base/path?relative",S_OK},
5848             {"google.com",S_OK},
5849             {"http://google.com/use/base/path?relative",S_OK},
5850             {"google.com",S_OK},
5851             {"",S_FALSE},
5852             {"",S_FALSE},
5853             {"google.com",S_OK},
5854             {"",S_FALSE},
5855             {"/use/base/path",S_OK},
5856             {"/use/base/path?relative",S_OK},
5857             {"?relative",S_OK},
5858             {"http://google.com/use/base/path?relative",S_OK},
5859             {"http",S_OK},
5860             {"",S_FALSE},
5861             {"",S_FALSE}
5862         },
5863         {
5864             {Uri_HOST_DNS,S_OK},
5865             {80,S_OK},
5866             {URL_SCHEME_HTTP,S_OK},
5867             {URLZONE_INVALID,E_NOTIMPL}
5868         }
5869     },
5870     {   "http://google.com/path",0,
5871         "/test/../test/.././testing",Uri_CREATE_ALLOW_RELATIVE,
5872         0,S_OK,FALSE,
5873         {
5874             {"http://google.com/testing",S_OK},
5875             {"google.com",S_OK},
5876             {"http://google.com/testing",S_OK},
5877             {"google.com",S_OK},
5878             {"",S_FALSE},
5879             {"",S_FALSE},
5880             {"google.com",S_OK},
5881             {"",S_FALSE},
5882             {"/testing",S_OK},
5883             {"/testing",S_OK},
5884             {"",S_FALSE},
5885             {"http://google.com/testing",S_OK},
5886             {"http",S_OK},
5887             {"",S_FALSE},
5888             {"",S_FALSE}
5889         },
5890         {
5891             {Uri_HOST_DNS,S_OK},
5892             {80,S_OK},
5893             {URL_SCHEME_HTTP,S_OK},
5894             {URLZONE_INVALID,E_NOTIMPL}
5895         }
5896     },
5897     {   "http://google.com/path",0,
5898         "/test/../test/.././testing",Uri_CREATE_ALLOW_RELATIVE,
5899         URL_DONT_SIMPLIFY,S_OK,FALSE,
5900         {
5901             {"http://google.com:80/test/../test/.././testing",S_OK},
5902             {"google.com",S_OK},
5903             {"http://google.com:80/test/../test/.././testing",S_OK},
5904             {"google.com",S_OK},
5905             {"",S_FALSE},
5906             {"",S_FALSE},
5907             {"google.com",S_OK},
5908             {"",S_FALSE},
5909             {"/test/../test/.././testing",S_OK},
5910             {"/test/../test/.././testing",S_OK},
5911             {"",S_FALSE},
5912             {"http://google.com:80/test/../test/.././testing",S_OK},
5913             {"http",S_OK},
5914             {"",S_FALSE},
5915             {"",S_FALSE}
5916         },
5917         {
5918             {Uri_HOST_DNS,S_OK},
5919             {80,S_OK},
5920             {URL_SCHEME_HTTP,S_OK},
5921             {URLZONE_INVALID,E_NOTIMPL}
5922         }
5923     },
5924     {   "http://winehq.org/test/abc",0,
5925         "testing/abc/../test",Uri_CREATE_ALLOW_RELATIVE,
5926         0,S_OK,FALSE,
5927         {
5928             {"http://winehq.org/test/testing/test",S_OK},
5929             {"winehq.org",S_OK},
5930             {"http://winehq.org/test/testing/test",S_OK},
5931             {"winehq.org",S_OK},
5932             {"",S_FALSE},
5933             {"",S_FALSE},
5934             {"winehq.org",S_OK},
5935             {"",S_FALSE},
5936             {"/test/testing/test",S_OK},
5937             {"/test/testing/test",S_OK},
5938             {"",S_FALSE},
5939             {"http://winehq.org/test/testing/test",S_OK},
5940             {"http",S_OK},
5941             {"",S_FALSE},
5942             {"",S_FALSE}
5943         },
5944         {
5945             {Uri_HOST_DNS,S_OK},
5946             {80,S_OK},
5947             {URL_SCHEME_HTTP,S_OK},
5948             {URLZONE_INVALID,E_NOTIMPL}
5949         }
5950     },
5951     {   "http://winehq.org/test/abc",0,
5952         "testing/abc/../test",Uri_CREATE_ALLOW_RELATIVE,
5953         URL_DONT_SIMPLIFY,S_OK,FALSE,
5954         {
5955             {"http://winehq.org:80/test/testing/abc/../test",S_OK},
5956             /* Default port is hidden in the authority. */
5957             {"winehq.org",S_OK},
5958             {"http://winehq.org:80/test/testing/abc/../test",S_OK},
5959             {"winehq.org",S_OK},
5960             {"",S_FALSE},
5961             {"",S_FALSE},
5962             {"winehq.org",S_OK},
5963             {"",S_FALSE},
5964             {"/test/testing/abc/../test",S_OK},
5965             {"/test/testing/abc/../test",S_OK},
5966             {"",S_FALSE},
5967             {"http://winehq.org:80/test/testing/abc/../test",S_OK},
5968             {"http",S_OK},
5969             {"",S_FALSE},
5970             {"",S_FALSE}
5971         },
5972         {
5973             {Uri_HOST_DNS,S_OK},
5974             {80,S_OK},
5975             {URL_SCHEME_HTTP,S_OK},
5976             {URLZONE_INVALID,E_NOTIMPL}
5977         }
5978     },
5979     {   "http://winehq.org/test?query",0,
5980         "testing",Uri_CREATE_ALLOW_RELATIVE,
5981         0,S_OK,FALSE,
5982         {
5983             {"http://winehq.org/testing",S_OK},
5984             {"winehq.org",S_OK},
5985             {"http://winehq.org/testing",S_OK},
5986             {"winehq.org",S_OK},
5987             {"",S_FALSE},
5988             {"",S_FALSE},
5989             {"winehq.org",S_OK},
5990             {"",S_FALSE},
5991             {"/testing",S_OK},
5992             {"/testing",S_OK},
5993             {"",S_FALSE},
5994             {"http://winehq.org/testing",S_OK},
5995             {"http",S_OK},
5996             {"",S_FALSE},
5997             {"",S_FALSE}
5998         },
5999         {
6000             {Uri_HOST_DNS,S_OK},
6001             {80,S_OK},
6002             {URL_SCHEME_HTTP,S_OK},
6003             {URLZONE_INVALID,E_NOTIMPL}
6004         }
6005     },
6006     {   "http://winehq.org/test#frag",0,
6007         "testing",Uri_CREATE_ALLOW_RELATIVE,
6008         0,S_OK,FALSE,
6009         {
6010             {"http://winehq.org/testing",S_OK},
6011             {"winehq.org",S_OK},
6012             {"http://winehq.org/testing",S_OK},
6013             {"winehq.org",S_OK},
6014             {"",S_FALSE},
6015             {"",S_FALSE},
6016             {"winehq.org",S_OK},
6017             {"",S_FALSE},
6018             {"/testing",S_OK},
6019             {"/testing",S_OK},
6020             {"",S_FALSE},
6021             {"http://winehq.org/testing",S_OK},
6022             {"http",S_OK},
6023             {"",S_FALSE},
6024             {"",S_FALSE}
6025         },
6026         {
6027             {Uri_HOST_DNS,S_OK},
6028             {80,S_OK},
6029             {URL_SCHEME_HTTP,S_OK},
6030             {URLZONE_INVALID,E_NOTIMPL}
6031         }
6032     },
6033     {   "testing?query#frag",Uri_CREATE_ALLOW_RELATIVE,
6034         "test",Uri_CREATE_ALLOW_RELATIVE,
6035         0,S_OK,FALSE,
6036         {
6037             {"test",S_OK},
6038             {"",S_FALSE},
6039             {"test",S_OK},
6040             {"",S_FALSE},
6041             {"",S_FALSE},
6042             {"",S_FALSE},
6043             {"",S_FALSE},
6044             {"",S_FALSE},
6045             {"test",S_OK},
6046             {"test",S_OK},
6047             {"",S_FALSE},
6048             {"test",S_OK},
6049             {"",S_FALSE},
6050             {"",S_FALSE},
6051             {"",S_FALSE}
6052         },
6053         {
6054             {Uri_HOST_UNKNOWN,S_OK},
6055             {0,S_FALSE},
6056             {URL_SCHEME_UNKNOWN,S_OK},
6057             {URLZONE_INVALID,E_NOTIMPL}
6058         }
6059     },
6060     {   "file:///c:/test/test",0,
6061         "/testing.mp3",Uri_CREATE_ALLOW_RELATIVE,
6062         URL_FILE_USE_PATHURL,S_OK,FALSE,
6063         {
6064             {"file://c:\\testing.mp3",S_OK},
6065             {"",S_FALSE},
6066             {"file://c:\\testing.mp3",S_OK},
6067             {"",S_FALSE},
6068             {".mp3",S_OK},
6069             {"",S_FALSE},
6070             {"",S_FALSE},
6071             {"",S_FALSE},
6072             {"c:\\testing.mp3",S_OK},
6073             {"c:\\testing.mp3",S_OK},
6074             {"",S_FALSE},
6075             {"file://c:\\testing.mp3",S_OK},
6076             {"file",S_OK},
6077             {"",S_FALSE},
6078             {"",S_FALSE}
6079         },
6080         {
6081             {Uri_HOST_UNKNOWN,S_OK},
6082             {0,S_FALSE},
6083             {URL_SCHEME_FILE,S_OK},
6084             {URLZONE_INVALID,E_NOTIMPL}
6085         }
6086     },
6087     {   "file:///c:/test/test",0,
6088         "/testing.mp3",Uri_CREATE_ALLOW_RELATIVE,
6089         0,S_OK,FALSE,
6090         {
6091             {"file:///c:/testing.mp3",S_OK},
6092             {"",S_FALSE},
6093             {"file:///c:/testing.mp3",S_OK},
6094             {"",S_FALSE},
6095             {".mp3",S_OK},
6096             {"",S_FALSE},
6097             {"",S_FALSE},
6098             {"",S_FALSE},
6099             {"/c:/testing.mp3",S_OK},
6100             {"/c:/testing.mp3",S_OK},
6101             {"",S_FALSE},
6102             {"file:///c:/testing.mp3",S_OK},
6103             {"file",S_OK},
6104             {"",S_FALSE},
6105             {"",S_FALSE}
6106         },
6107         {
6108             {Uri_HOST_UNKNOWN,S_OK},
6109             {0,S_FALSE},
6110             {URL_SCHEME_FILE,S_OK},
6111             {URLZONE_INVALID,E_NOTIMPL}
6112         }
6113     },
6114     {   "file://test.com/test/test",0,
6115         "/testing.mp3",Uri_CREATE_ALLOW_RELATIVE,
6116         URL_FILE_USE_PATHURL,S_OK,FALSE,
6117         {
6118             {"file://\\\\test.com\\testing.mp3",S_OK},
6119             {"test.com",S_OK},
6120             {"file://\\\\test.com\\testing.mp3",S_OK},
6121             {"test.com",S_OK},
6122             {".mp3",S_OK},
6123             {"",S_FALSE},
6124             {"test.com",S_OK},
6125             {"",S_FALSE},
6126             {"\\testing.mp3",S_OK},
6127             {"\\testing.mp3",S_OK},
6128             {"",S_FALSE},
6129             {"file://\\\\test.com\\testing.mp3",S_OK},
6130             {"file",S_OK},
6131             {"",S_FALSE},
6132             {"",S_FALSE}
6133         },
6134         {
6135             {Uri_HOST_DNS,S_OK},
6136             {0,S_FALSE},
6137             {URL_SCHEME_FILE,S_OK},
6138             {URLZONE_INVALID,E_NOTIMPL}
6139         }
6140     },
6141     /* URL_DONT_SIMPLIFY has no effect. */
6142     {   "http://google.com/test",0,
6143         "zip://test.com/cool/../cool/test",0,
6144         URL_DONT_SIMPLIFY,S_OK,FALSE,
6145         {
6146             {"zip://test.com/cool/test",S_OK,FALSE,NULL,"zip://test.com/cool/../cool/test"},
6147             {"test.com",S_OK},
6148             {"zip://test.com/cool/test",S_OK,FALSE,NULL,"zip://test.com/cool/../cool/test"},
6149             {"test.com",S_OK},
6150             {"",S_FALSE},
6151             {"",S_FALSE},
6152             {"test.com",S_OK},
6153             {"",S_FALSE},
6154             {"/cool/test",S_OK,FALSE,NULL,"/cool/../cool/test"},
6155             {"/cool/test",S_OK,FALSE,NULL,"/cool/../cool/test"},
6156             {"",S_FALSE},
6157             /* The resulting IUri has the same Raw URI as the relative URI (only IE 8).
6158              * On IE 7 it reduces the path in the Raw URI.
6159              */
6160             {"zip://test.com/cool/../cool/test",S_OK,FALSE,"zip://test.com/cool/test"},
6161             {"zip",S_OK},
6162             {"",S_FALSE},
6163             {"",S_FALSE}
6164         },
6165         {
6166             {Uri_HOST_DNS,S_OK},
6167             {0,S_FALSE},
6168             {URL_SCHEME_UNKNOWN,S_OK},
6169             {URLZONE_INVALID,E_NOTIMPL}
6170         }
6171     },
6172     /* FILE_USE_PATHURL has no effect in IE 8, in IE 7 the
6173      * resulting URI is converted into a dos path.
6174      */
6175     {   "http://google.com/test",0,
6176         "file:///c:/test/",0,
6177         URL_FILE_USE_PATHURL,S_OK,FALSE,
6178         {
6179             {"file:///c:/test/",S_OK,FALSE,"file://c:\\test\\"},
6180             {"",S_FALSE},
6181             {"file:///c:/test/",S_OK,FALSE,"file://c:\\test\\"},
6182             {"",S_FALSE},
6183             {"",S_FALSE},
6184             {"",S_FALSE},
6185             {"",S_FALSE},
6186             {"",S_FALSE},
6187             {"/c:/test/",S_OK,FALSE,"c:\\test\\"},
6188             {"/c:/test/",S_OK,FALSE,"c:\\test\\"},
6189             {"",S_FALSE},
6190             {"file:///c:/test/",S_OK,FALSE,"file://c:\\test\\"},
6191             {"file",S_OK},
6192             {"",S_FALSE},
6193             {"",S_FALSE}
6194         },
6195         {
6196             {Uri_HOST_UNKNOWN,S_OK},
6197             {0,S_FALSE},
6198             {URL_SCHEME_FILE,S_OK},
6199             {URLZONE_INVALID,E_NOTIMPL}
6200         }
6201     },
6202     {   "http://google.com/test",0,
6203         "http://test.com/test#%30test",0,
6204         URL_DONT_UNESCAPE_EXTRA_INFO,S_OK,FALSE,
6205         {
6206             {"http://test.com/test#0test",S_OK,FALSE,NULL,"http://test.com/test#%30test"},
6207             {"test.com",S_OK},
6208             {"http://test.com/test#0test",S_OK,FALSE,NULL,"http://test.com/test#%30test"},
6209             {"test.com",S_OK},
6210             {"",S_FALSE},
6211             {"#0test",S_OK,FALSE,NULL,"#%30test"},
6212             {"test.com",S_OK},
6213             {"",S_FALSE},
6214             {"/test",S_OK},
6215             {"/test",S_OK},
6216             {"",S_FALSE},
6217             /* IE 7 decodes the %30 to a 0 in the Raw URI. */
6218             {"http://test.com/test#%30test",S_OK,FALSE,"http://test.com/test#0test"},
6219             {"http",S_OK},
6220             {"",S_FALSE},
6221             {"",S_FALSE}
6222         },
6223         {
6224             {Uri_HOST_DNS,S_OK},
6225             {80,S_OK},
6226             {URL_SCHEME_HTTP,S_OK},
6227             {URLZONE_INVALID,E_NOTIMPL}
6228         }
6229     },
6230     /* Windows validates the path component from the relative Uri. */
6231     {   "http://google.com/test",0,
6232         "/Te%XXst",Uri_CREATE_ALLOW_RELATIVE,
6233         0,E_INVALIDARG,FALSE
6234     },
6235     /* Windows doesn't validate the query from the relative Uri. */
6236     {   "http://google.com/test",0,
6237         "?Tes%XXt",Uri_CREATE_ALLOW_RELATIVE,
6238         0,S_OK,FALSE,
6239         {
6240             {"http://google.com/test?Tes%XXt",S_OK},
6241             {"google.com",S_OK},
6242             {"http://google.com/test?Tes%XXt",S_OK},
6243             {"google.com",S_OK},
6244             {"",S_FALSE},
6245             {"",S_FALSE},
6246             {"google.com",S_OK},
6247             {"",S_FALSE},
6248             {"/test",S_OK},
6249             {"/test?Tes%XXt",S_OK},
6250             {"?Tes%XXt",S_OK},
6251             {"http://google.com/test?Tes%XXt",S_OK},
6252             {"http",S_OK},
6253             {"",S_FALSE},
6254             {"",S_FALSE}
6255         },
6256         {
6257             {Uri_HOST_DNS,S_OK},
6258             {80,S_OK},
6259             {URL_SCHEME_HTTP,S_OK},
6260             {URLZONE_INVALID,E_NOTIMPL}
6261         }
6262     },
6263     /* Windows doesn't validate the fragment from the relative Uri. */
6264     {   "http://google.com/test",0,
6265         "#Tes%XXt",Uri_CREATE_ALLOW_RELATIVE,
6266         0,S_OK,FALSE,
6267         {
6268             {"http://google.com/test#Tes%XXt",S_OK},
6269             {"google.com",S_OK},
6270             {"http://google.com/test#Tes%XXt",S_OK},
6271             {"google.com",S_OK},
6272             {"",S_FALSE},
6273             {"#Tes%XXt",S_OK},
6274             {"google.com",S_OK},
6275             {"",S_FALSE},
6276             {"/test",S_OK},
6277             {"/test",S_OK},
6278             {"",S_FALSE},
6279             {"http://google.com/test#Tes%XXt",S_OK},
6280             {"http",S_OK},
6281             {"",S_FALSE},
6282             {"",S_FALSE}
6283         },
6284         {
6285             {Uri_HOST_DNS,S_OK},
6286             {80,S_OK},
6287             {URL_SCHEME_HTTP,S_OK},
6288             {URLZONE_INVALID,E_NOTIMPL}
6289         }
6290     },
6291     /* Creates an IUri which contains an invalid dos path char. */
6292     {   "file:///c:/test",0,
6293         "/test<ing",Uri_CREATE_ALLOW_RELATIVE,
6294         URL_FILE_USE_PATHURL,S_OK,FALSE,
6295         {
6296             {"file://c:\\test<ing",S_OK},
6297             {"",S_FALSE},
6298             {"file://c:\\test<ing",S_OK},
6299             {"",S_FALSE},
6300             {"",S_FALSE},
6301             {"",S_FALSE},
6302             {"",S_FALSE},
6303             {"",S_FALSE},
6304             {"c:\\test<ing",S_OK},
6305             {"c:\\test<ing",S_OK},
6306             {"",S_FALSE},
6307             {"file://c:\\test<ing",S_OK},
6308             {"file",S_OK},
6309             {"",S_FALSE},
6310             {"",S_FALSE}
6311         },
6312         {
6313             {Uri_HOST_UNKNOWN,S_OK},
6314             {0,S_FALSE},
6315             {URL_SCHEME_FILE,S_OK},
6316             {URLZONE_INVALID,E_NOTIMPL}
6317         }
6318     },
6319     /* Appends the path after the drive letter (if any). */
6320     {   "file:///c:/test",0,
6321         "/c:/testing",Uri_CREATE_ALLOW_RELATIVE,
6322         0,S_OK,FALSE,
6323         {
6324             {"file:///c:/c:/testing",S_OK},
6325             {"",S_FALSE},
6326             {"file:///c:/c:/testing",S_OK},
6327             {"",S_FALSE},
6328             {"",S_FALSE},
6329             {"",S_FALSE},
6330             {"",S_FALSE},
6331             {"",S_FALSE},
6332             {"/c:/c:/testing",S_OK},
6333             {"/c:/c:/testing",S_OK},
6334             {"",S_FALSE},
6335             {"file:///c:/c:/testing",S_OK},
6336             {"file",S_OK},
6337             {"",S_FALSE},
6338             {"",S_FALSE}
6339         },
6340         {
6341             {Uri_HOST_UNKNOWN,S_OK},
6342             {0,S_FALSE},
6343             {URL_SCHEME_FILE,S_OK},
6344             {URLZONE_INVALID,E_NOTIMPL}
6345         }
6346     },
6347     /* A '/' is added if the base URI doesn't have a path and the
6348      * relative URI doesn't contain a path (since the base URI is
6349      * hierarchical.
6350      */
6351     {   "http://google.com",Uri_CREATE_NO_CANONICALIZE,
6352         "?test",Uri_CREATE_ALLOW_RELATIVE,
6353         0,S_OK,FALSE,
6354         {
6355             {"http://google.com/?test",S_OK},
6356             {"google.com",S_OK},
6357             {"http://google.com/?test",S_OK},
6358             {"google.com",S_OK},
6359             {"",S_FALSE},
6360             {"",S_FALSE},
6361             {"google.com",S_OK},
6362             {"",S_FALSE},
6363             {"/",S_OK},
6364             {"/?test",S_OK},
6365             {"?test",S_OK},
6366             {"http://google.com/?test",S_OK},
6367             {"http",S_OK},
6368             {"",S_FALSE},
6369             {"",S_FALSE}
6370         },
6371         {
6372             {Uri_HOST_DNS,S_OK},
6373             {80,S_OK},
6374             {URL_SCHEME_HTTP,S_OK},
6375             {URLZONE_INVALID,E_NOTIMPL}
6376         }
6377     },
6378     {   "zip://google.com",Uri_CREATE_NO_CANONICALIZE,
6379         "?test",Uri_CREATE_ALLOW_RELATIVE,
6380         0,S_OK,FALSE,
6381         {
6382             {"zip://google.com/?test",S_OK},
6383             {"google.com",S_OK},
6384             {"zip://google.com/?test",S_OK},
6385             {"google.com",S_OK},
6386             {"",S_FALSE},
6387             {"",S_FALSE},
6388             {"google.com",S_OK},
6389             {"",S_FALSE},
6390             {"/",S_OK},
6391             {"/?test",S_OK},
6392             {"?test",S_OK},
6393             {"zip://google.com/?test",S_OK},
6394             {"zip",S_OK},
6395             {"",S_FALSE},
6396             {"",S_FALSE}
6397         },
6398         {
6399             {Uri_HOST_DNS,S_OK},
6400             {0,S_FALSE},
6401             {URL_SCHEME_UNKNOWN,S_OK},
6402             {URLZONE_INVALID,E_NOTIMPL}
6403         }
6404     },
6405     /* No path is appended since the base URI is opaque. */
6406     {   "zip:?testing",0,
6407         "?test",Uri_CREATE_ALLOW_RELATIVE,
6408         0,S_OK,FALSE,
6409         {
6410             {"zip:?test",S_OK},
6411             {"",S_FALSE},
6412             {"zip:?test",S_OK},
6413             {"",S_FALSE},
6414             {"",S_FALSE},
6415             {"",S_FALSE},
6416             {"",S_FALSE},
6417             {"",S_FALSE},
6418             {"",S_OK},
6419             {"?test",S_OK},
6420             {"?test",S_OK},
6421             {"zip:?test",S_OK},
6422             {"zip",S_OK},
6423             {"",S_FALSE},
6424             {"",S_FALSE}
6425         },
6426         {
6427             {Uri_HOST_UNKNOWN,S_OK},
6428             {0,S_FALSE},
6429             {URL_SCHEME_UNKNOWN,S_OK},
6430             {URLZONE_INVALID,E_NOTIMPL}
6431         }
6432     },
6433     {   "file:///c:/",0,
6434         "../testing/test",Uri_CREATE_ALLOW_RELATIVE,
6435         0,S_OK,FALSE,
6436         {
6437             {"file:///c:/testing/test",S_OK},
6438             {"",S_FALSE},
6439             {"file:///c:/testing/test",S_OK},
6440             {"",S_FALSE},
6441             {"",S_FALSE},
6442             {"",S_FALSE},
6443             {"",S_FALSE},
6444             {"",S_FALSE},
6445             {"/c:/testing/test",S_OK},
6446             {"/c:/testing/test",S_OK},
6447             {"",S_FALSE},
6448             {"file:///c:/testing/test",S_OK},
6449             {"file",S_OK},
6450             {"",S_FALSE},
6451             {"",S_FALSE}
6452         },
6453         {
6454             {Uri_HOST_UNKNOWN,S_OK},
6455             {0,S_FALSE},
6456             {URL_SCHEME_FILE,S_OK},
6457             {URLZONE_INVALID,E_NOTIMPL}
6458         }
6459     },
6460     {   "http://winehq.org/dir/testfile",0,
6461         "test?querystring",Uri_CREATE_ALLOW_RELATIVE,
6462         0,S_OK,FALSE,
6463         {
6464             {"http://winehq.org/dir/test?querystring",S_OK},
6465             {"winehq.org",S_OK},
6466             {"http://winehq.org/dir/test?querystring",S_OK},
6467             {"winehq.org",S_OK},
6468             {"",S_FALSE},
6469             {"",S_FALSE},
6470             {"winehq.org",S_OK},
6471             {"",S_FALSE},
6472             {"/dir/test",S_OK},
6473             {"/dir/test?querystring",S_OK},
6474             {"?querystring",S_OK},
6475             {"http://winehq.org/dir/test?querystring",S_OK},
6476             {"http",S_OK},
6477             {"",S_FALSE},
6478             {"",S_FALSE}
6479         },
6480         {
6481             {Uri_HOST_DNS,S_OK},
6482             {80,S_OK},
6483             {URL_SCHEME_HTTP,S_OK},
6484             {URLZONE_INVALID,E_NOTIMPL}
6485         }
6486     },
6487     {   "http://winehq.org/dir/test",0,
6488         "test?querystring",Uri_CREATE_ALLOW_RELATIVE,
6489         0,S_OK,FALSE,
6490         {
6491             {"http://winehq.org/dir/test?querystring",S_OK},
6492             {"winehq.org",S_OK},
6493             {"http://winehq.org/dir/test?querystring",S_OK},
6494             {"winehq.org",S_OK},
6495             {"",S_FALSE},
6496             {"",S_FALSE},
6497             {"winehq.org",S_OK},
6498             {"",S_FALSE},
6499             {"/dir/test",S_OK},
6500             {"/dir/test?querystring",S_OK},
6501             {"?querystring",S_OK},
6502             {"http://winehq.org/dir/test?querystring",S_OK},
6503             {"http",S_OK},
6504             {"",S_FALSE},
6505             {"",S_FALSE}
6506         },
6507         {
6508             {Uri_HOST_DNS,S_OK},
6509             {80,S_OK},
6510             {URL_SCHEME_HTTP,S_OK},
6511             {URLZONE_INVALID,E_NOTIMPL}
6512         }
6513     },
6514     {   "http://winehq.org/dir/test?querystring",0,
6515         "#hash",Uri_CREATE_ALLOW_RELATIVE,
6516         0,S_OK,FALSE,
6517         {
6518             {"http://winehq.org/dir/test?querystring#hash",S_OK},
6519             {"winehq.org",S_OK},
6520             {"http://winehq.org/dir/test?querystring#hash",S_OK},
6521             {"winehq.org",S_OK},
6522             {"",S_FALSE},
6523             {"#hash",S_OK},
6524             {"winehq.org",S_OK},
6525             {"",S_FALSE},
6526             {"/dir/test",S_OK},
6527             {"/dir/test?querystring",S_OK},
6528             {"?querystring",S_OK},
6529             {"http://winehq.org/dir/test?querystring#hash",S_OK},
6530             {"http",S_OK},
6531             {"",S_FALSE},
6532             {"",S_FALSE}
6533         },
6534         {
6535             {Uri_HOST_DNS,S_OK},
6536             {80,S_OK},
6537             {URL_SCHEME_HTTP,S_OK},
6538             {URLZONE_INVALID,E_NOTIMPL}
6539         }
6540     },
6541     {   "mk:@MSITSTORE:C:\\Some\\Bogus\\Path.chm::/subdir\\file.txt",0,
6542         "relative/path.txt",Uri_CREATE_ALLOW_RELATIVE,
6543         0,S_OK,FALSE,
6544         {
6545             {"mk:@MSITSTORE:C:\\Some\\Bogus\\Path.chm::/subdir/relative/path.txt",S_OK},
6546             {"",S_FALSE},
6547             {"mk:@MSITSTORE:C:\\Some\\Bogus\\Path.chm::/subdir/relative/path.txt",S_OK},
6548             {"",S_FALSE},
6549             {".txt",S_OK},
6550             {"",S_FALSE},
6551             {"",S_FALSE},
6552             {"",S_FALSE},
6553             {"@MSITSTORE:C:\\Some\\Bogus\\Path.chm::/subdir/relative/path.txt",S_OK},
6554             {"@MSITSTORE:C:\\Some\\Bogus\\Path.chm::/subdir/relative/path.txt",S_OK},
6555             {"",S_FALSE},
6556             {"mk:@MSITSTORE:C:\\Some\\Bogus\\Path.chm::/subdir/relative/path.txt",S_OK},
6557             {"mk",S_OK},
6558             {"",S_FALSE},
6559             {"",S_FALSE}
6560         },
6561         {
6562             {Uri_HOST_UNKNOWN,S_OK},
6563             {0,S_FALSE},
6564             {URL_SCHEME_MK,S_OK},
6565             {URLZONE_INVALID,E_NOTIMPL}
6566         }
6567     },
6568     {   "mk:@MSITSTORE:C:\\Some\\Bogus\\Path.chm::\\subdir\\file.txt",0,
6569         "relative/path.txt",Uri_CREATE_ALLOW_RELATIVE,
6570         0,S_OK,FALSE,
6571         {
6572             {"mk:@MSITSTORE:C:\\Some\\Bogus\\Path.chm::/subdir/relative/path.txt",S_OK},
6573             {"",S_FALSE},
6574             {"mk:@MSITSTORE:C:\\Some\\Bogus\\Path.chm::/subdir/relative/path.txt",S_OK},
6575             {"",S_FALSE},
6576             {".txt",S_OK},
6577             {"",S_FALSE},
6578             {"",S_FALSE},
6579             {"",S_FALSE},
6580             {"@MSITSTORE:C:\\Some\\Bogus\\Path.chm::/subdir/relative/path.txt",S_OK},
6581             {"@MSITSTORE:C:\\Some\\Bogus\\Path.chm::/subdir/relative/path.txt",S_OK},
6582             {"",S_FALSE},
6583             {"mk:@MSITSTORE:C:\\Some\\Bogus\\Path.chm::/subdir/relative/path.txt",S_OK},
6584             {"mk",S_OK},
6585             {"",S_FALSE},
6586             {"",S_FALSE}
6587         },
6588         {
6589             {Uri_HOST_UNKNOWN,S_OK},
6590             {0,S_FALSE},
6591             {URL_SCHEME_MK,S_OK},
6592             {URLZONE_INVALID,E_NOTIMPL}
6593         }
6594     },
6595     {   "mk:@MSITSTORE:C:/Some\\Bogus/Path.chm::/subdir\\file.txt",0,
6596         "relative\\path.txt",Uri_CREATE_ALLOW_RELATIVE,
6597         0,S_OK,FALSE,
6598         {
6599             {"mk:@MSITSTORE:C:/Some\\Bogus/Path.chm::/subdir/relative/path.txt",S_OK},
6600             {"",S_FALSE},
6601             {"mk:@MSITSTORE:C:/Some\\Bogus/Path.chm::/subdir/relative/path.txt",S_OK},
6602             {"",S_FALSE},
6603             {".txt",S_OK},
6604             {"",S_FALSE},
6605             {"",S_FALSE},
6606             {"",S_FALSE},
6607             {"@MSITSTORE:C:/Some\\Bogus/Path.chm::/subdir/relative/path.txt",S_OK},
6608             {"@MSITSTORE:C:/Some\\Bogus/Path.chm::/subdir/relative/path.txt",S_OK},
6609             {"",S_FALSE},
6610             {"mk:@MSITSTORE:C:/Some\\Bogus/Path.chm::/subdir/relative/path.txt",S_OK},
6611             {"mk",S_OK},
6612             {"",S_FALSE},
6613             {"",S_FALSE}
6614         },
6615         {
6616             {Uri_HOST_UNKNOWN,S_OK},
6617             {0,S_FALSE},
6618             {URL_SCHEME_MK,S_OK},
6619             {URLZONE_INVALID,E_NOTIMPL}
6620         }
6621     }
6622 };
6623
6624 typedef struct _uri_parse_test {
6625     const char  *uri;
6626     DWORD       uri_flags;
6627     PARSEACTION action;
6628     DWORD       flags;
6629     const char  *property;
6630     HRESULT     expected;
6631     BOOL        todo;
6632 } uri_parse_test;
6633
6634 static const uri_parse_test uri_parse_tests[] = {
6635     /* PARSE_CANONICALIZE tests. */
6636     {"zip://google.com/test<|>",0,PARSE_CANONICALIZE,0,"zip://google.com/test<|>",S_OK,FALSE},
6637     {"http://google.com/test<|>",0,PARSE_CANONICALIZE,0,"http://google.com/test%3C%7C%3E",S_OK,FALSE},
6638     {"http://google.com/%30%23%3F",0,PARSE_CANONICALIZE,URL_UNESCAPE,"http://google.com/0#?",S_OK,FALSE},
6639     {"test <|>",Uri_CREATE_ALLOW_RELATIVE,PARSE_CANONICALIZE,URL_ESCAPE_UNSAFE,"test %3C%7C%3E",S_OK,FALSE},
6640     {"test <|>",Uri_CREATE_ALLOW_RELATIVE,PARSE_CANONICALIZE,URL_ESCAPE_SPACES_ONLY,"test%20<|>",S_OK,FALSE},
6641     {"test%20<|>",Uri_CREATE_ALLOW_RELATIVE,PARSE_CANONICALIZE,URL_UNESCAPE|URL_ESCAPE_UNSAFE,"test%20%3C%7C%3E",S_OK,FALSE},
6642     {"http://google.com/%20",0,PARSE_CANONICALIZE,URL_ESCAPE_PERCENT,"http://google.com/%2520",S_OK,FALSE},
6643     {"http://google.com/test/../",Uri_CREATE_NO_CANONICALIZE,PARSE_CANONICALIZE,URL_DONT_SIMPLIFY,"http://google.com/test/../",S_OK,FALSE},
6644     {"http://google.com/test/../",Uri_CREATE_NO_CANONICALIZE,PARSE_CANONICALIZE,URL_NO_META,"http://google.com/test/../",S_OK,FALSE},
6645     {"http://google.com/test/../",Uri_CREATE_NO_CANONICALIZE,PARSE_CANONICALIZE,0,"http://google.com/",S_OK,FALSE},
6646     {"zip://google.com/test/../",Uri_CREATE_NO_CANONICALIZE,PARSE_CANONICALIZE,0,"zip://google.com/",S_OK,FALSE},
6647     {"file:///c:/test/../test",Uri_CREATE_NO_CANONICALIZE,PARSE_CANONICALIZE,URL_DONT_SIMPLIFY,"file:///c:/test/../test",S_OK,FALSE},
6648
6649     /* PARSE_FRIENDLY tests. */
6650     {"http://test@google.com/test#test",0,PARSE_FRIENDLY,0,"http://google.com/test#test",S_OK,FALSE},
6651     {"zip://test@google.com/test",0,PARSE_FRIENDLY,0,"zip://test@google.com/test",S_OK,FALSE},
6652
6653     /* PARSE_ROOTDOCUMENT tests. */
6654     {"http://google.com:200/test/test",0,PARSE_ROOTDOCUMENT,0,"http://google.com:200/",S_OK,FALSE},
6655     {"http://google.com",Uri_CREATE_NO_CANONICALIZE,PARSE_ROOTDOCUMENT,0,"http://google.com/",S_OK,FALSE},
6656     {"zip://google.com/",0,PARSE_ROOTDOCUMENT,0,"",S_OK,FALSE},
6657     {"file:///c:/testing/",0,PARSE_ROOTDOCUMENT,0,"",S_OK,FALSE},
6658     {"file://server/test",0,PARSE_ROOTDOCUMENT,0,"",S_OK,FALSE},
6659     {"zip:test/test",0,PARSE_ROOTDOCUMENT,0,"",S_OK,FALSE},
6660
6661     /* PARSE_DOCUMENT tests. */
6662     {"http://test@google.com/test?query#frag",0,PARSE_DOCUMENT,0,"http://test@google.com/test?query",S_OK,FALSE},
6663     {"http:testing#frag",0,PARSE_DOCUMENT,0,"",S_OK,FALSE},
6664     {"file:///c:/test#frag",0,PARSE_DOCUMENT,0,"",S_OK,FALSE},
6665     {"zip://google.com/#frag",0,PARSE_DOCUMENT,0,"",S_OK,FALSE},
6666     {"zip:test#frag",0,PARSE_DOCUMENT,0,"",S_OK,FALSE},
6667     {"testing#frag",Uri_CREATE_ALLOW_RELATIVE,PARSE_DOCUMENT,0,"",S_OK,FALSE},
6668
6669     /* PARSE_PATH_FROM_URL tests. */
6670     {"file:///c:/test.mp3",0,PARSE_PATH_FROM_URL,0,"c:\\test.mp3",S_OK,FALSE},
6671     {"file:///c:/t<|>est.mp3",0,PARSE_PATH_FROM_URL,0,"c:\\t<|>est.mp3",S_OK,FALSE},
6672     {"file:///c:/te%XX t/",0,PARSE_PATH_FROM_URL,0,"c:\\te%XX t\\",S_OK,FALSE},
6673     {"file://server/test",0,PARSE_PATH_FROM_URL,0,"\\\\server\\test",S_OK,FALSE},
6674     {"http://google.com/",0,PARSE_PATH_FROM_URL,0,"",E_INVALIDARG,FALSE},
6675
6676     /* PARSE_URL_FROM_PATH tests. */
6677     /* This function almost seems to useless (just returns the absolute uri). */
6678     {"test.com",Uri_CREATE_ALLOW_RELATIVE,PARSE_URL_FROM_PATH,0,"test.com",S_OK,FALSE},
6679     {"/test/test",Uri_CREATE_ALLOW_RELATIVE,PARSE_URL_FROM_PATH,0,"/test/test",S_OK,FALSE},
6680     {"file://c:\\test\\test",Uri_CREATE_FILE_USE_DOS_PATH,PARSE_URL_FROM_PATH,0,"file://c:\\test\\test",S_OK,FALSE},
6681     {"file:c:/test",0,PARSE_URL_FROM_PATH,0,"",S_OK,FALSE},
6682     {"http:google.com/",0,PARSE_URL_FROM_PATH,0,"",S_OK,FALSE},
6683
6684     /* PARSE_SCHEMA tests. */
6685     {"http://google.com/test",0,PARSE_SCHEMA,0,"http",S_OK,FALSE},
6686     {"test",Uri_CREATE_ALLOW_RELATIVE,PARSE_SCHEMA,0,"",S_OK,FALSE},
6687
6688     /* PARSE_SITE tests. */
6689     {"http://google.uk.com/",0,PARSE_SITE,0,"google.uk.com",S_OK,FALSE},
6690     {"http://google.com.com/",0,PARSE_SITE,0,"google.com.com",S_OK,FALSE},
6691     {"google.com",Uri_CREATE_ALLOW_RELATIVE,PARSE_SITE,0,"",S_OK,FALSE},
6692     {"file://server/test",0,PARSE_SITE,0,"server",S_OK,FALSE},
6693
6694     /* PARSE_DOMAIN tests. */
6695     {"http://google.com.uk/",0,PARSE_DOMAIN,0,"google.com.uk",S_OK,FALSE},
6696     {"http://google.com.com/",0,PARSE_DOMAIN,0,"com.com",S_OK,FALSE},
6697     {"test/test",Uri_CREATE_ALLOW_RELATIVE,PARSE_DOMAIN,0,"",S_OK,FALSE},
6698     {"file://server/test",0,PARSE_DOMAIN,0,"",S_OK,FALSE},
6699
6700     /* PARSE_LOCATION and PARSE_ANCHOR tests. */
6701     {"http://google.com/test#Test",0,PARSE_ANCHOR,0,"#Test",S_OK,FALSE},
6702     {"http://google.com/test#Test",0,PARSE_LOCATION,0,"#Test",S_OK,FALSE},
6703     {"test",Uri_CREATE_ALLOW_RELATIVE,PARSE_ANCHOR,0,"",S_OK,FALSE},
6704     {"test",Uri_CREATE_ALLOW_RELATIVE,PARSE_LOCATION,0,"",S_OK,FALSE}
6705 };
6706
6707 static inline LPWSTR a2w(LPCSTR str) {
6708     LPWSTR ret = NULL;
6709
6710     if(str) {
6711         DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
6712         ret = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
6713         MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len);
6714     }
6715
6716     return ret;
6717 }
6718
6719 static inline BOOL heap_free(void* mem) {
6720     return HeapFree(GetProcessHeap(), 0, mem);
6721 }
6722
6723 static inline DWORD strcmp_aw(LPCSTR strA, LPCWSTR strB) {
6724     LPWSTR strAW = a2w(strA);
6725     DWORD ret = lstrcmpW(strAW, strB);
6726     heap_free(strAW);
6727     return ret;
6728 }
6729
6730 static inline ULONG get_refcnt(IUri *uri) {
6731     IUri_AddRef(uri);
6732     return IUri_Release(uri);
6733 }
6734
6735 static void change_property(IUriBuilder *builder, const uri_builder_property *prop,
6736                             DWORD test_index) {
6737     HRESULT hr;
6738     LPWSTR valueW;
6739
6740     valueW = a2w(prop->value);
6741     switch(prop->property) {
6742     case Uri_PROPERTY_FRAGMENT:
6743         hr = IUriBuilder_SetFragment(builder, valueW);
6744         if(prop->todo) {
6745             todo_wine {
6746                 ok(hr == prop->expected,
6747                     "Error: IUriBuilder_SetFragment returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6748                     hr, prop->expected, test_index);
6749             }
6750         } else {
6751             ok(hr == prop->expected,
6752                 "Error: IUriBuilder_SetFragment returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6753                 hr, prop->expected, test_index);
6754         }
6755         break;
6756     case Uri_PROPERTY_HOST:
6757         hr = IUriBuilder_SetHost(builder, valueW);
6758         if(prop->todo) {
6759             todo_wine {
6760                 ok(hr == prop->expected,
6761                     "Error: IUriBuilder_SetHost returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6762                     hr, prop->expected, test_index);
6763             }
6764         } else {
6765             ok(hr == prop->expected,
6766                 "Error: IUriBuilder_SetHost returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6767                 hr, prop->expected, test_index);
6768         }
6769         break;
6770     case Uri_PROPERTY_PASSWORD:
6771         hr = IUriBuilder_SetPassword(builder, valueW);
6772         if(prop->todo) {
6773             todo_wine {
6774                 ok(hr == prop->expected,
6775                     "Error: IUriBuilder_SetPassword returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6776                     hr, prop->expected, test_index);
6777             }
6778         } else {
6779             ok(hr == prop->expected,
6780                 "Error: IUriBuilder_SetPassword returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6781                 hr, prop->expected, test_index);
6782         }
6783         break;
6784     case Uri_PROPERTY_PATH:
6785         hr = IUriBuilder_SetPath(builder, valueW);
6786         if(prop->todo) {
6787             todo_wine {
6788                 ok(hr == prop->expected,
6789                     "Error: IUriBuilder_SetPath returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6790                     hr, prop->expected, test_index);
6791             }
6792         } else {
6793             ok(hr == prop->expected,
6794                 "Error: IUriBuilder_SetPath returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6795                 hr, prop->expected, test_index);
6796         }
6797         break;
6798     case Uri_PROPERTY_QUERY:
6799         hr = IUriBuilder_SetQuery(builder, valueW);
6800         if(prop->todo) {
6801             todo_wine {
6802                 ok(hr == prop->expected,
6803                     "Error: IUriBuilder_SetQuery returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6804                     hr, prop->expected, test_index);
6805             }
6806         } else {
6807             ok(hr == prop->expected,
6808                 "Error: IUriBuilder_SetQuery returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6809                 hr, prop->expected, test_index);
6810         }
6811         break;
6812     case Uri_PROPERTY_SCHEME_NAME:
6813         hr = IUriBuilder_SetSchemeName(builder, valueW);
6814         if(prop->todo) {
6815             todo_wine {
6816                 ok(hr == prop->expected,
6817                     "Error: IUriBuilder_SetSchemeName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6818                     hr, prop->expected, test_index);
6819             }
6820         } else {
6821             ok(hr == prop->expected,
6822                 "Error: IUriBuilder_SetSchemeName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6823                 hr, prop->expected, test_index);
6824         }
6825         break;
6826     case Uri_PROPERTY_USER_NAME:
6827         hr = IUriBuilder_SetUserName(builder, valueW);
6828         if(prop->todo) {
6829             todo_wine {
6830                 ok(hr == prop->expected,
6831                     "Error: IUriBuilder_SetUserName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6832                     hr, prop->expected, test_index);
6833             }
6834         } else {
6835             ok(hr == prop->expected,
6836                 "Error: IUriBuilder_SetUserName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
6837                 hr, prop->expected, test_index);
6838         }
6839         break;
6840     default:
6841         trace("Unsupported operation for %d on uri_builder_tests[%d].\n", prop->property, test_index);
6842     }
6843
6844     heap_free(valueW);
6845 }
6846
6847 /*
6848  * Simple tests to make sure the CreateUri function handles invalid flag combinations
6849  * correctly.
6850  */
6851 static void test_CreateUri_InvalidFlags(void) {
6852     DWORD i;
6853
6854     for(i = 0; i < sizeof(invalid_flag_tests)/sizeof(invalid_flag_tests[0]); ++i) {
6855         HRESULT hr;
6856         IUri *uri = (void*) 0xdeadbeef;
6857
6858         hr = pCreateUri(http_urlW, invalid_flag_tests[i].flags, 0, &uri);
6859         ok(hr == invalid_flag_tests[i].expected, "Error: CreateUri returned 0x%08x, expected 0x%08x, flags=0x%08x\n",
6860                 hr, invalid_flag_tests[i].expected, invalid_flag_tests[i].flags);
6861         ok(uri == NULL, "Error: expected the IUri to be NULL, but it was %p instead\n", uri);
6862     }
6863 }
6864
6865 static void test_CreateUri_InvalidArgs(void) {
6866     HRESULT hr;
6867     IUri *uri = (void*) 0xdeadbeef;
6868
6869     const WCHAR invalidW[] = {'i','n','v','a','l','i','d',0};
6870     static const WCHAR emptyW[] = {0};
6871
6872     hr = pCreateUri(http_urlW, 0, 0, NULL);
6873     ok(hr == E_INVALIDARG, "Error: CreateUri returned 0x%08x, expected 0x%08x\n", hr, E_INVALIDARG);
6874
6875     hr = pCreateUri(NULL, 0, 0, &uri);
6876     ok(hr == E_INVALIDARG, "Error: CreateUri returned 0x%08x, expected 0x%08x\n", hr, E_INVALIDARG);
6877     ok(uri == NULL, "Error: Expected the IUri to be NULL, but it was %p instead\n", uri);
6878
6879     uri = (void*) 0xdeadbeef;
6880     hr = pCreateUri(invalidW, 0, 0, &uri);
6881     ok(hr == E_INVALIDARG, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
6882     ok(uri == NULL, "Error: Expected the IUri to be NULL, but it was %p instead\n", uri);
6883
6884     uri = (void*) 0xdeadbeef;
6885     hr = pCreateUri(emptyW, 0, 0, &uri);
6886     ok(hr == E_INVALIDARG, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
6887     ok(uri == NULL, "Error: Expected the IUri to be NULL, but it was %p instead\n", uri);
6888 }
6889
6890 static void test_CreateUri_InvalidUri(void) {
6891     DWORD i;
6892
6893     for(i = 0; i < sizeof(invalid_uri_tests)/sizeof(invalid_uri_tests[0]); ++i) {
6894         invalid_uri test = invalid_uri_tests[i];
6895         IUri *uri = NULL;
6896         LPWSTR uriW;
6897         HRESULT hr;
6898
6899         uriW = a2w(test.uri);
6900         hr = pCreateUri(uriW, test.flags, 0, &uri);
6901         if(test.todo) {
6902             todo_wine {
6903                 ok(hr == E_INVALIDARG, "Error: CreateUri returned 0x%08x, expected 0x%08x on invalid_uri_tests[%d].\n",
6904                     hr, E_INVALIDARG, i);
6905             }
6906         } else {
6907             ok(hr == E_INVALIDARG, "Error: CreateUri returned 0x%08x, expected 0x%08x on invalid_uri_tests[%d].\n",
6908                 hr, E_INVALIDARG, i);
6909         }
6910         if(uri) IUri_Release(uri);
6911
6912         heap_free(uriW);
6913     }
6914 }
6915
6916 static void test_IUri_GetPropertyBSTR(void) {
6917     IUri *uri = NULL;
6918     HRESULT hr;
6919     DWORD i;
6920
6921     /* Make sure GetPropertyBSTR handles invalid args correctly. */
6922     hr = pCreateUri(http_urlW, 0, 0, &uri);
6923     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
6924     if(SUCCEEDED(hr)) {
6925         BSTR received = NULL;
6926
6927         hr = IUri_GetPropertyBSTR(uri, Uri_PROPERTY_RAW_URI, NULL, 0);
6928         ok(hr == E_POINTER, "Error: GetPropertyBSTR returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
6929
6930         /* Make sure it handles a invalid Uri_PROPERTY's correctly. */
6931         hr = IUri_GetPropertyBSTR(uri, Uri_PROPERTY_PORT, &received, 0);
6932         ok(hr == S_OK, "Error: GetPropertyBSTR returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
6933         ok(received != NULL, "Error: Expected the string not to be NULL.\n");
6934         ok(!SysStringLen(received), "Error: Expected the string to be of len=0 but it was %d instead.\n", SysStringLen(received));
6935         SysFreeString(received);
6936
6937         /* Make sure it handles the ZONE property correctly. */
6938         received = NULL;
6939         hr = IUri_GetPropertyBSTR(uri, Uri_PROPERTY_ZONE, &received, 0);
6940         ok(hr == S_FALSE, "Error: GetPropertyBSTR returned 0x%08x, expected 0x%08x.\n", hr, S_FALSE);
6941         ok(received != NULL, "Error: Expected the string not to be NULL.\n");
6942         ok(!SysStringLen(received), "Error: Expected the string to be of len=0 but it was %d instead.\n", SysStringLen(received));
6943         SysFreeString(received);
6944     }
6945     if(uri) IUri_Release(uri);
6946
6947     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
6948         uri_properties test = uri_tests[i];
6949         LPWSTR uriW;
6950         uri = NULL;
6951
6952         uriW = a2w(test.uri);
6953         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
6954         if(test.create_todo) {
6955             todo_wine {
6956                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x. Failed on uri_tests[%d].\n",
6957                         hr, test.create_expected, i);
6958             }
6959         } else {
6960             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x. Failed on uri_tests[%d].\n",
6961                     hr, test.create_expected, i);
6962         }
6963
6964         if(SUCCEEDED(hr)) {
6965             DWORD j;
6966
6967             /* Checks all the string properties of the uri. */
6968             for(j = Uri_PROPERTY_STRING_START; j <= Uri_PROPERTY_STRING_LAST; ++j) {
6969                 BSTR received = NULL;
6970                 uri_str_property prop = test.str_props[j];
6971
6972                 hr = IUri_GetPropertyBSTR(uri, j, &received, 0);
6973                 if(prop.todo) {
6974                     todo_wine {
6975                         ok(hr == prop.expected, "GetPropertyBSTR returned 0x%08x, expected 0x%08x. On uri_tests[%d].str_props[%d].\n",
6976                                 hr, prop.expected, i, j);
6977                     }
6978                     todo_wine {
6979                         ok(!strcmp_aw(prop.value, received) || broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
6980                                 "Expected %s but got %s on uri_tests[%d].str_props[%d].\n",
6981                                 prop.value, wine_dbgstr_w(received), i, j);
6982                     }
6983                 } else {
6984                     ok(hr == prop.expected, "GetPropertyBSTR returned 0x%08x, expected 0x%08x. On uri_tests[%d].str_props[%d].\n",
6985                             hr, prop.expected, i, j);
6986                     ok(!strcmp_aw(prop.value, received) || broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
6987                             "Expected %s but got %s on uri_tests[%d].str_props[%d].\n",
6988                             prop.value, wine_dbgstr_w(received), i, j);
6989                 }
6990
6991                 SysFreeString(received);
6992             }
6993         }
6994
6995         if(uri) IUri_Release(uri);
6996
6997         heap_free(uriW);
6998     }
6999 }
7000
7001 static void test_IUri_GetPropertyDWORD(void) {
7002     IUri *uri = NULL;
7003     HRESULT hr;
7004     DWORD i;
7005
7006     hr = pCreateUri(http_urlW, 0, 0, &uri);
7007     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7008     if(SUCCEEDED(hr)) {
7009         DWORD received = 0xdeadbeef;
7010
7011         hr = IUri_GetPropertyDWORD(uri, Uri_PROPERTY_DWORD_START, NULL, 0);
7012         ok(hr == E_INVALIDARG, "Error: GetPropertyDWORD returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
7013
7014         hr = IUri_GetPropertyDWORD(uri, Uri_PROPERTY_ABSOLUTE_URI, &received, 0);
7015         ok(hr == E_INVALIDARG, "Error: GetPropertyDWORD returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
7016         ok(received == 0, "Error: Expected received=%d but instead received=%d.\n", 0, received);
7017     }
7018     if(uri) IUri_Release(uri);
7019
7020     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
7021         uri_properties test = uri_tests[i];
7022         LPWSTR uriW;
7023         uri = NULL;
7024
7025         uriW = a2w(test.uri);
7026         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
7027         if(test.create_todo) {
7028             todo_wine {
7029                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x. Failed on uri_tests[%d].\n",
7030                         hr, test.create_expected, i);
7031             }
7032         } else {
7033             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x. Failed on uri_tests[%d].\n",
7034                     hr, test.create_expected, i);
7035         }
7036
7037         if(SUCCEEDED(hr)) {
7038             DWORD j;
7039
7040             /* Checks all the DWORD properties of the uri. */
7041             for(j = 0; j < sizeof(test.dword_props)/sizeof(test.dword_props[0]); ++j) {
7042                 DWORD received;
7043                 uri_dword_property prop = test.dword_props[j];
7044
7045                 hr = IUri_GetPropertyDWORD(uri, j+Uri_PROPERTY_DWORD_START, &received, 0);
7046                 if(prop.todo) {
7047                     todo_wine {
7048                         ok(hr == prop.expected, "GetPropertyDWORD returned 0x%08x, expected 0x%08x. On uri_tests[%d].dword_props[%d].\n",
7049                                 hr, prop.expected, i, j);
7050                     }
7051                     todo_wine {
7052                         ok(prop.value == received, "Expected %d but got %d on uri_tests[%d].dword_props[%d].\n",
7053                                 prop.value, received, i, j);
7054                     }
7055                 } else {
7056                     ok(hr == prop.expected, "GetPropertyDWORD returned 0x%08x, expected 0x%08x. On uri_tests[%d].dword_props[%d].\n",
7057                             hr, prop.expected, i, j);
7058                     ok(prop.value == received, "Expected %d but got %d on uri_tests[%d].dword_props[%d].\n",
7059                             prop.value, received, i, j);
7060                 }
7061             }
7062         }
7063
7064         if(uri) IUri_Release(uri);
7065
7066         heap_free(uriW);
7067     }
7068 }
7069
7070 /* Tests all the 'Get*' property functions which deal with strings. */
7071 static void test_IUri_GetStrProperties(void) {
7072     IUri *uri = NULL;
7073     HRESULT hr;
7074     DWORD i;
7075
7076     /* Make sure all the 'Get*' string property functions handle invalid args correctly. */
7077     hr = pCreateUri(http_urlW, 0, 0, &uri);
7078     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7079     if(SUCCEEDED(hr)) {
7080         hr = IUri_GetAbsoluteUri(uri, NULL);
7081         ok(hr == E_POINTER, "Error: GetAbsoluteUri returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
7082
7083         hr = IUri_GetAuthority(uri, NULL);
7084         ok(hr == E_POINTER, "Error: GetAuthority returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
7085
7086         hr = IUri_GetDisplayUri(uri, NULL);
7087         ok(hr == E_POINTER, "Error: GetDisplayUri returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
7088
7089         hr = IUri_GetDomain(uri, NULL);
7090         ok(hr == E_POINTER, "Error: GetDomain returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
7091
7092         hr = IUri_GetExtension(uri, NULL);
7093         ok(hr == E_POINTER, "Error: GetExtension returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
7094
7095         hr = IUri_GetFragment(uri, NULL);
7096         ok(hr == E_POINTER, "Error: GetFragment returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
7097
7098         hr = IUri_GetHost(uri, NULL);
7099         ok(hr == E_POINTER, "Error: GetHost returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
7100
7101         hr = IUri_GetPassword(uri, NULL);
7102         ok(hr == E_POINTER, "Error: GetPassword returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
7103
7104         hr = IUri_GetPath(uri, NULL);
7105         ok(hr == E_POINTER, "Error: GetPath returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
7106
7107         hr = IUri_GetPathAndQuery(uri, NULL);
7108         ok(hr == E_POINTER, "Error: GetPathAndQuery returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
7109
7110         hr = IUri_GetQuery(uri, NULL);
7111         ok(hr == E_POINTER, "Error: GetQuery returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
7112
7113         hr = IUri_GetRawUri(uri, NULL);
7114         ok(hr == E_POINTER, "Error: GetRawUri returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
7115
7116         hr = IUri_GetSchemeName(uri, NULL);
7117         ok(hr == E_POINTER, "Error: GetSchemeName returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
7118
7119         hr = IUri_GetUserInfo(uri, NULL);
7120         ok(hr == E_POINTER, "Error: GetUserInfo returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
7121
7122         hr = IUri_GetUserName(uri, NULL);
7123         ok(hr == E_POINTER, "Error: GetUserName returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
7124     }
7125     if(uri) IUri_Release(uri);
7126
7127     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
7128         uri_properties test = uri_tests[i];
7129         LPWSTR uriW;
7130         uri = NULL;
7131
7132         uriW = a2w(test.uri);
7133         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
7134         if(test.create_todo) {
7135             todo_wine {
7136                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7137                         hr, test.create_expected, i);
7138             }
7139         } else {
7140             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7141                     hr, test.create_expected, i);
7142         }
7143
7144         if(SUCCEEDED(hr)) {
7145             uri_str_property prop;
7146             BSTR received = NULL;
7147
7148             /* GetAbsoluteUri() tests. */
7149             prop = test.str_props[Uri_PROPERTY_ABSOLUTE_URI];
7150             hr = IUri_GetAbsoluteUri(uri, &received);
7151             if(prop.todo) {
7152                 todo_wine {
7153                     ok(hr == prop.expected, "Error: GetAbsoluteUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7154                             hr, prop.expected, i);
7155                 }
7156                 todo_wine {
7157                     ok(!strcmp_aw(prop.value, received) || broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
7158                             "Error: Expected %s but got %s on uri_tests[%d].\n",
7159                             prop.value, wine_dbgstr_w(received), i);
7160                 }
7161             } else {
7162                 ok(hr == prop.expected, "Error: GetAbsoluteUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7163                         hr, prop.expected, i);
7164                 ok(!strcmp_aw(prop.value, received) || broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
7165                         "Error: Expected %s but got %s on uri_tests[%d].\n",
7166                         prop.value, wine_dbgstr_w(received), i);
7167             }
7168             SysFreeString(received);
7169             received = NULL;
7170
7171             /* GetAuthority() tests. */
7172             prop = test.str_props[Uri_PROPERTY_AUTHORITY];
7173             hr = IUri_GetAuthority(uri, &received);
7174             if(prop.todo) {
7175                 todo_wine {
7176                     ok(hr == prop.expected, "Error: GetAuthority returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7177                             hr, prop.expected, i);
7178                 }
7179                 todo_wine {
7180                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
7181                             prop.value, wine_dbgstr_w(received), i);
7182                 }
7183             } else {
7184                 ok(hr == prop.expected, "Error: GetAuthority returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7185                         hr, prop.expected, i);
7186                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
7187                         prop.value, wine_dbgstr_w(received), i);
7188             }
7189             SysFreeString(received);
7190             received = NULL;
7191
7192             /* GetDisplayUri() tests. */
7193             prop = test.str_props[Uri_PROPERTY_DISPLAY_URI];
7194             hr = IUri_GetDisplayUri(uri, &received);
7195             if(prop.todo) {
7196                 todo_wine {
7197                     ok(hr == prop.expected, "Error: GetDisplayUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7198                             hr, prop.expected, i);
7199                 }
7200                 todo_wine {
7201                     ok(!strcmp_aw(prop.value, received) || broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
7202                             "Error: Expected %s but got %s on uri_test[%d].\n",
7203                             prop.value, wine_dbgstr_w(received), i);
7204                 }
7205             } else {
7206                 ok(hr == prop.expected, "Error: GetDisplayUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7207                         hr, prop.expected, i);
7208                 ok(!strcmp_aw(prop.value, received) || broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
7209                         "Error: Expected %s but got %s on uri_tests[%d].\n",
7210                         prop.value, wine_dbgstr_w(received), i);
7211             }
7212             SysFreeString(received);
7213             received = NULL;
7214
7215             /* GetDomain() tests. */
7216             prop = test.str_props[Uri_PROPERTY_DOMAIN];
7217             hr = IUri_GetDomain(uri, &received);
7218             if(prop.todo) {
7219                 todo_wine {
7220                     ok(hr == prop.expected, "Error: GetDomain returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7221                             hr, prop.expected, i);
7222                 }
7223                 todo_wine {
7224                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
7225                             prop.value, wine_dbgstr_w(received), i);
7226                 }
7227             } else {
7228                 ok(hr == prop.expected, "Error: GetDomain returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7229                         hr, prop.expected, i);
7230                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
7231                         prop.value, wine_dbgstr_w(received), i);
7232             }
7233             SysFreeString(received);
7234             received = NULL;
7235
7236             /* GetExtension() tests. */
7237             prop = test.str_props[Uri_PROPERTY_EXTENSION];
7238             hr = IUri_GetExtension(uri, &received);
7239             if(prop.todo) {
7240                 todo_wine {
7241                     ok(hr == prop.expected, "Error: GetExtension returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7242                             hr, prop.expected, i);
7243                 }
7244                 todo_wine {
7245                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
7246                             prop.value, wine_dbgstr_w(received), i);
7247                 }
7248             } else {
7249                 ok(hr == prop.expected, "Error: GetExtension returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7250                         hr, prop.expected, i);
7251                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
7252                         prop.value, wine_dbgstr_w(received), i);
7253             }
7254             SysFreeString(received);
7255             received = NULL;
7256
7257             /* GetFragment() tests. */
7258             prop = test.str_props[Uri_PROPERTY_FRAGMENT];
7259             hr = IUri_GetFragment(uri, &received);
7260             if(prop.todo) {
7261                 todo_wine {
7262                     ok(hr == prop.expected, "Error: GetFragment returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7263                             hr, prop.expected, i);
7264                 }
7265                 todo_wine {
7266                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
7267                             prop.value, wine_dbgstr_w(received), i);
7268                 }
7269             } else {
7270                 ok(hr == prop.expected, "Error: GetFragment returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7271                         hr, prop.expected, i);
7272                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
7273                         prop.value, wine_dbgstr_w(received), i);
7274             }
7275             SysFreeString(received);
7276             received = NULL;
7277
7278             /* GetHost() tests. */
7279             prop = test.str_props[Uri_PROPERTY_HOST];
7280             hr = IUri_GetHost(uri, &received);
7281             if(prop.todo) {
7282                 todo_wine {
7283                     ok(hr == prop.expected, "Error: GetHost returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7284                             hr, prop.expected, i);
7285                 }
7286                 todo_wine {
7287                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
7288                             prop.value, wine_dbgstr_w(received), i);
7289                 }
7290             } else {
7291                 ok(hr == prop.expected, "Error: GetHost returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7292                         hr, prop.expected, i);
7293                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
7294                         prop.value, wine_dbgstr_w(received), i);
7295             }
7296             SysFreeString(received);
7297             received = NULL;
7298
7299             /* GetPassword() tests. */
7300             prop = test.str_props[Uri_PROPERTY_PASSWORD];
7301             hr = IUri_GetPassword(uri, &received);
7302             if(prop.todo) {
7303                 todo_wine {
7304                     ok(hr == prop.expected, "Error: GetPassword returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7305                             hr, prop.expected, i);
7306                 }
7307                 todo_wine {
7308                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
7309                             prop.value, wine_dbgstr_w(received), i);
7310                 }
7311             } else {
7312                 ok(hr == prop.expected, "Error: GetPassword returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7313                         hr, prop.expected, i);
7314                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
7315                         prop.value, wine_dbgstr_w(received), i);
7316             }
7317             SysFreeString(received);
7318             received = NULL;
7319
7320             /* GetPath() tests. */
7321             prop = test.str_props[Uri_PROPERTY_PATH];
7322             hr = IUri_GetPath(uri, &received);
7323             if(prop.todo) {
7324                 todo_wine {
7325                     ok(hr == prop.expected, "Error: GetPath returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7326                             hr, prop.expected, i);
7327                 }
7328                 todo_wine {
7329                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
7330                             prop.value, wine_dbgstr_w(received), i);
7331                 }
7332             } else {
7333                 ok(hr == prop.expected, "Error: GetPath returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7334                         hr, prop.expected, i);
7335                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
7336                         prop.value, wine_dbgstr_w(received), i);
7337             }
7338             SysFreeString(received);
7339             received = NULL;
7340
7341             /* GetPathAndQuery() tests. */
7342             prop = test.str_props[Uri_PROPERTY_PATH_AND_QUERY];
7343             hr = IUri_GetPathAndQuery(uri, &received);
7344             if(prop.todo) {
7345                 todo_wine {
7346                     ok(hr == prop.expected, "Error: GetPathAndQuery returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7347                             hr, prop.expected, i);
7348                 }
7349                 todo_wine {
7350                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
7351                             prop.value, wine_dbgstr_w(received), i);
7352                 }
7353             } else {
7354                 ok(hr == prop.expected, "Error: GetPathAndQuery returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7355                         hr, prop.expected, i);
7356                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
7357                         prop.value, wine_dbgstr_w(received), i);
7358             }
7359             SysFreeString(received);
7360             received = NULL;
7361
7362             /* GetQuery() tests. */
7363             prop = test.str_props[Uri_PROPERTY_QUERY];
7364             hr = IUri_GetQuery(uri, &received);
7365             if(prop.todo) {
7366                 todo_wine {
7367                     ok(hr == prop.expected, "Error: GetQuery returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7368                             hr, prop.expected, i);
7369                 }
7370                 todo_wine {
7371                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
7372                             prop.value, wine_dbgstr_w(received), i);
7373                 }
7374             } else {
7375                 ok(hr == prop.expected, "Error: GetQuery returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7376                         hr, prop.expected, i);
7377                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
7378                         prop.value, wine_dbgstr_w(received), i);
7379             }
7380             SysFreeString(received);
7381             received = NULL;
7382
7383             /* GetRawUri() tests. */
7384             prop = test.str_props[Uri_PROPERTY_RAW_URI];
7385             hr = IUri_GetRawUri(uri, &received);
7386             if(prop.todo) {
7387                 todo_wine {
7388                     ok(hr == prop.expected, "Error: GetRawUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7389                             hr, prop.expected, i);
7390                 }
7391                 todo_wine {
7392                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
7393                             prop.value, wine_dbgstr_w(received), i);
7394                 }
7395             } else {
7396                 ok(hr == prop.expected, "Error: GetRawUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7397                         hr, prop.expected, i);
7398                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
7399                         prop.value, wine_dbgstr_w(received), i);
7400             }
7401             SysFreeString(received);
7402             received = NULL;
7403
7404             /* GetSchemeName() tests. */
7405             prop = test.str_props[Uri_PROPERTY_SCHEME_NAME];
7406             hr = IUri_GetSchemeName(uri, &received);
7407             if(prop.todo) {
7408                 todo_wine {
7409                     ok(hr == prop.expected, "Error: GetSchemeName returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7410                             hr, prop.expected, i);
7411                 }
7412                 todo_wine {
7413                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
7414                             prop.value, wine_dbgstr_w(received), i);
7415                 }
7416             } else {
7417                 ok(hr == prop.expected, "Error: GetSchemeName returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7418                         hr, prop.expected, i);
7419                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
7420                         prop.value, wine_dbgstr_w(received), i);
7421             }
7422             SysFreeString(received);
7423             received = NULL;
7424
7425             /* GetUserInfo() tests. */
7426             prop = test.str_props[Uri_PROPERTY_USER_INFO];
7427             hr = IUri_GetUserInfo(uri, &received);
7428             if(prop.todo) {
7429                 todo_wine {
7430                     ok(hr == prop.expected, "Error: GetUserInfo returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7431                             hr, prop.expected, i);
7432                 }
7433                 todo_wine {
7434                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
7435                             prop.value, wine_dbgstr_w(received), i);
7436                 }
7437             } else {
7438                 ok(hr == prop.expected, "Error: GetUserInfo returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7439                         hr, prop.expected, i);
7440                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
7441                         prop.value, wine_dbgstr_w(received), i);
7442             }
7443             SysFreeString(received);
7444             received = NULL;
7445
7446             /* GetUserName() tests. */
7447             prop = test.str_props[Uri_PROPERTY_USER_NAME];
7448             hr = IUri_GetUserName(uri, &received);
7449             if(prop.todo) {
7450                 todo_wine {
7451                     ok(hr == prop.expected, "Error: GetUserName returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7452                             hr, prop.expected, i);
7453                 }
7454                 todo_wine {
7455                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
7456                             prop.value, wine_dbgstr_w(received), i);
7457                 }
7458             } else {
7459                 ok(hr == prop.expected, "Error: GetUserName returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7460                         hr, prop.expected, i);
7461                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
7462                         prop.value, wine_dbgstr_w(received), i);
7463             }
7464             SysFreeString(received);
7465         }
7466
7467         if(uri) IUri_Release(uri);
7468
7469         heap_free(uriW);
7470     }
7471 }
7472
7473 static void test_IUri_GetDwordProperties(void) {
7474     IUri *uri = NULL;
7475     HRESULT hr;
7476     DWORD i;
7477
7478     /* Make sure all the 'Get*' dword property functions handle invalid args correctly. */
7479     hr = pCreateUri(http_urlW, 0, 0, &uri);
7480     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7481     if(SUCCEEDED(hr)) {
7482         hr = IUri_GetHostType(uri, NULL);
7483         ok(hr == E_INVALIDARG, "Error: GetHostType returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
7484
7485         hr = IUri_GetPort(uri, NULL);
7486         ok(hr == E_INVALIDARG, "Error: GetPort returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
7487
7488         hr = IUri_GetScheme(uri, NULL);
7489         ok(hr == E_INVALIDARG, "Error: GetScheme returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
7490
7491         hr = IUri_GetZone(uri, NULL);
7492         ok(hr == E_INVALIDARG, "Error: GetZone returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
7493     }
7494     if(uri) IUri_Release(uri);
7495
7496     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
7497         uri_properties test = uri_tests[i];
7498         LPWSTR uriW;
7499         uri = NULL;
7500
7501         uriW = a2w(test.uri);
7502         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
7503         if(test.create_todo) {
7504             todo_wine {
7505                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7506                         hr, test.create_expected, i);
7507             }
7508         } else {
7509             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7510                     hr, test.create_expected, i);
7511         }
7512
7513         if(SUCCEEDED(hr)) {
7514             uri_dword_property prop;
7515             DWORD received;
7516
7517             /* Assign an insane value so tests don't accidentally pass when
7518              * they shouldn't!
7519              */
7520             received = -9999999;
7521
7522             /* GetHostType() tests. */
7523             prop = test.dword_props[Uri_PROPERTY_HOST_TYPE-Uri_PROPERTY_DWORD_START];
7524             hr = IUri_GetHostType(uri, &received);
7525             if(prop.todo) {
7526                 todo_wine {
7527                     ok(hr == prop.expected, "Error: GetHostType returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7528                             hr, prop.expected, i);
7529                 }
7530                 todo_wine {
7531                     ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
7532                 }
7533             } else {
7534                 ok(hr == prop.expected, "Error: GetHostType returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7535                         hr, prop.expected, i);
7536                 ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
7537             }
7538             received = -9999999;
7539
7540             /* GetPort() tests. */
7541             prop = test.dword_props[Uri_PROPERTY_PORT-Uri_PROPERTY_DWORD_START];
7542             hr = IUri_GetPort(uri, &received);
7543             if(prop.todo) {
7544                 todo_wine {
7545                     ok(hr == prop.expected, "Error: GetPort returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7546                             hr, prop.expected, i);
7547                 }
7548                 todo_wine {
7549                     ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
7550                 }
7551             } else {
7552                 ok(hr == prop.expected, "Error: GetPort returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7553                         hr, prop.expected, i);
7554                 ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
7555             }
7556             received = -9999999;
7557
7558             /* GetScheme() tests. */
7559             prop = test.dword_props[Uri_PROPERTY_SCHEME-Uri_PROPERTY_DWORD_START];
7560             hr = IUri_GetScheme(uri, &received);
7561             if(prop.todo) {
7562                 todo_wine {
7563                     ok(hr == prop.expected, "Error: GetScheme returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7564                             hr, prop.expected, i);
7565                 }
7566                 todo_wine {
7567                     ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
7568                 }
7569             } else {
7570                 ok(hr == prop.expected, "Error: GetScheme returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7571                         hr, prop.expected, i);
7572                 ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
7573             }
7574             received = -9999999;
7575
7576             /* GetZone() tests. */
7577             prop = test.dword_props[Uri_PROPERTY_ZONE-Uri_PROPERTY_DWORD_START];
7578             hr = IUri_GetZone(uri, &received);
7579             if(prop.todo) {
7580                 todo_wine {
7581                     ok(hr == prop.expected, "Error: GetZone returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7582                             hr, prop.expected, i);
7583                 }
7584                 todo_wine {
7585                     ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
7586                 }
7587             } else {
7588                 ok(hr == prop.expected, "Error: GetZone returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7589                         hr, prop.expected, i);
7590                 ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
7591             }
7592         }
7593
7594         if(uri) IUri_Release(uri);
7595
7596         heap_free(uriW);
7597     }
7598 }
7599
7600 static void test_IUri_GetPropertyLength(void) {
7601     IUri *uri = NULL;
7602     HRESULT hr;
7603     DWORD i;
7604
7605     /* Make sure it handles invalid args correctly. */
7606     hr = pCreateUri(http_urlW, 0, 0, &uri);
7607     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7608     if(SUCCEEDED(hr)) {
7609         DWORD received = 0xdeadbeef;
7610
7611         hr = IUri_GetPropertyLength(uri, Uri_PROPERTY_STRING_START, NULL, 0);
7612         ok(hr == E_INVALIDARG, "Error: GetPropertyLength returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
7613
7614         hr = IUri_GetPropertyLength(uri, Uri_PROPERTY_DWORD_START, &received, 0);
7615         ok(hr == E_INVALIDARG, "Error: GetPropertyLength return 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
7616         ok(received == 0xdeadbeef, "Error: Expected 0xdeadbeef but got 0x%08x.\n", received);
7617     }
7618     if(uri) IUri_Release(uri);
7619
7620     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
7621         uri_properties test = uri_tests[i];
7622         LPWSTR uriW;
7623         uri = NULL;
7624
7625         uriW = a2w(test.uri);
7626         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
7627         if(test.create_todo) {
7628             todo_wine {
7629                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7630                         hr, test.create_expected, i);
7631             }
7632         } else {
7633             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_test[%d].\n",
7634                     hr, test.create_expected, i);
7635         }
7636
7637         if(SUCCEEDED(hr)) {
7638             DWORD j;
7639
7640             for(j = Uri_PROPERTY_STRING_START; j <= Uri_PROPERTY_STRING_LAST; ++j) {
7641                 DWORD expectedLen, brokenLen, receivedLen;
7642                 uri_str_property prop = test.str_props[j];
7643
7644                 expectedLen = lstrlen(prop.value);
7645                 brokenLen = lstrlen(prop.broken_value);
7646
7647                 /* This won't be necessary once GetPropertyLength is implemented. */
7648                 receivedLen = -1;
7649
7650                 hr = IUri_GetPropertyLength(uri, j, &receivedLen, 0);
7651                 if(prop.todo) {
7652                     todo_wine {
7653                         ok(hr == prop.expected, "Error: GetPropertyLength returned 0x%08x, expected 0x%08x on uri_tests[%d].str_props[%d].\n",
7654                                 hr, prop.expected, i, j);
7655                     }
7656                     todo_wine {
7657                         ok(receivedLen == expectedLen || broken(receivedLen == brokenLen),
7658                                 "Error: Expected a length of %d but got %d on uri_tests[%d].str_props[%d].\n",
7659                                 expectedLen, receivedLen, i, j);
7660                     }
7661                 } else {
7662                     ok(hr == prop.expected, "Error: GetPropertyLength returned 0x%08x, expected 0x%08x on uri_tests[%d].str_props[%d].\n",
7663                             hr, prop.expected, i, j);
7664                     ok(receivedLen == expectedLen || broken(receivedLen == brokenLen),
7665                             "Error: Expected a length of %d but got %d on uri_tests[%d].str_props[%d].\n",
7666                             expectedLen, receivedLen, i, j);
7667                 }
7668             }
7669         }
7670
7671         if(uri) IUri_Release(uri);
7672
7673         heap_free(uriW);
7674     }
7675 }
7676
7677 static DWORD compute_expected_props(uri_properties *test)
7678 {
7679     DWORD ret = 0, i;
7680
7681     for(i=Uri_PROPERTY_STRING_START; i <= Uri_PROPERTY_STRING_LAST; i++) {
7682         if(test->str_props[i-Uri_PROPERTY_STRING_START].expected == S_OK)
7683             ret |= 1<<i;
7684     }
7685
7686     for(i=Uri_PROPERTY_DWORD_START; i <= Uri_PROPERTY_DWORD_LAST; i++) {
7687         if(test->dword_props[i-Uri_PROPERTY_DWORD_START].expected == S_OK)
7688             ret |= 1<<i;
7689     }
7690
7691     return ret;
7692 }
7693
7694 static void test_IUri_GetProperties(void) {
7695     IUri *uri = NULL;
7696     HRESULT hr;
7697     DWORD i;
7698
7699     hr = pCreateUri(http_urlW, 0, 0, &uri);
7700     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7701     if(SUCCEEDED(hr)) {
7702         hr = IUri_GetProperties(uri, NULL);
7703         ok(hr == E_INVALIDARG, "Error: GetProperties returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
7704     }
7705     if(uri) IUri_Release(uri);
7706
7707     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
7708         uri_properties test = uri_tests[i];
7709         LPWSTR uriW;
7710         uri = NULL;
7711
7712         uriW = a2w(test.uri);
7713         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
7714         if(test.create_todo) {
7715             todo_wine {
7716                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, test.create_expected);
7717             }
7718         } else {
7719             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, test.create_expected);
7720         }
7721
7722         if(SUCCEEDED(hr)) {
7723             DWORD received = 0, expected_props;
7724             DWORD j;
7725
7726             hr = IUri_GetProperties(uri, &received);
7727             ok(hr == S_OK, "Error: GetProperties returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7728
7729             expected_props = compute_expected_props(&test);
7730
7731             for(j = 0; j <= Uri_PROPERTY_DWORD_LAST; ++j) {
7732                 /* (1 << j) converts a Uri_PROPERTY to its corresponding Uri_HAS_* flag mask. */
7733                 if(expected_props & (1 << j))
7734                     ok(received & (1 << j), "Error: Expected flag for property %d on uri_tests[%d].\n", j, i);
7735                 else
7736                     ok(!(received & (1 << j)), "Error: Received flag for property %d when not expected on uri_tests[%d].\n", j, i);
7737             }
7738         }
7739
7740         if(uri) IUri_Release(uri);
7741
7742         heap_free(uriW);
7743     }
7744 }
7745
7746 static void test_IUri_HasProperty(void) {
7747     IUri *uri = NULL;
7748     HRESULT hr;
7749     DWORD i;
7750
7751     hr = pCreateUri(http_urlW, 0, 0, &uri);
7752     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7753     if(SUCCEEDED(hr)) {
7754         hr = IUri_HasProperty(uri, Uri_PROPERTY_RAW_URI, NULL);
7755         ok(hr == E_INVALIDARG, "Error: HasProperty returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
7756     }
7757     if(uri) IUri_Release(uri);
7758
7759     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
7760         uri_properties test = uri_tests[i];
7761         LPWSTR uriW;
7762         uri = NULL;
7763
7764         uriW = a2w(test.uri);
7765
7766         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
7767         if(test.create_todo) {
7768             todo_wine {
7769                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, test.create_expected);
7770             }
7771         } else {
7772             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, test.create_expected);
7773         }
7774
7775         if(SUCCEEDED(hr)) {
7776             DWORD expected_props, j;
7777
7778             expected_props = compute_expected_props(&test);
7779
7780             for(j = 0; j <= Uri_PROPERTY_DWORD_LAST; ++j) {
7781                 /* Assign -1, then explicitly test for TRUE or FALSE later. */
7782                 BOOL received = -1;
7783
7784                 hr = IUri_HasProperty(uri, j, &received);
7785                 ok(hr == S_OK, "Error: HasProperty returned 0x%08x, expected 0x%08x for property %d on uri_tests[%d].\n",
7786                         hr, S_OK, j, i);
7787
7788                 if(expected_props & (1 << j)) {
7789                     ok(received == TRUE, "Error: Expected to have property %d on uri_tests[%d].\n", j, i);
7790                 } else {
7791                     ok(received == FALSE, "Error: Wasn't expecting to have property %d on uri_tests[%d].\n", j, i);
7792                 }
7793             }
7794         }
7795
7796         if(uri) IUri_Release(uri);
7797
7798         heap_free(uriW);
7799     }
7800 }
7801
7802 static void test_IUri_IsEqual(void) {
7803     IUri *uriA, *uriB;
7804     BOOL equal;
7805     HRESULT hres;
7806     DWORD i;
7807
7808     uriA = uriB = NULL;
7809
7810     /* Make sure IsEqual handles invalid args correctly. */
7811     hres = pCreateUri(http_urlW, 0, 0, &uriA);
7812     ok(hres == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hres, S_OK);
7813     hres = pCreateUri(http_urlW, 0, 0, &uriB);
7814     ok(hres == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hres, S_OK);
7815
7816     equal = -1;
7817     hres = IUri_IsEqual(uriA, NULL, &equal);
7818     ok(hres == S_OK, "Error: IsEqual returned 0x%08x, expected 0x%08x.\n", hres, S_OK);
7819     ok(!equal, "Error: Expected equal to be FALSE, but was %d instead.\n", equal);
7820
7821     hres = IUri_IsEqual(uriA, uriB, NULL);
7822     ok(hres == E_POINTER, "Error: IsEqual returned 0x%08x, expected 0x%08x.\n", hres, E_POINTER);
7823
7824     IUri_Release(uriA);
7825     IUri_Release(uriB);
7826
7827     for(i = 0; i < sizeof(equality_tests)/sizeof(equality_tests[0]); ++i) {
7828         uri_equality test = equality_tests[i];
7829         LPWSTR uriA_W, uriB_W;
7830
7831         uriA = uriB = NULL;
7832
7833         uriA_W = a2w(test.a);
7834         uriB_W = a2w(test.b);
7835
7836         hres = pCreateUri(uriA_W, test.create_flags_a, 0, &uriA);
7837         ok(hres == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x on equality_tests[%d].a\n", hres, S_OK, i);
7838
7839         hres = pCreateUri(uriB_W, test.create_flags_b, 0, &uriB);
7840         ok(hres == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x on equality_tests[%d].b\n", hres, S_OK, i);
7841
7842         equal = -1;
7843         hres = IUri_IsEqual(uriA, uriB, &equal);
7844         if(test.todo) todo_wine {
7845             ok(hres == S_OK, "Error: IsEqual returned 0x%08x, expected 0x%08x on equality_tests[%d].\n", hres, S_OK, i);
7846             ok(equal == test.equal, "Error: Expected the comparison to be %d on equality_tests[%d].\n", test.equal, i);
7847         } else {
7848             ok(hres == S_OK, "Error: IsEqual returned 0x%08x, expected 0x%08x on equality_tests[%d].\n", hres, S_OK, i);
7849             ok(equal == test.equal, "Error: Expected the comparison to be %d on equality_tests[%d].\n", test.equal, i);
7850         }
7851         if(uriA) IUri_Release(uriA);
7852         if(uriB) IUri_Release(uriB);
7853
7854         heap_free(uriA_W);
7855         heap_free(uriB_W);
7856     }
7857 }
7858
7859 static void test_CreateUriWithFragment_InvalidArgs(void) {
7860     HRESULT hr;
7861     IUri *uri = (void*) 0xdeadbeef;
7862     const WCHAR fragmentW[] = {'#','f','r','a','g','m','e','n','t',0};
7863
7864     hr = pCreateUriWithFragment(NULL, fragmentW, 0, 0, &uri);
7865     ok(hr == E_INVALIDARG, "Error: CreateUriWithFragment returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
7866     ok(uri == NULL, "Error: Expected uri to be NULL, but was %p instead.\n", uri);
7867
7868     hr = pCreateUriWithFragment(http_urlW, fragmentW, 0, 0, NULL);
7869     ok(hr == E_INVALIDARG, "Error: CreateUriWithFragment returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
7870
7871     /* Original URI can't already contain a fragment component. */
7872     uri = (void*) 0xdeadbeef;
7873     hr = pCreateUriWithFragment(http_url_fragW, fragmentW, 0, 0, &uri);
7874     ok(hr == E_INVALIDARG, "Error: CreateUriWithFragment returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
7875     ok(uri == NULL, "Error: Expected uri to be NULL, but was %p instead.\n", uri);
7876 }
7877
7878 /* CreateUriWithFragment has the same invalid flag combinations as CreateUri. */
7879 static void test_CreateUriWithFragment_InvalidFlags(void) {
7880     DWORD i;
7881
7882     for(i = 0; i < sizeof(invalid_flag_tests)/sizeof(invalid_flag_tests[0]); ++i) {
7883         HRESULT hr;
7884         IUri *uri = (void*) 0xdeadbeef;
7885
7886         hr = pCreateUriWithFragment(http_urlW, NULL, invalid_flag_tests[i].flags, 0, &uri);
7887         ok(hr == invalid_flag_tests[i].expected, "Error: CreateUriWithFragment returned 0x%08x, expected 0x%08x. flags=0x%08x.\n",
7888             hr, invalid_flag_tests[i].expected, invalid_flag_tests[i].flags);
7889         ok(uri == NULL, "Error: Expected uri to be NULL, but was %p instead.\n", uri);
7890     }
7891 }
7892
7893 static void test_CreateUriWithFragment(void) {
7894     DWORD i;
7895
7896     for(i = 0; i < sizeof(uri_fragment_tests)/sizeof(uri_fragment_tests[0]); ++i) {
7897         HRESULT hr;
7898         IUri *uri = NULL;
7899         LPWSTR uriW, fragW;
7900         uri_with_fragment test = uri_fragment_tests[i];
7901
7902         uriW = a2w(test.uri);
7903         fragW = a2w(test.fragment);
7904
7905         hr = pCreateUriWithFragment(uriW, fragW, test.create_flags, 0, &uri);
7906         if(test.expected_todo) {
7907             todo_wine {
7908                 ok(hr == test.create_expected,
7909                     "Error: CreateUriWithFragment returned 0x%08x, expected 0x%08x on uri_fragment_tests[%d].\n",
7910                     hr, test.create_expected, i);
7911             }
7912         } else
7913             ok(hr == test.create_expected,
7914                 "Error: CreateUriWithFragment returned 0x%08x, expected 0x%08x on uri_fragment_tests[%d].\n",
7915                 hr, test.create_expected, i);
7916
7917         if(SUCCEEDED(hr)) {
7918             BSTR received = NULL;
7919
7920             hr = IUri_GetAbsoluteUri(uri, &received);
7921             if(test.expected_todo) {
7922                 todo_wine {
7923                     ok(hr == S_OK,
7924                         "Error: GetAbsoluteUri returned 0x%08x, expected 0x%08x on uri_fragment_tests[%d].\n",
7925                         hr, S_OK, i);
7926                 }
7927                 todo_wine {
7928                     ok(!strcmp_aw(test.expected_uri, received),
7929                         "Error: Expected %s but got %s on uri_fragment_tests[%d].\n",
7930                         test.expected_uri, wine_dbgstr_w(received), i);
7931                 }
7932             } else {
7933                 ok(hr == S_OK, "Error: GetAbsoluteUri returned 0x%08x, expected 0x%08x on uri_fragment_tests[%d].\n",
7934                     hr, S_OK, i);
7935                 ok(!strcmp_aw(test.expected_uri, received), "Error: Expected %s but got %s on uri_fragment_tests[%d].\n",
7936                     test.expected_uri, wine_dbgstr_w(received), i);
7937             }
7938
7939             SysFreeString(received);
7940         }
7941
7942         if(uri) IUri_Release(uri);
7943         heap_free(uriW);
7944         heap_free(fragW);
7945     }
7946 }
7947
7948 static void test_CreateIUriBuilder(void) {
7949     HRESULT hr;
7950     IUriBuilder *builder = NULL;
7951     IUri *uri;
7952
7953     hr = pCreateIUriBuilder(NULL, 0, 0, NULL);
7954     ok(hr == E_POINTER, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x\n",
7955         hr, E_POINTER);
7956
7957     /* CreateIUriBuilder increases the ref count of the IUri it receives. */
7958     hr = pCreateUri(http_urlW, 0, 0, &uri);
7959     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7960     if(SUCCEEDED(hr)) {
7961         ULONG cur_count, orig_count;
7962
7963         orig_count = get_refcnt(uri);
7964         hr = pCreateIUriBuilder(uri, 0, 0, &builder);
7965         ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7966         ok(builder != NULL, "Error: Expecting builder not to be NULL\n");
7967
7968         cur_count = get_refcnt(uri);
7969         ok(cur_count == orig_count+1, "Error: Expected the ref count to be %u, but was %u instead.\n", orig_count+1, cur_count);
7970
7971         if(builder) IUriBuilder_Release(builder);
7972         cur_count = get_refcnt(uri);
7973         ok(cur_count == orig_count, "Error: Expected the ref count to be %u, but was %u instead.\n", orig_count, cur_count);
7974     }
7975     if(uri) IUri_Release(uri);
7976 }
7977
7978 static void test_IUriBuilder_CreateUri(IUriBuilder *builder, const uri_builder_test *test,
7979                                        DWORD test_index) {
7980     HRESULT hr;
7981     IUri *uri = NULL;
7982
7983     hr = IUriBuilder_CreateUri(builder, test->uri_flags, 0, 0, &uri);
7984     if(test->uri_todo) {
7985         todo_wine {
7986             ok(hr == test->uri_hres,
7987                 "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7988                 hr, test->uri_hres, test_index);
7989         }
7990     } else {
7991         ok(hr == test->uri_hres,
7992             "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7993             hr, test->uri_hres, test_index);
7994     }
7995
7996     if(SUCCEEDED(hr)) {
7997         DWORD i;
7998
7999         for(i = 0; i < sizeof(test->expected_str_props)/sizeof(test->expected_str_props[0]); ++i) {
8000             uri_builder_str_property prop = test->expected_str_props[i];
8001             BSTR received = NULL;
8002
8003             hr = IUri_GetPropertyBSTR(uri, i, &received, 0);
8004             if(prop.todo) {
8005                 todo_wine {
8006                     ok(hr == prop.result,
8007                         "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_str_props[%d].\n",
8008                         hr, prop.result, test_index, i);
8009                 }
8010             } else {
8011                 ok(hr == prop.result,
8012                     "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_str_props[%d].\n",
8013                     hr, prop.result, test_index, i);
8014             }
8015             if(SUCCEEDED(hr)) {
8016                 if(prop.todo) {
8017                     todo_wine {
8018                         ok(!strcmp_aw(prop.expected, received),
8019                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].expected_str_props[%d].\n",
8020                             prop.expected, wine_dbgstr_w(received), test_index, i);
8021                     }
8022                 } else {
8023                     ok(!strcmp_aw(prop.expected, received),
8024                         "Error: Expected %s but got %s instead on uri_builder_tests[%d].expected_str_props[%d].\n",
8025                         prop.expected, wine_dbgstr_w(received), test_index, i);
8026                 }
8027             }
8028             SysFreeString(received);
8029         }
8030
8031         for(i = 0; i < sizeof(test->expected_dword_props)/sizeof(test->expected_dword_props[0]); ++i) {
8032             uri_builder_dword_property prop = test->expected_dword_props[i];
8033             DWORD received = -2;
8034
8035             hr = IUri_GetPropertyDWORD(uri, i+Uri_PROPERTY_DWORD_START, &received, 0);
8036             if(prop.todo) {
8037                 todo_wine {
8038                     ok(hr == prop.result,
8039                         "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_dword_props[%d].\n",
8040                         hr, prop.result, test_index, i);
8041                 }
8042             } else {
8043                 ok(hr == prop.result,
8044                     "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_dword_props[%d].\n",
8045                     hr, prop.result, test_index, i);
8046             }
8047             if(SUCCEEDED(hr)) {
8048                 if(prop.todo) {
8049                     todo_wine {
8050                         ok(received == prop.expected,
8051                             "Error: Expected %d but got %d instead on uri_builder_tests[%d].expected_dword_props[%d].\n",
8052                             prop.expected, received, test_index, i);
8053                     }
8054                 } else {
8055                     ok(received == prop.expected,
8056                         "Error: Expected %d but got %d instead on uri_builder_tests[%d].expected_dword_props[%d].\n",
8057                         prop.expected, received, test_index, i);
8058                 }
8059             }
8060         }
8061     }
8062     if(uri) IUri_Release(uri);
8063 }
8064
8065 static void test_IUriBuilder_CreateUriSimple(IUriBuilder *builder, const uri_builder_test *test,
8066                                        DWORD test_index) {
8067     HRESULT hr;
8068     IUri *uri = NULL;
8069
8070     hr = IUriBuilder_CreateUriSimple(builder, test->uri_simple_encode_flags, 0, &uri);
8071     if(test->uri_simple_todo) {
8072         todo_wine {
8073             ok(hr == test->uri_simple_hres,
8074                 "Error: IUriBuilder_CreateUriSimple returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8075                 hr, test->uri_simple_hres, test_index);
8076         }
8077     } else {
8078         ok(hr == test->uri_simple_hres,
8079             "Error: IUriBuilder_CreateUriSimple returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8080             hr, test->uri_simple_hres, test_index);
8081     }
8082
8083     if(SUCCEEDED(hr)) {
8084         DWORD i;
8085
8086         for(i = 0; i < sizeof(test->expected_str_props)/sizeof(test->expected_str_props[0]); ++i) {
8087             uri_builder_str_property prop = test->expected_str_props[i];
8088             BSTR received = NULL;
8089
8090             hr = IUri_GetPropertyBSTR(uri, i, &received, 0);
8091             if(prop.todo) {
8092                 todo_wine {
8093                     ok(hr == prop.result,
8094                         "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_str_props[%d].\n",
8095                         hr, prop.result, test_index, i);
8096                 }
8097             } else {
8098                 ok(hr == prop.result,
8099                     "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_str_props[%d].\n",
8100                     hr, prop.result, test_index, i);
8101             }
8102             if(SUCCEEDED(hr)) {
8103                 if(prop.todo) {
8104                     todo_wine {
8105                         ok(!strcmp_aw(prop.expected, received),
8106                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].expected_str_props[%d].\n",
8107                             prop.expected, wine_dbgstr_w(received), test_index, i);
8108                     }
8109                 } else {
8110                     ok(!strcmp_aw(prop.expected, received),
8111                         "Error: Expected %s but got %s instead on uri_builder_tests[%d].expected_str_props[%d].\n",
8112                         prop.expected, wine_dbgstr_w(received), test_index, i);
8113                 }
8114             }
8115             SysFreeString(received);
8116         }
8117
8118         for(i = 0; i < sizeof(test->expected_dword_props)/sizeof(test->expected_dword_props[0]); ++i) {
8119             uri_builder_dword_property prop = test->expected_dword_props[i];
8120             DWORD received = -2;
8121
8122             hr = IUri_GetPropertyDWORD(uri, i+Uri_PROPERTY_DWORD_START, &received, 0);
8123             if(prop.todo) {
8124                 todo_wine {
8125                     ok(hr == prop.result,
8126                         "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_dword_props[%d].\n",
8127                         hr, prop.result, test_index, i);
8128                 }
8129             } else {
8130                 ok(hr == prop.result,
8131                     "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_dword_props[%d].\n",
8132                     hr, prop.result, test_index, i);
8133             }
8134             if(SUCCEEDED(hr)) {
8135                 if(prop.todo) {
8136                     todo_wine {
8137                         ok(received == prop.expected,
8138                             "Error: Expected %d but got %d instead on uri_builder_tests[%d].expected_dword_props[%d].\n",
8139                             prop.expected, received, test_index, i);
8140                     }
8141                 } else {
8142                     ok(received == prop.expected,
8143                         "Error: Expected %d but got %d instead on uri_builder_tests[%d].expected_dword_props[%d].\n",
8144                         prop.expected, received, test_index, i);
8145                 }
8146             }
8147         }
8148     }
8149     if(uri) IUri_Release(uri);
8150 }
8151
8152 static void test_IUriBuilder_CreateUriWithFlags(IUriBuilder *builder, const uri_builder_test *test,
8153                                                 DWORD test_index) {
8154     HRESULT hr;
8155     IUri *uri = NULL;
8156
8157     hr = IUriBuilder_CreateUriWithFlags(builder, test->uri_with_flags, test->uri_with_builder_flags,
8158                                         test->uri_with_encode_flags, 0, &uri);
8159     if(test->uri_with_todo) {
8160         todo_wine {
8161             ok(hr == test->uri_with_hres,
8162                 "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8163                 hr, test->uri_with_hres, test_index);
8164         }
8165     } else {
8166         ok(hr == test->uri_with_hres,
8167             "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8168             hr, test->uri_with_hres, test_index);
8169     }
8170
8171     if(SUCCEEDED(hr)) {
8172         DWORD i;
8173
8174         for(i = 0; i < sizeof(test->expected_str_props)/sizeof(test->expected_str_props[0]); ++i) {
8175             uri_builder_str_property prop = test->expected_str_props[i];
8176             BSTR received = NULL;
8177
8178             hr = IUri_GetPropertyBSTR(uri, i, &received, 0);
8179             if(prop.todo) {
8180                 todo_wine {
8181                     ok(hr == prop.result,
8182                         "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_str_props[%d].\n",
8183                         hr, prop.result, test_index, i);
8184                 }
8185             } else {
8186                 ok(hr == prop.result,
8187                     "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_str_props[%d].\n",
8188                     hr, prop.result, test_index, i);
8189             }
8190             if(SUCCEEDED(hr)) {
8191                 if(prop.todo) {
8192                     todo_wine {
8193                         ok(!strcmp_aw(prop.expected, received),
8194                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].expected_str_props[%d].\n",
8195                             prop.expected, wine_dbgstr_w(received), test_index, i);
8196                     }
8197                 } else {
8198                     ok(!strcmp_aw(prop.expected, received),
8199                         "Error: Expected %s but got %s instead on uri_builder_tests[%d].expected_str_props[%d].\n",
8200                         prop.expected, wine_dbgstr_w(received), test_index, i);
8201                 }
8202             }
8203             SysFreeString(received);
8204         }
8205
8206         for(i = 0; i < sizeof(test->expected_dword_props)/sizeof(test->expected_dword_props[0]); ++i) {
8207             uri_builder_dword_property prop = test->expected_dword_props[i];
8208             DWORD received = -2;
8209
8210             hr = IUri_GetPropertyDWORD(uri, i+Uri_PROPERTY_DWORD_START, &received, 0);
8211             if(prop.todo) {
8212                 todo_wine {
8213                     ok(hr == prop.result,
8214                         "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_dword_props[%d].\n",
8215                         hr, prop.result, test_index, i);
8216                 }
8217             } else {
8218                 ok(hr == prop.result,
8219                     "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_dword_props[%d].\n",
8220                     hr, prop.result, test_index, i);
8221             }
8222             if(SUCCEEDED(hr)) {
8223                 if(prop.todo) {
8224                     todo_wine {
8225                         ok(received == prop.expected,
8226                             "Error: Expected %d but got %d instead on uri_builder_tests[%d].expected_dword_props[%d].\n",
8227                             prop.expected, received, test_index, i);
8228                     }
8229                 } else {
8230                     ok(received == prop.expected,
8231                         "Error: Expected %d but got %d instead on uri_builder_tests[%d].expected_dword_props[%d].\n",
8232                         prop.expected, received, test_index, i);
8233                 }
8234             }
8235         }
8236     }
8237     if(uri) IUri_Release(uri);
8238 }
8239
8240 static void test_IUriBuilder_CreateInvalidArgs(void) {
8241     IUriBuilder *builder;
8242     HRESULT hr;
8243
8244     hr = pCreateIUriBuilder(NULL, 0, 0, &builder);
8245     ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8246     if(SUCCEEDED(hr)) {
8247         IUri *test = NULL, *uri = (void*) 0xdeadbeef;
8248
8249         /* Test what happens if the IUriBuilder doesn't have a IUri set. */
8250         hr = IUriBuilder_CreateUri(builder, 0, 0, 0, NULL);
8251         ok(hr == E_POINTER, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
8252
8253         uri = (void*) 0xdeadbeef;
8254         hr = IUriBuilder_CreateUri(builder, 0, Uri_HAS_USER_NAME, 0, &uri);
8255         ok(hr == E_NOTIMPL, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, E_NOTIMPL);
8256         ok(uri == NULL, "Error: expected uri to be NULL, but was %p instead.\n", uri);
8257
8258         hr = IUriBuilder_CreateUriSimple(builder, 0, 0, NULL);
8259         ok(hr == E_POINTER, "Error: IUriBuilder_CreateUriSimple returned 0x%08x, expected 0x%08x.\n",
8260             hr, E_POINTER);
8261
8262         uri = (void*) 0xdeadbeef;
8263         hr = IUriBuilder_CreateUriSimple(builder, Uri_HAS_USER_NAME, 0, &uri);
8264         ok(hr == E_NOTIMPL, "Error: IUriBuilder_CreateUriSimple returned 0x%08x, expected 0x%08x.\n",
8265             hr, E_NOTIMPL);
8266         ok(!uri, "Error: Expected uri to NULL, but was %p instead.\n", uri);
8267
8268         hr = IUriBuilder_CreateUriWithFlags(builder, 0, 0, 0, 0, NULL);
8269         ok(hr == E_POINTER, "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x.\n",
8270             hr, E_POINTER);
8271
8272         uri = (void*) 0xdeadbeef;
8273         hr = IUriBuilder_CreateUriWithFlags(builder, 0, 0, Uri_HAS_USER_NAME, 0, &uri);
8274         ok(hr == E_NOTIMPL, "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x.\n",
8275             hr, E_NOTIMPL);
8276         ok(!uri, "Error: Expected uri to be NULL, but was %p instead.\n", uri);
8277
8278         hr = pCreateUri(http_urlW, 0, 0, &test);
8279         ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8280         if(SUCCEEDED(hr)) {
8281             hr = IUriBuilder_SetIUri(builder, test);
8282             ok(hr == S_OK, "Error: IUriBuilder_SetIUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8283
8284             /* No longer returns E_NOTIMPL, since a IUri has been set and hasn't been modified. */
8285             uri = NULL;
8286             hr = IUriBuilder_CreateUri(builder, 0, Uri_HAS_USER_NAME, 0, &uri);
8287             ok(hr == S_OK, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8288             ok(uri != NULL, "Error: The uri was NULL.\n");
8289             if(uri) IUri_Release(uri);
8290
8291             uri = NULL;
8292             hr = IUriBuilder_CreateUriSimple(builder, Uri_HAS_USER_NAME, 0, &uri);
8293             ok(hr == S_OK, "Error: IUriBuilder_CreateUriSimple returned 0x%08x, expected 0x%08x.\n",
8294                 hr, S_OK);
8295             ok(uri != NULL, "Error: uri was NULL.\n");
8296             if(uri) IUri_Release(uri);
8297
8298             uri = NULL;
8299             hr = IUriBuilder_CreateUriWithFlags(builder, 0, 0, 0, 0, &uri);
8300             ok(hr == S_OK, "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x.\n",
8301                 hr, S_OK);
8302             ok(uri != NULL, "Error: uri was NULL.\n");
8303             if(uri) IUri_Release(uri);
8304
8305             hr = IUriBuilder_SetFragment(builder, NULL);
8306             ok(hr == S_OK, "Error: IUriBuilder_SetFragment returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8307
8308             /* The IUriBuilder is changed, so it returns E_NOTIMPL again. */
8309             uri = (void*) 0xdeadbeef;
8310             hr = IUriBuilder_CreateUri(builder, 0, Uri_HAS_USER_NAME, 0, &uri);
8311             ok(hr == E_NOTIMPL, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8312             ok(!uri, "Error: Expected uri to be NULL but was %p instead.\n", uri);
8313
8314             uri = (void*) 0xdeadbeef;
8315             hr = IUriBuilder_CreateUriSimple(builder, Uri_HAS_USER_NAME, 0, &uri);
8316             ok(hr == E_NOTIMPL, "Error: IUriBuilder_CreateUriSimple returned 0x%08x, expected 0x%08x.\n",
8317                 hr, S_OK);
8318             ok(!uri, "Error: Expected uri to be NULL, but was %p instead.\n", uri);
8319
8320             uri = (void*) 0xdeadbeef;
8321             hr = IUriBuilder_CreateUriWithFlags(builder, 0, 0, Uri_HAS_USER_NAME, 0, &uri);
8322             ok(hr == E_NOTIMPL, "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x.\n",
8323                 hr, E_NOTIMPL);
8324             ok(!uri, "Error: Expected uri to be NULL, but was %p instead.\n", uri);
8325         }
8326         if(test) IUri_Release(test);
8327     }
8328     if(builder) IUriBuilder_Release(builder);
8329 }
8330
8331 /* Tests invalid args to the "Get*" functions. */
8332 static void test_IUriBuilder_GetInvalidArgs(void) {
8333     IUriBuilder *builder = NULL;
8334     HRESULT hr;
8335
8336     hr = pCreateIUriBuilder(NULL, 0, 0, &builder);
8337     ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8338     if(SUCCEEDED(hr)) {
8339         LPCWSTR received = (void*) 0xdeadbeef;
8340         DWORD len = -1, port = -1;
8341         BOOL set = -1;
8342
8343         hr = IUriBuilder_GetFragment(builder, NULL, NULL);
8344         ok(hr == E_POINTER, "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x.\n",
8345             hr, E_POINTER);
8346         hr = IUriBuilder_GetFragment(builder, NULL, &received);
8347         ok(hr == E_POINTER, "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x.\n",
8348             hr, E_POINTER);
8349         ok(!received, "Error: Expected received to be NULL, but was %p instead.\n", received);
8350         hr = IUriBuilder_GetFragment(builder, &len, NULL);
8351         ok(hr == E_POINTER, "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x.\n",
8352             hr, E_POINTER);
8353         ok(!len, "Error: Expected len to be 0, but was %d instead.\n", len);
8354
8355         hr = IUriBuilder_GetHost(builder, NULL, NULL);
8356         ok(hr == E_POINTER, "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x.\n",
8357             hr, E_POINTER);
8358         received = (void*) 0xdeadbeef;
8359         hr = IUriBuilder_GetHost(builder, NULL, &received);
8360         ok(hr == E_POINTER, "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x.\n",
8361             hr, E_POINTER);
8362         ok(!received, "Error: Expected received to be NULL, but was %p instead.\n", received);
8363         len = -1;
8364         hr = IUriBuilder_GetHost(builder, &len, NULL);
8365         ok(hr == E_POINTER, "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x.\n",
8366             hr, E_POINTER);
8367         ok(!len, "Error: Expected len to be 0, but was %d instead.\n", len);
8368
8369         hr = IUriBuilder_GetPassword(builder, NULL, NULL);
8370         ok(hr == E_POINTER, "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x.\n",
8371             hr, E_POINTER);
8372         received = (void*) 0xdeadbeef;
8373         hr = IUriBuilder_GetPassword(builder, NULL, &received);
8374         ok(hr == E_POINTER, "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x.\n",
8375             hr, E_POINTER);
8376         ok(!received, "Error: Expected received to be NULL, but was %p instead.\n", received);
8377         len = -1;
8378         hr = IUriBuilder_GetPassword(builder, &len, NULL);
8379         ok(hr == E_POINTER, "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x.\n",
8380             hr, E_POINTER);
8381         ok(!len, "Error: Expected len to be 0, but was %d instead.\n", len);
8382
8383         hr = IUriBuilder_GetPath(builder, NULL, NULL);
8384         ok(hr == E_POINTER, "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x.\n",
8385             hr, E_POINTER);
8386         received = (void*) 0xdeadbeef;
8387         hr = IUriBuilder_GetPath(builder, NULL, &received);
8388         ok(hr == E_POINTER, "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x.\n",
8389             hr, E_POINTER);
8390         ok(!received, "Error: Expected received to be NULL, but was %p instead.\n", received);
8391         len = -1;
8392         hr = IUriBuilder_GetPath(builder, &len, NULL);
8393         ok(hr == E_POINTER, "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x.\n",
8394             hr, E_POINTER);
8395         ok(!len, "Error: Expected len to be 0, but was %d instead.\n", len);
8396
8397         hr = IUriBuilder_GetPort(builder, NULL, NULL);
8398         ok(hr == E_POINTER, "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x.\n",
8399             hr, E_POINTER);
8400         hr = IUriBuilder_GetPort(builder, NULL, &port);
8401         ok(hr == E_POINTER, "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x.\n",
8402             hr, E_POINTER);
8403         ok(!port, "Error: Expected port to be 0, but was %d instead.\n", port);
8404         hr = IUriBuilder_GetPort(builder, &set, NULL);
8405         ok(hr == E_POINTER, "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x.\n",
8406             hr, E_POINTER);
8407         ok(!set, "Error: Expected set to be FALSE, but was %d instead.\n", set);
8408
8409         hr = IUriBuilder_GetQuery(builder, NULL, NULL);
8410         ok(hr == E_POINTER, "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x.\n",
8411             hr, E_POINTER);
8412         received = (void*) 0xdeadbeef;
8413         hr = IUriBuilder_GetQuery(builder, NULL, &received);
8414         ok(hr == E_POINTER, "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x.\n",
8415             hr, E_POINTER);
8416         ok(!received, "Error: Expected received to be NULL, but was %p instead.\n", received);
8417         len = -1;
8418         hr = IUriBuilder_GetQuery(builder, &len, NULL);
8419         ok(hr == E_POINTER, "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x.\n",
8420             hr, E_POINTER);
8421         ok(!len, "Error: Expected len to be 0, but was %d instead.\n", len);
8422
8423         hr = IUriBuilder_GetSchemeName(builder, NULL, NULL);
8424         ok(hr == E_POINTER, "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x.\n",
8425             hr, E_POINTER);
8426         received = (void*) 0xdeadbeef;
8427         hr = IUriBuilder_GetSchemeName(builder, NULL, &received);
8428         ok(hr == E_POINTER, "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x.\n",
8429             hr, E_POINTER);
8430         ok(!received, "Error: Expected received to be NULL, but was %p instead.\n", received);
8431         len = -1;
8432         hr = IUriBuilder_GetSchemeName(builder, &len, NULL);
8433         ok(hr == E_POINTER, "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x.\n",
8434             hr, E_POINTER);
8435         ok(!len, "Error: Expected len to be 0, but was %d instead.\n", len);
8436
8437         hr = IUriBuilder_GetUserName(builder, NULL, NULL);
8438         ok(hr == E_POINTER, "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x.\n",
8439             hr, E_POINTER);
8440         received = (void*) 0xdeadbeef;
8441         hr = IUriBuilder_GetUserName(builder, NULL, &received);
8442         ok(hr == E_POINTER, "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x.\n",
8443             hr, E_POINTER);
8444         ok(!received, "Error: Expected received to be NULL, but was %p instead.\n", received);
8445         len = -1;
8446         hr = IUriBuilder_GetUserName(builder, &len, NULL);
8447         ok(hr == E_POINTER, "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x.\n",
8448             hr, E_POINTER);
8449         ok(!len, "Error: Expected len to be 0, but was %d instead.\n", len);
8450     }
8451     if(builder) IUriBuilder_Release(builder);
8452 }
8453
8454 static void test_IUriBuilder_GetFragment(IUriBuilder *builder, const uri_builder_test *test,
8455                                          DWORD test_index) {
8456     HRESULT hr;
8457     DWORD i;
8458     LPCWSTR received = NULL;
8459     DWORD len = -1;
8460     const uri_builder_property *prop = NULL;
8461
8462     /* Check if the property was set earlier. */
8463     for(i = 0; i < sizeof(test->properties)/sizeof(test->properties[0]); ++i) {
8464         if(test->properties[i].change && test->properties[i].property == Uri_PROPERTY_FRAGMENT)
8465             prop = &(test->properties[i]);
8466     }
8467
8468     if(prop) {
8469         /* Use expected_value unless it's NULL, then use value. */
8470         LPCSTR expected = prop->expected_value ? prop->expected_value : prop->value;
8471         hr = IUriBuilder_GetFragment(builder, &len, &received);
8472         if(prop->todo) {
8473             todo_wine {
8474                 ok(hr == (expected ? S_OK : S_FALSE),
8475                     "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8476                     hr, (expected ? S_OK : S_FALSE), test_index);
8477             }
8478             if(SUCCEEDED(hr)) {
8479                 todo_wine {
8480                     ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
8481                         expected, wine_dbgstr_w(received), test_index);
8482                 }
8483                 todo_wine {
8484                     ok(lstrlen(expected) == len,
8485                         "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8486                         lstrlen(expected), len, test_index);
8487                 }
8488             }
8489         } else {
8490             ok(hr == (expected ? S_OK : S_FALSE),
8491                 "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8492                 hr, (expected ? S_OK : S_FALSE), test_index);
8493             ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
8494                 expected, wine_dbgstr_w(received), test_index);
8495             ok(lstrlen(expected) == len,
8496                 "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8497                 lstrlen(expected), len, test_index);
8498         }
8499     } else {
8500         /* The property wasn't set earlier, so it should return whatever
8501          * the base IUri contains (if anything).
8502          */
8503         IUri *uri = NULL;
8504         hr = IUriBuilder_GetIUri(builder, &uri);
8505         ok(hr == S_OK,
8506             "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8507             hr, S_OK, test_index);
8508         if(SUCCEEDED(hr)) {
8509             if(!uri) {
8510                 received = (void*) 0xdeadbeef;
8511                 len = -1;
8512
8513                 hr = IUriBuilder_GetFragment(builder, &len, &received);
8514                 ok(hr == S_FALSE,
8515                     "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8516                     hr, S_FALSE, test_index);
8517                 if(SUCCEEDED(hr)) {
8518                     ok(!len, "Error: Expected len to be 0, but was %d instead on uri_builder_tests[%d].\n",
8519                         len, test_index);
8520                     ok(!received, "Error: Expected received to be NULL, but was %p instead on uri_builder_tests[%d].\n",
8521                         received, test_index);
8522                 }
8523             } else {
8524                 BOOL has_prop = FALSE;
8525                 BSTR expected = NULL;
8526
8527                 hr = IUri_GetFragment(uri, &expected);
8528                 ok(SUCCEEDED(hr),
8529                     "Error: Expected IUri_GetFragment to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
8530                     hr, test_index);
8531                 has_prop = hr == S_OK;
8532
8533                 hr = IUriBuilder_GetFragment(builder, &len, &received);
8534                 if(has_prop) {
8535                     ok(hr == S_OK,
8536                         "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8537                         hr, S_OK, test_index);
8538                     if(SUCCEEDED(hr)) {
8539                         ok(!lstrcmpW(expected, received),
8540                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].\n",
8541                             wine_dbgstr_w(expected), wine_dbgstr_w(received), test_index);
8542                         ok(lstrlenW(expected) == len,
8543                             "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8544                             lstrlenW(expected), len, test_index);
8545                     }
8546                 } else {
8547                     ok(hr == S_FALSE,
8548                         "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8549                         hr, S_FALSE, test_index);
8550                     if(SUCCEEDED(hr)) {
8551                         ok(!received, "Error: Expected received to be NULL on uri_builder_tests[%d].\n", test_index);
8552                         ok(!len, "Error: Expected the length to be 0, but was %d instead on uri_builder_tests[%d].\n",
8553                             len, test_index);
8554                     }
8555                 }
8556                 SysFreeString(expected);
8557             }
8558         }
8559         if(uri) IUri_Release(uri);
8560     }
8561 }
8562
8563 static void test_IUriBuilder_GetHost(IUriBuilder *builder, const uri_builder_test *test,
8564                                      DWORD test_index) {
8565     HRESULT hr;
8566     DWORD i;
8567     LPCWSTR received = NULL;
8568     DWORD len = -1;
8569     const uri_builder_property *prop = NULL;
8570
8571     /* Check if the property was set earlier. */
8572     for(i = 0; i < sizeof(test->properties)/sizeof(test->properties[0]); ++i) {
8573         if(test->properties[i].change && test->properties[i].property == Uri_PROPERTY_HOST)
8574             prop = &(test->properties[i]);
8575     }
8576
8577     if(prop) {
8578         /* Use expected_value unless it's NULL, then use value. */
8579         LPCSTR expected = prop->expected_value ? prop->expected_value : prop->value;
8580         hr = IUriBuilder_GetHost(builder, &len, &received);
8581         if(prop->todo) {
8582             todo_wine {
8583                 ok(hr == (expected ? S_OK : S_FALSE),
8584                     "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8585                     hr, (expected ? S_OK : S_FALSE), test_index);
8586             }
8587             if(SUCCEEDED(hr)) {
8588                 todo_wine {
8589                     ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
8590                         expected, wine_dbgstr_w(received), test_index);
8591                 }
8592                 todo_wine {
8593                     ok(lstrlen(expected) == len,
8594                         "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8595                         lstrlen(expected), len, test_index);
8596                 }
8597             }
8598         } else {
8599             ok(hr == (expected ? S_OK : S_FALSE),
8600                 "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8601                 hr, (expected ? S_OK : S_FALSE), test_index);
8602             ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
8603                 expected, wine_dbgstr_w(received), test_index);
8604             ok(lstrlen(expected) == len,
8605                 "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8606                 lstrlen(expected), len, test_index);
8607         }
8608     } else {
8609         /* The property wasn't set earlier, so it should return whatever
8610          * the base IUri contains (if anything).
8611          */
8612         IUri *uri = NULL;
8613         hr = IUriBuilder_GetIUri(builder, &uri);
8614         ok(hr == S_OK,
8615             "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8616             hr, S_OK, test_index);
8617         if(SUCCEEDED(hr)) {
8618             if(!uri) {
8619                 received = (void*) 0xdeadbeef;
8620                 len = -1;
8621
8622                 hr = IUriBuilder_GetHost(builder, &len, &received);
8623                 ok(hr == S_FALSE,
8624                     "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8625                     hr, S_FALSE, test_index);
8626                 if(SUCCEEDED(hr)) {
8627                     ok(!len, "Error: Expected len to be 0, but was %d instead on uri_builder_tests[%d].\n",
8628                         len, test_index);
8629                     ok(!received, "Error: Expected received to be NULL, but was %p instead on uri_builder_tests[%d].\n",
8630                         received, test_index);
8631                 }
8632             } else {
8633                 BOOL has_prop = FALSE;
8634                 BSTR expected = NULL;
8635
8636                 hr = IUri_GetHost(uri, &expected);
8637                 ok(SUCCEEDED(hr),
8638                     "Error: Expected IUri_GetHost to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
8639                     hr, test_index);
8640                 has_prop = hr == S_OK;
8641
8642                 hr = IUriBuilder_GetHost(builder, &len, &received);
8643                 if(has_prop) {
8644                     ok(hr == S_OK,
8645                         "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8646                         hr, S_OK, test_index);
8647                     if(SUCCEEDED(hr)) {
8648                         ok(!lstrcmpW(expected, received),
8649                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].\n",
8650                             wine_dbgstr_w(expected), wine_dbgstr_w(received), test_index);
8651                         ok(lstrlenW(expected) == len,
8652                             "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8653                             lstrlenW(expected), len, test_index);
8654                     }
8655                 } else {
8656                     ok(hr == S_FALSE,
8657                         "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8658                         hr, S_FALSE, test_index);
8659                     if(SUCCEEDED(hr)) {
8660                         ok(!received, "Error: Expected received to be NULL on uri_builder_tests[%d].\n", test_index);
8661                         ok(!len, "Error: Expected the length to be 0, but was %d instead on uri_builder_tests[%d].\n",
8662                             len, test_index);
8663                     }
8664                 }
8665                 SysFreeString(expected);
8666             }
8667         }
8668         if(uri) IUri_Release(uri);
8669     }
8670 }
8671
8672 static void test_IUriBuilder_GetPassword(IUriBuilder *builder, const uri_builder_test *test,
8673                                          DWORD test_index) {
8674     HRESULT hr;
8675     DWORD i;
8676     LPCWSTR received = NULL;
8677     DWORD len = -1;
8678     const uri_builder_property *prop = NULL;
8679
8680     /* Check if the property was set earlier. */
8681     for(i = 0; i < sizeof(test->properties)/sizeof(test->properties[0]); ++i) {
8682         if(test->properties[i].change && test->properties[i].property == Uri_PROPERTY_PASSWORD)
8683             prop = &(test->properties[i]);
8684     }
8685
8686     if(prop) {
8687         /* Use expected_value unless it's NULL, then use value. */
8688         LPCSTR expected = prop->expected_value ? prop->expected_value : prop->value;
8689         hr = IUriBuilder_GetPassword(builder, &len, &received);
8690         if(prop->todo) {
8691             todo_wine {
8692                 ok(hr == (expected ? S_OK : S_FALSE),
8693                     "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8694                     hr, (expected ? S_OK : S_FALSE), test_index);
8695             }
8696             if(SUCCEEDED(hr)) {
8697                 todo_wine {
8698                     ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
8699                         expected, wine_dbgstr_w(received), test_index);
8700                 }
8701                 todo_wine {
8702                     ok(lstrlen(expected) == len,
8703                         "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8704                         lstrlen(expected), len, test_index);
8705                 }
8706             }
8707         } else {
8708             ok(hr == (expected ? S_OK : S_FALSE),
8709                 "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8710                 hr, (expected ? S_OK : S_FALSE), test_index);
8711             ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
8712                 expected, wine_dbgstr_w(received), test_index);
8713             ok(lstrlen(expected) == len,
8714                 "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8715                 lstrlen(expected), len, test_index);
8716         }
8717     } else {
8718         /* The property wasn't set earlier, so it should return whatever
8719          * the base IUri contains (if anything).
8720          */
8721         IUri *uri = NULL;
8722         hr = IUriBuilder_GetIUri(builder, &uri);
8723         ok(hr == S_OK,
8724             "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8725             hr, S_OK, test_index);
8726         if(SUCCEEDED(hr)) {
8727             if(!uri) {
8728                 received = (void*) 0xdeadbeef;
8729                 len = -1;
8730
8731                 hr = IUriBuilder_GetPassword(builder, &len, &received);
8732                 ok(hr == S_FALSE,
8733                     "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8734                     hr, S_FALSE, test_index);
8735                 if(SUCCEEDED(hr)) {
8736                     ok(!len, "Error: Expected len to be 0, but was %d instead on uri_builder_tests[%d].\n",
8737                         len, test_index);
8738                     ok(!received, "Error: Expected received to be NULL, but was %p instead on uri_builder_tests[%d].\n",
8739                         received, test_index);
8740                 }
8741             } else {
8742                 BOOL has_prop = FALSE;
8743                 BSTR expected = NULL;
8744
8745                 hr = IUri_GetPassword(uri, &expected);
8746                 ok(SUCCEEDED(hr),
8747                     "Error: Expected IUri_GetPassword to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
8748                     hr, test_index);
8749                 has_prop = hr == S_OK;
8750
8751                 hr = IUriBuilder_GetPassword(builder, &len, &received);
8752                 if(has_prop) {
8753                     ok(hr == S_OK,
8754                         "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8755                         hr, S_OK, test_index);
8756                     if(SUCCEEDED(hr)) {
8757                         ok(!lstrcmpW(expected, received),
8758                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].\n",
8759                             wine_dbgstr_w(expected), wine_dbgstr_w(received), test_index);
8760                         ok(lstrlenW(expected) == len,
8761                             "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8762                             lstrlenW(expected), len, test_index);
8763                     }
8764                 } else {
8765                     ok(hr == S_FALSE,
8766                         "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8767                         hr, S_FALSE, test_index);
8768                     if(SUCCEEDED(hr)) {
8769                         ok(!received, "Error: Expected received to be NULL on uri_builder_tests[%d].\n", test_index);
8770                         ok(!len, "Error: Expected the length to be 0, but was %d instead on uri_builder_tests[%d].\n",
8771                             len, test_index);
8772                     }
8773                 }
8774                 SysFreeString(expected);
8775             }
8776         }
8777         if(uri) IUri_Release(uri);
8778     }
8779 }
8780
8781 static void test_IUriBuilder_GetPath(IUriBuilder *builder, const uri_builder_test *test,
8782                                      DWORD test_index) {
8783     HRESULT hr;
8784     DWORD i;
8785     LPCWSTR received = NULL;
8786     DWORD len = -1;
8787     const uri_builder_property *prop = NULL;
8788
8789     /* Check if the property was set earlier. */
8790     for(i = 0; i < sizeof(test->properties)/sizeof(test->properties[0]); ++i) {
8791         if(test->properties[i].change && test->properties[i].property == Uri_PROPERTY_PATH)
8792             prop = &(test->properties[i]);
8793     }
8794
8795     if(prop) {
8796         /* Use expected_value unless it's NULL, then use value. */
8797         LPCSTR expected = prop->expected_value ? prop->expected_value : prop->value;
8798         hr = IUriBuilder_GetPath(builder, &len, &received);
8799         if(prop->todo) {
8800             todo_wine {
8801                 ok(hr == (expected ? S_OK : S_FALSE),
8802                     "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8803                     hr, (expected ? S_OK : S_FALSE), test_index);
8804             }
8805             if(SUCCEEDED(hr)) {
8806                 todo_wine {
8807                     ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
8808                         expected, wine_dbgstr_w(received), test_index);
8809                 }
8810                 todo_wine {
8811                     ok(lstrlen(expected) == len,
8812                         "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8813                         lstrlen(expected), len, test_index);
8814                 }
8815             }
8816         } else {
8817             ok(hr == (expected ? S_OK : S_FALSE),
8818                 "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8819                 hr, (expected ? S_OK : S_FALSE), test_index);
8820             ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
8821                 expected, wine_dbgstr_w(received), test_index);
8822             ok(lstrlen(expected) == len,
8823                 "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8824                 lstrlen(expected), len, test_index);
8825         }
8826     } else {
8827         /* The property wasn't set earlier, so it should return whatever
8828          * the base IUri contains (if anything).
8829          */
8830         IUri *uri = NULL;
8831         hr = IUriBuilder_GetIUri(builder, &uri);
8832         ok(hr == S_OK,
8833             "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8834             hr, S_OK, test_index);
8835         if(SUCCEEDED(hr)) {
8836             if(!uri) {
8837                 received = (void*) 0xdeadbeef;
8838                 len = -1;
8839
8840                 hr = IUriBuilder_GetPath(builder, &len, &received);
8841                 ok(hr == S_FALSE,
8842                     "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8843                     hr, S_FALSE, test_index);
8844                 if(SUCCEEDED(hr)) {
8845                     ok(!len, "Error: Expected len to be 0, but was %d instead on uri_builder_tests[%d].\n",
8846                         len, test_index);
8847                     ok(!received, "Error: Expected received to be NULL, but was %p instead on uri_builder_tests[%d].\n",
8848                         received, test_index);
8849                 }
8850             } else {
8851                 BOOL has_prop = FALSE;
8852                 BSTR expected = NULL;
8853
8854                 hr = IUri_GetPath(uri, &expected);
8855                 ok(SUCCEEDED(hr),
8856                     "Error: Expected IUri_GetPath to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
8857                     hr, test_index);
8858                 has_prop = hr == S_OK;
8859
8860                 hr = IUriBuilder_GetPath(builder, &len, &received);
8861                 if(has_prop) {
8862                     ok(hr == S_OK,
8863                         "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8864                         hr, S_OK, test_index);
8865                     if(SUCCEEDED(hr)) {
8866                         ok(!lstrcmpW(expected, received),
8867                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].\n",
8868                             wine_dbgstr_w(expected), wine_dbgstr_w(received), test_index);
8869                         ok(lstrlenW(expected) == len,
8870                             "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8871                             lstrlenW(expected), len, test_index);
8872                     }
8873                 } else {
8874                     ok(hr == S_FALSE,
8875                         "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8876                         hr, S_FALSE, test_index);
8877                     if(SUCCEEDED(hr)) {
8878                         ok(!received, "Error: Expected received to be NULL on uri_builder_tests[%d].\n", test_index);
8879                         ok(!len, "Error: Expected the length to be 0, but was %d instead on uri_builder_tests[%d].\n",
8880                             len, test_index);
8881                     }
8882                 }
8883                 SysFreeString(expected);
8884             }
8885         }
8886         if(uri) IUri_Release(uri);
8887     }
8888 }
8889
8890 static void test_IUriBuilder_GetPort(IUriBuilder *builder, const uri_builder_test *test,
8891                                      DWORD test_index) {
8892     HRESULT hr;
8893     BOOL has_port = FALSE;
8894     DWORD received = -1;
8895
8896     if(test->port_prop.change) {
8897         DWORD expected = test->port_prop.value;
8898
8899         hr = IUriBuilder_GetPort(builder, &has_port, &received);
8900         if(test->port_prop.todo) {
8901             todo_wine {
8902                 ok(hr == S_OK,
8903                     "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8904                     hr, S_OK, test_index);
8905             }
8906             if(SUCCEEDED(hr)) {
8907                 todo_wine {
8908                     ok(has_port == test->port_prop.set,
8909                         "Error: Expected has_port to be %d but was %d instead on uri_builder_tests[%d].\n",
8910                         test->port_prop.set, has_port, test_index);
8911                 }
8912                 todo_wine {
8913                     ok(received == expected,
8914                         "Error: Expected received to be %d, but was %d instead on uri_builder_tests[%d].\n",
8915                         expected, received, test_index);
8916                 }
8917             }
8918         } else {
8919             ok(hr == S_OK,
8920                 "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8921                 hr, S_OK, test_index);
8922             ok(has_port == test->port_prop.set,
8923                 "Error: Expected has_port to be %d, but was %d instead on uri_builder_tests[%d].\n",
8924                 test->port_prop.set, has_port, test_index);
8925             ok(received == test->port_prop.value,
8926                 "Error: Expected port to be %d, but was %d instead on uri_builder_tests[%d].\n",
8927                 test->port_prop.value, received, test_index);
8928         }
8929     } else {
8930         IUri *uri = NULL;
8931
8932         hr = IUriBuilder_GetIUri(builder, &uri);
8933         ok(hr == S_OK,
8934             "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8935             hr, S_OK, test_index);
8936         if(SUCCEEDED(hr)) {
8937             if(!uri) {
8938                 hr = IUriBuilder_GetPort(builder, &has_port, &received);
8939                 ok(hr == S_OK,
8940                     "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8941                     hr, S_OK, test_index);
8942                 if(SUCCEEDED(hr)) {
8943                     ok(has_port == FALSE,
8944                         "Error: Expected has_port to be FALSE, but was %d instead on uri_builder_tests[%d].\n",
8945                         has_port, test_index);
8946                     ok(!received, "Error: Expected received to be 0, but was %d instead on uri_builder_tests[%d].\n",
8947                         received, test_index);
8948                 }
8949             } else {
8950                 DWORD expected;
8951
8952                 hr = IUri_GetPort(uri, &expected);
8953                 ok(SUCCEEDED(hr),
8954                     "Error: Expected IUri_Port to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
8955                     hr, test_index);
8956
8957                 hr = IUriBuilder_GetPort(builder, &has_port, &received);
8958                 ok(hr == S_OK,
8959                     "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8960                     hr, S_OK, test_index);
8961                 if(SUCCEEDED(hr)) {
8962                     ok(!has_port,
8963                         "Error: Expected has_port to be FALSE but was TRUE instead on uri_builder_tests[%d].\n",
8964                         test_index);
8965                     ok(received == expected,
8966                         "Error: Expected received to be %d, but was %d instead on uri_builder_tests[%d].\n",
8967                         expected, received, test_index);
8968                 }
8969             }
8970         }
8971         if(uri) IUri_Release(uri);
8972     }
8973 }
8974
8975 static void test_IUriBuilder_GetQuery(IUriBuilder *builder, const uri_builder_test *test,
8976                                       DWORD test_index) {
8977     HRESULT hr;
8978     DWORD i;
8979     LPCWSTR received = NULL;
8980     DWORD len = -1;
8981     const uri_builder_property *prop = NULL;
8982
8983     /* Check if the property was set earlier. */
8984     for(i = 0; i < sizeof(test->properties)/sizeof(test->properties[0]); ++i) {
8985         if(test->properties[i].change && test->properties[i].property == Uri_PROPERTY_QUERY)
8986             prop = &(test->properties[i]);
8987     }
8988
8989     if(prop) {
8990         /* Use expected_value unless it's NULL, then use value. */
8991         LPCSTR expected = prop->expected_value ? prop->expected_value : prop->value;
8992         hr = IUriBuilder_GetQuery(builder, &len, &received);
8993         if(prop->todo) {
8994             todo_wine {
8995                 ok(hr == (expected ? S_OK : S_FALSE),
8996                     "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8997                     hr, (expected ? S_OK : S_FALSE), test_index);
8998             }
8999             if(SUCCEEDED(hr)) {
9000                 todo_wine {
9001                     ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
9002                         expected, wine_dbgstr_w(received), test_index);
9003                 }
9004                 todo_wine {
9005                     ok(lstrlen(expected) == len,
9006                         "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
9007                         lstrlen(expected), len, test_index);
9008                 }
9009             }
9010         } else {
9011             ok(hr == (expected ? S_OK : S_FALSE),
9012                 "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9013                 hr, (expected ? S_OK : S_FALSE), test_index);
9014             ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
9015                 expected, wine_dbgstr_w(received), test_index);
9016             ok(lstrlen(expected) == len,
9017                 "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
9018                 lstrlen(expected), len, test_index);
9019         }
9020     } else {
9021         /* The property wasn't set earlier, so it should return whatever
9022          * the base IUri contains (if anything).
9023          */
9024         IUri *uri = NULL;
9025         hr = IUriBuilder_GetIUri(builder, &uri);
9026         ok(hr == S_OK,
9027             "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9028             hr, S_OK, test_index);
9029         if(SUCCEEDED(hr)) {
9030             if(!uri) {
9031                 received = (void*) 0xdeadbeef;
9032                 len = -1;
9033
9034                 hr = IUriBuilder_GetQuery(builder, &len, &received);
9035                 ok(hr == S_FALSE,
9036                     "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9037                     hr, S_FALSE, test_index);
9038                 if(SUCCEEDED(hr)) {
9039                     ok(!len, "Error: Expected len to be 0, but was %d instead on uri_builder_tests[%d].\n",
9040                         len, test_index);
9041                     ok(!received, "Error: Expected received to be NULL, but was %p instead on uri_builder_tests[%d].\n",
9042                         received, test_index);
9043                 }
9044             } else {
9045                 BOOL has_prop = FALSE;
9046                 BSTR expected = NULL;
9047
9048                 hr = IUri_GetQuery(uri, &expected);
9049                 ok(SUCCEEDED(hr),
9050                     "Error: Expected IUri_GetQuery to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
9051                     hr, test_index);
9052                 has_prop = hr == S_OK;
9053
9054                 hr = IUriBuilder_GetQuery(builder, &len, &received);
9055                 if(has_prop) {
9056                     ok(hr == S_OK,
9057                         "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9058                         hr, S_OK, test_index);
9059                     if(SUCCEEDED(hr)) {
9060                         ok(!lstrcmpW(expected, received),
9061                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].\n",
9062                             wine_dbgstr_w(expected), wine_dbgstr_w(received), test_index);
9063                         ok(lstrlenW(expected) == len,
9064                             "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
9065                             lstrlenW(expected), len, test_index);
9066                     }
9067                 } else {
9068                     ok(hr == S_FALSE,
9069                         "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9070                         hr, S_FALSE, test_index);
9071                     if(SUCCEEDED(hr)) {
9072                         ok(!received, "Error: Expected received to be NULL on uri_builder_tests[%d].\n", test_index);
9073                         ok(!len, "Error: Expected the length to be 0, but was %d instead on uri_builder_tests[%d].\n",
9074                             len, test_index);
9075                     }
9076                 }
9077                 SysFreeString(expected);
9078             }
9079         }
9080         if(uri) IUri_Release(uri);
9081     }
9082 }
9083
9084 static void test_IUriBuilder_GetSchemeName(IUriBuilder *builder, const uri_builder_test *test,
9085                                            DWORD test_index) {
9086     HRESULT hr;
9087     DWORD i;
9088     LPCWSTR received = NULL;
9089     DWORD len = -1;
9090     const uri_builder_property *prop = NULL;
9091
9092     /* Check if the property was set earlier. */
9093     for(i = 0; i < sizeof(test->properties)/sizeof(test->properties[0]); ++i) {
9094         if(test->properties[i].change && test->properties[i].property == Uri_PROPERTY_SCHEME_NAME)
9095             prop = &(test->properties[i]);
9096     }
9097
9098     if(prop) {
9099         /* Use expected_value unless it's NULL, then use value. */
9100         LPCSTR expected = prop->expected_value ? prop->expected_value : prop->value;
9101         hr = IUriBuilder_GetSchemeName(builder, &len, &received);
9102         if(prop->todo) {
9103             todo_wine {
9104                 ok(hr == (expected ? S_OK : S_FALSE),
9105                     "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9106                     hr, (expected ? S_OK : S_FALSE), test_index);
9107             }
9108             if(SUCCEEDED(hr)) {
9109                 todo_wine {
9110                     ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
9111                         expected, wine_dbgstr_w(received), test_index);
9112                 }
9113                 todo_wine {
9114                     ok(lstrlen(expected) == len,
9115                         "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
9116                         lstrlen(expected), len, test_index);
9117                 }
9118             }
9119         } else {
9120             ok(hr == (expected ? S_OK : S_FALSE),
9121                 "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9122                 hr, (expected ? S_OK : S_FALSE), test_index);
9123             ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
9124                 expected, wine_dbgstr_w(received), test_index);
9125             ok(lstrlen(expected) == len,
9126                 "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
9127                 lstrlen(expected), len, test_index);
9128         }
9129     } else {
9130         /* The property wasn't set earlier, so it should return whatever
9131          * the base IUri contains (if anything).
9132          */
9133         IUri *uri = NULL;
9134         hr = IUriBuilder_GetIUri(builder, &uri);
9135         ok(hr == S_OK,
9136             "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9137             hr, S_OK, test_index);
9138         if(SUCCEEDED(hr)) {
9139             if(!uri) {
9140                 received = (void*) 0xdeadbeef;
9141                 len = -1;
9142
9143                 hr = IUriBuilder_GetSchemeName(builder, &len, &received);
9144                 ok(hr == S_FALSE,
9145                     "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9146                     hr, S_FALSE, test_index);
9147                 if(SUCCEEDED(hr)) {
9148                     ok(!len, "Error: Expected len to be 0, but was %d instead on uri_builder_tests[%d].\n",
9149                         len, test_index);
9150                     ok(!received, "Error: Expected received to be NULL, but was %p instead on uri_builder_tests[%d].\n",
9151                         received, test_index);
9152                 }
9153             } else {
9154                 BOOL has_prop = FALSE;
9155                 BSTR expected = NULL;
9156
9157                 hr = IUri_GetSchemeName(uri, &expected);
9158                 ok(SUCCEEDED(hr),
9159                     "Error: Expected IUri_GetSchemeName to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
9160                     hr, test_index);
9161                 has_prop = hr == S_OK;
9162
9163                 hr = IUriBuilder_GetSchemeName(builder, &len, &received);
9164                 if(has_prop) {
9165                     ok(hr == S_OK,
9166                         "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9167                         hr, S_OK, test_index);
9168                     if(SUCCEEDED(hr)) {
9169                         ok(!lstrcmpW(expected, received),
9170                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].\n",
9171                             wine_dbgstr_w(expected), wine_dbgstr_w(received), test_index);
9172                         ok(lstrlenW(expected) == len,
9173                             "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
9174                             lstrlenW(expected), len, test_index);
9175                     }
9176                 } else {
9177                     ok(hr == S_FALSE,
9178                         "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9179                         hr, S_FALSE, test_index);
9180                     if(SUCCEEDED(hr)) {
9181                         ok(!received, "Error: Expected received to be NULL on uri_builder_tests[%d].\n", test_index);
9182                         ok(!len, "Error: Expected the length to be 0, but was %d instead on uri_builder_tests[%d].\n",
9183                             len, test_index);
9184                     }
9185                 }
9186                 SysFreeString(expected);
9187             }
9188         }
9189         if(uri) IUri_Release(uri);
9190     }
9191 }
9192
9193 static void test_IUriBuilder_GetUserName(IUriBuilder *builder, const uri_builder_test *test,
9194                                          DWORD test_index) {
9195     HRESULT hr;
9196     DWORD i;
9197     LPCWSTR received = NULL;
9198     DWORD len = -1;
9199     const uri_builder_property *prop = NULL;
9200
9201     /* Check if the property was set earlier. */
9202     for(i = 0; i < sizeof(test->properties)/sizeof(test->properties[0]); ++i) {
9203         if(test->properties[i].change && test->properties[i].property == Uri_PROPERTY_USER_NAME)
9204             prop = &(test->properties[i]);
9205     }
9206
9207     if(prop && prop->value && *prop->value) {
9208         /* Use expected_value unless it's NULL, then use value. */
9209         LPCSTR expected = prop->expected_value ? prop->expected_value : prop->value;
9210         hr = IUriBuilder_GetUserName(builder, &len, &received);
9211         if(prop->todo) {
9212             todo_wine {
9213                 ok(hr == (expected ? S_OK : S_FALSE),
9214                     "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9215                     hr, (expected ? S_OK : S_FALSE), test_index);
9216             }
9217             if(SUCCEEDED(hr)) {
9218                 todo_wine {
9219                     ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
9220                         expected, wine_dbgstr_w(received), test_index);
9221                 }
9222                 todo_wine {
9223                     ok(lstrlen(expected) == len,
9224                         "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
9225                         lstrlen(expected), len, test_index);
9226                 }
9227             }
9228         } else {
9229             ok(hr == (expected ? S_OK : S_FALSE),
9230                 "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9231                 hr, (expected ? S_OK : S_FALSE), test_index);
9232             ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
9233                 expected, wine_dbgstr_w(received), test_index);
9234             ok(lstrlen(expected) == len,
9235                 "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
9236                 lstrlen(expected), len, test_index);
9237         }
9238     } else {
9239         /* The property wasn't set earlier, so it should return whatever
9240          * the base IUri contains (if anything).
9241          */
9242         IUri *uri = NULL;
9243         hr = IUriBuilder_GetIUri(builder, &uri);
9244         ok(hr == S_OK,
9245             "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9246             hr, S_OK, test_index);
9247         if(SUCCEEDED(hr)) {
9248             if(!uri) {
9249                 received = (void*) 0xdeadbeef;
9250                 len = -1;
9251
9252                 hr = IUriBuilder_GetUserName(builder, &len, &received);
9253                 ok(hr == S_FALSE,
9254                     "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9255                     hr, S_FALSE, test_index);
9256                 if(SUCCEEDED(hr)) {
9257                     ok(!len, "Error: Expected len to be 0, but was %d instead on uri_builder_tests[%d].\n",
9258                         len, test_index);
9259                     ok(!received, "Error: Expected received to be NULL, but was %p instead on uri_builder_tests[%d].\n",
9260                         received, test_index);
9261                 }
9262             } else {
9263                 BSTR expected = NULL;
9264                 BOOL has_prop = FALSE;
9265
9266                 hr = IUri_GetUserName(uri, &expected);
9267                 ok(SUCCEEDED(hr),
9268                     "Error: Expected IUri_GetUserName to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
9269                     hr, test_index);
9270                 has_prop = hr == S_OK;
9271
9272                 hr = IUriBuilder_GetUserName(builder, &len, &received);
9273                 if(has_prop) {
9274                     ok(hr == S_OK,
9275                         "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9276                         hr, S_OK, test_index);
9277                     if(SUCCEEDED(hr)) {
9278                         ok(!lstrcmpW(expected, received),
9279                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].\n",
9280                             wine_dbgstr_w(expected), wine_dbgstr_w(received), test_index);
9281                         ok(lstrlenW(expected) == len,
9282                             "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
9283                             lstrlenW(expected), len, test_index);
9284                     }
9285                 } else {
9286                     ok(hr == S_FALSE,
9287                         "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9288                         hr, S_FALSE, test_index);
9289                     if(SUCCEEDED(hr)) {
9290                         ok(!received, "Error: Expected received to be NULL on uri_builder_tests[%d].\n", test_index);
9291                         ok(!len, "Error: Expected the length to be 0, but was %d instead on uri_builder_tests[%d].\n",
9292                             len, test_index);
9293                     }
9294                 }
9295                 SysFreeString(expected);
9296             }
9297         }
9298         if(uri) IUri_Release(uri);
9299     }
9300 }
9301
9302 /* Tests IUriBuilder functions. */
9303 static void test_IUriBuilder(void) {
9304     HRESULT hr;
9305     IUriBuilder *builder;
9306     DWORD i;
9307
9308     for(i = 0; i < sizeof(uri_builder_tests)/sizeof(uri_builder_tests[0]); ++i) {
9309         IUri *uri = NULL;
9310         uri_builder_test test = uri_builder_tests[i];
9311         LPWSTR uriW = NULL;
9312
9313         if(test.uri) {
9314             uriW = a2w(test.uri);
9315             hr = pCreateUri(uriW, test.create_flags, 0, &uri);
9316             ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9317                 hr, S_OK, i);
9318             if(FAILED(hr)) continue;
9319         }
9320         hr = pCreateIUriBuilder(uri, 0, 0, &builder);
9321         if(test.create_builder_todo) {
9322             todo_wine {
9323                 ok(hr == test.create_builder_expected,
9324                     "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9325                     hr, test.create_builder_expected, i);
9326             }
9327         } else {
9328             ok(hr == test.create_builder_expected,
9329                 "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9330                 hr, test.create_builder_expected, i);
9331         }
9332         if(SUCCEEDED(hr)) {
9333             DWORD j;
9334             BOOL modified = FALSE, received = FALSE;
9335
9336             /* Perform all the string property changes. */
9337             for(j = 0; j < URI_BUILDER_STR_PROPERTY_COUNT; ++j) {
9338                 uri_builder_property prop = test.properties[j];
9339                 if(prop.change) {
9340                     change_property(builder, &prop, i);
9341                     if(prop.property != Uri_PROPERTY_SCHEME_NAME &&
9342                        prop.property != Uri_PROPERTY_HOST)
9343                         modified = TRUE;
9344                     else if(prop.value && *prop.value)
9345                         modified = TRUE;
9346                     else if(prop.value && !*prop.value && prop.property == Uri_PROPERTY_HOST)
9347                         /* Host name property can't be NULL, but it can be empty. */
9348                         modified = TRUE;
9349                 }
9350             }
9351
9352             if(test.port_prop.change) {
9353                 hr = IUriBuilder_SetPort(builder, test.port_prop.set, test.port_prop.value);
9354                 modified = TRUE;
9355                 if(test.port_prop.todo) {
9356                     todo_wine {
9357                         ok(hr == test.port_prop.expected,
9358                             "Error: IUriBuilder_SetPort returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9359                             hr, test.port_prop.expected, i);
9360                     }
9361                 } else {
9362                     ok(hr == test.port_prop.expected,
9363                         "Error: IUriBuilder_SetPort returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9364                         hr, test.port_prop.expected, i);
9365                 }
9366             }
9367
9368             hr = IUriBuilder_HasBeenModified(builder, &received);
9369             ok(hr == S_OK,
9370                 "Error IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9371                 hr, S_OK, i);
9372             if(SUCCEEDED(hr))
9373                 ok(received == modified,
9374                     "Error: Expected received to be %d but was %d instead on uri_builder_tests[%d].\n",
9375                     modified, received, i);
9376
9377             /* Test the "Get*" functions. */
9378             test_IUriBuilder_GetFragment(builder, &test, i);
9379             test_IUriBuilder_GetHost(builder, &test, i);
9380             test_IUriBuilder_GetPassword(builder, &test, i);
9381             test_IUriBuilder_GetPath(builder, &test, i);
9382             test_IUriBuilder_GetPort(builder, &test, i);
9383             test_IUriBuilder_GetQuery(builder, &test, i);
9384             test_IUriBuilder_GetSchemeName(builder, &test, i);
9385             test_IUriBuilder_GetUserName(builder, &test, i);
9386
9387             test_IUriBuilder_CreateUri(builder, &test, i);
9388             test_IUriBuilder_CreateUriSimple(builder, &test, i);
9389             test_IUriBuilder_CreateUriWithFlags(builder, &test, i);
9390         }
9391         if(builder) IUriBuilder_Release(builder);
9392         if(uri) IUri_Release(uri);
9393         heap_free(uriW);
9394     }
9395 }
9396
9397 static void test_IUriBuilder_HasBeenModified(void) {
9398     HRESULT hr;
9399     IUriBuilder *builder = NULL;
9400
9401     hr = pCreateIUriBuilder(NULL, 0, 0, &builder);
9402     ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9403     if(SUCCEEDED(hr)) {
9404         static const WCHAR hostW[] = {'g','o','o','g','l','e','.','c','o','m',0};
9405         IUri *uri = NULL;
9406         BOOL received;
9407
9408         hr = IUriBuilder_HasBeenModified(builder, NULL);
9409         ok(hr == E_POINTER, "Error: IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x.\n",
9410             hr, E_POINTER);
9411
9412         hr = IUriBuilder_SetHost(builder, hostW);
9413         ok(hr == S_OK, "Error: IUriBuilder_SetHost returned 0x%08x, expected 0x%08x.\n",
9414             hr, S_OK);
9415
9416         hr = IUriBuilder_HasBeenModified(builder, &received);
9417         ok(hr == S_OK, "Error: IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x.\n",
9418             hr, S_OK);
9419         if(SUCCEEDED(hr))
9420             ok(received == TRUE, "Error: Expected received to be TRUE.\n");
9421
9422         hr = pCreateUri(http_urlW, 0, 0, &uri);
9423         ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9424         if(SUCCEEDED(hr)) {
9425             LPCWSTR prop;
9426             DWORD len = -1;
9427
9428             hr = IUriBuilder_SetIUri(builder, uri);
9429             ok(hr == S_OK, "Error: IUriBuilder_SetIUri returned 0x%08x, expected 0x%08x.\n",
9430                 hr, S_OK);
9431
9432             hr = IUriBuilder_HasBeenModified(builder, &received);
9433             ok(hr == S_OK, "Error: IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x.\n",
9434                 hr, S_OK);
9435             if(SUCCEEDED(hr))
9436                 ok(received == FALSE, "Error: Expected received to be FALSE.\n");
9437
9438             /* Test what happens with you call SetIUri with the same IUri again. */
9439             hr = IUriBuilder_SetHost(builder, hostW);
9440             ok(hr == S_OK, "Error: IUriBuilder_SetHost returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9441
9442             hr = IUriBuilder_HasBeenModified(builder, &received);
9443             ok(hr == S_OK, "Error: IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x.\n",
9444                 hr, S_OK);
9445             if(SUCCEEDED(hr))
9446                 ok(received == TRUE, "Error: Expected received to be TRUE.\n");
9447
9448             hr = IUriBuilder_SetIUri(builder, uri);
9449             ok(hr == S_OK, "Error: IUriBuilder_SetIUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9450
9451             /* IUriBuilder already had 'uri' as it's IUri property and so Windows doesn't
9452              * reset any of the changes that were made to the IUriBuilder.
9453              */
9454             hr = IUriBuilder_HasBeenModified(builder, &received);
9455             ok(hr == S_OK, "Error: IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9456             if(SUCCEEDED(hr))
9457                 ok(received == TRUE, "Error: Expected received to be TRUE.\n");
9458
9459             hr = IUriBuilder_GetHost(builder, &len, &prop);
9460             ok(hr == S_OK, "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9461             if(SUCCEEDED(hr)) {
9462                 ok(!lstrcmpW(prop, hostW), "Error: Expected %s but got %s instead.\n",
9463                     wine_dbgstr_w(hostW), wine_dbgstr_w(prop));
9464                 ok(len == lstrlenW(hostW), "Error: Expected len to be %d, but was %d instead.\n",
9465                     lstrlenW(hostW), len);
9466             }
9467
9468             hr = IUriBuilder_SetIUri(builder, NULL);
9469             ok(hr == S_OK, "Error: IUriBuilder_SetIUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9470
9471             hr = IUriBuilder_SetHost(builder, hostW);
9472             ok(hr == S_OK, "Error: IUriBuilder_SetHost returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9473             hr = IUriBuilder_HasBeenModified(builder, &received);
9474             ok(hr == S_OK, "Error: IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x.\n",
9475                 hr, S_OK);
9476             if(SUCCEEDED(hr))
9477                 ok(received == TRUE, "Error: Expected received to be TRUE.\n");
9478
9479             hr = IUriBuilder_SetIUri(builder, NULL);
9480             ok(hr == S_OK, "Error: IUriBuilder_SetIUri returned 0x%08x, expected 0x%09x.\n", hr, S_OK);
9481
9482             hr = IUriBuilder_HasBeenModified(builder, &received);
9483             ok(hr == S_OK, "Error: IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x.\n",
9484                 hr, S_OK);
9485             if(SUCCEEDED(hr))
9486                 ok(received == TRUE, "Error: Expected received to be TRUE.\n");
9487
9488             hr = IUriBuilder_GetHost(builder, &len, &prop);
9489             ok(hr == S_OK, "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9490             if(SUCCEEDED(hr)) {
9491                 ok(!lstrcmpW(prop, hostW), "Error: Expected %s but got %s instead.\n",
9492                     wine_dbgstr_w(hostW), wine_dbgstr_w(prop));
9493                 ok(len == lstrlenW(hostW), "Error: Expected len to %d, but was %d instead.\n",
9494                     lstrlenW(hostW), len);
9495             }
9496         }
9497         if(uri) IUri_Release(uri);
9498     }
9499     if(builder) IUriBuilder_Release(builder);
9500 }
9501
9502 /* Test IUriBuilder {Get,Set}IUri functions. */
9503 static void test_IUriBuilder_IUriProperty(void) {
9504     IUriBuilder *builder = NULL;
9505     HRESULT hr;
9506
9507     hr = pCreateIUriBuilder(NULL, 0, 0, &builder);
9508     ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9509     if(SUCCEEDED(hr)) {
9510         IUri *uri = NULL;
9511
9512         hr = IUriBuilder_GetIUri(builder, NULL);
9513         ok(hr == E_POINTER, "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x.\n",
9514             hr, E_POINTER);
9515
9516         hr = pCreateUri(http_urlW, 0, 0, &uri);
9517         if(SUCCEEDED(hr)) {
9518             IUri *test = NULL;
9519             ULONG cur_count, orig_count;
9520
9521             /* IUriBuilder doesn't clone the IUri, it use the same IUri. */
9522             orig_count = get_refcnt(uri);
9523             hr = IUriBuilder_SetIUri(builder, uri);
9524             cur_count = get_refcnt(uri);
9525             if(SUCCEEDED(hr))
9526                 ok(cur_count == orig_count+1, "Error: Expected uri ref count to be %d, but was %d instead.\n",
9527                     orig_count+1, cur_count);
9528
9529             hr = IUriBuilder_SetIUri(builder, NULL);
9530             cur_count = get_refcnt(uri);
9531             if(SUCCEEDED(hr))
9532                 ok(cur_count == orig_count, "Error: Expected uri ref count to be %d, but was %d instead.\n",
9533                     orig_count, cur_count);
9534
9535             /* CreateUri* functions will return back the same IUri if nothing has changed. */
9536             hr = IUriBuilder_SetIUri(builder, uri);
9537             ok(hr == S_OK, "Error: IUriBuilder_SetIUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9538             orig_count = get_refcnt(uri);
9539
9540             hr = IUriBuilder_CreateUri(builder, 0, 0, 0, &test);
9541             ok(hr == S_OK, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9542             if(SUCCEEDED(hr)) {
9543                 cur_count = get_refcnt(uri);
9544                 ok(cur_count == orig_count+1, "Error: Expected uri ref count to be %d, but was %d instead.\n",
9545                     orig_count+1, cur_count);
9546                 ok(test == uri, "Error: Expected test to be %p, but was %p instead.\n",
9547                     uri, test);
9548             }
9549             if(test) IUri_Release(test);
9550
9551             test = NULL;
9552             hr = IUriBuilder_CreateUri(builder, -1, 0, 0, &test);
9553             ok(hr == S_OK, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9554             if(SUCCEEDED(hr)) {
9555                 cur_count = get_refcnt(uri);
9556                 ok(cur_count == orig_count+1, "Error: Expected uri ref count to be %d, but was %d instead.\n",
9557                     orig_count+1, cur_count);
9558                 ok(test == uri, "Error: Expected test to be %p, but was %p instead.\n", uri, test);
9559             }
9560             if(test) IUri_Release(test);
9561
9562             /* Doesn't return the same IUri, if the flag combination is different then the one that created
9563              * the base IUri.
9564              */
9565             test = NULL;
9566             hr = IUriBuilder_CreateUri(builder, Uri_CREATE_ALLOW_RELATIVE, 0, 0, &test);
9567             ok(hr == S_OK, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9568             if(SUCCEEDED(hr))
9569                 ok(test != uri, "Error: Wasn't expecting 'test' to be 'uri'\n");
9570
9571             if(test) IUri_Release(test);
9572
9573             /* Still returns the same IUri, even though the base one wasn't created with CREATE_CANONICALIZE
9574              * explicitly set (because it's a default flags).
9575              */
9576             test = NULL;
9577             hr = IUriBuilder_CreateUri(builder, Uri_CREATE_CANONICALIZE, 0, 0, &test);
9578             ok(hr == S_OK, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9579             if(SUCCEEDED(hr)) {
9580                 cur_count = get_refcnt(uri);
9581                 ok(cur_count == orig_count+1, "Error: Expected uri ref count to be %d, but was %d instead.\n",
9582                     orig_count+1, cur_count);
9583                 ok(test == uri, "Error: Expected 'test' to be %p, but was %p instead.\n", uri, test);
9584             }
9585             if(test) IUri_Release(test);
9586
9587             test = NULL;
9588             hr = IUriBuilder_CreateUriSimple(builder, 0, 0, &test);
9589             ok(hr == S_OK, "Error: IUriBuilder_CreateUriSimple returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9590             if(SUCCEEDED(hr)) {
9591                 cur_count = get_refcnt(uri);
9592                 ok(cur_count == orig_count+1, "Error: Expected uri ref count to be %d, but was %d instead.\n",
9593                     orig_count+1, cur_count);
9594                 ok(test == uri, "Error: Expected test to be %p, but was %p instead.\n", uri, test);
9595             }
9596             if(test) IUri_Release(test);
9597
9598             test = NULL;
9599             hr = IUriBuilder_CreateUriWithFlags(builder, 0, 0, 0, 0, &test);
9600             ok(hr == S_OK, "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x.\n",
9601                 hr, S_OK);
9602             if(SUCCEEDED(hr)) {
9603                 cur_count = get_refcnt(uri);
9604                 ok(cur_count == orig_count+1, "Error: Expected uri ref count to be %d, but was %d instead.\n",
9605                     orig_count+1, cur_count);
9606                 ok(test == uri, "Error: Expected test to be %p, but was %p instead.\n", uri, test);
9607             }
9608             if(test) IUri_Release(test);
9609
9610             /* Doesn't return the same IUri, if the flag combination is different then the one that created
9611              * the base IUri.
9612              */
9613             test = NULL;
9614             hr = IUriBuilder_CreateUriWithFlags(builder, Uri_CREATE_ALLOW_RELATIVE, 0, 0, 0, &test);
9615             ok(hr == S_OK, "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9616             if(SUCCEEDED(hr))
9617                 ok(test != uri, "Error: Wasn't expecting 'test' to be 'uri'\n");
9618
9619             if(test) IUri_Release(test);
9620
9621             /* Still returns the same IUri, even though the base one wasn't created with CREATE_CANONICALIZE
9622              * explicitly set (because it's a default flags).
9623              */
9624             test = NULL;
9625             hr = IUriBuilder_CreateUriWithFlags(builder, Uri_CREATE_CANONICALIZE, 0, 0, 0, &test);
9626             ok(hr == S_OK, "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9627             if(SUCCEEDED(hr)) {
9628                 cur_count = get_refcnt(uri);
9629                 ok(cur_count == orig_count+1, "Error: Expected uri ref count to be %d, but was %d instead.\n",
9630                     orig_count+1, cur_count);
9631                 ok(test == uri, "Error: Expected 'test' to be %p, but was %p instead.\n", uri, test);
9632             }
9633             if(test) IUri_Release(test);
9634         }
9635         if(uri) IUri_Release(uri);
9636     }
9637     if(builder) IUriBuilder_Release(builder);
9638 }
9639
9640 static void test_IUriBuilder_RemoveProperties(void) {
9641     IUriBuilder *builder = NULL;
9642     HRESULT hr;
9643     DWORD i;
9644
9645     hr = pCreateIUriBuilder(NULL, 0, 0, &builder);
9646     ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9647     if(SUCCEEDED(hr)) {
9648         /* Properties that can't be removed. */
9649         const DWORD invalid = Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_RAW_URI|Uri_HAS_HOST_TYPE|
9650                               Uri_HAS_SCHEME|Uri_HAS_ZONE;
9651
9652         for(i = Uri_PROPERTY_STRING_START; i <= Uri_PROPERTY_DWORD_LAST; ++i) {
9653             hr = IUriBuilder_RemoveProperties(builder, i << 1);
9654             if((i << 1) & invalid) {
9655                 ok(hr == E_INVALIDARG,
9656                     "Error: IUriBuilder_RemoveProperties returned 0x%08x, expected 0x%08x with prop=%d.\n",
9657                     hr, E_INVALIDARG, i);
9658             } else {
9659                 ok(hr == S_OK,
9660                     "Error: IUriBuilder_RemoveProperties returned 0x%08x, expected 0x%08x with prop=%d.\n",
9661                     hr, S_OK, i);
9662             }
9663         }
9664
9665         /* Also doesn't accept anything that's outside the range of the
9666          * Uri_HAS flags.
9667          */
9668         hr = IUriBuilder_RemoveProperties(builder, (Uri_PROPERTY_DWORD_LAST+1) << 1);
9669         ok(hr == E_INVALIDARG, "Error: IUriBuilder_RemoveProperties returned 0x%08x, expected 0x%08x.\n",
9670             hr, E_INVALIDARG);
9671     }
9672     if(builder) IUriBuilder_Release(builder);
9673
9674     for(i = 0; i < sizeof(uri_builder_remove_tests)/sizeof(uri_builder_remove_tests[0]); ++i) {
9675         uri_builder_remove_test test = uri_builder_remove_tests[i];
9676         IUri *uri = NULL;
9677         LPWSTR uriW;
9678
9679         uriW = a2w(test.uri);
9680         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
9681         if(SUCCEEDED(hr)) {
9682             builder = NULL;
9683
9684             hr = pCreateIUriBuilder(uri, 0, 0, &builder);
9685             if(test.create_builder_todo) {
9686                 todo_wine {
9687                     ok(hr == test.create_builder_expected,
9688                         "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x on test %d.\n",
9689                         hr, test.create_builder_expected, i);
9690                 }
9691             } else {
9692                 ok(hr == test.create_builder_expected,
9693                     "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x on test %d.\n",
9694                     hr, test.create_builder_expected, i);
9695             }
9696             if(SUCCEEDED(hr)) {
9697                 hr = IUriBuilder_RemoveProperties(builder, test.remove_properties);
9698                 if(test.remove_todo) {
9699                     todo_wine {
9700                         ok(hr == test.remove_expected,
9701                             "Error: IUriBuilder_RemoveProperties returned 0x%08x, expected 0x%08x on test %d.\n",
9702                             hr, test.remove_expected, i);
9703                     }
9704                 } else {
9705                     ok(hr == test.remove_expected,
9706                         "Error: IUriBuilder returned 0x%08x, expected 0x%08x on test %d.\n",
9707                         hr, test.remove_expected, i);
9708                 }
9709                 if(SUCCEEDED(hr)) {
9710                     IUri *result = NULL;
9711
9712                     hr = IUriBuilder_CreateUri(builder, test.expected_flags, 0, 0, &result);
9713                     if(test.expected_todo) {
9714                         todo_wine {
9715                             ok(hr == test.expected_hres,
9716                                 "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x on test %d.\n",
9717                                 hr, test.expected_hres, i);
9718                         }
9719                     } else {
9720                         ok(hr == test.expected_hres,
9721                             "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x on test %d.\n",
9722                             hr, test.expected_hres, i);
9723                     }
9724                     if(SUCCEEDED(hr)) {
9725                         BSTR received = NULL;
9726
9727                         hr = IUri_GetAbsoluteUri(result, &received);
9728                         ok(hr == S_OK, "Error: Expected S_OK, but got 0x%08x instead.\n", hr);
9729                         ok(!strcmp_aw(test.expected_uri, received),
9730                             "Error: Expected %s but got %s instead on test %d.\n",
9731                             test.expected_uri, wine_dbgstr_w(received), i);
9732                         SysFreeString(received);
9733                     }
9734                     if(result) IUri_Release(result);
9735                 }
9736             }
9737             if(builder) IUriBuilder_Release(builder);
9738         }
9739         if(uri) IUri_Release(uri);
9740         heap_free(uriW);
9741     }
9742 }
9743
9744 static void test_IUriBuilder_Misc(void) {
9745     HRESULT hr;
9746     IUri *uri;
9747
9748     hr = pCreateUri(http_urlW, 0, 0, &uri);
9749     if(SUCCEEDED(hr)) {
9750         IUriBuilder *builder;
9751
9752         hr = pCreateIUriBuilder(uri, 0, 0, &builder);
9753         ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9754         if(SUCCEEDED(hr)) {
9755             BOOL has = -1;
9756             DWORD port = -1;
9757
9758             hr = IUriBuilder_GetPort(builder, &has, &port);
9759             ok(hr == S_OK, "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9760             if(SUCCEEDED(hr)) {
9761                 /* 'has' will be set to FALSE, even though uri had a port. */
9762                 ok(has == FALSE, "Error: Expected 'has' to be FALSE, was %d instead.\n", has);
9763                 /* Still sets 'port' to 80. */
9764                 ok(port == 80, "Error: Expected the port to be 80, but, was %d instead.\n", port);
9765             }
9766         }
9767         if(builder) IUriBuilder_Release(builder);
9768     }
9769     if(uri) IUri_Release(uri);
9770 }
9771
9772 static void test_IUriBuilderFactory(void) {
9773     HRESULT hr;
9774     IUri *uri;
9775     IUriBuilderFactory *factory;
9776     IUriBuilder *builder;
9777
9778     hr = pCreateUri(http_urlW, 0, 0, &uri);
9779     ok(SUCCEEDED(hr), "Error: CreateUri returned 0x%08x.\n", hr);
9780     if(SUCCEEDED(hr)) {
9781         factory = NULL;
9782         hr = IUri_QueryInterface(uri, &IID_IUriBuilderFactory, (void**)&factory);
9783         ok(hr == S_OK, "Error: Expected S_OK, but got 0x%08x.\n", hr);
9784         ok(factory != NULL, "Error: Expected 'factory' to not be NULL.\n");
9785
9786         if(SUCCEEDED(hr)) {
9787             builder = (void*) 0xdeadbeef;
9788             hr = IUriBuilderFactory_CreateIUriBuilder(factory, 10, 0, &builder);
9789             ok(hr == E_INVALIDARG, "Error: CreateInitializedIUriBuilder returned 0x%08x, expected 0x%08x.\n",
9790                 hr, E_INVALIDARG);
9791             ok(!builder, "Error: Expected 'builder' to be NULL, but was %p.\n", builder);
9792
9793             builder = (void*) 0xdeadbeef;
9794             hr = IUriBuilderFactory_CreateIUriBuilder(factory, 0, 10, &builder);
9795             ok(hr == E_INVALIDARG, "Error: CreateInitializedIUriBuilder returned 0x%08x, expected 0x%08x.\n",
9796                 hr, E_INVALIDARG);
9797             ok(!builder, "Error: Expected 'builder' to be NULL, but was %p.\n", builder);
9798
9799             hr = IUriBuilderFactory_CreateIUriBuilder(factory, 0, 0, NULL);
9800             ok(hr == E_POINTER, "Error: CreateInitializedIUriBuilder returned 0x%08x, expected 0x%08x.\n",
9801                 hr, E_POINTER);
9802
9803             builder = NULL;
9804             hr = IUriBuilderFactory_CreateIUriBuilder(factory, 0, 0, &builder);
9805             ok(hr == S_OK, "Error: CreateInitializedIUriBuilder returned 0x%08x, expected 0x%08x.\n",
9806                 hr, S_OK);
9807             if(SUCCEEDED(hr)) {
9808                 IUri *tmp = (void*) 0xdeadbeef;
9809                 LPCWSTR result;
9810                 DWORD result_len;
9811
9812                 hr = IUriBuilder_GetIUri(builder, &tmp);
9813                 ok(hr == S_OK, "Error: GetIUri returned 0x%08x, expected 0x%08x.\n",
9814                     hr, S_OK);
9815                 ok(!tmp, "Error: Expected 'tmp' to be NULL, but was %p instead.\n", tmp);
9816
9817                 hr = IUriBuilder_GetHost(builder, &result_len, &result);
9818                 ok(hr == S_FALSE, "Error: GetHost returned 0x%08x, expected 0x%08x.\n",
9819                     hr, S_FALSE);
9820             }
9821             if(builder) IUriBuilder_Release(builder);
9822
9823             builder = (void*) 0xdeadbeef;
9824             hr = IUriBuilderFactory_CreateInitializedIUriBuilder(factory, 10, 0, &builder);
9825             ok(hr == E_INVALIDARG, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n",
9826                 hr, E_INVALIDARG);
9827             ok(!builder, "Error: Expected 'builder' to be NULL, but was %p.\n", builder);
9828
9829             builder = (void*) 0xdeadbeef;
9830             hr = IUriBuilderFactory_CreateInitializedIUriBuilder(factory, 0, 10, &builder);
9831             ok(hr == E_INVALIDARG, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n",
9832                 hr, E_INVALIDARG);
9833             ok(!builder, "Error: Expected 'builder' to be NULL, but was %p.\n", builder);
9834
9835             hr = IUriBuilderFactory_CreateInitializedIUriBuilder(factory, 0, 0, NULL);
9836             ok(hr == E_POINTER, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n",
9837                 hr, E_POINTER);
9838
9839             builder = NULL;
9840             hr = IUriBuilderFactory_CreateInitializedIUriBuilder(factory, 0, 0, &builder);
9841             ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n",
9842                 hr, S_OK);
9843             if(SUCCEEDED(hr)) {
9844                 IUri *tmp = NULL;
9845
9846                 hr = IUriBuilder_GetIUri(builder, &tmp);
9847                 ok(hr == S_OK, "Error: GetIUri return 0x%08x, expected 0x%08x.\n",
9848                     hr, S_OK);
9849                 ok(tmp == uri, "Error: Expected tmp to be %p, but was %p.\n", uri, tmp);
9850                 if(uri) IUri_Release(uri);
9851             }
9852             if(builder) IUriBuilder_Release(builder);
9853         }
9854         if(factory) IUriBuilderFactory_Release(factory);
9855     }
9856     if(uri) IUri_Release(uri);
9857 }
9858
9859 static void test_CoInternetCombineIUri(void) {
9860     HRESULT hr;
9861     IUri *base, *relative, *result;
9862     DWORD i;
9863
9864     base = NULL;
9865     hr = pCreateUri(http_urlW, 0, 0, &base);
9866     ok(SUCCEEDED(hr), "Error: Expected CreateUri to succeed, got 0x%08x.\n", hr);
9867     if(SUCCEEDED(hr)) {
9868         result = (void*) 0xdeadbeef;
9869         hr = pCoInternetCombineIUri(base, NULL, 0, &result, 0);
9870         ok(hr == E_INVALIDARG, "Error: CoInternetCombineIUri returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
9871         ok(!result, "Error: Expected 'result' to be NULL, was %p.\n", result);
9872     }
9873
9874     relative = NULL;
9875     hr = pCreateUri(http_urlW, 0, 0, &relative);
9876     ok(SUCCEEDED(hr), "Error: Expected CreateUri to succeed, got 0x%08x.\n", hr);
9877     if(SUCCEEDED(hr)) {
9878         result = (void*) 0xdeadbeef;
9879         hr = pCoInternetCombineIUri(NULL, relative, 0, &result, 0);
9880         ok(hr == E_INVALIDARG, "Error: CoInternetCombineIUri returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
9881         ok(!result, "Error: Expected 'result' to be NULL, was %p.\n", result);
9882     }
9883
9884     hr = pCoInternetCombineIUri(base, relative, 0, NULL, 0);
9885     ok(hr == E_INVALIDARG, "Error: CoInternetCombineIUri returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
9886
9887     if(base) IUri_Release(base);
9888     if(relative) IUri_Release(relative);
9889
9890     for(i = 0; i < sizeof(uri_combine_tests)/sizeof(uri_combine_tests[0]); ++i) {
9891         LPWSTR baseW = a2w(uri_combine_tests[i].base_uri);
9892
9893         hr = pCreateUri(baseW, uri_combine_tests[i].base_create_flags, 0, &base);
9894         ok(SUCCEEDED(hr), "Error: Expected CreateUri to succeed, got 0x%08x on uri_combine_tests[%d].\n", hr, i);
9895         if(SUCCEEDED(hr)) {
9896             LPWSTR relativeW = a2w(uri_combine_tests[i].relative_uri);
9897
9898             hr = pCreateUri(relativeW, uri_combine_tests[i].relative_create_flags, 0, &relative);
9899             ok(SUCCEEDED(hr), "Error: Expected CreateUri to succeed, got 0x%08x on uri_combine_tests[%d].\n", hr, i);
9900             if(SUCCEEDED(hr)) {
9901                 result = NULL;
9902
9903                 hr = pCoInternetCombineIUri(base, relative, uri_combine_tests[i].combine_flags, &result, 0);
9904                 if(uri_combine_tests[i].todo) {
9905                     todo_wine {
9906                         ok(hr == uri_combine_tests[i].expected,
9907                             "Error: CoInternetCombineIUri returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].\n",
9908                             hr, uri_combine_tests[i].expected, i);
9909                     }
9910                 } else {
9911                     ok(hr == uri_combine_tests[i].expected,
9912                         "Error: CoInternetCombineIUri returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].\n",
9913                         hr, uri_combine_tests[i]. expected, i);
9914                 }
9915                 if(SUCCEEDED(hr)) {
9916                     DWORD j;
9917
9918                     for(j = 0; j < sizeof(uri_combine_tests[i].str_props)/sizeof(uri_combine_tests[i].str_props[0]); ++j) {
9919                         uri_combine_str_property prop = uri_combine_tests[i].str_props[j];
9920                         BSTR received;
9921
9922                         hr = IUri_GetPropertyBSTR(result, j, &received, 0);
9923                         if(prop.todo) {
9924                             todo_wine {
9925                                 ok(hr == prop.expected,
9926                                     "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].str_props[%d].\n",
9927                                     hr, prop.expected, i, j);
9928                             }
9929                             todo_wine {
9930                                 ok(!strcmp_aw(prop.value, received) ||
9931                                    broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
9932                                     "Error: Expected %s but got %s instead on uri_combine_tests[%d].str_props[%d].\n",
9933                                     prop.value, wine_dbgstr_w(received), i, j);
9934                             }
9935                         } else {
9936                             ok(hr == prop.expected,
9937                                 "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].str_props[%d].\n",
9938                                 hr, prop.expected, i, j);
9939                             ok(!strcmp_aw(prop.value, received) ||
9940                                broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
9941                                 "Error: Expected %s but got %s instead on uri_combine_tests[%d].str_props[%d].\n",
9942                                 prop.value, wine_dbgstr_w(received), i, j);
9943                         }
9944                         SysFreeString(received);
9945                     }
9946
9947                     for(j = 0; j < sizeof(uri_combine_tests[i].dword_props)/sizeof(uri_combine_tests[i].dword_props[0]); ++j) {
9948                         uri_dword_property prop = uri_combine_tests[i].dword_props[j];
9949                         DWORD received;
9950
9951                         hr = IUri_GetPropertyDWORD(result, j+Uri_PROPERTY_DWORD_START, &received, 0);
9952                         if(prop.todo) {
9953                             todo_wine {
9954                                 ok(hr == prop.expected,
9955                                     "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].dword_props[%d].\n",
9956                                     hr, prop.expected, i, j);
9957                             }
9958                             todo_wine {
9959                                 ok(prop.value == received, "Error: Expected %d, but got %d instead on uri_combine_tests[%d].dword_props[%d].\n",
9960                                     prop.value, received, i, j);
9961                             }
9962                         } else {
9963                             ok(hr == prop.expected,
9964                                 "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].dword_props[%d].\n",
9965                                 hr, prop.expected, i, j);
9966                             ok(prop.value == received, "Error: Expected %d, but got %d instead on uri_combine_tests[%d].dword_props[%d].\n",
9967                                 prop.value, received, i, j);
9968                         }
9969                     }
9970                 }
9971                 if(result) IUri_Release(result);
9972             }
9973             if(relative) IUri_Release(relative);
9974             heap_free(relativeW);
9975         }
9976         if(base) IUri_Release(base);
9977         heap_free(baseW);
9978     }
9979 }
9980
9981 static HRESULT WINAPI InternetProtocolInfo_QueryInterface(IInternetProtocolInfo *iface,
9982                                                           REFIID riid, void **ppv)
9983 {
9984     ok(0, "unexpected call\n");
9985     return E_NOINTERFACE;
9986 }
9987
9988 static ULONG WINAPI InternetProtocolInfo_AddRef(IInternetProtocolInfo *iface)
9989 {
9990     return 2;
9991 }
9992
9993 static ULONG WINAPI InternetProtocolInfo_Release(IInternetProtocolInfo *iface)
9994 {
9995     return 1;
9996 }
9997
9998 static HRESULT WINAPI InternetProtocolInfo_ParseUrl(IInternetProtocolInfo *iface, LPCWSTR pwzUrl,
9999         PARSEACTION ParseAction, DWORD dwParseFlags, LPWSTR pwzResult, DWORD cchResult,
10000         DWORD *pcchResult, DWORD dwReserved)
10001 {
10002     CHECK_EXPECT(ParseUrl);
10003     ok(!lstrcmpW(pwzUrl, parse_urlW), "Error: Expected %s, but got %s instead.\n",
10004         wine_dbgstr_w(parse_urlW), wine_dbgstr_w(pwzUrl));
10005     ok(ParseAction == parse_action, "Error: Expected %d, but got %d.\n", parse_action, ParseAction);
10006     ok(dwParseFlags == parse_flags, "Error: Expected 0x%08x, but got 0x%08x.\n", parse_flags, dwParseFlags);
10007     ok(cchResult == 200, "Error: Got %d.\n", cchResult);
10008
10009     memcpy(pwzResult, parse_resultW, sizeof(parse_resultW));
10010     *pcchResult = lstrlenW(parse_resultW);
10011
10012     return S_OK;
10013 }
10014
10015 static HRESULT WINAPI InternetProtocolInfo_CombineUrl(IInternetProtocolInfo *iface,
10016         LPCWSTR pwzBaseUrl, LPCWSTR pwzRelativeUrl, DWORD dwCombineFlags,
10017         LPWSTR pwzResult, DWORD cchResult, DWORD *pcchResult, DWORD dwReserved)
10018 {
10019     CHECK_EXPECT(CombineUrl);
10020     ok(!lstrcmpW(pwzBaseUrl, combine_baseW), "Error: Expected %s, but got %s instead.\n",
10021         wine_dbgstr_w(combine_baseW), wine_dbgstr_w(pwzBaseUrl));
10022     ok(!lstrcmpW(pwzRelativeUrl, combine_relativeW), "Error: Expected %s, but got %s instead.\n",
10023         wine_dbgstr_w(combine_relativeW), wine_dbgstr_w(pwzRelativeUrl));
10024     ok(dwCombineFlags == (URL_DONT_SIMPLIFY|URL_FILE_USE_PATHURL|URL_DONT_UNESCAPE_EXTRA_INFO),
10025         "Error: Expected 0, but got 0x%08x.\n", dwCombineFlags);
10026     ok(cchResult == INTERNET_MAX_URL_LENGTH+1, "Error: Got %d.\n", cchResult);
10027
10028     memcpy(pwzResult, combine_resultW, sizeof(combine_resultW));
10029     *pcchResult = lstrlenW(combine_resultW);
10030
10031     return S_OK;
10032 }
10033
10034 static HRESULT WINAPI InternetProtocolInfo_CompareUrl(IInternetProtocolInfo *iface,
10035         LPCWSTR pwzUrl1, LPCWSTR pwzUrl2, DWORD dwCompareFlags)
10036 {
10037     ok(0, "unexpected call\n");
10038     return E_NOTIMPL;
10039 }
10040
10041 static HRESULT WINAPI InternetProtocolInfo_QueryInfo(IInternetProtocolInfo *iface,
10042         LPCWSTR pwzUrl, QUERYOPTION OueryOption, DWORD dwQueryFlags, LPVOID pBuffer,
10043         DWORD cbBuffer, DWORD *pcbBuf, DWORD dwReserved)
10044 {
10045     ok(0, "unexpected call\n");
10046     return E_NOTIMPL;
10047 }
10048
10049 static const IInternetProtocolInfoVtbl InternetProtocolInfoVtbl = {
10050     InternetProtocolInfo_QueryInterface,
10051     InternetProtocolInfo_AddRef,
10052     InternetProtocolInfo_Release,
10053     InternetProtocolInfo_ParseUrl,
10054     InternetProtocolInfo_CombineUrl,
10055     InternetProtocolInfo_CompareUrl,
10056     InternetProtocolInfo_QueryInfo
10057 };
10058
10059 static IInternetProtocolInfo protocol_info = { &InternetProtocolInfoVtbl };
10060
10061 static HRESULT WINAPI ClassFactory_QueryInterface(IClassFactory *iface, REFIID riid, void **ppv)
10062 {
10063     if(IsEqualGUID(&IID_IInternetProtocolInfo, riid)) {
10064         *ppv = &protocol_info;
10065         return S_OK;
10066     }
10067
10068     ok(0, "unexpected call\n");
10069     return E_NOINTERFACE;
10070 }
10071
10072 static ULONG WINAPI ClassFactory_AddRef(IClassFactory *iface)
10073 {
10074     return 2;
10075 }
10076
10077 static ULONG WINAPI ClassFactory_Release(IClassFactory *iface)
10078 {
10079     return 1;
10080 }
10081
10082 static HRESULT WINAPI ClassFactory_CreateInstance(IClassFactory *iface, IUnknown *pOuter,
10083                                         REFIID riid, void **ppv)
10084 {
10085     ok(0, "unexpected call\n");
10086     return E_NOTIMPL;
10087 }
10088
10089 static HRESULT WINAPI ClassFactory_LockServer(IClassFactory *iface, BOOL dolock)
10090 {
10091     ok(0, "unexpected call\n");
10092     return S_OK;
10093 }
10094
10095 static const IClassFactoryVtbl ClassFactoryVtbl = {
10096     ClassFactory_QueryInterface,
10097     ClassFactory_AddRef,
10098     ClassFactory_Release,
10099     ClassFactory_CreateInstance,
10100     ClassFactory_LockServer
10101 };
10102
10103 static IClassFactory protocol_cf = { &ClassFactoryVtbl };
10104
10105 static void register_protocols(void)
10106 {
10107     IInternetSession *session;
10108     HRESULT hres;
10109
10110     hres = pCoInternetGetSession(0, &session, 0);
10111     ok(hres == S_OK, "CoInternetGetSession failed: %08x\n", hres);
10112     if(FAILED(hres))
10113         return;
10114
10115     hres = IInternetSession_RegisterNameSpace(session, &protocol_cf, &IID_NULL,
10116             winetestW, 0, NULL, 0);
10117     ok(hres == S_OK, "RegisterNameSpace failed: %08x\n", hres);
10118
10119     IInternetSession_Release(session);
10120 }
10121
10122 static void unregister_protocols(void) {
10123     IInternetSession *session;
10124     HRESULT hr;
10125
10126     hr = pCoInternetGetSession(0, &session, 0);
10127     ok(hr == S_OK, "CoInternetGetSession failed: 0x%08x\n", hr);
10128     if(FAILED(hr))
10129         return;
10130
10131     hr = IInternetSession_UnregisterNameSpace(session, &protocol_cf, winetestW);
10132     ok(hr == S_OK, "UnregisterNameSpace failed: 0x%08x\n", hr);
10133
10134     IInternetSession_Release(session);
10135 }
10136
10137 static void test_CoInternetCombineIUri_Pluggable(void) {
10138     HRESULT hr;
10139     IUri *base = NULL;
10140
10141     hr = pCreateUri(combine_baseW, 0, 0, &base);
10142     ok(SUCCEEDED(hr), "Error: CreateUri returned 0x%08x.\n", hr);
10143     if(SUCCEEDED(hr)) {
10144         IUri *relative = NULL;
10145
10146         hr = pCreateUri(combine_relativeW, Uri_CREATE_ALLOW_RELATIVE, 0, &relative);
10147         ok(SUCCEEDED(hr), "Error: CreateUri returned 0x%08x.\n", hr);
10148         if(SUCCEEDED(hr)) {
10149             IUri *result = NULL;
10150
10151             SET_EXPECT(CombineUrl);
10152
10153             hr = pCoInternetCombineIUri(base, relative, URL_DONT_SIMPLIFY|URL_FILE_USE_PATHURL|URL_DONT_UNESCAPE_EXTRA_INFO,
10154                                         &result, 0);
10155             ok(hr == S_OK, "Error: CoInternetCombineIUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
10156
10157             CHECK_CALLED(CombineUrl);
10158
10159             if(SUCCEEDED(hr)) {
10160                 BSTR received = NULL;
10161                 hr = IUri_GetAbsoluteUri(result, &received);
10162                 ok(hr == S_OK, "Error: Expected S_OK, but got 0x%08x instead.\n", hr);
10163                 if(SUCCEEDED(hr)) {
10164                     ok(!lstrcmpW(combine_resultW, received), "Error: Expected %s, but got %s.\n",
10165                         wine_dbgstr_w(combine_resultW), wine_dbgstr_w(received));
10166                 }
10167                 SysFreeString(received);
10168             }
10169             if(result) IUri_Release(result);
10170         }
10171         if(relative) IUri_Release(relative);
10172     }
10173     if(base) IUri_Release(base);
10174 }
10175
10176 static void test_CoInternetCombineUrlEx(void) {
10177     HRESULT hr;
10178     IUri *base, *result;
10179     DWORD i;
10180
10181     base = NULL;
10182     hr = pCreateUri(http_urlW, 0, 0, &base);
10183     ok(SUCCEEDED(hr), "Error: CreateUri returned 0x%08x.\n", hr);
10184     if(SUCCEEDED(hr)) {
10185         result = (void*) 0xdeadbeef;
10186         hr = pCoInternetCombineUrlEx(base, NULL, 0, &result, 0);
10187         ok(hr == E_UNEXPECTED, "Error: CoInternetCombineUrlEx returned 0x%08x, expected 0x%08x.\n",
10188             hr, E_UNEXPECTED);
10189         ok(!result, "Error: Expected 'result' to be NULL was %p instead.\n", result);
10190     }
10191
10192     result = (void*) 0xdeadbeef;
10193     hr = pCoInternetCombineUrlEx(NULL, http_urlW, 0, &result, 0);
10194     ok(hr == E_INVALIDARG, "Error: CoInternetCombineUrlEx returned 0x%08x, expected 0x%08x.\n",
10195         hr, E_INVALIDARG);
10196     ok(!result, "Error: Expected 'result' to be NULL, but was %p instead.\n", result);
10197
10198     result = (void*) 0xdeadbeef;
10199     hr = pCoInternetCombineUrlEx(NULL, NULL, 0, &result, 0);
10200     ok(hr == E_UNEXPECTED, "Error: CoInternetCombineUrlEx returned 0x%08x, expected 0x%08x.\n",
10201         hr, E_UNEXPECTED);
10202     ok(!result, "Error: Expected 'result' to be NULL, but was %p instead.\n", result);
10203
10204     hr = pCoInternetCombineUrlEx(base, http_urlW, 0, NULL, 0);
10205     ok(hr == E_POINTER, "Error: CoInternetCombineUrlEx returned 0x%08x, expected 0x%08x.\n",
10206         hr, E_POINTER);
10207     if(base) IUri_Release(base);
10208
10209     for(i = 0; i < sizeof(uri_combine_tests)/sizeof(uri_combine_tests[0]); ++i) {
10210         LPWSTR baseW = a2w(uri_combine_tests[i].base_uri);
10211
10212         hr = pCreateUri(baseW, uri_combine_tests[i].base_create_flags, 0, &base);
10213         ok(SUCCEEDED(hr), "Error: CreateUri returned 0x%08x on uri_combine_tests[%d].\n", hr, i);
10214         if(SUCCEEDED(hr)) {
10215             LPWSTR relativeW = a2w(uri_combine_tests[i].relative_uri);
10216
10217             hr = pCoInternetCombineUrlEx(base, relativeW, uri_combine_tests[i].combine_flags,
10218                                          &result, 0);
10219             if(uri_combine_tests[i].todo) {
10220                 todo_wine {
10221                     ok(hr == uri_combine_tests[i].expected,
10222                         "Error: CoInternetCombineUrlEx returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].\n",
10223                         hr, uri_combine_tests[i].expected, i);
10224                 }
10225             } else {
10226                 ok(hr == uri_combine_tests[i].expected,
10227                     "Error: CoInternetCombineUrlEx returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].\n",
10228                     hr, uri_combine_tests[i]. expected, i);
10229             }
10230             if(SUCCEEDED(hr)) {
10231                 DWORD j;
10232
10233                 for(j = 0; j < sizeof(uri_combine_tests[i].str_props)/sizeof(uri_combine_tests[i].str_props[0]); ++j) {
10234                     uri_combine_str_property prop = uri_combine_tests[i].str_props[j];
10235                     BSTR received;
10236                     LPCSTR value = (prop.value_ex) ? prop.value_ex : prop.value;
10237
10238                     hr = IUri_GetPropertyBSTR(result, j, &received, 0);
10239                     if(prop.todo) {
10240                         todo_wine {
10241                             ok(hr == prop.expected,
10242                                 "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].str_props[%d].\n",
10243                                 hr, prop.expected, i, j);
10244                         }
10245                         todo_wine {
10246                             ok(!strcmp_aw(value, received) ||
10247                                broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
10248                                 "Error: Expected %s but got %s instead on uri_combine_tests[%d].str_props[%d].\n",
10249                                 value, wine_dbgstr_w(received), i, j);
10250                         }
10251                     } else {
10252                         ok(hr == prop.expected,
10253                             "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].str_props[%d].\n",
10254                             hr, prop.expected, i, j);
10255                         ok(!strcmp_aw(value, received) ||
10256                            broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
10257                             "Error: Expected %s but got %s instead on uri_combine_tests[%d].str_props[%d].\n",
10258                             value, wine_dbgstr_w(received), i, j);
10259                     }
10260                     SysFreeString(received);
10261                 }
10262
10263                 for(j = 0; j < sizeof(uri_combine_tests[i].dword_props)/sizeof(uri_combine_tests[i].dword_props[0]); ++j) {
10264                     uri_dword_property prop = uri_combine_tests[i].dword_props[j];
10265                     DWORD received;
10266
10267                     hr = IUri_GetPropertyDWORD(result, j+Uri_PROPERTY_DWORD_START, &received, 0);
10268                     if(prop.todo) {
10269                         todo_wine {
10270                             ok(hr == prop.expected,
10271                                 "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].dword_props[%d].\n",
10272                                 hr, prop.expected, i, j);
10273                         }
10274                         todo_wine {
10275                             ok(prop.value == received, "Error: Expected %d, but got %d instead on uri_combine_tests[%d].dword_props[%d].\n",
10276                                 prop.value, received, i, j);
10277                         }
10278                     } else {
10279                         ok(hr == prop.expected,
10280                             "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].dword_props[%d].\n",
10281                             hr, prop.expected, i, j);
10282                         ok(prop.value == received, "Error: Expected %d, but got %d instead on uri_combine_tests[%d].dword_props[%d].\n",
10283                             prop.value, received, i, j);
10284                     }
10285                 }
10286             }
10287             if(result) IUri_Release(result);
10288             heap_free(relativeW);
10289         }
10290         if(base) IUri_Release(base);
10291         heap_free(baseW);
10292     }
10293 }
10294
10295 static void test_CoInternetCombineUrlEx_Pluggable(void) {
10296     HRESULT hr;
10297     IUri *base = NULL;
10298
10299     hr = pCreateUri(combine_baseW, 0, 0, &base);
10300     ok(SUCCEEDED(hr), "Error: CreateUri returned 0x%08x.\n", hr);
10301     if(SUCCEEDED(hr)) {
10302         IUri *result = NULL;
10303
10304         SET_EXPECT(CombineUrl);
10305
10306         hr = pCoInternetCombineUrlEx(base, combine_relativeW, URL_DONT_SIMPLIFY|URL_FILE_USE_PATHURL|URL_DONT_UNESCAPE_EXTRA_INFO,
10307                                      &result, 0);
10308         ok(hr == S_OK, "Error: CoInternetCombineUrlEx returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
10309
10310         CHECK_CALLED(CombineUrl);
10311
10312         if(SUCCEEDED(hr)) {
10313             BSTR received = NULL;
10314             hr = IUri_GetAbsoluteUri(result, &received);
10315             ok(hr == S_OK, "Error: Expected S_OK, but got 0x%08x instead.\n", hr);
10316             if(SUCCEEDED(hr)) {
10317                 ok(!lstrcmpW(combine_resultW, received), "Error: Expected %s, but got %s.\n",
10318                     wine_dbgstr_w(combine_resultW), wine_dbgstr_w(received));
10319             }
10320             SysFreeString(received);
10321         }
10322         if(result) IUri_Release(result);
10323     }
10324     if(base) IUri_Release(base);
10325 }
10326
10327 static void test_CoInternetParseIUri_InvalidArgs(void) {
10328     HRESULT hr;
10329     IUri *uri = NULL;
10330     WCHAR tmp[3];
10331     DWORD result = -1;
10332
10333     hr = pCoInternetParseIUri(NULL, PARSE_CANONICALIZE, 0, tmp, 3, &result, 0);
10334     ok(hr == E_INVALIDARG, "Error: CoInternetParseIUri returned 0x%08x, expected 0x%08x.\n",
10335         hr, E_INVALIDARG);
10336     ok(!result, "Error: Expected 'result' to be 0, but was %d.\n", result);
10337
10338     hr = pCreateUri(http_urlW, 0, 0, &uri);
10339     ok(SUCCEEDED(hr), "Error: CreateUri returned 0x%08x.\n", hr);
10340     if(SUCCEEDED(hr)) {
10341         DWORD expected_len;
10342
10343         result = -1;
10344         hr = pCoInternetParseIUri(uri, PARSE_CANONICALIZE, 0, NULL, 0, &result, 0);
10345         ok(hr == E_INVALIDARG, "Error: CoInternetParseIUri returned 0x%08x, expected 0x%08x.\n",
10346             hr, E_INVALIDARG);
10347         ok(!result, "Error: Expected 'result' to be 0, but was %d.\n", result);
10348
10349         hr = pCoInternetParseIUri(uri, PARSE_CANONICALIZE, 0, tmp, 3, NULL, 0);
10350         ok(hr == E_POINTER, "Error: CoInternetParseIUri returned 0x%08x, expected 0x%08x.\n",
10351             hr, E_POINTER);
10352
10353         result = -1;
10354         hr = pCoInternetParseIUri(uri, PARSE_SECURITY_URL, 0, tmp, 3, &result, 0);
10355         ok(hr == E_FAIL, "Error: CoInternetParseIUri returned 0x%08x expected 0x%08x.\n",
10356             hr, E_FAIL);
10357         ok(!result, "Error: Expected 'result' to be 0, but was %d.\n", result);
10358
10359         result = -1;
10360         hr = pCoInternetParseIUri(uri, PARSE_MIME, 0, tmp, 3, &result, 0);
10361         ok(hr == E_FAIL, "Error: CoInternetParseIUri returned 0x%08x, expected 0x%08x.\n",
10362             hr, E_FAIL);
10363         ok(!result, "Error: Expected 'result' to be 0, but was %d.\n", result);
10364
10365         result = -1;
10366         hr = pCoInternetParseIUri(uri, PARSE_SERVER, 0, tmp, 3, &result, 0);
10367         ok(hr == E_FAIL, "Error: CoInternetParseIUri returned 0x%08x, expected 0x%08x.\n",
10368             hr, E_FAIL);
10369         ok(!result, "Error: Expected 'result' to be 0, but was %d.\n", result);
10370
10371         result = -1;
10372         hr = pCoInternetParseIUri(uri, PARSE_SECURITY_DOMAIN, 0, tmp, 3, &result, 0);
10373         ok(hr == E_FAIL, "Error: CoInternetParseIUri returned 0x%08x, expected 0x%08x.\n",
10374             hr, E_FAIL);
10375         ok(!result, "Error: Expected 'result' to be 0, but was %d.\n", result);
10376
10377         expected_len = lstrlenW(http_urlW);
10378         result = -1;
10379         hr = pCoInternetParseIUri(uri, PARSE_CANONICALIZE, 0, tmp, 3, &result, 0);
10380         ok(hr == STRSAFE_E_INSUFFICIENT_BUFFER,
10381             "Error: CoInternetParseIUri returned 0x%08x, expected 0x%08x.\n",
10382             hr, STRSAFE_E_INSUFFICIENT_BUFFER);
10383         ok(result == expected_len, "Error: Expected 'result' to be %d, but was %d instead.\n",
10384             expected_len, result);
10385     }
10386     if(uri) IUri_Release(uri);
10387 }
10388
10389 static void test_CoInternetParseIUri(void) {
10390     DWORD i;
10391
10392     for(i = 0; i < sizeof(uri_parse_tests)/sizeof(uri_parse_tests[0]); ++i) {
10393         HRESULT hr;
10394         IUri *uri;
10395         LPWSTR uriW;
10396         uri_parse_test test = uri_parse_tests[i];
10397
10398         uriW = a2w(test.uri);
10399         hr = pCreateUri(uriW, test.uri_flags, 0, &uri);
10400         ok(SUCCEEDED(hr), "Error: CreateUri returned 0x%08x on uri_parse_tests[%d].\n", hr, i);
10401         if(SUCCEEDED(hr)) {
10402             WCHAR result[INTERNET_MAX_URL_LENGTH+1];
10403             DWORD result_len = -1;
10404
10405             hr = pCoInternetParseIUri(uri, test.action, test.flags, result, INTERNET_MAX_URL_LENGTH+1, &result_len, 0);
10406             if(test.todo) {
10407                 todo_wine {
10408                     ok(hr == test.expected,
10409                         "Error: CoInternetParseIUri returned 0x%08x, expected 0x%08x on uri_parse_tests[%d].\n",
10410                         hr, test.expected, i);
10411                 }
10412             } else {
10413                 ok(hr == test.expected,
10414                     "Error: CoInternetParseIUri returned 0x%08x, expected 0x%08x on uri_parse_tests[%d].\n",
10415                     hr, test.expected, i);
10416             }
10417             if(SUCCEEDED(hr)) {
10418                 DWORD len = lstrlenA(test.property);
10419                 ok(!strcmp_aw(test.property, result),
10420                     "Error: Expected %s but got %s instead on uri_parse_tests[%d].\n",
10421                     test.property, wine_dbgstr_w(result), i);
10422                 ok(len == result_len,
10423                     "Error: Expected %d, but got %d instead on uri_parse_tests[%d].\n",
10424                     len, result_len, i);
10425             } else {
10426                 ok(!result_len,
10427                     "Error: Expected 'result_len' to be 0, but was %d on uri_parse_tests[%d].\n",
10428                     result_len, i);
10429             }
10430         }
10431         if(uri) IUri_Release(uri);
10432         heap_free(uriW);
10433     }
10434 }
10435
10436 static void test_CoInternetParseIUri_Pluggable(void) {
10437     HRESULT hr;
10438     IUri *uri = NULL;
10439
10440     hr = pCreateUri(parse_urlW, 0, 0, &uri);
10441     ok(SUCCEEDED(hr), "Error: Expected CreateUri to succeed, but got 0x%08x.\n", hr);
10442     if(SUCCEEDED(hr)) {
10443         WCHAR result[200];
10444         DWORD result_len;
10445
10446         SET_EXPECT(ParseUrl);
10447
10448         parse_action = PARSE_CANONICALIZE;
10449         parse_flags = URL_UNESCAPE|URL_ESCAPE_UNSAFE;
10450
10451         hr = pCoInternetParseIUri(uri, parse_action, parse_flags, result, 200, &result_len, 0);
10452         ok(hr == S_OK, "Error: CoInternetParseIUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
10453
10454         CHECK_CALLED(ParseUrl);
10455
10456         if(SUCCEEDED(hr)) {
10457             ok(result_len == lstrlenW(parse_resultW), "Error: Expected %d, but got %d.\n",
10458                 lstrlenW(parse_resultW), result_len);
10459             ok(!lstrcmpW(result, parse_resultW), "Error: Expected %s, but got %s.\n",
10460                 wine_dbgstr_w(parse_resultW), wine_dbgstr_w(result));
10461         }
10462     }
10463     if(uri) IUri_Release(uri);
10464 }
10465
10466 typedef struct {
10467     const char *url;
10468     DWORD uri_flags;
10469     const char *base_url;
10470     DWORD base_uri_flags;
10471     const char *legacy_url;
10472     const char *uniform_url;
10473     const char *no_canon_url;
10474     const char *uri_url;
10475 } create_urlmon_test_t;
10476
10477 static const create_urlmon_test_t create_urlmon_tests[] = {
10478     {
10479         "http://www.winehq.org",Uri_CREATE_NO_CANONICALIZE,
10480         NULL,0,
10481         "http://www.winehq.org/",
10482         "http://www.winehq.org/",
10483         "http://www.winehq.org",
10484         "http://www.winehq.org"
10485     },
10486     {
10487         "file://c:\\dir\\file.txt",Uri_CREATE_NO_CANONICALIZE,
10488         NULL,0,
10489         "file://c:\\dir\\file.txt",
10490         "file:///c:/dir/file.txt",
10491         "file:///c:/dir/file.txt",
10492         "file:///c:/dir/file.txt"
10493     },
10494     {
10495         "file://c:\\dir\\file.txt",Uri_CREATE_FILE_USE_DOS_PATH,
10496         NULL,0,
10497         "file://c:\\dir\\file.txt",
10498         "file:///c:/dir/file.txt",
10499         "file:///c:/dir/file.txt",
10500         "file://c:\\dir\\file.txt"
10501     },
10502     {
10503         "dat%61",Uri_CREATE_ALLOW_RELATIVE,
10504         "http://www.winehq.org",0,
10505         "http://www.winehq.org/data",
10506         "http://www.winehq.org/data",
10507         "http://www.winehq.org:80/data",
10508     },
10509     {
10510         "file.txt",Uri_CREATE_ALLOW_RELATIVE,
10511         "file://c:\\dir\\x.txt",Uri_CREATE_NO_CANONICALIZE,
10512         "file://c:\\dir\\file.txt",
10513         "file:///c:/dir/file.txt",
10514         "file:///c:/dir/file.txt",
10515     },
10516     {
10517         "",Uri_CREATE_ALLOW_RELATIVE,
10518         NULL,0,
10519         "",
10520         "",
10521         "",
10522         ""
10523     },
10524     {
10525         "test",Uri_CREATE_ALLOW_RELATIVE,
10526         NULL,0,
10527         "test",
10528         "test",
10529         "test",
10530         "test"
10531     },
10532     {
10533         "c:\\dir\\file.txt",Uri_CREATE_ALLOW_IMPLICIT_FILE_SCHEME,
10534         NULL,0,
10535         "file://c:\\dir\\file.txt",
10536         "file:///c:/dir/file.txt",
10537         "file:///c:/dir/file.txt",
10538         "file:///c:/dir/file.txt",
10539     }
10540 };
10541
10542 #define test_urlmon_display_name(a,b) _test_urlmon_display_name(__LINE__,a,b)
10543 static void _test_urlmon_display_name(unsigned line, IMoniker *mon, const char *exurl)
10544 {
10545     WCHAR *display_name;
10546     HRESULT hres;
10547
10548     hres = IMoniker_GetDisplayName(mon, NULL, NULL, &display_name);
10549     ok_(__FILE__,line)(hres == S_OK, "GetDisplayName failed: %08x\n", hres);
10550     ok_(__FILE__,line)(!strcmp_aw(exurl, display_name), "unexpected display name: %s, expected %s\n",
10551             wine_dbgstr_w(display_name), exurl);
10552
10553     CoTaskMemFree(display_name);
10554 }
10555
10556 #define test_display_uri(a,b) _test_display_uri(__LINE__,a,b)
10557 static void _test_display_uri(unsigned line, IMoniker *mon, const char *exurl)
10558 {
10559     IUriContainer *uri_container;
10560     IUri *uri;
10561     BSTR display_uri;
10562     HRESULT hres;
10563
10564     hres = IMoniker_QueryInterface(mon, &IID_IUriContainer, (void**)&uri_container);
10565     ok(hres == S_OK, "Could not get IUriContainer iface: %08x\n", hres);
10566
10567     uri = NULL;
10568     hres = IUriContainer_GetIUri(uri_container, &uri);
10569     IUriContainer_Release(uri_container);
10570     ok(hres == S_OK, "GetIUri failed: %08x\n", hres);
10571     ok(uri != NULL, "uri == NULL\n");
10572
10573     hres = IUri_GetDisplayUri(uri, &display_uri);
10574     IUri_Release(uri);
10575     ok(hres == S_OK, "GetDisplayUri failed: %08x\n", hres);
10576     ok_(__FILE__,line)(!strcmp_aw(exurl, display_uri), "unexpected display uri: %s, expected %s\n",
10577             wine_dbgstr_w(display_uri), exurl);
10578     SysFreeString(display_uri);
10579 }
10580
10581 static void test_CreateURLMoniker(void)
10582 {
10583     const create_urlmon_test_t *test;
10584     IMoniker *mon, *base_mon;
10585     WCHAR *url, *base_url;
10586     IUri *uri, *base_uri;
10587     HRESULT hres;
10588
10589     for(test = create_urlmon_tests; test < create_urlmon_tests + sizeof(create_urlmon_tests)/sizeof(*create_urlmon_tests); test++) {
10590         url = a2w(test->url);
10591         base_url = a2w(test->base_url);
10592
10593         if(base_url) {
10594             hres = pCreateUri(base_url, test->base_uri_flags, 0, &base_uri);
10595             ok(hres == S_OK, "CreateUri failed: %08x\n", hres);
10596
10597             hres = pCreateURLMonikerEx2(NULL, base_uri, &base_mon, URL_MK_NO_CANONICALIZE);
10598             ok(hres == S_OK, "CreateURLMonikerEx2 failed: %08x\n", hres);
10599         }else {
10600             base_uri = NULL;
10601             base_mon = NULL;
10602         }
10603
10604         hres = CreateURLMoniker(base_mon, url, &mon);
10605         ok(hres == S_OK, "CreateURLMoniker failed: %08x\n", hres);
10606         test_urlmon_display_name(mon, test->legacy_url);
10607         test_display_uri(mon, test->legacy_url);
10608         IMoniker_Release(mon);
10609
10610         hres = pCreateURLMonikerEx(base_mon, url, &mon, URL_MK_LEGACY);
10611         ok(hres == S_OK, "CreateURLMoniker failed: %08x\n", hres);
10612         test_urlmon_display_name(mon, test->legacy_url);
10613         test_display_uri(mon, test->legacy_url);
10614         IMoniker_Release(mon);
10615
10616         hres = pCreateURLMonikerEx(base_mon, url, &mon, URL_MK_UNIFORM);
10617         ok(hres == S_OK, "CreateURLMoniker failed: %08x\n", hres);
10618         test_urlmon_display_name(mon, test->uniform_url);
10619         test_display_uri(mon, test->uniform_url);
10620         IMoniker_Release(mon);
10621
10622         hres = pCreateURLMonikerEx(base_mon, url, &mon, URL_MK_NO_CANONICALIZE);
10623         ok(hres == S_OK, "CreateURLMoniker failed: %08x\n", hres);
10624         test_urlmon_display_name(mon, test->no_canon_url);
10625         test_display_uri(mon, test->no_canon_url);
10626         IMoniker_Release(mon);
10627
10628         hres = pCreateUri(url, test->uri_flags, 0, &uri);
10629         ok(hres == S_OK, "CreateUri failed: %08x\n", hres);
10630
10631         hres = pCreateURLMonikerEx2(base_mon, uri, &mon, URL_MK_LEGACY);
10632         ok(hres == S_OK, "CreateURLMonikerEx2 failed: %08x\n", hres);
10633         test_urlmon_display_name(mon, base_url ? test->legacy_url : test->uri_url);
10634         test_display_uri(mon, base_url ? test->legacy_url : test->uri_url);
10635         IMoniker_Release(mon);
10636
10637         hres = pCreateURLMonikerEx2(base_mon, uri, &mon, URL_MK_UNIFORM);
10638         ok(hres == S_OK, "CreateURLMonikerEx2 failed: %08x\n", hres);
10639         test_urlmon_display_name(mon, base_url ? test->uniform_url : test->uri_url);
10640         test_display_uri(mon, base_url ? test->uniform_url : test->uri_url);
10641         IMoniker_Release(mon);
10642
10643         hres = pCreateURLMonikerEx2(base_mon, uri, &mon, URL_MK_NO_CANONICALIZE);
10644         ok(hres == S_OK, "CreateURLMonikerEx2 failed: %08x\n", hres);
10645         test_urlmon_display_name(mon, base_url ? test->no_canon_url : test->uri_url);
10646         test_display_uri(mon, base_url ? test->no_canon_url : test->uri_url);
10647         IMoniker_Release(mon);
10648
10649         IUri_Release(uri);
10650         heap_free(url);
10651         heap_free(base_url);
10652         if(base_uri)
10653             IUri_Release(base_uri);
10654         if(base_mon)
10655             IMoniker_Release(base_mon);
10656     }
10657 }
10658
10659 static int add_default_flags(DWORD flags) {
10660     if(!(flags & Uri_CREATE_NO_CANONICALIZE))
10661         flags |= Uri_CREATE_CANONICALIZE;
10662     if(!(flags & Uri_CREATE_NO_DECODE_EXTRA_INFO))
10663         flags |= Uri_CREATE_DECODE_EXTRA_INFO;
10664     if(!(flags & Uri_CREATE_NO_CRACK_UNKNOWN_SCHEMES))
10665         flags |= Uri_CREATE_CRACK_UNKNOWN_SCHEMES;
10666     if(!(flags & Uri_CREATE_NO_PRE_PROCESS_HTML_URI))
10667         flags |= Uri_CREATE_PRE_PROCESS_HTML_URI;
10668     if(!(flags & Uri_CREATE_IE_SETTINGS))
10669         flags |= Uri_CREATE_NO_IE_SETTINGS;
10670
10671     return flags;
10672 }
10673
10674 static void test_IPersistStream(void)
10675 {
10676     int i, props_order[Uri_PROPERTY_DWORD_LAST+1] = { 0 };
10677
10678     props_order[Uri_PROPERTY_RAW_URI] = 1;
10679     props_order[Uri_PROPERTY_FRAGMENT] = 2;
10680     props_order[Uri_PROPERTY_HOST] = 3;
10681     props_order[Uri_PROPERTY_PASSWORD] = 4;
10682     props_order[Uri_PROPERTY_PATH] = 5;
10683     props_order[Uri_PROPERTY_PORT] = 6;
10684     props_order[Uri_PROPERTY_QUERY] = 7;
10685     props_order[Uri_PROPERTY_SCHEME_NAME] = 8;
10686     props_order[Uri_PROPERTY_USER_NAME] = 9;
10687
10688     for(i=0; i<sizeof(uri_tests)/sizeof(*uri_tests); i++) {
10689         const uri_properties *test = uri_tests+i;
10690         LPWSTR uriW;
10691         IUri *uri;
10692         IPersistStream *persist_stream;
10693         IStream *stream;
10694         IMarshal *marshal;
10695         DWORD props, props_no, dw_data[6];
10696         WCHAR str_data[1024];
10697         ULARGE_INTEGER size, max_size;
10698         LARGE_INTEGER no_off;
10699         CLSID curi;
10700         BSTR raw_uri;
10701         HRESULT hr;
10702
10703         if(test->create_todo || test->create_expected!=S_OK)
10704             continue;
10705
10706         uriW = a2w(test->uri);
10707         hr = pCreateUri(uriW, test->create_flags, 0, &uri);
10708         ok(hr == S_OK, "%d) CreateUri failed 0x%08x, expected S_OK..\n", i, hr);
10709
10710         hr = IUri_QueryInterface(uri, &IID_IPersistStream, (void**)&persist_stream);
10711         ok(hr == S_OK, "%d) QueryInterface failed 0x%08x, expected S_OK.\n", i, hr);
10712
10713         hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
10714         ok(hr == S_OK, "CreateStreamOnHGlobal failed 0x%08x.\n", hr);
10715         hr = IPersistStream_IsDirty(persist_stream);
10716         ok(hr == S_FALSE, "%d) IsDirty returned 0x%08x, expected S_FALSE.\n", i, hr);
10717         hr = IPersistStream_Save(persist_stream, stream, FALSE);
10718         ok(hr == S_OK, "%d) Save failed 0x%08x, expected S_OK.\n", i, hr);
10719         hr = IPersistStream_IsDirty(persist_stream);
10720         ok(hr == S_FALSE, "%d) IsDirty returned 0x%08x, expected S_FALSE.\n", i, hr);
10721         no_off.QuadPart = 0;
10722         hr = IStream_Seek(stream, no_off, STREAM_SEEK_CUR, &size);
10723         ok(hr == S_OK, "%d) Seek failed 0x%08x, expected S_OK.\n", i, hr);
10724         hr = IStream_Seek(stream, no_off, STREAM_SEEK_SET, NULL);
10725         ok(hr == S_OK, "%d) Seek failed 0x%08x, expected S_OK.\n", i, hr);
10726         hr = IPersistStream_GetSizeMax(persist_stream, &max_size);
10727         ok(hr == S_OK, "%d) GetSizeMax failed 0x%08x, expected S_OK.\n", i, hr);
10728         ok(U(size).LowPart+2 == U(max_size).LowPart,
10729                 "%d) Written data size is %d, max_size %d.\n",
10730                 i, U(size).LowPart, U(max_size).LowPart);
10731
10732         hr = IStream_Read(stream, (void*)dw_data, sizeof(DWORD), NULL);
10733         ok(hr == S_OK, "%d) Read failed 0x%08x, expected S_OK.\n", i, hr);
10734         ok(dw_data[0]-2 == U(size).LowPart, "%d) Structure size is %d, expected %d\n",
10735                 i, dw_data[0]-2, U(size).LowPart);
10736         hr = IStream_Read(stream, (void*)dw_data, 6*sizeof(DWORD), NULL);
10737         ok(hr == S_OK, "%d) Read failed 0x%08x, expected S_OK.\n", i, hr);
10738         ok(dw_data[0] == 0, "%d) Incorrect value %x, expected 0 (unknown).\n", i, dw_data[0]);
10739         ok(dw_data[1] == 0, "%d) Incorrect value %x, expected 0 (unknown).\n", i, dw_data[1]);
10740         ok(dw_data[2] == add_default_flags(test->create_flags),
10741                 "%d) Incorrect value %x, expected %x (creation flags).\n",
10742                 i, dw_data[2], add_default_flags(test->create_flags));
10743         ok(dw_data[3] == 0, "%d) Incorrect value %x, expected 0 (unknown).\n", i, dw_data[3]);
10744         ok(dw_data[4] == 0, "%d) Incorrect value %x, expected 0 (unknown).\n", i, dw_data[4]);
10745         ok(dw_data[5] == 0, "%d) Incorrect value %x, expected 0 (unknown).\n", i, dw_data[5]);
10746
10747         props_no = 0;
10748         for(props=0; props<=Uri_PROPERTY_DWORD_LAST; props++) {
10749             if(!props_order[props])
10750                 continue;
10751
10752             if(props <= Uri_PROPERTY_STRING_LAST) {
10753                 if(test->str_props[props].expected == S_OK)
10754                     props_no++;
10755             } else {
10756                 if(test->dword_props[props-Uri_PROPERTY_DWORD_START].expected == S_OK)
10757                     props_no++;
10758             }
10759         }
10760         if(test->dword_props[Uri_PROPERTY_SCHEME-Uri_PROPERTY_DWORD_START].value != URL_SCHEME_HTTP
10761                 && test->dword_props[Uri_PROPERTY_SCHEME-Uri_PROPERTY_DWORD_START].value != URL_SCHEME_FTP
10762                 && test->dword_props[Uri_PROPERTY_SCHEME-Uri_PROPERTY_DWORD_START].value != URL_SCHEME_HTTPS)
10763             props_no = 1;
10764
10765         hr = IStream_Read(stream, (void*)&props, sizeof(DWORD), NULL);
10766         ok(hr == S_OK, "%d) Read failed 0x%08x, expected S_OK.\n", i, hr);
10767         ok(props == props_no, "%d) Properties no is %d, expected %d.\n", i, props, props_no);
10768
10769         dw_data[2] = 0;
10770         dw_data[3] = -1;
10771         while(props) {
10772             hr = IStream_Read(stream, (void*)dw_data, 2*sizeof(DWORD), NULL);
10773             ok(hr == S_OK, "%d) Read failed 0x%08x, expected S_OK.\n", i, hr);
10774             props--;
10775             ok(dw_data[2]<props_order[dw_data[0]],
10776                     "%d) Incorrect properties order (%d, %d)\n",
10777                     i, dw_data[0], dw_data[3]);
10778             dw_data[2] = props_order[dw_data[0]];
10779             dw_data[3] = dw_data[0];
10780
10781             if(dw_data[0]<=Uri_PROPERTY_STRING_LAST) {
10782                 const uri_str_property *prop = test->str_props+dw_data[0];
10783                 hr = IStream_Read(stream, (void*)str_data, dw_data[1], NULL);
10784                 ok(hr == S_OK, "%d) Read failed 0x%08x, expected S_OK.\n", i, hr);
10785                 ok(!strcmp_aw(prop->value, str_data) || broken(prop->broken_value && !strcmp_aw(prop->broken_value, str_data)),
10786                         "%d) Expected %s but got %s (%d).\n", i, prop->value, wine_dbgstr_w(str_data), dw_data[0]);
10787             } else if(dw_data[0]>=Uri_PROPERTY_DWORD_START && dw_data[0]<=Uri_PROPERTY_DWORD_LAST) {
10788                 const uri_dword_property *prop = test->dword_props+dw_data[0]-Uri_PROPERTY_DWORD_START;
10789                 ok(dw_data[1] == sizeof(DWORD), "%d) Size of dword property is %d (%d)\n", i, dw_data[1], dw_data[0]);
10790                 hr = IStream_Read(stream, (void*)&dw_data[1], sizeof(DWORD), NULL);
10791                 ok(hr == S_OK, "%d) Read failed 0x%08x, expected S_OK.\n", i, hr);
10792                 ok(prop->value == dw_data[1], "%d) Expected %d but got %d (%d).\n", i, prop->value, dw_data[1], dw_data[0]);
10793             } else {
10794                 ok(FALSE, "%d) Incorrect property type (%d)\n", i, dw_data[0]);
10795                 break;
10796             }
10797         }
10798         ok(props == 0, "%d) No all properties were processed %d. Next property type: %d\n",
10799                 i, props, dw_data[0]);
10800
10801         IPersistStream_Release(persist_stream);
10802         IUri_Release(uri);
10803
10804         hr = IStream_Seek(stream, no_off, STREAM_SEEK_SET, NULL);
10805         ok(hr == S_OK, "%d) Seek failed 0x%08x, expected S_OK.\n", i, hr);
10806         hr = IPersistStream_GetClassID(persist_stream, &curi);
10807         ok(hr == S_OK, "%d) GetClassID failed 0x%08x, expected S_OK.\n", i, hr);
10808         ok(IsEqualCLSID(&curi, &CLSID_CUri), "%d) GetClassID returned incorrect CLSID.\n", i);
10809         hr = CoCreateInstance(&curi, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
10810                 &IID_IUri, (void**)&uri);
10811         ok(hr == S_OK, "%d) Error creating uninitialized Uri: 0x%08x.\n", i, hr);
10812         hr = IUri_QueryInterface(uri, &IID_IPersistStream, (void**)&persist_stream);
10813         ok(hr == S_OK, "%d) QueryInterface failed 0x%08x, expected S_OK.\n", i, hr);
10814         hr = IPersistStream_Load(persist_stream, stream);
10815         ok(hr == S_OK, "%d) Load failed 0x%08x, expected S_OK.\n", i, hr);
10816         hr = IUri_GetRawUri(uri, &raw_uri);
10817         ok(hr == S_OK, "%d) GetRawUri failed 0x%08x, expected S_OK.\n", i, hr);
10818         ok(!strcmp_aw(test->str_props[Uri_PROPERTY_RAW_URI].value, raw_uri)
10819                 || broken(test->str_props[Uri_PROPERTY_RAW_URI].broken_value
10820                     && !strcmp_aw(test->str_props[Uri_PROPERTY_RAW_URI].broken_value, raw_uri)),
10821                 "%d) Expected %s but got %s.\n", i, test->str_props[Uri_PROPERTY_RAW_URI].value,
10822                 wine_dbgstr_w(raw_uri));
10823         SysFreeString(raw_uri);
10824
10825         hr = IUri_QueryInterface(uri, &IID_IMarshal, (void**)&marshal);
10826         ok(hr == S_OK, "%d) QueryInterface(IID_IMarshal) failed 0x%08x, expected S_OK.\n", i, hr);
10827         hr = IStream_Seek(stream, no_off, STREAM_SEEK_SET, NULL);
10828         ok(hr == S_OK, "%d) Seek failed 0x%08x, expected S_OK.\n", i, hr);
10829         hr = IMarshal_MarshalInterface(marshal, stream, &IID_IUri, (void*)uri,
10830                 MSHCTX_DIFFERENTMACHINE, NULL, MSHLFLAGS_NORMAL);
10831         ok(hr == E_INVALIDARG, "%d) MarshalInterface returned 0x%08x, expected E_INVALIDARG.\n", i, hr);
10832         hr = IMarshal_MarshalInterface(marshal, stream, &IID_IUri, (void*)uri,
10833                 MSHCTX_CROSSCTX, NULL, MSHLFLAGS_NORMAL);
10834         ok(hr == E_INVALIDARG, "%d) MarshalInterface returned 0x%08x, expected E_INVALIDARG.\n", i, hr);
10835         hr = IMarshal_MarshalInterface(marshal, stream, &IID_IUri, (void*)uri,
10836                 MSHCTX_LOCAL, NULL, MSHLFLAGS_TABLESTRONG);
10837         ok(hr == E_INVALIDARG, "%d) MarshalInterface returned 0x%08x, expected E_INVALIDARG.\n", i, hr);
10838         hr = IMarshal_MarshalInterface(marshal, stream, &IID_IUri, (void*)uri,
10839                 MSHCTX_LOCAL, NULL, MSHLFLAGS_TABLEWEAK);
10840         ok(hr == E_INVALIDARG, "%d) MarshalInterface returned 0x%08x, expected E_INVALIDARG.\n", i, hr);
10841         hr = IMarshal_MarshalInterface(marshal, stream, &IID_IUri, (void*)uri,
10842                 MSHCTX_LOCAL, NULL, MSHLFLAGS_NOPING);
10843         ok(hr == E_INVALIDARG, "%d) MarshalInterface returned 0x%08x, expected E_INVALIDARG.\n", i, hr);
10844         hr = IMarshal_MarshalInterface(marshal, stream, &IID_IUri, (void*)uri,
10845                 MSHCTX_LOCAL, NULL, MSHLFLAGS_NORMAL);
10846         ok(hr == S_OK, "%d) MarshalInterface failed 0x%08x, expected S_OK.\n", i, hr);
10847         hr = IMarshal_GetUnmarshalClass(marshal, &IID_IUri, (void*)uri,
10848                 MSHCTX_CROSSCTX, NULL, MSHLFLAGS_NORMAL, &curi);
10849         ok(hr == E_INVALIDARG, "%d) GetUnmarshalClass returned 0x%08x, expected E_INVALIDARG.\n", i, hr);
10850         hr = IMarshal_GetUnmarshalClass(marshal, &IID_IUri, (void*)uri,
10851                 MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL, &curi);
10852         ok(hr == S_OK, "%d) GetUnmarshalClass failed 0x%08x, expected S_OK.\n", i, hr);
10853         ok(IsEqualCLSID(&curi, &CLSID_CUri), "%d) GetUnmarshalClass returned incorrect CLSID.\n", i);
10854
10855         hr = IStream_Seek(stream, no_off, STREAM_SEEK_CUR, &size);
10856         ok(hr == S_OK, "%d) Seek failed 0x%08x, expected S_OK.\n", i, hr);
10857         hr = IStream_Seek(stream, no_off, STREAM_SEEK_SET, NULL);
10858         ok(hr == S_OK, "%d) Seek failed 0x%08x, expected S_OK.\n", i, hr);
10859         hr = IStream_Read(stream, (void*)dw_data, 3*sizeof(DWORD), NULL);
10860         ok(hr == S_OK, "%d) Read failed 0x%08x, expected S_OK.\n", i, hr);
10861         ok(dw_data[0]-2 == U(size).LowPart, "%d) Structure size is %d, expected %d\n",
10862                 i, dw_data[0]-2, U(size).LowPart);
10863         ok(dw_data[1] == MSHCTX_LOCAL, "%d) Incorrect value %d, expected MSHCTX_LOCAL.\n",
10864                 i, dw_data[1]);
10865         ok(dw_data[2] == dw_data[0]-8, "%d) Incorrect value %d, expected %d (PersistStream size).\n",
10866                 i, dw_data[2], dw_data[0]-8);
10867         if(!test->str_props[Uri_PROPERTY_PATH].value[0] &&
10868                 (test->dword_props[Uri_PROPERTY_SCHEME-Uri_PROPERTY_DWORD_START].value == URL_SCHEME_HTTP
10869                  || test->dword_props[Uri_PROPERTY_SCHEME-Uri_PROPERTY_DWORD_START].value == URL_SCHEME_FTP
10870                  || test->dword_props[Uri_PROPERTY_SCHEME-Uri_PROPERTY_DWORD_START].value == URL_SCHEME_HTTPS))
10871             U(max_size).LowPart += 3*sizeof(DWORD);
10872         ok(dw_data[2] == U(max_size).LowPart, "%d) Incorrect value %d, expected %d (PersistStream size).\n",
10873                 i, dw_data[2], U(max_size).LowPart);
10874         IMarshal_Release(marshal);
10875         IUri_Release(uri);
10876
10877         hr = IStream_Seek(stream, no_off, STREAM_SEEK_SET, NULL);
10878         ok(hr == S_OK, "%d) Seek failed 0x%08x, expected S_OK.\n", i, hr);
10879         hr = CoCreateInstance(&curi, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
10880                 &IID_IUri, (void**)&uri);
10881         ok(hr == S_OK, "%d) Error creating uninitialized Uri: 0x%08x.\n", i, hr);
10882         hr = IUri_QueryInterface(uri, &IID_IMarshal, (void**)&marshal);
10883         ok(hr == S_OK, "%d) QueryInterface failed 0x%08x, expected S_OK.\n", i, hr);
10884         hr = IMarshal_UnmarshalInterface(marshal, stream, &IID_IUri, (void**)&uri);
10885         ok(hr == S_OK, "%d) UnmarshalInterface failed 0x%08x, expected S_OK.\n", i, hr);
10886         hr = IUri_GetRawUri(uri, &raw_uri);
10887         ok(hr == S_OK, "%d) GetRawUri failed 0x%08x, expected S_OK.\n", i, hr);
10888         ok(!strcmp_aw(test->str_props[Uri_PROPERTY_RAW_URI].value, raw_uri)
10889                 || broken(test->str_props[Uri_PROPERTY_RAW_URI].broken_value
10890                     && !strcmp_aw(test->str_props[Uri_PROPERTY_RAW_URI].broken_value, raw_uri)),
10891                 "%d) Expected %s but got %s.\n", i, test->str_props[Uri_PROPERTY_RAW_URI].value,
10892                 wine_dbgstr_w(raw_uri));
10893         SysFreeString(raw_uri);
10894
10895         IMarshal_Release(marshal);
10896         IStream_Release(stream);
10897         IPersistStream_Release(persist_stream);
10898         IUri_Release(uri);
10899         heap_free(uriW);
10900     }
10901 }
10902
10903 static void test_UninitializedUri(void)
10904 {
10905     IUri *uri;
10906     IUriBuilderFactory *ubf;
10907     IPersistStream *ps;
10908     IUriBuilder *ub;
10909     BSTR bstr;
10910     DWORD dword;
10911     BOOL eq;
10912     ULARGE_INTEGER ui;
10913     HRESULT hr;
10914
10915     hr = CoCreateInstance(&CLSID_CUri, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
10916             &IID_IUri, (void**)&uri);
10917     if(FAILED(hr)) {
10918         win_skip("Skipping uninitialized Uri tests.\n");
10919         return;
10920     }
10921
10922     hr = IUri_QueryInterface(uri, &IID_IUriBuilderFactory, (void**)&ubf);
10923     ok(hr == S_OK, "QueryInterface(IID_IUriBuillderFactory) failed: %x.\n", hr);
10924     hr = IUri_QueryInterface(uri, &IID_IPersistStream, (void**)&ps);
10925     ok(hr == S_OK, "QueryInterface(IID_IPersistStream) failed: %x.\n", hr);
10926
10927     hr = IUri_GetAbsoluteUri(uri, NULL);
10928     ok(hr == E_UNEXPECTED, "GetAbsoluteUri returned %x, expected E_UNEXPECTED.\n", hr);
10929     hr = IUri_GetAbsoluteUri(uri, &bstr);
10930     ok(hr == E_UNEXPECTED, "GetAbsoluteUri returned %x, expected E_UNEXPECTED.\n", hr);
10931     hr = IUri_GetAuthority(uri, &bstr);
10932     ok(hr == E_UNEXPECTED, "GetAuthority returned %x, expected E_UNEXPECTED.\n", hr);
10933     hr = IUri_GetDisplayUri(uri, &bstr);
10934     ok(hr == E_UNEXPECTED, "GetDisplayUri returned %x, expected E_UNEXPECTED.\n", hr);
10935     hr = IUri_GetDomain(uri, &bstr);
10936     ok(hr == E_UNEXPECTED, "GetDomain returned %x, expected E_UNEXPECTED.\n", hr);
10937     hr = IUri_GetExtension(uri, &bstr);
10938     ok(hr == E_UNEXPECTED, "GetExtension returned %x, expected E_UNEXPECTED.\n", hr);
10939     hr = IUri_GetFragment(uri, &bstr);
10940     ok(hr == E_UNEXPECTED, "GetFragment returned %x, expected E_UNEXPECTED.\n", hr);
10941     hr = IUri_GetHost(uri, &bstr);
10942     ok(hr == E_UNEXPECTED, "GetHost returned %x, expected E_UNEXPECTED.\n", hr);
10943     hr = IUri_GetHostType(uri, &dword);
10944     ok(hr == E_UNEXPECTED, "GetHostType returned %x, expected E_UNEXPECTED.\n", hr);
10945     hr = IUri_GetPassword(uri, &bstr);
10946     ok(hr == E_UNEXPECTED, "GetPassword returned %x, expected E_UNEXPECTED.\n", hr);
10947     hr = IUri_GetPassword(uri, &bstr);
10948     ok(hr == E_UNEXPECTED, "GetPassword returned %x, expected E_UNEXPECTED.\n", hr);
10949     hr = IUri_GetPathAndQuery(uri, &bstr);
10950     ok(hr == E_UNEXPECTED, "GetPathAndQuery returned %x, expected E_UNEXPECTED.\n", hr);
10951     hr = IUri_GetPort(uri, &dword);
10952     ok(hr == E_UNEXPECTED, "GetPort returned %x, expected E_UNEXPECTED.\n", hr);
10953     hr = IUri_GetProperties(uri, &dword);
10954     ok(hr == E_UNEXPECTED, "GetProperties returned %x, expected E_UNEXPECTED.\n", hr);
10955     hr = IUri_GetPropertyBSTR(uri, Uri_PROPERTY_RAW_URI, &bstr, 0);
10956     ok(hr == E_UNEXPECTED, "GetPropertyBSTR returned %x, expected E_UNEXPECTED.\n", hr);
10957     hr = IUri_GetPropertyDWORD(uri, Uri_PROPERTY_PORT, &dword, 0);
10958     ok(hr == E_UNEXPECTED, "GetPropertyDWORD returned %x, expected E_UNEXPECTED.\n", hr);
10959     hr = IUri_GetPropertyLength(uri, Uri_PROPERTY_RAW_URI, &dword, 0);
10960     ok(hr == E_UNEXPECTED, "GetPropertyLength returned %x, expected E_UNEXPECTED.\n", hr);
10961     hr = IUri_GetQuery(uri, &bstr);
10962     ok(hr == E_UNEXPECTED, "GetQuery returned %x, expected E_UNEXPECTED.\n", hr);
10963     hr = IUri_GetRawUri(uri, &bstr);
10964     ok(hr == E_UNEXPECTED, "GetRawUri returned %x, expected E_UNEXPECTED.\n", hr);
10965     hr = IUri_GetScheme(uri, &dword);
10966     ok(hr == E_UNEXPECTED, "GetScheme returned %x, expected E_UNEXPECTED.\n", hr);
10967     hr = IUri_GetSchemeName(uri, &bstr);
10968     ok(hr == E_UNEXPECTED, "GetSchemeName returned %x, expected E_UNEXPECTED.\n", hr);
10969     hr = IUri_GetUserInfo(uri, &bstr);
10970     ok(hr == E_UNEXPECTED, "GetUserInfo returned %x, expected E_UNEXPECTED.\n", hr);
10971     hr = IUri_GetUserName(uri, &bstr);
10972     ok(hr == E_UNEXPECTED, "GetUserName returned %x, expected E_UNEXPECTED.\n", hr);
10973     hr = IUri_GetZone(uri, &dword);
10974     ok(hr == E_UNEXPECTED, "GetZone returned %x, expected E_UNEXPECTED.\n", hr);
10975     hr = IUri_IsEqual(uri, uri, &eq);
10976     ok(hr == E_UNEXPECTED, "IsEqual returned %x, expected E_UNEXPECTED.\n", hr);
10977
10978     hr = IUriBuilderFactory_CreateInitializedIUriBuilder(ubf, 0, 0, &ub);
10979     ok(hr == E_UNEXPECTED, "CreateInitializedIUriBuilder returned %x, expected E_UNEXPECTED.\n", hr);
10980     hr = IUriBuilderFactory_CreateIUriBuilder(ubf, 0, 0, &ub);
10981     ok(hr == S_OK, "CreateIUriBuilder returned %x, expected S_OK.\n", hr);
10982     IUriBuilder_Release(ub);
10983
10984     hr = IPersistStream_GetSizeMax(ps, &ui);
10985     ok(hr == S_OK, "GetSizeMax returned %x, expected S_OK.\n", hr);
10986     ok(ui.u.LowPart == 34, "ui.LowPart = %d, expected 34.\n", ui.u.LowPart);
10987     hr = IPersistStream_IsDirty(ps);
10988     ok(hr == S_FALSE, "IsDirty returned %x, expected S_FALSE.\n", hr);
10989
10990     IPersistStream_Release(ps);
10991     IUriBuilderFactory_Release(ubf);
10992     IUri_Release(uri);
10993 }
10994
10995 START_TEST(uri) {
10996     HMODULE hurlmon;
10997
10998     hurlmon = GetModuleHandle("urlmon.dll");
10999     pCoInternetGetSession = (void*) GetProcAddress(hurlmon, "CoInternetGetSession");
11000     pCreateUri = (void*) GetProcAddress(hurlmon, "CreateUri");
11001     pCreateUriWithFragment = (void*) GetProcAddress(hurlmon, "CreateUriWithFragment");
11002     pCreateIUriBuilder = (void*) GetProcAddress(hurlmon, "CreateIUriBuilder");
11003     pCoInternetCombineIUri = (void*) GetProcAddress(hurlmon, "CoInternetCombineIUri");
11004     pCoInternetCombineUrlEx = (void*) GetProcAddress(hurlmon, "CoInternetCombineUrlEx");
11005     pCoInternetParseIUri = (void*) GetProcAddress(hurlmon, "CoInternetParseIUri");
11006     pCreateURLMonikerEx = (void*) GetProcAddress(hurlmon, "CreateURLMonikerEx");
11007     pCreateURLMonikerEx2 = (void*) GetProcAddress(hurlmon, "CreateURLMonikerEx2");
11008
11009     if(!pCreateUri) {
11010         win_skip("CreateUri is not present, skipping tests.\n");
11011         return;
11012     }
11013
11014     trace("test CreateUri invalid flags...\n");
11015     test_CreateUri_InvalidFlags();
11016
11017     trace("test CreateUri invalid args...\n");
11018     test_CreateUri_InvalidArgs();
11019
11020     trace("test CreateUri invalid URIs...\n");
11021     test_CreateUri_InvalidUri();
11022
11023     trace("test IUri_GetPropertyBSTR...\n");
11024     test_IUri_GetPropertyBSTR();
11025
11026     trace("test IUri_GetPropertyDWORD...\n");
11027     test_IUri_GetPropertyDWORD();
11028
11029     trace("test IUri_GetStrProperties...\n");
11030     test_IUri_GetStrProperties();
11031
11032     trace("test IUri_GetDwordProperties...\n");
11033     test_IUri_GetDwordProperties();
11034
11035     trace("test IUri_GetPropertyLength...\n");
11036     test_IUri_GetPropertyLength();
11037
11038     trace("test IUri_GetProperties...\n");
11039     test_IUri_GetProperties();
11040
11041     trace("test IUri_HasProperty...\n");
11042     test_IUri_HasProperty();
11043
11044     trace("test IUri_IsEqual...\n");
11045     test_IUri_IsEqual();
11046
11047     trace("test CreateUriWithFragment invalid args...\n");
11048     test_CreateUriWithFragment_InvalidArgs();
11049
11050     trace("test CreateUriWithFragment invalid flags...\n");
11051     test_CreateUriWithFragment_InvalidFlags();
11052
11053     trace("test CreateUriWithFragment...\n");
11054     test_CreateUriWithFragment();
11055
11056     trace("test CreateIUriBuilder...\n");
11057     test_CreateIUriBuilder();
11058
11059     trace("test IUriBuilder_CreateInvalidArgs...\n");
11060     test_IUriBuilder_CreateInvalidArgs();
11061
11062     trace("test IUriBuilder...\n");
11063     test_IUriBuilder();
11064
11065     trace("test IUriBuilder_GetInvalidArgs...\n");
11066     test_IUriBuilder_GetInvalidArgs();
11067
11068     trace("test IUriBuilder_HasBeenModified...\n");
11069     test_IUriBuilder_HasBeenModified();
11070
11071     trace("test IUriBuilder_IUriProperty...\n");
11072     test_IUriBuilder_IUriProperty();
11073
11074     trace("test IUriBuilder_RemoveProperties...\n");
11075     test_IUriBuilder_RemoveProperties();
11076
11077     trace("test IUriBuilder miscellaneous...\n");
11078     test_IUriBuilder_Misc();
11079
11080     trace("test IUriBuilderFactory...\n");
11081     test_IUriBuilderFactory();
11082
11083     trace("test CoInternetCombineIUri...\n");
11084     test_CoInternetCombineIUri();
11085
11086     trace("test CoInternetCombineUrlEx...\n");
11087     test_CoInternetCombineUrlEx();
11088
11089     trace("test CoInternetParseIUri Invalid Args...\n");
11090     test_CoInternetParseIUri_InvalidArgs();
11091
11092     trace("test CoInternetParseIUri...\n");
11093     test_CoInternetParseIUri();
11094
11095     register_protocols();
11096
11097     trace("test CoInternetCombineIUri pluggable...\n");
11098     test_CoInternetCombineIUri_Pluggable();
11099
11100     trace("test CoInternetCombineUrlEx Pluggable...\n");
11101     test_CoInternetCombineUrlEx_Pluggable();
11102
11103     trace("test CoInternetParseIUri pluggable...\n");
11104     test_CoInternetParseIUri_Pluggable();
11105
11106     trace("test CreateURLMoniker...\n");
11107     test_CreateURLMoniker();
11108
11109     CoInitialize(NULL);
11110
11111     trace("test IPersistStream...\n");
11112     test_IPersistStream();
11113
11114     trace("test uninitialized Uri...\n");
11115     test_UninitializedUri();
11116
11117     CoUninitialize();
11118     unregister_protocols();
11119 }