urlmon: Added empty hash URIs comparing tests.
[wine] / dlls / urlmon / tests / uri.c
1 /*
2  * UrlMon IUri tests
3  *
4  * Copyright 2010 Thomas Mullaly
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #include <wine/test.h>
22 #include <stdarg.h>
23 #include <stddef.h>
24
25 #define COBJMACROS
26 #define CONST_VTABLE
27 #define WIN32_LEAN_AND_MEAN
28
29 #include "windef.h"
30 #include "winbase.h"
31 #include "urlmon.h"
32 #include "shlwapi.h"
33 #include "wininet.h"
34 #include "strsafe.h"
35 #include "initguid.h"
36
37 DEFINE_GUID(CLSID_CUri, 0xDF2FCE13, 0x25EC, 0x45BB, 0x9D,0x4C, 0xCE,0xCD,0x47,0xC2,0x43,0x0C);
38
39 #define URI_STR_PROPERTY_COUNT Uri_PROPERTY_STRING_LAST+1
40 #define URI_DWORD_PROPERTY_COUNT (Uri_PROPERTY_DWORD_LAST - Uri_PROPERTY_DWORD_START)+1
41 #define URI_BUILDER_STR_PROPERTY_COUNT 7
42
43 #define DEFINE_EXPECT(func) \
44     static BOOL expect_ ## func = FALSE, called_ ## func = FALSE
45
46 #define SET_EXPECT(func) \
47     expect_ ## func = TRUE
48
49 #define CHECK_EXPECT(func) \
50     do { \
51         ok(expect_ ##func, "unexpected call " #func "\n"); \
52         expect_ ## func = FALSE; \
53         called_ ## func = TRUE; \
54     }while(0)
55
56 #define CHECK_EXPECT2(func) \
57     do { \
58         ok(expect_ ##func, "unexpected call " #func "\n"); \
59         called_ ## func = TRUE; \
60     }while(0)
61
62 #define CHECK_CALLED(func) \
63     do { \
64         ok(called_ ## func, "expected " #func "\n"); \
65         expect_ ## func = called_ ## func = FALSE; \
66     }while(0)
67
68 DEFINE_EXPECT(CombineUrl);
69 DEFINE_EXPECT(ParseUrl);
70
71 static HRESULT (WINAPI *pCreateUri)(LPCWSTR, DWORD, DWORD_PTR, IUri**);
72 static HRESULT (WINAPI *pCreateUriWithFragment)(LPCWSTR, LPCWSTR, DWORD, DWORD_PTR, IUri**);
73 static HRESULT (WINAPI *pCreateIUriBuilder)(IUri*, DWORD, DWORD_PTR, IUriBuilder**);
74 static HRESULT (WINAPI *pCoInternetCombineIUri)(IUri*,IUri*,DWORD,IUri**,DWORD_PTR);
75 static HRESULT (WINAPI *pCoInternetGetSession)(DWORD,IInternetSession**,DWORD);
76 static HRESULT (WINAPI *pCoInternetCombineUrlEx)(IUri*,LPCWSTR,DWORD,IUri**,DWORD_PTR);
77 static HRESULT (WINAPI *pCoInternetParseIUri)(IUri*,PARSEACTION,DWORD,LPWSTR,DWORD,DWORD*,DWORD_PTR);
78 static HRESULT (WINAPI *pCreateURLMonikerEx)(IMoniker*,LPCWSTR,IMoniker**,DWORD);
79 static HRESULT (WINAPI *pCreateURLMonikerEx2)(IMoniker*,IUri*,IMoniker**,DWORD);
80
81 static const WCHAR http_urlW[] = { 'h','t','t','p',':','/','/','w','w','w','.','w','i','n','e','h','q',
82         '.','o','r','g','/',0};
83 static const WCHAR http_url_fragW[] = { 'h','t','t','p',':','/','/','w','w','w','.','w','i','n','e','h','q',
84         '.','o','r','g','/','#','F','r','a','g',0};
85
86 static const WCHAR combine_baseW[] = {'w','i','n','e','t','e','s','t',':','?','t',
87         'e','s','t','i','n','g',0};
88 static const WCHAR combine_relativeW[] = {'?','t','e','s','t',0};
89 static const WCHAR combine_resultW[] = {'z','i','p',':','t','e','s','t',0};
90
91 static const WCHAR winetestW[] = {'w','i','n','e','t','e','s','t',0};
92
93 static const WCHAR parse_urlW[] = {'w','i','n','e','t','e','s','t',':','t','e','s','t',0};
94 static const WCHAR parse_resultW[] = {'z','i','p',':','t','e','s','t',0};
95
96 static PARSEACTION parse_action;
97 static DWORD parse_flags;
98
99 typedef struct _uri_create_flag_test {
100     DWORD   flags;
101     HRESULT expected;
102 } uri_create_flag_test;
103
104 static const uri_create_flag_test invalid_flag_tests[] = {
105     /* Set of invalid flag combinations to test for. */
106     {Uri_CREATE_DECODE_EXTRA_INFO | Uri_CREATE_NO_DECODE_EXTRA_INFO, E_INVALIDARG},
107     {Uri_CREATE_CANONICALIZE | Uri_CREATE_NO_CANONICALIZE, E_INVALIDARG},
108     {Uri_CREATE_CRACK_UNKNOWN_SCHEMES | Uri_CREATE_NO_CRACK_UNKNOWN_SCHEMES, E_INVALIDARG},
109     {Uri_CREATE_PRE_PROCESS_HTML_URI | Uri_CREATE_NO_PRE_PROCESS_HTML_URI, E_INVALIDARG},
110     {Uri_CREATE_IE_SETTINGS | Uri_CREATE_NO_IE_SETTINGS, E_INVALIDARG}
111 };
112
113 typedef struct _uri_str_property {
114     const char* value;
115     HRESULT     expected;
116     BOOL        todo;
117     const char* broken_value;
118 } uri_str_property;
119
120 typedef struct _uri_dword_property {
121     DWORD   value;
122     HRESULT expected;
123     BOOL    todo;
124     BOOL    broken_combine_hres;
125 } uri_dword_property;
126
127 typedef struct _uri_properties {
128     const char*         uri;
129     DWORD               create_flags;
130     HRESULT             create_expected;
131     BOOL                create_todo;
132
133     uri_str_property    str_props[URI_STR_PROPERTY_COUNT];
134     uri_dword_property  dword_props[URI_DWORD_PROPERTY_COUNT];
135 } uri_properties;
136
137 static const uri_properties uri_tests[] = {
138     {   "http://www.winehq.org/tests/../tests/../..", 0, S_OK, FALSE,
139         {
140             {"http://www.winehq.org/",S_OK,FALSE},                      /* ABSOLUTE_URI */
141             {"www.winehq.org",S_OK,FALSE},                              /* AUTHORITY */
142             {"http://www.winehq.org/",S_OK,FALSE},                      /* DISPLAY_URI */
143             {"winehq.org",S_OK,FALSE},                                  /* DOMAIN */
144             {"",S_FALSE,FALSE},                                         /* EXTENSION */
145             {"",S_FALSE,FALSE},                                         /* FRAGMENT */
146             {"www.winehq.org",S_OK,FALSE},                              /* HOST */
147             {"",S_FALSE,FALSE},                                         /* PASSWORD */
148             {"/",S_OK,FALSE},                                           /* PATH */
149             {"/",S_OK,FALSE},                                           /* PATH_AND_QUERY */
150             {"",S_FALSE,FALSE},                                         /* QUERY */
151             {"http://www.winehq.org/tests/../tests/../..",S_OK,FALSE},  /* RAW_URI */
152             {"http",S_OK,FALSE},                                        /* SCHEME_NAME */
153             {"",S_FALSE,FALSE},                                         /* USER_INFO */
154             {"",S_FALSE,FALSE}                                          /* USER_NAME */
155         },
156         {
157             {Uri_HOST_DNS,S_OK,FALSE},                                  /* HOST_TYPE */
158             {80,S_OK,FALSE},                                            /* PORT */
159             {URL_SCHEME_HTTP,S_OK,FALSE},                               /* SCHEME */
160             {URLZONE_INVALID,E_NOTIMPL,FALSE}                           /* ZONE */
161         }
162     },
163     {   "http://winehq.org/tests/.././tests", 0, S_OK, FALSE,
164         {
165             {"http://winehq.org/tests",S_OK,FALSE},
166             {"winehq.org",S_OK,FALSE},
167             {"http://winehq.org/tests",S_OK,FALSE},
168             {"winehq.org",S_OK,FALSE},
169             {"",S_FALSE,FALSE},
170             {"",S_FALSE,FALSE},
171             {"winehq.org",S_OK,FALSE},
172             {"",S_FALSE,FALSE},
173             {"/tests",S_OK,FALSE},
174             {"/tests",S_OK,FALSE},
175             {"",S_FALSE,FALSE},
176             {"http://winehq.org/tests/.././tests",S_OK,FALSE},
177             {"http",S_OK,FALSE},
178             {"",S_FALSE,FALSE},
179             {"",S_FALSE,FALSE}
180         },
181         {
182             {Uri_HOST_DNS,S_OK,FALSE},
183             {80,S_OK,FALSE},
184             {URL_SCHEME_HTTP,S_OK,FALSE},
185             {URLZONE_INVALID,E_NOTIMPL,FALSE}
186         }
187     },
188     {   "HtTp://www.winehq.org/tests/..?query=x&return=y", 0, S_OK, FALSE,
189         {
190             {"http://www.winehq.org/?query=x&return=y",S_OK,FALSE},
191             {"www.winehq.org",S_OK,FALSE},
192             {"http://www.winehq.org/?query=x&return=y",S_OK,FALSE},
193             {"winehq.org",S_OK,FALSE},
194             {"",S_FALSE,FALSE},
195             {"",S_FALSE,FALSE},
196             {"www.winehq.org",S_OK,FALSE},
197             {"",S_FALSE,FALSE},
198             {"/",S_OK,FALSE},
199             {"/?query=x&return=y",S_OK,FALSE},
200             {"?query=x&return=y",S_OK,FALSE},
201             {"HtTp://www.winehq.org/tests/..?query=x&return=y",S_OK,FALSE},
202             {"http",S_OK,FALSE},
203             {"",S_FALSE,FALSE},
204             {"",S_FALSE,FALSE}
205         },
206         {
207             {Uri_HOST_DNS,S_OK,FALSE},
208             {80,S_OK,FALSE},
209             {URL_SCHEME_HTTP,S_OK,FALSE},
210             {URLZONE_INVALID,E_NOTIMPL,FALSE},
211         }
212     },
213     {   "HtTpS://www.winehq.org/tests/..?query=x&return=y", 0, S_OK, FALSE,
214         {
215             {"https://www.winehq.org/?query=x&return=y",S_OK,FALSE},
216             {"www.winehq.org",S_OK,FALSE},
217             {"https://www.winehq.org/?query=x&return=y",S_OK,FALSE},
218             {"winehq.org",S_OK,FALSE},
219             {"",S_FALSE,FALSE},
220             {"",S_FALSE,FALSE},
221             {"www.winehq.org",S_OK,FALSE},
222             {"",S_FALSE,FALSE},
223             {"/",S_OK,FALSE},
224             {"/?query=x&return=y",S_OK,FALSE},
225             {"?query=x&return=y",S_OK,FALSE},
226             {"HtTpS://www.winehq.org/tests/..?query=x&return=y",S_OK,FALSE},
227             {"https",S_OK,FALSE},
228             {"",S_FALSE,FALSE},
229             {"",S_FALSE,FALSE}
230         },
231         {
232             {Uri_HOST_DNS,S_OK,FALSE},
233             {443,S_OK,FALSE},
234             {URL_SCHEME_HTTPS,S_OK,FALSE},
235             {URLZONE_INVALID,E_NOTIMPL,FALSE},
236         }
237     },
238     {   "hTTp://us%45r%3Ainfo@examp%4CE.com:80/path/a/b/./c/../%2E%2E/Forbidden'<|> Characters", 0, S_OK, FALSE,
239         {
240             {"http://usEr%3Ainfo@example.com/path/a/Forbidden'%3C%7C%3E%20Characters",S_OK,FALSE},
241             {"usEr%3Ainfo@example.com",S_OK,FALSE},
242             {"http://example.com/path/a/Forbidden'%3C%7C%3E%20Characters",S_OK,FALSE},
243             {"example.com",S_OK,FALSE},
244             {"",S_FALSE,FALSE},
245             {"",S_FALSE,FALSE},
246             {"example.com",S_OK,FALSE},
247             {"",S_FALSE,FALSE},
248             {"/path/a/Forbidden'%3C%7C%3E%20Characters",S_OK,FALSE},
249             {"/path/a/Forbidden'%3C%7C%3E%20Characters",S_OK,FALSE},
250             {"",S_FALSE,FALSE},
251             {"hTTp://us%45r%3Ainfo@examp%4CE.com:80/path/a/b/./c/../%2E%2E/Forbidden'<|> Characters",S_OK,FALSE},
252             {"http",S_OK,FALSE},
253             {"usEr%3Ainfo",S_OK,FALSE},
254             {"usEr%3Ainfo",S_OK,FALSE}
255         },
256         {
257             {Uri_HOST_DNS,S_OK,FALSE},
258             {80,S_OK,FALSE},
259             {URL_SCHEME_HTTP,S_OK,FALSE},
260             {URLZONE_INVALID,E_NOTIMPL,FALSE},
261         }
262     },
263     {   "ftp://winepass:wine@ftp.winehq.org:9999/dir/foo bar.txt", 0, S_OK, FALSE,
264         {
265             {"ftp://winepass:wine@ftp.winehq.org:9999/dir/foo%20bar.txt",S_OK,FALSE},
266             {"winepass:wine@ftp.winehq.org:9999",S_OK,FALSE},
267             {"ftp://ftp.winehq.org:9999/dir/foo%20bar.txt",S_OK,FALSE},
268             {"winehq.org",S_OK,FALSE},
269             {".txt",S_OK,FALSE},
270             {"",S_FALSE,FALSE},
271             {"ftp.winehq.org",S_OK,FALSE},
272             {"wine",S_OK,FALSE},
273             {"/dir/foo%20bar.txt",S_OK,FALSE},
274             {"/dir/foo%20bar.txt",S_OK,FALSE},
275             {"",S_FALSE,FALSE},
276             {"ftp://winepass:wine@ftp.winehq.org:9999/dir/foo bar.txt",S_OK,FALSE},
277             {"ftp",S_OK,FALSE},
278             {"winepass:wine",S_OK,FALSE},
279             {"winepass",S_OK,FALSE}
280         },
281         {
282             {Uri_HOST_DNS,S_OK,FALSE},
283             {9999,S_OK,FALSE},
284             {URL_SCHEME_FTP,S_OK,FALSE},
285             {URLZONE_INVALID,E_NOTIMPL,FALSE}
286         }
287     },
288     {   "file://c:\\tests\\../tests/foo%20bar.mp3", 0, S_OK, FALSE,
289         {
290             {"file:///c:/tests/foo%2520bar.mp3",S_OK,FALSE},
291             {"",S_FALSE,FALSE},
292             {"file:///c:/tests/foo%2520bar.mp3",S_OK,FALSE},
293             {"",S_FALSE,FALSE},
294             {".mp3",S_OK,FALSE},
295             {"",S_FALSE,FALSE},
296             {"",S_FALSE,FALSE},
297             {"",S_FALSE,FALSE},
298             {"/c:/tests/foo%2520bar.mp3",S_OK,FALSE},
299             {"/c:/tests/foo%2520bar.mp3",S_OK,FALSE},
300             {"",S_FALSE,FALSE},
301             {"file://c:\\tests\\../tests/foo%20bar.mp3",S_OK,FALSE},
302             {"file",S_OK,FALSE},
303             {"",S_FALSE,FALSE},
304             {"",S_FALSE,FALSE}
305         },
306         {
307             {Uri_HOST_UNKNOWN,S_OK,FALSE},
308             {0,S_FALSE,FALSE},
309             {URL_SCHEME_FILE,S_OK,FALSE},
310             {URLZONE_INVALID,E_NOTIMPL,FALSE}
311         }
312     },
313     {   "file://c:\\tests\\../tests/foo%20bar.mp3", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
314         {
315             {"file:///c:/tests/../tests/foo%2520bar.mp3",S_OK,FALSE},
316             {"",S_FALSE,FALSE},
317             {"file:///c:/tests/../tests/foo%2520bar.mp3",S_OK,FALSE},
318             {"",S_FALSE,FALSE},
319             {".mp3",S_OK,FALSE},
320             {"",S_FALSE,FALSE},
321             {"",S_FALSE,FALSE},
322             {"",S_FALSE,FALSE},
323             {"/c:/tests/../tests/foo%2520bar.mp3",S_OK,FALSE},
324             {"/c:/tests/../tests/foo%2520bar.mp3",S_OK,FALSE},
325             {"",S_FALSE,FALSE},
326             {"file://c:\\tests\\../tests/foo%20bar.mp3",S_OK,FALSE},
327             {"file",S_OK,FALSE},
328             {"",S_FALSE,FALSE},
329             {"",S_FALSE,FALSE}
330         },
331         {
332             {Uri_HOST_UNKNOWN,S_OK,FALSE},
333             {0,S_FALSE,FALSE},
334             {URL_SCHEME_FILE,S_OK,FALSE},
335             {URLZONE_INVALID,E_NOTIMPL,FALSE}
336         }
337     },
338     {   "FILE://localhost/test dir\\../tests/test%20file.README.txt", 0, S_OK, FALSE,
339         {
340             {"file:///tests/test%20file.README.txt",S_OK,FALSE},
341             {"",S_FALSE,FALSE},
342             {"file:///tests/test%20file.README.txt",S_OK,FALSE},
343             {"",S_FALSE,FALSE},
344             {".txt",S_OK,FALSE},
345             {"",S_FALSE,FALSE},
346             {"",S_FALSE,FALSE},
347             {"",S_FALSE,FALSE},
348             {"/tests/test%20file.README.txt",S_OK,FALSE},
349             {"/tests/test%20file.README.txt",S_OK,FALSE},
350             {"",S_FALSE,FALSE},
351             {"FILE://localhost/test dir\\../tests/test%20file.README.txt",S_OK,FALSE},
352             {"file",S_OK,FALSE},
353             {"",S_FALSE,FALSE},
354             {"",S_FALSE,FALSE}
355         },
356         {
357             {Uri_HOST_UNKNOWN,S_OK,FALSE},
358             {0,S_FALSE,FALSE},
359             {URL_SCHEME_FILE,S_OK,FALSE},
360             {URLZONE_INVALID,E_NOTIMPL,FALSE}
361         }
362     },
363     {   "urn:nothing:should:happen here", 0, S_OK, FALSE,
364         {
365             {"urn:nothing:should:happen here",S_OK,FALSE},
366             {"",S_FALSE,FALSE},
367             {"urn:nothing:should:happen here",S_OK,FALSE},
368             {"",S_FALSE,FALSE},
369             {"",S_FALSE,FALSE},
370             {"",S_FALSE,FALSE},
371             {"",S_FALSE,FALSE},
372             {"",S_FALSE,FALSE},
373             {"nothing:should:happen here",S_OK,FALSE},
374             {"nothing:should:happen here",S_OK,FALSE},
375             {"",S_FALSE,FALSE},
376             {"urn:nothing:should:happen here",S_OK,FALSE},
377             {"urn",S_OK,FALSE},
378             {"",S_FALSE,FALSE},
379             {"",S_FALSE,FALSE}
380         },
381         {
382             {Uri_HOST_UNKNOWN,S_OK,FALSE},
383             {0,S_FALSE,FALSE},
384             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
385             {URLZONE_INVALID,E_NOTIMPL,FALSE}
386         }
387     },
388     {   "http://127.0.0.1/tests/../test dir/./test.txt", 0, S_OK, FALSE,
389         {
390             {"http://127.0.0.1/test%20dir/test.txt",S_OK,FALSE},
391             {"127.0.0.1",S_OK,FALSE},
392             {"http://127.0.0.1/test%20dir/test.txt",S_OK,FALSE},
393             {"",S_FALSE,FALSE},
394             {".txt",S_OK,FALSE},
395             {"",S_FALSE,FALSE},
396             {"127.0.0.1",S_OK,FALSE},
397             {"",S_FALSE,FALSE},
398             {"/test%20dir/test.txt",S_OK,FALSE},
399             {"/test%20dir/test.txt",S_OK,FALSE},
400             {"",S_FALSE,FALSE},
401             {"http://127.0.0.1/tests/../test dir/./test.txt",S_OK,FALSE},
402             {"http",S_OK,FALSE},
403             {"",S_FALSE,FALSE},
404             {"",S_FALSE,FALSE}
405         },
406         {
407             {Uri_HOST_IPV4,S_OK,FALSE},
408             {80,S_OK,FALSE},
409             {URL_SCHEME_HTTP,S_OK,FALSE},
410             {URLZONE_INVALID,E_NOTIMPL,FALSE}
411         }
412     },
413     {   "http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]", 0, S_OK, FALSE,
414         {
415             {"http://[fedc:ba98:7654:3210:fedc:ba98:7654:3210]/",S_OK,FALSE},
416             {"[fedc:ba98:7654:3210:fedc:ba98:7654:3210]",S_OK,FALSE},
417             {"http://[fedc:ba98:7654:3210:fedc:ba98:7654:3210]/",S_OK,FALSE},
418             {"",S_FALSE,FALSE},
419             {"",S_FALSE,FALSE},
420             {"",S_FALSE,FALSE},
421             {"fedc:ba98:7654:3210:fedc:ba98:7654:3210",S_OK,FALSE},
422             {"",S_FALSE,FALSE},
423             {"/",S_OK,FALSE},
424             {"/",S_OK,FALSE},
425             {"",S_FALSE,FALSE},
426             {"http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]",S_OK,FALSE},
427             {"http",S_OK,FALSE},
428             {"",S_FALSE,FALSE},
429             {"",S_FALSE,FALSE}
430         },
431         {
432             {Uri_HOST_IPV6,S_OK,FALSE},
433             {80,S_OK,FALSE},
434             {URL_SCHEME_HTTP,S_OK,FALSE},
435             {URLZONE_INVALID,E_NOTIMPL,FALSE}
436         }
437     },
438     {   "ftp://[::13.1.68.3]", 0, S_OK, FALSE,
439         {
440             {"ftp://[::13.1.68.3]/",S_OK,FALSE},
441             {"[::13.1.68.3]",S_OK,FALSE},
442             {"ftp://[::13.1.68.3]/",S_OK,FALSE},
443             {"",S_FALSE,FALSE},
444             {"",S_FALSE,FALSE},
445             {"",S_FALSE,FALSE},
446             {"::13.1.68.3",S_OK,FALSE},
447             {"",S_FALSE,FALSE},
448             {"/",S_OK,FALSE},
449             {"/",S_OK,FALSE},
450             {"",S_FALSE,FALSE},
451             {"ftp://[::13.1.68.3]",S_OK,FALSE},
452             {"ftp",S_OK,FALSE},
453             {"",S_FALSE,FALSE},
454             {"",S_FALSE,FALSE}
455         },
456         {
457             {Uri_HOST_IPV6,S_OK,FALSE},
458             {21,S_OK,FALSE},
459             {URL_SCHEME_FTP,S_OK,FALSE},
460             {URLZONE_INVALID,E_NOTIMPL,FALSE}
461         }
462     },
463     {   "http://[FEDC:BA98:0:0:0:0:0:3210]", 0, S_OK, FALSE,
464         {
465             {"http://[fedc:ba98::3210]/",S_OK,FALSE},
466             {"[fedc:ba98::3210]",S_OK,FALSE},
467             {"http://[fedc:ba98::3210]/",S_OK,FALSE},
468             {"",S_FALSE,FALSE},
469             {"",S_FALSE,FALSE},
470             {"",S_FALSE,FALSE},
471             {"fedc:ba98::3210",S_OK,FALSE},
472             {"",S_FALSE,FALSE},
473             {"/",S_OK,FALSE},
474             {"/",S_OK,FALSE},
475             {"",S_FALSE,FALSE},
476             {"http://[FEDC:BA98:0:0:0:0:0:3210]",S_OK,FALSE},
477             {"http",S_OK,FALSE},
478             {"",S_FALSE,FALSE},
479             {"",S_FALSE,FALSE},
480         },
481         {
482             {Uri_HOST_IPV6,S_OK,FALSE},
483             {80,S_OK,FALSE},
484             {URL_SCHEME_HTTP,S_OK,FALSE},
485             {URLZONE_INVALID,E_NOTIMPL,FALSE}
486         }
487     },
488     {   "1234://www.winehq.org", 0, S_OK, FALSE,
489         {
490             {"1234://www.winehq.org/",S_OK,FALSE},
491             {"www.winehq.org",S_OK,FALSE},
492             {"1234://www.winehq.org/",S_OK,FALSE},
493             {"winehq.org",S_OK,FALSE},
494             {"",S_FALSE,FALSE},
495             {"",S_FALSE,FALSE},
496             {"www.winehq.org",S_OK,FALSE},
497             {"",S_FALSE,FALSE},
498             {"/",S_OK,FALSE},
499             {"/",S_OK,FALSE},
500             {"",S_FALSE,FALSE},
501             {"1234://www.winehq.org",S_OK,FALSE},
502             {"1234",S_OK,FALSE},
503             {"",S_FALSE,FALSE},
504             {"",S_FALSE,FALSE}
505         },
506         {
507             {Uri_HOST_DNS,S_OK,FALSE},
508             {0,S_FALSE,FALSE},
509             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
510             {URLZONE_INVALID,E_NOTIMPL,FALSE}
511         }
512     },
513     /* Test's to make sure the parser/canonicalizer handles implicit file schemes correctly. */
514     {   "C:/test/test.mp3", Uri_CREATE_ALLOW_IMPLICIT_FILE_SCHEME, S_OK, FALSE,
515         {
516             {"file:///C:/test/test.mp3",S_OK,FALSE},
517             {"",S_FALSE,FALSE},
518             {"file:///C:/test/test.mp3",S_OK,FALSE},
519             {"",S_FALSE,FALSE},
520             {".mp3",S_OK,FALSE},
521             {"",S_FALSE,FALSE},
522             {"",S_FALSE,FALSE},
523             {"",S_FALSE,FALSE},
524             {"/C:/test/test.mp3",S_OK,FALSE},
525             {"/C:/test/test.mp3",S_OK,FALSE},
526             {"",S_FALSE,FALSE},
527             {"C:/test/test.mp3",S_OK,FALSE},
528             {"file",S_OK,FALSE},
529             {"",S_FALSE,FALSE},
530             {"",S_FALSE,FALSE}
531         },
532         {
533             {Uri_HOST_UNKNOWN,S_OK,FALSE},
534             {0,S_FALSE,FALSE},
535             {URL_SCHEME_FILE,S_OK,FALSE},
536             {URLZONE_INVALID,E_NOTIMPL,FALSE}
537         }
538     },
539     /* Test's to make sure the parser/canonicalizer handles implicit file schemes correctly. */
540     {   "\\\\Server/test.mp3", Uri_CREATE_ALLOW_IMPLICIT_FILE_SCHEME, S_OK, FALSE,
541         {
542             {"file://server/test.mp3",S_OK,FALSE},
543             {"server",S_OK,FALSE},
544             {"file://server/test.mp3",S_OK,FALSE},
545             {"",S_FALSE,FALSE},
546             {".mp3",S_OK,FALSE},
547             {"",S_FALSE,FALSE},
548             {"server",S_OK,FALSE},
549             {"",S_FALSE,FALSE},
550             {"/test.mp3",S_OK,FALSE},
551             {"/test.mp3",S_OK,FALSE},
552             {"",S_FALSE,FALSE},
553             {"\\\\Server/test.mp3",S_OK,FALSE},
554             {"file",S_OK,FALSE},
555             {"",S_FALSE,FALSE},
556             {"",S_FALSE,FALSE}
557         },
558         {
559             {Uri_HOST_DNS,S_OK,FALSE},
560             {0,S_FALSE,FALSE},
561             {URL_SCHEME_FILE,S_OK,FALSE},
562             {URLZONE_INVALID,E_NOTIMPL,FALSE}
563         }
564     },
565     {   "www.winehq.org/test", Uri_CREATE_ALLOW_IMPLICIT_WILDCARD_SCHEME, S_OK, FALSE,
566         {
567             {"*:www.winehq.org/test",S_OK,FALSE},
568             {"www.winehq.org",S_OK,FALSE},
569             {"*:www.winehq.org/test",S_OK,FALSE},
570             {"winehq.org",S_OK,FALSE},
571             {"",S_FALSE,FALSE},
572             {"",S_FALSE,FALSE},
573             {"www.winehq.org",S_OK,FALSE},
574             {"",S_FALSE,FALSE},
575             {"/test",S_OK,FALSE},
576             {"/test",S_OK,FALSE},
577             {"",S_FALSE,FALSE},
578             {"www.winehq.org/test",S_OK,FALSE},
579             {"*",S_OK,FALSE},
580             {"",S_FALSE,FALSE},
581             {"",S_FALSE,FALSE}
582         },
583         {
584             {Uri_HOST_DNS,S_OK,FALSE},
585             {0,S_FALSE,FALSE},
586             {URL_SCHEME_WILDCARD,S_OK,FALSE},
587             {URLZONE_INVALID,E_NOTIMPL,FALSE}
588         }
589     },
590     /* Valid since the '*' is the only character in the scheme name. */
591     {   "*:www.winehq.org/test", 0, S_OK, FALSE,
592         {
593             {"*:www.winehq.org/test",S_OK,FALSE},
594             {"www.winehq.org",S_OK,FALSE},
595             {"*:www.winehq.org/test",S_OK,FALSE},
596             {"winehq.org",S_OK,FALSE},
597             {"",S_FALSE,FALSE},
598             {"",S_FALSE,FALSE},
599             {"www.winehq.org",S_OK,FALSE},
600             {"",S_FALSE,FALSE},
601             {"/test",S_OK,FALSE},
602             {"/test",S_OK,FALSE},
603             {"",S_FALSE,FALSE},
604             {"*:www.winehq.org/test",S_OK,FALSE},
605             {"*",S_OK,FALSE},
606             {"",S_FALSE,FALSE},
607             {"",S_FALSE,FALSE}
608         },
609         {
610             {Uri_HOST_DNS,S_OK,FALSE},
611             {0,S_FALSE,FALSE},
612             {URL_SCHEME_WILDCARD,S_OK,FALSE},
613             {URLZONE_INVALID,E_NOTIMPL,FALSE}
614         }
615     },
616     {   "/../some dir/test.ext", Uri_CREATE_ALLOW_RELATIVE, S_OK, FALSE,
617         {
618             {"/../some dir/test.ext",S_OK,FALSE},
619             {"",S_FALSE,FALSE},
620             {"/../some dir/test.ext",S_OK,FALSE},
621             {"",S_FALSE,FALSE},
622             {".ext",S_OK,FALSE},
623             {"",S_FALSE,FALSE},
624             {"",S_FALSE,FALSE},
625             {"",S_FALSE,FALSE},
626             {"/../some dir/test.ext",S_OK,FALSE},
627             {"/../some dir/test.ext",S_OK,FALSE},
628             {"",S_FALSE,FALSE},
629             {"/../some dir/test.ext",S_OK,FALSE},
630             {"",S_FALSE,FALSE},
631             {"",S_FALSE,FALSE},
632             {"",S_FALSE,FALSE}
633         },
634         {
635             {Uri_HOST_UNKNOWN,S_OK,FALSE},
636             {0,S_FALSE,FALSE},
637             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
638             {URLZONE_INVALID,E_NOTIMPL,FALSE}
639         }
640     },
641     {   "//implicit/wildcard/uri scheme", Uri_CREATE_ALLOW_RELATIVE|Uri_CREATE_ALLOW_IMPLICIT_WILDCARD_SCHEME, S_OK, FALSE,
642         {
643             {"*://implicit/wildcard/uri%20scheme",S_OK,FALSE},
644             {"",S_OK,FALSE},
645             {"*://implicit/wildcard/uri%20scheme",S_OK,FALSE},
646             {"",S_FALSE,FALSE},
647             {"",S_FALSE,FALSE},
648             {"",S_FALSE,FALSE},
649             {"",S_OK,FALSE},
650             {"",S_FALSE,FALSE},
651             {"//implicit/wildcard/uri%20scheme",S_OK,FALSE},
652             {"//implicit/wildcard/uri%20scheme",S_OK,FALSE},
653             {"",S_FALSE,FALSE},
654             {"//implicit/wildcard/uri scheme",S_OK,FALSE},
655             {"*",S_OK,FALSE},
656             {"",S_FALSE,FALSE},
657             {"",S_FALSE,FALSE},
658         },
659         {
660             {Uri_HOST_UNKNOWN,S_OK,FALSE},
661             {0,S_FALSE,FALSE},
662             {URL_SCHEME_WILDCARD,S_OK,FALSE},
663             {URLZONE_INVALID,E_NOTIMPL,FALSE}
664         }
665     },
666     /* URI is considered opaque since CREATE_NO_CRACK_UNKNOWN_SCHEMES is set and its an unknown scheme. */
667     {   "zip://google.com", Uri_CREATE_NO_CRACK_UNKNOWN_SCHEMES, S_OK, FALSE,
668         {
669             {"zip:/.//google.com",S_OK,FALSE},
670             {"",S_FALSE,FALSE},
671             {"zip:/.//google.com",S_OK,FALSE},
672             {"",S_FALSE,FALSE},
673             {".com",S_OK,FALSE},
674             {"",S_FALSE,FALSE},
675             {"",S_FALSE,FALSE},
676             {"",S_FALSE,FALSE},
677             {"/.//google.com",S_OK,FALSE},
678             {"/.//google.com",S_OK,FALSE},
679             {"",S_FALSE,FALSE},
680             {"zip://google.com",S_OK,FALSE},
681             {"zip",S_OK,FALSE},
682             {"",S_FALSE,FALSE},
683             {"",S_FALSE,FALSE}
684         },
685         {
686             {Uri_HOST_UNKNOWN,S_OK,FALSE},
687             {0,S_FALSE,FALSE},
688             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
689             {URLZONE_INVALID,E_NOTIMPL,FALSE}
690         }
691     },
692     /* Windows uses the first occurrence of ':' to delimit the userinfo. */
693     {   "ftp://user:pass:word@winehq.org/", 0, S_OK, FALSE,
694         {
695             {"ftp://user:pass:word@winehq.org/",S_OK,FALSE},
696             {"user:pass:word@winehq.org",S_OK,FALSE},
697             {"ftp://winehq.org/",S_OK,FALSE},
698             {"winehq.org",S_OK,FALSE},
699             {"",S_FALSE,FALSE},
700             {"",S_FALSE,FALSE},
701             {"winehq.org",S_OK,FALSE},
702             {"pass:word",S_OK,FALSE},
703             {"/",S_OK,FALSE},
704             {"/",S_OK,FALSE},
705             {"",S_FALSE,FALSE},
706             {"ftp://user:pass:word@winehq.org/",S_OK,FALSE},
707             {"ftp",S_OK,FALSE},
708             {"user:pass:word",S_OK,FALSE},
709             {"user",S_OK,FALSE}
710         },
711         {
712             {Uri_HOST_DNS,S_OK,FALSE},
713             {21,S_OK,FALSE},
714             {URL_SCHEME_FTP,S_OK,FALSE},
715             {URLZONE_INVALID,E_NOTIMPL,FALSE}
716         }
717     },
718     /* Make sure % encoded unreserved characters are decoded. */
719     {   "ftp://w%49%4Ee:PA%53%53@ftp.google.com/", 0, S_OK, FALSE,
720         {
721             {"ftp://wINe:PASS@ftp.google.com/",S_OK,FALSE},
722             {"wINe:PASS@ftp.google.com",S_OK,FALSE},
723             {"ftp://ftp.google.com/",S_OK,FALSE},
724             {"google.com",S_OK,FALSE},
725             {"",S_FALSE,FALSE},
726             {"",S_FALSE,FALSE},
727             {"ftp.google.com",S_OK,FALSE},
728             {"PASS",S_OK,FALSE},
729             {"/",S_OK,FALSE},
730             {"/",S_OK,FALSE},
731             {"",S_FALSE,FALSE},
732             {"ftp://w%49%4Ee:PA%53%53@ftp.google.com/",S_OK,FALSE},
733             {"ftp",S_OK,FALSE},
734             {"wINe:PASS",S_OK,FALSE},
735             {"wINe",S_OK,FALSE}
736         },
737         {
738             {Uri_HOST_DNS,S_OK,FALSE},
739             {21,S_OK,FALSE},
740             {URL_SCHEME_FTP,S_OK,FALSE},
741             {URLZONE_INVALID,E_NOTIMPL,FALSE}
742         }
743     },
744     /* Make sure % encoded characters which are NOT unreserved are NOT decoded. */
745     {   "ftp://w%5D%5Be:PA%7B%7D@ftp.google.com/", 0, S_OK, FALSE,
746         {
747             {"ftp://w%5D%5Be:PA%7B%7D@ftp.google.com/",S_OK,FALSE},
748             {"w%5D%5Be:PA%7B%7D@ftp.google.com",S_OK,FALSE},
749             {"ftp://ftp.google.com/",S_OK,FALSE},
750             {"google.com",S_OK,FALSE},
751             {"",S_FALSE,FALSE},
752             {"",S_FALSE,FALSE},
753             {"ftp.google.com",S_OK,FALSE},
754             {"PA%7B%7D",S_OK,FALSE},
755             {"/",S_OK,FALSE},
756             {"/",S_OK,FALSE},
757             {"",S_FALSE,FALSE},
758             {"ftp://w%5D%5Be:PA%7B%7D@ftp.google.com/",S_OK,FALSE},
759             {"ftp",S_OK,FALSE},
760             {"w%5D%5Be:PA%7B%7D",S_OK,FALSE},
761             {"w%5D%5Be",S_OK,FALSE}
762         },
763         {
764             {Uri_HOST_DNS,S_OK,FALSE},
765             {21,S_OK,FALSE},
766             {URL_SCHEME_FTP,S_OK,FALSE},
767             {URLZONE_INVALID,E_NOTIMPL,FALSE}
768         }
769     },
770     /* You're allowed to have an empty password portion in the userinfo section. */
771     {   "ftp://empty:@ftp.google.com/", 0, S_OK, FALSE,
772         {
773             {"ftp://empty:@ftp.google.com/",S_OK,FALSE},
774             {"empty:@ftp.google.com",S_OK,FALSE},
775             {"ftp://ftp.google.com/",S_OK,FALSE},
776             {"google.com",S_OK,FALSE},
777             {"",S_FALSE,FALSE},
778             {"",S_FALSE,FALSE},
779             {"ftp.google.com",S_OK,FALSE},
780             {"",S_OK,FALSE},
781             {"/",S_OK,FALSE},
782             {"/",S_OK,FALSE},
783             {"",S_FALSE,FALSE},
784             {"ftp://empty:@ftp.google.com/",S_OK,FALSE},
785             {"ftp",S_OK,FALSE},
786             {"empty:",S_OK,FALSE},
787             {"empty",S_OK,FALSE}
788         },
789         {
790             {Uri_HOST_DNS,S_OK,FALSE},
791             {21,S_OK,FALSE},
792             {URL_SCHEME_FTP,S_OK,FALSE},
793             {URLZONE_INVALID,E_NOTIMPL,FALSE}
794         }
795     },
796     /* Make sure forbidden characters in "userinfo" get encoded. */
797     {   "ftp://\" \"weird@ftp.google.com/", 0, S_OK, FALSE,
798         {
799             {"ftp://%22%20%22weird@ftp.google.com/",S_OK,FALSE},
800             {"%22%20%22weird@ftp.google.com",S_OK,FALSE},
801             {"ftp://ftp.google.com/",S_OK,FALSE},
802             {"google.com",S_OK,FALSE},
803             {"",S_FALSE,FALSE},
804             {"",S_FALSE,FALSE},
805             {"ftp.google.com",S_OK,FALSE},
806             {"",S_FALSE,FALSE},
807             {"/",S_OK,FALSE},
808             {"/",S_OK,FALSE},
809             {"",S_FALSE,FALSE},
810             {"ftp://\" \"weird@ftp.google.com/",S_OK,FALSE},
811             {"ftp",S_OK,FALSE},
812             {"%22%20%22weird",S_OK,FALSE},
813             {"%22%20%22weird",S_OK,FALSE}
814         },
815         {
816             {Uri_HOST_DNS,S_OK,FALSE},
817             {21,S_OK,FALSE},
818             {URL_SCHEME_FTP,S_OK,FALSE},
819             {URLZONE_INVALID,E_NOTIMPL,FALSE}
820         }
821     },
822     /* Make sure the forbidden characters don't get percent encoded. */
823     {   "ftp://\" \"weird@ftp.google.com/", Uri_CREATE_NO_ENCODE_FORBIDDEN_CHARACTERS, S_OK, FALSE,
824         {
825             {"ftp://\" \"weird@ftp.google.com/",S_OK,FALSE},
826             {"\" \"weird@ftp.google.com",S_OK,FALSE},
827             {"ftp://ftp.google.com/",S_OK,FALSE},
828             {"google.com",S_OK,FALSE},
829             {"",S_FALSE,FALSE},
830             {"",S_FALSE,FALSE},
831             {"ftp.google.com",S_OK,FALSE},
832             {"",S_FALSE,FALSE},
833             {"/",S_OK,FALSE},
834             {"/",S_OK,FALSE},
835             {"",S_FALSE,FALSE},
836             {"ftp://\" \"weird@ftp.google.com/",S_OK,FALSE},
837             {"ftp",S_OK,FALSE},
838             {"\" \"weird",S_OK,FALSE},
839             {"\" \"weird",S_OK,FALSE}
840         },
841         {
842             {Uri_HOST_DNS,S_OK,FALSE},
843             {21,S_OK,FALSE},
844             {URL_SCHEME_FTP,S_OK,FALSE},
845             {URLZONE_INVALID,E_NOTIMPL,FALSE}
846         }
847     },
848     /* Make sure already percent encoded characters don't get unencoded. */
849     {   "ftp://\"%20\"weird@ftp.google.com/\"%20\"weird", Uri_CREATE_NO_ENCODE_FORBIDDEN_CHARACTERS, S_OK, FALSE,
850         {
851             {"ftp://\"%20\"weird@ftp.google.com/\"%20\"weird",S_OK,FALSE},
852             {"\"%20\"weird@ftp.google.com",S_OK,FALSE},
853             {"ftp://ftp.google.com/\"%20\"weird",S_OK,FALSE},
854             {"google.com",S_OK,FALSE},
855             {"",S_FALSE,FALSE},
856             {"",S_FALSE,FALSE},
857             {"ftp.google.com",S_OK,FALSE},
858             {"",S_FALSE,FALSE},
859             {"/\"%20\"weird",S_OK,FALSE},
860             {"/\"%20\"weird",S_OK,FALSE},
861             {"",S_FALSE,FALSE},
862             {"ftp://\"%20\"weird@ftp.google.com/\"%20\"weird",S_OK,FALSE},
863             {"ftp",S_OK,FALSE},
864             {"\"%20\"weird",S_OK,FALSE},
865             {"\"%20\"weird",S_OK,FALSE}
866         },
867         {
868             {Uri_HOST_DNS,S_OK,FALSE},
869             {21,S_OK,FALSE},
870             {URL_SCHEME_FTP,S_OK,FALSE},
871             {URLZONE_INVALID,E_NOTIMPL,FALSE}
872         }
873     },
874     /* Allowed to have invalid % encoded because its an unknown scheme type. */
875     {   "zip://%xy:word@winehq.org/", 0, S_OK, FALSE,
876         {
877             {"zip://%xy:word@winehq.org/",S_OK,FALSE},
878             {"%xy:word@winehq.org",S_OK,FALSE},
879             {"zip://%xy:word@winehq.org/",S_OK,FALSE},
880             {"winehq.org",S_OK,FALSE},
881             {"",S_FALSE,FALSE},
882             {"",S_FALSE,FALSE},
883             {"winehq.org",S_OK,FALSE},
884             {"word",S_OK,FALSE},
885             {"/",S_OK,FALSE},
886             {"/",S_OK,FALSE},
887             {"",S_FALSE,FALSE},
888             {"zip://%xy:word@winehq.org/",S_OK,FALSE},
889             {"zip",S_OK,FALSE},
890             {"%xy:word",S_OK,FALSE},
891             {"%xy",S_OK,FALSE}
892         },
893         {
894             {Uri_HOST_DNS,S_OK,FALSE},
895             {0,S_FALSE,FALSE},
896             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
897             {URLZONE_INVALID,E_NOTIMPL,FALSE}
898         }
899     },
900     /* Unreserved, percent encoded characters aren't decoded in the userinfo because the scheme
901      * isn't known.
902      */
903     {   "zip://%2E:%52%53ord@winehq.org/", 0, S_OK, FALSE,
904         {
905             {"zip://%2E:%52%53ord@winehq.org/",S_OK,FALSE},
906             {"%2E:%52%53ord@winehq.org",S_OK,FALSE},
907             {"zip://%2E:%52%53ord@winehq.org/",S_OK,FALSE},
908             {"winehq.org",S_OK,FALSE},
909             {"",S_FALSE,FALSE},
910             {"",S_FALSE,FALSE},
911             {"winehq.org",S_OK,FALSE},
912             {"%52%53ord",S_OK,FALSE},
913             {"/",S_OK,FALSE},
914             {"/",S_OK,FALSE},
915             {"",S_FALSE,FALSE},
916             {"zip://%2E:%52%53ord@winehq.org/",S_OK,FALSE},
917             {"zip",S_OK,FALSE},
918             {"%2E:%52%53ord",S_OK,FALSE},
919             {"%2E",S_OK,FALSE}
920         },
921         {
922             {Uri_HOST_DNS,S_OK,FALSE},
923             {0,S_FALSE,FALSE},
924             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
925             {URLZONE_INVALID,E_NOTIMPL,FALSE}
926         }
927     },
928     {   "ftp://[](),'test':word@winehq.org/", 0, S_OK, FALSE,
929         {
930             {"ftp://[](),'test':word@winehq.org/",S_OK,FALSE},
931             {"[](),'test':word@winehq.org",S_OK,FALSE},
932             {"ftp://winehq.org/",S_OK,FALSE},
933             {"winehq.org",S_OK,FALSE},
934             {"",S_FALSE,FALSE},
935             {"",S_FALSE,FALSE},
936             {"winehq.org",S_OK,FALSE},
937             {"word",S_OK,FALSE},
938             {"/",S_OK,FALSE},
939             {"/",S_OK,FALSE},
940             {"",S_FALSE,FALSE},
941             {"ftp://[](),'test':word@winehq.org/",S_OK,FALSE},
942             {"ftp",S_OK,FALSE},
943             {"[](),'test':word",S_OK,FALSE},
944             {"[](),'test'",S_OK,FALSE}
945         },
946         {
947             {Uri_HOST_DNS,S_OK,FALSE},
948             {21,S_OK,FALSE},
949             {URL_SCHEME_FTP,S_OK,FALSE},
950             {URLZONE_INVALID,E_NOTIMPL,FALSE}
951         }
952     },
953     {   "ftp://test?:word@winehq.org/", 0, S_OK, FALSE,
954         {
955             {"ftp://test/?:word@winehq.org/",S_OK,FALSE},
956             {"test",S_OK,FALSE},
957             {"ftp://test/?:word@winehq.org/",S_OK,FALSE},
958             {"",S_FALSE,FALSE},
959             {"",S_FALSE,FALSE},
960             {"",S_FALSE,FALSE},
961             {"test",S_OK,FALSE},
962             {"",S_FALSE,FALSE},
963             {"/",S_OK,FALSE},
964             {"/?:word@winehq.org/",S_OK,FALSE},
965             {"?:word@winehq.org/",S_OK,FALSE},
966             {"ftp://test?:word@winehq.org/",S_OK,FALSE},
967             {"ftp",S_OK,FALSE},
968             {"",S_FALSE,FALSE},
969             {"",S_FALSE,FALSE}
970         },
971         {
972             {Uri_HOST_DNS,S_OK,FALSE},
973             {21,S_OK,FALSE},
974             {URL_SCHEME_FTP,S_OK,FALSE},
975             {URLZONE_INVALID,E_NOTIMPL,FALSE}
976         }
977     },
978     {   "ftp://test#:word@winehq.org/", 0, S_OK, FALSE,
979         {
980             {"ftp://test/#:word@winehq.org/",S_OK,FALSE},
981             {"test",S_OK,FALSE},
982             {"ftp://test/#:word@winehq.org/",S_OK,FALSE},
983             {"",S_FALSE,FALSE},
984             {"",S_FALSE,FALSE},
985             {"#:word@winehq.org/",S_OK,FALSE},
986             {"test",S_OK,FALSE},
987             {"",S_FALSE,FALSE},
988             {"/",S_OK,FALSE},
989             {"/",S_OK,FALSE},
990             {"",S_FALSE,FALSE},
991             {"ftp://test#:word@winehq.org/",S_OK,FALSE},
992             {"ftp",S_OK,FALSE},
993             {"",S_FALSE,FALSE},
994             {"",S_FALSE,FALSE}
995         },
996         {
997             {Uri_HOST_DNS,S_OK,FALSE},
998             {21,S_OK,FALSE},
999             {URL_SCHEME_FTP,S_OK,FALSE},
1000             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1001         }
1002     },
1003     /* Allowed to have a backslash in the userinfo since it's an unknown scheme. */
1004     {   "zip://test\\:word@winehq.org/", 0, S_OK, FALSE,
1005         {
1006             {"zip://test\\:word@winehq.org/",S_OK,FALSE},
1007             {"test\\:word@winehq.org",S_OK,FALSE},
1008             {"zip://test\\:word@winehq.org/",S_OK,FALSE},
1009             {"winehq.org",S_OK,FALSE},
1010             {"",S_FALSE,FALSE},
1011             {"",S_FALSE,FALSE},
1012             {"winehq.org",S_OK,FALSE},
1013             {"word",S_OK,FALSE},
1014             {"/",S_OK,FALSE},
1015             {"/",S_OK,FALSE},
1016             {"",S_FALSE,FALSE},
1017             {"zip://test\\:word@winehq.org/",S_OK,FALSE},
1018             {"zip",S_OK,FALSE},
1019             {"test\\:word",S_OK,FALSE},
1020             {"test\\",S_OK,FALSE}
1021         },
1022         {
1023             {Uri_HOST_DNS,S_OK,FALSE},
1024             {0,S_FALSE,FALSE},
1025             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1026             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1027         }
1028     },
1029     /* It normalizes IPv4 addresses correctly. */
1030     {   "http://127.000.000.100/", 0, S_OK, FALSE,
1031         {
1032             {"http://127.0.0.100/",S_OK,FALSE},
1033             {"127.0.0.100",S_OK,FALSE},
1034             {"http://127.0.0.100/",S_OK,FALSE},
1035             {"",S_FALSE,FALSE},
1036             {"",S_FALSE,FALSE},
1037             {"",S_FALSE,FALSE},
1038             {"127.0.0.100",S_OK,FALSE},
1039             {"",S_FALSE,FALSE},
1040             {"/",S_OK,FALSE},
1041             {"/",S_OK,FALSE},
1042             {"",S_FALSE,FALSE},
1043             {"http://127.000.000.100/",S_OK,FALSE},
1044             {"http",S_OK,FALSE},
1045             {"",S_FALSE,FALSE},
1046             {"",S_FALSE,FALSE}
1047         },
1048         {
1049             {Uri_HOST_IPV4,S_OK,FALSE},
1050             {80,S_OK,FALSE},
1051             {URL_SCHEME_HTTP,S_OK,FALSE},
1052             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1053         }
1054     },
1055     {   "http://127.0.0.1:8000", 0, S_OK, FALSE,
1056         {
1057             {"http://127.0.0.1:8000/",S_OK},
1058             {"127.0.0.1:8000",S_OK},
1059             {"http://127.0.0.1:8000/",S_OK},
1060             {"",S_FALSE},
1061             {"",S_FALSE},
1062             {"",S_FALSE},
1063             {"127.0.0.1",S_OK},
1064             {"",S_FALSE},
1065             {"/",S_OK},
1066             {"/",S_OK},
1067             {"",S_FALSE},
1068             {"http://127.0.0.1:8000",S_OK},
1069             {"http",S_OK},
1070             {"",S_FALSE},
1071             {"",S_FALSE}
1072         },
1073         {
1074             {Uri_HOST_IPV4,S_OK,FALSE},
1075             {8000,S_OK,FALSE},
1076             {URL_SCHEME_HTTP,S_OK,FALSE},
1077             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1078         }
1079     },
1080     /* Make sure it normalizes partial IPv4 addresses correctly. */
1081     {   "http://127.0/", 0, S_OK, FALSE,
1082         {
1083             {"http://127.0.0.0/",S_OK,FALSE},
1084             {"127.0.0.0",S_OK,FALSE},
1085             {"http://127.0.0.0/",S_OK,FALSE},
1086             {"",S_FALSE,FALSE},
1087             {"",S_FALSE,FALSE},
1088             {"",S_FALSE,FALSE},
1089             {"127.0.0.0",S_OK,FALSE},
1090             {"",S_FALSE,FALSE},
1091             {"/",S_OK,FALSE},
1092             {"/",S_OK,FALSE},
1093             {"",S_FALSE,FALSE},
1094             {"http://127.0/",S_OK,FALSE},
1095             {"http",S_OK,FALSE},
1096             {"",S_FALSE,FALSE},
1097             {"",S_FALSE,FALSE}
1098         },
1099         {
1100             {Uri_HOST_IPV4,S_OK,FALSE},
1101             {80,S_OK,FALSE},
1102             {URL_SCHEME_HTTP,S_OK,FALSE},
1103             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1104         }
1105     },
1106     /* Make sure it converts implicit IPv4's correctly. */
1107     {   "http://123456/", 0, S_OK, FALSE,
1108         {
1109             {"http://0.1.226.64/",S_OK,FALSE},
1110             {"0.1.226.64",S_OK,FALSE},
1111             {"http://0.1.226.64/",S_OK,FALSE},
1112             {"",S_FALSE,FALSE},
1113             {"",S_FALSE,FALSE},
1114             {"",S_FALSE,FALSE},
1115             {"0.1.226.64",S_OK,FALSE},
1116             {"",S_FALSE,FALSE},
1117             {"/",S_OK,FALSE},
1118             {"/",S_OK,FALSE},
1119             {"",S_FALSE,FALSE},
1120             {"http://123456/",S_OK,FALSE},
1121             {"http",S_OK,FALSE},
1122             {"",S_FALSE,FALSE},
1123             {"",S_FALSE,FALSE}
1124         },
1125         {
1126             {Uri_HOST_IPV4,S_OK,FALSE},
1127             {80,S_OK,FALSE},
1128             {URL_SCHEME_HTTP,S_OK,FALSE},
1129             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1130         }
1131     },
1132     /* UINT_MAX */
1133     {   "http://4294967295/", 0, S_OK, FALSE,
1134         {
1135             {"http://255.255.255.255/",S_OK,FALSE},
1136             {"255.255.255.255",S_OK,FALSE},
1137             {"http://255.255.255.255/",S_OK,FALSE},
1138             {"",S_FALSE,FALSE},
1139             {"",S_FALSE,FALSE},
1140             {"",S_FALSE,FALSE},
1141             {"255.255.255.255",S_OK,FALSE},
1142             {"",S_FALSE,FALSE},
1143             {"/",S_OK,FALSE},
1144             {"/",S_OK,FALSE},
1145             {"",S_FALSE,FALSE},
1146             {"http://4294967295/",S_OK,FALSE},
1147             {"http",S_OK,FALSE},
1148             {"",S_FALSE,FALSE},
1149             {"",S_FALSE,FALSE}
1150         },
1151         {
1152             {Uri_HOST_IPV4,S_OK,FALSE},
1153             {80,S_OK,FALSE},
1154             {URL_SCHEME_HTTP,S_OK,FALSE},
1155             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1156         }
1157     },
1158     /* UINT_MAX+1 */
1159     {   "http://4294967296/", 0, S_OK, FALSE,
1160         {
1161             {"http://4294967296/",S_OK,FALSE},
1162             {"4294967296",S_OK,FALSE},
1163             {"http://4294967296/",S_OK,FALSE},
1164             {"",S_FALSE,FALSE},
1165             {"",S_FALSE,FALSE},
1166             {"",S_FALSE,FALSE},
1167             {"4294967296",S_OK,FALSE},
1168             {"",S_FALSE,FALSE},
1169             {"/",S_OK,FALSE},
1170             {"/",S_OK,FALSE},
1171             {"",S_FALSE,FALSE},
1172             {"http://4294967296/",S_OK,FALSE},
1173             {"http",S_OK,FALSE},
1174             {"",S_FALSE,FALSE},
1175             {"",S_FALSE,FALSE}
1176         },
1177         {
1178             {Uri_HOST_DNS,S_OK,FALSE},
1179             {80,S_OK,FALSE},
1180             {URL_SCHEME_HTTP,S_OK,FALSE},
1181             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1182         }
1183     },
1184     /* Window's doesn't normalize IP address for unknown schemes. */
1185     {   "1234://4294967295/", 0, S_OK, FALSE,
1186         {
1187             {"1234://4294967295/",S_OK,FALSE},
1188             {"4294967295",S_OK,FALSE},
1189             {"1234://4294967295/",S_OK,FALSE},
1190             {"",S_FALSE,FALSE},
1191             {"",S_FALSE,FALSE},
1192             {"",S_FALSE,FALSE},
1193             {"4294967295",S_OK,FALSE},
1194             {"",S_FALSE,FALSE},
1195             {"/",S_OK,FALSE},
1196             {"/",S_OK,FALSE},
1197             {"",S_FALSE,FALSE},
1198             {"1234://4294967295/",S_OK,FALSE},
1199             {"1234",S_OK,FALSE},
1200             {"",S_FALSE,FALSE},
1201             {"",S_FALSE,FALSE}
1202         },
1203         {
1204             {Uri_HOST_IPV4,S_OK,FALSE},
1205             {0,S_FALSE,FALSE},
1206             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1207             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1208         }
1209     },
1210     /* Window's doesn't normalize IP address for unknown schemes. */
1211     {   "1234://127.001/", 0, S_OK, FALSE,
1212         {
1213             {"1234://127.001/",S_OK,FALSE},
1214             {"127.001",S_OK,FALSE},
1215             {"1234://127.001/",S_OK,FALSE},
1216             {"",S_FALSE,FALSE},
1217             {"",S_FALSE,FALSE},
1218             {"",S_FALSE,FALSE},
1219             {"127.001",S_OK,FALSE},
1220             {"",S_FALSE,FALSE},
1221             {"/",S_OK,FALSE},
1222             {"/",S_OK,FALSE},
1223             {"",S_FALSE,FALSE},
1224             {"1234://127.001/",S_OK,FALSE},
1225             {"1234",S_OK,FALSE},
1226             {"",S_FALSE,FALSE},
1227             {"",S_FALSE,FALSE}
1228         },
1229         {
1230             {Uri_HOST_IPV4,S_OK,FALSE},
1231             {0,S_FALSE,FALSE},
1232             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1233             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1234         }
1235     },
1236     {   "http://[FEDC:BA98::3210]", 0, S_OK, FALSE,
1237         {
1238             {"http://[fedc:ba98::3210]/",S_OK,FALSE},
1239             {"[fedc:ba98::3210]",S_OK,FALSE},
1240             {"http://[fedc:ba98::3210]/",S_OK,FALSE},
1241             {"",S_FALSE,FALSE},
1242             {"",S_FALSE,FALSE},
1243             {"",S_FALSE,FALSE},
1244             {"fedc:ba98::3210",S_OK,FALSE},
1245             {"",S_FALSE,FALSE},
1246             {"/",S_OK,FALSE},
1247             {"/",S_OK,FALSE},
1248             {"",S_FALSE,FALSE},
1249             {"http://[FEDC:BA98::3210]",S_OK,FALSE},
1250             {"http",S_OK,FALSE},
1251             {"",S_FALSE,FALSE},
1252             {"",S_FALSE,FALSE},
1253         },
1254         {
1255             {Uri_HOST_IPV6,S_OK,FALSE},
1256             {80,S_OK,FALSE},
1257             {URL_SCHEME_HTTP,S_OK,FALSE},
1258             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1259         }
1260     },
1261     {   "http://[::]", 0, S_OK, FALSE,
1262         {
1263             {"http://[::]/",S_OK,FALSE},
1264             {"[::]",S_OK,FALSE},
1265             {"http://[::]/",S_OK,FALSE},
1266             {"",S_FALSE,FALSE},
1267             {"",S_FALSE,FALSE},
1268             {"",S_FALSE,FALSE},
1269             {"::",S_OK,FALSE},
1270             {"",S_FALSE,FALSE},
1271             {"/",S_OK,FALSE},
1272             {"/",S_OK,FALSE},
1273             {"",S_FALSE,FALSE},
1274             {"http://[::]",S_OK,FALSE},
1275             {"http",S_OK,FALSE},
1276             {"",S_FALSE,FALSE},
1277             {"",S_FALSE,FALSE},
1278         },
1279         {
1280             {Uri_HOST_IPV6,S_OK,FALSE},
1281             {80,S_OK,FALSE},
1282             {URL_SCHEME_HTTP,S_OK,FALSE},
1283             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1284         }
1285     },
1286     {   "http://[FEDC:BA98::]", 0, S_OK, FALSE,
1287         {
1288             {"http://[fedc:ba98::]/",S_OK,FALSE},
1289             {"[fedc:ba98::]",S_OK,FALSE},
1290             {"http://[fedc:ba98::]/",S_OK,FALSE},
1291             {"",S_FALSE,FALSE},
1292             {"",S_FALSE,FALSE},
1293             {"",S_FALSE,FALSE},
1294             {"fedc:ba98::",S_OK,FALSE},
1295             {"",S_FALSE,FALSE},
1296             {"/",S_OK,FALSE},
1297             {"/",S_OK,FALSE},
1298             {"",S_FALSE,FALSE},
1299             {"http://[FEDC:BA98::]",S_OK,FALSE},
1300             {"http",S_OK,FALSE},
1301             {"",S_FALSE,FALSE},
1302             {"",S_FALSE,FALSE},
1303         },
1304         {
1305             {Uri_HOST_IPV6,S_OK,FALSE},
1306             {80,S_OK,FALSE},
1307             {URL_SCHEME_HTTP,S_OK,FALSE},
1308             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1309         }
1310     },
1311     /* Valid even with 2 byte elision because it doesn't appear the beginning or end. */
1312     {   "http://[1::3:4:5:6:7:8]", 0, S_OK, FALSE,
1313         {
1314             {"http://[1:0:3:4:5:6:7:8]/",S_OK,FALSE},
1315             {"[1:0:3:4:5:6:7:8]",S_OK,FALSE},
1316             {"http://[1:0:3:4:5:6:7:8]/",S_OK,FALSE},
1317             {"",S_FALSE,FALSE},
1318             {"",S_FALSE,FALSE},
1319             {"",S_FALSE,FALSE},
1320             {"1:0:3:4:5:6:7:8",S_OK,FALSE},
1321             {"",S_FALSE,FALSE},
1322             {"/",S_OK,FALSE},
1323             {"/",S_OK,FALSE},
1324             {"",S_FALSE,FALSE},
1325             {"http://[1::3:4:5:6:7:8]",S_OK,FALSE},
1326             {"http",S_OK,FALSE},
1327             {"",S_FALSE,FALSE},
1328             {"",S_FALSE,FALSE},
1329         },
1330         {
1331             {Uri_HOST_IPV6,S_OK,FALSE},
1332             {80,S_OK,FALSE},
1333             {URL_SCHEME_HTTP,S_OK,FALSE},
1334             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1335         }
1336     },
1337     {   "http://[v2.34]/", 0, S_OK, FALSE,
1338         {
1339             {"http://[v2.34]/",S_OK,FALSE},
1340             {"[v2.34]",S_OK,FALSE},
1341             {"http://[v2.34]/",S_OK,FALSE},
1342             {"",S_FALSE,FALSE},
1343             {"",S_FALSE,FALSE},
1344             {"",S_FALSE,FALSE},
1345             {"[v2.34]",S_OK,FALSE},
1346             {"",S_FALSE,FALSE},
1347             {"/",S_OK,FALSE},
1348             {"/",S_OK,FALSE},
1349             {"",S_FALSE,FALSE},
1350             {"http://[v2.34]/",S_OK,FALSE},
1351             {"http",S_OK,FALSE},
1352             {"",S_FALSE,FALSE},
1353             {"",S_FALSE,FALSE}
1354         },
1355         {
1356             {Uri_HOST_UNKNOWN,S_OK,FALSE},
1357             {80,S_OK,FALSE},
1358             {URL_SCHEME_HTTP,S_OK,FALSE},
1359             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1360         }
1361     },
1362     /* Windows ignores ':' if they appear after a '[' on a non-IPLiteral host. */
1363     {   "http://[xyz:12345.com/test", 0, S_OK, FALSE,
1364         {
1365             {"http://[xyz:12345.com/test",S_OK,FALSE},
1366             {"[xyz:12345.com",S_OK,FALSE},
1367             {"http://[xyz:12345.com/test",S_OK,FALSE},
1368             {"[xyz:12345.com",S_OK,FALSE},
1369             {"",S_FALSE,FALSE},
1370             {"",S_FALSE,FALSE},
1371             {"[xyz:12345.com",S_OK,FALSE},
1372             {"",S_FALSE,FALSE},
1373             {"/test",S_OK,FALSE},
1374             {"/test",S_OK,FALSE},
1375             {"",S_FALSE,FALSE},
1376             {"http://[xyz:12345.com/test",S_OK,FALSE},
1377             {"http",S_OK,FALSE},
1378             {"",S_FALSE,FALSE},
1379             {"",S_FALSE,FALSE}
1380         },
1381         {
1382             {Uri_HOST_DNS,S_OK,FALSE},
1383             {80,S_OK,FALSE},
1384             {URL_SCHEME_HTTP,S_OK,FALSE},
1385             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1386         }
1387     },
1388     /* Valid URI since the '[' and ']' don't appear at the beginning and end
1389      * of the host name (respectively).
1390      */
1391     {   "ftp://www.[works].com/", 0, S_OK, FALSE,
1392         {
1393             {"ftp://www.[works].com/",S_OK,FALSE},
1394             {"www.[works].com",S_OK,FALSE},
1395             {"ftp://www.[works].com/",S_OK,FALSE},
1396             {"[works].com",S_OK,FALSE},
1397             {"",S_FALSE,FALSE},
1398             {"",S_FALSE,FALSE},
1399             {"www.[works].com",S_OK,FALSE},
1400             {"",S_FALSE,FALSE},
1401             {"/",S_OK,FALSE},
1402             {"/",S_OK,FALSE},
1403             {"",S_FALSE,FALSE},
1404             {"ftp://www.[works].com/",S_OK,FALSE},
1405             {"ftp",S_OK,FALSE},
1406             {"",S_FALSE,FALSE},
1407             {"",S_FALSE,FALSE}
1408         },
1409         {
1410             {Uri_HOST_DNS,S_OK,FALSE},
1411             {21,S_OK,FALSE},
1412             {URL_SCHEME_FTP,S_OK,FALSE},
1413             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1414         }
1415     },
1416     /* Considers ':' a delimiter since it appears after the ']'. */
1417     {   "http://www.google.com]:12345/", 0, S_OK, FALSE,
1418         {
1419             {"http://www.google.com]:12345/",S_OK,FALSE},
1420             {"www.google.com]:12345",S_OK,FALSE},
1421             {"http://www.google.com]:12345/",S_OK,FALSE},
1422             {"google.com]",S_OK,FALSE},
1423             {"",S_FALSE,FALSE},
1424             {"",S_FALSE,FALSE},
1425             {"www.google.com]",S_OK,FALSE},
1426             {"",S_FALSE,FALSE},
1427             {"/",S_OK,FALSE},
1428             {"/",S_OK,FALSE},
1429             {"",S_FALSE,FALSE},
1430             {"http://www.google.com]:12345/",S_OK,FALSE},
1431             {"http",S_OK,FALSE},
1432             {"",S_FALSE,FALSE},
1433             {"",S_FALSE,FALSE}
1434         },
1435         {
1436             {Uri_HOST_DNS,S_OK,FALSE},
1437             {12345,S_OK,FALSE},
1438             {URL_SCHEME_HTTP,S_OK,FALSE},
1439             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1440         }
1441     },
1442     /* Unknown scheme types can have invalid % encoded data in the hostname. */
1443     {   "zip://w%XXw%GEw.google.com/", 0, S_OK, FALSE,
1444         {
1445             {"zip://w%XXw%GEw.google.com/",S_OK,FALSE},
1446             {"w%XXw%GEw.google.com",S_OK,FALSE},
1447             {"zip://w%XXw%GEw.google.com/",S_OK,FALSE},
1448             {"google.com",S_OK,FALSE},
1449             {"",S_FALSE,FALSE},
1450             {"",S_FALSE,FALSE},
1451             {"w%XXw%GEw.google.com",S_OK,FALSE},
1452             {"",S_FALSE,FALSE},
1453             {"/",S_OK,FALSE},
1454             {"/",S_OK,FALSE},
1455             {"",S_FALSE,FALSE},
1456             {"zip://w%XXw%GEw.google.com/",S_OK,FALSE},
1457             {"zip",S_OK,FALSE},
1458             {"",S_FALSE,FALSE},
1459             {"",S_FALSE,FALSE}
1460         },
1461         {
1462             {Uri_HOST_DNS,S_OK,FALSE},
1463             {0,S_FALSE,FALSE},
1464             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1465             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1466         }
1467     },
1468     /* Unknown scheme types hostname doesn't get lower cased. */
1469     {   "zip://GOOGLE.com/", 0, S_OK, FALSE,
1470         {
1471             {"zip://GOOGLE.com/",S_OK,FALSE},
1472             {"GOOGLE.com",S_OK,FALSE},
1473             {"zip://GOOGLE.com/",S_OK,FALSE},
1474             {"GOOGLE.com",S_OK,FALSE},
1475             {"",S_FALSE,FALSE},
1476             {"",S_FALSE,FALSE},
1477             {"GOOGLE.com",S_OK,FALSE},
1478             {"",S_FALSE,FALSE},
1479             {"/",S_OK,FALSE},
1480             {"/",S_OK,FALSE},
1481             {"",S_FALSE,FALSE},
1482             {"zip://GOOGLE.com/",S_OK,FALSE},
1483             {"zip",S_OK,FALSE},
1484             {"",S_FALSE,FALSE},
1485             {"",S_FALSE,FALSE}
1486         },
1487         {
1488             {Uri_HOST_DNS,S_OK,FALSE},
1489             {0,S_FALSE,FALSE},
1490             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1491             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1492         }
1493     },
1494     /* Hostname gets lower-cased for known scheme types. */
1495     {   "http://WWW.GOOGLE.com/", 0, S_OK, FALSE,
1496         {
1497             {"http://www.google.com/",S_OK,FALSE},
1498             {"www.google.com",S_OK,FALSE},
1499             {"http://www.google.com/",S_OK,FALSE},
1500             {"google.com",S_OK,FALSE},
1501             {"",S_FALSE,FALSE},
1502             {"",S_FALSE,FALSE},
1503             {"www.google.com",S_OK,FALSE},
1504             {"",S_FALSE,FALSE},
1505             {"/",S_OK,FALSE},
1506             {"/",S_OK,FALSE},
1507             {"",S_FALSE,FALSE},
1508             {"http://WWW.GOOGLE.com/",S_OK,FALSE},
1509             {"http",S_OK,FALSE},
1510             {"",S_FALSE,FALSE},
1511             {"",S_FALSE,FALSE}
1512         },
1513         {
1514             {Uri_HOST_DNS,S_OK,FALSE},
1515             {80,S_OK,FALSE},
1516             {URL_SCHEME_HTTP,S_OK,FALSE},
1517             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1518         }
1519     },
1520     /* Characters that get % encoded in the hostname also have their percent
1521      * encoded forms lower cased.
1522      */
1523     {   "http://www.%7Cgoogle|.com/", 0, S_OK, FALSE,
1524         {
1525             {"http://www.%7cgoogle%7c.com/",S_OK,FALSE},
1526             {"www.%7cgoogle%7c.com",S_OK,FALSE},
1527             {"http://www.%7cgoogle%7c.com/",S_OK,FALSE},
1528             {"%7cgoogle%7c.com",S_OK,FALSE},
1529             {"",S_FALSE,FALSE},
1530             {"",S_FALSE,FALSE},
1531             {"www.%7cgoogle%7c.com",S_OK,FALSE},
1532             {"",S_FALSE,FALSE},
1533             {"/",S_OK,FALSE},
1534             {"/",S_OK,FALSE},
1535             {"",S_FALSE,FALSE},
1536             {"http://www.%7Cgoogle|.com/",S_OK,FALSE},
1537             {"http",S_OK,FALSE},
1538             {"",S_FALSE,FALSE},
1539             {"",S_FALSE,FALSE}
1540         },
1541         {
1542             {Uri_HOST_DNS,S_OK,FALSE},
1543             {80,S_OK,FALSE},
1544             {URL_SCHEME_HTTP,S_OK,FALSE},
1545             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1546         }
1547     },
1548     /* IPv4 addresses attached to IPv6 can be included in elisions. */
1549     {   "http://[1:2:3:4:5:6:0.0.0.0]", 0, S_OK, FALSE,
1550         {
1551             {"http://[1:2:3:4:5:6::]/",S_OK,FALSE},
1552             {"[1:2:3:4:5:6::]",S_OK,FALSE},
1553             {"http://[1:2:3:4:5:6::]/",S_OK,FALSE},
1554             {"",S_FALSE,FALSE},
1555             {"",S_FALSE,FALSE},
1556             {"",S_FALSE,FALSE},
1557             {"1:2:3:4:5:6::",S_OK,FALSE},
1558             {"",S_FALSE,FALSE},
1559             {"/",S_OK,FALSE},
1560             {"/",S_OK,FALSE},
1561             {"",S_FALSE,FALSE},
1562             {"http://[1:2:3:4:5:6:0.0.0.0]",S_OK,FALSE},
1563             {"http",S_OK,FALSE},
1564             {"",S_FALSE,FALSE},
1565             {"",S_FALSE,FALSE},
1566         },
1567         {
1568             {Uri_HOST_IPV6,S_OK,FALSE},
1569             {80,S_OK,FALSE},
1570             {URL_SCHEME_HTTP,S_OK,FALSE},
1571             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1572         }
1573     },
1574     /* IPv4 addresses get normalized. */
1575     {   "http://[::001.002.003.000]", 0, S_OK, FALSE,
1576         {
1577             {"http://[::1.2.3.0]/",S_OK,FALSE},
1578             {"[::1.2.3.0]",S_OK,FALSE},
1579             {"http://[::1.2.3.0]/",S_OK,FALSE},
1580             {"",S_FALSE,FALSE},
1581             {"",S_FALSE,FALSE},
1582             {"",S_FALSE,FALSE},
1583             {"::1.2.3.0",S_OK,FALSE},
1584             {"",S_FALSE,FALSE},
1585             {"/",S_OK,FALSE},
1586             {"/",S_OK,FALSE},
1587             {"",S_FALSE,FALSE},
1588             {"http://[::001.002.003.000]",S_OK,FALSE},
1589             {"http",S_OK,FALSE},
1590             {"",S_FALSE,FALSE},
1591             {"",S_FALSE,FALSE},
1592         },
1593         {
1594             {Uri_HOST_IPV6,S_OK,FALSE},
1595             {80,S_OK,FALSE},
1596             {URL_SCHEME_HTTP,S_OK,FALSE},
1597             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1598         }
1599     },
1600     /* Windows doesn't do anything to IPv6's in unknown schemes. */
1601     {   "zip://[0001:0:000:0004:0005:0006:001.002.003.000]", 0, S_OK, FALSE,
1602         {
1603             {"zip://[0001:0:000:0004:0005:0006:001.002.003.000]/",S_OK,FALSE},
1604             {"[0001:0:000:0004:0005:0006:001.002.003.000]",S_OK,FALSE},
1605             {"zip://[0001:0:000:0004:0005:0006:001.002.003.000]/",S_OK,FALSE},
1606             {"",S_FALSE,FALSE},
1607             {"",S_FALSE,FALSE},
1608             {"",S_FALSE,FALSE},
1609             {"0001:0:000:0004:0005:0006:001.002.003.000",S_OK,FALSE},
1610             {"",S_FALSE,FALSE},
1611             {"/",S_OK,FALSE},
1612             {"/",S_OK,FALSE},
1613             {"",S_FALSE,FALSE},
1614             {"zip://[0001:0:000:0004:0005:0006:001.002.003.000]",S_OK,FALSE},
1615             {"zip",S_OK,FALSE},
1616             {"",S_FALSE,FALSE},
1617             {"",S_FALSE,FALSE},
1618         },
1619         {
1620             {Uri_HOST_IPV6,S_OK,FALSE},
1621             {0,S_FALSE,FALSE},
1622             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1623             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1624         }
1625     },
1626     /* IPv4 address is converted into 2 h16 components. */
1627     {   "http://[ffff::192.222.111.32]", 0, S_OK, FALSE,
1628         {
1629             {"http://[ffff::c0de:6f20]/",S_OK,FALSE},
1630             {"[ffff::c0de:6f20]",S_OK,FALSE},
1631             {"http://[ffff::c0de:6f20]/",S_OK,FALSE},
1632             {"",S_FALSE,FALSE},
1633             {"",S_FALSE,FALSE},
1634             {"",S_FALSE,FALSE},
1635             {"ffff::c0de:6f20",S_OK,FALSE},
1636             {"",S_FALSE,FALSE},
1637             {"/",S_OK,FALSE},
1638             {"/",S_OK,FALSE},
1639             {"",S_FALSE,FALSE},
1640             {"http://[ffff::192.222.111.32]",S_OK,FALSE},
1641             {"http",S_OK,FALSE},
1642             {"",S_FALSE,FALSE},
1643             {"",S_FALSE,FALSE},
1644         },
1645         {
1646             {Uri_HOST_IPV6,S_OK,FALSE},
1647             {80,S_OK,FALSE},
1648             {URL_SCHEME_HTTP,S_OK,FALSE},
1649             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1650         }
1651     },
1652     /* Max value for a port. */
1653     {   "http://google.com:65535", 0, S_OK, FALSE,
1654         {
1655             {"http://google.com:65535/",S_OK,FALSE},
1656             {"google.com:65535",S_OK,FALSE},
1657             {"http://google.com:65535/",S_OK,FALSE},
1658             {"google.com",S_OK,FALSE},
1659             {"",S_FALSE,FALSE},
1660             {"",S_FALSE,FALSE},
1661             {"google.com",S_OK,FALSE},
1662             {"",S_FALSE,FALSE},
1663             {"/",S_OK,FALSE},
1664             {"/",S_OK,FALSE},
1665             {"",S_FALSE,FALSE},
1666             {"http://google.com:65535",S_OK,FALSE},
1667             {"http",S_OK,FALSE},
1668             {"",S_FALSE,FALSE},
1669             {"",S_FALSE,FALSE}
1670         },
1671         {
1672             {Uri_HOST_DNS,S_OK,FALSE},
1673             {65535,S_OK,FALSE},
1674             {URL_SCHEME_HTTP,S_OK,FALSE},
1675             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1676         }
1677     },
1678     {   "zip://google.com:65536", 0, S_OK, FALSE,
1679         {
1680             {"zip://google.com:65536/",S_OK,FALSE},
1681             {"google.com:65536",S_OK,FALSE},
1682             {"zip://google.com:65536/",S_OK,FALSE},
1683             {"google.com:65536",S_OK,FALSE},
1684             {"",S_FALSE,FALSE},
1685             {"",S_FALSE,FALSE},
1686             {"google.com:65536",S_OK,FALSE},
1687             {"",S_FALSE,FALSE},
1688             {"/",S_OK,FALSE},
1689             {"/",S_OK,FALSE},
1690             {"",S_FALSE,FALSE},
1691             {"zip://google.com:65536",S_OK,FALSE},
1692             {"zip",S_OK,FALSE},
1693             {"",S_FALSE,FALSE},
1694             {"",S_FALSE,FALSE}
1695         },
1696         {
1697             {Uri_HOST_DNS,S_OK,FALSE},
1698             {0,S_FALSE,FALSE},
1699             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1700             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1701         }
1702     },
1703     {   "zip://google.com:65536:25", 0, S_OK, FALSE,
1704         {
1705             {"zip://google.com:65536:25/",S_OK,FALSE},
1706             {"google.com:65536:25",S_OK,FALSE},
1707             {"zip://google.com:65536:25/",S_OK,FALSE},
1708             {"google.com:65536:25",S_OK,FALSE},
1709             {"",S_FALSE,FALSE},
1710             {"",S_FALSE,FALSE},
1711             {"google.com:65536:25",S_OK,FALSE},
1712             {"",S_FALSE,FALSE},
1713             {"/",S_OK,FALSE},
1714             {"/",S_OK,FALSE},
1715             {"",S_FALSE,FALSE},
1716             {"zip://google.com:65536:25",S_OK,FALSE},
1717             {"zip",S_OK,FALSE},
1718             {"",S_FALSE,FALSE},
1719             {"",S_FALSE,FALSE}
1720         },
1721         {
1722             {Uri_HOST_DNS,S_OK,FALSE},
1723             {0,S_FALSE,FALSE},
1724             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1725             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1726         }
1727     },
1728     {   "zip://[::ffff]:abcd", 0, S_OK, FALSE,
1729         {
1730             {"zip://[::ffff]:abcd/",S_OK,FALSE},
1731             {"[::ffff]:abcd",S_OK,FALSE},
1732             {"zip://[::ffff]:abcd/",S_OK,FALSE},
1733             {"",S_FALSE,FALSE},
1734             {"",S_FALSE,FALSE},
1735             {"",S_FALSE,FALSE},
1736             {"[::ffff]:abcd",S_OK,FALSE},
1737             {"",S_FALSE,FALSE},
1738             {"/",S_OK,FALSE},
1739             {"/",S_OK,FALSE},
1740             {"",S_FALSE,FALSE},
1741             {"zip://[::ffff]:abcd",S_OK,FALSE},
1742             {"zip",S_OK,FALSE},
1743             {"",S_FALSE,FALSE},
1744             {"",S_FALSE,FALSE}
1745         },
1746         {
1747             {Uri_HOST_DNS,S_OK,FALSE},
1748             {0,S_FALSE,FALSE},
1749             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1750             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1751         }
1752     },
1753     {   "zip://127.0.0.1:abcd", 0, S_OK, FALSE,
1754         {
1755             {"zip://127.0.0.1:abcd/",S_OK,FALSE},
1756             {"127.0.0.1:abcd",S_OK,FALSE},
1757             {"zip://127.0.0.1:abcd/",S_OK,FALSE},
1758             {"0.1:abcd",S_OK,FALSE},
1759             {"",S_FALSE,FALSE},
1760             {"",S_FALSE,FALSE},
1761             {"127.0.0.1:abcd",S_OK,FALSE},
1762             {"",S_FALSE,FALSE},
1763             {"/",S_OK,FALSE},
1764             {"/",S_OK,FALSE},
1765             {"",S_FALSE,FALSE},
1766             {"zip://127.0.0.1:abcd",S_OK,FALSE},
1767             {"zip",S_OK,FALSE},
1768             {"",S_FALSE,FALSE},
1769             {"",S_FALSE,FALSE}
1770         },
1771         {
1772             {Uri_HOST_DNS,S_OK,FALSE},
1773             {0,S_FALSE,FALSE},
1774             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1775             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1776         }
1777     },
1778     /* Port is just copied over. */
1779     {   "http://google.com:00035", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
1780         {
1781             {"http://google.com:00035",S_OK,FALSE},
1782             {"google.com:00035",S_OK,FALSE},
1783             {"http://google.com:00035",S_OK,FALSE,"http://google.com:35"},
1784             {"google.com",S_OK,FALSE},
1785             {"",S_FALSE,FALSE},
1786             {"",S_FALSE,FALSE},
1787             {"google.com",S_OK,FALSE},
1788             {"",S_FALSE,FALSE},
1789             {"",S_FALSE,FALSE},
1790             {"",S_FALSE,FALSE},
1791             {"",S_FALSE,FALSE},
1792             {"http://google.com:00035",S_OK,FALSE},
1793             {"http",S_OK,FALSE},
1794             {"",S_FALSE,FALSE},
1795             {"",S_FALSE,FALSE}
1796         },
1797         {
1798             {Uri_HOST_DNS,S_OK,FALSE},
1799             {35,S_OK,FALSE},
1800             {URL_SCHEME_HTTP,S_OK,FALSE},
1801             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1802         }
1803     },
1804     /* Default port is copied over. */
1805     {   "http://google.com:80", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
1806         {
1807             {"http://google.com:80",S_OK,FALSE},
1808             {"google.com:80",S_OK,FALSE},
1809             {"http://google.com:80",S_OK,FALSE},
1810             {"google.com",S_OK,FALSE},
1811             {"",S_FALSE,FALSE},
1812             {"",S_FALSE,FALSE},
1813             {"google.com",S_OK,FALSE},
1814             {"",S_FALSE,FALSE},
1815             {"",S_FALSE,FALSE},
1816             {"",S_FALSE,FALSE},
1817             {"",S_FALSE,FALSE},
1818             {"http://google.com:80",S_OK,FALSE},
1819             {"http",S_OK,FALSE},
1820             {"",S_FALSE,FALSE},
1821             {"",S_FALSE,FALSE}
1822         },
1823         {
1824             {Uri_HOST_DNS,S_OK,FALSE},
1825             {80,S_OK,FALSE},
1826             {URL_SCHEME_HTTP,S_OK,FALSE},
1827             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1828         }
1829     },
1830     {   "http://google.com.uk", 0, S_OK, FALSE,
1831         {
1832             {"http://google.com.uk/",S_OK,FALSE},
1833             {"google.com.uk",S_OK,FALSE},
1834             {"http://google.com.uk/",S_OK,FALSE},
1835             {"google.com.uk",S_OK,FALSE},
1836             {"",S_FALSE,FALSE},
1837             {"",S_FALSE,FALSE},
1838             {"google.com.uk",S_OK,FALSE},
1839             {"",S_FALSE,FALSE},
1840             {"/",S_OK,FALSE},
1841             {"/",S_OK,FALSE},
1842             {"",S_FALSE,FALSE},
1843             {"http://google.com.uk",S_OK,FALSE},
1844             {"http",S_OK,FALSE},
1845             {"",S_FALSE,FALSE},
1846             {"",S_FALSE,FALSE}
1847         },
1848         {
1849             {Uri_HOST_DNS,S_OK,FALSE},
1850             {80,S_OK,FALSE},
1851             {URL_SCHEME_HTTP,S_OK,FALSE},
1852             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1853         }
1854     },
1855     {   "http://google.com.com", 0, S_OK, FALSE,
1856         {
1857             {"http://google.com.com/",S_OK,FALSE},
1858             {"google.com.com",S_OK,FALSE},
1859             {"http://google.com.com/",S_OK,FALSE},
1860             {"com.com",S_OK,FALSE},
1861             {"",S_FALSE,FALSE},
1862             {"",S_FALSE,FALSE},
1863             {"google.com.com",S_OK,FALSE},
1864             {"",S_FALSE,FALSE},
1865             {"/",S_OK,FALSE},
1866             {"/",S_OK,FALSE},
1867             {"",S_FALSE,FALSE},
1868             {"http://google.com.com",S_OK,FALSE},
1869             {"http",S_OK,FALSE},
1870             {"",S_FALSE,FALSE},
1871             {"",S_FALSE,FALSE}
1872         },
1873         {
1874             {Uri_HOST_DNS,S_OK,FALSE},
1875             {80,S_OK,FALSE},
1876             {URL_SCHEME_HTTP,S_OK,FALSE},
1877             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1878         }
1879     },
1880     {   "http://google.uk.1", 0, S_OK, FALSE,
1881         {
1882             {"http://google.uk.1/",S_OK,FALSE},
1883             {"google.uk.1",S_OK,FALSE},
1884             {"http://google.uk.1/",S_OK,FALSE},
1885             {"google.uk.1",S_OK,FALSE},
1886             {"",S_FALSE,FALSE},
1887             {"",S_FALSE,FALSE},
1888             {"google.uk.1",S_OK,FALSE},
1889             {"",S_FALSE,FALSE},
1890             {"/",S_OK,FALSE},
1891             {"/",S_OK,FALSE},
1892             {"",S_FALSE,FALSE},
1893             {"http://google.uk.1",S_OK,FALSE},
1894             {"http",S_OK,FALSE},
1895             {"",S_FALSE,FALSE},
1896             {"",S_FALSE,FALSE}
1897         },
1898         {
1899             {Uri_HOST_DNS,S_OK,FALSE},
1900             {80,S_OK,FALSE},
1901             {URL_SCHEME_HTTP,S_OK,FALSE},
1902             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1903         }
1904     },
1905     /* Since foo isn't a recognized 3 character TLD its considered the domain name. */
1906     {   "http://google.foo.uk", 0, S_OK, FALSE,
1907         {
1908             {"http://google.foo.uk/",S_OK,FALSE},
1909             {"google.foo.uk",S_OK,FALSE},
1910             {"http://google.foo.uk/",S_OK,FALSE},
1911             {"foo.uk",S_OK,FALSE},
1912             {"",S_FALSE,FALSE},
1913             {"",S_FALSE,FALSE},
1914             {"google.foo.uk",S_OK,FALSE},
1915             {"",S_FALSE,FALSE},
1916             {"/",S_OK,FALSE},
1917             {"/",S_OK,FALSE},
1918             {"",S_FALSE,FALSE},
1919             {"http://google.foo.uk",S_OK,FALSE},
1920             {"http",S_OK,FALSE},
1921             {"",S_FALSE,FALSE},
1922             {"",S_FALSE,FALSE}
1923         },
1924         {
1925             {Uri_HOST_DNS,S_OK,FALSE},
1926             {80,S_OK,FALSE},
1927             {URL_SCHEME_HTTP,S_OK,FALSE},
1928             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1929         }
1930     },
1931     {   "http://.com", 0, S_OK, FALSE,
1932         {
1933             {"http://.com/",S_OK,FALSE},
1934             {".com",S_OK,FALSE},
1935             {"http://.com/",S_OK,FALSE},
1936             {".com",S_OK,FALSE},
1937             {"",S_FALSE,FALSE},
1938             {"",S_FALSE,FALSE},
1939             {".com",S_OK,FALSE},
1940             {"",S_FALSE,FALSE},
1941             {"/",S_OK,FALSE},
1942             {"/",S_OK,FALSE},
1943             {"",S_FALSE,FALSE},
1944             {"http://.com",S_OK,FALSE},
1945             {"http",S_OK,FALSE},
1946             {"",S_FALSE,FALSE},
1947             {"",S_FALSE,FALSE}
1948         },
1949         {
1950             {Uri_HOST_DNS,S_OK,FALSE},
1951             {80,S_OK,FALSE},
1952             {URL_SCHEME_HTTP,S_OK,FALSE},
1953             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1954         }
1955     },
1956     {   "http://.uk", 0, S_OK, FALSE,
1957         {
1958             {"http://.uk/",S_OK,FALSE},
1959             {".uk",S_OK,FALSE},
1960             {"http://.uk/",S_OK,FALSE},
1961             {"",S_FALSE,FALSE},
1962             {"",S_FALSE,FALSE},
1963             {"",S_FALSE,FALSE},
1964             {".uk",S_OK,FALSE},
1965             {"",S_FALSE,FALSE},
1966             {"/",S_OK,FALSE},
1967             {"/",S_OK,FALSE},
1968             {"",S_FALSE,FALSE},
1969             {"http://.uk",S_OK,FALSE},
1970             {"http",S_OK,FALSE},
1971             {"",S_FALSE,FALSE},
1972             {"",S_FALSE,FALSE}
1973         },
1974         {
1975             {Uri_HOST_DNS,S_OK,FALSE},
1976             {80,S_OK,FALSE},
1977             {URL_SCHEME_HTTP,S_OK,FALSE},
1978             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1979         }
1980     },
1981     {   "http://www.co.google.com.[]", 0, S_OK, FALSE,
1982         {
1983             {"http://www.co.google.com.[]/",S_OK,FALSE},
1984             {"www.co.google.com.[]",S_OK,FALSE},
1985             {"http://www.co.google.com.[]/",S_OK,FALSE},
1986             {"google.com.[]",S_OK,FALSE},
1987             {"",S_FALSE,FALSE},
1988             {"",S_FALSE,FALSE},
1989             {"www.co.google.com.[]",S_OK,FALSE},
1990             {"",S_FALSE,FALSE},
1991             {"/",S_OK,FALSE},
1992             {"/",S_OK,FALSE},
1993             {"",S_FALSE,FALSE},
1994             {"http://www.co.google.com.[]",S_OK,FALSE},
1995             {"http",S_OK,FALSE},
1996             {"",S_FALSE,FALSE},
1997             {"",S_FALSE,FALSE}
1998         },
1999         {
2000             {Uri_HOST_DNS,S_OK,FALSE},
2001             {80,S_OK,FALSE},
2002             {URL_SCHEME_HTTP,S_OK,FALSE},
2003             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2004         }
2005     },
2006     {   "http://co.uk", 0, S_OK, FALSE,
2007         {
2008             {"http://co.uk/",S_OK,FALSE},
2009             {"co.uk",S_OK,FALSE},
2010             {"http://co.uk/",S_OK,FALSE},
2011             {"",S_FALSE,FALSE},
2012             {"",S_FALSE,FALSE},
2013             {"",S_FALSE,FALSE},
2014             {"co.uk",S_OK,FALSE},
2015             {"",S_FALSE,FALSE},
2016             {"/",S_OK,FALSE},
2017             {"/",S_OK,FALSE},
2018             {"",S_FALSE,FALSE},
2019             {"http://co.uk",S_OK,FALSE},
2020             {"http",S_OK,FALSE},
2021             {"",S_FALSE,FALSE},
2022             {"",S_FALSE,FALSE}
2023         },
2024         {
2025             {Uri_HOST_DNS,S_OK,FALSE},
2026             {80,S_OK,FALSE},
2027             {URL_SCHEME_HTTP,S_OK,FALSE},
2028             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2029         }
2030     },
2031     {   "http://www.co.google.us.test", 0, S_OK, FALSE,
2032         {
2033             {"http://www.co.google.us.test/",S_OK,FALSE},
2034             {"www.co.google.us.test",S_OK,FALSE},
2035             {"http://www.co.google.us.test/",S_OK,FALSE},
2036             {"us.test",S_OK,FALSE},
2037             {"",S_FALSE,FALSE},
2038             {"",S_FALSE,FALSE},
2039             {"www.co.google.us.test",S_OK,FALSE},
2040             {"",S_FALSE,FALSE},
2041             {"/",S_OK,FALSE},
2042             {"/",S_OK,FALSE},
2043             {"",S_FALSE,FALSE},
2044             {"http://www.co.google.us.test",S_OK,FALSE},
2045             {"http",S_OK,FALSE},
2046             {"",S_FALSE,FALSE},
2047             {"",S_FALSE,FALSE}
2048         },
2049         {
2050             {Uri_HOST_DNS,S_OK,FALSE},
2051             {80,S_OK,FALSE},
2052             {URL_SCHEME_HTTP,S_OK,FALSE},
2053             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2054         }
2055     },
2056     {   "http://gov.uk", 0, S_OK, FALSE,
2057         {
2058             {"http://gov.uk/",S_OK,FALSE},
2059             {"gov.uk",S_OK,FALSE},
2060             {"http://gov.uk/",S_OK,FALSE},
2061             {"",S_FALSE,FALSE},
2062             {"",S_FALSE,FALSE},
2063             {"",S_FALSE,FALSE},
2064             {"gov.uk",S_OK,FALSE},
2065             {"",S_FALSE,FALSE},
2066             {"/",S_OK,FALSE},
2067             {"/",S_OK,FALSE},
2068             {"",S_FALSE,FALSE},
2069             {"http://gov.uk",S_OK,FALSE},
2070             {"http",S_OK,FALSE},
2071             {"",S_FALSE,FALSE},
2072             {"",S_FALSE,FALSE}
2073         },
2074         {
2075             {Uri_HOST_DNS,S_OK,FALSE},
2076             {80,S_OK,FALSE},
2077             {URL_SCHEME_HTTP,S_OK,FALSE},
2078             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2079         }
2080     },
2081     {   "zip://www.google.com\\test", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
2082         {
2083             {"zip://www.google.com\\test",S_OK,FALSE},
2084             {"www.google.com\\test",S_OK,FALSE},
2085             {"zip://www.google.com\\test",S_OK,FALSE},
2086             {"google.com\\test",S_OK,FALSE},
2087             {"",S_FALSE,FALSE},
2088             {"",S_FALSE,FALSE},
2089             {"www.google.com\\test",S_OK,FALSE},
2090             {"",S_FALSE,FALSE},
2091             {"",S_FALSE,FALSE},
2092             {"",S_FALSE,FALSE},
2093             {"",S_FALSE,FALSE},
2094             {"zip://www.google.com\\test",S_OK,FALSE},
2095             {"zip",S_OK,FALSE},
2096             {"",S_FALSE,FALSE},
2097             {"",S_FALSE,FALSE}
2098         },
2099         {
2100             {Uri_HOST_DNS,S_OK,FALSE},
2101             {0,S_FALSE,FALSE},
2102             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2103             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2104         }
2105     },
2106     {   "urn:excepts:bad:%XY:encoded", 0, S_OK, FALSE,
2107         {
2108             {"urn:excepts:bad:%XY:encoded",S_OK,FALSE},
2109             {"",S_FALSE,FALSE},
2110             {"urn:excepts:bad:%XY:encoded",S_OK,FALSE},
2111             {"",S_FALSE,FALSE},
2112             {"",S_FALSE,FALSE},
2113             {"",S_FALSE,FALSE},
2114             {"",S_FALSE,FALSE},
2115             {"",S_FALSE,FALSE},
2116             {"excepts:bad:%XY:encoded",S_OK,FALSE},
2117             {"excepts:bad:%XY:encoded",S_OK,FALSE},
2118             {"",S_FALSE,FALSE},
2119             {"urn:excepts:bad:%XY:encoded",S_OK,FALSE},
2120             {"urn",S_OK,FALSE},
2121             {"",S_FALSE,FALSE},
2122             {"",S_FALSE,FALSE}
2123         },
2124         {
2125             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2126             {0,S_FALSE,FALSE},
2127             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2128             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2129         }
2130     },
2131     /* Since the original URI doesn't contain an extra '/' before the path no % encoded values
2132      * are decoded and all '%' are encoded.
2133      */
2134     {   "file://C:/te%3Es%2Et/tes%t.mp3", 0, S_OK, FALSE,
2135         {
2136             {"file:///C:/te%253Es%252Et/tes%25t.mp3",S_OK,FALSE},
2137             {"",S_FALSE,FALSE},
2138             {"file:///C:/te%253Es%252Et/tes%25t.mp3",S_OK,FALSE},
2139             {"",S_FALSE,FALSE},
2140             {".mp3",S_OK,FALSE},
2141             {"",S_FALSE,FALSE},
2142             {"",S_FALSE,FALSE},
2143             {"",S_FALSE,FALSE},
2144             {"/C:/te%253Es%252Et/tes%25t.mp3",S_OK,FALSE},
2145             {"/C:/te%253Es%252Et/tes%25t.mp3",S_OK,FALSE},
2146             {"",S_FALSE,FALSE},
2147             {"file://C:/te%3Es%2Et/tes%t.mp3",S_OK,FALSE},
2148             {"file",S_OK,FALSE},
2149             {"",S_FALSE,FALSE},
2150             {"",S_FALSE,FALSE}
2151         },
2152         {
2153             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2154             {0,S_FALSE,FALSE},
2155             {URL_SCHEME_FILE,S_OK,FALSE},
2156             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2157         }
2158     },
2159     /* Since there's a '/' in front of the drive letter, any percent encoded, non-forbidden character
2160      * is decoded and only %'s in front of invalid hex digits are encoded.
2161      */
2162     {   "file:///C:/te%3Es%2Et/t%23es%t.mp3", 0, S_OK, FALSE,
2163         {
2164             {"file:///C:/te%3Es.t/t#es%25t.mp3",S_OK,FALSE},
2165             {"",S_FALSE,FALSE},
2166             {"file:///C:/te%3Es.t/t#es%25t.mp3",S_OK,FALSE},
2167             {"",S_FALSE,FALSE},
2168             {".mp3",S_OK,FALSE},
2169             {"",S_FALSE,FALSE},
2170             {"",S_FALSE,FALSE},
2171             {"",S_FALSE,FALSE},
2172             {"/C:/te%3Es.t/t#es%25t.mp3",S_OK,FALSE},
2173             {"/C:/te%3Es.t/t#es%25t.mp3",S_OK,FALSE},
2174             {"",S_FALSE,FALSE},
2175             {"file:///C:/te%3Es%2Et/t%23es%t.mp3",S_OK,FALSE},
2176             {"file",S_OK,FALSE},
2177             {"",S_FALSE,FALSE},
2178             {"",S_FALSE,FALSE}
2179         },
2180         {
2181             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2182             {0,S_FALSE,FALSE},
2183             {URL_SCHEME_FILE,S_OK,FALSE},
2184             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2185         }
2186     },
2187     /* Only unreserved percent encoded characters are decoded for known schemes that aren't file. */
2188     {   "http://[::001.002.003.000]/%3F%23%2E%54/test", 0, S_OK, FALSE,
2189         {
2190             {"http://[::1.2.3.0]/%3F%23.T/test",S_OK,FALSE},
2191             {"[::1.2.3.0]",S_OK,FALSE},
2192             {"http://[::1.2.3.0]/%3F%23.T/test",S_OK,FALSE},
2193             {"",S_FALSE,FALSE},
2194             {"",S_FALSE,FALSE},
2195             {"",S_FALSE,FALSE},
2196             {"::1.2.3.0",S_OK,FALSE},
2197             {"",S_FALSE,FALSE},
2198             {"/%3F%23.T/test",S_OK,FALSE},
2199             {"/%3F%23.T/test",S_OK,FALSE},
2200             {"",S_FALSE,FALSE},
2201             {"http://[::001.002.003.000]/%3F%23%2E%54/test",S_OK,FALSE},
2202             {"http",S_OK,FALSE},
2203             {"",S_FALSE,FALSE},
2204             {"",S_FALSE,FALSE},
2205         },
2206         {
2207             {Uri_HOST_IPV6,S_OK,FALSE},
2208             {80,S_OK,FALSE},
2209             {URL_SCHEME_HTTP,S_OK,FALSE},
2210             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2211         }
2212     },
2213     /* Forbidden characters are always encoded for file URIs. */
2214     {   "file:///C:/\"test\"/test.mp3", Uri_CREATE_NO_ENCODE_FORBIDDEN_CHARACTERS, S_OK, FALSE,
2215         {
2216             {"file:///C:/%22test%22/test.mp3",S_OK,FALSE},
2217             {"",S_FALSE,FALSE},
2218             {"file:///C:/%22test%22/test.mp3",S_OK,FALSE},
2219             {"",S_FALSE,FALSE},
2220             {".mp3",S_OK,FALSE},
2221             {"",S_FALSE,FALSE},
2222             {"",S_FALSE,FALSE},
2223             {"",S_FALSE,FALSE},
2224             {"/C:/%22test%22/test.mp3",S_OK,FALSE},
2225             {"/C:/%22test%22/test.mp3",S_OK,FALSE},
2226             {"",S_FALSE,FALSE},
2227             {"file:///C:/\"test\"/test.mp3",S_OK,FALSE},
2228             {"file",S_OK,FALSE},
2229             {"",S_FALSE,FALSE},
2230             {"",S_FALSE,FALSE}
2231         },
2232         {
2233             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2234             {0,S_FALSE,FALSE},
2235             {URL_SCHEME_FILE,S_OK,FALSE},
2236             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2237         }
2238     },
2239     /* Forbidden characters are never encoded for unknown scheme types. */
2240     {   "1234://4294967295/<|>\" test<|>", 0, S_OK, FALSE,
2241         {
2242             {"1234://4294967295/<|>\" test<|>",S_OK,FALSE},
2243             {"4294967295",S_OK,FALSE},
2244             {"1234://4294967295/<|>\" test<|>",S_OK,FALSE},
2245             {"",S_FALSE,FALSE},
2246             {"",S_FALSE,FALSE},
2247             {"",S_FALSE,FALSE},
2248             {"4294967295",S_OK,FALSE},
2249             {"",S_FALSE,FALSE},
2250             {"/<|>\" test<|>",S_OK,FALSE},
2251             {"/<|>\" test<|>",S_OK,FALSE},
2252             {"",S_FALSE,FALSE},
2253             {"1234://4294967295/<|>\" test<|>",S_OK,FALSE},
2254             {"1234",S_OK,FALSE},
2255             {"",S_FALSE,FALSE},
2256             {"",S_FALSE,FALSE}
2257         },
2258         {
2259             {Uri_HOST_IPV4,S_OK,FALSE},
2260             {0,S_FALSE,FALSE},
2261             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2262             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2263         }
2264     },
2265     /* Make sure forbidden characters are percent encoded. */
2266     {   "http://gov.uk/<|> test<|>", 0, S_OK, FALSE,
2267         {
2268             {"http://gov.uk/%3C%7C%3E%20test%3C%7C%3E",S_OK,FALSE},
2269             {"gov.uk",S_OK,FALSE},
2270             {"http://gov.uk/%3C%7C%3E%20test%3C%7C%3E",S_OK,FALSE},
2271             {"",S_FALSE,FALSE},
2272             {"",S_FALSE,FALSE},
2273             {"",S_FALSE,FALSE},
2274             {"gov.uk",S_OK,FALSE},
2275             {"",S_FALSE,FALSE},
2276             {"/%3C%7C%3E%20test%3C%7C%3E",S_OK,FALSE},
2277             {"/%3C%7C%3E%20test%3C%7C%3E",S_OK,FALSE},
2278             {"",S_FALSE,FALSE},
2279             {"http://gov.uk/<|> test<|>",S_OK,FALSE},
2280             {"http",S_OK,FALSE},
2281             {"",S_FALSE,FALSE},
2282             {"",S_FALSE,FALSE}
2283         },
2284         {
2285             {Uri_HOST_DNS,S_OK,FALSE},
2286             {80,S_OK,FALSE},
2287             {URL_SCHEME_HTTP,S_OK,FALSE},
2288             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2289         }
2290     },
2291     {   "http://gov.uk/test/../test2/././../test3/.././././", 0, S_OK, FALSE,
2292         {
2293             {"http://gov.uk/",S_OK,FALSE},
2294             {"gov.uk",S_OK,FALSE},
2295             {"http://gov.uk/",S_OK,FALSE},
2296             {"",S_FALSE,FALSE},
2297             {"",S_FALSE,FALSE},
2298             {"",S_FALSE,FALSE},
2299             {"gov.uk",S_OK,FALSE},
2300             {"",S_FALSE,FALSE},
2301             {"/",S_OK,FALSE},
2302             {"/",S_OK,FALSE},
2303             {"",S_FALSE,FALSE},
2304             {"http://gov.uk/test/../test2/././../test3/.././././",S_OK,FALSE},
2305             {"http",S_OK,FALSE},
2306             {"",S_FALSE,FALSE},
2307             {"",S_FALSE,FALSE}
2308         },
2309         {
2310             {Uri_HOST_DNS,S_OK,FALSE},
2311             {80,S_OK,FALSE},
2312             {URL_SCHEME_HTTP,S_OK,FALSE},
2313             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2314         }
2315     },
2316     {   "http://gov.uk/test/test2/../../..", 0, S_OK, FALSE,
2317         {
2318             {"http://gov.uk/",S_OK,FALSE},
2319             {"gov.uk",S_OK,FALSE},
2320             {"http://gov.uk/",S_OK,FALSE},
2321             {"",S_FALSE,FALSE},
2322             {"",S_FALSE,FALSE},
2323             {"",S_FALSE,FALSE},
2324             {"gov.uk",S_OK,FALSE},
2325             {"",S_FALSE,FALSE},
2326             {"/",S_OK,FALSE},
2327             {"/",S_OK,FALSE},
2328             {"",S_FALSE,FALSE},
2329             {"http://gov.uk/test/test2/../../..",S_OK,FALSE},
2330             {"http",S_OK,FALSE},
2331             {"",S_FALSE,FALSE},
2332             {"",S_FALSE,FALSE}
2333         },
2334         {
2335             {Uri_HOST_DNS,S_OK,FALSE},
2336             {80,S_OK,FALSE},
2337             {URL_SCHEME_HTTP,S_OK,FALSE},
2338             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2339         }
2340     },
2341     {   "http://gov.uk/test/test2/../../.", 0, S_OK, FALSE,
2342         {
2343             {"http://gov.uk/",S_OK,FALSE},
2344             {"gov.uk",S_OK,FALSE},
2345             {"http://gov.uk/",S_OK,FALSE},
2346             {"",S_FALSE,FALSE},
2347             {"",S_FALSE,FALSE},
2348             {"",S_FALSE,FALSE},
2349             {"gov.uk",S_OK,FALSE},
2350             {"",S_FALSE,FALSE},
2351             {"/",S_OK,FALSE},
2352             {"/",S_OK,FALSE},
2353             {"",S_FALSE,FALSE},
2354             {"http://gov.uk/test/test2/../../.",S_OK,FALSE},
2355             {"http",S_OK,FALSE},
2356             {"",S_FALSE,FALSE},
2357             {"",S_FALSE,FALSE}
2358         },
2359         {
2360             {Uri_HOST_DNS,S_OK,FALSE},
2361             {80,S_OK,FALSE},
2362             {URL_SCHEME_HTTP,S_OK,FALSE},
2363             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2364         }
2365     },
2366     {   "file://c:\\tests\\../tests\\./.\\..\\foo%20bar.mp3", 0, S_OK, FALSE,
2367         {
2368             {"file:///c:/foo%2520bar.mp3",S_OK,FALSE},
2369             {"",S_FALSE,FALSE},
2370             {"file:///c:/foo%2520bar.mp3",S_OK,FALSE},
2371             {"",S_FALSE,FALSE},
2372             {".mp3",S_OK,FALSE},
2373             {"",S_FALSE,FALSE},
2374             {"",S_FALSE,FALSE},
2375             {"",S_FALSE,FALSE},
2376             {"/c:/foo%2520bar.mp3",S_OK,FALSE},
2377             {"/c:/foo%2520bar.mp3",S_OK,FALSE},
2378             {"",S_FALSE,FALSE},
2379             {"file://c:\\tests\\../tests\\./.\\..\\foo%20bar.mp3",S_OK,FALSE},
2380             {"file",S_OK,FALSE},
2381             {"",S_FALSE,FALSE},
2382             {"",S_FALSE,FALSE}
2383         },
2384         {
2385             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2386             {0,S_FALSE,FALSE},
2387             {URL_SCHEME_FILE,S_OK,FALSE},
2388             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2389         }
2390     },
2391     /* Dot removal happens for unknown scheme types. */
2392     {   "zip://gov.uk/test/test2/../../.", 0, S_OK, FALSE,
2393         {
2394             {"zip://gov.uk/",S_OK,FALSE},
2395             {"gov.uk",S_OK,FALSE},
2396             {"zip://gov.uk/",S_OK,FALSE},
2397             {"",S_FALSE,FALSE},
2398             {"",S_FALSE,FALSE},
2399             {"",S_FALSE,FALSE},
2400             {"gov.uk",S_OK,FALSE},
2401             {"",S_FALSE,FALSE},
2402             {"/",S_OK,FALSE},
2403             {"/",S_OK,FALSE},
2404             {"",S_FALSE,FALSE},
2405             {"zip://gov.uk/test/test2/../../.",S_OK,FALSE},
2406             {"zip",S_OK,FALSE},
2407             {"",S_FALSE,FALSE},
2408             {"",S_FALSE,FALSE}
2409         },
2410         {
2411             {Uri_HOST_DNS,S_OK,FALSE},
2412             {0,S_FALSE,FALSE},
2413             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2414             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2415         }
2416     },
2417     /* Dot removal doesn't happen if NO_CANONICALIZE is set. */
2418     {   "http://gov.uk/test/test2/../../.", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
2419         {
2420             {"http://gov.uk/test/test2/../../.",S_OK,FALSE},
2421             {"gov.uk",S_OK,FALSE},
2422             {"http://gov.uk/test/test2/../../.",S_OK,FALSE},
2423             {"",S_FALSE,FALSE},
2424             {".",S_OK,FALSE},
2425             {"",S_FALSE,FALSE},
2426             {"gov.uk",S_OK,FALSE},
2427             {"",S_FALSE,FALSE},
2428             {"/test/test2/../../.",S_OK,FALSE},
2429             {"/test/test2/../../.",S_OK,FALSE},
2430             {"",S_FALSE,FALSE},
2431             {"http://gov.uk/test/test2/../../.",S_OK,FALSE},
2432             {"http",S_OK,FALSE},
2433             {"",S_FALSE,FALSE},
2434             {"",S_FALSE,FALSE}
2435         },
2436         {
2437             {Uri_HOST_DNS,S_OK,FALSE},
2438             {80,S_OK,FALSE},
2439             {URL_SCHEME_HTTP,S_OK,FALSE},
2440             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2441         }
2442     },
2443     /* Dot removal doesn't happen for wildcard scheme types. */
2444     {   "*:gov.uk/test/test2/../../.", 0, S_OK, FALSE,
2445         {
2446             {"*:gov.uk/test/test2/../../.",S_OK,FALSE},
2447             {"gov.uk",S_OK,FALSE},
2448             {"*:gov.uk/test/test2/../../.",S_OK,FALSE},
2449             {"",S_FALSE,FALSE},
2450             {".",S_OK,FALSE},
2451             {"",S_FALSE,FALSE},
2452             {"gov.uk",S_OK,FALSE},
2453             {"",S_FALSE,FALSE},
2454             {"/test/test2/../../.",S_OK,FALSE},
2455             {"/test/test2/../../.",S_OK,FALSE},
2456             {"",S_FALSE,FALSE},
2457             {"*:gov.uk/test/test2/../../.",S_OK,FALSE},
2458             {"*",S_OK,FALSE},
2459             {"",S_FALSE,FALSE},
2460             {"",S_FALSE,FALSE}
2461         },
2462         {
2463             {Uri_HOST_DNS,S_OK,FALSE},
2464             {0,S_FALSE,FALSE},
2465             {URL_SCHEME_WILDCARD,S_OK,FALSE},
2466             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2467         }
2468     },
2469     /* Forbidden characters are encoded for opaque known scheme types. */
2470     {   "mailto:\"acco<|>unt@example.com\"", 0, S_OK, FALSE,
2471         {
2472             {"mailto:%22acco%3C%7C%3Eunt@example.com%22",S_OK,FALSE},
2473             {"",S_FALSE,FALSE},
2474             {"mailto:%22acco%3C%7C%3Eunt@example.com%22",S_OK,FALSE},
2475             {"",S_FALSE,FALSE},
2476             {".com%22",S_OK,FALSE},
2477             {"",S_FALSE,FALSE},
2478             {"",S_FALSE,FALSE},
2479             {"",S_FALSE,FALSE},
2480             {"%22acco%3C%7C%3Eunt@example.com%22",S_OK,FALSE},
2481             {"%22acco%3C%7C%3Eunt@example.com%22",S_OK,FALSE},
2482             {"",S_FALSE,FALSE},
2483             {"mailto:\"acco<|>unt@example.com\"",S_OK,FALSE},
2484             {"mailto",S_OK,FALSE},
2485             {"",S_FALSE,FALSE},
2486             {"",S_FALSE,FALSE}
2487         },
2488         {
2489             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2490             {0,S_FALSE,FALSE},
2491             {URL_SCHEME_MAILTO,S_OK,FALSE},
2492             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2493         }
2494     },
2495     {   "news:test.tes<|>t.com", 0, S_OK, FALSE,
2496         {
2497             {"news:test.tes%3C%7C%3Et.com",S_OK,FALSE},
2498             {"",S_FALSE,FALSE},
2499             {"news:test.tes%3C%7C%3Et.com",S_OK,FALSE},
2500             {"",S_FALSE,FALSE},
2501             {".com",S_OK,FALSE},
2502             {"",S_FALSE,FALSE},
2503             {"",S_FALSE,FALSE},
2504             {"",S_FALSE,FALSE},
2505             {"test.tes%3C%7C%3Et.com",S_OK,FALSE},
2506             {"test.tes%3C%7C%3Et.com",S_OK,FALSE},
2507             {"",S_FALSE,FALSE},
2508             {"news:test.tes<|>t.com",S_OK,FALSE},
2509             {"news",S_OK,FALSE},
2510             {"",S_FALSE,FALSE},
2511             {"",S_FALSE,FALSE}
2512         },
2513         {
2514             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2515             {0,S_FALSE,FALSE},
2516             {URL_SCHEME_NEWS,S_OK,FALSE},
2517             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2518         }
2519     },
2520     /* Don't encode forbidden characters. */
2521     {   "news:test.tes<|>t.com", Uri_CREATE_NO_ENCODE_FORBIDDEN_CHARACTERS, S_OK, FALSE,
2522         {
2523             {"news:test.tes<|>t.com",S_OK,FALSE},
2524             {"",S_FALSE,FALSE},
2525             {"news:test.tes<|>t.com",S_OK,FALSE},
2526             {"",S_FALSE,FALSE},
2527             {".com",S_OK,FALSE},
2528             {"",S_FALSE,FALSE},
2529             {"",S_FALSE,FALSE},
2530             {"",S_FALSE,FALSE},
2531             {"test.tes<|>t.com",S_OK,FALSE},
2532             {"test.tes<|>t.com",S_OK,FALSE},
2533             {"",S_FALSE,FALSE},
2534             {"news:test.tes<|>t.com",S_OK,FALSE},
2535             {"news",S_OK,FALSE},
2536             {"",S_FALSE,FALSE},
2537             {"",S_FALSE,FALSE}
2538         },
2539         {
2540             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2541             {0,S_FALSE,FALSE},
2542             {URL_SCHEME_NEWS,S_OK,FALSE},
2543             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2544         }
2545     },
2546     /* Forbidden characters aren't encoded for unknown, opaque URIs. */
2547     {   "urn:test.tes<|>t.com", 0, S_OK, FALSE,
2548         {
2549             {"urn:test.tes<|>t.com",S_OK,FALSE},
2550             {"",S_FALSE,FALSE},
2551             {"urn:test.tes<|>t.com",S_OK,FALSE},
2552             {"",S_FALSE,FALSE},
2553             {".com",S_OK,FALSE},
2554             {"",S_FALSE,FALSE},
2555             {"",S_FALSE,FALSE},
2556             {"",S_FALSE,FALSE},
2557             {"test.tes<|>t.com",S_OK,FALSE},
2558             {"test.tes<|>t.com",S_OK,FALSE},
2559             {"",S_FALSE,FALSE},
2560             {"urn:test.tes<|>t.com",S_OK,FALSE},
2561             {"urn",S_OK,FALSE},
2562             {"",S_FALSE,FALSE},
2563             {"",S_FALSE,FALSE}
2564         },
2565         {
2566             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2567             {0,S_FALSE,FALSE},
2568             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2569             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2570         }
2571     },
2572     /* Percent encoded unreserved characters are decoded for known opaque URIs. */
2573     {   "news:test.%74%65%73%74.com", 0, S_OK, FALSE,
2574         {
2575             {"news:test.test.com",S_OK,FALSE},
2576             {"",S_FALSE,FALSE},
2577             {"news:test.test.com",S_OK,FALSE},
2578             {"",S_FALSE,FALSE},
2579             {".com",S_OK,FALSE},
2580             {"",S_FALSE,FALSE},
2581             {"",S_FALSE,FALSE},
2582             {"",S_FALSE,FALSE},
2583             {"test.test.com",S_OK,FALSE},
2584             {"test.test.com",S_OK,FALSE},
2585             {"",S_FALSE,FALSE},
2586             {"news:test.%74%65%73%74.com",S_OK,FALSE},
2587             {"news",S_OK,FALSE},
2588             {"",S_FALSE,FALSE},
2589             {"",S_FALSE,FALSE}
2590         },
2591         {
2592             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2593             {0,S_FALSE,FALSE},
2594             {URL_SCHEME_NEWS,S_OK,FALSE},
2595             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2596         }
2597     },
2598     /* Percent encoded characters are still decoded for known scheme types. */
2599     {   "news:test.%74%65%73%74.com", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
2600         {
2601             {"news:test.test.com",S_OK,FALSE},
2602             {"",S_FALSE,FALSE},
2603             {"news:test.test.com",S_OK,FALSE},
2604             {"",S_FALSE,FALSE},
2605             {".com",S_OK,FALSE},
2606             {"",S_FALSE,FALSE},
2607             {"",S_FALSE,FALSE},
2608             {"",S_FALSE,FALSE},
2609             {"test.test.com",S_OK,FALSE},
2610             {"test.test.com",S_OK,FALSE},
2611             {"",S_FALSE,FALSE},
2612             {"news:test.%74%65%73%74.com",S_OK,FALSE},
2613             {"news",S_OK,FALSE},
2614             {"",S_FALSE,FALSE},
2615             {"",S_FALSE,FALSE}
2616         },
2617         {
2618             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2619             {0,S_FALSE,FALSE},
2620             {URL_SCHEME_NEWS,S_OK,FALSE},
2621             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2622         }
2623     },
2624     /* Percent encoded characters aren't decoded for unknown scheme types. */
2625     {   "urn:test.%74%65%73%74.com", 0, S_OK, FALSE,
2626         {
2627             {"urn:test.%74%65%73%74.com",S_OK,FALSE},
2628             {"",S_FALSE,FALSE},
2629             {"urn:test.%74%65%73%74.com",S_OK,FALSE},
2630             {"",S_FALSE,FALSE},
2631             {".com",S_OK,FALSE},
2632             {"",S_FALSE,FALSE},
2633             {"",S_FALSE,FALSE},
2634             {"",S_FALSE,FALSE},
2635             {"test.%74%65%73%74.com",S_OK,FALSE},
2636             {"test.%74%65%73%74.com",S_OK,FALSE},
2637             {"",S_FALSE,FALSE},
2638             {"urn:test.%74%65%73%74.com",S_OK,FALSE},
2639             {"urn",S_OK,FALSE},
2640             {"",S_FALSE,FALSE},
2641             {"",S_FALSE,FALSE}
2642         },
2643         {
2644             {Uri_HOST_UNKNOWN,S_OK,FALSE},
2645             {0,S_FALSE,FALSE},
2646             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2647             {URLZONE_INVALID,E_NOTIMPL,FALSE}
2648         }
2649     },
2650     /* Unknown scheme types can have invalid % encoded data in query string. */
2651     {   "zip://www.winehq.org/tests/..?query=%xx&return=y", 0, S_OK, FALSE,
2652         {
2653             {"zip://www.winehq.org/?query=%xx&return=y",S_OK,FALSE},
2654             {"www.winehq.org",S_OK,FALSE},
2655             {"zip://www.winehq.org/?query=%xx&return=y",S_OK,FALSE},
2656             {"winehq.org",S_OK,FALSE},
2657             {"",S_FALSE,FALSE},
2658             {"",S_FALSE,FALSE},
2659             {"www.winehq.org",S_OK,FALSE},
2660             {"",S_FALSE,FALSE},
2661             {"/",S_OK,FALSE},
2662             {"/?query=%xx&return=y",S_OK,FALSE},
2663             {"?query=%xx&return=y",S_OK,FALSE},
2664             {"zip://www.winehq.org/tests/..?query=%xx&return=y",S_OK,FALSE},
2665             {"zip",S_OK,FALSE},
2666             {"",S_FALSE,FALSE},
2667             {"",S_FALSE,FALSE}
2668         },
2669         {
2670             {Uri_HOST_DNS,S_OK,FALSE},
2671             {0,S_FALSE,FALSE},
2672             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2673             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2674         }
2675     },
2676     /* Known scheme types can have invalid % encoded data with the right flags. */
2677     {   "http://www.winehq.org/tests/..?query=%xx&return=y", Uri_CREATE_NO_DECODE_EXTRA_INFO, S_OK, FALSE,
2678         {
2679             {"http://www.winehq.org/?query=%xx&return=y",S_OK,FALSE},
2680             {"www.winehq.org",S_OK,FALSE},
2681             {"http://www.winehq.org/?query=%xx&return=y",S_OK,FALSE},
2682             {"winehq.org",S_OK,FALSE},
2683             {"",S_FALSE,FALSE},
2684             {"",S_FALSE,FALSE},
2685             {"www.winehq.org",S_OK,FALSE},
2686             {"",S_FALSE,FALSE},
2687             {"/",S_OK,FALSE},
2688             {"/?query=%xx&return=y",S_OK,FALSE},
2689             {"?query=%xx&return=y",S_OK,FALSE},
2690             {"http://www.winehq.org/tests/..?query=%xx&return=y",S_OK,FALSE},
2691             {"http",S_OK,FALSE},
2692             {"",S_FALSE,FALSE},
2693             {"",S_FALSE,FALSE}
2694         },
2695         {
2696             {Uri_HOST_DNS,S_OK,FALSE},
2697             {80,S_OK,FALSE},
2698             {URL_SCHEME_HTTP,S_OK,FALSE},
2699             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2700         }
2701     },
2702     /* Forbidden characters in query aren't percent encoded for known scheme types with this flag. */
2703     {   "http://www.winehq.org/tests/..?query=<|>&return=y", Uri_CREATE_NO_DECODE_EXTRA_INFO, S_OK, FALSE,
2704         {
2705             {"http://www.winehq.org/?query=<|>&return=y",S_OK,FALSE},
2706             {"www.winehq.org",S_OK,FALSE},
2707             {"http://www.winehq.org/?query=<|>&return=y",S_OK,FALSE},
2708             {"winehq.org",S_OK,FALSE},
2709             {"",S_FALSE,FALSE},
2710             {"",S_FALSE,FALSE},
2711             {"www.winehq.org",S_OK,FALSE},
2712             {"",S_FALSE,FALSE},
2713             {"/",S_OK,FALSE},
2714             {"/?query=<|>&return=y",S_OK,FALSE},
2715             {"?query=<|>&return=y",S_OK,FALSE},
2716             {"http://www.winehq.org/tests/..?query=<|>&return=y",S_OK,FALSE},
2717             {"http",S_OK,FALSE},
2718             {"",S_FALSE,FALSE},
2719             {"",S_FALSE,FALSE}
2720         },
2721         {
2722             {Uri_HOST_DNS,S_OK,FALSE},
2723             {80,S_OK,FALSE},
2724             {URL_SCHEME_HTTP,S_OK,FALSE},
2725             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2726         }
2727     },
2728     /* Forbidden characters in query aren't percent encoded for known scheme types with this flag. */
2729     {   "http://www.winehq.org/tests/..?query=<|>&return=y", Uri_CREATE_NO_ENCODE_FORBIDDEN_CHARACTERS, S_OK, FALSE,
2730         {
2731             {"http://www.winehq.org/?query=<|>&return=y",S_OK,FALSE},
2732             {"www.winehq.org",S_OK,FALSE},
2733             {"http://www.winehq.org/?query=<|>&return=y",S_OK,FALSE},
2734             {"winehq.org",S_OK,FALSE},
2735             {"",S_FALSE,FALSE},
2736             {"",S_FALSE,FALSE},
2737             {"www.winehq.org",S_OK,FALSE},
2738             {"",S_FALSE,FALSE},
2739             {"/",S_OK,FALSE},
2740             {"/?query=<|>&return=y",S_OK,FALSE},
2741             {"?query=<|>&return=y",S_OK,FALSE},
2742             {"http://www.winehq.org/tests/..?query=<|>&return=y",S_OK,FALSE},
2743             {"http",S_OK,FALSE},
2744             {"",S_FALSE,FALSE},
2745             {"",S_FALSE,FALSE}
2746         },
2747         {
2748             {Uri_HOST_DNS,S_OK,FALSE},
2749             {80,S_OK,FALSE},
2750             {URL_SCHEME_HTTP,S_OK,FALSE},
2751             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2752         }
2753     },
2754     /* Forbidden characters are encoded for known scheme types. */
2755     {   "http://www.winehq.org/tests/..?query=<|>&return=y", 0, S_OK, FALSE,
2756         {
2757             {"http://www.winehq.org/?query=%3C%7C%3E&return=y",S_OK,FALSE},
2758             {"www.winehq.org",S_OK,FALSE},
2759             {"http://www.winehq.org/?query=%3C%7C%3E&return=y",S_OK,FALSE},
2760             {"winehq.org",S_OK,FALSE},
2761             {"",S_FALSE,FALSE},
2762             {"",S_FALSE,FALSE},
2763             {"www.winehq.org",S_OK,FALSE},
2764             {"",S_FALSE,FALSE},
2765             {"/",S_OK,FALSE},
2766             {"/?query=%3C%7C%3E&return=y",S_OK,FALSE},
2767             {"?query=%3C%7C%3E&return=y",S_OK,FALSE},
2768             {"http://www.winehq.org/tests/..?query=<|>&return=y",S_OK,FALSE},
2769             {"http",S_OK,FALSE},
2770             {"",S_FALSE,FALSE},
2771             {"",S_FALSE,FALSE}
2772         },
2773         {
2774             {Uri_HOST_DNS,S_OK,FALSE},
2775             {80,S_OK,FALSE},
2776             {URL_SCHEME_HTTP,S_OK,FALSE},
2777             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2778         }
2779     },
2780     /* Forbidden characters are not encoded for unknown scheme types. */
2781     {   "zip://www.winehq.org/tests/..?query=<|>&return=y", 0, S_OK, FALSE,
2782         {
2783             {"zip://www.winehq.org/?query=<|>&return=y",S_OK,FALSE},
2784             {"www.winehq.org",S_OK,FALSE},
2785             {"zip://www.winehq.org/?query=<|>&return=y",S_OK,FALSE},
2786             {"winehq.org",S_OK,FALSE},
2787             {"",S_FALSE,FALSE},
2788             {"",S_FALSE,FALSE},
2789             {"www.winehq.org",S_OK,FALSE},
2790             {"",S_FALSE,FALSE},
2791             {"/",S_OK,FALSE},
2792             {"/?query=<|>&return=y",S_OK,FALSE},
2793             {"?query=<|>&return=y",S_OK,FALSE},
2794             {"zip://www.winehq.org/tests/..?query=<|>&return=y",S_OK,FALSE},
2795             {"zip",S_OK,FALSE},
2796             {"",S_FALSE,FALSE},
2797             {"",S_FALSE,FALSE}
2798         },
2799         {
2800             {Uri_HOST_DNS,S_OK,FALSE},
2801             {0,S_FALSE,FALSE},
2802             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2803             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2804         }
2805     },
2806     /* Percent encoded, unreserved characters are decoded for known scheme types. */
2807     {   "http://www.winehq.org/tests/..?query=%30%31&return=y", 0, S_OK, FALSE,
2808         {
2809             {"http://www.winehq.org/?query=01&return=y",S_OK,FALSE},
2810             {"www.winehq.org",S_OK,FALSE},
2811             {"http://www.winehq.org/?query=01&return=y",S_OK,FALSE},
2812             {"winehq.org",S_OK,FALSE},
2813             {"",S_FALSE,FALSE},
2814             {"",S_FALSE,FALSE},
2815             {"www.winehq.org",S_OK,FALSE},
2816             {"",S_FALSE,FALSE},
2817             {"/",S_OK,FALSE},
2818             {"/?query=01&return=y",S_OK,FALSE},
2819             {"?query=01&return=y",S_OK,FALSE},
2820             {"http://www.winehq.org/tests/..?query=%30%31&return=y",S_OK,FALSE},
2821             {"http",S_OK,FALSE},
2822             {"",S_FALSE,FALSE},
2823             {"",S_FALSE,FALSE}
2824         },
2825         {
2826             {Uri_HOST_DNS,S_OK,FALSE},
2827             {80,S_OK,FALSE},
2828             {URL_SCHEME_HTTP,S_OK,FALSE},
2829             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2830         }
2831     },
2832     /* Percent encoded, unreserved characters aren't decoded for unknown scheme types. */
2833     {   "zip://www.winehq.org/tests/..?query=%30%31&return=y", 0, S_OK, FALSE,
2834         {
2835             {"zip://www.winehq.org/?query=%30%31&return=y",S_OK,FALSE},
2836             {"www.winehq.org",S_OK,FALSE},
2837             {"zip://www.winehq.org/?query=%30%31&return=y",S_OK,FALSE},
2838             {"winehq.org",S_OK,FALSE},
2839             {"",S_FALSE,FALSE},
2840             {"",S_FALSE,FALSE},
2841             {"www.winehq.org",S_OK,FALSE},
2842             {"",S_FALSE,FALSE},
2843             {"/",S_OK,FALSE},
2844             {"/?query=%30%31&return=y",S_OK,FALSE},
2845             {"?query=%30%31&return=y",S_OK,FALSE},
2846             {"zip://www.winehq.org/tests/..?query=%30%31&return=y",S_OK,FALSE},
2847             {"zip",S_OK,FALSE},
2848             {"",S_FALSE,FALSE},
2849             {"",S_FALSE,FALSE}
2850         },
2851         {
2852             {Uri_HOST_DNS,S_OK,FALSE},
2853             {0,S_FALSE,FALSE},
2854             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2855             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2856         }
2857     },
2858     /* Percent encoded characters aren't decoded when NO_DECODE_EXTRA_INFO is set. */
2859     {   "http://www.winehq.org/tests/..?query=%30%31&return=y", Uri_CREATE_NO_DECODE_EXTRA_INFO, S_OK, FALSE,
2860         {
2861             {"http://www.winehq.org/?query=%30%31&return=y",S_OK,FALSE},
2862             {"www.winehq.org",S_OK,FALSE},
2863             {"http://www.winehq.org/?query=%30%31&return=y",S_OK,FALSE},
2864             {"winehq.org",S_OK,FALSE},
2865             {"",S_FALSE,FALSE},
2866             {"",S_FALSE,FALSE},
2867             {"www.winehq.org",S_OK,FALSE},
2868             {"",S_FALSE,FALSE},
2869             {"/",S_OK,FALSE},
2870             {"/?query=%30%31&return=y",S_OK,FALSE},
2871             {"?query=%30%31&return=y",S_OK,FALSE},
2872             {"http://www.winehq.org/tests/..?query=%30%31&return=y",S_OK,FALSE},
2873             {"http",S_OK,FALSE},
2874             {"",S_FALSE,FALSE},
2875             {"",S_FALSE,FALSE}
2876         },
2877         {
2878             {Uri_HOST_DNS,S_OK,FALSE},
2879             {80,S_OK,FALSE},
2880             {URL_SCHEME_HTTP,S_OK,FALSE},
2881             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2882         }
2883     },
2884     {   "http://www.winehq.org?query=12&return=y", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
2885         {
2886             {"http://www.winehq.org?query=12&return=y",S_OK,FALSE},
2887             {"www.winehq.org",S_OK,FALSE},
2888             {"http://www.winehq.org?query=12&return=y",S_OK,FALSE},
2889             {"winehq.org",S_OK,FALSE},
2890             {"",S_FALSE,FALSE},
2891             {"",S_FALSE,FALSE},
2892             {"www.winehq.org",S_OK,FALSE},
2893             {"",S_FALSE,FALSE},
2894             {"",S_FALSE,FALSE},
2895             {"?query=12&return=y",S_OK,FALSE},
2896             {"?query=12&return=y",S_OK,FALSE},
2897             {"http://www.winehq.org?query=12&return=y",S_OK,FALSE},
2898             {"http",S_OK,FALSE},
2899             {"",S_FALSE,FALSE},
2900             {"",S_FALSE,FALSE}
2901         },
2902         {
2903             {Uri_HOST_DNS,S_OK,FALSE},
2904             {80,S_OK,FALSE},
2905             {URL_SCHEME_HTTP,S_OK,FALSE},
2906             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2907         }
2908     },
2909     /* Unknown scheme types can have invalid % encoded data in fragments. */
2910     {   "zip://www.winehq.org/tests/#Te%xx", 0, S_OK, FALSE,
2911         {
2912             {"zip://www.winehq.org/tests/#Te%xx",S_OK,FALSE},
2913             {"www.winehq.org",S_OK,FALSE},
2914             {"zip://www.winehq.org/tests/#Te%xx",S_OK,FALSE},
2915             {"winehq.org",S_OK,FALSE},
2916             {"",S_FALSE,FALSE},
2917             {"#Te%xx",S_OK,FALSE},
2918             {"www.winehq.org",S_OK,FALSE},
2919             {"",S_FALSE,FALSE},
2920             {"/tests/",S_OK,FALSE},
2921             {"/tests/",S_OK,FALSE},
2922             {"",S_FALSE,FALSE},
2923             {"zip://www.winehq.org/tests/#Te%xx",S_OK,FALSE},
2924             {"zip",S_OK,FALSE},
2925             {"",S_FALSE,FALSE},
2926             {"",S_FALSE,FALSE}
2927         },
2928         {
2929             {Uri_HOST_DNS,S_OK,FALSE},
2930             {0,S_FALSE,FALSE},
2931             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2932             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2933         }
2934     },
2935     /* Forbidden characters in fragment aren't encoded for unknown schemes. */
2936     {   "zip://www.winehq.org/tests/#Te<|>", 0, S_OK, FALSE,
2937         {
2938             {"zip://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
2939             {"www.winehq.org",S_OK,FALSE},
2940             {"zip://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
2941             {"winehq.org",S_OK,FALSE},
2942             {"",S_FALSE,FALSE},
2943             {"#Te<|>",S_OK,FALSE},
2944             {"www.winehq.org",S_OK,FALSE},
2945             {"",S_FALSE,FALSE},
2946             {"/tests/",S_OK,FALSE},
2947             {"/tests/",S_OK,FALSE},
2948             {"",S_FALSE,FALSE},
2949             {"zip://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
2950             {"zip",S_OK,FALSE},
2951             {"",S_FALSE,FALSE},
2952             {"",S_FALSE,FALSE}
2953         },
2954         {
2955             {Uri_HOST_DNS,S_OK,FALSE},
2956             {0,S_FALSE,FALSE},
2957             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
2958             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2959         }
2960     },
2961     /* Forbidden characters in the fragment are percent encoded for known schemes. */
2962     {   "http://www.winehq.org/tests/#Te<|>", 0, S_OK, FALSE,
2963         {
2964             {"http://www.winehq.org/tests/#Te%3C%7C%3E",S_OK,FALSE},
2965             {"www.winehq.org",S_OK,FALSE},
2966             {"http://www.winehq.org/tests/#Te%3C%7C%3E",S_OK,FALSE},
2967             {"winehq.org",S_OK,FALSE},
2968             {"",S_FALSE,FALSE},
2969             {"#Te%3C%7C%3E",S_OK,FALSE},
2970             {"www.winehq.org",S_OK,FALSE},
2971             {"",S_FALSE,FALSE},
2972             {"/tests/",S_OK,FALSE},
2973             {"/tests/",S_OK,FALSE},
2974             {"",S_FALSE,FALSE},
2975             {"http://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
2976             {"http",S_OK,FALSE},
2977             {"",S_FALSE,FALSE},
2978             {"",S_FALSE,FALSE}
2979         },
2980         {
2981             {Uri_HOST_DNS,S_OK,FALSE},
2982             {80,S_OK,FALSE},
2983             {URL_SCHEME_HTTP,S_OK,FALSE},
2984             {URLZONE_INVALID,E_NOTIMPL,FALSE},
2985         }
2986     },
2987     /* Forbidden characters aren't encoded in the fragment with this flag. */
2988     {   "http://www.winehq.org/tests/#Te<|>", Uri_CREATE_NO_DECODE_EXTRA_INFO, S_OK, FALSE,
2989         {
2990             {"http://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
2991             {"www.winehq.org",S_OK,FALSE},
2992             {"http://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
2993             {"winehq.org",S_OK,FALSE},
2994             {"",S_FALSE,FALSE},
2995             {"#Te<|>",S_OK,FALSE},
2996             {"www.winehq.org",S_OK,FALSE},
2997             {"",S_FALSE,FALSE},
2998             {"/tests/",S_OK,FALSE},
2999             {"/tests/",S_OK,FALSE},
3000             {"",S_FALSE,FALSE},
3001             {"http://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
3002             {"http",S_OK,FALSE},
3003             {"",S_FALSE,FALSE},
3004             {"",S_FALSE,FALSE}
3005         },
3006         {
3007             {Uri_HOST_DNS,S_OK,FALSE},
3008             {80,S_OK,FALSE},
3009             {URL_SCHEME_HTTP,S_OK,FALSE},
3010             {URLZONE_INVALID,E_NOTIMPL,FALSE},
3011         }
3012     },
3013     /* Forbidden characters aren't encoded in the fragment with this flag. */
3014     {   "http://www.winehq.org/tests/#Te<|>", Uri_CREATE_NO_ENCODE_FORBIDDEN_CHARACTERS, S_OK, FALSE,
3015         {
3016             {"http://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
3017             {"www.winehq.org",S_OK,FALSE},
3018             {"http://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
3019             {"winehq.org",S_OK,FALSE},
3020             {"",S_FALSE,FALSE},
3021             {"#Te<|>",S_OK,FALSE},
3022             {"www.winehq.org",S_OK,FALSE},
3023             {"",S_FALSE,FALSE},
3024             {"/tests/",S_OK,FALSE},
3025             {"/tests/",S_OK,FALSE},
3026             {"",S_FALSE,FALSE},
3027             {"http://www.winehq.org/tests/#Te<|>",S_OK,FALSE},
3028             {"http",S_OK,FALSE},
3029             {"",S_FALSE,FALSE},
3030             {"",S_FALSE,FALSE}
3031         },
3032         {
3033             {Uri_HOST_DNS,S_OK,FALSE},
3034             {80,S_OK,FALSE},
3035             {URL_SCHEME_HTTP,S_OK,FALSE},
3036             {URLZONE_INVALID,E_NOTIMPL,FALSE},
3037         }
3038     },
3039     /* Percent encoded, unreserved characters aren't decoded for known scheme types. */
3040     {   "zip://www.winehq.org/tests/#Te%30%31%32", 0, S_OK, FALSE,
3041         {
3042             {"zip://www.winehq.org/tests/#Te%30%31%32",S_OK,FALSE},
3043             {"www.winehq.org",S_OK,FALSE},
3044             {"zip://www.winehq.org/tests/#Te%30%31%32",S_OK,FALSE},
3045             {"winehq.org",S_OK,FALSE},
3046             {"",S_FALSE,FALSE},
3047             {"#Te%30%31%32",S_OK,FALSE},
3048             {"www.winehq.org",S_OK,FALSE},
3049             {"",S_FALSE,FALSE},
3050             {"/tests/",S_OK,FALSE},
3051             {"/tests/",S_OK,FALSE},
3052             {"",S_FALSE,FALSE},
3053             {"zip://www.winehq.org/tests/#Te%30%31%32",S_OK,FALSE},
3054             {"zip",S_OK,FALSE},
3055             {"",S_FALSE,FALSE},
3056             {"",S_FALSE,FALSE}
3057         },
3058         {
3059             {Uri_HOST_DNS,S_OK,FALSE},
3060             {0,S_FALSE,FALSE},
3061             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
3062             {URLZONE_INVALID,E_NOTIMPL,FALSE},
3063         }
3064     },
3065     /* Percent encoded, unreserved characters are decoded for known schemes. */
3066     {   "http://www.winehq.org/tests/#Te%30%31%32", 0, S_OK, FALSE,
3067         {
3068             {"http://www.winehq.org/tests/#Te012",S_OK,FALSE},
3069             {"www.winehq.org",S_OK,FALSE},
3070             {"http://www.winehq.org/tests/#Te012",S_OK,FALSE},
3071             {"winehq.org",S_OK,FALSE},
3072             {"",S_FALSE,FALSE},
3073             {"#Te012",S_OK,FALSE},
3074             {"www.winehq.org",S_OK,FALSE},
3075             {"",S_FALSE,FALSE},
3076             {"/tests/",S_OK,FALSE},
3077             {"/tests/",S_OK,FALSE},
3078             {"",S_FALSE,FALSE},
3079             {"http://www.winehq.org/tests/#Te%30%31%32",S_OK,FALSE},
3080             {"http",S_OK,FALSE},
3081             {"",S_FALSE,FALSE},
3082             {"",S_FALSE,FALSE}
3083         },
3084         {
3085             {Uri_HOST_DNS,S_OK,FALSE},
3086             {80,S_OK,FALSE},
3087             {URL_SCHEME_HTTP,S_OK,FALSE},
3088             {URLZONE_INVALID,E_NOTIMPL,FALSE},
3089         }
3090     },
3091     /* Percent encoded, unreserved characters are decoded even if NO_CANONICALIZE is set. */
3092     {   "http://www.winehq.org/tests/#Te%30%31%32", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
3093         {
3094             {"http://www.winehq.org/tests/#Te012",S_OK,FALSE},
3095             {"www.winehq.org",S_OK,FALSE},
3096             {"http://www.winehq.org/tests/#Te012",S_OK,FALSE},
3097             {"winehq.org",S_OK,FALSE},
3098             {"",S_FALSE,FALSE},
3099             {"#Te012",S_OK,FALSE},
3100             {"www.winehq.org",S_OK,FALSE},
3101             {"",S_FALSE,FALSE},
3102             {"/tests/",S_OK,FALSE},
3103             {"/tests/",S_OK,FALSE},
3104             {"",S_FALSE,FALSE},
3105             {"http://www.winehq.org/tests/#Te%30%31%32",S_OK,FALSE},
3106             {"http",S_OK,FALSE},
3107             {"",S_FALSE,FALSE},
3108             {"",S_FALSE,FALSE}
3109         },
3110         {
3111             {Uri_HOST_DNS,S_OK,FALSE},
3112             {80,S_OK,FALSE},
3113             {URL_SCHEME_HTTP,S_OK,FALSE},
3114             {URLZONE_INVALID,E_NOTIMPL,FALSE},
3115         }
3116     },
3117     /* Percent encoded, unreserved characters aren't decoded when NO_DECODE_EXTRA is set. */
3118     {   "http://www.winehq.org/tests/#Te%30%31%32", Uri_CREATE_NO_DECODE_EXTRA_INFO, S_OK, FALSE,
3119         {
3120             {"http://www.winehq.org/tests/#Te%30%31%32",S_OK,FALSE},
3121             {"www.winehq.org",S_OK,FALSE},
3122             {"http://www.winehq.org/tests/#Te%30%31%32",S_OK,FALSE},
3123             {"winehq.org",S_OK,FALSE},
3124             {"",S_FALSE,FALSE},
3125             {"#Te%30%31%32",S_OK,FALSE},
3126             {"www.winehq.org",S_OK,FALSE},
3127             {"",S_FALSE,FALSE},
3128             {"/tests/",S_OK,FALSE},
3129             {"/tests/",S_OK,FALSE},
3130             {"",S_FALSE,FALSE},
3131             {"http://www.winehq.org/tests/#Te%30%31%32",S_OK,FALSE},
3132             {"http",S_OK,FALSE},
3133             {"",S_FALSE,FALSE},
3134             {"",S_FALSE,FALSE}
3135         },
3136         {
3137             {Uri_HOST_DNS,S_OK,FALSE},
3138             {80,S_OK,FALSE},
3139             {URL_SCHEME_HTTP,S_OK,FALSE},
3140             {URLZONE_INVALID,E_NOTIMPL,FALSE},
3141         }
3142     },
3143     /* Leading/Trailing whitespace is removed. */
3144     {   "    http://google.com/     ", 0, S_OK, FALSE,
3145         {
3146             {"http://google.com/",S_OK,FALSE},
3147             {"google.com",S_OK,FALSE},
3148             {"http://google.com/",S_OK,FALSE},
3149             {"google.com",S_OK,FALSE},
3150             {"",S_FALSE,FALSE},
3151             {"",S_FALSE,FALSE},
3152             {"google.com",S_OK,FALSE},
3153             {"",S_FALSE,FALSE},
3154             {"/",S_OK,FALSE},
3155             {"/",S_OK,FALSE},
3156             {"",S_FALSE,FALSE},
3157             {"http://google.com/",S_OK,FALSE},
3158             {"http",S_OK,FALSE},
3159             {"",S_FALSE,FALSE},
3160             {"",S_FALSE,FALSE}
3161         },
3162         {
3163             {Uri_HOST_DNS,S_OK,FALSE},
3164             {80,S_OK,FALSE},
3165             {URL_SCHEME_HTTP,S_OK,FALSE},
3166             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3167         }
3168     },
3169     {   "\t\t\r\nhttp\n://g\noogle.co\rm/\n\n\n", 0, S_OK, FALSE,
3170         {
3171             {"http://google.com/",S_OK,FALSE},
3172             {"google.com",S_OK,FALSE},
3173             {"http://google.com/",S_OK,FALSE},
3174             {"google.com",S_OK,FALSE},
3175             {"",S_FALSE,FALSE},
3176             {"",S_FALSE,FALSE},
3177             {"google.com",S_OK,FALSE},
3178             {"",S_FALSE,FALSE},
3179             {"/",S_OK,FALSE},
3180             {"/",S_OK,FALSE},
3181             {"",S_FALSE,FALSE},
3182             {"http://google.com/",S_OK,FALSE},
3183             {"http",S_OK,FALSE},
3184             {"",S_FALSE,FALSE},
3185             {"",S_FALSE,FALSE}
3186         },
3187         {
3188             {Uri_HOST_DNS,S_OK,FALSE},
3189             {80,S_OK,FALSE},
3190             {URL_SCHEME_HTTP,S_OK,FALSE},
3191             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3192         }
3193     },
3194     {   "http://g\noogle.co\rm/\n\n\n", Uri_CREATE_NO_PRE_PROCESS_HTML_URI, S_OK, FALSE,
3195         {
3196             {"http://g%0aoogle.co%0dm/%0A%0A%0A",S_OK,FALSE},
3197             {"g%0aoogle.co%0dm",S_OK,FALSE},
3198             {"http://g%0aoogle.co%0dm/%0A%0A%0A",S_OK,FALSE},
3199             {"g%0aoogle.co%0dm",S_OK,FALSE},
3200             {"",S_FALSE,FALSE},
3201             {"",S_FALSE,FALSE},
3202             {"g%0aoogle.co%0dm",S_OK,FALSE},
3203             {"",S_FALSE,FALSE},
3204             {"/%0A%0A%0A",S_OK,FALSE},
3205             {"/%0A%0A%0A",S_OK,FALSE},
3206             {"",S_FALSE,FALSE},
3207             {"http://g\noogle.co\rm/\n\n\n",S_OK,FALSE},
3208             {"http",S_OK,FALSE},
3209             {"",S_FALSE,FALSE},
3210             {"",S_FALSE,FALSE}
3211         },
3212         {
3213             {Uri_HOST_DNS,S_OK,FALSE},
3214             {80,S_OK,FALSE},
3215             {URL_SCHEME_HTTP,S_OK,FALSE},
3216             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3217         }
3218     },
3219     {   "zip://g\noogle.co\rm/\n\n\n", Uri_CREATE_NO_PRE_PROCESS_HTML_URI, S_OK, FALSE,
3220         {
3221             {"zip://g\noogle.co\rm/\n\n\n",S_OK,FALSE},
3222             {"g\noogle.co\rm",S_OK,FALSE},
3223             {"zip://g\noogle.co\rm/\n\n\n",S_OK,FALSE},
3224             {"g\noogle.co\rm",S_OK,FALSE},
3225             {"",S_FALSE,FALSE},
3226             {"",S_FALSE,FALSE},
3227             {"g\noogle.co\rm",S_OK,FALSE},
3228             {"",S_FALSE,FALSE},
3229             {"/\n\n\n",S_OK,FALSE},
3230             {"/\n\n\n",S_OK,FALSE},
3231             {"",S_FALSE,FALSE},
3232             {"zip://g\noogle.co\rm/\n\n\n",S_OK,FALSE},
3233             {"zip",S_OK,FALSE},
3234             {"",S_FALSE,FALSE},
3235             {"",S_FALSE,FALSE}
3236         },
3237         {
3238             {Uri_HOST_DNS,S_OK,FALSE},
3239             {0,S_FALSE,FALSE},
3240             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
3241             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3242         }
3243     },
3244     /* Since file URLs are usually hierarchical, it returns an empty string
3245      * for the absolute URI property since it was declared as an opaque URI.
3246      */
3247     {   "file:index.html", 0, S_OK, FALSE,
3248         {
3249             {"",S_FALSE,FALSE},
3250             {"",S_FALSE,FALSE},
3251             {"file:index.html",S_OK,FALSE},
3252             {"",S_FALSE,FALSE},
3253             {".html",S_OK,FALSE},
3254             {"",S_FALSE,FALSE},
3255             {"",S_FALSE,FALSE},
3256             {"",S_FALSE,FALSE},
3257             {"index.html",S_OK,FALSE},
3258             {"index.html",S_OK,FALSE},
3259             {"",S_FALSE,FALSE},
3260             {"file:index.html",S_OK,FALSE},
3261             {"file",S_OK,FALSE},
3262             {"",S_FALSE,FALSE},
3263             {"",S_FALSE,FALSE}
3264         },
3265         {
3266             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3267             {0,S_FALSE,FALSE},
3268             {URL_SCHEME_FILE,S_OK,FALSE},
3269             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3270         }
3271     },
3272     /* Doesn't have an absolute since it's opaque, but gets it port set. */
3273     {   "http:test.com/index.html", 0, S_OK, FALSE,
3274         {
3275             {"",S_FALSE,FALSE},
3276             {"",S_FALSE,FALSE},
3277             {"http:test.com/index.html",S_OK,FALSE},
3278             {"",S_FALSE,FALSE},
3279             {".html",S_OK,FALSE},
3280             {"",S_FALSE,FALSE},
3281             {"",S_FALSE,FALSE},
3282             {"",S_FALSE,FALSE},
3283             {"test.com/index.html",S_OK,FALSE},
3284             {"test.com/index.html",S_OK,FALSE},
3285             {"",S_FALSE,FALSE},
3286             {"http:test.com/index.html",S_OK,FALSE},
3287             {"http",S_OK,FALSE},
3288             {"",S_FALSE,FALSE},
3289             {"",S_FALSE,FALSE}
3290         },
3291         {
3292             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3293             {80,S_OK,FALSE},
3294             {URL_SCHEME_HTTP,S_OK,FALSE},
3295             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3296         }
3297     },
3298     {   "ftp:test.com/index.html", 0, S_OK, FALSE,
3299         {
3300             {"",S_FALSE,FALSE},
3301             {"",S_FALSE,FALSE},
3302             {"ftp:test.com/index.html",S_OK,FALSE},
3303             {"",S_FALSE,FALSE},
3304             {".html",S_OK,FALSE},
3305             {"",S_FALSE,FALSE},
3306             {"",S_FALSE,FALSE},
3307             {"",S_FALSE,FALSE},
3308             {"test.com/index.html",S_OK,FALSE},
3309             {"test.com/index.html",S_OK,FALSE},
3310             {"",S_FALSE,FALSE},
3311             {"ftp:test.com/index.html",S_OK,FALSE},
3312             {"ftp",S_OK,FALSE},
3313             {"",S_FALSE,FALSE},
3314             {"",S_FALSE,FALSE}
3315         },
3316         {
3317             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3318             {21,S_OK,FALSE},
3319             {URL_SCHEME_FTP,S_OK,FALSE},
3320             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3321         }
3322     },
3323     {   "file://C|/test.mp3", 0, S_OK, FALSE,
3324         {
3325             {"file:///C:/test.mp3",S_OK,FALSE},
3326             {"",S_FALSE,FALSE},
3327             {"file:///C:/test.mp3",S_OK,FALSE},
3328             {"",S_FALSE,FALSE},
3329             {".mp3",S_OK,FALSE},
3330             {"",S_FALSE,FALSE},
3331             {"",S_FALSE,FALSE},
3332             {"",S_FALSE,FALSE},
3333             {"/C:/test.mp3",S_OK,FALSE},
3334             {"/C:/test.mp3",S_OK,FALSE},
3335             {"",S_FALSE,FALSE},
3336             {"file://C|/test.mp3",S_OK,FALSE},
3337             {"file",S_OK,FALSE},
3338             {"",S_FALSE,FALSE},
3339             {"",S_FALSE,FALSE}
3340         },
3341         {
3342             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3343             {0,S_FALSE,FALSE},
3344             {URL_SCHEME_FILE,S_OK,FALSE},
3345             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3346         }
3347     },
3348     {   "file:///C|/test.mp3", 0, S_OK, FALSE,
3349         {
3350             {"file:///C:/test.mp3",S_OK,FALSE},
3351             {"",S_FALSE,FALSE},
3352             {"file:///C:/test.mp3",S_OK,FALSE},
3353             {"",S_FALSE,FALSE},
3354             {".mp3",S_OK,FALSE},
3355             {"",S_FALSE,FALSE},
3356             {"",S_FALSE,FALSE},
3357             {"",S_FALSE,FALSE},
3358             {"/C:/test.mp3",S_OK,FALSE},
3359             {"/C:/test.mp3",S_OK,FALSE},
3360             {"",S_FALSE,FALSE},
3361             {"file:///C|/test.mp3",S_OK,FALSE},
3362             {"file",S_OK,FALSE},
3363             {"",S_FALSE,FALSE},
3364             {"",S_FALSE,FALSE}
3365         },
3366         {
3367             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3368             {0,S_FALSE,FALSE},
3369             {URL_SCHEME_FILE,S_OK,FALSE},
3370             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3371         }
3372     },
3373     /* Extra '/' isn't added before "c:" since USE_DOS_PATH is set and '/' are converted
3374      * to '\\'.
3375      */
3376     {   "file://c:/dir/index.html", Uri_CREATE_FILE_USE_DOS_PATH, S_OK, FALSE,
3377         {
3378             {"file://c:\\dir\\index.html",S_OK,FALSE},
3379             {"",S_FALSE,FALSE},
3380             {"file://c:\\dir\\index.html",S_OK,FALSE},
3381             {"",S_FALSE,FALSE},
3382             {".html",S_OK,FALSE},
3383             {"",S_FALSE,FALSE},
3384             {"",S_FALSE,FALSE},
3385             {"",S_FALSE,FALSE},
3386             {"c:\\dir\\index.html",S_OK,FALSE},
3387             {"c:\\dir\\index.html",S_OK,FALSE},
3388             {"",S_FALSE,FALSE},
3389             {"file://c:/dir/index.html",S_OK,FALSE},
3390             {"file",S_OK,FALSE},
3391             {"",S_FALSE,FALSE},
3392             {"",S_FALSE,FALSE}
3393         },
3394         {
3395             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3396             {0,S_FALSE,FALSE},
3397             {URL_SCHEME_FILE,S_OK,FALSE},
3398             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3399         }
3400     },
3401     /* Extra '/' after "file://" is removed. */
3402     {   "file:///c:/dir/index.html", Uri_CREATE_FILE_USE_DOS_PATH, S_OK, FALSE,
3403         {
3404             {"file://c:\\dir\\index.html",S_OK,FALSE},
3405             {"",S_FALSE,FALSE},
3406             {"file://c:\\dir\\index.html",S_OK,FALSE},
3407             {"",S_FALSE,FALSE},
3408             {".html",S_OK,FALSE},
3409             {"",S_FALSE,FALSE},
3410             {"",S_FALSE,FALSE},
3411             {"",S_FALSE,FALSE},
3412             {"c:\\dir\\index.html",S_OK,FALSE},
3413             {"c:\\dir\\index.html",S_OK,FALSE},
3414             {"",S_FALSE,FALSE},
3415             {"file:///c:/dir/index.html",S_OK,FALSE},
3416             {"file",S_OK,FALSE},
3417             {"",S_FALSE,FALSE},
3418             {"",S_FALSE,FALSE}
3419         },
3420         {
3421             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3422             {0,S_FALSE,FALSE},
3423             {URL_SCHEME_FILE,S_OK,FALSE},
3424             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3425         }
3426     },
3427     /* Allow more characters when Uri_CREATE_FILE_USE_DOS_PATH is specified */
3428     {   "file:///c:/dir\\%%61%20%5Fname/file%2A.html", Uri_CREATE_FILE_USE_DOS_PATH, S_OK, FALSE,
3429         {
3430             {"file://c:\\dir\\%a _name\\file*.html",S_OK,FALSE},
3431             {"",S_FALSE,FALSE},
3432             {"file://c:\\dir\\%a _name\\file*.html",S_OK,FALSE},
3433             {"",S_FALSE,FALSE},
3434             {".html",S_OK,FALSE},
3435             {"",S_FALSE,FALSE},
3436             {"",S_FALSE,FALSE},
3437             {"",S_FALSE,FALSE},
3438             {"c:\\dir\\%a _name\\file*.html",S_OK,FALSE},
3439             {"c:\\dir\\%a _name\\file*.html",S_OK,FALSE},
3440             {"",S_FALSE,FALSE},
3441             {"file:///c:/dir\\%%61%20%5Fname/file%2A.html",S_OK,FALSE},
3442             {"file",S_OK,FALSE},
3443             {"",S_FALSE,FALSE},
3444             {"",S_FALSE,FALSE}
3445         },
3446         {
3447             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3448             {0,S_FALSE,FALSE},
3449             {URL_SCHEME_FILE,S_OK,FALSE},
3450             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3451         }
3452     },
3453     {   "file://c|/dir\\index.html", Uri_CREATE_FILE_USE_DOS_PATH, S_OK, FALSE,
3454         {
3455             {"file://c:\\dir\\index.html",S_OK,FALSE},
3456             {"",S_FALSE,FALSE},
3457             {"file://c:\\dir\\index.html",S_OK,FALSE},
3458             {"",S_FALSE,FALSE},
3459             {".html",S_OK,FALSE},
3460             {"",S_FALSE,FALSE},
3461             {"",S_FALSE,FALSE},
3462             {"",S_FALSE,FALSE},
3463             {"c:\\dir\\index.html",S_OK,FALSE},
3464             {"c:\\dir\\index.html",S_OK,FALSE},
3465             {"",S_FALSE,FALSE},
3466             {"file://c|/dir\\index.html",S_OK,FALSE},
3467             {"file",S_OK,FALSE},
3468             {"",S_FALSE,FALSE},
3469             {"",S_FALSE,FALSE}
3470         },
3471         {
3472             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3473             {0,S_FALSE,FALSE},
3474             {URL_SCHEME_FILE,S_OK,FALSE},
3475             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3476         }
3477     },
3478     /* The backslashes after the scheme name are converted to forward slashes. */
3479     {   "file:\\\\c:\\dir\\index.html", Uri_CREATE_FILE_USE_DOS_PATH, S_OK, FALSE,
3480         {
3481             {"file://c:\\dir\\index.html",S_OK,FALSE},
3482             {"",S_FALSE,FALSE},
3483             {"file://c:\\dir\\index.html",S_OK,FALSE},
3484             {"",S_FALSE,FALSE},
3485             {".html",S_OK,FALSE},
3486             {"",S_FALSE,FALSE},
3487             {"",S_FALSE,FALSE},
3488             {"",S_FALSE,FALSE},
3489             {"c:\\dir\\index.html",S_OK,FALSE},
3490             {"c:\\dir\\index.html",S_OK,FALSE},
3491             {"",S_FALSE,FALSE},
3492             {"file:\\\\c:\\dir\\index.html",S_OK,FALSE},
3493             {"file",S_OK,FALSE},
3494             {"",S_FALSE,FALSE},
3495             {"",S_FALSE,FALSE}
3496         },
3497         {
3498             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3499             {0,S_FALSE,FALSE},
3500             {URL_SCHEME_FILE,S_OK,FALSE},
3501             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3502         }
3503     },
3504     {   "file:\\\\c:/dir/index.html", 0, S_OK, FALSE,
3505         {
3506             {"file:///c:/dir/index.html",S_OK,FALSE},
3507             {"",S_FALSE,FALSE},
3508             {"file:///c:/dir/index.html",S_OK,FALSE},
3509             {"",S_FALSE,FALSE},
3510             {".html",S_OK,FALSE},
3511             {"",S_FALSE,FALSE},
3512             {"",S_FALSE,FALSE},
3513             {"",S_FALSE,FALSE},
3514             {"/c:/dir/index.html",S_OK,FALSE},
3515             {"/c:/dir/index.html",S_OK,FALSE},
3516             {"",S_FALSE,FALSE},
3517             {"file:\\\\c:/dir/index.html",S_OK,FALSE},
3518             {"file",S_OK,FALSE},
3519             {"",S_FALSE,FALSE},
3520             {"",S_FALSE,FALSE}
3521         },
3522         {
3523             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3524             {0,S_FALSE,FALSE},
3525             {URL_SCHEME_FILE,S_OK,FALSE},
3526             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3527         }
3528     },
3529     {   "http:\\\\google.com", 0, S_OK, FALSE,
3530         {
3531             {"http://google.com/",S_OK,FALSE},
3532             {"google.com",S_OK,FALSE},
3533             {"http://google.com/",S_OK,FALSE},
3534             {"google.com",S_OK,FALSE},
3535             {"",S_FALSE,FALSE},
3536             {"",S_FALSE,FALSE},
3537             {"google.com",S_OK,FALSE},
3538             {"",S_FALSE,FALSE},
3539             {"/",S_OK,FALSE},
3540             {"/",S_OK,FALSE},
3541             {"",S_FALSE,FALSE},
3542             {"http:\\\\google.com",S_OK,FALSE},
3543             {"http",S_OK,FALSE},
3544             {"",S_FALSE,FALSE},
3545             {"",S_FALSE,FALSE}
3546         },
3547         {
3548             {Uri_HOST_DNS,S_OK,FALSE},
3549             {80,S_OK,FALSE},
3550             {URL_SCHEME_HTTP,S_OK,FALSE},
3551             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3552         }
3553     },
3554     /* the "\\\\" aren't converted to "//" for unknown scheme types and it's considered opaque. */
3555     {   "zip:\\\\google.com", 0, S_OK, FALSE,
3556         {
3557             {"zip:\\\\google.com",S_OK,FALSE},
3558             {"",S_FALSE,FALSE},
3559             {"zip:\\\\google.com",S_OK,FALSE},
3560             {"",S_FALSE,FALSE},
3561             {".com",S_OK,FALSE},
3562             {"",S_FALSE,FALSE},
3563             {"",S_FALSE,FALSE},
3564             {"",S_FALSE,FALSE},
3565             {"\\\\google.com",S_OK,FALSE},
3566             {"\\\\google.com",S_OK,FALSE},
3567             {"",S_FALSE,FALSE},
3568             {"zip:\\\\google.com",S_OK,FALSE},
3569             {"zip",S_OK,FALSE},
3570             {"",S_FALSE,FALSE},
3571             {"",S_FALSE,FALSE}
3572         },
3573         {
3574             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3575             {0,S_FALSE,FALSE},
3576             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
3577             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3578         }
3579     },
3580     /* Dot segments aren't removed. */
3581     {   "file://c:\\dir\\../..\\./index.html", Uri_CREATE_FILE_USE_DOS_PATH, S_OK, FALSE,
3582         {
3583             {"file://c:\\dir\\..\\..\\.\\index.html",S_OK,FALSE},
3584             {"",S_FALSE,FALSE},
3585             {"file://c:\\dir\\..\\..\\.\\index.html",S_OK,FALSE},
3586             {"",S_FALSE,FALSE},
3587             {".html",S_OK,FALSE},
3588             {"",S_FALSE,FALSE},
3589             {"",S_FALSE,FALSE},
3590             {"",S_FALSE,FALSE},
3591             {"c:\\dir\\..\\..\\.\\index.html",S_OK,FALSE},
3592             {"c:\\dir\\..\\..\\.\\index.html",S_OK,FALSE},
3593             {"",S_FALSE,FALSE},
3594             {"file://c:\\dir\\../..\\./index.html",S_OK,FALSE},
3595             {"file",S_OK,FALSE},
3596             {"",S_FALSE,FALSE},
3597             {"",S_FALSE,FALSE}
3598         },
3599         {
3600             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3601             {0,S_FALSE,FALSE},
3602             {URL_SCHEME_FILE,S_OK,FALSE},
3603             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3604         }
3605     },
3606     /* Forbidden characters aren't percent encoded. */
3607     {   "file://c:\\dir\\i^|ndex.html", Uri_CREATE_FILE_USE_DOS_PATH, S_OK, FALSE,
3608         {
3609             {"file://c:\\dir\\i^|ndex.html",S_OK,FALSE},
3610             {"",S_FALSE,FALSE},
3611             {"file://c:\\dir\\i^|ndex.html",S_OK,FALSE},
3612             {"",S_FALSE,FALSE},
3613             {".html",S_OK,FALSE},
3614             {"",S_FALSE,FALSE},
3615             {"",S_FALSE,FALSE},
3616             {"",S_FALSE,FALSE},
3617             {"c:\\dir\\i^|ndex.html",S_OK,FALSE},
3618             {"c:\\dir\\i^|ndex.html",S_OK,FALSE},
3619             {"",S_FALSE,FALSE},
3620             {"file://c:\\dir\\i^|ndex.html",S_OK,FALSE},
3621             {"file",S_OK,FALSE},
3622             {"",S_FALSE,FALSE},
3623             {"",S_FALSE,FALSE}
3624         },
3625         {
3626             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3627             {0,S_FALSE,FALSE},
3628             {URL_SCHEME_FILE,S_OK,FALSE},
3629             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3630         }
3631     },
3632     /* The '\' are still converted to '/' even though it's an opaque file URI. */
3633     {   "file:c:\\dir\\../..\\index.html", 0, S_OK, FALSE,
3634         {
3635             {"",S_FALSE,FALSE},
3636             {"",S_FALSE,FALSE},
3637             {"file:c:/dir/../../index.html",S_OK,FALSE},
3638             {"",S_FALSE,FALSE},
3639             {".html",S_OK,FALSE},
3640             {"",S_FALSE,FALSE},
3641             {"",S_FALSE,FALSE},
3642             {"",S_FALSE,FALSE},
3643             {"c:/dir/../../index.html",S_OK,FALSE},
3644             {"c:/dir/../../index.html",S_OK,FALSE},
3645             {"",S_FALSE,FALSE},
3646             {"file:c:\\dir\\../..\\index.html",S_OK,FALSE},
3647             {"file",S_OK,FALSE},
3648             {"",S_FALSE,FALSE},
3649             {"",S_FALSE,FALSE}
3650         },
3651         {
3652             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3653             {0,S_FALSE,FALSE},
3654             {URL_SCHEME_FILE,S_OK,FALSE},
3655             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3656         }
3657     },
3658     /* '/' are still converted to '\' even though it's an opaque URI. */
3659     {   "file:c:/dir\\../..\\index.html", Uri_CREATE_FILE_USE_DOS_PATH, S_OK, FALSE,
3660         {
3661             {"",S_FALSE,FALSE},
3662             {"",S_FALSE,FALSE},
3663             {"file:c:\\dir\\..\\..\\index.html",S_OK,FALSE},
3664             {"",S_FALSE,FALSE},
3665             {".html",S_OK,FALSE},
3666             {"",S_FALSE,FALSE},
3667             {"",S_FALSE,FALSE},
3668             {"",S_FALSE,FALSE},
3669             {"c:\\dir\\..\\..\\index.html",S_OK,FALSE},
3670             {"c:\\dir\\..\\..\\index.html",S_OK,FALSE},
3671             {"",S_FALSE,FALSE},
3672             {"file:c:/dir\\../..\\index.html",S_OK,FALSE},
3673             {"file",S_OK,FALSE},
3674             {"",S_FALSE,FALSE},
3675             {"",S_FALSE,FALSE}
3676         },
3677         {
3678             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3679             {0,S_FALSE,FALSE},
3680             {URL_SCHEME_FILE,S_OK,FALSE},
3681             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3682         }
3683     },
3684     /* Forbidden characters aren't percent encoded. */
3685     {   "file:c:\\in^|dex.html", Uri_CREATE_FILE_USE_DOS_PATH, S_OK, FALSE,
3686         {
3687             {"",S_FALSE,FALSE},
3688             {"",S_FALSE,FALSE},
3689             {"file:c:\\in^|dex.html",S_OK,FALSE},
3690             {"",S_FALSE,FALSE},
3691             {".html",S_OK,FALSE},
3692             {"",S_FALSE,FALSE},
3693             {"",S_FALSE,FALSE},
3694             {"",S_FALSE,FALSE},
3695             {"c:\\in^|dex.html",S_OK,FALSE},
3696             {"c:\\in^|dex.html",S_OK,FALSE},
3697             {"",S_FALSE,FALSE},
3698             {"file:c:\\in^|dex.html",S_OK,FALSE},
3699             {"file",S_OK,FALSE},
3700             {"",S_FALSE,FALSE},
3701             {"",S_FALSE,FALSE}
3702         },
3703         {
3704             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3705             {0,S_FALSE,FALSE},
3706             {URL_SCHEME_FILE,S_OK,FALSE},
3707             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3708         }
3709     },
3710     /* Doesn't have a UserName since the ':' appears at the beginning of the
3711      * userinfo section.
3712      */
3713     {   "http://:password@gov.uk", 0, S_OK, FALSE,
3714         {
3715             {"http://:password@gov.uk/",S_OK,FALSE},
3716             {":password@gov.uk",S_OK,FALSE},
3717             {"http://gov.uk/",S_OK,FALSE},
3718             {"",S_FALSE,FALSE},
3719             {"",S_FALSE,FALSE},
3720             {"",S_FALSE,FALSE},
3721             {"gov.uk",S_OK,FALSE},
3722             {"password",S_OK,FALSE},
3723             {"/",S_OK,FALSE},
3724             {"/",S_OK,FALSE},
3725             {"",S_FALSE,FALSE},
3726             {"http://:password@gov.uk",S_OK,FALSE},
3727             {"http",S_OK,FALSE},
3728             {":password",S_OK,FALSE},
3729             {"",S_FALSE,FALSE}
3730         },
3731         {
3732             {Uri_HOST_DNS,S_OK,FALSE},
3733             {80,S_OK,FALSE},
3734             {URL_SCHEME_HTTP,S_OK,FALSE},
3735             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3736         }
3737     },
3738     /* Has a UserName since the userinfo section doesn't contain a password. */
3739     {   "http://@gov.uk", 0, S_OK, FALSE,
3740         {
3741             {"http://gov.uk/",S_OK,FALSE,"http://@gov.uk/"},
3742             {"@gov.uk",S_OK,FALSE},
3743             {"http://gov.uk/",S_OK,FALSE},
3744             {"",S_FALSE,FALSE},
3745             {"",S_FALSE,FALSE},
3746             {"",S_FALSE,FALSE},
3747             {"gov.uk",S_OK,FALSE},
3748             {"",S_FALSE,FALSE},
3749             {"/",S_OK,FALSE},
3750             {"/",S_OK,FALSE},
3751             {"",S_FALSE,FALSE},
3752             {"http://@gov.uk",S_OK,FALSE},
3753             {"http",S_OK,FALSE},
3754             {"",S_OK,FALSE},
3755             {"",S_OK,FALSE}
3756         },
3757         {
3758             {Uri_HOST_DNS,S_OK,FALSE},
3759             {80,S_OK,FALSE},
3760             {URL_SCHEME_HTTP,S_OK,FALSE},
3761             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3762         }
3763     },
3764     /* ":@" not included in the absolute URI. */
3765     {   "http://:@gov.uk", 0, S_OK, FALSE,
3766         {
3767             {"http://gov.uk/",S_OK,FALSE,"http://:@gov.uk/"},
3768             {":@gov.uk",S_OK,FALSE},
3769             {"http://gov.uk/",S_OK,FALSE},
3770             {"",S_FALSE,FALSE},
3771             {"",S_FALSE,FALSE},
3772             {"",S_FALSE,FALSE},
3773             {"gov.uk",S_OK,FALSE},
3774             {"",S_OK,FALSE},
3775             {"/",S_OK,FALSE},
3776             {"/",S_OK,FALSE},
3777             {"",S_FALSE,FALSE},
3778             {"http://:@gov.uk",S_OK,FALSE},
3779             {"http",S_OK,FALSE},
3780             {":",S_OK,FALSE},
3781             {"",S_FALSE,FALSE}
3782         },
3783         {
3784             {Uri_HOST_DNS,S_OK,FALSE},
3785             {80,S_OK,FALSE},
3786             {URL_SCHEME_HTTP,S_OK,FALSE},
3787             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3788         }
3789     },
3790     /* '@' is included because it's an unknown scheme type. */
3791     {   "zip://@gov.uk", 0, S_OK, FALSE,
3792         {
3793             {"zip://@gov.uk/",S_OK,FALSE},
3794             {"@gov.uk",S_OK,FALSE},
3795             {"zip://@gov.uk/",S_OK,FALSE},
3796             {"",S_FALSE,FALSE},
3797             {"",S_FALSE,FALSE},
3798             {"",S_FALSE,FALSE},
3799             {"gov.uk",S_OK,FALSE},
3800             {"",S_FALSE,FALSE},
3801             {"/",S_OK,FALSE},
3802             {"/",S_OK,FALSE},
3803             {"",S_FALSE,FALSE},
3804             {"zip://@gov.uk",S_OK,FALSE},
3805             {"zip",S_OK,FALSE},
3806             {"",S_OK,FALSE},
3807             {"",S_OK,FALSE}
3808         },
3809         {
3810             {Uri_HOST_DNS,S_OK,FALSE},
3811             {0,S_FALSE,FALSE},
3812             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
3813             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3814         }
3815     },
3816     /* ":@" are included because it's an unknown scheme type. */
3817     {   "zip://:@gov.uk", 0, S_OK, FALSE,
3818         {
3819             {"zip://:@gov.uk/",S_OK,FALSE},
3820             {":@gov.uk",S_OK,FALSE},
3821             {"zip://:@gov.uk/",S_OK,FALSE},
3822             {"",S_FALSE,FALSE},
3823             {"",S_FALSE,FALSE},
3824             {"",S_FALSE,FALSE},
3825             {"gov.uk",S_OK,FALSE},
3826             {"",S_OK,FALSE},
3827             {"/",S_OK,FALSE},
3828             {"/",S_OK,FALSE},
3829             {"",S_FALSE,FALSE},
3830             {"zip://:@gov.uk",S_OK,FALSE},
3831             {"zip",S_OK,FALSE},
3832             {":",S_OK,FALSE},
3833             {"",S_FALSE,FALSE}
3834         },
3835         {
3836             {Uri_HOST_DNS,S_OK,FALSE},
3837             {0,S_FALSE,FALSE},
3838             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
3839             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3840         }
3841     },
3842     {   "about:blank", 0, S_OK, FALSE,
3843         {
3844             {"about:blank",S_OK,FALSE},
3845             {"",S_FALSE,FALSE},
3846             {"about:blank",S_OK,FALSE},
3847             {"",S_FALSE,FALSE},
3848             {"",S_FALSE,FALSE},
3849             {"",S_FALSE,FALSE},
3850             {"",S_FALSE,FALSE},
3851             {"",S_FALSE,FALSE},
3852             {"blank",S_OK,FALSE},
3853             {"blank",S_OK,FALSE},
3854             {"",S_FALSE,FALSE},
3855             {"about:blank",S_OK,FALSE},
3856             {"about",S_OK,FALSE},
3857             {"",S_FALSE,FALSE},
3858             {"",S_FALSE,FALSE}
3859         },
3860         {
3861             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3862             {0,S_FALSE,FALSE},
3863             {URL_SCHEME_ABOUT,S_OK,FALSE},
3864             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3865         }
3866     },
3867     {   "mk:@MSITStore:C:\\Program Files/AutoCAD 2008\\Help/acad_acg.chm::/WSfacf1429558a55de1a7524c1004e616f8b-322b.htm",0,S_OK,FALSE,
3868         {
3869             {"mk:@MSITStore:C:\\Program%20Files/AutoCAD%202008\\Help/acad_acg.chm::/WSfacf1429558a55de1a7524c1004e616f8b-322b.htm",S_OK,FALSE},
3870             {"",S_FALSE,FALSE},
3871             {"mk:@MSITStore:C:\\Program%20Files/AutoCAD%202008\\Help/acad_acg.chm::/WSfacf1429558a55de1a7524c1004e616f8b-322b.htm",S_OK,FALSE},
3872             {"",S_FALSE,FALSE},
3873             {".htm",S_OK,FALSE},
3874             {"",S_FALSE,FALSE},
3875             {"",S_FALSE,FALSE},
3876             {"",S_FALSE,FALSE},
3877             {"@MSITStore:C:\\Program%20Files/AutoCAD%202008\\Help/acad_acg.chm::/WSfacf1429558a55de1a7524c1004e616f8b-322b.htm",S_OK,FALSE},
3878             {"@MSITStore:C:\\Program%20Files/AutoCAD%202008\\Help/acad_acg.chm::/WSfacf1429558a55de1a7524c1004e616f8b-322b.htm",S_OK,FALSE},
3879             {"",S_FALSE,FALSE},
3880             {"mk:@MSITStore:C:\\Program Files/AutoCAD 2008\\Help/acad_acg.chm::/WSfacf1429558a55de1a7524c1004e616f8b-322b.htm",S_OK,FALSE},
3881             {"mk",S_OK,FALSE},
3882             {"",S_FALSE,FALSE},
3883             {"",S_FALSE,FALSE}
3884         },
3885         {
3886             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3887             {0,S_FALSE,FALSE},
3888             {URL_SCHEME_MK,S_OK,FALSE},
3889             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3890         }
3891     },
3892     {   "mk:@MSITStore:Z:\\home\\test\\chm\\silqhelp.chm::/thesilqquickstartguide.htm",0,S_OK,FALSE,
3893         {
3894             {"mk:@MSITStore:Z:\\home\\test\\chm\\silqhelp.chm::/thesilqquickstartguide.htm",S_OK,FALSE},
3895             {"",S_FALSE,FALSE},
3896             {"mk:@MSITStore:Z:\\home\\test\\chm\\silqhelp.chm::/thesilqquickstartguide.htm",S_OK,FALSE},
3897             {"",S_FALSE,FALSE},
3898             {".htm",S_OK,FALSE},
3899             {"",S_FALSE,FALSE},
3900             {"",S_FALSE,FALSE},
3901             {"",S_FALSE,FALSE},
3902             {"@MSITStore:Z:\\home\\test\\chm\\silqhelp.chm::/thesilqquickstartguide.htm",S_OK,FALSE},
3903             {"@MSITStore:Z:\\home\\test\\chm\\silqhelp.chm::/thesilqquickstartguide.htm",S_OK,FALSE},
3904             {"",S_FALSE,FALSE},
3905             {"mk:@MSITStore:Z:\\home\\test\\chm\\silqhelp.chm::/thesilqquickstartguide.htm",S_OK,FALSE},
3906             {"mk",S_OK,FALSE},
3907             {"",S_FALSE,FALSE},
3908             {"",S_FALSE,FALSE}
3909         },
3910         {
3911             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3912             {0,S_FALSE,FALSE},
3913             {URL_SCHEME_MK,S_OK,FALSE},
3914             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3915         }
3916     },
3917     /* Two '\' are added to the URI when USE_DOS_PATH is set, and it's a UNC path. */
3918     {   "file://server/dir/index.html", Uri_CREATE_FILE_USE_DOS_PATH, S_OK, FALSE,
3919         {
3920             {"file://\\\\server\\dir\\index.html",S_OK,FALSE},
3921             {"server",S_OK,FALSE},
3922             {"file://\\\\server\\dir\\index.html",S_OK,FALSE},
3923             {"",S_FALSE,FALSE},
3924             {".html",S_OK,FALSE},
3925             {"",S_FALSE,FALSE},
3926             {"server",S_OK,FALSE},
3927             {"",S_FALSE,FALSE},
3928             {"\\dir\\index.html",S_OK,FALSE},
3929             {"\\dir\\index.html",S_OK,FALSE},
3930             {"",S_FALSE,FALSE},
3931             {"file://server/dir/index.html",S_OK,FALSE},
3932             {"file",S_OK,FALSE},
3933             {"",S_FALSE,FALSE},
3934             {"",S_FALSE,FALSE}
3935         },
3936         {
3937             {Uri_HOST_DNS,S_OK,FALSE},
3938             {0,S_FALSE,FALSE},
3939             {URL_SCHEME_FILE,S_OK,FALSE},
3940             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3941         }
3942     },
3943     /* When CreateUri generates an IUri, it still displays the default port in the
3944      * authority.
3945      */
3946     {   "http://google.com:80/", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
3947         {
3948             {"http://google.com:80/",S_OK,FALSE},
3949             {"google.com:80",S_OK,FALSE},
3950             {"http://google.com:80/",S_OK,FALSE},
3951             {"google.com",S_OK,FALSE},
3952             {"",S_FALSE,FALSE},
3953             {"",S_FALSE,FALSE},
3954             {"google.com",S_OK,FALSE},
3955             {"",S_FALSE,FALSE},
3956             {"/",S_OK,FALSE},
3957             {"/",S_OK,FALSE},
3958             {"",S_FALSE,FALSE},
3959             {"http://google.com:80/",S_OK,FALSE},
3960             {"http",S_OK,FALSE},
3961             {"",S_FALSE,FALSE},
3962             {"",S_FALSE,FALSE}
3963         },
3964         {
3965             {Uri_HOST_DNS,S_OK,FALSE},
3966             {80,S_OK,FALSE},
3967             {URL_SCHEME_HTTP,S_OK,FALSE},
3968             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3969         }
3970     },
3971     /* For res URIs the host is everything up until the first '/'. */
3972     {   "res://C:\\dir\\file.exe/DATA/test.html", 0, S_OK, FALSE,
3973         {
3974             {"res://C:\\dir\\file.exe/DATA/test.html",S_OK,FALSE},
3975             {"C:\\dir\\file.exe",S_OK,FALSE},
3976             {"res://C:\\dir\\file.exe/DATA/test.html",S_OK,FALSE},
3977             {"",S_FALSE,FALSE},
3978             {".html",S_OK,FALSE},
3979             {"",S_FALSE,FALSE},
3980             {"C:\\dir\\file.exe",S_OK,FALSE},
3981             {"",S_FALSE,FALSE},
3982             {"/DATA/test.html",S_OK,FALSE},
3983             {"/DATA/test.html",S_OK,FALSE},
3984             {"",S_FALSE,FALSE},
3985             {"res://C:\\dir\\file.exe/DATA/test.html",S_OK,FALSE},
3986             {"res",S_OK,FALSE},
3987             {"",S_FALSE,FALSE},
3988             {"",S_FALSE,FALSE}
3989         },
3990         {
3991             {Uri_HOST_UNKNOWN,S_OK,FALSE},
3992             {0,S_FALSE,FALSE},
3993             {URL_SCHEME_RES,S_OK,FALSE},
3994             {URLZONE_INVALID,E_NOTIMPL,FALSE}
3995         }
3996     },
3997     /* Res URI can contain a '|' in the host name. */
3998     {   "res://c:\\di|r\\file.exe/test", 0, S_OK, FALSE,
3999         {
4000             {"res://c:\\di|r\\file.exe/test",S_OK,FALSE},
4001             {"c:\\di|r\\file.exe",S_OK,FALSE},
4002             {"res://c:\\di|r\\file.exe/test",S_OK,FALSE},
4003             {"",S_FALSE,FALSE},
4004             {"",S_FALSE,FALSE},
4005             {"",S_FALSE,FALSE},
4006             {"c:\\di|r\\file.exe",S_OK,FALSE},
4007             {"",S_FALSE,FALSE},
4008             {"/test",S_OK,FALSE},
4009             {"/test",S_OK,FALSE},
4010             {"",S_FALSE,FALSE},
4011             {"res://c:\\di|r\\file.exe/test",S_OK,FALSE},
4012             {"res",S_OK,FALSE},
4013             {"",S_FALSE,FALSE},
4014             {"",S_FALSE,FALSE}
4015         },
4016         {
4017             {Uri_HOST_UNKNOWN,S_OK,FALSE},
4018             {0,S_FALSE,FALSE},
4019             {URL_SCHEME_RES,S_OK,FALSE},
4020             {URLZONE_INVALID,E_NOTIMPL,FALSE},
4021         }
4022     },
4023     /* Res URIs can have invalid percent encoded values. */
4024     {   "res://c:\\dir%xx\\file.exe/test", 0, S_OK, FALSE,
4025         {
4026             {"res://c:\\dir%xx\\file.exe/test",S_OK,FALSE},
4027             {"c:\\dir%xx\\file.exe",S_OK,FALSE},
4028             {"res://c:\\dir%xx\\file.exe/test",S_OK,FALSE},
4029             {"",S_FALSE,FALSE},
4030             {"",S_FALSE,FALSE},
4031             {"",S_FALSE,FALSE},
4032             {"c:\\dir%xx\\file.exe",S_OK,FALSE},
4033             {"",S_FALSE,FALSE},
4034             {"/test",S_OK,FALSE},
4035             {"/test",S_OK,FALSE},
4036             {"",S_FALSE,FALSE},
4037             {"res://c:\\dir%xx\\file.exe/test",S_OK,FALSE},
4038             {"res",S_OK,FALSE},
4039             {"",S_FALSE,FALSE},
4040             {"",S_FALSE,FALSE}
4041         },
4042         {
4043             {Uri_HOST_UNKNOWN,S_OK,FALSE},
4044             {0,S_FALSE,FALSE},
4045             {URL_SCHEME_RES,S_OK,FALSE},
4046             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4047         }
4048     },
4049     /* Res doesn't get forbidden characters percent encoded in it's path. */
4050     {   "res://c:\\test/tes<|>t", 0, S_OK, FALSE,
4051         {
4052             {"res://c:\\test/tes<|>t",S_OK,FALSE},
4053             {"c:\\test",S_OK,FALSE},
4054             {"res://c:\\test/tes<|>t",S_OK,FALSE},
4055             {"",S_FALSE,FALSE},
4056             {"",S_FALSE,FALSE},
4057             {"",S_FALSE,FALSE},
4058             {"c:\\test",S_OK,FALSE},
4059             {"",S_FALSE,FALSE},
4060             {"/tes<|>t",S_OK,FALSE},
4061             {"/tes<|>t",S_OK,FALSE},
4062             {"",S_FALSE,FALSE},
4063             {"res://c:\\test/tes<|>t",S_OK,FALSE},
4064             {"res",S_OK,FALSE},
4065             {"",S_FALSE,FALSE},
4066             {"",S_FALSE,FALSE}
4067         },
4068         {
4069             {Uri_HOST_UNKNOWN,S_OK,FALSE},
4070             {0,S_FALSE,FALSE},
4071             {URL_SCHEME_RES,S_OK,FALSE},
4072             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4073         }
4074     },
4075     {   "mk:@MSITStore:Z:\\dir\\test.chm::/html/../images/xxx.jpg", 0, S_OK, FALSE,
4076         {
4077             {"mk:@MSITStore:Z:\\dir\\test.chm::/images/xxx.jpg",S_OK,FALSE},
4078             {"",S_FALSE,FALSE},
4079             {"mk:@MSITStore:Z:\\dir\\test.chm::/images/xxx.jpg",S_OK,FALSE},
4080             {"",S_FALSE,FALSE},
4081             {".jpg",S_OK,FALSE},
4082             {"",S_FALSE,FALSE},
4083             {"",S_FALSE,FALSE},
4084             {"",S_FALSE,FALSE},
4085             {"@MSITStore:Z:\\dir\\test.chm::/images/xxx.jpg",S_OK,FALSE},
4086             {"@MSITStore:Z:\\dir\\test.chm::/images/xxx.jpg",S_OK,FALSE},
4087             {"",S_FALSE,FALSE},
4088             {"mk:@MSITStore:Z:\\dir\\test.chm::/html/../images/xxx.jpg",S_OK,FALSE},
4089             {"mk",S_OK,FALSE},
4090             {"",S_FALSE,FALSE},
4091             {"",S_FALSE,FALSE}
4092         },
4093         {
4094             {Uri_HOST_UNKNOWN,S_OK,FALSE},
4095             {0,S_FALSE,FALSE},
4096             {URL_SCHEME_MK,S_OK,FALSE},
4097             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4098         }
4099     },
4100     {   "mk:@MSITStore:Z:\\dir\\test.chm::/html/../images/xxx.jpg", Uri_CREATE_NO_CANONICALIZE, S_OK, FALSE,
4101         {
4102             {"mk:@MSITStore:Z:\\dir\\test.chm::/html/../images/xxx.jpg",S_OK,FALSE},
4103             {"",S_FALSE,FALSE},
4104             {"mk:@MSITStore:Z:\\dir\\test.chm::/html/../images/xxx.jpg",S_OK,FALSE},
4105             {"",S_FALSE,FALSE},
4106             {".jpg",S_OK,FALSE},
4107             {"",S_FALSE,FALSE},
4108             {"",S_FALSE,FALSE},
4109             {"",S_FALSE,FALSE},
4110             {"@MSITStore:Z:\\dir\\test.chm::/html/../images/xxx.jpg",S_OK,FALSE},
4111             {"@MSITStore:Z:\\dir\\test.chm::/html/../images/xxx.jpg",S_OK,FALSE},
4112             {"",S_FALSE,FALSE},
4113             {"mk:@MSITStore:Z:\\dir\\test.chm::/html/../images/xxx.jpg",S_OK,FALSE},
4114             {"mk",S_OK,FALSE},
4115             {"",S_FALSE,FALSE},
4116             {"",S_FALSE,FALSE}
4117         },
4118         {
4119             {Uri_HOST_UNKNOWN,S_OK,FALSE},
4120             {0,S_FALSE,FALSE},
4121             {URL_SCHEME_MK,S_OK,FALSE},
4122             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4123         }
4124     },
4125     {   "xx:@MSITStore:Z:\\dir\\test.chm::/html/../images/xxx.jpg", 0, S_OK, FALSE,
4126         {
4127             {"xx:@MSITStore:Z:\\dir\\test.chm::/html/../images/xxx.jpg",S_OK,FALSE},
4128             {"",S_FALSE,FALSE},
4129             {"xx:@MSITStore:Z:\\dir\\test.chm::/html/../images/xxx.jpg",S_OK,FALSE},
4130             {"",S_FALSE,FALSE},
4131             {".jpg",S_OK,FALSE},
4132             {"",S_FALSE,FALSE},
4133             {"",S_FALSE,FALSE},
4134             {"",S_FALSE,FALSE},
4135             {"@MSITStore:Z:\\dir\\test.chm::/html/../images/xxx.jpg",S_OK,FALSE},
4136             {"@MSITStore:Z:\\dir\\test.chm::/html/../images/xxx.jpg",S_OK,FALSE},
4137             {"",S_FALSE,FALSE},
4138             {"xx:@MSITStore:Z:\\dir\\test.chm::/html/../images/xxx.jpg",S_OK,FALSE},
4139             {"xx",S_OK,FALSE},
4140             {"",S_FALSE,FALSE},
4141             {"",S_FALSE,FALSE}
4142         },
4143         {
4144             {Uri_HOST_UNKNOWN,S_OK,FALSE},
4145             {0,S_FALSE,FALSE},
4146             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
4147             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4148         }
4149     },
4150     {   "mk:@MSITStore:Z:\\dir\\test.chm::/html/../../images/xxx.jpg", 0, S_OK, FALSE,
4151         {
4152             {"mk:@MSITStore:Z:\\dir\\images/xxx.jpg",S_OK,FALSE},
4153             {"",S_FALSE,FALSE},
4154             {"mk:@MSITStore:Z:\\dir\\images/xxx.jpg",S_OK,FALSE},
4155             {"",S_FALSE,FALSE},
4156             {".jpg",S_OK,FALSE},
4157             {"",S_FALSE,FALSE},
4158             {"",S_FALSE,FALSE},
4159             {"",S_FALSE,FALSE},
4160             {"@MSITStore:Z:\\dir\\images/xxx.jpg",S_OK,FALSE},
4161             {"@MSITStore:Z:\\dir\\images/xxx.jpg",S_OK,FALSE},
4162             {"",S_FALSE,FALSE},
4163             {"mk:@MSITStore:Z:\\dir\\test.chm::/html/../../images/xxx.jpg",S_OK,FALSE},
4164             {"mk",S_OK,FALSE},
4165             {"",S_FALSE,FALSE},
4166             {"",S_FALSE,FALSE}
4167         },
4168         {
4169             {Uri_HOST_UNKNOWN,S_OK,FALSE},
4170             {0,S_FALSE,FALSE},
4171             {URL_SCHEME_MK,S_OK,FALSE},
4172             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4173         }
4174     },
4175     {   "mk:@MSITStore:Z:\\dir\\dir2\\..\\test.chm::/html/../../images/xxx.jpg", 0, S_OK, FALSE,
4176         {
4177             {"mk:@MSITStore:Z:\\dir\\images/xxx.jpg",S_OK,FALSE},
4178             {"",S_FALSE,FALSE},
4179             {"mk:@MSITStore:Z:\\dir\\images/xxx.jpg",S_OK,FALSE},
4180             {"",S_FALSE,FALSE},
4181             {".jpg",S_OK,FALSE},
4182             {"",S_FALSE,FALSE},
4183             {"",S_FALSE,FALSE},
4184             {"",S_FALSE,FALSE},
4185             {"@MSITStore:Z:\\dir\\images/xxx.jpg",S_OK,FALSE},
4186             {"@MSITStore:Z:\\dir\\images/xxx.jpg",S_OK,FALSE},
4187             {"",S_FALSE,FALSE},
4188             {"mk:@MSITStore:Z:\\dir\\dir2\\..\\test.chm::/html/../../images/xxx.jpg",S_OK,FALSE},
4189             {"mk",S_OK,FALSE},
4190             {"",S_FALSE,FALSE},
4191             {"",S_FALSE,FALSE}
4192         },
4193         {
4194             {Uri_HOST_UNKNOWN,S_OK,FALSE},
4195             {0,S_FALSE,FALSE},
4196             {URL_SCHEME_MK,S_OK,FALSE},
4197             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4198         }
4199     },
4200     {   "mk:@MSITStore:Z:\\dir\\test.chm::/html/../../../../images/xxx.jpg", 0, S_OK, FALSE,
4201         {
4202             {"mk:images/xxx.jpg",S_OK,FALSE},
4203             {"",S_FALSE,FALSE},
4204             {"mk:images/xxx.jpg",S_OK,FALSE},
4205             {"",S_FALSE,FALSE},
4206             {".jpg",S_OK,FALSE},
4207             {"",S_FALSE,FALSE},
4208             {"",S_FALSE,FALSE},
4209             {"",S_FALSE,FALSE},
4210             {"images/xxx.jpg",S_OK,FALSE},
4211             {"images/xxx.jpg",S_OK,FALSE},
4212             {"",S_FALSE,FALSE},
4213             {"mk:@MSITStore:Z:\\dir\\test.chm::/html/../../../../images/xxx.jpg",S_OK,FALSE},
4214             {"mk",S_OK,FALSE},
4215             {"",S_FALSE,FALSE},
4216             {"",S_FALSE,FALSE}
4217         },
4218         {
4219             {Uri_HOST_UNKNOWN,S_OK,FALSE},
4220             {0,S_FALSE,FALSE},
4221             {URL_SCHEME_MK,S_OK,FALSE},
4222             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4223         }
4224     },
4225     {   "", Uri_CREATE_ALLOW_RELATIVE, S_OK, FALSE,
4226         {
4227             {"",S_OK,FALSE},
4228             {"",S_FALSE,FALSE},
4229             {"",S_OK,FALSE},
4230             {"",S_FALSE,FALSE},
4231             {"",S_FALSE,FALSE},
4232             {"",S_FALSE,FALSE},
4233             {"",S_FALSE,FALSE},
4234             {"",S_FALSE,FALSE},
4235             {"",S_OK,FALSE},
4236             {"",S_OK,FALSE},
4237             {"",S_FALSE,FALSE},
4238             {"",S_OK,FALSE},
4239             {"",S_FALSE,FALSE},
4240             {"",S_FALSE,FALSE},
4241             {"",S_FALSE,FALSE}
4242         },
4243         {
4244             {Uri_HOST_UNKNOWN,S_OK,FALSE},
4245             {0,S_FALSE,FALSE},
4246             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
4247             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4248         }
4249     },
4250     {   " \t ", Uri_CREATE_ALLOW_RELATIVE, S_OK, FALSE,
4251         {
4252             {"",S_OK,FALSE},
4253             {"",S_FALSE,FALSE},
4254             {"",S_OK,FALSE},
4255             {"",S_FALSE,FALSE},
4256             {"",S_FALSE,FALSE},
4257             {"",S_FALSE,FALSE},
4258             {"",S_FALSE,FALSE},
4259             {"",S_FALSE,FALSE},
4260             {"",S_OK,FALSE},
4261             {"",S_OK,FALSE},
4262             {"",S_FALSE,FALSE},
4263             {"",S_OK,FALSE},
4264             {"",S_FALSE,FALSE},
4265             {"",S_FALSE,FALSE},
4266             {"",S_FALSE,FALSE}
4267         },
4268         {
4269             {Uri_HOST_UNKNOWN,S_OK,FALSE},
4270             {0,S_FALSE,FALSE},
4271             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
4272             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4273         }
4274     },
4275     {   "javascript:void", 0, S_OK, FALSE,
4276         {
4277             {"javascript:void",S_OK},
4278             {"",S_FALSE},
4279             {"javascript:void",S_OK},
4280             {"",S_FALSE},
4281             {"",S_FALSE},
4282             {"",S_FALSE},
4283             {"",S_FALSE},
4284             {"",S_FALSE},
4285             {"void",S_OK},
4286             {"void",S_OK},
4287             {"",S_FALSE},
4288             {"javascript:void",S_OK},
4289             {"javascript",S_OK},
4290             {"",S_FALSE},
4291             {"",S_FALSE}
4292         },
4293         {
4294             {Uri_HOST_UNKNOWN,S_OK},
4295             {0,S_FALSE},
4296             {URL_SCHEME_JAVASCRIPT,S_OK},
4297             {URLZONE_INVALID,E_NOTIMPL}
4298         }
4299     },
4300     {   "javascript://undefined", 0, S_OK, FALSE,
4301         {
4302             {"javascript://undefined",S_OK},
4303             {"",S_FALSE},
4304             {"javascript://undefined",S_OK},
4305             {"",S_FALSE},
4306             {"",S_FALSE},
4307             {"",S_FALSE},
4308             {"",S_FALSE},
4309             {"",S_FALSE},
4310             {"//undefined",S_OK},
4311             {"//undefined",S_OK},
4312             {"",S_FALSE},
4313             {"javascript://undefined",S_OK},
4314             {"javascript",S_OK},
4315             {"",S_FALSE},
4316             {"",S_FALSE}
4317         },
4318         {
4319             {Uri_HOST_UNKNOWN,S_OK},
4320             {0,S_FALSE},
4321             {URL_SCHEME_JAVASCRIPT,S_OK},
4322             {URLZONE_INVALID,E_NOTIMPL}
4323         }
4324     },
4325     {   "JavaSCript:escape('/\\?#?')", 0, S_OK, FALSE,
4326         {
4327             {"javascript:escape('/\\?#?')",S_OK},
4328             {"",S_FALSE},
4329             {"javascript:escape('/\\?#?')",S_OK},
4330             {"",S_FALSE},
4331             {"",S_FALSE},
4332             {"",S_FALSE},
4333             {"",S_FALSE},
4334             {"",S_FALSE},
4335             {"escape('/\\?#?')",S_OK},
4336             {"escape('/\\?#?')",S_OK},
4337             {"",S_FALSE},
4338             {"JavaSCript:escape('/\\?#?')",S_OK},
4339             {"javascript",S_OK},
4340             {"",S_FALSE},
4341             {"",S_FALSE}
4342         },
4343         {
4344             {Uri_HOST_UNKNOWN,S_OK},
4345             {0,S_FALSE},
4346             {URL_SCHEME_JAVASCRIPT,S_OK},
4347             {URLZONE_INVALID,E_NOTIMPL}
4348         }
4349     },
4350     {   "*://google.com", 0, S_OK, FALSE,
4351         {
4352             {"*:google.com/",S_OK,FALSE},
4353             {"google.com",S_OK},
4354             {"*:google.com/",S_OK,FALSE},
4355             {"google.com",S_OK,FALSE},
4356             {"",S_FALSE,FALSE},
4357             {"",S_FALSE,FALSE},
4358             {"google.com",S_OK,FALSE},
4359             {"",S_FALSE,FALSE},
4360             {"/",S_OK,FALSE},
4361             {"/",S_OK,FALSE},
4362             {"",S_FALSE,FALSE},
4363             {"*://google.com",S_OK,FALSE},
4364             {"*",S_OK,FALSE},
4365             {"",S_FALSE,FALSE},
4366             {"",S_FALSE,FALSE}
4367         },
4368         {
4369             {Uri_HOST_DNS,S_OK,FALSE},
4370             {0,S_FALSE,FALSE},
4371             {URL_SCHEME_WILDCARD,S_OK,FALSE},
4372             {URLZONE_INVALID,E_NOTIMPL,FALSE}
4373         }
4374     },
4375     {   "mk:@MSITSTORE:C:\\Some\\Bogus\\Path.chm::/subdir/file.txt",0,S_OK,FALSE,
4376         {
4377             {"mk:@MSITSTORE:C:\\Some\\Bogus\\Path.chm::/subdir/file.txt",S_OK},
4378             {"",S_FALSE},
4379             {"mk:@MSITSTORE:C:\\Some\\Bogus\\Path.chm::/subdir/file.txt",S_OK},
4380             {"",S_FALSE},
4381             {".txt",S_OK},
4382             {"",S_FALSE},
4383             {"",S_FALSE},
4384             {"",S_FALSE},
4385             {"@MSITSTORE:C:\\Some\\Bogus\\Path.chm::/subdir/file.txt",S_OK},
4386             {"@MSITSTORE:C:\\Some\\Bogus\\Path.chm::/subdir/file.txt",S_OK},
4387             {"",S_FALSE},
4388             {"mk:@MSITSTORE:C:\\Some\\Bogus\\Path.chm::/subdir/file.txt",S_OK},
4389             {"mk",S_OK},
4390             {"",S_FALSE},
4391             {"",S_FALSE}
4392         },
4393         {
4394             {Uri_HOST_UNKNOWN,S_OK},
4395             {0,S_FALSE},
4396             {URL_SCHEME_MK,S_OK},
4397             {URLZONE_INVALID,E_NOTIMPL}
4398         }
4399     },
4400     {   "gopher://test.winehq.org:151/file.txt",0,S_OK,FALSE,
4401         {
4402             {"gopher://test.winehq.org:151/file.txt",S_OK},
4403             {"test.winehq.org:151",S_OK},
4404             {"gopher://test.winehq.org:151/file.txt",S_OK},
4405             {"winehq.org",S_OK},
4406             {".txt",S_OK},
4407             {"",S_FALSE},
4408             {"test.winehq.org",S_OK},
4409             {"",S_FALSE},
4410             {"/file.txt",S_OK},
4411             {"/file.txt",S_OK},
4412             {"",S_FALSE},
4413             {"gopher://test.winehq.org:151/file.txt",S_OK},
4414             {"gopher",S_OK},
4415             {"",S_FALSE},
4416             {"",S_FALSE}
4417         },
4418         {
4419             {Uri_HOST_DNS,S_OK},
4420             {151,S_OK},
4421             {URL_SCHEME_GOPHER,S_OK},
4422             {URLZONE_INVALID,E_NOTIMPL}
4423         }
4424     },
4425     {   "//host.com/path/file.txt?query", Uri_CREATE_ALLOW_RELATIVE, S_OK, FALSE,
4426         {
4427             {"//host.com/path/file.txt?query",S_OK},
4428             {"host.com",S_OK},
4429             {"//host.com/path/file.txt?query",S_OK},
4430             {"host.com",S_OK},
4431             {".txt",S_OK},
4432             {"",S_FALSE},
4433             {"host.com",S_OK},
4434             {"",S_FALSE},
4435             {"/path/file.txt",S_OK},
4436             {"/path/file.txt?query",S_OK},
4437             {"?query",S_OK},
4438             {"//host.com/path/file.txt?query",S_OK},
4439             {"",S_FALSE},
4440             {"",S_FALSE},
4441             {"",S_FALSE},
4442         },
4443         {
4444             {Uri_HOST_DNS,S_OK},
4445             {0,S_FALSE},
4446             {URL_SCHEME_UNKNOWN,S_OK},
4447             {URLZONE_INVALID,E_NOTIMPL}
4448         }
4449     },
4450     {   "//host/path/file.txt?query", Uri_CREATE_ALLOW_RELATIVE, S_OK, FALSE,
4451         {
4452             {"//host/path/file.txt?query",S_OK},
4453             {"host",S_OK},
4454             {"//host/path/file.txt?query",S_OK},
4455             {"",S_FALSE},
4456             {".txt",S_OK},
4457             {"",S_FALSE},
4458             {"host",S_OK},
4459             {"",S_FALSE},
4460             {"/path/file.txt",S_OK},
4461             {"/path/file.txt?query",S_OK},
4462             {"?query",S_OK},
4463             {"//host/path/file.txt?query",S_OK},
4464             {"",S_FALSE},
4465             {"",S_FALSE},
4466             {"",S_FALSE},
4467         },
4468         {
4469             {Uri_HOST_DNS,S_OK},
4470             {0,S_FALSE},
4471             {URL_SCHEME_UNKNOWN,S_OK},
4472             {URLZONE_INVALID,E_NOTIMPL}
4473         }
4474     },
4475     {   "//host", Uri_CREATE_ALLOW_RELATIVE, S_OK, FALSE,
4476         {
4477             {"//host/",S_OK},
4478             {"host",S_OK},
4479             {"//host/",S_OK},
4480             {"",S_FALSE},
4481             {"",S_FALSE},
4482             {"",S_FALSE},
4483             {"host",S_OK},
4484             {"",S_FALSE},
4485             {"/",S_OK},
4486             {"/",S_OK},
4487             {"",S_FALSE},
4488             {"//host",S_OK},
4489             {"",S_FALSE},
4490             {"",S_FALSE},
4491             {"",S_FALSE},
4492         },
4493         {
4494             {Uri_HOST_DNS,S_OK},
4495             {0,S_FALSE},
4496             {URL_SCHEME_UNKNOWN,S_OK},
4497             {URLZONE_INVALID,E_NOTIMPL}
4498         }
4499     }
4500 };
4501
4502 typedef struct _invalid_uri {
4503     const char* uri;
4504     DWORD       flags;
4505     BOOL        todo;
4506 } invalid_uri;
4507
4508 static const invalid_uri invalid_uri_tests[] = {
4509     /* Has to have a scheme name. */
4510     {"://www.winehq.org",0,FALSE},
4511     /* Window's doesn't like URI's which are implicitly file paths without the
4512      * ALLOW_IMPLICIT_FILE_SCHEME flag set.
4513      */
4514     {"C:/test/test.mp3",0,FALSE},
4515     {"\\\\Server/test/test.mp3",0,FALSE},
4516     {"C:/test/test.mp3",Uri_CREATE_ALLOW_IMPLICIT_WILDCARD_SCHEME,FALSE},
4517     {"\\\\Server/test/test.mp3",Uri_CREATE_ALLOW_RELATIVE,FALSE},
4518     /* Invalid schemes. */
4519     {"*abcd://not.valid.com",0,FALSE},
4520     {"*a*b*c*d://not.valid.com",0,FALSE},
4521     /* Not allowed to have invalid % encoded data. */
4522     {"ftp://google.co%XX/",0,FALSE},
4523     /* To many h16 components. */
4524     {"http://[1:2:3:4:5:6:7:8:9]",0,FALSE},
4525     /* Not enough room for IPv4 address. */
4526     {"http://[1:2:3:4:5:6:7:192.0.1.0]",0,FALSE},
4527     /* Not enough h16 components. */
4528     {"http://[1:2:3:4]",0,FALSE},
4529     /* Not enough components including IPv4. */
4530     {"http://[1:192.0.1.0]",0,FALSE},
4531     /* Not allowed to have partial IPv4 in IPv6. */
4532     {"http://[::192.0]",0,FALSE},
4533     /* Can't have elision of 1 h16 at beginning of address. */
4534     {"http://[::2:3:4:5:6:7:8]",0,FALSE},
4535     /* Can't have elision of 1 h16 at end of address. */
4536     {"http://[1:2:3:4:5:6:7::]",0,FALSE},
4537     /* Expects a valid IP Literal. */
4538     {"ftp://[not.valid.uri]/",0,FALSE},
4539     /* Expects valid port for a known scheme type. */
4540     {"ftp://www.winehq.org:123fgh",0,FALSE},
4541     /* Port exceeds USHORT_MAX for known scheme type. */
4542     {"ftp://www.winehq.org:65536",0,FALSE},
4543     /* Invalid port with IPv4 address. */
4544     {"http://www.winehq.org:1abcd",0,FALSE},
4545     /* Invalid port with IPv6 address. */
4546     {"http://[::ffff]:32xy",0,FALSE},
4547     /* Not allowed to have backslashes with NO_CANONICALIZE. */
4548     {"gopher://www.google.com\\test",Uri_CREATE_NO_CANONICALIZE,FALSE},
4549     /* Not allowed to have invalid % encoded data in opaque URI path. */
4550     {"news:test%XX",0,FALSE},
4551     {"mailto:wine@winehq%G8.com",0,FALSE},
4552     /* Known scheme types can't have invalid % encoded data in query string. */
4553     {"http://google.com/?query=te%xx",0,FALSE},
4554     /* Invalid % encoded data in fragment of know scheme type. */
4555     {"ftp://google.com/#Test%xx",0,FALSE},
4556     {"  http://google.com/",Uri_CREATE_NO_PRE_PROCESS_HTML_URI,FALSE},
4557     {"\n\nhttp://google.com/",Uri_CREATE_NO_PRE_PROCESS_HTML_URI,FALSE},
4558     {"file://c:\\test<test",Uri_CREATE_FILE_USE_DOS_PATH,FALSE},
4559     {"file://c:\\test>test",Uri_CREATE_FILE_USE_DOS_PATH,FALSE},
4560     {"file://c:\\test\"test",Uri_CREATE_FILE_USE_DOS_PATH,FALSE},
4561     {"file:c:\\test<test",Uri_CREATE_FILE_USE_DOS_PATH,FALSE},
4562     {"file:c:\\test>test",Uri_CREATE_FILE_USE_DOS_PATH,FALSE},
4563     {"file:c:\\test\"test",Uri_CREATE_FILE_USE_DOS_PATH,FALSE},
4564     /* res URIs aren't allowed to have forbidden dos path characters in the
4565      * hostname.
4566      */
4567     {"res://c:\\te<st\\test/test",0,FALSE},
4568     {"res://c:\\te>st\\test/test",0,FALSE},
4569     {"res://c:\\te\"st\\test/test",0,FALSE},
4570     {"res://c:\\test/te%xxst",0,FALSE}
4571 };
4572
4573 typedef struct _uri_equality {
4574     const char* a;
4575     DWORD       create_flags_a;
4576     const char* b;
4577     DWORD       create_flags_b;
4578     BOOL        equal;
4579     BOOL        todo;
4580 } uri_equality;
4581
4582 static const uri_equality equality_tests[] = {
4583     {
4584         "HTTP://www.winehq.org/test dir/./",0,
4585         "http://www.winehq.org/test dir/../test dir/",0,
4586         TRUE
4587     },
4588     {
4589         /* http://www.winehq.org/test%20dir */
4590         "http://%77%77%77%2E%77%69%6E%65%68%71%2E%6F%72%67/%74%65%73%74%20%64%69%72",0,
4591         "http://www.winehq.org/test dir",0,
4592         TRUE
4593     },
4594     {
4595         "c:\\test.mp3",Uri_CREATE_ALLOW_IMPLICIT_FILE_SCHEME,
4596         "file:///c:/test.mp3",0,
4597         TRUE
4598     },
4599     {
4600         "ftp://ftp.winehq.org/",0,
4601         "ftp://ftp.winehq.org",0,
4602         TRUE
4603     },
4604     {
4605         "ftp://ftp.winehq.org/test/test2/../../testB/",0,
4606         "ftp://ftp.winehq.org/t%45stB/",0,
4607         FALSE
4608     },
4609     {
4610         "http://google.com/TEST",0,
4611         "http://google.com/test",0,
4612         FALSE
4613     },
4614     {
4615         "http://GOOGLE.com/",0,
4616         "http://google.com/",0,
4617         TRUE
4618     },
4619     /* Performs case insensitive compare of host names (for known scheme types). */
4620     {
4621         "ftp://GOOGLE.com/",Uri_CREATE_NO_CANONICALIZE,
4622         "ftp://google.com/",0,
4623         TRUE
4624     },
4625     {
4626         "zip://GOOGLE.com/",0,
4627         "zip://google.com/",0,
4628         FALSE
4629     },
4630     {
4631         "file:///c:/TEST/TeST/",0,
4632         "file:///c:/test/test/",0,
4633         TRUE
4634     },
4635     {
4636         "file:///server/TEST",0,
4637         "file:///SERVER/TEST",0,
4638         TRUE
4639     },
4640     {
4641         "http://google.com",Uri_CREATE_NO_CANONICALIZE,
4642         "http://google.com/",0,
4643         TRUE
4644     },
4645     {
4646         "ftp://google.com:21/",0,
4647         "ftp://google.com/",0,
4648         TRUE
4649     },
4650     {
4651         "http://google.com:80/",Uri_CREATE_NO_CANONICALIZE,
4652         "http://google.com/",0,
4653         TRUE
4654     },
4655     {
4656         "http://google.com:70/",0,
4657         "http://google.com:71/",0,
4658         FALSE
4659     },
4660     {
4661         "file:///c:/dir/file.txt", 0,
4662         "file:///c:/dir/file.txt", Uri_CREATE_FILE_USE_DOS_PATH,
4663         TRUE
4664     },
4665     {
4666         "file:///c:/dir/file.txt", 0,
4667         "file:///c:\\dir\\file.txt", Uri_CREATE_NO_CANONICALIZE,
4668         TRUE
4669     },
4670     {
4671         "file:///c:/dir/file.txt", 0,
4672         "file:///c:\\dir2\\..\\dir\\file.txt", Uri_CREATE_NO_CANONICALIZE,
4673         TRUE
4674     },
4675     {
4676         "file:///c:\\dir2\\..\\ dir\\file.txt", Uri_CREATE_NO_CANONICALIZE,
4677         "file:///c:/%20dir/file.txt", 0,
4678         TRUE
4679     },
4680     {
4681         "file:///c:/Dir/file.txt", 0,
4682         "file:///C:/dir/file.TXT", Uri_CREATE_FILE_USE_DOS_PATH,
4683         TRUE
4684     },
4685     {
4686         "file:///c:/dir/file.txt", 0,
4687         "file:///c:\\dir\\file.txt", Uri_CREATE_FILE_USE_DOS_PATH,
4688         TRUE
4689     },
4690     {
4691         "file:///c:/dir/file.txt#a", 0,
4692         "file:///c:\\dir\\file.txt#b", Uri_CREATE_FILE_USE_DOS_PATH,
4693         FALSE
4694     },
4695     /* Tests of an empty hash/fragment part */
4696     {
4697         "http://google.com/test",0,
4698         "http://google.com/test#",0,
4699         FALSE
4700     },
4701     {
4702         "ftp://ftp.winehq.org/",0,
4703         "ftp://ftp.winehq.org/#",0,
4704         FALSE
4705     },
4706     {
4707         "file:///c:/dir/file.txt#", 0,
4708         "file:///c:\\dir\\file.txt", Uri_CREATE_FILE_USE_DOS_PATH,
4709         FALSE
4710     }
4711 };
4712
4713 typedef struct _uri_with_fragment {
4714     const char* uri;
4715     const char* fragment;
4716     DWORD       create_flags;
4717     HRESULT     create_expected;
4718     BOOL        create_todo;
4719
4720     const char* expected_uri;
4721     BOOL        expected_todo;
4722 } uri_with_fragment;
4723
4724 static const uri_with_fragment uri_fragment_tests[] = {
4725     {
4726         "http://google.com/","#fragment",0,S_OK,FALSE,
4727         "http://google.com/#fragment",FALSE
4728     },
4729     {
4730         "http://google.com/","fragment",0,S_OK,FALSE,
4731         "http://google.com/#fragment",FALSE
4732     },
4733     {
4734         "zip://test.com/","?test",0,S_OK,FALSE,
4735         "zip://test.com/#?test",FALSE
4736     },
4737     /* The fragment can be empty. */
4738     {
4739         "ftp://ftp.google.com/","",0,S_OK,FALSE,
4740         "ftp://ftp.google.com/#",FALSE
4741     }
4742 };
4743
4744 typedef struct _uri_builder_property {
4745     BOOL            change;
4746     const char      *value;
4747     const char      *expected_value;
4748     Uri_PROPERTY    property;
4749     HRESULT         expected;
4750     BOOL            todo;
4751 } uri_builder_property;
4752
4753 typedef struct _uri_builder_port {
4754     BOOL    change;
4755     BOOL    set;
4756     DWORD   value;
4757     HRESULT expected;
4758     BOOL    todo;
4759 } uri_builder_port;
4760
4761 typedef struct _uri_builder_str_property {
4762     const char* expected;
4763     HRESULT     result;
4764     BOOL        todo;
4765 } uri_builder_str_property;
4766
4767 typedef struct _uri_builder_dword_property {
4768     DWORD   expected;
4769     HRESULT result;
4770     BOOL    todo;
4771 } uri_builder_dword_property;
4772
4773 typedef struct _uri_builder_test {
4774     const char                  *uri;
4775     DWORD                       create_flags;
4776     HRESULT                     create_builder_expected;
4777     BOOL                        create_builder_todo;
4778
4779     uri_builder_property        properties[URI_BUILDER_STR_PROPERTY_COUNT];
4780
4781     uri_builder_port            port_prop;
4782
4783     DWORD                       uri_flags;
4784     HRESULT                     uri_hres;
4785     BOOL                        uri_todo;
4786
4787     DWORD                       uri_simple_encode_flags;
4788     HRESULT                     uri_simple_hres;
4789     BOOL                        uri_simple_todo;
4790
4791     DWORD                       uri_with_flags;
4792     DWORD                       uri_with_builder_flags;
4793     DWORD                       uri_with_encode_flags;
4794     HRESULT                     uri_with_hres;
4795     BOOL                        uri_with_todo;
4796
4797     uri_builder_str_property    expected_str_props[URI_STR_PROPERTY_COUNT];
4798     uri_builder_dword_property  expected_dword_props[URI_DWORD_PROPERTY_COUNT];
4799 } uri_builder_test;
4800
4801 static const uri_builder_test uri_builder_tests[] = {
4802     {   "http://google.com/",0,S_OK,FALSE,
4803         {
4804             {TRUE,"#fragment",NULL,Uri_PROPERTY_FRAGMENT,S_OK,FALSE},
4805             {TRUE,"password",NULL,Uri_PROPERTY_PASSWORD,S_OK,FALSE},
4806             {TRUE,"?query=x",NULL,Uri_PROPERTY_QUERY,S_OK,FALSE},
4807             {TRUE,"username",NULL,Uri_PROPERTY_USER_NAME,S_OK,FALSE}
4808         },
4809         {FALSE},
4810         0,S_OK,FALSE,
4811         0,S_OK,FALSE,
4812         0,0,0,S_OK,FALSE,
4813         {
4814             {"http://username:password@google.com/?query=x#fragment",S_OK},
4815             {"username:password@google.com",S_OK},
4816             {"http://google.com/?query=x#fragment",S_OK},
4817             {"google.com",S_OK},
4818             {"",S_FALSE},
4819             {"#fragment",S_OK},
4820             {"google.com",S_OK},
4821             {"password",S_OK},
4822             {"/",S_OK},
4823             {"/?query=x",S_OK},
4824             {"?query=x",S_OK},
4825             {"http://username:password@google.com/?query=x#fragment",S_OK},
4826             {"http",S_OK},
4827             {"username:password",S_OK},
4828             {"username",S_OK}
4829         },
4830         {
4831             {Uri_HOST_DNS,S_OK},
4832             {80,S_OK},
4833             {URL_SCHEME_HTTP,S_OK},
4834             {URLZONE_INVALID,E_NOTIMPL}
4835         }
4836     },
4837     {   "http://google.com/",0,S_OK,FALSE,
4838         {
4839             {TRUE,"test",NULL,Uri_PROPERTY_SCHEME_NAME,S_OK,FALSE}
4840         },
4841         {TRUE,TRUE,120,S_OK,FALSE},
4842         0,S_OK,FALSE,
4843         0,S_OK,FALSE,
4844         0,0,0,S_OK,FALSE,
4845         {
4846             {"test://google.com:120/",S_OK},
4847             {"google.com:120",S_OK},
4848             {"test://google.com:120/",S_OK},
4849             {"google.com",S_OK},
4850             {"",S_FALSE},
4851             {"",S_FALSE},
4852             {"google.com",S_OK},
4853             {"",S_FALSE},
4854             {"/",S_OK},
4855             {"/",S_OK},
4856             {"",S_FALSE},
4857             {"test://google.com:120/",S_OK},
4858             {"test",S_OK},
4859             {"",S_FALSE},
4860             {"",S_FALSE}
4861         },
4862         {
4863             {Uri_HOST_DNS,S_OK},
4864             {120,S_OK},
4865             {URL_SCHEME_UNKNOWN,S_OK},
4866             {URLZONE_INVALID,E_NOTIMPL}
4867         }
4868     },
4869     {   "/Test/test dir",Uri_CREATE_ALLOW_RELATIVE,S_OK,FALSE,
4870         {
4871             {TRUE,"http",NULL,Uri_PROPERTY_SCHEME_NAME,S_OK,FALSE},
4872             {TRUE,"::192.2.3.4",NULL,Uri_PROPERTY_HOST,S_OK,FALSE},
4873             {TRUE,NULL,NULL,Uri_PROPERTY_PATH,S_OK,FALSE}
4874         },
4875         {FALSE},
4876         0,S_OK,FALSE,
4877         0,S_OK,FALSE,
4878         0,0,0,S_OK,FALSE,
4879         {
4880             {"http://[::192.2.3.4]/",S_OK},
4881             {"[::192.2.3.4]",S_OK},
4882             {"http://[::192.2.3.4]/",S_OK},
4883             {"",S_FALSE},
4884             {"",S_FALSE},
4885             {"",S_FALSE},
4886             {"::192.2.3.4",S_OK},
4887             {"",S_FALSE},
4888             {"/",S_OK},
4889             {"/",S_OK},
4890             {"",S_FALSE},
4891             {"http://[::192.2.3.4]/",S_OK},
4892             {"http",S_OK},
4893             {"",S_FALSE},
4894             {"",S_FALSE}
4895         },
4896         {
4897             {Uri_HOST_IPV6,S_OK},
4898             {80,S_OK},
4899             {URL_SCHEME_HTTP,S_OK},
4900             {URLZONE_INVALID,E_NOTIMPL}
4901         }
4902     },
4903     {   "http://google.com/",0,S_OK,FALSE,
4904         {
4905             {TRUE,"Frag","#Frag",Uri_PROPERTY_FRAGMENT,S_OK,FALSE}
4906         },
4907         {FALSE},
4908         0,S_OK,FALSE,
4909         0,S_OK,FALSE,
4910         0,0,0,S_OK,FALSE,
4911         {
4912             {"http://google.com/#Frag",S_OK},
4913             {"google.com",S_OK},
4914             {"http://google.com/#Frag",S_OK},
4915             {"google.com",S_OK},
4916             {"",S_FALSE},
4917             {"#Frag",S_OK},
4918             {"google.com",S_OK},
4919             {"",S_FALSE},
4920             {"/",S_OK},
4921             {"/",S_OK},
4922             {"",S_FALSE},
4923             {"http://google.com/#Frag",S_OK},
4924             {"http",S_OK},
4925             {"",S_FALSE},
4926             {"",S_FALSE}
4927         },
4928         {
4929             {Uri_HOST_DNS,S_OK},
4930             {80,S_OK},
4931             {URL_SCHEME_HTTP,S_OK},
4932             {URLZONE_INVALID,E_NOTIMPL}
4933         }
4934     },
4935     {   "http://google.com/",0,S_OK,FALSE,
4936         {
4937             {TRUE,"","#",Uri_PROPERTY_FRAGMENT,S_OK,FALSE},
4938         },
4939         {FALSE},
4940         0,S_OK,FALSE,
4941         0,S_OK,FALSE,
4942         0,0,0,S_OK,FALSE,
4943         {
4944             {"http://google.com/#",S_OK},
4945             {"google.com",S_OK},
4946             {"http://google.com/#",S_OK},
4947             {"google.com",S_OK},
4948             {"",S_FALSE},
4949             {"#",S_OK},
4950             {"google.com",S_OK},
4951             {"",S_FALSE},
4952             {"/",S_OK},
4953             {"/",S_OK},
4954             {"",S_FALSE},
4955             {"http://google.com/#",S_OK},
4956             {"http",S_OK},
4957             {"",S_FALSE},
4958             {"",S_FALSE}
4959         },
4960         {
4961             {Uri_HOST_DNS,S_OK},
4962             {80,S_OK},
4963             {URL_SCHEME_HTTP,S_OK},
4964             {URLZONE_INVALID,E_NOTIMPL}
4965         }
4966     },
4967     {   "http://google.com/",0,S_OK,FALSE,
4968         {
4969             {TRUE,":password",NULL,Uri_PROPERTY_PASSWORD,S_OK,FALSE}
4970         },
4971         {FALSE},
4972         0,S_OK,FALSE,
4973         0,S_OK,FALSE,
4974         0,0,0,S_OK,FALSE,
4975         {
4976             {"http://::password@google.com/",S_OK},
4977             {"::password@google.com",S_OK},
4978             {"http://google.com/",S_OK},
4979             {"google.com",S_OK},
4980             {"",S_FALSE},
4981             {"",S_FALSE},
4982             {"google.com",S_OK},
4983             {":password",S_OK},
4984             {"/",S_OK},
4985             {"/",S_OK},
4986             {"",S_FALSE},
4987             {"http://::password@google.com/",S_OK},
4988             {"http",S_OK},
4989             {"::password",S_OK},
4990             {"",S_FALSE}
4991         },
4992         {
4993             {Uri_HOST_DNS,S_OK},
4994             {80,S_OK},
4995             {URL_SCHEME_HTTP,S_OK},
4996             {URLZONE_INVALID,E_NOTIMPL}
4997         }
4998     },
4999     {   "test/test",Uri_CREATE_ALLOW_RELATIVE,S_OK,FALSE,
5000         {
5001             {TRUE,"password",NULL,Uri_PROPERTY_PASSWORD,S_OK,FALSE}
5002         },
5003         {FALSE},
5004         Uri_CREATE_ALLOW_RELATIVE,S_OK,FALSE,
5005         0,S_OK,FALSE,
5006         Uri_CREATE_ALLOW_RELATIVE,0,0,S_OK,FALSE,
5007         {
5008             {":password@test/test",S_OK},
5009             {":password@",S_OK},
5010             {":password@test/test",S_OK},
5011             {"",S_FALSE},
5012             {"",S_FALSE},
5013             {"",S_FALSE},
5014             {"",S_FALSE},
5015             {"password",S_OK},
5016             {"test/test",S_OK},
5017             {"test/test",S_OK},
5018             {"",S_FALSE},
5019             {":password@test/test",S_OK},
5020             {"",S_FALSE},
5021             {":password",S_OK},
5022             {"",S_FALSE}
5023         },
5024         {
5025             {Uri_HOST_UNKNOWN,S_OK},
5026             {0,S_FALSE},
5027             {URL_SCHEME_UNKNOWN,S_OK},
5028             {URLZONE_INVALID,E_NOTIMPL}
5029         }
5030     },
5031     {   "http://google.com/",0,S_OK,FALSE,
5032         {
5033             {TRUE,"test/test",NULL,Uri_PROPERTY_PATH,S_OK,FALSE},
5034         },
5035         {FALSE},
5036         0,S_OK,FALSE,
5037         0,S_OK,FALSE,
5038         0,0,0,S_OK,FALSE,
5039         {
5040             {"http://google.com/test/test",S_OK},
5041             {"google.com",S_OK},
5042             {"http://google.com/test/test",S_OK},
5043             {"google.com",S_OK},
5044             {"",S_FALSE},
5045             {"",S_FALSE},
5046             {"google.com",S_OK},
5047             {"",S_FALSE},
5048             {"/test/test",S_OK},
5049             {"/test/test",S_OK},
5050             {"",S_FALSE},
5051             {"http://google.com/test/test",S_OK},
5052             {"http",S_OK},
5053             {"",S_FALSE},
5054             {"",S_FALSE}
5055         },
5056         {
5057             {Uri_HOST_DNS,S_OK},
5058             {80,S_OK},
5059             {URL_SCHEME_HTTP,S_OK},
5060             {URLZONE_INVALID,E_NOTIMPL}
5061         }
5062     },
5063     {   "zip:testing/test",0,S_OK,FALSE,
5064         {
5065             {TRUE,"test",NULL,Uri_PROPERTY_PATH,S_OK,FALSE},
5066         },
5067         {FALSE},
5068         0,S_OK,FALSE,
5069         0,S_OK,FALSE,
5070         0,0,0,S_OK,FALSE,
5071         {
5072             {"zip:test",S_OK},
5073             {"",S_FALSE},
5074             {"zip:test",S_OK},
5075             {"",S_FALSE},
5076             {"",S_FALSE},
5077             {"",S_FALSE},
5078             {"",S_FALSE},
5079             {"",S_FALSE},
5080             {"test",S_OK},
5081             {"test",S_OK},
5082             {"",S_FALSE},
5083             {"zip:test",S_OK},
5084             {"zip",S_OK},
5085             {"",S_FALSE},
5086             {"",S_FALSE}
5087         },
5088         {
5089             {Uri_HOST_UNKNOWN,S_OK},
5090             {0,S_FALSE},
5091             {URL_SCHEME_UNKNOWN,S_OK},
5092             {URLZONE_INVALID,E_NOTIMPL}
5093         }
5094     },
5095     {   "http://google.com/",0,S_OK,FALSE,
5096         {
5097             {FALSE},
5098         },
5099         /* 555 will be returned from GetPort even though FALSE was passed as the hasPort parameter. */
5100         {TRUE,FALSE,555,S_OK,FALSE},
5101         0,S_OK,FALSE,
5102         0,S_OK,FALSE,
5103         0,0,0,S_OK,FALSE,
5104         {
5105             {"http://google.com/",S_OK},
5106             {"google.com",S_OK},
5107             {"http://google.com/",S_OK},
5108             {"google.com",S_OK},
5109             {"",S_FALSE},
5110             {"",S_FALSE},
5111             {"google.com",S_OK},
5112             {"",S_FALSE},
5113             {"/",S_OK},
5114             {"/",S_OK},
5115             {"",S_FALSE},
5116             {"http://google.com/",S_OK},
5117             {"http",S_OK},
5118             {"",S_FALSE},
5119             {"",S_FALSE}
5120         },
5121         {
5122             {Uri_HOST_DNS,S_OK},
5123             /* Still returns 80, even though earlier the port was disabled. */
5124             {80,S_OK},
5125             {URL_SCHEME_HTTP,S_OK},
5126             {URLZONE_INVALID,E_NOTIMPL}
5127         }
5128     },
5129     {   "http://google.com/",0,S_OK,FALSE,
5130         {
5131             {FALSE},
5132         },
5133         /* Instead of getting "TRUE" back as the "hasPort" parameter in GetPort,
5134          * you'll get 122345 instead.
5135          */
5136         {TRUE,122345,222,S_OK,FALSE},
5137         0,S_OK,FALSE,
5138         0,S_OK,FALSE,
5139         0,0,0,S_OK,FALSE,
5140         {
5141             {"http://google.com:222/",S_OK},
5142             {"google.com:222",S_OK},
5143             {"http://google.com:222/",S_OK},
5144             {"google.com",S_OK},
5145             {"",S_FALSE},
5146             {"",S_FALSE},
5147             {"google.com",S_OK},
5148             {"",S_FALSE},
5149             {"/",S_OK},
5150             {"/",S_OK},
5151             {"",S_FALSE},
5152             {"http://google.com:222/",S_OK},
5153             {"http",S_OK},
5154             {"",S_FALSE},
5155             {"",S_FALSE}
5156         },
5157         {
5158             {Uri_HOST_DNS,S_OK},
5159             {222,S_OK},
5160             {URL_SCHEME_HTTP,S_OK},
5161             {URLZONE_INVALID,E_NOTIMPL}
5162         }
5163     },
5164     /* IUri's created with the IUriBuilder can have ports that exceed USHORT_MAX. */
5165     {   "http://google.com/",0,S_OK,FALSE,
5166         {
5167             {FALSE},
5168         },
5169         {TRUE,TRUE,999999,S_OK,FALSE},
5170         0,S_OK,FALSE,
5171         0,S_OK,FALSE,
5172         0,0,0,S_OK,FALSE,
5173         {
5174             {"http://google.com:999999/",S_OK},
5175             {"google.com:999999",S_OK},
5176             {"http://google.com:999999/",S_OK},
5177             {"google.com",S_OK},
5178             {"",S_FALSE},
5179             {"",S_FALSE},
5180             {"google.com",S_OK},
5181             {"",S_FALSE},
5182             {"/",S_OK},
5183             {"/",S_OK},
5184             {"",S_FALSE},
5185             {"http://google.com:999999/",S_OK},
5186             {"http",S_OK},
5187             {"",S_FALSE},
5188             {"",S_FALSE}
5189         },
5190         {
5191             {Uri_HOST_DNS,S_OK},
5192             {999999,S_OK},
5193             {URL_SCHEME_HTTP,S_OK},
5194             {URLZONE_INVALID,E_NOTIMPL}
5195         }
5196     },
5197     {   "http://google.com/",0,S_OK,FALSE,
5198         {
5199             {TRUE,"test","?test",Uri_PROPERTY_QUERY,S_OK,FALSE},
5200         },
5201
5202         {FALSE},
5203         0,S_OK,FALSE,
5204         0,S_OK,FALSE,
5205         0,0,0,S_OK,FALSE,
5206         {
5207             {"http://google.com/?test",S_OK},
5208             {"google.com",S_OK},
5209             {"http://google.com/?test",S_OK},
5210             {"google.com",S_OK},
5211             {"",S_FALSE},
5212             {"",S_FALSE},
5213             {"google.com",S_OK},
5214             {"",S_FALSE},
5215             {"/",S_OK},
5216             {"/?test",S_OK},
5217             {"?test",S_OK},
5218             {"http://google.com/?test",S_OK},
5219             {"http",S_OK},
5220             {"",S_FALSE},
5221             {"",S_FALSE}
5222         },
5223         {
5224             {Uri_HOST_DNS,S_OK},
5225             {80,S_OK},
5226             {URL_SCHEME_HTTP,S_OK},
5227             {URLZONE_INVALID,E_NOTIMPL}
5228         }
5229     },
5230     {   "http://:password@google.com/",0,S_OK,FALSE,
5231         {
5232             {FALSE},
5233         },
5234         {FALSE},
5235         0,S_OK,FALSE,
5236         0,S_OK,FALSE,
5237         0,0,0,S_OK,FALSE,
5238         {
5239             {"http://:password@google.com/",S_OK},
5240             {":password@google.com",S_OK},
5241             {"http://google.com/",S_OK},
5242             {"google.com",S_OK},
5243             {"",S_FALSE},
5244             {"",S_FALSE},
5245             {"google.com",S_OK},
5246             {"password",S_OK},
5247             {"/",S_OK},
5248             {"/",S_OK},
5249             {"",S_FALSE},
5250             {"http://:password@google.com/",S_OK},
5251             {"http",S_OK},
5252             {":password",S_OK},
5253             {"",S_FALSE}
5254         },
5255         {
5256             {Uri_HOST_DNS,S_OK},
5257             {80,S_OK},
5258             {URL_SCHEME_HTTP,S_OK},
5259             {URLZONE_INVALID,E_NOTIMPL}
5260         }
5261     },
5262     /* IUriBuilder doesn't need a base IUri to build a IUri. */
5263     {   NULL,0,S_OK,FALSE,
5264         {
5265             {TRUE,"http",NULL,Uri_PROPERTY_SCHEME_NAME,S_OK,FALSE},
5266             {TRUE,"google.com",NULL,Uri_PROPERTY_HOST,S_OK,FALSE}
5267         },
5268         {FALSE},
5269         0,S_OK,FALSE,
5270         0,S_OK,FALSE,
5271         0,0,0,S_OK,FALSE,
5272         {
5273             {"http://google.com/",S_OK},
5274             {"google.com",S_OK},
5275             {"http://google.com/",S_OK},
5276             {"google.com",S_OK},
5277             {"",S_FALSE},
5278             {"",S_FALSE},
5279             {"google.com",S_OK},
5280             {"",S_FALSE},
5281             {"/",S_OK},
5282             {"/",S_OK},
5283             {"",S_FALSE},
5284             {"http://google.com/",S_OK},
5285             {"http",S_OK},
5286             {"",S_FALSE},
5287             {"",S_FALSE}
5288         },
5289         {
5290             {Uri_HOST_DNS,S_OK},
5291             {80,S_OK},
5292             {URL_SCHEME_HTTP,S_OK},
5293             {URLZONE_INVALID,E_NOTIMPL}
5294         }
5295     },
5296     /* Can't set the scheme name to NULL. */
5297     {   "zip://google.com/",0,S_OK,FALSE,
5298         {
5299             {TRUE,NULL,"zip",Uri_PROPERTY_SCHEME_NAME,E_INVALIDARG,FALSE}
5300         },
5301         {FALSE},
5302         0,S_OK,FALSE,
5303         0,S_OK,FALSE,
5304         0,0,0,S_OK,FALSE,
5305         {
5306             {"zip://google.com/",S_OK},
5307             {"google.com",S_OK},
5308             {"zip://google.com/",S_OK},
5309             {"google.com",S_OK},
5310             {"",S_FALSE},
5311             {"",S_FALSE},
5312             {"google.com",S_OK},
5313             {"",S_FALSE},
5314             {"/",S_OK},
5315             {"/",S_OK},
5316             {"",S_FALSE},
5317             {"zip://google.com/",S_OK},
5318             {"zip",S_OK},
5319             {"",S_FALSE},
5320             {"",S_FALSE}
5321         },
5322         {
5323             {Uri_HOST_DNS,S_OK},
5324             {0,S_FALSE},
5325             {URL_SCHEME_UNKNOWN,S_OK},
5326             {URLZONE_INVALID,E_NOTIMPL}
5327         }
5328     },
5329     /* Can't set the scheme name to an empty string. */
5330     {   "zip://google.com/",0,S_OK,FALSE,
5331         {
5332             {TRUE,"","zip",Uri_PROPERTY_SCHEME_NAME,E_INVALIDARG,FALSE}
5333         },
5334         {FALSE},
5335         0,S_OK,FALSE,
5336         0,S_OK,FALSE,
5337         0,0,0,S_OK,FALSE,
5338         {
5339             {"zip://google.com/",S_OK},
5340             {"google.com",S_OK},
5341             {"zip://google.com/",S_OK},
5342             {"google.com",S_OK},
5343             {"",S_FALSE},
5344             {"",S_FALSE},
5345             {"google.com",S_OK},
5346             {"",S_FALSE},
5347             {"/",S_OK},
5348             {"/",S_OK},
5349             {"",S_FALSE},
5350             {"zip://google.com/",S_OK},
5351             {"zip",S_OK},
5352             {"",S_FALSE},
5353             {"",S_FALSE}
5354         },
5355         {
5356             {Uri_HOST_DNS,S_OK},
5357             {0,S_FALSE},
5358             {URL_SCHEME_UNKNOWN,S_OK},
5359             {URLZONE_INVALID,E_NOTIMPL}
5360         }
5361     },
5362     /* -1 to CreateUri makes it use the same flags as the base IUri was created with.
5363      * CreateUriSimple always uses the flags the base IUri was created with (if any).
5364      */
5365     {   "http://google.com/../../",Uri_CREATE_NO_CANONICALIZE,S_OK,FALSE,
5366         {{FALSE}},
5367         {FALSE},
5368         -1,S_OK,FALSE,
5369         0,S_OK,FALSE,
5370         0,UriBuilder_USE_ORIGINAL_FLAGS,0,S_OK,FALSE,
5371         {
5372             {"http://google.com/../../",S_OK},
5373             {"google.com",S_OK},
5374             {"http://google.com/../../",S_OK},
5375             {"google.com",S_OK},
5376             {"",S_FALSE},
5377             {"",S_FALSE},
5378             {"google.com",S_OK},
5379             {"",S_FALSE},
5380             {"/../../",S_OK},
5381             {"/../../",S_OK},
5382             {"",S_FALSE},
5383             {"http://google.com/../../",S_OK},
5384             {"http",S_OK},
5385             {"",S_FALSE},
5386             {"",S_FALSE}
5387         },
5388         {
5389             {Uri_HOST_DNS,S_OK},
5390             {80,S_OK},
5391             {URL_SCHEME_HTTP,S_OK},
5392             {URLZONE_INVALID,E_NOTIMPL}
5393         }
5394     },
5395     {   "http://google.com/",0,S_OK,FALSE,
5396         {
5397             {TRUE,"#Fr<|>g",NULL,Uri_PROPERTY_FRAGMENT,S_OK,FALSE}
5398         },
5399         {FALSE},
5400         -1,S_OK,FALSE,
5401         0,S_OK,FALSE,
5402         Uri_CREATE_NO_DECODE_EXTRA_INFO,UriBuilder_USE_ORIGINAL_FLAGS,0,S_OK,FALSE,
5403         {
5404             {"http://google.com/#Fr%3C%7C%3Eg",S_OK},
5405             {"google.com",S_OK},
5406             {"http://google.com/#Fr%3C%7C%3Eg",S_OK},
5407             {"google.com",S_OK},
5408             {"",S_FALSE},
5409             {"#Fr%3C%7C%3Eg",S_OK},
5410             {"google.com",S_OK},
5411             {"",S_FALSE},
5412             {"/",S_OK},
5413             {"/",S_OK},
5414             {"",S_FALSE},
5415             {"http://google.com/#Fr<|>g",S_OK},
5416             {"http",S_OK},
5417             {"",S_FALSE},
5418             {"",S_FALSE}
5419         },
5420         {
5421             {Uri_HOST_DNS,S_OK},
5422             {80,S_OK},
5423             {URL_SCHEME_HTTP,S_OK},
5424             {URLZONE_INVALID,E_NOTIMPL}
5425         }
5426     },
5427     {   "http://google.com/",0,S_OK,FALSE,
5428         {
5429             {TRUE,"#Fr<|>g",NULL,Uri_PROPERTY_FRAGMENT,S_OK,FALSE}
5430         },
5431         {FALSE},
5432         Uri_CREATE_CANONICALIZE|Uri_CREATE_NO_CANONICALIZE,E_INVALIDARG,FALSE,
5433         0,S_OK,FALSE,
5434         Uri_CREATE_CANONICALIZE|Uri_CREATE_NO_CANONICALIZE,UriBuilder_USE_ORIGINAL_FLAGS,0,S_OK,FALSE,
5435         {
5436             {"http://google.com/#Fr%3C%7C%3Eg",S_OK},
5437             {"google.com",S_OK},
5438             {"http://google.com/#Fr%3C%7C%3Eg",S_OK},
5439             {"google.com",S_OK},
5440             {"",S_FALSE},
5441             {"#Fr%3C%7C%3Eg",S_OK},
5442             {"google.com",S_OK},
5443             {"",S_FALSE},
5444             {"/",S_OK},
5445             {"/",S_OK},
5446             {"",S_FALSE},
5447             {"http://google.com/#Fr<|>g",S_OK},
5448             {"http",S_OK},
5449             {"",S_FALSE},
5450             {"",S_FALSE}
5451         },
5452         {
5453             {Uri_HOST_DNS,S_OK},
5454             {80,S_OK},
5455             {URL_SCHEME_HTTP,S_OK},
5456             {URLZONE_INVALID,E_NOTIMPL}
5457         }
5458     },
5459     {   NULL,0,S_OK,FALSE,
5460         {
5461             {TRUE,"/test/test/",NULL,Uri_PROPERTY_PATH,S_OK,FALSE},
5462             {TRUE,"#Fr<|>g",NULL,Uri_PROPERTY_FRAGMENT,S_OK,FALSE}
5463         },
5464         {FALSE},
5465         0,INET_E_INVALID_URL,FALSE,
5466         0,INET_E_INVALID_URL,FALSE,
5467         0,0,0,INET_E_INVALID_URL,FALSE
5468     },
5469     {   "http://google.com/",0,S_OK,FALSE,
5470         {
5471             {TRUE,"ht%xxtp",NULL,Uri_PROPERTY_SCHEME_NAME,S_OK,FALSE}
5472         },
5473         {FALSE},
5474         0,INET_E_INVALID_URL,FALSE,
5475         0,INET_E_INVALID_URL,FALSE,
5476         0,0,0,INET_E_INVALID_URL,FALSE
5477     },
5478     /* File scheme's can't have a username set. */
5479     {   "file://google.com/",0,S_OK,FALSE,
5480         {
5481             {TRUE,"username",NULL,Uri_PROPERTY_USER_NAME,S_OK,FALSE}
5482         },
5483         {FALSE},
5484         0,INET_E_INVALID_URL,FALSE,
5485         0,INET_E_INVALID_URL,FALSE,
5486         0,0,0,INET_E_INVALID_URL,FALSE
5487     },
5488     /* File schemes can't have a password set. */
5489     {   "file://google.com/",0,S_OK,FALSE,
5490         {
5491             {TRUE,"password",NULL,Uri_PROPERTY_PASSWORD,S_OK,FALSE}
5492         },
5493         {FALSE},
5494         0,INET_E_INVALID_URL,FALSE,
5495         0,INET_E_INVALID_URL,FALSE,
5496         0,0,0,INET_E_INVALID_URL,FALSE
5497     },
5498     /* UserName can't contain any character that is a delimeter for another
5499      * component that appears after it in a normal URI.
5500      */
5501     {   "http://google.com/",0,S_OK,FALSE,
5502         {
5503             {TRUE,"user:pass",NULL,Uri_PROPERTY_USER_NAME,S_OK,FALSE}
5504         },
5505         {FALSE},
5506         0,INET_E_INVALID_URL,FALSE,
5507         0,INET_E_INVALID_URL,FALSE,
5508         0,0,0,INET_E_INVALID_URL,FALSE
5509     },
5510     {   "http://google.com/",0,S_OK,FALSE,
5511         {
5512             {TRUE,"user@google.com",NULL,Uri_PROPERTY_USER_NAME,S_OK,FALSE}
5513         },
5514         {FALSE},
5515         0,INET_E_INVALID_URL,FALSE,
5516         0,INET_E_INVALID_URL,FALSE,
5517         0,0,0,INET_E_INVALID_URL,FALSE
5518     },
5519     {   "http://google.com/",0,S_OK,FALSE,
5520         {
5521             {TRUE,"user/path",NULL,Uri_PROPERTY_USER_NAME,S_OK,FALSE}
5522         },
5523         {FALSE},
5524         0,INET_E_INVALID_URL,FALSE,
5525         0,INET_E_INVALID_URL,FALSE,
5526         0,0,0,INET_E_INVALID_URL,FALSE
5527     },
5528     {   "http://google.com/",0,S_OK,FALSE,
5529         {
5530             {TRUE,"user?Query",NULL,Uri_PROPERTY_USER_NAME,S_OK,FALSE}
5531         },
5532         {FALSE},
5533         0,INET_E_INVALID_URL,FALSE,
5534         0,INET_E_INVALID_URL,FALSE,
5535         0,0,0,INET_E_INVALID_URL,FALSE
5536     },
5537     {   "http://google.com/",0,S_OK,FALSE,
5538         {
5539             {TRUE,"user#Frag",NULL,Uri_PROPERTY_USER_NAME,S_OK,FALSE}
5540         },
5541         {FALSE},
5542         0,INET_E_INVALID_URL,FALSE,
5543         0,INET_E_INVALID_URL,FALSE,
5544         0,0,0,INET_E_INVALID_URL,FALSE
5545     },
5546     {   "http://google.com/",0,S_OK,FALSE,
5547         {
5548             {TRUE,"pass@google.com",NULL,Uri_PROPERTY_PASSWORD,S_OK,FALSE}
5549         },
5550         {FALSE},
5551         0,INET_E_INVALID_URL,FALSE,
5552         0,INET_E_INVALID_URL,FALSE,
5553         0,0,0,INET_E_INVALID_URL,FALSE
5554     },
5555     {   "http://google.com/",0,S_OK,FALSE,
5556         {
5557             {TRUE,"pass/path",NULL,Uri_PROPERTY_PASSWORD,S_OK,FALSE}
5558         },
5559         {FALSE},
5560         0,INET_E_INVALID_URL,FALSE,
5561         0,INET_E_INVALID_URL,FALSE,
5562         0,0,0,INET_E_INVALID_URL,FALSE
5563     },
5564     {   "http://google.com/",0,S_OK,FALSE,
5565         {
5566             {TRUE,"pass?query",NULL,Uri_PROPERTY_PASSWORD,S_OK,FALSE}
5567         },
5568         {FALSE},
5569         0,INET_E_INVALID_URL,FALSE,
5570         0,INET_E_INVALID_URL,FALSE,
5571        0,0,0,INET_E_INVALID_URL,FALSE
5572     },
5573     {   "http://google.com/",0,S_OK,FALSE,
5574         {
5575             {TRUE,"pass#frag",NULL,Uri_PROPERTY_PASSWORD,S_OK,FALSE}
5576         },
5577         {FALSE},
5578         0,INET_E_INVALID_URL,FALSE,
5579         0,INET_E_INVALID_URL,FALSE,
5580         0,0,0,INET_E_INVALID_URL,FALSE
5581     },
5582     {   "http://google.com/",0,S_OK,FALSE,
5583         {
5584             {TRUE,"winehq.org/test",NULL,Uri_PROPERTY_HOST,S_OK,FALSE}
5585         },
5586         {FALSE},
5587         0,INET_E_INVALID_URL,FALSE,
5588         0,INET_E_INVALID_URL,FALSE,
5589         0,0,0,INET_E_INVALID_URL,FALSE
5590     },
5591     {   "http://google.com/",0,S_OK,FALSE,
5592         {
5593             {TRUE,"winehq.org?test",NULL,Uri_PROPERTY_HOST,S_OK,FALSE}
5594         },
5595         {FALSE},
5596         0,INET_E_INVALID_URL,FALSE,
5597         0,INET_E_INVALID_URL,FALSE,
5598         0,0,0,INET_E_INVALID_URL,FALSE
5599     },
5600     {   "http://google.com/",0,S_OK,FALSE,
5601         {
5602             {TRUE,"winehq.org#test",NULL,Uri_PROPERTY_HOST,S_OK,FALSE}
5603         },
5604         {FALSE},
5605         0,INET_E_INVALID_URL,FALSE,
5606         0,INET_E_INVALID_URL,FALSE,
5607         0,0,0,INET_E_INVALID_URL,FALSE
5608     },
5609     /* Hostname is allowed to contain a ':' (even for known scheme types). */
5610     {   "http://google.com/",0,S_OK,FALSE,
5611         {
5612             {TRUE,"winehq.org:test",NULL,Uri_PROPERTY_HOST,S_OK,FALSE},
5613         },
5614         {FALSE},
5615         0,S_OK,FALSE,
5616         0,S_OK,FALSE,
5617         0,0,0,S_OK,FALSE,
5618         {
5619             {"http://winehq.org:test/",S_OK},
5620             {"winehq.org:test",S_OK},
5621             {"http://winehq.org:test/",S_OK},
5622             {"winehq.org:test",S_OK},
5623             {"",S_FALSE},
5624             {"",S_FALSE},
5625             {"winehq.org:test",S_OK},
5626             {"",S_FALSE},
5627             {"/",S_OK},
5628             {"/",S_OK},
5629             {"",S_FALSE},
5630             {"http://winehq.org:test/",S_OK},
5631             {"http",S_OK},
5632             {"",S_FALSE},
5633             {"",S_FALSE}
5634         },
5635         {
5636             {Uri_HOST_DNS,S_OK},
5637             {80,S_OK},
5638             {URL_SCHEME_HTTP,S_OK},
5639             {URLZONE_INVALID,E_NOTIMPL}
5640         }
5641     },
5642     /* Can't set the host name to NULL. */
5643     {   "http://google.com/",0,S_OK,FALSE,
5644         {
5645             {TRUE,NULL,"google.com",Uri_PROPERTY_HOST,E_INVALIDARG,FALSE}
5646         },
5647         {FALSE},
5648         0,S_OK,FALSE,
5649         0,S_OK,FALSE,
5650         0,0,0,S_OK,FALSE,
5651         {
5652             {"http://google.com/",S_OK},
5653             {"google.com",S_OK},
5654             {"http://google.com/",S_OK},
5655             {"google.com",S_OK},
5656             {"",S_FALSE},
5657             {"",S_FALSE},
5658             {"google.com",S_OK},
5659             {"",S_FALSE},
5660             {"/",S_OK},
5661             {"/",S_OK},
5662             {"",S_FALSE},
5663             {"http://google.com/",S_OK},
5664             {"http",S_OK},
5665             {"",S_FALSE},
5666             {"",S_FALSE}
5667         },
5668         {
5669             {Uri_HOST_DNS,S_OK},
5670             {80,S_OK},
5671             {URL_SCHEME_HTTP,S_OK},
5672             {URLZONE_INVALID,E_NOTIMPL}
5673         }
5674     },
5675     /* Can set the host name to an empty string. */
5676     {   "http://google.com/",0,S_OK,FALSE,
5677         {
5678             {TRUE,"",NULL,Uri_PROPERTY_HOST,S_OK,FALSE}
5679         },
5680         {FALSE},
5681         0,S_OK,FALSE,
5682         0,S_OK,FALSE,
5683         0,0,0,S_OK,FALSE,
5684         {
5685             {"http:///",S_OK},
5686             {"",S_OK},
5687             {"http:///",S_OK},
5688             {"",S_FALSE},
5689             {"",S_FALSE},
5690             {"",S_FALSE},
5691             {"",S_OK},
5692             {"",S_FALSE},
5693             {"/",S_OK},
5694             {"/",S_OK},
5695             {"",S_FALSE},
5696             {"http:///",S_OK},
5697             {"http",S_OK},
5698             {"",S_FALSE},
5699             {"",S_FALSE}
5700         },
5701         {
5702             {Uri_HOST_UNKNOWN,S_OK},
5703             {80,S_OK},
5704             {URL_SCHEME_HTTP,S_OK},
5705             {URLZONE_INVALID,E_NOTIMPL}
5706         }
5707     },
5708     {   "http://google.com/",0,S_OK,FALSE,
5709         {
5710             {TRUE,"/path?query",NULL,Uri_PROPERTY_PATH,S_OK,FALSE}
5711         },
5712         {FALSE},
5713         0,INET_E_INVALID_URL,FALSE,
5714         0,INET_E_INVALID_URL,FALSE,
5715         0,0,0,INET_E_INVALID_URL,FALSE
5716     },
5717     {   "http://google.com/",0,S_OK,FALSE,
5718         {
5719             {TRUE,"/path#test",NULL,Uri_PROPERTY_PATH,S_OK,FALSE}
5720         },
5721         {FALSE},
5722         0,INET_E_INVALID_URL,FALSE,
5723         0,INET_E_INVALID_URL,FALSE,
5724         0,0,0,INET_E_INVALID_URL,FALSE
5725     },
5726     {   "http://google.com/",0,S_OK,FALSE,
5727         {
5728             {TRUE,"?path#test",NULL,Uri_PROPERTY_QUERY,S_OK,FALSE}
5729         },
5730         {FALSE},
5731         0,INET_E_INVALID_URL,FALSE,
5732         0,INET_E_INVALID_URL,FALSE,
5733         0,0,0,INET_E_INVALID_URL,FALSE
5734     },
5735     {   "file:///c:/dir/file.html",0,S_OK,FALSE,
5736         {
5737             {TRUE,NULL,NULL,Uri_PROPERTY_FRAGMENT,S_OK},
5738         },
5739         {FALSE},
5740         0,S_OK,FALSE,
5741         0,S_OK,FALSE,
5742         0,0,0,S_OK,FALSE,
5743         {
5744             {"file:///c:/dir/file.html",S_OK},
5745             {"",S_FALSE},
5746             {"file:///c:/dir/file.html",S_OK},
5747             {"",S_FALSE},
5748             {".html",S_OK},
5749             {"",S_FALSE},
5750             {"",S_FALSE},
5751             {"",S_FALSE},
5752             {"/c:/dir/file.html",S_OK},
5753             {"/c:/dir/file.html",S_OK},
5754             {"",S_FALSE},
5755             {"file:///c:/dir/file.html",S_OK},
5756             {"file",S_OK},
5757             {"",S_FALSE},
5758             {"",S_FALSE}
5759         },
5760         {
5761             {Uri_HOST_UNKNOWN,S_OK},
5762             {0,S_FALSE},
5763             {URL_SCHEME_FILE,S_OK},
5764             {URLZONE_INVALID,E_NOTIMPL}
5765         }
5766     },
5767     {   "file:///c:/dir/file.html",0,S_OK,FALSE,
5768         {
5769             {TRUE,"#",NULL,Uri_PROPERTY_FRAGMENT,S_OK},
5770         },
5771         {FALSE},
5772         0,S_OK,FALSE,
5773         0,S_OK,FALSE,
5774         0,0,0,S_OK,FALSE,
5775         {
5776             {"file:///c:/dir/file.html#",S_OK},
5777             {"",S_FALSE},
5778             {"file:///c:/dir/file.html#",S_OK},
5779             {"",S_FALSE},
5780             {".html",S_OK},
5781             {"#",S_OK},
5782             {"",S_FALSE},
5783             {"",S_FALSE},
5784             {"/c:/dir/file.html",S_OK},
5785             {"/c:/dir/file.html",S_OK},
5786             {"",S_FALSE},
5787             {"file:///c:/dir/file.html#",S_OK},
5788             {"file",S_OK},
5789             {"",S_FALSE},
5790             {"",S_FALSE}
5791         },
5792         {
5793             {Uri_HOST_UNKNOWN,S_OK},
5794             {0,S_FALSE},
5795             {URL_SCHEME_FILE,S_OK},
5796             {URLZONE_INVALID,E_NOTIMPL}
5797         }
5798     }
5799 };
5800
5801 typedef struct _uri_builder_remove_test {
5802     const char  *uri;
5803     DWORD       create_flags;
5804     HRESULT     create_builder_expected;
5805     BOOL        create_builder_todo;
5806
5807     DWORD       remove_properties;
5808     HRESULT     remove_expected;
5809     BOOL        remove_todo;
5810
5811     const char  *expected_uri;
5812     DWORD       expected_flags;
5813     HRESULT     expected_hres;
5814     BOOL        expected_todo;
5815 } uri_builder_remove_test;
5816
5817 static const uri_builder_remove_test uri_builder_remove_tests[] = {
5818     {   "http://google.com/test?test=y#Frag",0,S_OK,FALSE,
5819         Uri_HAS_FRAGMENT|Uri_HAS_PATH|Uri_HAS_QUERY,S_OK,FALSE,
5820         "http://google.com/",0,S_OK,FALSE
5821     },
5822     {   "http://user:pass@winehq.org/",0,S_OK,FALSE,
5823         Uri_HAS_USER_NAME|Uri_HAS_PASSWORD,S_OK,FALSE,
5824         "http://winehq.org/",0,S_OK,FALSE
5825     },
5826     {   "zip://google.com?Test=x",0,S_OK,FALSE,
5827         Uri_HAS_HOST,S_OK,FALSE,
5828         "zip:/?Test=x",0,S_OK,FALSE
5829     },
5830     /* Doesn't remove the whole userinfo component. */
5831     {   "http://username:pass@google.com/",0,S_OK,FALSE,
5832         Uri_HAS_USER_INFO,S_OK,FALSE,
5833         "http://username:pass@google.com/",0,S_OK,FALSE
5834     },
5835     /* Doesn't remove the domain. */
5836     {   "http://google.com/",0,S_OK,FALSE,
5837         Uri_HAS_DOMAIN,S_OK,FALSE,
5838         "http://google.com/",0,S_OK,FALSE
5839     },
5840     {   "http://google.com:120/",0,S_OK,FALSE,
5841         Uri_HAS_AUTHORITY,S_OK,FALSE,
5842         "http://google.com:120/",0,S_OK,FALSE
5843     },
5844     {   "http://google.com/test.com/",0,S_OK,FALSE,
5845         Uri_HAS_EXTENSION,S_OK,FALSE,
5846         "http://google.com/test.com/",0,S_OK,FALSE
5847     },
5848     {   "http://google.com/?test=x",0,S_OK,FALSE,
5849         Uri_HAS_PATH_AND_QUERY,S_OK,FALSE,
5850         "http://google.com/?test=x",0,S_OK,FALSE
5851     },
5852     /* Can't remove the scheme name. */
5853     {   "http://google.com/?test=x",0,S_OK,FALSE,
5854         Uri_HAS_SCHEME_NAME|Uri_HAS_QUERY,E_INVALIDARG,FALSE,
5855         "http://google.com/?test=x",0,S_OK,FALSE
5856     }
5857 };
5858
5859 typedef struct _uri_combine_str_property {
5860     const char  *value;
5861     HRESULT     expected;
5862     BOOL        todo;
5863     const char  *broken_value;
5864     const char  *value_ex;
5865 } uri_combine_str_property;
5866
5867 typedef struct _uri_combine_test {
5868     const char  *base_uri;
5869     DWORD       base_create_flags;
5870     const char  *relative_uri;
5871     DWORD       relative_create_flags;
5872     DWORD       combine_flags;
5873     HRESULT     expected;
5874     BOOL        todo;
5875
5876     uri_combine_str_property    str_props[URI_STR_PROPERTY_COUNT];
5877     uri_dword_property          dword_props[URI_DWORD_PROPERTY_COUNT];
5878 } uri_combine_test;
5879
5880 static const uri_combine_test uri_combine_tests[] = {
5881     {   "http://google.com/fun/stuff",0,
5882         "../not/fun/stuff",Uri_CREATE_ALLOW_RELATIVE,
5883         0,S_OK,FALSE,
5884         {
5885             {"http://google.com/not/fun/stuff",S_OK},
5886             {"google.com",S_OK},
5887             {"http://google.com/not/fun/stuff",S_OK},
5888             {"google.com",S_OK},
5889             {"",S_FALSE},
5890             {"",S_FALSE},
5891             {"google.com",S_OK},
5892             {"",S_FALSE},
5893             {"/not/fun/stuff",S_OK},
5894             {"/not/fun/stuff",S_OK},
5895             {"",S_FALSE},
5896             {"http://google.com/not/fun/stuff",S_OK},
5897             {"http",S_OK},
5898             {"",S_FALSE},
5899             {"",S_FALSE}
5900         },
5901         {
5902             {Uri_HOST_DNS,S_OK},
5903             {80,S_OK},
5904             {URL_SCHEME_HTTP,S_OK},
5905             {URLZONE_INVALID,E_NOTIMPL}
5906         }
5907     },
5908     {   "http://google.com/test",0,
5909         "zip://test.com/cool",0,
5910         0,S_OK,FALSE,
5911         {
5912             {"zip://test.com/cool",S_OK},
5913             {"test.com",S_OK},
5914             {"zip://test.com/cool",S_OK},
5915             {"test.com",S_OK},
5916             {"",S_FALSE},
5917             {"",S_FALSE},
5918             {"test.com",S_OK},
5919             {"",S_FALSE},
5920             {"/cool",S_OK},
5921             {"/cool",S_OK},
5922             {"",S_FALSE},
5923             {"zip://test.com/cool",S_OK},
5924             {"zip",S_OK},
5925             {"",S_FALSE},
5926             {"",S_FALSE}
5927         },
5928         {
5929             {Uri_HOST_DNS,S_OK},
5930             {0,S_FALSE},
5931             {URL_SCHEME_UNKNOWN,S_OK},
5932             {URLZONE_INVALID,E_NOTIMPL}
5933         }
5934     },
5935     {   "http://google.com/use/base/path",0,
5936         "?relative",Uri_CREATE_ALLOW_RELATIVE,
5937         0,S_OK,FALSE,
5938         {
5939             {"http://google.com/use/base/path?relative",S_OK},
5940             {"google.com",S_OK},
5941             {"http://google.com/use/base/path?relative",S_OK},
5942             {"google.com",S_OK},
5943             {"",S_FALSE},
5944             {"",S_FALSE},
5945             {"google.com",S_OK},
5946             {"",S_FALSE},
5947             {"/use/base/path",S_OK},
5948             {"/use/base/path?relative",S_OK},
5949             {"?relative",S_OK},
5950             {"http://google.com/use/base/path?relative",S_OK},
5951             {"http",S_OK},
5952             {"",S_FALSE},
5953             {"",S_FALSE}
5954         },
5955         {
5956             {Uri_HOST_DNS,S_OK},
5957             {80,S_OK},
5958             {URL_SCHEME_HTTP,S_OK},
5959             {URLZONE_INVALID,E_NOTIMPL}
5960         }
5961     },
5962     {   "http://google.com/path",0,
5963         "/test/../test/.././testing",Uri_CREATE_ALLOW_RELATIVE,
5964         0,S_OK,FALSE,
5965         {
5966             {"http://google.com/testing",S_OK},
5967             {"google.com",S_OK},
5968             {"http://google.com/testing",S_OK},
5969             {"google.com",S_OK},
5970             {"",S_FALSE},
5971             {"",S_FALSE},
5972             {"google.com",S_OK},
5973             {"",S_FALSE},
5974             {"/testing",S_OK},
5975             {"/testing",S_OK},
5976             {"",S_FALSE},
5977             {"http://google.com/testing",S_OK},
5978             {"http",S_OK},
5979             {"",S_FALSE},
5980             {"",S_FALSE}
5981         },
5982         {
5983             {Uri_HOST_DNS,S_OK},
5984             {80,S_OK},
5985             {URL_SCHEME_HTTP,S_OK},
5986             {URLZONE_INVALID,E_NOTIMPL}
5987         }
5988     },
5989     {   "http://google.com/path",0,
5990         "/test/../test/.././testing",Uri_CREATE_ALLOW_RELATIVE,
5991         URL_DONT_SIMPLIFY,S_OK,FALSE,
5992         {
5993             {"http://google.com:80/test/../test/.././testing",S_OK},
5994             {"google.com",S_OK},
5995             {"http://google.com:80/test/../test/.././testing",S_OK},
5996             {"google.com",S_OK},
5997             {"",S_FALSE},
5998             {"",S_FALSE},
5999             {"google.com",S_OK},
6000             {"",S_FALSE},
6001             {"/test/../test/.././testing",S_OK},
6002             {"/test/../test/.././testing",S_OK},
6003             {"",S_FALSE},
6004             {"http://google.com:80/test/../test/.././testing",S_OK},
6005             {"http",S_OK},
6006             {"",S_FALSE},
6007             {"",S_FALSE}
6008         },
6009         {
6010             {Uri_HOST_DNS,S_OK},
6011             {80,S_OK},
6012             {URL_SCHEME_HTTP,S_OK},
6013             {URLZONE_INVALID,E_NOTIMPL}
6014         }
6015     },
6016     {   "http://winehq.org/test/abc",0,
6017         "testing/abc/../test",Uri_CREATE_ALLOW_RELATIVE,
6018         0,S_OK,FALSE,
6019         {
6020             {"http://winehq.org/test/testing/test",S_OK},
6021             {"winehq.org",S_OK},
6022             {"http://winehq.org/test/testing/test",S_OK},
6023             {"winehq.org",S_OK},
6024             {"",S_FALSE},
6025             {"",S_FALSE},
6026             {"winehq.org",S_OK},
6027             {"",S_FALSE},
6028             {"/test/testing/test",S_OK},
6029             {"/test/testing/test",S_OK},
6030             {"",S_FALSE},
6031             {"http://winehq.org/test/testing/test",S_OK},
6032             {"http",S_OK},
6033             {"",S_FALSE},
6034             {"",S_FALSE}
6035         },
6036         {
6037             {Uri_HOST_DNS,S_OK},
6038             {80,S_OK},
6039             {URL_SCHEME_HTTP,S_OK},
6040             {URLZONE_INVALID,E_NOTIMPL}
6041         }
6042     },
6043     {   "http://winehq.org/test/abc",0,
6044         "testing/abc/../test",Uri_CREATE_ALLOW_RELATIVE,
6045         URL_DONT_SIMPLIFY,S_OK,FALSE,
6046         {
6047             {"http://winehq.org:80/test/testing/abc/../test",S_OK},
6048             /* Default port is hidden in the authority. */
6049             {"winehq.org",S_OK},
6050             {"http://winehq.org:80/test/testing/abc/../test",S_OK},
6051             {"winehq.org",S_OK},
6052             {"",S_FALSE},
6053             {"",S_FALSE},
6054             {"winehq.org",S_OK},
6055             {"",S_FALSE},
6056             {"/test/testing/abc/../test",S_OK},
6057             {"/test/testing/abc/../test",S_OK},
6058             {"",S_FALSE},
6059             {"http://winehq.org:80/test/testing/abc/../test",S_OK},
6060             {"http",S_OK},
6061             {"",S_FALSE},
6062             {"",S_FALSE}
6063         },
6064         {
6065             {Uri_HOST_DNS,S_OK},
6066             {80,S_OK},
6067             {URL_SCHEME_HTTP,S_OK},
6068             {URLZONE_INVALID,E_NOTIMPL}
6069         }
6070     },
6071     {   "http://winehq.org/test?query",0,
6072         "testing",Uri_CREATE_ALLOW_RELATIVE,
6073         0,S_OK,FALSE,
6074         {
6075             {"http://winehq.org/testing",S_OK},
6076             {"winehq.org",S_OK},
6077             {"http://winehq.org/testing",S_OK},
6078             {"winehq.org",S_OK},
6079             {"",S_FALSE},
6080             {"",S_FALSE},
6081             {"winehq.org",S_OK},
6082             {"",S_FALSE},
6083             {"/testing",S_OK},
6084             {"/testing",S_OK},
6085             {"",S_FALSE},
6086             {"http://winehq.org/testing",S_OK},
6087             {"http",S_OK},
6088             {"",S_FALSE},
6089             {"",S_FALSE}
6090         },
6091         {
6092             {Uri_HOST_DNS,S_OK},
6093             {80,S_OK},
6094             {URL_SCHEME_HTTP,S_OK},
6095             {URLZONE_INVALID,E_NOTIMPL}
6096         }
6097     },
6098     {   "http://winehq.org/test#frag",0,
6099         "testing",Uri_CREATE_ALLOW_RELATIVE,
6100         0,S_OK,FALSE,
6101         {
6102             {"http://winehq.org/testing",S_OK},
6103             {"winehq.org",S_OK},
6104             {"http://winehq.org/testing",S_OK},
6105             {"winehq.org",S_OK},
6106             {"",S_FALSE},
6107             {"",S_FALSE},
6108             {"winehq.org",S_OK},
6109             {"",S_FALSE},
6110             {"/testing",S_OK},
6111             {"/testing",S_OK},
6112             {"",S_FALSE},
6113             {"http://winehq.org/testing",S_OK},
6114             {"http",S_OK},
6115             {"",S_FALSE},
6116             {"",S_FALSE}
6117         },
6118         {
6119             {Uri_HOST_DNS,S_OK},
6120             {80,S_OK},
6121             {URL_SCHEME_HTTP,S_OK},
6122             {URLZONE_INVALID,E_NOTIMPL}
6123         }
6124     },
6125     {   "testing?query#frag",Uri_CREATE_ALLOW_RELATIVE,
6126         "test",Uri_CREATE_ALLOW_RELATIVE,
6127         0,S_OK,FALSE,
6128         {
6129             {"test",S_OK},
6130             {"",S_FALSE},
6131             {"test",S_OK},
6132             {"",S_FALSE},
6133             {"",S_FALSE},
6134             {"",S_FALSE},
6135             {"",S_FALSE},
6136             {"",S_FALSE},
6137             {"test",S_OK},
6138             {"test",S_OK},
6139             {"",S_FALSE},
6140             {"test",S_OK},
6141             {"",S_FALSE},
6142             {"",S_FALSE},
6143             {"",S_FALSE}
6144         },
6145         {
6146             {Uri_HOST_UNKNOWN,S_OK},
6147             {0,S_FALSE},
6148             {URL_SCHEME_UNKNOWN,S_OK},
6149             {URLZONE_INVALID,E_NOTIMPL}
6150         }
6151     },
6152     {   "file:///c:/test/test",0,
6153         "/testing.mp3",Uri_CREATE_ALLOW_RELATIVE,
6154         URL_FILE_USE_PATHURL,S_OK,FALSE,
6155         {
6156             {"file://c:\\testing.mp3",S_OK},
6157             {"",S_FALSE},
6158             {"file://c:\\testing.mp3",S_OK},
6159             {"",S_FALSE},
6160             {".mp3",S_OK},
6161             {"",S_FALSE},
6162             {"",S_FALSE},
6163             {"",S_FALSE},
6164             {"c:\\testing.mp3",S_OK},
6165             {"c:\\testing.mp3",S_OK},
6166             {"",S_FALSE},
6167             {"file://c:\\testing.mp3",S_OK},
6168             {"file",S_OK},
6169             {"",S_FALSE},
6170             {"",S_FALSE}
6171         },
6172         {
6173             {Uri_HOST_UNKNOWN,S_OK},
6174             {0,S_FALSE},
6175             {URL_SCHEME_FILE,S_OK},
6176             {URLZONE_INVALID,E_NOTIMPL}
6177         }
6178     },
6179     {   "file:///c:/test/test",0,
6180         "/testing.mp3",Uri_CREATE_ALLOW_RELATIVE,
6181         0,S_OK,FALSE,
6182         {
6183             {"file:///c:/testing.mp3",S_OK},
6184             {"",S_FALSE},
6185             {"file:///c:/testing.mp3",S_OK},
6186             {"",S_FALSE},
6187             {".mp3",S_OK},
6188             {"",S_FALSE},
6189             {"",S_FALSE},
6190             {"",S_FALSE},
6191             {"/c:/testing.mp3",S_OK},
6192             {"/c:/testing.mp3",S_OK},
6193             {"",S_FALSE},
6194             {"file:///c:/testing.mp3",S_OK},
6195             {"file",S_OK},
6196             {"",S_FALSE},
6197             {"",S_FALSE}
6198         },
6199         {
6200             {Uri_HOST_UNKNOWN,S_OK},
6201             {0,S_FALSE},
6202             {URL_SCHEME_FILE,S_OK},
6203             {URLZONE_INVALID,E_NOTIMPL}
6204         }
6205     },
6206     {   "file://test.com/test/test",0,
6207         "/testing.mp3",Uri_CREATE_ALLOW_RELATIVE,
6208         URL_FILE_USE_PATHURL,S_OK,FALSE,
6209         {
6210             {"file://\\\\test.com\\testing.mp3",S_OK},
6211             {"test.com",S_OK},
6212             {"file://\\\\test.com\\testing.mp3",S_OK},
6213             {"test.com",S_OK},
6214             {".mp3",S_OK},
6215             {"",S_FALSE},
6216             {"test.com",S_OK},
6217             {"",S_FALSE},
6218             {"\\testing.mp3",S_OK},
6219             {"\\testing.mp3",S_OK},
6220             {"",S_FALSE},
6221             {"file://\\\\test.com\\testing.mp3",S_OK},
6222             {"file",S_OK},
6223             {"",S_FALSE},
6224             {"",S_FALSE}
6225         },
6226         {
6227             {Uri_HOST_DNS,S_OK},
6228             {0,S_FALSE},
6229             {URL_SCHEME_FILE,S_OK},
6230             {URLZONE_INVALID,E_NOTIMPL}
6231         }
6232     },
6233     /* URL_DONT_SIMPLIFY has no effect. */
6234     {   "http://google.com/test",0,
6235         "zip://test.com/cool/../cool/test",0,
6236         URL_DONT_SIMPLIFY,S_OK,FALSE,
6237         {
6238             {"zip://test.com/cool/test",S_OK,FALSE,NULL,"zip://test.com/cool/../cool/test"},
6239             {"test.com",S_OK},
6240             {"zip://test.com/cool/test",S_OK,FALSE,NULL,"zip://test.com/cool/../cool/test"},
6241             {"test.com",S_OK},
6242             {"",S_FALSE},
6243             {"",S_FALSE},
6244             {"test.com",S_OK},
6245             {"",S_FALSE},
6246             {"/cool/test",S_OK,FALSE,NULL,"/cool/../cool/test"},
6247             {"/cool/test",S_OK,FALSE,NULL,"/cool/../cool/test"},
6248             {"",S_FALSE},
6249             /* The resulting IUri has the same Raw URI as the relative URI (only IE 8).
6250              * On IE 7 it reduces the path in the Raw URI.
6251              */
6252             {"zip://test.com/cool/../cool/test",S_OK,FALSE,"zip://test.com/cool/test"},
6253             {"zip",S_OK},
6254             {"",S_FALSE},
6255             {"",S_FALSE}
6256         },
6257         {
6258             {Uri_HOST_DNS,S_OK},
6259             {0,S_FALSE},
6260             {URL_SCHEME_UNKNOWN,S_OK},
6261             {URLZONE_INVALID,E_NOTIMPL}
6262         }
6263     },
6264     /* FILE_USE_PATHURL has no effect in IE 8, in IE 7 the
6265      * resulting URI is converted into a dos path.
6266      */
6267     {   "http://google.com/test",0,
6268         "file:///c:/test/",0,
6269         URL_FILE_USE_PATHURL,S_OK,FALSE,
6270         {
6271             {"file:///c:/test/",S_OK,FALSE,"file://c:\\test\\"},
6272             {"",S_FALSE},
6273             {"file:///c:/test/",S_OK,FALSE,"file://c:\\test\\"},
6274             {"",S_FALSE},
6275             {"",S_FALSE},
6276             {"",S_FALSE},
6277             {"",S_FALSE},
6278             {"",S_FALSE},
6279             {"/c:/test/",S_OK,FALSE,"c:\\test\\"},
6280             {"/c:/test/",S_OK,FALSE,"c:\\test\\"},
6281             {"",S_FALSE},
6282             {"file:///c:/test/",S_OK,FALSE,"file://c:\\test\\"},
6283             {"file",S_OK},
6284             {"",S_FALSE},
6285             {"",S_FALSE}
6286         },
6287         {
6288             {Uri_HOST_UNKNOWN,S_OK},
6289             {0,S_FALSE},
6290             {URL_SCHEME_FILE,S_OK},
6291             {URLZONE_INVALID,E_NOTIMPL}
6292         }
6293     },
6294     {   "http://google.com/test",0,
6295         "http://test.com/test#%30test",0,
6296         URL_DONT_UNESCAPE_EXTRA_INFO,S_OK,FALSE,
6297         {
6298             {"http://test.com/test#0test",S_OK,FALSE,NULL,"http://test.com/test#%30test"},
6299             {"test.com",S_OK},
6300             {"http://test.com/test#0test",S_OK,FALSE,NULL,"http://test.com/test#%30test"},
6301             {"test.com",S_OK},
6302             {"",S_FALSE},
6303             {"#0test",S_OK,FALSE,NULL,"#%30test"},
6304             {"test.com",S_OK},
6305             {"",S_FALSE},
6306             {"/test",S_OK},
6307             {"/test",S_OK},
6308             {"",S_FALSE},
6309             /* IE 7 decodes the %30 to a 0 in the Raw URI. */
6310             {"http://test.com/test#%30test",S_OK,FALSE,"http://test.com/test#0test"},
6311             {"http",S_OK},
6312             {"",S_FALSE},
6313             {"",S_FALSE}
6314         },
6315         {
6316             {Uri_HOST_DNS,S_OK},
6317             {80,S_OK},
6318             {URL_SCHEME_HTTP,S_OK},
6319             {URLZONE_INVALID,E_NOTIMPL}
6320         }
6321     },
6322     /* Windows validates the path component from the relative Uri. */
6323     {   "http://google.com/test",0,
6324         "/Te%XXst",Uri_CREATE_ALLOW_RELATIVE,
6325         0,E_INVALIDARG,FALSE
6326     },
6327     /* Windows doesn't validate the query from the relative Uri. */
6328     {   "http://google.com/test",0,
6329         "?Tes%XXt",Uri_CREATE_ALLOW_RELATIVE,
6330         0,S_OK,FALSE,
6331         {
6332             {"http://google.com/test?Tes%XXt",S_OK},
6333             {"google.com",S_OK},
6334             {"http://google.com/test?Tes%XXt",S_OK},
6335             {"google.com",S_OK},
6336             {"",S_FALSE},
6337             {"",S_FALSE},
6338             {"google.com",S_OK},
6339             {"",S_FALSE},
6340             {"/test",S_OK},
6341             {"/test?Tes%XXt",S_OK},
6342             {"?Tes%XXt",S_OK},
6343             {"http://google.com/test?Tes%XXt",S_OK},
6344             {"http",S_OK},
6345             {"",S_FALSE},
6346             {"",S_FALSE}
6347         },
6348         {
6349             {Uri_HOST_DNS,S_OK},
6350             {80,S_OK},
6351             {URL_SCHEME_HTTP,S_OK},
6352             {URLZONE_INVALID,E_NOTIMPL}
6353         }
6354     },
6355     /* Windows doesn't validate the fragment from the relative Uri. */
6356     {   "http://google.com/test",0,
6357         "#Tes%XXt",Uri_CREATE_ALLOW_RELATIVE,
6358         0,S_OK,FALSE,
6359         {
6360             {"http://google.com/test#Tes%XXt",S_OK},
6361             {"google.com",S_OK},
6362             {"http://google.com/test#Tes%XXt",S_OK},
6363             {"google.com",S_OK},
6364             {"",S_FALSE},
6365             {"#Tes%XXt",S_OK},
6366             {"google.com",S_OK},
6367             {"",S_FALSE},
6368             {"/test",S_OK},
6369             {"/test",S_OK},
6370             {"",S_FALSE},
6371             {"http://google.com/test#Tes%XXt",S_OK},
6372             {"http",S_OK},
6373             {"",S_FALSE},
6374             {"",S_FALSE}
6375         },
6376         {
6377             {Uri_HOST_DNS,S_OK},
6378             {80,S_OK},
6379             {URL_SCHEME_HTTP,S_OK},
6380             {URLZONE_INVALID,E_NOTIMPL}
6381         }
6382     },
6383     /* Creates an IUri which contains an invalid dos path char. */
6384     {   "file:///c:/test",0,
6385         "/test<ing",Uri_CREATE_ALLOW_RELATIVE,
6386         URL_FILE_USE_PATHURL,S_OK,FALSE,
6387         {
6388             {"file://c:\\test<ing",S_OK},
6389             {"",S_FALSE},
6390             {"file://c:\\test<ing",S_OK},
6391             {"",S_FALSE},
6392             {"",S_FALSE},
6393             {"",S_FALSE},
6394             {"",S_FALSE},
6395             {"",S_FALSE},
6396             {"c:\\test<ing",S_OK},
6397             {"c:\\test<ing",S_OK},
6398             {"",S_FALSE},
6399             {"file://c:\\test<ing",S_OK},
6400             {"file",S_OK},
6401             {"",S_FALSE},
6402             {"",S_FALSE}
6403         },
6404         {
6405             {Uri_HOST_UNKNOWN,S_OK},
6406             {0,S_FALSE},
6407             {URL_SCHEME_FILE,S_OK},
6408             {URLZONE_INVALID,E_NOTIMPL}
6409         }
6410     },
6411     /* Appends the path after the drive letter (if any). */
6412     {   "file:///c:/test",0,
6413         "/c:/testing",Uri_CREATE_ALLOW_RELATIVE,
6414         0,S_OK,FALSE,
6415         {
6416             {"file:///c:/c:/testing",S_OK},
6417             {"",S_FALSE},
6418             {"file:///c:/c:/testing",S_OK},
6419             {"",S_FALSE},
6420             {"",S_FALSE},
6421             {"",S_FALSE},
6422             {"",S_FALSE},
6423             {"",S_FALSE},
6424             {"/c:/c:/testing",S_OK},
6425             {"/c:/c:/testing",S_OK},
6426             {"",S_FALSE},
6427             {"file:///c:/c:/testing",S_OK},
6428             {"file",S_OK},
6429             {"",S_FALSE},
6430             {"",S_FALSE}
6431         },
6432         {
6433             {Uri_HOST_UNKNOWN,S_OK},
6434             {0,S_FALSE},
6435             {URL_SCHEME_FILE,S_OK},
6436             {URLZONE_INVALID,E_NOTIMPL}
6437         }
6438     },
6439     /* A '/' is added if the base URI doesn't have a path and the
6440      * relative URI doesn't contain a path (since the base URI is
6441      * hierarchical.
6442      */
6443     {   "http://google.com",Uri_CREATE_NO_CANONICALIZE,
6444         "?test",Uri_CREATE_ALLOW_RELATIVE,
6445         0,S_OK,FALSE,
6446         {
6447             {"http://google.com/?test",S_OK},
6448             {"google.com",S_OK},
6449             {"http://google.com/?test",S_OK},
6450             {"google.com",S_OK},
6451             {"",S_FALSE},
6452             {"",S_FALSE},
6453             {"google.com",S_OK},
6454             {"",S_FALSE},
6455             {"/",S_OK},
6456             {"/?test",S_OK},
6457             {"?test",S_OK},
6458             {"http://google.com/?test",S_OK},
6459             {"http",S_OK},
6460             {"",S_FALSE},
6461             {"",S_FALSE}
6462         },
6463         {
6464             {Uri_HOST_DNS,S_OK},
6465             {80,S_OK},
6466             {URL_SCHEME_HTTP,S_OK},
6467             {URLZONE_INVALID,E_NOTIMPL}
6468         }
6469     },
6470     {   "zip://google.com",Uri_CREATE_NO_CANONICALIZE,
6471         "?test",Uri_CREATE_ALLOW_RELATIVE,
6472         0,S_OK,FALSE,
6473         {
6474             {"zip://google.com/?test",S_OK},
6475             {"google.com",S_OK},
6476             {"zip://google.com/?test",S_OK},
6477             {"google.com",S_OK},
6478             {"",S_FALSE},
6479             {"",S_FALSE},
6480             {"google.com",S_OK},
6481             {"",S_FALSE},
6482             {"/",S_OK},
6483             {"/?test",S_OK},
6484             {"?test",S_OK},
6485             {"zip://google.com/?test",S_OK},
6486             {"zip",S_OK},
6487             {"",S_FALSE},
6488             {"",S_FALSE}
6489         },
6490         {
6491             {Uri_HOST_DNS,S_OK},
6492             {0,S_FALSE},
6493             {URL_SCHEME_UNKNOWN,S_OK},
6494             {URLZONE_INVALID,E_NOTIMPL}
6495         }
6496     },
6497     /* No path is appended since the base URI is opaque. */
6498     {   "zip:?testing",0,
6499         "?test",Uri_CREATE_ALLOW_RELATIVE,
6500         0,S_OK,FALSE,
6501         {
6502             {"zip:?test",S_OK},
6503             {"",S_FALSE},
6504             {"zip:?test",S_OK},
6505             {"",S_FALSE},
6506             {"",S_FALSE},
6507             {"",S_FALSE},
6508             {"",S_FALSE},
6509             {"",S_FALSE},
6510             {"",S_OK},
6511             {"?test",S_OK},
6512             {"?test",S_OK},
6513             {"zip:?test",S_OK},
6514             {"zip",S_OK},
6515             {"",S_FALSE},
6516             {"",S_FALSE}
6517         },
6518         {
6519             {Uri_HOST_UNKNOWN,S_OK},
6520             {0,S_FALSE},
6521             {URL_SCHEME_UNKNOWN,S_OK},
6522             {URLZONE_INVALID,E_NOTIMPL}
6523         }
6524     },
6525     {   "file:///c:/",0,
6526         "../testing/test",Uri_CREATE_ALLOW_RELATIVE,
6527         0,S_OK,FALSE,
6528         {
6529             {"file:///c:/testing/test",S_OK},
6530             {"",S_FALSE},
6531             {"file:///c:/testing/test",S_OK},
6532             {"",S_FALSE},
6533             {"",S_FALSE},
6534             {"",S_FALSE},
6535             {"",S_FALSE},
6536             {"",S_FALSE},
6537             {"/c:/testing/test",S_OK},
6538             {"/c:/testing/test",S_OK},
6539             {"",S_FALSE},
6540             {"file:///c:/testing/test",S_OK},
6541             {"file",S_OK},
6542             {"",S_FALSE},
6543             {"",S_FALSE}
6544         },
6545         {
6546             {Uri_HOST_UNKNOWN,S_OK},
6547             {0,S_FALSE},
6548             {URL_SCHEME_FILE,S_OK},
6549             {URLZONE_INVALID,E_NOTIMPL}
6550         }
6551     },
6552     {   "http://winehq.org/dir/testfile",0,
6553         "test?querystring",Uri_CREATE_ALLOW_RELATIVE,
6554         0,S_OK,FALSE,
6555         {
6556             {"http://winehq.org/dir/test?querystring",S_OK},
6557             {"winehq.org",S_OK},
6558             {"http://winehq.org/dir/test?querystring",S_OK},
6559             {"winehq.org",S_OK},
6560             {"",S_FALSE},
6561             {"",S_FALSE},
6562             {"winehq.org",S_OK},
6563             {"",S_FALSE},
6564             {"/dir/test",S_OK},
6565             {"/dir/test?querystring",S_OK},
6566             {"?querystring",S_OK},
6567             {"http://winehq.org/dir/test?querystring",S_OK},
6568             {"http",S_OK},
6569             {"",S_FALSE},
6570             {"",S_FALSE}
6571         },
6572         {
6573             {Uri_HOST_DNS,S_OK},
6574             {80,S_OK},
6575             {URL_SCHEME_HTTP,S_OK},
6576             {URLZONE_INVALID,E_NOTIMPL}
6577         }
6578     },
6579     {   "http://winehq.org/dir/test",0,
6580         "test?querystring",Uri_CREATE_ALLOW_RELATIVE,
6581         0,S_OK,FALSE,
6582         {
6583             {"http://winehq.org/dir/test?querystring",S_OK},
6584             {"winehq.org",S_OK},
6585             {"http://winehq.org/dir/test?querystring",S_OK},
6586             {"winehq.org",S_OK},
6587             {"",S_FALSE},
6588             {"",S_FALSE},
6589             {"winehq.org",S_OK},
6590             {"",S_FALSE},
6591             {"/dir/test",S_OK},
6592             {"/dir/test?querystring",S_OK},
6593             {"?querystring",S_OK},
6594             {"http://winehq.org/dir/test?querystring",S_OK},
6595             {"http",S_OK},
6596             {"",S_FALSE},
6597             {"",S_FALSE}
6598         },
6599         {
6600             {Uri_HOST_DNS,S_OK},
6601             {80,S_OK},
6602             {URL_SCHEME_HTTP,S_OK},
6603             {URLZONE_INVALID,E_NOTIMPL}
6604         }
6605     },
6606     {   "http://winehq.org/dir/test?querystring",0,
6607         "#hash",Uri_CREATE_ALLOW_RELATIVE,
6608         0,S_OK,FALSE,
6609         {
6610             {"http://winehq.org/dir/test?querystring#hash",S_OK},
6611             {"winehq.org",S_OK},
6612             {"http://winehq.org/dir/test?querystring#hash",S_OK},
6613             {"winehq.org",S_OK},
6614             {"",S_FALSE},
6615             {"#hash",S_OK},
6616             {"winehq.org",S_OK},
6617             {"",S_FALSE},
6618             {"/dir/test",S_OK},
6619             {"/dir/test?querystring",S_OK},
6620             {"?querystring",S_OK},
6621             {"http://winehq.org/dir/test?querystring#hash",S_OK},
6622             {"http",S_OK},
6623             {"",S_FALSE},
6624             {"",S_FALSE}
6625         },
6626         {
6627             {Uri_HOST_DNS,S_OK},
6628             {80,S_OK},
6629             {URL_SCHEME_HTTP,S_OK},
6630             {URLZONE_INVALID,E_NOTIMPL}
6631         }
6632     },
6633     {   "mk:@MSITSTORE:C:\\Some\\Bogus\\Path.chm::/subdir\\file.txt",0,
6634         "relative/path.txt",Uri_CREATE_ALLOW_RELATIVE,
6635         0,S_OK,FALSE,
6636         {
6637             {"mk:@MSITSTORE:C:\\Some\\Bogus\\Path.chm::/subdir/relative/path.txt",S_OK},
6638             {"",S_FALSE},
6639             {"mk:@MSITSTORE:C:\\Some\\Bogus\\Path.chm::/subdir/relative/path.txt",S_OK},
6640             {"",S_FALSE},
6641             {".txt",S_OK},
6642             {"",S_FALSE},
6643             {"",S_FALSE},
6644             {"",S_FALSE},
6645             {"@MSITSTORE:C:\\Some\\Bogus\\Path.chm::/subdir/relative/path.txt",S_OK},
6646             {"@MSITSTORE:C:\\Some\\Bogus\\Path.chm::/subdir/relative/path.txt",S_OK},
6647             {"",S_FALSE},
6648             {"mk:@MSITSTORE:C:\\Some\\Bogus\\Path.chm::/subdir/relative/path.txt",S_OK},
6649             {"mk",S_OK},
6650             {"",S_FALSE},
6651             {"",S_FALSE}
6652         },
6653         {
6654             {Uri_HOST_UNKNOWN,S_OK},
6655             {0,S_FALSE},
6656             {URL_SCHEME_MK,S_OK},
6657             {URLZONE_INVALID,E_NOTIMPL}
6658         }
6659     },
6660     {   "mk:@MSITSTORE:C:\\Some\\Bogus\\Path.chm::\\subdir\\file.txt",0,
6661         "relative/path.txt",Uri_CREATE_ALLOW_RELATIVE,
6662         0,S_OK,FALSE,
6663         {
6664             {"mk:@MSITSTORE:C:\\Some\\Bogus\\Path.chm::/subdir/relative/path.txt",S_OK},
6665             {"",S_FALSE},
6666             {"mk:@MSITSTORE:C:\\Some\\Bogus\\Path.chm::/subdir/relative/path.txt",S_OK},
6667             {"",S_FALSE},
6668             {".txt",S_OK},
6669             {"",S_FALSE},
6670             {"",S_FALSE},
6671             {"",S_FALSE},
6672             {"@MSITSTORE:C:\\Some\\Bogus\\Path.chm::/subdir/relative/path.txt",S_OK},
6673             {"@MSITSTORE:C:\\Some\\Bogus\\Path.chm::/subdir/relative/path.txt",S_OK},
6674             {"",S_FALSE},
6675             {"mk:@MSITSTORE:C:\\Some\\Bogus\\Path.chm::/subdir/relative/path.txt",S_OK},
6676             {"mk",S_OK},
6677             {"",S_FALSE},
6678             {"",S_FALSE}
6679         },
6680         {
6681             {Uri_HOST_UNKNOWN,S_OK},
6682             {0,S_FALSE},
6683             {URL_SCHEME_MK,S_OK},
6684             {URLZONE_INVALID,E_NOTIMPL}
6685         }
6686     },
6687     {   "mk:@MSITSTORE:C:/Some\\Bogus/Path.chm::/subdir\\file.txt",0,
6688         "relative\\path.txt",Uri_CREATE_ALLOW_RELATIVE,
6689         0,S_OK,FALSE,
6690         {
6691             {"mk:@MSITSTORE:C:/Some\\Bogus/Path.chm::/subdir/relative/path.txt",S_OK},
6692             {"",S_FALSE},
6693             {"mk:@MSITSTORE:C:/Some\\Bogus/Path.chm::/subdir/relative/path.txt",S_OK},
6694             {"",S_FALSE},
6695             {".txt",S_OK},
6696             {"",S_FALSE},
6697             {"",S_FALSE},
6698             {"",S_FALSE},
6699             {"@MSITSTORE:C:/Some\\Bogus/Path.chm::/subdir/relative/path.txt",S_OK},
6700             {"@MSITSTORE:C:/Some\\Bogus/Path.chm::/subdir/relative/path.txt",S_OK},
6701             {"",S_FALSE},
6702             {"mk:@MSITSTORE:C:/Some\\Bogus/Path.chm::/subdir/relative/path.txt",S_OK},
6703             {"mk",S_OK},
6704             {"",S_FALSE},
6705             {"",S_FALSE}
6706         },
6707         {
6708             {Uri_HOST_UNKNOWN,S_OK},
6709             {0,S_FALSE},
6710             {URL_SCHEME_MK,S_OK},
6711             {URLZONE_INVALID,E_NOTIMPL}
6712         }
6713     },
6714     {   "mk:@MSITSTORE:C:\\dir\\file.chm::/subdir/file.txt",0,
6715         "/relative/path.txt",Uri_CREATE_ALLOW_RELATIVE,
6716         0,S_OK,FALSE,
6717         {
6718             {"mk:@MSITSTORE:C:\\dir\\file.chm::/relative/path.txt",S_OK},
6719             {"",S_FALSE},
6720             {"mk:@MSITSTORE:C:\\dir\\file.chm::/relative/path.txt",S_OK},
6721             {"",S_FALSE},
6722             {".txt",S_OK},
6723             {"",S_FALSE},
6724             {"",S_FALSE},
6725             {"",S_FALSE},
6726             {"@MSITSTORE:C:\\dir\\file.chm::/relative/path.txt",S_OK},
6727             {"@MSITSTORE:C:\\dir\\file.chm::/relative/path.txt",S_OK},
6728             {"",S_FALSE},
6729             {"mk:@MSITSTORE:C:\\dir\\file.chm::/relative/path.txt",S_OK},
6730             {"mk",S_OK},
6731             {"",S_FALSE},
6732             {"",S_FALSE}
6733         },
6734         {
6735             {Uri_HOST_UNKNOWN,S_OK},
6736             {0,S_FALSE},
6737             {URL_SCHEME_MK,S_OK},
6738             {URLZONE_INVALID,E_NOTIMPL}
6739         }
6740     },
6741     {   "mk:MSITSTORE:C:\\dir\\file.chm::/subdir/file.txt",0,
6742         "/relative/path.txt",Uri_CREATE_ALLOW_RELATIVE,
6743         0,S_OK,FALSE,
6744         {
6745             {"mk:MSITSTORE:C:\\dir\\file.chm::/relative/path.txt",S_OK},
6746             {"",S_FALSE},
6747             {"mk:MSITSTORE:C:\\dir\\file.chm::/relative/path.txt",S_OK},
6748             {"",S_FALSE},
6749             {".txt",S_OK},
6750             {"",S_FALSE},
6751             {"",S_FALSE},
6752             {"",S_FALSE},
6753             {"MSITSTORE:C:\\dir\\file.chm::/relative/path.txt",S_OK},
6754             {"MSITSTORE:C:\\dir\\file.chm::/relative/path.txt",S_OK},
6755             {"",S_FALSE},
6756             {"mk:MSITSTORE:C:\\dir\\file.chm::/relative/path.txt",S_OK},
6757             {"mk",S_OK},
6758             {"",S_FALSE},
6759             {"",S_FALSE}
6760         },
6761         {
6762             {Uri_HOST_UNKNOWN,S_OK},
6763             {0,S_FALSE},
6764             {URL_SCHEME_MK,S_OK},
6765             {URLZONE_INVALID,E_NOTIMPL}
6766         }
6767     },
6768     {   "mk:@MSITSTORE:C:\\dir\\file.chm::/subdir/../../file.txt",0,
6769         "/relative/path.txt",Uri_CREATE_ALLOW_RELATIVE,
6770         0,S_OK,FALSE,
6771         {
6772             {"mk:@MSITSTORE:/relative/path.txt",S_OK},
6773             {"",S_FALSE},
6774             {"mk:@MSITSTORE:/relative/path.txt",S_OK},
6775             {"",S_FALSE},
6776             {".txt",S_OK},
6777             {"",S_FALSE},
6778             {"",S_FALSE},
6779             {"",S_FALSE},
6780             {"@MSITSTORE:/relative/path.txt",S_OK},
6781             {"@MSITSTORE:/relative/path.txt",S_OK},
6782             {"",S_FALSE},
6783             {"mk:@MSITSTORE:/relative/path.txt",S_OK},
6784             {"mk",S_OK},
6785             {"",S_FALSE},
6786             {"",S_FALSE}
6787         },
6788         {
6789             {Uri_HOST_UNKNOWN,S_OK},
6790             {0,S_FALSE},
6791             {URL_SCHEME_MK,S_OK},
6792             {URLZONE_INVALID,E_NOTIMPL}
6793         }
6794     },
6795     {   "mk:@xxx:C:\\dir\\file.chm::/subdir/../../file.txt",0,
6796         "/relative/path.txt",Uri_CREATE_ALLOW_RELATIVE,
6797         0,S_OK,FALSE,
6798         {
6799             {"mk:@xxx:/relative/path.txt",S_OK},
6800             {"",S_FALSE},
6801             {"mk:@xxx:/relative/path.txt",S_OK},
6802             {"",S_FALSE},
6803             {".txt",S_OK},
6804             {"",S_FALSE},
6805             {"",S_FALSE},
6806             {"",S_FALSE},
6807             {"@xxx:/relative/path.txt",S_OK},
6808             {"@xxx:/relative/path.txt",S_OK},
6809             {"",S_FALSE},
6810             {"mk:@xxx:/relative/path.txt",S_OK},
6811             {"mk",S_OK},
6812             {"",S_FALSE},
6813             {"",S_FALSE}
6814         },
6815         {
6816             {Uri_HOST_UNKNOWN,S_OK},
6817             {0,S_FALSE},
6818             {URL_SCHEME_MK,S_OK},
6819             {URLZONE_INVALID,E_NOTIMPL}
6820         }
6821     },
6822     {   "mk:xxx:C:\\dir\\file.chm::/subdir/../../file.txt",0,
6823         "/relative/path.txt",Uri_CREATE_ALLOW_RELATIVE,
6824         0,S_OK,FALSE,
6825         {
6826             {"mk:/relative/path.txt",S_OK},
6827             {"",S_FALSE},
6828             {"mk:/relative/path.txt",S_OK},
6829             {"",S_FALSE},
6830             {".txt",S_OK},
6831             {"",S_FALSE},
6832             {"",S_FALSE},
6833             {"",S_FALSE},
6834             {"/relative/path.txt",S_OK},
6835             {"/relative/path.txt",S_OK},
6836             {"",S_FALSE},
6837             {"mk:/relative/path.txt",S_OK},
6838             {"mk",S_OK},
6839             {"",S_FALSE},
6840             {"",S_FALSE}
6841         },
6842         {
6843             {Uri_HOST_UNKNOWN,S_OK},
6844             {0,S_FALSE},
6845             {URL_SCHEME_MK,S_OK},
6846             {URLZONE_INVALID,E_NOTIMPL}
6847         }
6848     },
6849     {   "ml:@MSITSTORE:C:\\dir\\file.chm::/subdir/file.txt",0,
6850         "/relative/path.txt",Uri_CREATE_ALLOW_RELATIVE,
6851         0,S_OK,FALSE,
6852         {
6853             {"ml:/relative/path.txt",S_OK},
6854             {"",S_FALSE},
6855             {"ml:/relative/path.txt",S_OK},
6856             {"",S_FALSE},
6857             {".txt",S_OK},
6858             {"",S_FALSE},
6859             {"",S_FALSE},
6860             {"",S_FALSE},
6861             {"/relative/path.txt",S_OK},
6862             {"/relative/path.txt",S_OK},
6863             {"",S_FALSE},
6864             {"ml:/relative/path.txt",S_OK},
6865             {"ml",S_OK},
6866             {"",S_FALSE},
6867             {"",S_FALSE}
6868         },
6869         {
6870             {Uri_HOST_UNKNOWN,S_OK},
6871             {0,S_FALSE},
6872             {URL_SCHEME_UNKNOWN,S_OK},
6873             {URLZONE_INVALID,E_NOTIMPL}
6874         }
6875     },
6876     {   "http://winehq.org/dir/test?querystring",0,
6877         "//winehq.com/#hash",Uri_CREATE_ALLOW_RELATIVE,
6878         0,S_OK,FALSE,
6879         {
6880             {"http://winehq.com/#hash",S_OK},
6881             {"winehq.com",S_OK},
6882             {"http://winehq.com/#hash",S_OK},
6883             {"winehq.com",S_OK},
6884             {"",S_FALSE},
6885             {"#hash",S_OK},
6886             {"winehq.com",S_OK},
6887             {"",S_FALSE},
6888             {"/",S_OK},
6889             {"/",S_OK},
6890             {"",S_FALSE},
6891             {"http://winehq.com/#hash",S_OK},
6892             {"http",S_OK},
6893             {"",S_FALSE},
6894             {"",S_FALSE}
6895         },
6896         {
6897             {Uri_HOST_DNS,S_OK},
6898             {80,S_OK,FALSE,TRUE},
6899             {URL_SCHEME_HTTP,S_OK},
6900             {URLZONE_INVALID,E_NOTIMPL}
6901         }
6902     },
6903     {   "http://winehq.org/dir/test?querystring",0,
6904         "//winehq.com/dir2/../dir/file.txt?query#hash",Uri_CREATE_ALLOW_RELATIVE,
6905         0,S_OK,FALSE,
6906         {
6907             {"http://winehq.com/dir/file.txt?query#hash",S_OK},
6908             {"winehq.com",S_OK},
6909             {"http://winehq.com/dir/file.txt?query#hash",S_OK},
6910             {"winehq.com",S_OK},
6911             {".txt",S_OK},
6912             {"#hash",S_OK},
6913             {"winehq.com",S_OK},
6914             {"",S_FALSE},
6915             {"/dir/file.txt",S_OK},
6916             {"/dir/file.txt?query",S_OK},
6917             {"?query",S_OK},
6918             {"http://winehq.com/dir/file.txt?query#hash",S_OK},
6919             {"http",S_OK},
6920             {"",S_FALSE},
6921             {"",S_FALSE}
6922         },
6923         {
6924             {Uri_HOST_DNS,S_OK},
6925             {80,S_OK,FALSE,TRUE},
6926             {URL_SCHEME_HTTP,S_OK},
6927             {URLZONE_INVALID,E_NOTIMPL}
6928         }
6929     }
6930 };
6931
6932 typedef struct _uri_parse_test {
6933     const char  *uri;
6934     DWORD       uri_flags;
6935     PARSEACTION action;
6936     DWORD       flags;
6937     const char  *property;
6938     HRESULT     expected;
6939     BOOL        todo;
6940 } uri_parse_test;
6941
6942 static const uri_parse_test uri_parse_tests[] = {
6943     /* PARSE_CANONICALIZE tests. */
6944     {"zip://google.com/test<|>",0,PARSE_CANONICALIZE,0,"zip://google.com/test<|>",S_OK,FALSE},
6945     {"http://google.com/test<|>",0,PARSE_CANONICALIZE,0,"http://google.com/test%3C%7C%3E",S_OK,FALSE},
6946     {"http://google.com/%30%23%3F",0,PARSE_CANONICALIZE,URL_UNESCAPE,"http://google.com/0#?",S_OK,FALSE},
6947     {"test <|>",Uri_CREATE_ALLOW_RELATIVE,PARSE_CANONICALIZE,URL_ESCAPE_UNSAFE,"test %3C%7C%3E",S_OK,FALSE},
6948     {"test <|>",Uri_CREATE_ALLOW_RELATIVE,PARSE_CANONICALIZE,URL_ESCAPE_SPACES_ONLY,"test%20<|>",S_OK,FALSE},
6949     {"test%20<|>",Uri_CREATE_ALLOW_RELATIVE,PARSE_CANONICALIZE,URL_UNESCAPE|URL_ESCAPE_UNSAFE,"test%20%3C%7C%3E",S_OK,FALSE},
6950     {"http://google.com/%20",0,PARSE_CANONICALIZE,URL_ESCAPE_PERCENT,"http://google.com/%2520",S_OK,FALSE},
6951     {"http://google.com/test/../",Uri_CREATE_NO_CANONICALIZE,PARSE_CANONICALIZE,URL_DONT_SIMPLIFY,"http://google.com/test/../",S_OK,FALSE},
6952     {"http://google.com/test/../",Uri_CREATE_NO_CANONICALIZE,PARSE_CANONICALIZE,URL_NO_META,"http://google.com/test/../",S_OK,FALSE},
6953     {"http://google.com/test/../",Uri_CREATE_NO_CANONICALIZE,PARSE_CANONICALIZE,0,"http://google.com/",S_OK,FALSE},
6954     {"zip://google.com/test/../",Uri_CREATE_NO_CANONICALIZE,PARSE_CANONICALIZE,0,"zip://google.com/",S_OK,FALSE},
6955     {"file:///c:/test/../test",Uri_CREATE_NO_CANONICALIZE,PARSE_CANONICALIZE,URL_DONT_SIMPLIFY,"file:///c:/test/../test",S_OK,FALSE},
6956
6957     /* PARSE_FRIENDLY tests. */
6958     {"http://test@google.com/test#test",0,PARSE_FRIENDLY,0,"http://google.com/test#test",S_OK,FALSE},
6959     {"zip://test@google.com/test",0,PARSE_FRIENDLY,0,"zip://test@google.com/test",S_OK,FALSE},
6960
6961     /* PARSE_ROOTDOCUMENT tests. */
6962     {"http://google.com:200/test/test",0,PARSE_ROOTDOCUMENT,0,"http://google.com:200/",S_OK,FALSE},
6963     {"http://google.com",Uri_CREATE_NO_CANONICALIZE,PARSE_ROOTDOCUMENT,0,"http://google.com/",S_OK,FALSE},
6964     {"zip://google.com/",0,PARSE_ROOTDOCUMENT,0,"",S_OK,FALSE},
6965     {"file:///c:/testing/",0,PARSE_ROOTDOCUMENT,0,"",S_OK,FALSE},
6966     {"file://server/test",0,PARSE_ROOTDOCUMENT,0,"",S_OK,FALSE},
6967     {"zip:test/test",0,PARSE_ROOTDOCUMENT,0,"",S_OK,FALSE},
6968
6969     /* PARSE_DOCUMENT tests. */
6970     {"http://test@google.com/test?query#frag",0,PARSE_DOCUMENT,0,"http://test@google.com/test?query",S_OK,FALSE},
6971     {"http:testing#frag",0,PARSE_DOCUMENT,0,"",S_OK,FALSE},
6972     {"file:///c:/test#frag",0,PARSE_DOCUMENT,0,"",S_OK,FALSE},
6973     {"zip://google.com/#frag",0,PARSE_DOCUMENT,0,"",S_OK,FALSE},
6974     {"zip:test#frag",0,PARSE_DOCUMENT,0,"",S_OK,FALSE},
6975     {"testing#frag",Uri_CREATE_ALLOW_RELATIVE,PARSE_DOCUMENT,0,"",S_OK,FALSE},
6976
6977     /* PARSE_PATH_FROM_URL tests. */
6978     {"file:///c:/test.mp3",0,PARSE_PATH_FROM_URL,0,"c:\\test.mp3",S_OK,FALSE},
6979     {"file:///c:/t<|>est.mp3",0,PARSE_PATH_FROM_URL,0,"c:\\t<|>est.mp3",S_OK,FALSE},
6980     {"file:///c:/te%XX t/",0,PARSE_PATH_FROM_URL,0,"c:\\te%XX t\\",S_OK,FALSE},
6981     {"file://server/test",0,PARSE_PATH_FROM_URL,0,"\\\\server\\test",S_OK,FALSE},
6982     {"http://google.com/",0,PARSE_PATH_FROM_URL,0,"",E_INVALIDARG,FALSE},
6983
6984     /* PARSE_URL_FROM_PATH tests. */
6985     /* This function almost seems to useless (just returns the absolute uri). */
6986     {"test.com",Uri_CREATE_ALLOW_RELATIVE,PARSE_URL_FROM_PATH,0,"test.com",S_OK,FALSE},
6987     {"/test/test",Uri_CREATE_ALLOW_RELATIVE,PARSE_URL_FROM_PATH,0,"/test/test",S_OK,FALSE},
6988     {"file://c:\\test\\test",Uri_CREATE_FILE_USE_DOS_PATH,PARSE_URL_FROM_PATH,0,"file://c:\\test\\test",S_OK,FALSE},
6989     {"file:c:/test",0,PARSE_URL_FROM_PATH,0,"",S_OK,FALSE},
6990     {"http:google.com/",0,PARSE_URL_FROM_PATH,0,"",S_OK,FALSE},
6991
6992     /* PARSE_SCHEMA tests. */
6993     {"http://google.com/test",0,PARSE_SCHEMA,0,"http",S_OK,FALSE},
6994     {"test",Uri_CREATE_ALLOW_RELATIVE,PARSE_SCHEMA,0,"",S_OK,FALSE},
6995
6996     /* PARSE_SITE tests. */
6997     {"http://google.uk.com/",0,PARSE_SITE,0,"google.uk.com",S_OK,FALSE},
6998     {"http://google.com.com/",0,PARSE_SITE,0,"google.com.com",S_OK,FALSE},
6999     {"google.com",Uri_CREATE_ALLOW_RELATIVE,PARSE_SITE,0,"",S_OK,FALSE},
7000     {"file://server/test",0,PARSE_SITE,0,"server",S_OK,FALSE},
7001
7002     /* PARSE_DOMAIN tests. */
7003     {"http://google.com.uk/",0,PARSE_DOMAIN,0,"google.com.uk",S_OK,FALSE},
7004     {"http://google.com.com/",0,PARSE_DOMAIN,0,"com.com",S_OK,FALSE},
7005     {"test/test",Uri_CREATE_ALLOW_RELATIVE,PARSE_DOMAIN,0,"",S_OK,FALSE},
7006     {"file://server/test",0,PARSE_DOMAIN,0,"",S_OK,FALSE},
7007
7008     /* PARSE_LOCATION and PARSE_ANCHOR tests. */
7009     {"http://google.com/test#Test",0,PARSE_ANCHOR,0,"#Test",S_OK,FALSE},
7010     {"http://google.com/test#Test",0,PARSE_LOCATION,0,"#Test",S_OK,FALSE},
7011     {"test",Uri_CREATE_ALLOW_RELATIVE,PARSE_ANCHOR,0,"",S_OK,FALSE},
7012     {"test",Uri_CREATE_ALLOW_RELATIVE,PARSE_LOCATION,0,"",S_OK,FALSE}
7013 };
7014
7015 static inline LPWSTR a2w(LPCSTR str) {
7016     LPWSTR ret = NULL;
7017
7018     if(str) {
7019         DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
7020         ret = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
7021         MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len);
7022     }
7023
7024     return ret;
7025 }
7026
7027 static inline BOOL heap_free(void* mem) {
7028     return HeapFree(GetProcessHeap(), 0, mem);
7029 }
7030
7031 static inline DWORD strcmp_aw(LPCSTR strA, LPCWSTR strB) {
7032     LPWSTR strAW = a2w(strA);
7033     DWORD ret = lstrcmpW(strAW, strB);
7034     heap_free(strAW);
7035     return ret;
7036 }
7037
7038 static inline ULONG get_refcnt(IUri *uri) {
7039     IUri_AddRef(uri);
7040     return IUri_Release(uri);
7041 }
7042
7043 static void change_property(IUriBuilder *builder, const uri_builder_property *prop,
7044                             DWORD test_index) {
7045     HRESULT hr;
7046     LPWSTR valueW;
7047
7048     valueW = a2w(prop->value);
7049     switch(prop->property) {
7050     case Uri_PROPERTY_FRAGMENT:
7051         hr = IUriBuilder_SetFragment(builder, valueW);
7052         if(prop->todo) {
7053             todo_wine {
7054                 ok(hr == prop->expected,
7055                     "Error: IUriBuilder_SetFragment returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7056                     hr, prop->expected, test_index);
7057             }
7058         } else {
7059             ok(hr == prop->expected,
7060                 "Error: IUriBuilder_SetFragment returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7061                 hr, prop->expected, test_index);
7062         }
7063         break;
7064     case Uri_PROPERTY_HOST:
7065         hr = IUriBuilder_SetHost(builder, valueW);
7066         if(prop->todo) {
7067             todo_wine {
7068                 ok(hr == prop->expected,
7069                     "Error: IUriBuilder_SetHost returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7070                     hr, prop->expected, test_index);
7071             }
7072         } else {
7073             ok(hr == prop->expected,
7074                 "Error: IUriBuilder_SetHost returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7075                 hr, prop->expected, test_index);
7076         }
7077         break;
7078     case Uri_PROPERTY_PASSWORD:
7079         hr = IUriBuilder_SetPassword(builder, valueW);
7080         if(prop->todo) {
7081             todo_wine {
7082                 ok(hr == prop->expected,
7083                     "Error: IUriBuilder_SetPassword returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7084                     hr, prop->expected, test_index);
7085             }
7086         } else {
7087             ok(hr == prop->expected,
7088                 "Error: IUriBuilder_SetPassword returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7089                 hr, prop->expected, test_index);
7090         }
7091         break;
7092     case Uri_PROPERTY_PATH:
7093         hr = IUriBuilder_SetPath(builder, valueW);
7094         if(prop->todo) {
7095             todo_wine {
7096                 ok(hr == prop->expected,
7097                     "Error: IUriBuilder_SetPath returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7098                     hr, prop->expected, test_index);
7099             }
7100         } else {
7101             ok(hr == prop->expected,
7102                 "Error: IUriBuilder_SetPath returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7103                 hr, prop->expected, test_index);
7104         }
7105         break;
7106     case Uri_PROPERTY_QUERY:
7107         hr = IUriBuilder_SetQuery(builder, valueW);
7108         if(prop->todo) {
7109             todo_wine {
7110                 ok(hr == prop->expected,
7111                     "Error: IUriBuilder_SetQuery returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7112                     hr, prop->expected, test_index);
7113             }
7114         } else {
7115             ok(hr == prop->expected,
7116                 "Error: IUriBuilder_SetQuery returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7117                 hr, prop->expected, test_index);
7118         }
7119         break;
7120     case Uri_PROPERTY_SCHEME_NAME:
7121         hr = IUriBuilder_SetSchemeName(builder, valueW);
7122         if(prop->todo) {
7123             todo_wine {
7124                 ok(hr == prop->expected,
7125                     "Error: IUriBuilder_SetSchemeName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7126                     hr, prop->expected, test_index);
7127             }
7128         } else {
7129             ok(hr == prop->expected,
7130                 "Error: IUriBuilder_SetSchemeName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7131                 hr, prop->expected, test_index);
7132         }
7133         break;
7134     case Uri_PROPERTY_USER_NAME:
7135         hr = IUriBuilder_SetUserName(builder, valueW);
7136         if(prop->todo) {
7137             todo_wine {
7138                 ok(hr == prop->expected,
7139                     "Error: IUriBuilder_SetUserName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7140                     hr, prop->expected, test_index);
7141             }
7142         } else {
7143             ok(hr == prop->expected,
7144                 "Error: IUriBuilder_SetUserName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
7145                 hr, prop->expected, test_index);
7146         }
7147         break;
7148     default:
7149         trace("Unsupported operation for %d on uri_builder_tests[%d].\n", prop->property, test_index);
7150     }
7151
7152     heap_free(valueW);
7153 }
7154
7155 /*
7156  * Simple tests to make sure the CreateUri function handles invalid flag combinations
7157  * correctly.
7158  */
7159 static void test_CreateUri_InvalidFlags(void) {
7160     DWORD i;
7161
7162     for(i = 0; i < sizeof(invalid_flag_tests)/sizeof(invalid_flag_tests[0]); ++i) {
7163         HRESULT hr;
7164         IUri *uri = (void*) 0xdeadbeef;
7165
7166         hr = pCreateUri(http_urlW, invalid_flag_tests[i].flags, 0, &uri);
7167         ok(hr == invalid_flag_tests[i].expected, "Error: CreateUri returned 0x%08x, expected 0x%08x, flags=0x%08x\n",
7168                 hr, invalid_flag_tests[i].expected, invalid_flag_tests[i].flags);
7169         ok(uri == NULL, "Error: expected the IUri to be NULL, but it was %p instead\n", uri);
7170     }
7171 }
7172
7173 static void test_CreateUri_InvalidArgs(void) {
7174     HRESULT hr;
7175     IUri *uri = (void*) 0xdeadbeef;
7176
7177     const WCHAR invalidW[] = {'i','n','v','a','l','i','d',0};
7178     static const WCHAR emptyW[] = {0};
7179
7180     hr = pCreateUri(http_urlW, 0, 0, NULL);
7181     ok(hr == E_INVALIDARG, "Error: CreateUri returned 0x%08x, expected 0x%08x\n", hr, E_INVALIDARG);
7182
7183     hr = pCreateUri(NULL, 0, 0, &uri);
7184     ok(hr == E_INVALIDARG, "Error: CreateUri returned 0x%08x, expected 0x%08x\n", hr, E_INVALIDARG);
7185     ok(uri == NULL, "Error: Expected the IUri to be NULL, but it was %p instead\n", uri);
7186
7187     uri = (void*) 0xdeadbeef;
7188     hr = pCreateUri(invalidW, 0, 0, &uri);
7189     ok(hr == E_INVALIDARG, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
7190     ok(uri == NULL, "Error: Expected the IUri to be NULL, but it was %p instead\n", uri);
7191
7192     uri = (void*) 0xdeadbeef;
7193     hr = pCreateUri(emptyW, 0, 0, &uri);
7194     ok(hr == E_INVALIDARG, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
7195     ok(uri == NULL, "Error: Expected the IUri to be NULL, but it was %p instead\n", uri);
7196 }
7197
7198 static void test_CreateUri_InvalidUri(void) {
7199     DWORD i;
7200
7201     for(i = 0; i < sizeof(invalid_uri_tests)/sizeof(invalid_uri_tests[0]); ++i) {
7202         invalid_uri test = invalid_uri_tests[i];
7203         IUri *uri = NULL;
7204         LPWSTR uriW;
7205         HRESULT hr;
7206
7207         uriW = a2w(test.uri);
7208         hr = pCreateUri(uriW, test.flags, 0, &uri);
7209         if(test.todo) {
7210             todo_wine {
7211                 ok(hr == E_INVALIDARG, "Error: CreateUri returned 0x%08x, expected 0x%08x on invalid_uri_tests[%d].\n",
7212                     hr, E_INVALIDARG, i);
7213             }
7214         } else {
7215             ok(hr == E_INVALIDARG, "Error: CreateUri returned 0x%08x, expected 0x%08x on invalid_uri_tests[%d].\n",
7216                 hr, E_INVALIDARG, i);
7217         }
7218         if(uri) IUri_Release(uri);
7219
7220         heap_free(uriW);
7221     }
7222 }
7223
7224 static void test_IUri_GetPropertyBSTR(void) {
7225     IUri *uri = NULL;
7226     HRESULT hr;
7227     DWORD i;
7228
7229     /* Make sure GetPropertyBSTR handles invalid args correctly. */
7230     hr = pCreateUri(http_urlW, 0, 0, &uri);
7231     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7232     if(SUCCEEDED(hr)) {
7233         BSTR received = NULL;
7234
7235         hr = IUri_GetPropertyBSTR(uri, Uri_PROPERTY_RAW_URI, NULL, 0);
7236         ok(hr == E_POINTER, "Error: GetPropertyBSTR returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
7237
7238         /* Make sure it handles a invalid Uri_PROPERTY's correctly. */
7239         hr = IUri_GetPropertyBSTR(uri, Uri_PROPERTY_PORT, &received, 0);
7240         ok(hr == S_OK, "Error: GetPropertyBSTR returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7241         ok(received != NULL, "Error: Expected the string not to be NULL.\n");
7242         ok(!SysStringLen(received), "Error: Expected the string to be of len=0 but it was %d instead.\n", SysStringLen(received));
7243         SysFreeString(received);
7244
7245         /* Make sure it handles the ZONE property correctly. */
7246         received = NULL;
7247         hr = IUri_GetPropertyBSTR(uri, Uri_PROPERTY_ZONE, &received, 0);
7248         ok(hr == S_FALSE, "Error: GetPropertyBSTR returned 0x%08x, expected 0x%08x.\n", hr, S_FALSE);
7249         ok(received != NULL, "Error: Expected the string not to be NULL.\n");
7250         ok(!SysStringLen(received), "Error: Expected the string to be of len=0 but it was %d instead.\n", SysStringLen(received));
7251         SysFreeString(received);
7252     }
7253     if(uri) IUri_Release(uri);
7254
7255     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
7256         uri_properties test = uri_tests[i];
7257         LPWSTR uriW;
7258         uri = NULL;
7259
7260         uriW = a2w(test.uri);
7261         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
7262         if(test.create_todo) {
7263             todo_wine {
7264                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x. Failed on uri_tests[%d].\n",
7265                         hr, test.create_expected, i);
7266             }
7267         } else {
7268             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x. Failed on uri_tests[%d].\n",
7269                     hr, test.create_expected, i);
7270         }
7271
7272         if(SUCCEEDED(hr)) {
7273             DWORD j;
7274
7275             /* Checks all the string properties of the uri. */
7276             for(j = Uri_PROPERTY_STRING_START; j <= Uri_PROPERTY_STRING_LAST; ++j) {
7277                 BSTR received = NULL;
7278                 uri_str_property prop = test.str_props[j];
7279
7280                 hr = IUri_GetPropertyBSTR(uri, j, &received, 0);
7281                 if(prop.todo) {
7282                     todo_wine {
7283                         ok(hr == prop.expected, "GetPropertyBSTR returned 0x%08x, expected 0x%08x. On uri_tests[%d].str_props[%d].\n",
7284                                 hr, prop.expected, i, j);
7285                     }
7286                     todo_wine {
7287                         ok(!strcmp_aw(prop.value, received) || broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
7288                                 "Expected %s but got %s on uri_tests[%d].str_props[%d].\n",
7289                                 prop.value, wine_dbgstr_w(received), i, j);
7290                     }
7291                 } else {
7292                     ok(hr == prop.expected, "GetPropertyBSTR returned 0x%08x, expected 0x%08x. On uri_tests[%d].str_props[%d].\n",
7293                             hr, prop.expected, i, j);
7294                     ok(!strcmp_aw(prop.value, received) || broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
7295                             "Expected %s but got %s on uri_tests[%d].str_props[%d].\n",
7296                             prop.value, wine_dbgstr_w(received), i, j);
7297                 }
7298
7299                 SysFreeString(received);
7300             }
7301         }
7302
7303         if(uri) IUri_Release(uri);
7304
7305         heap_free(uriW);
7306     }
7307 }
7308
7309 static void test_IUri_GetPropertyDWORD(void) {
7310     IUri *uri = NULL;
7311     HRESULT hr;
7312     DWORD i;
7313
7314     hr = pCreateUri(http_urlW, 0, 0, &uri);
7315     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7316     if(SUCCEEDED(hr)) {
7317         DWORD received = 0xdeadbeef;
7318
7319         hr = IUri_GetPropertyDWORD(uri, Uri_PROPERTY_DWORD_START, NULL, 0);
7320         ok(hr == E_INVALIDARG, "Error: GetPropertyDWORD returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
7321
7322         hr = IUri_GetPropertyDWORD(uri, Uri_PROPERTY_ABSOLUTE_URI, &received, 0);
7323         ok(hr == E_INVALIDARG, "Error: GetPropertyDWORD returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
7324         ok(received == 0, "Error: Expected received=%d but instead received=%d.\n", 0, received);
7325     }
7326     if(uri) IUri_Release(uri);
7327
7328     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
7329         uri_properties test = uri_tests[i];
7330         LPWSTR uriW;
7331         uri = NULL;
7332
7333         uriW = a2w(test.uri);
7334         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
7335         if(test.create_todo) {
7336             todo_wine {
7337                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x. Failed on uri_tests[%d].\n",
7338                         hr, test.create_expected, i);
7339             }
7340         } else {
7341             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x. Failed on uri_tests[%d].\n",
7342                     hr, test.create_expected, i);
7343         }
7344
7345         if(SUCCEEDED(hr)) {
7346             DWORD j;
7347
7348             /* Checks all the DWORD properties of the uri. */
7349             for(j = 0; j < sizeof(test.dword_props)/sizeof(test.dword_props[0]); ++j) {
7350                 DWORD received;
7351                 uri_dword_property prop = test.dword_props[j];
7352
7353                 hr = IUri_GetPropertyDWORD(uri, j+Uri_PROPERTY_DWORD_START, &received, 0);
7354                 if(prop.todo) {
7355                     todo_wine {
7356                         ok(hr == prop.expected, "GetPropertyDWORD returned 0x%08x, expected 0x%08x. On uri_tests[%d].dword_props[%d].\n",
7357                                 hr, prop.expected, i, j);
7358                     }
7359                     todo_wine {
7360                         ok(prop.value == received, "Expected %d but got %d on uri_tests[%d].dword_props[%d].\n",
7361                                 prop.value, received, i, j);
7362                     }
7363                 } else {
7364                     ok(hr == prop.expected, "GetPropertyDWORD returned 0x%08x, expected 0x%08x. On uri_tests[%d].dword_props[%d].\n",
7365                             hr, prop.expected, i, j);
7366                     ok(prop.value == received, "Expected %d but got %d on uri_tests[%d].dword_props[%d].\n",
7367                             prop.value, received, i, j);
7368                 }
7369             }
7370         }
7371
7372         if(uri) IUri_Release(uri);
7373
7374         heap_free(uriW);
7375     }
7376 }
7377
7378 /* Tests all the 'Get*' property functions which deal with strings. */
7379 static void test_IUri_GetStrProperties(void) {
7380     IUri *uri = NULL;
7381     HRESULT hr;
7382     DWORD i;
7383
7384     /* Make sure all the 'Get*' string property functions handle invalid args correctly. */
7385     hr = pCreateUri(http_urlW, 0, 0, &uri);
7386     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7387     if(SUCCEEDED(hr)) {
7388         hr = IUri_GetAbsoluteUri(uri, NULL);
7389         ok(hr == E_POINTER, "Error: GetAbsoluteUri returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
7390
7391         hr = IUri_GetAuthority(uri, NULL);
7392         ok(hr == E_POINTER, "Error: GetAuthority returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
7393
7394         hr = IUri_GetDisplayUri(uri, NULL);
7395         ok(hr == E_POINTER, "Error: GetDisplayUri returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
7396
7397         hr = IUri_GetDomain(uri, NULL);
7398         ok(hr == E_POINTER, "Error: GetDomain returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
7399
7400         hr = IUri_GetExtension(uri, NULL);
7401         ok(hr == E_POINTER, "Error: GetExtension returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
7402
7403         hr = IUri_GetFragment(uri, NULL);
7404         ok(hr == E_POINTER, "Error: GetFragment returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
7405
7406         hr = IUri_GetHost(uri, NULL);
7407         ok(hr == E_POINTER, "Error: GetHost returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
7408
7409         hr = IUri_GetPassword(uri, NULL);
7410         ok(hr == E_POINTER, "Error: GetPassword returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
7411
7412         hr = IUri_GetPath(uri, NULL);
7413         ok(hr == E_POINTER, "Error: GetPath returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
7414
7415         hr = IUri_GetPathAndQuery(uri, NULL);
7416         ok(hr == E_POINTER, "Error: GetPathAndQuery returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
7417
7418         hr = IUri_GetQuery(uri, NULL);
7419         ok(hr == E_POINTER, "Error: GetQuery returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
7420
7421         hr = IUri_GetRawUri(uri, NULL);
7422         ok(hr == E_POINTER, "Error: GetRawUri returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
7423
7424         hr = IUri_GetSchemeName(uri, NULL);
7425         ok(hr == E_POINTER, "Error: GetSchemeName returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
7426
7427         hr = IUri_GetUserInfo(uri, NULL);
7428         ok(hr == E_POINTER, "Error: GetUserInfo returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
7429
7430         hr = IUri_GetUserName(uri, NULL);
7431         ok(hr == E_POINTER, "Error: GetUserName returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
7432     }
7433     if(uri) IUri_Release(uri);
7434
7435     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
7436         uri_properties test = uri_tests[i];
7437         LPWSTR uriW;
7438         uri = NULL;
7439
7440         uriW = a2w(test.uri);
7441         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
7442         if(test.create_todo) {
7443             todo_wine {
7444                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7445                         hr, test.create_expected, i);
7446             }
7447         } else {
7448             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7449                     hr, test.create_expected, i);
7450         }
7451
7452         if(SUCCEEDED(hr)) {
7453             uri_str_property prop;
7454             BSTR received = NULL;
7455
7456             /* GetAbsoluteUri() tests. */
7457             prop = test.str_props[Uri_PROPERTY_ABSOLUTE_URI];
7458             hr = IUri_GetAbsoluteUri(uri, &received);
7459             if(prop.todo) {
7460                 todo_wine {
7461                     ok(hr == prop.expected, "Error: GetAbsoluteUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7462                             hr, prop.expected, i);
7463                 }
7464                 todo_wine {
7465                     ok(!strcmp_aw(prop.value, received) || broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
7466                             "Error: Expected %s but got %s on uri_tests[%d].\n",
7467                             prop.value, wine_dbgstr_w(received), i);
7468                 }
7469             } else {
7470                 ok(hr == prop.expected, "Error: GetAbsoluteUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7471                         hr, prop.expected, i);
7472                 ok(!strcmp_aw(prop.value, received) || broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
7473                         "Error: Expected %s but got %s on uri_tests[%d].\n",
7474                         prop.value, wine_dbgstr_w(received), i);
7475             }
7476             SysFreeString(received);
7477             received = NULL;
7478
7479             /* GetAuthority() tests. */
7480             prop = test.str_props[Uri_PROPERTY_AUTHORITY];
7481             hr = IUri_GetAuthority(uri, &received);
7482             if(prop.todo) {
7483                 todo_wine {
7484                     ok(hr == prop.expected, "Error: GetAuthority returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7485                             hr, prop.expected, i);
7486                 }
7487                 todo_wine {
7488                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
7489                             prop.value, wine_dbgstr_w(received), i);
7490                 }
7491             } else {
7492                 ok(hr == prop.expected, "Error: GetAuthority returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7493                         hr, prop.expected, i);
7494                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
7495                         prop.value, wine_dbgstr_w(received), i);
7496             }
7497             SysFreeString(received);
7498             received = NULL;
7499
7500             /* GetDisplayUri() tests. */
7501             prop = test.str_props[Uri_PROPERTY_DISPLAY_URI];
7502             hr = IUri_GetDisplayUri(uri, &received);
7503             if(prop.todo) {
7504                 todo_wine {
7505                     ok(hr == prop.expected, "Error: GetDisplayUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7506                             hr, prop.expected, i);
7507                 }
7508                 todo_wine {
7509                     ok(!strcmp_aw(prop.value, received) || broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
7510                             "Error: Expected %s but got %s on uri_test[%d].\n",
7511                             prop.value, wine_dbgstr_w(received), i);
7512                 }
7513             } else {
7514                 ok(hr == prop.expected, "Error: GetDisplayUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7515                         hr, prop.expected, i);
7516                 ok(!strcmp_aw(prop.value, received) || broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
7517                         "Error: Expected %s but got %s on uri_tests[%d].\n",
7518                         prop.value, wine_dbgstr_w(received), i);
7519             }
7520             SysFreeString(received);
7521             received = NULL;
7522
7523             /* GetDomain() tests. */
7524             prop = test.str_props[Uri_PROPERTY_DOMAIN];
7525             hr = IUri_GetDomain(uri, &received);
7526             if(prop.todo) {
7527                 todo_wine {
7528                     ok(hr == prop.expected, "Error: GetDomain returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7529                             hr, prop.expected, i);
7530                 }
7531                 todo_wine {
7532                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
7533                             prop.value, wine_dbgstr_w(received), i);
7534                 }
7535             } else {
7536                 ok(hr == prop.expected, "Error: GetDomain returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7537                         hr, prop.expected, i);
7538                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
7539                         prop.value, wine_dbgstr_w(received), i);
7540             }
7541             SysFreeString(received);
7542             received = NULL;
7543
7544             /* GetExtension() tests. */
7545             prop = test.str_props[Uri_PROPERTY_EXTENSION];
7546             hr = IUri_GetExtension(uri, &received);
7547             if(prop.todo) {
7548                 todo_wine {
7549                     ok(hr == prop.expected, "Error: GetExtension returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7550                             hr, prop.expected, i);
7551                 }
7552                 todo_wine {
7553                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
7554                             prop.value, wine_dbgstr_w(received), i);
7555                 }
7556             } else {
7557                 ok(hr == prop.expected, "Error: GetExtension returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7558                         hr, prop.expected, i);
7559                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
7560                         prop.value, wine_dbgstr_w(received), i);
7561             }
7562             SysFreeString(received);
7563             received = NULL;
7564
7565             /* GetFragment() tests. */
7566             prop = test.str_props[Uri_PROPERTY_FRAGMENT];
7567             hr = IUri_GetFragment(uri, &received);
7568             if(prop.todo) {
7569                 todo_wine {
7570                     ok(hr == prop.expected, "Error: GetFragment returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7571                             hr, prop.expected, i);
7572                 }
7573                 todo_wine {
7574                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
7575                             prop.value, wine_dbgstr_w(received), i);
7576                 }
7577             } else {
7578                 ok(hr == prop.expected, "Error: GetFragment returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7579                         hr, prop.expected, i);
7580                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
7581                         prop.value, wine_dbgstr_w(received), i);
7582             }
7583             SysFreeString(received);
7584             received = NULL;
7585
7586             /* GetHost() tests. */
7587             prop = test.str_props[Uri_PROPERTY_HOST];
7588             hr = IUri_GetHost(uri, &received);
7589             if(prop.todo) {
7590                 todo_wine {
7591                     ok(hr == prop.expected, "Error: GetHost returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7592                             hr, prop.expected, i);
7593                 }
7594                 todo_wine {
7595                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
7596                             prop.value, wine_dbgstr_w(received), i);
7597                 }
7598             } else {
7599                 ok(hr == prop.expected, "Error: GetHost returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7600                         hr, prop.expected, i);
7601                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
7602                         prop.value, wine_dbgstr_w(received), i);
7603             }
7604             SysFreeString(received);
7605             received = NULL;
7606
7607             /* GetPassword() tests. */
7608             prop = test.str_props[Uri_PROPERTY_PASSWORD];
7609             hr = IUri_GetPassword(uri, &received);
7610             if(prop.todo) {
7611                 todo_wine {
7612                     ok(hr == prop.expected, "Error: GetPassword returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7613                             hr, prop.expected, i);
7614                 }
7615                 todo_wine {
7616                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
7617                             prop.value, wine_dbgstr_w(received), i);
7618                 }
7619             } else {
7620                 ok(hr == prop.expected, "Error: GetPassword returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7621                         hr, prop.expected, i);
7622                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
7623                         prop.value, wine_dbgstr_w(received), i);
7624             }
7625             SysFreeString(received);
7626             received = NULL;
7627
7628             /* GetPath() tests. */
7629             prop = test.str_props[Uri_PROPERTY_PATH];
7630             hr = IUri_GetPath(uri, &received);
7631             if(prop.todo) {
7632                 todo_wine {
7633                     ok(hr == prop.expected, "Error: GetPath returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7634                             hr, prop.expected, i);
7635                 }
7636                 todo_wine {
7637                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
7638                             prop.value, wine_dbgstr_w(received), i);
7639                 }
7640             } else {
7641                 ok(hr == prop.expected, "Error: GetPath returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7642                         hr, prop.expected, i);
7643                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
7644                         prop.value, wine_dbgstr_w(received), i);
7645             }
7646             SysFreeString(received);
7647             received = NULL;
7648
7649             /* GetPathAndQuery() tests. */
7650             prop = test.str_props[Uri_PROPERTY_PATH_AND_QUERY];
7651             hr = IUri_GetPathAndQuery(uri, &received);
7652             if(prop.todo) {
7653                 todo_wine {
7654                     ok(hr == prop.expected, "Error: GetPathAndQuery returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7655                             hr, prop.expected, i);
7656                 }
7657                 todo_wine {
7658                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
7659                             prop.value, wine_dbgstr_w(received), i);
7660                 }
7661             } else {
7662                 ok(hr == prop.expected, "Error: GetPathAndQuery returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7663                         hr, prop.expected, i);
7664                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
7665                         prop.value, wine_dbgstr_w(received), i);
7666             }
7667             SysFreeString(received);
7668             received = NULL;
7669
7670             /* GetQuery() tests. */
7671             prop = test.str_props[Uri_PROPERTY_QUERY];
7672             hr = IUri_GetQuery(uri, &received);
7673             if(prop.todo) {
7674                 todo_wine {
7675                     ok(hr == prop.expected, "Error: GetQuery returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7676                             hr, prop.expected, i);
7677                 }
7678                 todo_wine {
7679                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
7680                             prop.value, wine_dbgstr_w(received), i);
7681                 }
7682             } else {
7683                 ok(hr == prop.expected, "Error: GetQuery returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7684                         hr, prop.expected, i);
7685                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
7686                         prop.value, wine_dbgstr_w(received), i);
7687             }
7688             SysFreeString(received);
7689             received = NULL;
7690
7691             /* GetRawUri() tests. */
7692             prop = test.str_props[Uri_PROPERTY_RAW_URI];
7693             hr = IUri_GetRawUri(uri, &received);
7694             if(prop.todo) {
7695                 todo_wine {
7696                     ok(hr == prop.expected, "Error: GetRawUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7697                             hr, prop.expected, i);
7698                 }
7699                 todo_wine {
7700                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
7701                             prop.value, wine_dbgstr_w(received), i);
7702                 }
7703             } else {
7704                 ok(hr == prop.expected, "Error: GetRawUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7705                         hr, prop.expected, i);
7706                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
7707                         prop.value, wine_dbgstr_w(received), i);
7708             }
7709             SysFreeString(received);
7710             received = NULL;
7711
7712             /* GetSchemeName() tests. */
7713             prop = test.str_props[Uri_PROPERTY_SCHEME_NAME];
7714             hr = IUri_GetSchemeName(uri, &received);
7715             if(prop.todo) {
7716                 todo_wine {
7717                     ok(hr == prop.expected, "Error: GetSchemeName returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7718                             hr, prop.expected, i);
7719                 }
7720                 todo_wine {
7721                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
7722                             prop.value, wine_dbgstr_w(received), i);
7723                 }
7724             } else {
7725                 ok(hr == prop.expected, "Error: GetSchemeName returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7726                         hr, prop.expected, i);
7727                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
7728                         prop.value, wine_dbgstr_w(received), i);
7729             }
7730             SysFreeString(received);
7731             received = NULL;
7732
7733             /* GetUserInfo() tests. */
7734             prop = test.str_props[Uri_PROPERTY_USER_INFO];
7735             hr = IUri_GetUserInfo(uri, &received);
7736             if(prop.todo) {
7737                 todo_wine {
7738                     ok(hr == prop.expected, "Error: GetUserInfo returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7739                             hr, prop.expected, i);
7740                 }
7741                 todo_wine {
7742                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
7743                             prop.value, wine_dbgstr_w(received), i);
7744                 }
7745             } else {
7746                 ok(hr == prop.expected, "Error: GetUserInfo returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7747                         hr, prop.expected, i);
7748                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
7749                         prop.value, wine_dbgstr_w(received), i);
7750             }
7751             SysFreeString(received);
7752             received = NULL;
7753
7754             /* GetUserName() tests. */
7755             prop = test.str_props[Uri_PROPERTY_USER_NAME];
7756             hr = IUri_GetUserName(uri, &received);
7757             if(prop.todo) {
7758                 todo_wine {
7759                     ok(hr == prop.expected, "Error: GetUserName returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7760                             hr, prop.expected, i);
7761                 }
7762                 todo_wine {
7763                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
7764                             prop.value, wine_dbgstr_w(received), i);
7765                 }
7766             } else {
7767                 ok(hr == prop.expected, "Error: GetUserName returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7768                         hr, prop.expected, i);
7769                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
7770                         prop.value, wine_dbgstr_w(received), i);
7771             }
7772             SysFreeString(received);
7773         }
7774
7775         if(uri) IUri_Release(uri);
7776
7777         heap_free(uriW);
7778     }
7779 }
7780
7781 static void test_IUri_GetDwordProperties(void) {
7782     IUri *uri = NULL;
7783     HRESULT hr;
7784     DWORD i;
7785
7786     /* Make sure all the 'Get*' dword property functions handle invalid args correctly. */
7787     hr = pCreateUri(http_urlW, 0, 0, &uri);
7788     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7789     if(SUCCEEDED(hr)) {
7790         hr = IUri_GetHostType(uri, NULL);
7791         ok(hr == E_INVALIDARG, "Error: GetHostType returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
7792
7793         hr = IUri_GetPort(uri, NULL);
7794         ok(hr == E_INVALIDARG, "Error: GetPort returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
7795
7796         hr = IUri_GetScheme(uri, NULL);
7797         ok(hr == E_INVALIDARG, "Error: GetScheme returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
7798
7799         hr = IUri_GetZone(uri, NULL);
7800         ok(hr == E_INVALIDARG, "Error: GetZone returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
7801     }
7802     if(uri) IUri_Release(uri);
7803
7804     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
7805         uri_properties test = uri_tests[i];
7806         LPWSTR uriW;
7807         uri = NULL;
7808
7809         uriW = a2w(test.uri);
7810         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
7811         if(test.create_todo) {
7812             todo_wine {
7813                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7814                         hr, test.create_expected, i);
7815             }
7816         } else {
7817             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7818                     hr, test.create_expected, i);
7819         }
7820
7821         if(SUCCEEDED(hr)) {
7822             uri_dword_property prop;
7823             DWORD received;
7824
7825             /* Assign an insane value so tests don't accidentally pass when
7826              * they shouldn't!
7827              */
7828             received = -9999999;
7829
7830             /* GetHostType() tests. */
7831             prop = test.dword_props[Uri_PROPERTY_HOST_TYPE-Uri_PROPERTY_DWORD_START];
7832             hr = IUri_GetHostType(uri, &received);
7833             if(prop.todo) {
7834                 todo_wine {
7835                     ok(hr == prop.expected, "Error: GetHostType returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7836                             hr, prop.expected, i);
7837                 }
7838                 todo_wine {
7839                     ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
7840                 }
7841             } else {
7842                 ok(hr == prop.expected, "Error: GetHostType returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7843                         hr, prop.expected, i);
7844                 ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
7845             }
7846             received = -9999999;
7847
7848             /* GetPort() tests. */
7849             prop = test.dword_props[Uri_PROPERTY_PORT-Uri_PROPERTY_DWORD_START];
7850             hr = IUri_GetPort(uri, &received);
7851             if(prop.todo) {
7852                 todo_wine {
7853                     ok(hr == prop.expected, "Error: GetPort returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7854                             hr, prop.expected, i);
7855                 }
7856                 todo_wine {
7857                     ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
7858                 }
7859             } else {
7860                 ok(hr == prop.expected, "Error: GetPort returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7861                         hr, prop.expected, i);
7862                 ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
7863             }
7864             received = -9999999;
7865
7866             /* GetScheme() tests. */
7867             prop = test.dword_props[Uri_PROPERTY_SCHEME-Uri_PROPERTY_DWORD_START];
7868             hr = IUri_GetScheme(uri, &received);
7869             if(prop.todo) {
7870                 todo_wine {
7871                     ok(hr == prop.expected, "Error: GetScheme returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7872                             hr, prop.expected, i);
7873                 }
7874                 todo_wine {
7875                     ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
7876                 }
7877             } else {
7878                 ok(hr == prop.expected, "Error: GetScheme returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7879                         hr, prop.expected, i);
7880                 ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
7881             }
7882             received = -9999999;
7883
7884             /* GetZone() tests. */
7885             prop = test.dword_props[Uri_PROPERTY_ZONE-Uri_PROPERTY_DWORD_START];
7886             hr = IUri_GetZone(uri, &received);
7887             if(prop.todo) {
7888                 todo_wine {
7889                     ok(hr == prop.expected, "Error: GetZone returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7890                             hr, prop.expected, i);
7891                 }
7892                 todo_wine {
7893                     ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
7894                 }
7895             } else {
7896                 ok(hr == prop.expected, "Error: GetZone returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7897                         hr, prop.expected, i);
7898                 ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
7899             }
7900         }
7901
7902         if(uri) IUri_Release(uri);
7903
7904         heap_free(uriW);
7905     }
7906 }
7907
7908 static void test_IUri_GetPropertyLength(void) {
7909     IUri *uri = NULL;
7910     HRESULT hr;
7911     DWORD i;
7912
7913     /* Make sure it handles invalid args correctly. */
7914     hr = pCreateUri(http_urlW, 0, 0, &uri);
7915     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
7916     if(SUCCEEDED(hr)) {
7917         DWORD received = 0xdeadbeef;
7918
7919         hr = IUri_GetPropertyLength(uri, Uri_PROPERTY_STRING_START, NULL, 0);
7920         ok(hr == E_INVALIDARG, "Error: GetPropertyLength returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
7921
7922         hr = IUri_GetPropertyLength(uri, Uri_PROPERTY_DWORD_START, &received, 0);
7923         ok(hr == E_INVALIDARG, "Error: GetPropertyLength return 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
7924         ok(received == 0xdeadbeef, "Error: Expected 0xdeadbeef but got 0x%08x.\n", received);
7925     }
7926     if(uri) IUri_Release(uri);
7927
7928     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
7929         uri_properties test = uri_tests[i];
7930         LPWSTR uriW;
7931         uri = NULL;
7932
7933         uriW = a2w(test.uri);
7934         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
7935         if(test.create_todo) {
7936             todo_wine {
7937                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
7938                         hr, test.create_expected, i);
7939             }
7940         } else {
7941             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_test[%d].\n",
7942                     hr, test.create_expected, i);
7943         }
7944
7945         if(SUCCEEDED(hr)) {
7946             DWORD j;
7947
7948             for(j = Uri_PROPERTY_STRING_START; j <= Uri_PROPERTY_STRING_LAST; ++j) {
7949                 DWORD expectedLen, brokenLen, receivedLen;
7950                 uri_str_property prop = test.str_props[j];
7951
7952                 expectedLen = lstrlen(prop.value);
7953                 brokenLen = lstrlen(prop.broken_value);
7954
7955                 /* This won't be necessary once GetPropertyLength is implemented. */
7956                 receivedLen = -1;
7957
7958                 hr = IUri_GetPropertyLength(uri, j, &receivedLen, 0);
7959                 if(prop.todo) {
7960                     todo_wine {
7961                         ok(hr == prop.expected, "Error: GetPropertyLength returned 0x%08x, expected 0x%08x on uri_tests[%d].str_props[%d].\n",
7962                                 hr, prop.expected, i, j);
7963                     }
7964                     todo_wine {
7965                         ok(receivedLen == expectedLen || broken(receivedLen == brokenLen),
7966                                 "Error: Expected a length of %d but got %d on uri_tests[%d].str_props[%d].\n",
7967                                 expectedLen, receivedLen, i, j);
7968                     }
7969                 } else {
7970                     ok(hr == prop.expected, "Error: GetPropertyLength returned 0x%08x, expected 0x%08x on uri_tests[%d].str_props[%d].\n",
7971                             hr, prop.expected, i, j);
7972                     ok(receivedLen == expectedLen || broken(receivedLen == brokenLen),
7973                             "Error: Expected a length of %d but got %d on uri_tests[%d].str_props[%d].\n",
7974                             expectedLen, receivedLen, i, j);
7975                 }
7976             }
7977         }
7978
7979         if(uri) IUri_Release(uri);
7980
7981         heap_free(uriW);
7982     }
7983 }
7984
7985 static DWORD compute_expected_props(uri_properties *test)
7986 {
7987     DWORD ret = 0, i;
7988
7989     for(i=Uri_PROPERTY_STRING_START; i <= Uri_PROPERTY_STRING_LAST; i++) {
7990         if(test->str_props[i-Uri_PROPERTY_STRING_START].expected == S_OK)
7991             ret |= 1<<i;
7992     }
7993
7994     for(i=Uri_PROPERTY_DWORD_START; i <= Uri_PROPERTY_DWORD_LAST; i++) {
7995         if(test->dword_props[i-Uri_PROPERTY_DWORD_START].expected == S_OK)
7996             ret |= 1<<i;
7997     }
7998
7999     return ret;
8000 }
8001
8002 static void test_IUri_GetProperties(void) {
8003     IUri *uri = NULL;
8004     HRESULT hr;
8005     DWORD i;
8006
8007     hr = pCreateUri(http_urlW, 0, 0, &uri);
8008     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8009     if(SUCCEEDED(hr)) {
8010         hr = IUri_GetProperties(uri, NULL);
8011         ok(hr == E_INVALIDARG, "Error: GetProperties returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
8012     }
8013     if(uri) IUri_Release(uri);
8014
8015     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
8016         uri_properties test = uri_tests[i];
8017         LPWSTR uriW;
8018         uri = NULL;
8019
8020         uriW = a2w(test.uri);
8021         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
8022         if(test.create_todo) {
8023             todo_wine {
8024                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, test.create_expected);
8025             }
8026         } else {
8027             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, test.create_expected);
8028         }
8029
8030         if(SUCCEEDED(hr)) {
8031             DWORD received = 0, expected_props;
8032             DWORD j;
8033
8034             hr = IUri_GetProperties(uri, &received);
8035             ok(hr == S_OK, "Error: GetProperties returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8036
8037             expected_props = compute_expected_props(&test);
8038
8039             for(j = 0; j <= Uri_PROPERTY_DWORD_LAST; ++j) {
8040                 /* (1 << j) converts a Uri_PROPERTY to its corresponding Uri_HAS_* flag mask. */
8041                 if(expected_props & (1 << j))
8042                     ok(received & (1 << j), "Error: Expected flag for property %d on uri_tests[%d].\n", j, i);
8043                 else
8044                     ok(!(received & (1 << j)), "Error: Received flag for property %d when not expected on uri_tests[%d].\n", j, i);
8045             }
8046         }
8047
8048         if(uri) IUri_Release(uri);
8049
8050         heap_free(uriW);
8051     }
8052 }
8053
8054 static void test_IUri_HasProperty(void) {
8055     IUri *uri = NULL;
8056     HRESULT hr;
8057     DWORD i;
8058
8059     hr = pCreateUri(http_urlW, 0, 0, &uri);
8060     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8061     if(SUCCEEDED(hr)) {
8062         hr = IUri_HasProperty(uri, Uri_PROPERTY_RAW_URI, NULL);
8063         ok(hr == E_INVALIDARG, "Error: HasProperty returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
8064     }
8065     if(uri) IUri_Release(uri);
8066
8067     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
8068         uri_properties test = uri_tests[i];
8069         LPWSTR uriW;
8070         uri = NULL;
8071
8072         uriW = a2w(test.uri);
8073
8074         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
8075         if(test.create_todo) {
8076             todo_wine {
8077                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, test.create_expected);
8078             }
8079         } else {
8080             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, test.create_expected);
8081         }
8082
8083         if(SUCCEEDED(hr)) {
8084             DWORD expected_props, j;
8085
8086             expected_props = compute_expected_props(&test);
8087
8088             for(j = 0; j <= Uri_PROPERTY_DWORD_LAST; ++j) {
8089                 /* Assign -1, then explicitly test for TRUE or FALSE later. */
8090                 BOOL received = -1;
8091
8092                 hr = IUri_HasProperty(uri, j, &received);
8093                 ok(hr == S_OK, "Error: HasProperty returned 0x%08x, expected 0x%08x for property %d on uri_tests[%d].\n",
8094                         hr, S_OK, j, i);
8095
8096                 if(expected_props & (1 << j)) {
8097                     ok(received == TRUE, "Error: Expected to have property %d on uri_tests[%d].\n", j, i);
8098                 } else {
8099                     ok(received == FALSE, "Error: Wasn't expecting to have property %d on uri_tests[%d].\n", j, i);
8100                 }
8101             }
8102         }
8103
8104         if(uri) IUri_Release(uri);
8105
8106         heap_free(uriW);
8107     }
8108 }
8109
8110 static void test_IUri_IsEqual(void) {
8111     IUri *uriA, *uriB;
8112     BOOL equal;
8113     HRESULT hres;
8114     DWORD i;
8115
8116     uriA = uriB = NULL;
8117
8118     /* Make sure IsEqual handles invalid args correctly. */
8119     hres = pCreateUri(http_urlW, 0, 0, &uriA);
8120     ok(hres == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hres, S_OK);
8121     hres = pCreateUri(http_urlW, 0, 0, &uriB);
8122     ok(hres == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hres, S_OK);
8123
8124     equal = -1;
8125     hres = IUri_IsEqual(uriA, NULL, &equal);
8126     ok(hres == S_OK, "Error: IsEqual returned 0x%08x, expected 0x%08x.\n", hres, S_OK);
8127     ok(!equal, "Error: Expected equal to be FALSE, but was %d instead.\n", equal);
8128
8129     hres = IUri_IsEqual(uriA, uriB, NULL);
8130     ok(hres == E_POINTER, "Error: IsEqual returned 0x%08x, expected 0x%08x.\n", hres, E_POINTER);
8131
8132     IUri_Release(uriA);
8133     IUri_Release(uriB);
8134
8135     for(i = 0; i < sizeof(equality_tests)/sizeof(equality_tests[0]); ++i) {
8136         uri_equality test = equality_tests[i];
8137         LPWSTR uriA_W, uriB_W;
8138
8139         uriA = uriB = NULL;
8140
8141         uriA_W = a2w(test.a);
8142         uriB_W = a2w(test.b);
8143
8144         hres = pCreateUri(uriA_W, test.create_flags_a, 0, &uriA);
8145         ok(hres == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x on equality_tests[%d].a\n", hres, S_OK, i);
8146
8147         hres = pCreateUri(uriB_W, test.create_flags_b, 0, &uriB);
8148         ok(hres == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x on equality_tests[%d].b\n", hres, S_OK, i);
8149
8150         equal = -1;
8151         hres = IUri_IsEqual(uriA, uriB, &equal);
8152         if(test.todo) todo_wine {
8153             ok(hres == S_OK, "Error: IsEqual returned 0x%08x, expected 0x%08x on equality_tests[%d].\n", hres, S_OK, i);
8154             ok(equal == test.equal, "Error: Expected the comparison to be %d on equality_tests[%d].\n", test.equal, i);
8155         } else {
8156             ok(hres == S_OK, "Error: IsEqual returned 0x%08x, expected 0x%08x on equality_tests[%d].\n", hres, S_OK, i);
8157             ok(equal == test.equal, "Error: Expected the comparison to be %d on equality_tests[%d].\n", test.equal, i);
8158         }
8159         if(uriA) IUri_Release(uriA);
8160         if(uriB) IUri_Release(uriB);
8161
8162         heap_free(uriA_W);
8163         heap_free(uriB_W);
8164     }
8165 }
8166
8167 static void test_CreateUriWithFragment_InvalidArgs(void) {
8168     HRESULT hr;
8169     IUri *uri = (void*) 0xdeadbeef;
8170     const WCHAR fragmentW[] = {'#','f','r','a','g','m','e','n','t',0};
8171
8172     hr = pCreateUriWithFragment(NULL, fragmentW, 0, 0, &uri);
8173     ok(hr == E_INVALIDARG, "Error: CreateUriWithFragment returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
8174     ok(uri == NULL, "Error: Expected uri to be NULL, but was %p instead.\n", uri);
8175
8176     hr = pCreateUriWithFragment(http_urlW, fragmentW, 0, 0, NULL);
8177     ok(hr == E_INVALIDARG, "Error: CreateUriWithFragment returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
8178
8179     /* Original URI can't already contain a fragment component. */
8180     uri = (void*) 0xdeadbeef;
8181     hr = pCreateUriWithFragment(http_url_fragW, fragmentW, 0, 0, &uri);
8182     ok(hr == E_INVALIDARG, "Error: CreateUriWithFragment returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
8183     ok(uri == NULL, "Error: Expected uri to be NULL, but was %p instead.\n", uri);
8184 }
8185
8186 /* CreateUriWithFragment has the same invalid flag combinations as CreateUri. */
8187 static void test_CreateUriWithFragment_InvalidFlags(void) {
8188     DWORD i;
8189
8190     for(i = 0; i < sizeof(invalid_flag_tests)/sizeof(invalid_flag_tests[0]); ++i) {
8191         HRESULT hr;
8192         IUri *uri = (void*) 0xdeadbeef;
8193
8194         hr = pCreateUriWithFragment(http_urlW, NULL, invalid_flag_tests[i].flags, 0, &uri);
8195         ok(hr == invalid_flag_tests[i].expected, "Error: CreateUriWithFragment returned 0x%08x, expected 0x%08x. flags=0x%08x.\n",
8196             hr, invalid_flag_tests[i].expected, invalid_flag_tests[i].flags);
8197         ok(uri == NULL, "Error: Expected uri to be NULL, but was %p instead.\n", uri);
8198     }
8199 }
8200
8201 static void test_CreateUriWithFragment(void) {
8202     DWORD i;
8203
8204     for(i = 0; i < sizeof(uri_fragment_tests)/sizeof(uri_fragment_tests[0]); ++i) {
8205         HRESULT hr;
8206         IUri *uri = NULL;
8207         LPWSTR uriW, fragW;
8208         uri_with_fragment test = uri_fragment_tests[i];
8209
8210         uriW = a2w(test.uri);
8211         fragW = a2w(test.fragment);
8212
8213         hr = pCreateUriWithFragment(uriW, fragW, test.create_flags, 0, &uri);
8214         if(test.expected_todo) {
8215             todo_wine {
8216                 ok(hr == test.create_expected,
8217                     "Error: CreateUriWithFragment returned 0x%08x, expected 0x%08x on uri_fragment_tests[%d].\n",
8218                     hr, test.create_expected, i);
8219             }
8220         } else
8221             ok(hr == test.create_expected,
8222                 "Error: CreateUriWithFragment returned 0x%08x, expected 0x%08x on uri_fragment_tests[%d].\n",
8223                 hr, test.create_expected, i);
8224
8225         if(SUCCEEDED(hr)) {
8226             BSTR received = NULL;
8227
8228             hr = IUri_GetAbsoluteUri(uri, &received);
8229             if(test.expected_todo) {
8230                 todo_wine {
8231                     ok(hr == S_OK,
8232                         "Error: GetAbsoluteUri returned 0x%08x, expected 0x%08x on uri_fragment_tests[%d].\n",
8233                         hr, S_OK, i);
8234                 }
8235                 todo_wine {
8236                     ok(!strcmp_aw(test.expected_uri, received),
8237                         "Error: Expected %s but got %s on uri_fragment_tests[%d].\n",
8238                         test.expected_uri, wine_dbgstr_w(received), i);
8239                 }
8240             } else {
8241                 ok(hr == S_OK, "Error: GetAbsoluteUri returned 0x%08x, expected 0x%08x on uri_fragment_tests[%d].\n",
8242                     hr, S_OK, i);
8243                 ok(!strcmp_aw(test.expected_uri, received), "Error: Expected %s but got %s on uri_fragment_tests[%d].\n",
8244                     test.expected_uri, wine_dbgstr_w(received), i);
8245             }
8246
8247             SysFreeString(received);
8248         }
8249
8250         if(uri) IUri_Release(uri);
8251         heap_free(uriW);
8252         heap_free(fragW);
8253     }
8254 }
8255
8256 static void test_CreateIUriBuilder(void) {
8257     HRESULT hr;
8258     IUriBuilder *builder = NULL;
8259     IUri *uri;
8260
8261     hr = pCreateIUriBuilder(NULL, 0, 0, NULL);
8262     ok(hr == E_POINTER, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x\n",
8263         hr, E_POINTER);
8264
8265     /* CreateIUriBuilder increases the ref count of the IUri it receives. */
8266     hr = pCreateUri(http_urlW, 0, 0, &uri);
8267     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8268     if(SUCCEEDED(hr)) {
8269         ULONG cur_count, orig_count;
8270
8271         orig_count = get_refcnt(uri);
8272         hr = pCreateIUriBuilder(uri, 0, 0, &builder);
8273         ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8274         ok(builder != NULL, "Error: Expecting builder not to be NULL\n");
8275
8276         cur_count = get_refcnt(uri);
8277         ok(cur_count == orig_count+1, "Error: Expected the ref count to be %u, but was %u instead.\n", orig_count+1, cur_count);
8278
8279         if(builder) IUriBuilder_Release(builder);
8280         cur_count = get_refcnt(uri);
8281         ok(cur_count == orig_count, "Error: Expected the ref count to be %u, but was %u instead.\n", orig_count, cur_count);
8282     }
8283     if(uri) IUri_Release(uri);
8284 }
8285
8286 static void test_IUriBuilder_CreateUri(IUriBuilder *builder, const uri_builder_test *test,
8287                                        DWORD test_index) {
8288     HRESULT hr;
8289     IUri *uri = NULL;
8290
8291     hr = IUriBuilder_CreateUri(builder, test->uri_flags, 0, 0, &uri);
8292     if(test->uri_todo) {
8293         todo_wine {
8294             ok(hr == test->uri_hres,
8295                 "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8296                 hr, test->uri_hres, test_index);
8297         }
8298     } else {
8299         ok(hr == test->uri_hres,
8300             "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8301             hr, test->uri_hres, test_index);
8302     }
8303
8304     if(SUCCEEDED(hr)) {
8305         DWORD i;
8306
8307         for(i = 0; i < sizeof(test->expected_str_props)/sizeof(test->expected_str_props[0]); ++i) {
8308             uri_builder_str_property prop = test->expected_str_props[i];
8309             BSTR received = NULL;
8310
8311             hr = IUri_GetPropertyBSTR(uri, i, &received, 0);
8312             if(prop.todo) {
8313                 todo_wine {
8314                     ok(hr == prop.result,
8315                         "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_str_props[%d].\n",
8316                         hr, prop.result, test_index, i);
8317                 }
8318             } else {
8319                 ok(hr == prop.result,
8320                     "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_str_props[%d].\n",
8321                     hr, prop.result, test_index, i);
8322             }
8323             if(SUCCEEDED(hr)) {
8324                 if(prop.todo) {
8325                     todo_wine {
8326                         ok(!strcmp_aw(prop.expected, received),
8327                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].expected_str_props[%d].\n",
8328                             prop.expected, wine_dbgstr_w(received), test_index, i);
8329                     }
8330                 } else {
8331                     ok(!strcmp_aw(prop.expected, received),
8332                         "Error: Expected %s but got %s instead on uri_builder_tests[%d].expected_str_props[%d].\n",
8333                         prop.expected, wine_dbgstr_w(received), test_index, i);
8334                 }
8335             }
8336             SysFreeString(received);
8337         }
8338
8339         for(i = 0; i < sizeof(test->expected_dword_props)/sizeof(test->expected_dword_props[0]); ++i) {
8340             uri_builder_dword_property prop = test->expected_dword_props[i];
8341             DWORD received = -2;
8342
8343             hr = IUri_GetPropertyDWORD(uri, i+Uri_PROPERTY_DWORD_START, &received, 0);
8344             if(prop.todo) {
8345                 todo_wine {
8346                     ok(hr == prop.result,
8347                         "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_dword_props[%d].\n",
8348                         hr, prop.result, test_index, i);
8349                 }
8350             } else {
8351                 ok(hr == prop.result,
8352                     "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_dword_props[%d].\n",
8353                     hr, prop.result, test_index, i);
8354             }
8355             if(SUCCEEDED(hr)) {
8356                 if(prop.todo) {
8357                     todo_wine {
8358                         ok(received == prop.expected,
8359                             "Error: Expected %d but got %d instead on uri_builder_tests[%d].expected_dword_props[%d].\n",
8360                             prop.expected, received, test_index, i);
8361                     }
8362                 } else {
8363                     ok(received == prop.expected,
8364                         "Error: Expected %d but got %d instead on uri_builder_tests[%d].expected_dword_props[%d].\n",
8365                         prop.expected, received, test_index, i);
8366                 }
8367             }
8368         }
8369     }
8370     if(uri) IUri_Release(uri);
8371 }
8372
8373 static void test_IUriBuilder_CreateUriSimple(IUriBuilder *builder, const uri_builder_test *test,
8374                                        DWORD test_index) {
8375     HRESULT hr;
8376     IUri *uri = NULL;
8377
8378     hr = IUriBuilder_CreateUriSimple(builder, test->uri_simple_encode_flags, 0, &uri);
8379     if(test->uri_simple_todo) {
8380         todo_wine {
8381             ok(hr == test->uri_simple_hres,
8382                 "Error: IUriBuilder_CreateUriSimple returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8383                 hr, test->uri_simple_hres, test_index);
8384         }
8385     } else {
8386         ok(hr == test->uri_simple_hres,
8387             "Error: IUriBuilder_CreateUriSimple returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8388             hr, test->uri_simple_hres, test_index);
8389     }
8390
8391     if(SUCCEEDED(hr)) {
8392         DWORD i;
8393
8394         for(i = 0; i < sizeof(test->expected_str_props)/sizeof(test->expected_str_props[0]); ++i) {
8395             uri_builder_str_property prop = test->expected_str_props[i];
8396             BSTR received = NULL;
8397
8398             hr = IUri_GetPropertyBSTR(uri, i, &received, 0);
8399             if(prop.todo) {
8400                 todo_wine {
8401                     ok(hr == prop.result,
8402                         "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_str_props[%d].\n",
8403                         hr, prop.result, test_index, i);
8404                 }
8405             } else {
8406                 ok(hr == prop.result,
8407                     "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_str_props[%d].\n",
8408                     hr, prop.result, test_index, i);
8409             }
8410             if(SUCCEEDED(hr)) {
8411                 if(prop.todo) {
8412                     todo_wine {
8413                         ok(!strcmp_aw(prop.expected, received),
8414                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].expected_str_props[%d].\n",
8415                             prop.expected, wine_dbgstr_w(received), test_index, i);
8416                     }
8417                 } else {
8418                     ok(!strcmp_aw(prop.expected, received),
8419                         "Error: Expected %s but got %s instead on uri_builder_tests[%d].expected_str_props[%d].\n",
8420                         prop.expected, wine_dbgstr_w(received), test_index, i);
8421                 }
8422             }
8423             SysFreeString(received);
8424         }
8425
8426         for(i = 0; i < sizeof(test->expected_dword_props)/sizeof(test->expected_dword_props[0]); ++i) {
8427             uri_builder_dword_property prop = test->expected_dword_props[i];
8428             DWORD received = -2;
8429
8430             hr = IUri_GetPropertyDWORD(uri, i+Uri_PROPERTY_DWORD_START, &received, 0);
8431             if(prop.todo) {
8432                 todo_wine {
8433                     ok(hr == prop.result,
8434                         "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_dword_props[%d].\n",
8435                         hr, prop.result, test_index, i);
8436                 }
8437             } else {
8438                 ok(hr == prop.result,
8439                     "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_dword_props[%d].\n",
8440                     hr, prop.result, test_index, i);
8441             }
8442             if(SUCCEEDED(hr)) {
8443                 if(prop.todo) {
8444                     todo_wine {
8445                         ok(received == prop.expected,
8446                             "Error: Expected %d but got %d instead on uri_builder_tests[%d].expected_dword_props[%d].\n",
8447                             prop.expected, received, test_index, i);
8448                     }
8449                 } else {
8450                     ok(received == prop.expected,
8451                         "Error: Expected %d but got %d instead on uri_builder_tests[%d].expected_dword_props[%d].\n",
8452                         prop.expected, received, test_index, i);
8453                 }
8454             }
8455         }
8456     }
8457     if(uri) IUri_Release(uri);
8458 }
8459
8460 static void test_IUriBuilder_CreateUriWithFlags(IUriBuilder *builder, const uri_builder_test *test,
8461                                                 DWORD test_index) {
8462     HRESULT hr;
8463     IUri *uri = NULL;
8464
8465     hr = IUriBuilder_CreateUriWithFlags(builder, test->uri_with_flags, test->uri_with_builder_flags,
8466                                         test->uri_with_encode_flags, 0, &uri);
8467     if(test->uri_with_todo) {
8468         todo_wine {
8469             ok(hr == test->uri_with_hres,
8470                 "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8471                 hr, test->uri_with_hres, test_index);
8472         }
8473     } else {
8474         ok(hr == test->uri_with_hres,
8475             "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8476             hr, test->uri_with_hres, test_index);
8477     }
8478
8479     if(SUCCEEDED(hr)) {
8480         DWORD i;
8481
8482         for(i = 0; i < sizeof(test->expected_str_props)/sizeof(test->expected_str_props[0]); ++i) {
8483             uri_builder_str_property prop = test->expected_str_props[i];
8484             BSTR received = NULL;
8485
8486             hr = IUri_GetPropertyBSTR(uri, i, &received, 0);
8487             if(prop.todo) {
8488                 todo_wine {
8489                     ok(hr == prop.result,
8490                         "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_str_props[%d].\n",
8491                         hr, prop.result, test_index, i);
8492                 }
8493             } else {
8494                 ok(hr == prop.result,
8495                     "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_str_props[%d].\n",
8496                     hr, prop.result, test_index, i);
8497             }
8498             if(SUCCEEDED(hr)) {
8499                 if(prop.todo) {
8500                     todo_wine {
8501                         ok(!strcmp_aw(prop.expected, received),
8502                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].expected_str_props[%d].\n",
8503                             prop.expected, wine_dbgstr_w(received), test_index, i);
8504                     }
8505                 } else {
8506                     ok(!strcmp_aw(prop.expected, received),
8507                         "Error: Expected %s but got %s instead on uri_builder_tests[%d].expected_str_props[%d].\n",
8508                         prop.expected, wine_dbgstr_w(received), test_index, i);
8509                 }
8510             }
8511             SysFreeString(received);
8512         }
8513
8514         for(i = 0; i < sizeof(test->expected_dword_props)/sizeof(test->expected_dword_props[0]); ++i) {
8515             uri_builder_dword_property prop = test->expected_dword_props[i];
8516             DWORD received = -2;
8517
8518             hr = IUri_GetPropertyDWORD(uri, i+Uri_PROPERTY_DWORD_START, &received, 0);
8519             if(prop.todo) {
8520                 todo_wine {
8521                     ok(hr == prop.result,
8522                         "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_dword_props[%d].\n",
8523                         hr, prop.result, test_index, i);
8524                 }
8525             } else {
8526                 ok(hr == prop.result,
8527                     "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].expected_dword_props[%d].\n",
8528                     hr, prop.result, test_index, i);
8529             }
8530             if(SUCCEEDED(hr)) {
8531                 if(prop.todo) {
8532                     todo_wine {
8533                         ok(received == prop.expected,
8534                             "Error: Expected %d but got %d instead on uri_builder_tests[%d].expected_dword_props[%d].\n",
8535                             prop.expected, received, test_index, i);
8536                     }
8537                 } else {
8538                     ok(received == prop.expected,
8539                         "Error: Expected %d but got %d instead on uri_builder_tests[%d].expected_dword_props[%d].\n",
8540                         prop.expected, received, test_index, i);
8541                 }
8542             }
8543         }
8544     }
8545     if(uri) IUri_Release(uri);
8546 }
8547
8548 static void test_IUriBuilder_CreateInvalidArgs(void) {
8549     IUriBuilder *builder;
8550     HRESULT hr;
8551
8552     hr = pCreateIUriBuilder(NULL, 0, 0, &builder);
8553     ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8554     if(SUCCEEDED(hr)) {
8555         IUri *test = NULL, *uri = (void*) 0xdeadbeef;
8556
8557         /* Test what happens if the IUriBuilder doesn't have a IUri set. */
8558         hr = IUriBuilder_CreateUri(builder, 0, 0, 0, NULL);
8559         ok(hr == E_POINTER, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
8560
8561         uri = (void*) 0xdeadbeef;
8562         hr = IUriBuilder_CreateUri(builder, 0, Uri_HAS_USER_NAME, 0, &uri);
8563         ok(hr == E_NOTIMPL, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, E_NOTIMPL);
8564         ok(uri == NULL, "Error: expected uri to be NULL, but was %p instead.\n", uri);
8565
8566         hr = IUriBuilder_CreateUriSimple(builder, 0, 0, NULL);
8567         ok(hr == E_POINTER, "Error: IUriBuilder_CreateUriSimple returned 0x%08x, expected 0x%08x.\n",
8568             hr, E_POINTER);
8569
8570         uri = (void*) 0xdeadbeef;
8571         hr = IUriBuilder_CreateUriSimple(builder, Uri_HAS_USER_NAME, 0, &uri);
8572         ok(hr == E_NOTIMPL, "Error: IUriBuilder_CreateUriSimple returned 0x%08x, expected 0x%08x.\n",
8573             hr, E_NOTIMPL);
8574         ok(!uri, "Error: Expected uri to NULL, but was %p instead.\n", uri);
8575
8576         hr = IUriBuilder_CreateUriWithFlags(builder, 0, 0, 0, 0, NULL);
8577         ok(hr == E_POINTER, "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x.\n",
8578             hr, E_POINTER);
8579
8580         uri = (void*) 0xdeadbeef;
8581         hr = IUriBuilder_CreateUriWithFlags(builder, 0, 0, Uri_HAS_USER_NAME, 0, &uri);
8582         ok(hr == E_NOTIMPL, "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x.\n",
8583             hr, E_NOTIMPL);
8584         ok(!uri, "Error: Expected uri to be NULL, but was %p instead.\n", uri);
8585
8586         hr = pCreateUri(http_urlW, 0, 0, &test);
8587         ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8588         if(SUCCEEDED(hr)) {
8589             hr = IUriBuilder_SetIUri(builder, test);
8590             ok(hr == S_OK, "Error: IUriBuilder_SetIUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8591
8592             /* No longer returns E_NOTIMPL, since a IUri has been set and hasn't been modified. */
8593             uri = NULL;
8594             hr = IUriBuilder_CreateUri(builder, 0, Uri_HAS_USER_NAME, 0, &uri);
8595             ok(hr == S_OK, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8596             ok(uri != NULL, "Error: The uri was NULL.\n");
8597             if(uri) IUri_Release(uri);
8598
8599             uri = NULL;
8600             hr = IUriBuilder_CreateUriSimple(builder, Uri_HAS_USER_NAME, 0, &uri);
8601             ok(hr == S_OK, "Error: IUriBuilder_CreateUriSimple returned 0x%08x, expected 0x%08x.\n",
8602                 hr, S_OK);
8603             ok(uri != NULL, "Error: uri was NULL.\n");
8604             if(uri) IUri_Release(uri);
8605
8606             uri = NULL;
8607             hr = IUriBuilder_CreateUriWithFlags(builder, 0, 0, 0, 0, &uri);
8608             ok(hr == S_OK, "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x.\n",
8609                 hr, S_OK);
8610             ok(uri != NULL, "Error: uri was NULL.\n");
8611             if(uri) IUri_Release(uri);
8612
8613             hr = IUriBuilder_SetFragment(builder, NULL);
8614             ok(hr == S_OK, "Error: IUriBuilder_SetFragment returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8615
8616             /* The IUriBuilder is changed, so it returns E_NOTIMPL again. */
8617             uri = (void*) 0xdeadbeef;
8618             hr = IUriBuilder_CreateUri(builder, 0, Uri_HAS_USER_NAME, 0, &uri);
8619             ok(hr == E_NOTIMPL, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8620             ok(!uri, "Error: Expected uri to be NULL but was %p instead.\n", uri);
8621
8622             uri = (void*) 0xdeadbeef;
8623             hr = IUriBuilder_CreateUriSimple(builder, Uri_HAS_USER_NAME, 0, &uri);
8624             ok(hr == E_NOTIMPL, "Error: IUriBuilder_CreateUriSimple returned 0x%08x, expected 0x%08x.\n",
8625                 hr, S_OK);
8626             ok(!uri, "Error: Expected uri to be NULL, but was %p instead.\n", uri);
8627
8628             uri = (void*) 0xdeadbeef;
8629             hr = IUriBuilder_CreateUriWithFlags(builder, 0, 0, Uri_HAS_USER_NAME, 0, &uri);
8630             ok(hr == E_NOTIMPL, "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x.\n",
8631                 hr, E_NOTIMPL);
8632             ok(!uri, "Error: Expected uri to be NULL, but was %p instead.\n", uri);
8633         }
8634         if(test) IUri_Release(test);
8635     }
8636     if(builder) IUriBuilder_Release(builder);
8637 }
8638
8639 /* Tests invalid args to the "Get*" functions. */
8640 static void test_IUriBuilder_GetInvalidArgs(void) {
8641     IUriBuilder *builder = NULL;
8642     HRESULT hr;
8643
8644     hr = pCreateIUriBuilder(NULL, 0, 0, &builder);
8645     ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
8646     if(SUCCEEDED(hr)) {
8647         LPCWSTR received = (void*) 0xdeadbeef;
8648         DWORD len = -1, port = -1;
8649         BOOL set = -1;
8650
8651         hr = IUriBuilder_GetFragment(builder, NULL, NULL);
8652         ok(hr == E_POINTER, "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x.\n",
8653             hr, E_POINTER);
8654         hr = IUriBuilder_GetFragment(builder, NULL, &received);
8655         ok(hr == E_POINTER, "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x.\n",
8656             hr, E_POINTER);
8657         ok(!received, "Error: Expected received to be NULL, but was %p instead.\n", received);
8658         hr = IUriBuilder_GetFragment(builder, &len, NULL);
8659         ok(hr == E_POINTER, "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x.\n",
8660             hr, E_POINTER);
8661         ok(!len, "Error: Expected len to be 0, but was %d instead.\n", len);
8662
8663         hr = IUriBuilder_GetHost(builder, NULL, NULL);
8664         ok(hr == E_POINTER, "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x.\n",
8665             hr, E_POINTER);
8666         received = (void*) 0xdeadbeef;
8667         hr = IUriBuilder_GetHost(builder, NULL, &received);
8668         ok(hr == E_POINTER, "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x.\n",
8669             hr, E_POINTER);
8670         ok(!received, "Error: Expected received to be NULL, but was %p instead.\n", received);
8671         len = -1;
8672         hr = IUriBuilder_GetHost(builder, &len, NULL);
8673         ok(hr == E_POINTER, "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x.\n",
8674             hr, E_POINTER);
8675         ok(!len, "Error: Expected len to be 0, but was %d instead.\n", len);
8676
8677         hr = IUriBuilder_GetPassword(builder, NULL, NULL);
8678         ok(hr == E_POINTER, "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x.\n",
8679             hr, E_POINTER);
8680         received = (void*) 0xdeadbeef;
8681         hr = IUriBuilder_GetPassword(builder, NULL, &received);
8682         ok(hr == E_POINTER, "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x.\n",
8683             hr, E_POINTER);
8684         ok(!received, "Error: Expected received to be NULL, but was %p instead.\n", received);
8685         len = -1;
8686         hr = IUriBuilder_GetPassword(builder, &len, NULL);
8687         ok(hr == E_POINTER, "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x.\n",
8688             hr, E_POINTER);
8689         ok(!len, "Error: Expected len to be 0, but was %d instead.\n", len);
8690
8691         hr = IUriBuilder_GetPath(builder, NULL, NULL);
8692         ok(hr == E_POINTER, "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x.\n",
8693             hr, E_POINTER);
8694         received = (void*) 0xdeadbeef;
8695         hr = IUriBuilder_GetPath(builder, NULL, &received);
8696         ok(hr == E_POINTER, "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x.\n",
8697             hr, E_POINTER);
8698         ok(!received, "Error: Expected received to be NULL, but was %p instead.\n", received);
8699         len = -1;
8700         hr = IUriBuilder_GetPath(builder, &len, NULL);
8701         ok(hr == E_POINTER, "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x.\n",
8702             hr, E_POINTER);
8703         ok(!len, "Error: Expected len to be 0, but was %d instead.\n", len);
8704
8705         hr = IUriBuilder_GetPort(builder, NULL, NULL);
8706         ok(hr == E_POINTER, "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x.\n",
8707             hr, E_POINTER);
8708         hr = IUriBuilder_GetPort(builder, NULL, &port);
8709         ok(hr == E_POINTER, "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x.\n",
8710             hr, E_POINTER);
8711         ok(!port, "Error: Expected port to be 0, but was %d instead.\n", port);
8712         hr = IUriBuilder_GetPort(builder, &set, NULL);
8713         ok(hr == E_POINTER, "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x.\n",
8714             hr, E_POINTER);
8715         ok(!set, "Error: Expected set to be FALSE, but was %d instead.\n", set);
8716
8717         hr = IUriBuilder_GetQuery(builder, NULL, NULL);
8718         ok(hr == E_POINTER, "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x.\n",
8719             hr, E_POINTER);
8720         received = (void*) 0xdeadbeef;
8721         hr = IUriBuilder_GetQuery(builder, NULL, &received);
8722         ok(hr == E_POINTER, "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x.\n",
8723             hr, E_POINTER);
8724         ok(!received, "Error: Expected received to be NULL, but was %p instead.\n", received);
8725         len = -1;
8726         hr = IUriBuilder_GetQuery(builder, &len, NULL);
8727         ok(hr == E_POINTER, "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x.\n",
8728             hr, E_POINTER);
8729         ok(!len, "Error: Expected len to be 0, but was %d instead.\n", len);
8730
8731         hr = IUriBuilder_GetSchemeName(builder, NULL, NULL);
8732         ok(hr == E_POINTER, "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x.\n",
8733             hr, E_POINTER);
8734         received = (void*) 0xdeadbeef;
8735         hr = IUriBuilder_GetSchemeName(builder, NULL, &received);
8736         ok(hr == E_POINTER, "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x.\n",
8737             hr, E_POINTER);
8738         ok(!received, "Error: Expected received to be NULL, but was %p instead.\n", received);
8739         len = -1;
8740         hr = IUriBuilder_GetSchemeName(builder, &len, NULL);
8741         ok(hr == E_POINTER, "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x.\n",
8742             hr, E_POINTER);
8743         ok(!len, "Error: Expected len to be 0, but was %d instead.\n", len);
8744
8745         hr = IUriBuilder_GetUserName(builder, NULL, NULL);
8746         ok(hr == E_POINTER, "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x.\n",
8747             hr, E_POINTER);
8748         received = (void*) 0xdeadbeef;
8749         hr = IUriBuilder_GetUserName(builder, NULL, &received);
8750         ok(hr == E_POINTER, "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x.\n",
8751             hr, E_POINTER);
8752         ok(!received, "Error: Expected received to be NULL, but was %p instead.\n", received);
8753         len = -1;
8754         hr = IUriBuilder_GetUserName(builder, &len, NULL);
8755         ok(hr == E_POINTER, "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x.\n",
8756             hr, E_POINTER);
8757         ok(!len, "Error: Expected len to be 0, but was %d instead.\n", len);
8758     }
8759     if(builder) IUriBuilder_Release(builder);
8760 }
8761
8762 static void test_IUriBuilder_GetFragment(IUriBuilder *builder, const uri_builder_test *test,
8763                                          DWORD test_index) {
8764     HRESULT hr;
8765     DWORD i;
8766     LPCWSTR received = NULL;
8767     DWORD len = -1;
8768     const uri_builder_property *prop = NULL;
8769
8770     /* Check if the property was set earlier. */
8771     for(i = 0; i < sizeof(test->properties)/sizeof(test->properties[0]); ++i) {
8772         if(test->properties[i].change && test->properties[i].property == Uri_PROPERTY_FRAGMENT)
8773             prop = &(test->properties[i]);
8774     }
8775
8776     if(prop) {
8777         /* Use expected_value unless it's NULL, then use value. */
8778         LPCSTR expected = prop->expected_value ? prop->expected_value : prop->value;
8779         hr = IUriBuilder_GetFragment(builder, &len, &received);
8780         if(prop->todo) {
8781             todo_wine {
8782                 ok(hr == (expected ? S_OK : S_FALSE),
8783                     "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8784                     hr, (expected ? S_OK : S_FALSE), test_index);
8785             }
8786             if(SUCCEEDED(hr)) {
8787                 todo_wine {
8788                     ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
8789                         expected, wine_dbgstr_w(received), test_index);
8790                 }
8791                 todo_wine {
8792                     ok(lstrlen(expected) == len,
8793                         "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8794                         lstrlen(expected), len, test_index);
8795                 }
8796             }
8797         } else {
8798             ok(hr == (expected ? S_OK : S_FALSE),
8799                 "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8800                 hr, (expected ? S_OK : S_FALSE), test_index);
8801             ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
8802                 expected, wine_dbgstr_w(received), test_index);
8803             ok(lstrlen(expected) == len,
8804                 "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8805                 lstrlen(expected), len, test_index);
8806         }
8807     } else {
8808         /* The property wasn't set earlier, so it should return whatever
8809          * the base IUri contains (if anything).
8810          */
8811         IUri *uri = NULL;
8812         hr = IUriBuilder_GetIUri(builder, &uri);
8813         ok(hr == S_OK,
8814             "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8815             hr, S_OK, test_index);
8816         if(SUCCEEDED(hr)) {
8817             if(!uri) {
8818                 received = (void*) 0xdeadbeef;
8819                 len = -1;
8820
8821                 hr = IUriBuilder_GetFragment(builder, &len, &received);
8822                 ok(hr == S_FALSE,
8823                     "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8824                     hr, S_FALSE, test_index);
8825                 if(SUCCEEDED(hr)) {
8826                     ok(!len, "Error: Expected len to be 0, but was %d instead on uri_builder_tests[%d].\n",
8827                         len, test_index);
8828                     ok(!received, "Error: Expected received to be NULL, but was %p instead on uri_builder_tests[%d].\n",
8829                         received, test_index);
8830                 }
8831             } else {
8832                 BOOL has_prop = FALSE;
8833                 BSTR expected = NULL;
8834
8835                 hr = IUri_GetFragment(uri, &expected);
8836                 ok(SUCCEEDED(hr),
8837                     "Error: Expected IUri_GetFragment to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
8838                     hr, test_index);
8839                 has_prop = hr == S_OK;
8840
8841                 hr = IUriBuilder_GetFragment(builder, &len, &received);
8842                 if(has_prop) {
8843                     ok(hr == S_OK,
8844                         "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8845                         hr, S_OK, test_index);
8846                     if(SUCCEEDED(hr)) {
8847                         ok(!lstrcmpW(expected, received),
8848                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].\n",
8849                             wine_dbgstr_w(expected), wine_dbgstr_w(received), test_index);
8850                         ok(lstrlenW(expected) == len,
8851                             "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8852                             lstrlenW(expected), len, test_index);
8853                     }
8854                 } else {
8855                     ok(hr == S_FALSE,
8856                         "Error: IUriBuilder_GetFragment returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8857                         hr, S_FALSE, test_index);
8858                     if(SUCCEEDED(hr)) {
8859                         ok(!received, "Error: Expected received to be NULL on uri_builder_tests[%d].\n", test_index);
8860                         ok(!len, "Error: Expected the length to be 0, but was %d instead on uri_builder_tests[%d].\n",
8861                             len, test_index);
8862                     }
8863                 }
8864                 SysFreeString(expected);
8865             }
8866         }
8867         if(uri) IUri_Release(uri);
8868     }
8869 }
8870
8871 static void test_IUriBuilder_GetHost(IUriBuilder *builder, const uri_builder_test *test,
8872                                      DWORD test_index) {
8873     HRESULT hr;
8874     DWORD i;
8875     LPCWSTR received = NULL;
8876     DWORD len = -1;
8877     const uri_builder_property *prop = NULL;
8878
8879     /* Check if the property was set earlier. */
8880     for(i = 0; i < sizeof(test->properties)/sizeof(test->properties[0]); ++i) {
8881         if(test->properties[i].change && test->properties[i].property == Uri_PROPERTY_HOST)
8882             prop = &(test->properties[i]);
8883     }
8884
8885     if(prop) {
8886         /* Use expected_value unless it's NULL, then use value. */
8887         LPCSTR expected = prop->expected_value ? prop->expected_value : prop->value;
8888         hr = IUriBuilder_GetHost(builder, &len, &received);
8889         if(prop->todo) {
8890             todo_wine {
8891                 ok(hr == (expected ? S_OK : S_FALSE),
8892                     "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8893                     hr, (expected ? S_OK : S_FALSE), test_index);
8894             }
8895             if(SUCCEEDED(hr)) {
8896                 todo_wine {
8897                     ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
8898                         expected, wine_dbgstr_w(received), test_index);
8899                 }
8900                 todo_wine {
8901                     ok(lstrlen(expected) == len,
8902                         "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8903                         lstrlen(expected), len, test_index);
8904                 }
8905             }
8906         } else {
8907             ok(hr == (expected ? S_OK : S_FALSE),
8908                 "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8909                 hr, (expected ? S_OK : S_FALSE), test_index);
8910             ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
8911                 expected, wine_dbgstr_w(received), test_index);
8912             ok(lstrlen(expected) == len,
8913                 "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8914                 lstrlen(expected), len, test_index);
8915         }
8916     } else {
8917         /* The property wasn't set earlier, so it should return whatever
8918          * the base IUri contains (if anything).
8919          */
8920         IUri *uri = NULL;
8921         hr = IUriBuilder_GetIUri(builder, &uri);
8922         ok(hr == S_OK,
8923             "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8924             hr, S_OK, test_index);
8925         if(SUCCEEDED(hr)) {
8926             if(!uri) {
8927                 received = (void*) 0xdeadbeef;
8928                 len = -1;
8929
8930                 hr = IUriBuilder_GetHost(builder, &len, &received);
8931                 ok(hr == S_FALSE,
8932                     "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8933                     hr, S_FALSE, test_index);
8934                 if(SUCCEEDED(hr)) {
8935                     ok(!len, "Error: Expected len to be 0, but was %d instead on uri_builder_tests[%d].\n",
8936                         len, test_index);
8937                     ok(!received, "Error: Expected received to be NULL, but was %p instead on uri_builder_tests[%d].\n",
8938                         received, test_index);
8939                 }
8940             } else {
8941                 BOOL has_prop = FALSE;
8942                 BSTR expected = NULL;
8943
8944                 hr = IUri_GetHost(uri, &expected);
8945                 ok(SUCCEEDED(hr),
8946                     "Error: Expected IUri_GetHost to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
8947                     hr, test_index);
8948                 has_prop = hr == S_OK;
8949
8950                 hr = IUriBuilder_GetHost(builder, &len, &received);
8951                 if(has_prop) {
8952                     ok(hr == S_OK,
8953                         "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8954                         hr, S_OK, test_index);
8955                     if(SUCCEEDED(hr)) {
8956                         ok(!lstrcmpW(expected, received),
8957                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].\n",
8958                             wine_dbgstr_w(expected), wine_dbgstr_w(received), test_index);
8959                         ok(lstrlenW(expected) == len,
8960                             "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
8961                             lstrlenW(expected), len, test_index);
8962                     }
8963                 } else {
8964                     ok(hr == S_FALSE,
8965                         "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
8966                         hr, S_FALSE, test_index);
8967                     if(SUCCEEDED(hr)) {
8968                         ok(!received, "Error: Expected received to be NULL on uri_builder_tests[%d].\n", test_index);
8969                         ok(!len, "Error: Expected the length to be 0, but was %d instead on uri_builder_tests[%d].\n",
8970                             len, test_index);
8971                     }
8972                 }
8973                 SysFreeString(expected);
8974             }
8975         }
8976         if(uri) IUri_Release(uri);
8977     }
8978 }
8979
8980 static void test_IUriBuilder_GetPassword(IUriBuilder *builder, const uri_builder_test *test,
8981                                          DWORD test_index) {
8982     HRESULT hr;
8983     DWORD i;
8984     LPCWSTR received = NULL;
8985     DWORD len = -1;
8986     const uri_builder_property *prop = NULL;
8987
8988     /* Check if the property was set earlier. */
8989     for(i = 0; i < sizeof(test->properties)/sizeof(test->properties[0]); ++i) {
8990         if(test->properties[i].change && test->properties[i].property == Uri_PROPERTY_PASSWORD)
8991             prop = &(test->properties[i]);
8992     }
8993
8994     if(prop) {
8995         /* Use expected_value unless it's NULL, then use value. */
8996         LPCSTR expected = prop->expected_value ? prop->expected_value : prop->value;
8997         hr = IUriBuilder_GetPassword(builder, &len, &received);
8998         if(prop->todo) {
8999             todo_wine {
9000                 ok(hr == (expected ? S_OK : S_FALSE),
9001                     "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9002                     hr, (expected ? S_OK : S_FALSE), test_index);
9003             }
9004             if(SUCCEEDED(hr)) {
9005                 todo_wine {
9006                     ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
9007                         expected, wine_dbgstr_w(received), test_index);
9008                 }
9009                 todo_wine {
9010                     ok(lstrlen(expected) == len,
9011                         "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
9012                         lstrlen(expected), len, test_index);
9013                 }
9014             }
9015         } else {
9016             ok(hr == (expected ? S_OK : S_FALSE),
9017                 "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9018                 hr, (expected ? S_OK : S_FALSE), test_index);
9019             ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
9020                 expected, wine_dbgstr_w(received), test_index);
9021             ok(lstrlen(expected) == len,
9022                 "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
9023                 lstrlen(expected), len, test_index);
9024         }
9025     } else {
9026         /* The property wasn't set earlier, so it should return whatever
9027          * the base IUri contains (if anything).
9028          */
9029         IUri *uri = NULL;
9030         hr = IUriBuilder_GetIUri(builder, &uri);
9031         ok(hr == S_OK,
9032             "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9033             hr, S_OK, test_index);
9034         if(SUCCEEDED(hr)) {
9035             if(!uri) {
9036                 received = (void*) 0xdeadbeef;
9037                 len = -1;
9038
9039                 hr = IUriBuilder_GetPassword(builder, &len, &received);
9040                 ok(hr == S_FALSE,
9041                     "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9042                     hr, S_FALSE, test_index);
9043                 if(SUCCEEDED(hr)) {
9044                     ok(!len, "Error: Expected len to be 0, but was %d instead on uri_builder_tests[%d].\n",
9045                         len, test_index);
9046                     ok(!received, "Error: Expected received to be NULL, but was %p instead on uri_builder_tests[%d].\n",
9047                         received, test_index);
9048                 }
9049             } else {
9050                 BOOL has_prop = FALSE;
9051                 BSTR expected = NULL;
9052
9053                 hr = IUri_GetPassword(uri, &expected);
9054                 ok(SUCCEEDED(hr),
9055                     "Error: Expected IUri_GetPassword to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
9056                     hr, test_index);
9057                 has_prop = hr == S_OK;
9058
9059                 hr = IUriBuilder_GetPassword(builder, &len, &received);
9060                 if(has_prop) {
9061                     ok(hr == S_OK,
9062                         "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9063                         hr, S_OK, test_index);
9064                     if(SUCCEEDED(hr)) {
9065                         ok(!lstrcmpW(expected, received),
9066                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].\n",
9067                             wine_dbgstr_w(expected), wine_dbgstr_w(received), test_index);
9068                         ok(lstrlenW(expected) == len,
9069                             "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
9070                             lstrlenW(expected), len, test_index);
9071                     }
9072                 } else {
9073                     ok(hr == S_FALSE,
9074                         "Error: IUriBuilder_GetPassword returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9075                         hr, S_FALSE, test_index);
9076                     if(SUCCEEDED(hr)) {
9077                         ok(!received, "Error: Expected received to be NULL on uri_builder_tests[%d].\n", test_index);
9078                         ok(!len, "Error: Expected the length to be 0, but was %d instead on uri_builder_tests[%d].\n",
9079                             len, test_index);
9080                     }
9081                 }
9082                 SysFreeString(expected);
9083             }
9084         }
9085         if(uri) IUri_Release(uri);
9086     }
9087 }
9088
9089 static void test_IUriBuilder_GetPath(IUriBuilder *builder, const uri_builder_test *test,
9090                                      DWORD test_index) {
9091     HRESULT hr;
9092     DWORD i;
9093     LPCWSTR received = NULL;
9094     DWORD len = -1;
9095     const uri_builder_property *prop = NULL;
9096
9097     /* Check if the property was set earlier. */
9098     for(i = 0; i < sizeof(test->properties)/sizeof(test->properties[0]); ++i) {
9099         if(test->properties[i].change && test->properties[i].property == Uri_PROPERTY_PATH)
9100             prop = &(test->properties[i]);
9101     }
9102
9103     if(prop) {
9104         /* Use expected_value unless it's NULL, then use value. */
9105         LPCSTR expected = prop->expected_value ? prop->expected_value : prop->value;
9106         hr = IUriBuilder_GetPath(builder, &len, &received);
9107         if(prop->todo) {
9108             todo_wine {
9109                 ok(hr == (expected ? S_OK : S_FALSE),
9110                     "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9111                     hr, (expected ? S_OK : S_FALSE), test_index);
9112             }
9113             if(SUCCEEDED(hr)) {
9114                 todo_wine {
9115                     ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
9116                         expected, wine_dbgstr_w(received), test_index);
9117                 }
9118                 todo_wine {
9119                     ok(lstrlen(expected) == len,
9120                         "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
9121                         lstrlen(expected), len, test_index);
9122                 }
9123             }
9124         } else {
9125             ok(hr == (expected ? S_OK : S_FALSE),
9126                 "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9127                 hr, (expected ? S_OK : S_FALSE), test_index);
9128             ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
9129                 expected, wine_dbgstr_w(received), test_index);
9130             ok(lstrlen(expected) == len,
9131                 "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
9132                 lstrlen(expected), len, test_index);
9133         }
9134     } else {
9135         /* The property wasn't set earlier, so it should return whatever
9136          * the base IUri contains (if anything).
9137          */
9138         IUri *uri = NULL;
9139         hr = IUriBuilder_GetIUri(builder, &uri);
9140         ok(hr == S_OK,
9141             "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9142             hr, S_OK, test_index);
9143         if(SUCCEEDED(hr)) {
9144             if(!uri) {
9145                 received = (void*) 0xdeadbeef;
9146                 len = -1;
9147
9148                 hr = IUriBuilder_GetPath(builder, &len, &received);
9149                 ok(hr == S_FALSE,
9150                     "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9151                     hr, S_FALSE, test_index);
9152                 if(SUCCEEDED(hr)) {
9153                     ok(!len, "Error: Expected len to be 0, but was %d instead on uri_builder_tests[%d].\n",
9154                         len, test_index);
9155                     ok(!received, "Error: Expected received to be NULL, but was %p instead on uri_builder_tests[%d].\n",
9156                         received, test_index);
9157                 }
9158             } else {
9159                 BOOL has_prop = FALSE;
9160                 BSTR expected = NULL;
9161
9162                 hr = IUri_GetPath(uri, &expected);
9163                 ok(SUCCEEDED(hr),
9164                     "Error: Expected IUri_GetPath to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
9165                     hr, test_index);
9166                 has_prop = hr == S_OK;
9167
9168                 hr = IUriBuilder_GetPath(builder, &len, &received);
9169                 if(has_prop) {
9170                     ok(hr == S_OK,
9171                         "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9172                         hr, S_OK, test_index);
9173                     if(SUCCEEDED(hr)) {
9174                         ok(!lstrcmpW(expected, received),
9175                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].\n",
9176                             wine_dbgstr_w(expected), wine_dbgstr_w(received), test_index);
9177                         ok(lstrlenW(expected) == len,
9178                             "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
9179                             lstrlenW(expected), len, test_index);
9180                     }
9181                 } else {
9182                     ok(hr == S_FALSE,
9183                         "Error: IUriBuilder_GetPath returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9184                         hr, S_FALSE, test_index);
9185                     if(SUCCEEDED(hr)) {
9186                         ok(!received, "Error: Expected received to be NULL on uri_builder_tests[%d].\n", test_index);
9187                         ok(!len, "Error: Expected the length to be 0, but was %d instead on uri_builder_tests[%d].\n",
9188                             len, test_index);
9189                     }
9190                 }
9191                 SysFreeString(expected);
9192             }
9193         }
9194         if(uri) IUri_Release(uri);
9195     }
9196 }
9197
9198 static void test_IUriBuilder_GetPort(IUriBuilder *builder, const uri_builder_test *test,
9199                                      DWORD test_index) {
9200     HRESULT hr;
9201     BOOL has_port = FALSE;
9202     DWORD received = -1;
9203
9204     if(test->port_prop.change) {
9205         DWORD expected = test->port_prop.value;
9206
9207         hr = IUriBuilder_GetPort(builder, &has_port, &received);
9208         if(test->port_prop.todo) {
9209             todo_wine {
9210                 ok(hr == S_OK,
9211                     "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9212                     hr, S_OK, test_index);
9213             }
9214             if(SUCCEEDED(hr)) {
9215                 todo_wine {
9216                     ok(has_port == test->port_prop.set,
9217                         "Error: Expected has_port to be %d but was %d instead on uri_builder_tests[%d].\n",
9218                         test->port_prop.set, has_port, test_index);
9219                 }
9220                 todo_wine {
9221                     ok(received == expected,
9222                         "Error: Expected received to be %d, but was %d instead on uri_builder_tests[%d].\n",
9223                         expected, received, test_index);
9224                 }
9225             }
9226         } else {
9227             ok(hr == S_OK,
9228                 "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9229                 hr, S_OK, test_index);
9230             ok(has_port == test->port_prop.set,
9231                 "Error: Expected has_port to be %d, but was %d instead on uri_builder_tests[%d].\n",
9232                 test->port_prop.set, has_port, test_index);
9233             ok(received == test->port_prop.value,
9234                 "Error: Expected port to be %d, but was %d instead on uri_builder_tests[%d].\n",
9235                 test->port_prop.value, received, test_index);
9236         }
9237     } else {
9238         IUri *uri = NULL;
9239
9240         hr = IUriBuilder_GetIUri(builder, &uri);
9241         ok(hr == S_OK,
9242             "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9243             hr, S_OK, test_index);
9244         if(SUCCEEDED(hr)) {
9245             if(!uri) {
9246                 hr = IUriBuilder_GetPort(builder, &has_port, &received);
9247                 ok(hr == S_OK,
9248                     "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9249                     hr, S_OK, test_index);
9250                 if(SUCCEEDED(hr)) {
9251                     ok(has_port == FALSE,
9252                         "Error: Expected has_port to be FALSE, but was %d instead on uri_builder_tests[%d].\n",
9253                         has_port, test_index);
9254                     ok(!received, "Error: Expected received to be 0, but was %d instead on uri_builder_tests[%d].\n",
9255                         received, test_index);
9256                 }
9257             } else {
9258                 DWORD expected;
9259
9260                 hr = IUri_GetPort(uri, &expected);
9261                 ok(SUCCEEDED(hr),
9262                     "Error: Expected IUri_Port to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
9263                     hr, test_index);
9264
9265                 hr = IUriBuilder_GetPort(builder, &has_port, &received);
9266                 ok(hr == S_OK,
9267                     "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9268                     hr, S_OK, test_index);
9269                 if(SUCCEEDED(hr)) {
9270                     ok(!has_port,
9271                         "Error: Expected has_port to be FALSE but was TRUE instead on uri_builder_tests[%d].\n",
9272                         test_index);
9273                     ok(received == expected,
9274                         "Error: Expected received to be %d, but was %d instead on uri_builder_tests[%d].\n",
9275                         expected, received, test_index);
9276                 }
9277             }
9278         }
9279         if(uri) IUri_Release(uri);
9280     }
9281 }
9282
9283 static void test_IUriBuilder_GetQuery(IUriBuilder *builder, const uri_builder_test *test,
9284                                       DWORD test_index) {
9285     HRESULT hr;
9286     DWORD i;
9287     LPCWSTR received = NULL;
9288     DWORD len = -1;
9289     const uri_builder_property *prop = NULL;
9290
9291     /* Check if the property was set earlier. */
9292     for(i = 0; i < sizeof(test->properties)/sizeof(test->properties[0]); ++i) {
9293         if(test->properties[i].change && test->properties[i].property == Uri_PROPERTY_QUERY)
9294             prop = &(test->properties[i]);
9295     }
9296
9297     if(prop) {
9298         /* Use expected_value unless it's NULL, then use value. */
9299         LPCSTR expected = prop->expected_value ? prop->expected_value : prop->value;
9300         hr = IUriBuilder_GetQuery(builder, &len, &received);
9301         if(prop->todo) {
9302             todo_wine {
9303                 ok(hr == (expected ? S_OK : S_FALSE),
9304                     "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9305                     hr, (expected ? S_OK : S_FALSE), test_index);
9306             }
9307             if(SUCCEEDED(hr)) {
9308                 todo_wine {
9309                     ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
9310                         expected, wine_dbgstr_w(received), test_index);
9311                 }
9312                 todo_wine {
9313                     ok(lstrlen(expected) == len,
9314                         "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
9315                         lstrlen(expected), len, test_index);
9316                 }
9317             }
9318         } else {
9319             ok(hr == (expected ? S_OK : S_FALSE),
9320                 "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9321                 hr, (expected ? S_OK : S_FALSE), test_index);
9322             ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
9323                 expected, wine_dbgstr_w(received), test_index);
9324             ok(lstrlen(expected) == len,
9325                 "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
9326                 lstrlen(expected), len, test_index);
9327         }
9328     } else {
9329         /* The property wasn't set earlier, so it should return whatever
9330          * the base IUri contains (if anything).
9331          */
9332         IUri *uri = NULL;
9333         hr = IUriBuilder_GetIUri(builder, &uri);
9334         ok(hr == S_OK,
9335             "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9336             hr, S_OK, test_index);
9337         if(SUCCEEDED(hr)) {
9338             if(!uri) {
9339                 received = (void*) 0xdeadbeef;
9340                 len = -1;
9341
9342                 hr = IUriBuilder_GetQuery(builder, &len, &received);
9343                 ok(hr == S_FALSE,
9344                     "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9345                     hr, S_FALSE, test_index);
9346                 if(SUCCEEDED(hr)) {
9347                     ok(!len, "Error: Expected len to be 0, but was %d instead on uri_builder_tests[%d].\n",
9348                         len, test_index);
9349                     ok(!received, "Error: Expected received to be NULL, but was %p instead on uri_builder_tests[%d].\n",
9350                         received, test_index);
9351                 }
9352             } else {
9353                 BOOL has_prop = FALSE;
9354                 BSTR expected = NULL;
9355
9356                 hr = IUri_GetQuery(uri, &expected);
9357                 ok(SUCCEEDED(hr),
9358                     "Error: Expected IUri_GetQuery to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
9359                     hr, test_index);
9360                 has_prop = hr == S_OK;
9361
9362                 hr = IUriBuilder_GetQuery(builder, &len, &received);
9363                 if(has_prop) {
9364                     ok(hr == S_OK,
9365                         "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9366                         hr, S_OK, test_index);
9367                     if(SUCCEEDED(hr)) {
9368                         ok(!lstrcmpW(expected, received),
9369                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].\n",
9370                             wine_dbgstr_w(expected), wine_dbgstr_w(received), test_index);
9371                         ok(lstrlenW(expected) == len,
9372                             "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
9373                             lstrlenW(expected), len, test_index);
9374                     }
9375                 } else {
9376                     ok(hr == S_FALSE,
9377                         "Error: IUriBuilder_GetQuery returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9378                         hr, S_FALSE, test_index);
9379                     if(SUCCEEDED(hr)) {
9380                         ok(!received, "Error: Expected received to be NULL on uri_builder_tests[%d].\n", test_index);
9381                         ok(!len, "Error: Expected the length to be 0, but was %d instead on uri_builder_tests[%d].\n",
9382                             len, test_index);
9383                     }
9384                 }
9385                 SysFreeString(expected);
9386             }
9387         }
9388         if(uri) IUri_Release(uri);
9389     }
9390 }
9391
9392 static void test_IUriBuilder_GetSchemeName(IUriBuilder *builder, const uri_builder_test *test,
9393                                            DWORD test_index) {
9394     HRESULT hr;
9395     DWORD i;
9396     LPCWSTR received = NULL;
9397     DWORD len = -1;
9398     const uri_builder_property *prop = NULL;
9399
9400     /* Check if the property was set earlier. */
9401     for(i = 0; i < sizeof(test->properties)/sizeof(test->properties[0]); ++i) {
9402         if(test->properties[i].change && test->properties[i].property == Uri_PROPERTY_SCHEME_NAME)
9403             prop = &(test->properties[i]);
9404     }
9405
9406     if(prop) {
9407         /* Use expected_value unless it's NULL, then use value. */
9408         LPCSTR expected = prop->expected_value ? prop->expected_value : prop->value;
9409         hr = IUriBuilder_GetSchemeName(builder, &len, &received);
9410         if(prop->todo) {
9411             todo_wine {
9412                 ok(hr == (expected ? S_OK : S_FALSE),
9413                     "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9414                     hr, (expected ? S_OK : S_FALSE), test_index);
9415             }
9416             if(SUCCEEDED(hr)) {
9417                 todo_wine {
9418                     ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
9419                         expected, wine_dbgstr_w(received), test_index);
9420                 }
9421                 todo_wine {
9422                     ok(lstrlen(expected) == len,
9423                         "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
9424                         lstrlen(expected), len, test_index);
9425                 }
9426             }
9427         } else {
9428             ok(hr == (expected ? S_OK : S_FALSE),
9429                 "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9430                 hr, (expected ? S_OK : S_FALSE), test_index);
9431             ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
9432                 expected, wine_dbgstr_w(received), test_index);
9433             ok(lstrlen(expected) == len,
9434                 "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
9435                 lstrlen(expected), len, test_index);
9436         }
9437     } else {
9438         /* The property wasn't set earlier, so it should return whatever
9439          * the base IUri contains (if anything).
9440          */
9441         IUri *uri = NULL;
9442         hr = IUriBuilder_GetIUri(builder, &uri);
9443         ok(hr == S_OK,
9444             "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9445             hr, S_OK, test_index);
9446         if(SUCCEEDED(hr)) {
9447             if(!uri) {
9448                 received = (void*) 0xdeadbeef;
9449                 len = -1;
9450
9451                 hr = IUriBuilder_GetSchemeName(builder, &len, &received);
9452                 ok(hr == S_FALSE,
9453                     "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9454                     hr, S_FALSE, test_index);
9455                 if(SUCCEEDED(hr)) {
9456                     ok(!len, "Error: Expected len to be 0, but was %d instead on uri_builder_tests[%d].\n",
9457                         len, test_index);
9458                     ok(!received, "Error: Expected received to be NULL, but was %p instead on uri_builder_tests[%d].\n",
9459                         received, test_index);
9460                 }
9461             } else {
9462                 BOOL has_prop = FALSE;
9463                 BSTR expected = NULL;
9464
9465                 hr = IUri_GetSchemeName(uri, &expected);
9466                 ok(SUCCEEDED(hr),
9467                     "Error: Expected IUri_GetSchemeName to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
9468                     hr, test_index);
9469                 has_prop = hr == S_OK;
9470
9471                 hr = IUriBuilder_GetSchemeName(builder, &len, &received);
9472                 if(has_prop) {
9473                     ok(hr == S_OK,
9474                         "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9475                         hr, S_OK, test_index);
9476                     if(SUCCEEDED(hr)) {
9477                         ok(!lstrcmpW(expected, received),
9478                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].\n",
9479                             wine_dbgstr_w(expected), wine_dbgstr_w(received), test_index);
9480                         ok(lstrlenW(expected) == len,
9481                             "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
9482                             lstrlenW(expected), len, test_index);
9483                     }
9484                 } else {
9485                     ok(hr == S_FALSE,
9486                         "Error: IUriBuilder_GetSchemeName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9487                         hr, S_FALSE, test_index);
9488                     if(SUCCEEDED(hr)) {
9489                         ok(!received, "Error: Expected received to be NULL on uri_builder_tests[%d].\n", test_index);
9490                         ok(!len, "Error: Expected the length to be 0, but was %d instead on uri_builder_tests[%d].\n",
9491                             len, test_index);
9492                     }
9493                 }
9494                 SysFreeString(expected);
9495             }
9496         }
9497         if(uri) IUri_Release(uri);
9498     }
9499 }
9500
9501 static void test_IUriBuilder_GetUserName(IUriBuilder *builder, const uri_builder_test *test,
9502                                          DWORD test_index) {
9503     HRESULT hr;
9504     DWORD i;
9505     LPCWSTR received = NULL;
9506     DWORD len = -1;
9507     const uri_builder_property *prop = NULL;
9508
9509     /* Check if the property was set earlier. */
9510     for(i = 0; i < sizeof(test->properties)/sizeof(test->properties[0]); ++i) {
9511         if(test->properties[i].change && test->properties[i].property == Uri_PROPERTY_USER_NAME)
9512             prop = &(test->properties[i]);
9513     }
9514
9515     if(prop && prop->value && *prop->value) {
9516         /* Use expected_value unless it's NULL, then use value. */
9517         LPCSTR expected = prop->expected_value ? prop->expected_value : prop->value;
9518         hr = IUriBuilder_GetUserName(builder, &len, &received);
9519         if(prop->todo) {
9520             todo_wine {
9521                 ok(hr == (expected ? S_OK : S_FALSE),
9522                     "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9523                     hr, (expected ? S_OK : S_FALSE), test_index);
9524             }
9525             if(SUCCEEDED(hr)) {
9526                 todo_wine {
9527                     ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
9528                         expected, wine_dbgstr_w(received), test_index);
9529                 }
9530                 todo_wine {
9531                     ok(lstrlen(expected) == len,
9532                         "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
9533                         lstrlen(expected), len, test_index);
9534                 }
9535             }
9536         } else {
9537             ok(hr == (expected ? S_OK : S_FALSE),
9538                 "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9539                 hr, (expected ? S_OK : S_FALSE), test_index);
9540             ok(!strcmp_aw(expected, received), "Error: Expected %s but got %s on uri_builder_tests[%d].\n",
9541                 expected, wine_dbgstr_w(received), test_index);
9542             ok(lstrlen(expected) == len,
9543                 "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
9544                 lstrlen(expected), len, test_index);
9545         }
9546     } else {
9547         /* The property wasn't set earlier, so it should return whatever
9548          * the base IUri contains (if anything).
9549          */
9550         IUri *uri = NULL;
9551         hr = IUriBuilder_GetIUri(builder, &uri);
9552         ok(hr == S_OK,
9553             "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9554             hr, S_OK, test_index);
9555         if(SUCCEEDED(hr)) {
9556             if(!uri) {
9557                 received = (void*) 0xdeadbeef;
9558                 len = -1;
9559
9560                 hr = IUriBuilder_GetUserName(builder, &len, &received);
9561                 ok(hr == S_FALSE,
9562                     "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9563                     hr, S_FALSE, test_index);
9564                 if(SUCCEEDED(hr)) {
9565                     ok(!len, "Error: Expected len to be 0, but was %d instead on uri_builder_tests[%d].\n",
9566                         len, test_index);
9567                     ok(!received, "Error: Expected received to be NULL, but was %p instead on uri_builder_tests[%d].\n",
9568                         received, test_index);
9569                 }
9570             } else {
9571                 BSTR expected = NULL;
9572                 BOOL has_prop = FALSE;
9573
9574                 hr = IUri_GetUserName(uri, &expected);
9575                 ok(SUCCEEDED(hr),
9576                     "Error: Expected IUri_GetUserName to succeed, but got 0x%08x instead on uri_builder_tests[%d].\n",
9577                     hr, test_index);
9578                 has_prop = hr == S_OK;
9579
9580                 hr = IUriBuilder_GetUserName(builder, &len, &received);
9581                 if(has_prop) {
9582                     ok(hr == S_OK,
9583                         "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9584                         hr, S_OK, test_index);
9585                     if(SUCCEEDED(hr)) {
9586                         ok(!lstrcmpW(expected, received),
9587                             "Error: Expected %s but got %s instead on uri_builder_tests[%d].\n",
9588                             wine_dbgstr_w(expected), wine_dbgstr_w(received), test_index);
9589                         ok(lstrlenW(expected) == len,
9590                             "Error: Expected the length to be %d, but was %d instead on uri_builder_tests[%d].\n",
9591                             lstrlenW(expected), len, test_index);
9592                     }
9593                 } else {
9594                     ok(hr == S_FALSE,
9595                         "Error: IUriBuilder_GetUserName returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9596                         hr, S_FALSE, test_index);
9597                     if(SUCCEEDED(hr)) {
9598                         ok(!received, "Error: Expected received to be NULL on uri_builder_tests[%d].\n", test_index);
9599                         ok(!len, "Error: Expected the length to be 0, but was %d instead on uri_builder_tests[%d].\n",
9600                             len, test_index);
9601                     }
9602                 }
9603                 SysFreeString(expected);
9604             }
9605         }
9606         if(uri) IUri_Release(uri);
9607     }
9608 }
9609
9610 /* Tests IUriBuilder functions. */
9611 static void test_IUriBuilder(void) {
9612     HRESULT hr;
9613     IUriBuilder *builder;
9614     DWORD i;
9615
9616     for(i = 0; i < sizeof(uri_builder_tests)/sizeof(uri_builder_tests[0]); ++i) {
9617         IUri *uri = NULL;
9618         uri_builder_test test = uri_builder_tests[i];
9619         LPWSTR uriW = NULL;
9620
9621         if(test.uri) {
9622             uriW = a2w(test.uri);
9623             hr = pCreateUri(uriW, test.create_flags, 0, &uri);
9624             ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9625                 hr, S_OK, i);
9626             if(FAILED(hr)) continue;
9627         }
9628         hr = pCreateIUriBuilder(uri, 0, 0, &builder);
9629         if(test.create_builder_todo) {
9630             todo_wine {
9631                 ok(hr == test.create_builder_expected,
9632                     "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9633                     hr, test.create_builder_expected, i);
9634             }
9635         } else {
9636             ok(hr == test.create_builder_expected,
9637                 "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9638                 hr, test.create_builder_expected, i);
9639         }
9640         if(SUCCEEDED(hr)) {
9641             DWORD j;
9642             BOOL modified = FALSE, received = FALSE;
9643
9644             /* Perform all the string property changes. */
9645             for(j = 0; j < URI_BUILDER_STR_PROPERTY_COUNT; ++j) {
9646                 uri_builder_property prop = test.properties[j];
9647                 if(prop.change) {
9648                     change_property(builder, &prop, i);
9649                     if(prop.property != Uri_PROPERTY_SCHEME_NAME &&
9650                        prop.property != Uri_PROPERTY_HOST)
9651                         modified = TRUE;
9652                     else if(prop.value && *prop.value)
9653                         modified = TRUE;
9654                     else if(prop.value && !*prop.value && prop.property == Uri_PROPERTY_HOST)
9655                         /* Host name property can't be NULL, but it can be empty. */
9656                         modified = TRUE;
9657                 }
9658             }
9659
9660             if(test.port_prop.change) {
9661                 hr = IUriBuilder_SetPort(builder, test.port_prop.set, test.port_prop.value);
9662                 modified = TRUE;
9663                 if(test.port_prop.todo) {
9664                     todo_wine {
9665                         ok(hr == test.port_prop.expected,
9666                             "Error: IUriBuilder_SetPort returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9667                             hr, test.port_prop.expected, i);
9668                     }
9669                 } else {
9670                     ok(hr == test.port_prop.expected,
9671                         "Error: IUriBuilder_SetPort returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9672                         hr, test.port_prop.expected, i);
9673                 }
9674             }
9675
9676             hr = IUriBuilder_HasBeenModified(builder, &received);
9677             ok(hr == S_OK,
9678                 "Error IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x on uri_builder_tests[%d].\n",
9679                 hr, S_OK, i);
9680             if(SUCCEEDED(hr))
9681                 ok(received == modified,
9682                     "Error: Expected received to be %d but was %d instead on uri_builder_tests[%d].\n",
9683                     modified, received, i);
9684
9685             /* Test the "Get*" functions. */
9686             test_IUriBuilder_GetFragment(builder, &test, i);
9687             test_IUriBuilder_GetHost(builder, &test, i);
9688             test_IUriBuilder_GetPassword(builder, &test, i);
9689             test_IUriBuilder_GetPath(builder, &test, i);
9690             test_IUriBuilder_GetPort(builder, &test, i);
9691             test_IUriBuilder_GetQuery(builder, &test, i);
9692             test_IUriBuilder_GetSchemeName(builder, &test, i);
9693             test_IUriBuilder_GetUserName(builder, &test, i);
9694
9695             test_IUriBuilder_CreateUri(builder, &test, i);
9696             test_IUriBuilder_CreateUriSimple(builder, &test, i);
9697             test_IUriBuilder_CreateUriWithFlags(builder, &test, i);
9698         }
9699         if(builder) IUriBuilder_Release(builder);
9700         if(uri) IUri_Release(uri);
9701         heap_free(uriW);
9702     }
9703 }
9704
9705 static void test_IUriBuilder_HasBeenModified(void) {
9706     HRESULT hr;
9707     IUriBuilder *builder = NULL;
9708
9709     hr = pCreateIUriBuilder(NULL, 0, 0, &builder);
9710     ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9711     if(SUCCEEDED(hr)) {
9712         static const WCHAR hostW[] = {'g','o','o','g','l','e','.','c','o','m',0};
9713         IUri *uri = NULL;
9714         BOOL received;
9715
9716         hr = IUriBuilder_HasBeenModified(builder, NULL);
9717         ok(hr == E_POINTER, "Error: IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x.\n",
9718             hr, E_POINTER);
9719
9720         hr = IUriBuilder_SetHost(builder, hostW);
9721         ok(hr == S_OK, "Error: IUriBuilder_SetHost returned 0x%08x, expected 0x%08x.\n",
9722             hr, S_OK);
9723
9724         hr = IUriBuilder_HasBeenModified(builder, &received);
9725         ok(hr == S_OK, "Error: IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x.\n",
9726             hr, S_OK);
9727         if(SUCCEEDED(hr))
9728             ok(received == TRUE, "Error: Expected received to be TRUE.\n");
9729
9730         hr = pCreateUri(http_urlW, 0, 0, &uri);
9731         ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9732         if(SUCCEEDED(hr)) {
9733             LPCWSTR prop;
9734             DWORD len = -1;
9735
9736             hr = IUriBuilder_SetIUri(builder, uri);
9737             ok(hr == S_OK, "Error: IUriBuilder_SetIUri returned 0x%08x, expected 0x%08x.\n",
9738                 hr, S_OK);
9739
9740             hr = IUriBuilder_HasBeenModified(builder, &received);
9741             ok(hr == S_OK, "Error: IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x.\n",
9742                 hr, S_OK);
9743             if(SUCCEEDED(hr))
9744                 ok(received == FALSE, "Error: Expected received to be FALSE.\n");
9745
9746             /* Test what happens with you call SetIUri with the same IUri again. */
9747             hr = IUriBuilder_SetHost(builder, hostW);
9748             ok(hr == S_OK, "Error: IUriBuilder_SetHost returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9749
9750             hr = IUriBuilder_HasBeenModified(builder, &received);
9751             ok(hr == S_OK, "Error: IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x.\n",
9752                 hr, S_OK);
9753             if(SUCCEEDED(hr))
9754                 ok(received == TRUE, "Error: Expected received to be TRUE.\n");
9755
9756             hr = IUriBuilder_SetIUri(builder, uri);
9757             ok(hr == S_OK, "Error: IUriBuilder_SetIUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9758
9759             /* IUriBuilder already had 'uri' as it's IUri property and so Windows doesn't
9760              * reset any of the changes that were made to the IUriBuilder.
9761              */
9762             hr = IUriBuilder_HasBeenModified(builder, &received);
9763             ok(hr == S_OK, "Error: IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9764             if(SUCCEEDED(hr))
9765                 ok(received == TRUE, "Error: Expected received to be TRUE.\n");
9766
9767             hr = IUriBuilder_GetHost(builder, &len, &prop);
9768             ok(hr == S_OK, "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9769             if(SUCCEEDED(hr)) {
9770                 ok(!lstrcmpW(prop, hostW), "Error: Expected %s but got %s instead.\n",
9771                     wine_dbgstr_w(hostW), wine_dbgstr_w(prop));
9772                 ok(len == lstrlenW(hostW), "Error: Expected len to be %d, but was %d instead.\n",
9773                     lstrlenW(hostW), len);
9774             }
9775
9776             hr = IUriBuilder_SetIUri(builder, NULL);
9777             ok(hr == S_OK, "Error: IUriBuilder_SetIUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9778
9779             hr = IUriBuilder_SetHost(builder, hostW);
9780             ok(hr == S_OK, "Error: IUriBuilder_SetHost returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9781             hr = IUriBuilder_HasBeenModified(builder, &received);
9782             ok(hr == S_OK, "Error: IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x.\n",
9783                 hr, S_OK);
9784             if(SUCCEEDED(hr))
9785                 ok(received == TRUE, "Error: Expected received to be TRUE.\n");
9786
9787             hr = IUriBuilder_SetIUri(builder, NULL);
9788             ok(hr == S_OK, "Error: IUriBuilder_SetIUri returned 0x%08x, expected 0x%09x.\n", hr, S_OK);
9789
9790             hr = IUriBuilder_HasBeenModified(builder, &received);
9791             ok(hr == S_OK, "Error: IUriBuilder_HasBeenModified returned 0x%08x, expected 0x%08x.\n",
9792                 hr, S_OK);
9793             if(SUCCEEDED(hr))
9794                 ok(received == TRUE, "Error: Expected received to be TRUE.\n");
9795
9796             hr = IUriBuilder_GetHost(builder, &len, &prop);
9797             ok(hr == S_OK, "Error: IUriBuilder_GetHost returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9798             if(SUCCEEDED(hr)) {
9799                 ok(!lstrcmpW(prop, hostW), "Error: Expected %s but got %s instead.\n",
9800                     wine_dbgstr_w(hostW), wine_dbgstr_w(prop));
9801                 ok(len == lstrlenW(hostW), "Error: Expected len to %d, but was %d instead.\n",
9802                     lstrlenW(hostW), len);
9803             }
9804         }
9805         if(uri) IUri_Release(uri);
9806     }
9807     if(builder) IUriBuilder_Release(builder);
9808 }
9809
9810 /* Test IUriBuilder {Get,Set}IUri functions. */
9811 static void test_IUriBuilder_IUriProperty(void) {
9812     IUriBuilder *builder = NULL;
9813     HRESULT hr;
9814
9815     hr = pCreateIUriBuilder(NULL, 0, 0, &builder);
9816     ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9817     if(SUCCEEDED(hr)) {
9818         IUri *uri = NULL;
9819
9820         hr = IUriBuilder_GetIUri(builder, NULL);
9821         ok(hr == E_POINTER, "Error: IUriBuilder_GetIUri returned 0x%08x, expected 0x%08x.\n",
9822             hr, E_POINTER);
9823
9824         hr = pCreateUri(http_urlW, 0, 0, &uri);
9825         if(SUCCEEDED(hr)) {
9826             IUri *test = NULL;
9827             ULONG cur_count, orig_count;
9828
9829             /* IUriBuilder doesn't clone the IUri, it use the same IUri. */
9830             orig_count = get_refcnt(uri);
9831             hr = IUriBuilder_SetIUri(builder, uri);
9832             cur_count = get_refcnt(uri);
9833             if(SUCCEEDED(hr))
9834                 ok(cur_count == orig_count+1, "Error: Expected uri ref count to be %d, but was %d instead.\n",
9835                     orig_count+1, cur_count);
9836
9837             hr = IUriBuilder_SetIUri(builder, NULL);
9838             cur_count = get_refcnt(uri);
9839             if(SUCCEEDED(hr))
9840                 ok(cur_count == orig_count, "Error: Expected uri ref count to be %d, but was %d instead.\n",
9841                     orig_count, cur_count);
9842
9843             /* CreateUri* functions will return back the same IUri if nothing has changed. */
9844             hr = IUriBuilder_SetIUri(builder, uri);
9845             ok(hr == S_OK, "Error: IUriBuilder_SetIUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9846             orig_count = get_refcnt(uri);
9847
9848             hr = IUriBuilder_CreateUri(builder, 0, 0, 0, &test);
9849             ok(hr == S_OK, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9850             if(SUCCEEDED(hr)) {
9851                 cur_count = get_refcnt(uri);
9852                 ok(cur_count == orig_count+1, "Error: Expected uri ref count to be %d, but was %d instead.\n",
9853                     orig_count+1, cur_count);
9854                 ok(test == uri, "Error: Expected test to be %p, but was %p instead.\n",
9855                     uri, test);
9856             }
9857             if(test) IUri_Release(test);
9858
9859             test = NULL;
9860             hr = IUriBuilder_CreateUri(builder, -1, 0, 0, &test);
9861             ok(hr == S_OK, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9862             if(SUCCEEDED(hr)) {
9863                 cur_count = get_refcnt(uri);
9864                 ok(cur_count == orig_count+1, "Error: Expected uri ref count to be %d, but was %d instead.\n",
9865                     orig_count+1, cur_count);
9866                 ok(test == uri, "Error: Expected test to be %p, but was %p instead.\n", uri, test);
9867             }
9868             if(test) IUri_Release(test);
9869
9870             /* Doesn't return the same IUri, if the flag combination is different then the one that created
9871              * the base IUri.
9872              */
9873             test = NULL;
9874             hr = IUriBuilder_CreateUri(builder, Uri_CREATE_ALLOW_RELATIVE, 0, 0, &test);
9875             ok(hr == S_OK, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9876             if(SUCCEEDED(hr))
9877                 ok(test != uri, "Error: Wasn't expecting 'test' to be 'uri'\n");
9878
9879             if(test) IUri_Release(test);
9880
9881             /* Still returns the same IUri, even though the base one wasn't created with CREATE_CANONICALIZE
9882              * explicitly set (because it's a default flags).
9883              */
9884             test = NULL;
9885             hr = IUriBuilder_CreateUri(builder, Uri_CREATE_CANONICALIZE, 0, 0, &test);
9886             ok(hr == S_OK, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9887             if(SUCCEEDED(hr)) {
9888                 cur_count = get_refcnt(uri);
9889                 ok(cur_count == orig_count+1, "Error: Expected uri ref count to be %d, but was %d instead.\n",
9890                     orig_count+1, cur_count);
9891                 ok(test == uri, "Error: Expected 'test' to be %p, but was %p instead.\n", uri, test);
9892             }
9893             if(test) IUri_Release(test);
9894
9895             test = NULL;
9896             hr = IUriBuilder_CreateUriSimple(builder, 0, 0, &test);
9897             ok(hr == S_OK, "Error: IUriBuilder_CreateUriSimple returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9898             if(SUCCEEDED(hr)) {
9899                 cur_count = get_refcnt(uri);
9900                 ok(cur_count == orig_count+1, "Error: Expected uri ref count to be %d, but was %d instead.\n",
9901                     orig_count+1, cur_count);
9902                 ok(test == uri, "Error: Expected test to be %p, but was %p instead.\n", uri, test);
9903             }
9904             if(test) IUri_Release(test);
9905
9906             test = NULL;
9907             hr = IUriBuilder_CreateUriWithFlags(builder, 0, 0, 0, 0, &test);
9908             ok(hr == S_OK, "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x.\n",
9909                 hr, S_OK);
9910             if(SUCCEEDED(hr)) {
9911                 cur_count = get_refcnt(uri);
9912                 ok(cur_count == orig_count+1, "Error: Expected uri ref count to be %d, but was %d instead.\n",
9913                     orig_count+1, cur_count);
9914                 ok(test == uri, "Error: Expected test to be %p, but was %p instead.\n", uri, test);
9915             }
9916             if(test) IUri_Release(test);
9917
9918             /* Doesn't return the same IUri, if the flag combination is different then the one that created
9919              * the base IUri.
9920              */
9921             test = NULL;
9922             hr = IUriBuilder_CreateUriWithFlags(builder, Uri_CREATE_ALLOW_RELATIVE, 0, 0, 0, &test);
9923             ok(hr == S_OK, "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9924             if(SUCCEEDED(hr))
9925                 ok(test != uri, "Error: Wasn't expecting 'test' to be 'uri'\n");
9926
9927             if(test) IUri_Release(test);
9928
9929             /* Still returns the same IUri, even though the base one wasn't created with CREATE_CANONICALIZE
9930              * explicitly set (because it's a default flags).
9931              */
9932             test = NULL;
9933             hr = IUriBuilder_CreateUriWithFlags(builder, Uri_CREATE_CANONICALIZE, 0, 0, 0, &test);
9934             ok(hr == S_OK, "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9935             if(SUCCEEDED(hr)) {
9936                 cur_count = get_refcnt(uri);
9937                 ok(cur_count == orig_count+1, "Error: Expected uri ref count to be %d, but was %d instead.\n",
9938                     orig_count+1, cur_count);
9939                 ok(test == uri, "Error: Expected 'test' to be %p, but was %p instead.\n", uri, test);
9940             }
9941             if(test) IUri_Release(test);
9942         }
9943         if(uri) IUri_Release(uri);
9944     }
9945     if(builder) IUriBuilder_Release(builder);
9946 }
9947
9948 static void test_IUriBuilder_RemoveProperties(void) {
9949     IUriBuilder *builder = NULL;
9950     HRESULT hr;
9951     DWORD i;
9952
9953     hr = pCreateIUriBuilder(NULL, 0, 0, &builder);
9954     ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
9955     if(SUCCEEDED(hr)) {
9956         /* Properties that can't be removed. */
9957         const DWORD invalid = Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_RAW_URI|Uri_HAS_HOST_TYPE|
9958                               Uri_HAS_SCHEME|Uri_HAS_ZONE;
9959
9960         for(i = Uri_PROPERTY_STRING_START; i <= Uri_PROPERTY_DWORD_LAST; ++i) {
9961             hr = IUriBuilder_RemoveProperties(builder, i << 1);
9962             if((i << 1) & invalid) {
9963                 ok(hr == E_INVALIDARG,
9964                     "Error: IUriBuilder_RemoveProperties returned 0x%08x, expected 0x%08x with prop=%d.\n",
9965                     hr, E_INVALIDARG, i);
9966             } else {
9967                 ok(hr == S_OK,
9968                     "Error: IUriBuilder_RemoveProperties returned 0x%08x, expected 0x%08x with prop=%d.\n",
9969                     hr, S_OK, i);
9970             }
9971         }
9972
9973         /* Also doesn't accept anything that's outside the range of the
9974          * Uri_HAS flags.
9975          */
9976         hr = IUriBuilder_RemoveProperties(builder, (Uri_PROPERTY_DWORD_LAST+1) << 1);
9977         ok(hr == E_INVALIDARG, "Error: IUriBuilder_RemoveProperties returned 0x%08x, expected 0x%08x.\n",
9978             hr, E_INVALIDARG);
9979     }
9980     if(builder) IUriBuilder_Release(builder);
9981
9982     for(i = 0; i < sizeof(uri_builder_remove_tests)/sizeof(uri_builder_remove_tests[0]); ++i) {
9983         uri_builder_remove_test test = uri_builder_remove_tests[i];
9984         IUri *uri = NULL;
9985         LPWSTR uriW;
9986
9987         uriW = a2w(test.uri);
9988         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
9989         if(SUCCEEDED(hr)) {
9990             builder = NULL;
9991
9992             hr = pCreateIUriBuilder(uri, 0, 0, &builder);
9993             if(test.create_builder_todo) {
9994                 todo_wine {
9995                     ok(hr == test.create_builder_expected,
9996                         "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x on test %d.\n",
9997                         hr, test.create_builder_expected, i);
9998                 }
9999             } else {
10000                 ok(hr == test.create_builder_expected,
10001                     "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x on test %d.\n",
10002                     hr, test.create_builder_expected, i);
10003             }
10004             if(SUCCEEDED(hr)) {
10005                 hr = IUriBuilder_RemoveProperties(builder, test.remove_properties);
10006                 if(test.remove_todo) {
10007                     todo_wine {
10008                         ok(hr == test.remove_expected,
10009                             "Error: IUriBuilder_RemoveProperties returned 0x%08x, expected 0x%08x on test %d.\n",
10010                             hr, test.remove_expected, i);
10011                     }
10012                 } else {
10013                     ok(hr == test.remove_expected,
10014                         "Error: IUriBuilder returned 0x%08x, expected 0x%08x on test %d.\n",
10015                         hr, test.remove_expected, i);
10016                 }
10017                 if(SUCCEEDED(hr)) {
10018                     IUri *result = NULL;
10019
10020                     hr = IUriBuilder_CreateUri(builder, test.expected_flags, 0, 0, &result);
10021                     if(test.expected_todo) {
10022                         todo_wine {
10023                             ok(hr == test.expected_hres,
10024                                 "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x on test %d.\n",
10025                                 hr, test.expected_hres, i);
10026                         }
10027                     } else {
10028                         ok(hr == test.expected_hres,
10029                             "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x on test %d.\n",
10030                             hr, test.expected_hres, i);
10031                     }
10032                     if(SUCCEEDED(hr)) {
10033                         BSTR received = NULL;
10034
10035                         hr = IUri_GetAbsoluteUri(result, &received);
10036                         ok(hr == S_OK, "Error: Expected S_OK, but got 0x%08x instead.\n", hr);
10037                         ok(!strcmp_aw(test.expected_uri, received),
10038                             "Error: Expected %s but got %s instead on test %d.\n",
10039                             test.expected_uri, wine_dbgstr_w(received), i);
10040                         SysFreeString(received);
10041                     }
10042                     if(result) IUri_Release(result);
10043                 }
10044             }
10045             if(builder) IUriBuilder_Release(builder);
10046         }
10047         if(uri) IUri_Release(uri);
10048         heap_free(uriW);
10049     }
10050 }
10051
10052 static void test_IUriBuilder_Misc(void) {
10053     HRESULT hr;
10054     IUri *uri;
10055
10056     hr = pCreateUri(http_urlW, 0, 0, &uri);
10057     if(SUCCEEDED(hr)) {
10058         IUriBuilder *builder;
10059
10060         hr = pCreateIUriBuilder(uri, 0, 0, &builder);
10061         ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
10062         if(SUCCEEDED(hr)) {
10063             BOOL has = -1;
10064             DWORD port = -1;
10065
10066             hr = IUriBuilder_GetPort(builder, &has, &port);
10067             ok(hr == S_OK, "Error: IUriBuilder_GetPort returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
10068             if(SUCCEEDED(hr)) {
10069                 /* 'has' will be set to FALSE, even though uri had a port. */
10070                 ok(has == FALSE, "Error: Expected 'has' to be FALSE, was %d instead.\n", has);
10071                 /* Still sets 'port' to 80. */
10072                 ok(port == 80, "Error: Expected the port to be 80, but, was %d instead.\n", port);
10073             }
10074         }
10075         if(builder) IUriBuilder_Release(builder);
10076     }
10077     if(uri) IUri_Release(uri);
10078 }
10079
10080 static void test_IUriBuilderFactory(void) {
10081     HRESULT hr;
10082     IUri *uri;
10083     IUriBuilderFactory *factory;
10084     IUriBuilder *builder;
10085
10086     hr = pCreateUri(http_urlW, 0, 0, &uri);
10087     ok(SUCCEEDED(hr), "Error: CreateUri returned 0x%08x.\n", hr);
10088     if(SUCCEEDED(hr)) {
10089         factory = NULL;
10090         hr = IUri_QueryInterface(uri, &IID_IUriBuilderFactory, (void**)&factory);
10091         ok(hr == S_OK, "Error: Expected S_OK, but got 0x%08x.\n", hr);
10092         ok(factory != NULL, "Error: Expected 'factory' to not be NULL.\n");
10093
10094         if(SUCCEEDED(hr)) {
10095             builder = (void*) 0xdeadbeef;
10096             hr = IUriBuilderFactory_CreateIUriBuilder(factory, 10, 0, &builder);
10097             ok(hr == E_INVALIDARG, "Error: CreateInitializedIUriBuilder returned 0x%08x, expected 0x%08x.\n",
10098                 hr, E_INVALIDARG);
10099             ok(!builder, "Error: Expected 'builder' to be NULL, but was %p.\n", builder);
10100
10101             builder = (void*) 0xdeadbeef;
10102             hr = IUriBuilderFactory_CreateIUriBuilder(factory, 0, 10, &builder);
10103             ok(hr == E_INVALIDARG, "Error: CreateInitializedIUriBuilder returned 0x%08x, expected 0x%08x.\n",
10104                 hr, E_INVALIDARG);
10105             ok(!builder, "Error: Expected 'builder' to be NULL, but was %p.\n", builder);
10106
10107             hr = IUriBuilderFactory_CreateIUriBuilder(factory, 0, 0, NULL);
10108             ok(hr == E_POINTER, "Error: CreateInitializedIUriBuilder returned 0x%08x, expected 0x%08x.\n",
10109                 hr, E_POINTER);
10110
10111             builder = NULL;
10112             hr = IUriBuilderFactory_CreateIUriBuilder(factory, 0, 0, &builder);
10113             ok(hr == S_OK, "Error: CreateInitializedIUriBuilder returned 0x%08x, expected 0x%08x.\n",
10114                 hr, S_OK);
10115             if(SUCCEEDED(hr)) {
10116                 IUri *tmp = (void*) 0xdeadbeef;
10117                 LPCWSTR result;
10118                 DWORD result_len;
10119
10120                 hr = IUriBuilder_GetIUri(builder, &tmp);
10121                 ok(hr == S_OK, "Error: GetIUri returned 0x%08x, expected 0x%08x.\n",
10122                     hr, S_OK);
10123                 ok(!tmp, "Error: Expected 'tmp' to be NULL, but was %p instead.\n", tmp);
10124
10125                 hr = IUriBuilder_GetHost(builder, &result_len, &result);
10126                 ok(hr == S_FALSE, "Error: GetHost returned 0x%08x, expected 0x%08x.\n",
10127                     hr, S_FALSE);
10128             }
10129             if(builder) IUriBuilder_Release(builder);
10130
10131             builder = (void*) 0xdeadbeef;
10132             hr = IUriBuilderFactory_CreateInitializedIUriBuilder(factory, 10, 0, &builder);
10133             ok(hr == E_INVALIDARG, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n",
10134                 hr, E_INVALIDARG);
10135             ok(!builder, "Error: Expected 'builder' to be NULL, but was %p.\n", builder);
10136
10137             builder = (void*) 0xdeadbeef;
10138             hr = IUriBuilderFactory_CreateInitializedIUriBuilder(factory, 0, 10, &builder);
10139             ok(hr == E_INVALIDARG, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n",
10140                 hr, E_INVALIDARG);
10141             ok(!builder, "Error: Expected 'builder' to be NULL, but was %p.\n", builder);
10142
10143             hr = IUriBuilderFactory_CreateInitializedIUriBuilder(factory, 0, 0, NULL);
10144             ok(hr == E_POINTER, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n",
10145                 hr, E_POINTER);
10146
10147             builder = NULL;
10148             hr = IUriBuilderFactory_CreateInitializedIUriBuilder(factory, 0, 0, &builder);
10149             ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n",
10150                 hr, S_OK);
10151             if(SUCCEEDED(hr)) {
10152                 IUri *tmp = NULL;
10153
10154                 hr = IUriBuilder_GetIUri(builder, &tmp);
10155                 ok(hr == S_OK, "Error: GetIUri return 0x%08x, expected 0x%08x.\n",
10156                     hr, S_OK);
10157                 ok(tmp == uri, "Error: Expected tmp to be %p, but was %p.\n", uri, tmp);
10158                 if(uri) IUri_Release(uri);
10159             }
10160             if(builder) IUriBuilder_Release(builder);
10161         }
10162         if(factory) IUriBuilderFactory_Release(factory);
10163     }
10164     if(uri) IUri_Release(uri);
10165 }
10166
10167 static void test_CoInternetCombineIUri(void) {
10168     HRESULT hr;
10169     IUri *base, *relative, *result;
10170     DWORD i;
10171
10172     base = NULL;
10173     hr = pCreateUri(http_urlW, 0, 0, &base);
10174     ok(SUCCEEDED(hr), "Error: Expected CreateUri to succeed, got 0x%08x.\n", hr);
10175     if(SUCCEEDED(hr)) {
10176         result = (void*) 0xdeadbeef;
10177         hr = pCoInternetCombineIUri(base, NULL, 0, &result, 0);
10178         ok(hr == E_INVALIDARG, "Error: CoInternetCombineIUri returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
10179         ok(!result, "Error: Expected 'result' to be NULL, was %p.\n", result);
10180     }
10181
10182     relative = NULL;
10183     hr = pCreateUri(http_urlW, 0, 0, &relative);
10184     ok(SUCCEEDED(hr), "Error: Expected CreateUri to succeed, got 0x%08x.\n", hr);
10185     if(SUCCEEDED(hr)) {
10186         result = (void*) 0xdeadbeef;
10187         hr = pCoInternetCombineIUri(NULL, relative, 0, &result, 0);
10188         ok(hr == E_INVALIDARG, "Error: CoInternetCombineIUri returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
10189         ok(!result, "Error: Expected 'result' to be NULL, was %p.\n", result);
10190     }
10191
10192     hr = pCoInternetCombineIUri(base, relative, 0, NULL, 0);
10193     ok(hr == E_INVALIDARG, "Error: CoInternetCombineIUri returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
10194
10195     if(base) IUri_Release(base);
10196     if(relative) IUri_Release(relative);
10197
10198     for(i = 0; i < sizeof(uri_combine_tests)/sizeof(uri_combine_tests[0]); ++i) {
10199         LPWSTR baseW = a2w(uri_combine_tests[i].base_uri);
10200
10201         hr = pCreateUri(baseW, uri_combine_tests[i].base_create_flags, 0, &base);
10202         ok(SUCCEEDED(hr), "Error: Expected CreateUri to succeed, got 0x%08x on uri_combine_tests[%d].\n", hr, i);
10203         if(SUCCEEDED(hr)) {
10204             LPWSTR relativeW = a2w(uri_combine_tests[i].relative_uri);
10205
10206             hr = pCreateUri(relativeW, uri_combine_tests[i].relative_create_flags, 0, &relative);
10207             ok(SUCCEEDED(hr), "Error: Expected CreateUri to succeed, got 0x%08x on uri_combine_tests[%d].\n", hr, i);
10208             if(SUCCEEDED(hr)) {
10209                 result = NULL;
10210
10211                 hr = pCoInternetCombineIUri(base, relative, uri_combine_tests[i].combine_flags, &result, 0);
10212                 if(uri_combine_tests[i].todo) {
10213                     todo_wine {
10214                         ok(hr == uri_combine_tests[i].expected,
10215                             "Error: CoInternetCombineIUri returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].\n",
10216                             hr, uri_combine_tests[i].expected, i);
10217                     }
10218                 } else {
10219                     ok(hr == uri_combine_tests[i].expected,
10220                         "Error: CoInternetCombineIUri returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].\n",
10221                         hr, uri_combine_tests[i]. expected, i);
10222                 }
10223                 if(SUCCEEDED(hr)) {
10224                     DWORD j;
10225
10226                     for(j = 0; j < sizeof(uri_combine_tests[i].str_props)/sizeof(uri_combine_tests[i].str_props[0]); ++j) {
10227                         uri_combine_str_property prop = uri_combine_tests[i].str_props[j];
10228                         BSTR received;
10229
10230                         hr = IUri_GetPropertyBSTR(result, j, &received, 0);
10231                         if(prop.todo) {
10232                             todo_wine {
10233                                 ok(hr == prop.expected,
10234                                     "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].str_props[%d].\n",
10235                                     hr, prop.expected, i, j);
10236                             }
10237                             todo_wine {
10238                                 ok(!strcmp_aw(prop.value, received) ||
10239                                    broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
10240                                     "Error: Expected %s but got %s instead on uri_combine_tests[%d].str_props[%d].\n",
10241                                     prop.value, wine_dbgstr_w(received), i, j);
10242                             }
10243                         } else {
10244                             ok(hr == prop.expected,
10245                                 "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].str_props[%d].\n",
10246                                 hr, prop.expected, i, j);
10247                             ok(!strcmp_aw(prop.value, received) ||
10248                                broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
10249                                 "Error: Expected %s but got %s instead on uri_combine_tests[%d].str_props[%d].\n",
10250                                 prop.value, wine_dbgstr_w(received), i, j);
10251                         }
10252                         SysFreeString(received);
10253                     }
10254
10255                     for(j = 0; j < sizeof(uri_combine_tests[i].dword_props)/sizeof(uri_combine_tests[i].dword_props[0]); ++j) {
10256                         uri_dword_property prop = uri_combine_tests[i].dword_props[j];
10257                         DWORD received;
10258
10259                         hr = IUri_GetPropertyDWORD(result, j+Uri_PROPERTY_DWORD_START, &received, 0);
10260                         if(prop.todo) {
10261                             todo_wine {
10262                                 ok(hr == prop.expected,
10263                                     "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].dword_props[%d].\n",
10264                                     hr, prop.expected, i, j);
10265                             }
10266                             todo_wine {
10267                                 ok(prop.value == received, "Error: Expected %d, but got %d instead on uri_combine_tests[%d].dword_props[%d].\n",
10268                                     prop.value, received, i, j);
10269                             }
10270                         } else {
10271                             ok(hr == prop.expected || broken(prop.broken_combine_hres && hr == S_FALSE),
10272                                 "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].dword_props[%d].\n",
10273                                 hr, prop.expected, i, j);
10274                             if(!prop.broken_combine_hres || hr != S_FALSE)
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                     }
10279                 }
10280                 if(result) IUri_Release(result);
10281             }
10282             if(relative) IUri_Release(relative);
10283             heap_free(relativeW);
10284         }
10285         if(base) IUri_Release(base);
10286         heap_free(baseW);
10287     }
10288 }
10289
10290 static HRESULT WINAPI InternetProtocolInfo_QueryInterface(IInternetProtocolInfo *iface,
10291                                                           REFIID riid, void **ppv)
10292 {
10293     ok(0, "unexpected call\n");
10294     return E_NOINTERFACE;
10295 }
10296
10297 static ULONG WINAPI InternetProtocolInfo_AddRef(IInternetProtocolInfo *iface)
10298 {
10299     return 2;
10300 }
10301
10302 static ULONG WINAPI InternetProtocolInfo_Release(IInternetProtocolInfo *iface)
10303 {
10304     return 1;
10305 }
10306
10307 static HRESULT WINAPI InternetProtocolInfo_ParseUrl(IInternetProtocolInfo *iface, LPCWSTR pwzUrl,
10308         PARSEACTION ParseAction, DWORD dwParseFlags, LPWSTR pwzResult, DWORD cchResult,
10309         DWORD *pcchResult, DWORD dwReserved)
10310 {
10311     CHECK_EXPECT(ParseUrl);
10312     ok(!lstrcmpW(pwzUrl, parse_urlW), "Error: Expected %s, but got %s instead.\n",
10313         wine_dbgstr_w(parse_urlW), wine_dbgstr_w(pwzUrl));
10314     ok(ParseAction == parse_action, "Error: Expected %d, but got %d.\n", parse_action, ParseAction);
10315     ok(dwParseFlags == parse_flags, "Error: Expected 0x%08x, but got 0x%08x.\n", parse_flags, dwParseFlags);
10316     ok(cchResult == 200, "Error: Got %d.\n", cchResult);
10317
10318     memcpy(pwzResult, parse_resultW, sizeof(parse_resultW));
10319     *pcchResult = lstrlenW(parse_resultW);
10320
10321     return S_OK;
10322 }
10323
10324 static HRESULT WINAPI InternetProtocolInfo_CombineUrl(IInternetProtocolInfo *iface,
10325         LPCWSTR pwzBaseUrl, LPCWSTR pwzRelativeUrl, DWORD dwCombineFlags,
10326         LPWSTR pwzResult, DWORD cchResult, DWORD *pcchResult, DWORD dwReserved)
10327 {
10328     CHECK_EXPECT(CombineUrl);
10329     ok(!lstrcmpW(pwzBaseUrl, combine_baseW), "Error: Expected %s, but got %s instead.\n",
10330         wine_dbgstr_w(combine_baseW), wine_dbgstr_w(pwzBaseUrl));
10331     ok(!lstrcmpW(pwzRelativeUrl, combine_relativeW), "Error: Expected %s, but got %s instead.\n",
10332         wine_dbgstr_w(combine_relativeW), wine_dbgstr_w(pwzRelativeUrl));
10333     ok(dwCombineFlags == (URL_DONT_SIMPLIFY|URL_FILE_USE_PATHURL|URL_DONT_UNESCAPE_EXTRA_INFO),
10334         "Error: Expected 0, but got 0x%08x.\n", dwCombineFlags);
10335     ok(cchResult == INTERNET_MAX_URL_LENGTH+1, "Error: Got %d.\n", cchResult);
10336
10337     memcpy(pwzResult, combine_resultW, sizeof(combine_resultW));
10338     *pcchResult = lstrlenW(combine_resultW);
10339
10340     return S_OK;
10341 }
10342
10343 static HRESULT WINAPI InternetProtocolInfo_CompareUrl(IInternetProtocolInfo *iface,
10344         LPCWSTR pwzUrl1, LPCWSTR pwzUrl2, DWORD dwCompareFlags)
10345 {
10346     ok(0, "unexpected call\n");
10347     return E_NOTIMPL;
10348 }
10349
10350 static HRESULT WINAPI InternetProtocolInfo_QueryInfo(IInternetProtocolInfo *iface,
10351         LPCWSTR pwzUrl, QUERYOPTION OueryOption, DWORD dwQueryFlags, LPVOID pBuffer,
10352         DWORD cbBuffer, DWORD *pcbBuf, DWORD dwReserved)
10353 {
10354     ok(0, "unexpected call\n");
10355     return E_NOTIMPL;
10356 }
10357
10358 static const IInternetProtocolInfoVtbl InternetProtocolInfoVtbl = {
10359     InternetProtocolInfo_QueryInterface,
10360     InternetProtocolInfo_AddRef,
10361     InternetProtocolInfo_Release,
10362     InternetProtocolInfo_ParseUrl,
10363     InternetProtocolInfo_CombineUrl,
10364     InternetProtocolInfo_CompareUrl,
10365     InternetProtocolInfo_QueryInfo
10366 };
10367
10368 static IInternetProtocolInfo protocol_info = { &InternetProtocolInfoVtbl };
10369
10370 static HRESULT WINAPI ClassFactory_QueryInterface(IClassFactory *iface, REFIID riid, void **ppv)
10371 {
10372     if(IsEqualGUID(&IID_IInternetProtocolInfo, riid)) {
10373         *ppv = &protocol_info;
10374         return S_OK;
10375     }
10376
10377     ok(0, "unexpected call\n");
10378     return E_NOINTERFACE;
10379 }
10380
10381 static ULONG WINAPI ClassFactory_AddRef(IClassFactory *iface)
10382 {
10383     return 2;
10384 }
10385
10386 static ULONG WINAPI ClassFactory_Release(IClassFactory *iface)
10387 {
10388     return 1;
10389 }
10390
10391 static HRESULT WINAPI ClassFactory_CreateInstance(IClassFactory *iface, IUnknown *pOuter,
10392                                         REFIID riid, void **ppv)
10393 {
10394     ok(0, "unexpected call\n");
10395     return E_NOTIMPL;
10396 }
10397
10398 static HRESULT WINAPI ClassFactory_LockServer(IClassFactory *iface, BOOL dolock)
10399 {
10400     ok(0, "unexpected call\n");
10401     return S_OK;
10402 }
10403
10404 static const IClassFactoryVtbl ClassFactoryVtbl = {
10405     ClassFactory_QueryInterface,
10406     ClassFactory_AddRef,
10407     ClassFactory_Release,
10408     ClassFactory_CreateInstance,
10409     ClassFactory_LockServer
10410 };
10411
10412 static IClassFactory protocol_cf = { &ClassFactoryVtbl };
10413
10414 static void register_protocols(void)
10415 {
10416     IInternetSession *session;
10417     HRESULT hres;
10418
10419     hres = pCoInternetGetSession(0, &session, 0);
10420     ok(hres == S_OK, "CoInternetGetSession failed: %08x\n", hres);
10421     if(FAILED(hres))
10422         return;
10423
10424     hres = IInternetSession_RegisterNameSpace(session, &protocol_cf, &IID_NULL,
10425             winetestW, 0, NULL, 0);
10426     ok(hres == S_OK, "RegisterNameSpace failed: %08x\n", hres);
10427
10428     IInternetSession_Release(session);
10429 }
10430
10431 static void unregister_protocols(void) {
10432     IInternetSession *session;
10433     HRESULT hr;
10434
10435     hr = pCoInternetGetSession(0, &session, 0);
10436     ok(hr == S_OK, "CoInternetGetSession failed: 0x%08x\n", hr);
10437     if(FAILED(hr))
10438         return;
10439
10440     hr = IInternetSession_UnregisterNameSpace(session, &protocol_cf, winetestW);
10441     ok(hr == S_OK, "UnregisterNameSpace failed: 0x%08x\n", hr);
10442
10443     IInternetSession_Release(session);
10444 }
10445
10446 static void test_CoInternetCombineIUri_Pluggable(void) {
10447     HRESULT hr;
10448     IUri *base = NULL;
10449
10450     hr = pCreateUri(combine_baseW, 0, 0, &base);
10451     ok(SUCCEEDED(hr), "Error: CreateUri returned 0x%08x.\n", hr);
10452     if(SUCCEEDED(hr)) {
10453         IUri *relative = NULL;
10454
10455         hr = pCreateUri(combine_relativeW, Uri_CREATE_ALLOW_RELATIVE, 0, &relative);
10456         ok(SUCCEEDED(hr), "Error: CreateUri returned 0x%08x.\n", hr);
10457         if(SUCCEEDED(hr)) {
10458             IUri *result = NULL;
10459
10460             SET_EXPECT(CombineUrl);
10461
10462             hr = pCoInternetCombineIUri(base, relative, URL_DONT_SIMPLIFY|URL_FILE_USE_PATHURL|URL_DONT_UNESCAPE_EXTRA_INFO,
10463                                         &result, 0);
10464             ok(hr == S_OK, "Error: CoInternetCombineIUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
10465
10466             CHECK_CALLED(CombineUrl);
10467
10468             if(SUCCEEDED(hr)) {
10469                 BSTR received = NULL;
10470                 hr = IUri_GetAbsoluteUri(result, &received);
10471                 ok(hr == S_OK, "Error: Expected S_OK, but got 0x%08x instead.\n", hr);
10472                 if(SUCCEEDED(hr)) {
10473                     ok(!lstrcmpW(combine_resultW, received), "Error: Expected %s, but got %s.\n",
10474                         wine_dbgstr_w(combine_resultW), wine_dbgstr_w(received));
10475                 }
10476                 SysFreeString(received);
10477             }
10478             if(result) IUri_Release(result);
10479         }
10480         if(relative) IUri_Release(relative);
10481     }
10482     if(base) IUri_Release(base);
10483 }
10484
10485 static void test_CoInternetCombineUrlEx(void) {
10486     HRESULT hr;
10487     IUri *base, *result;
10488     DWORD i;
10489
10490     base = NULL;
10491     hr = pCreateUri(http_urlW, 0, 0, &base);
10492     ok(SUCCEEDED(hr), "Error: CreateUri returned 0x%08x.\n", hr);
10493     if(SUCCEEDED(hr)) {
10494         result = (void*) 0xdeadbeef;
10495         hr = pCoInternetCombineUrlEx(base, NULL, 0, &result, 0);
10496         ok(hr == E_UNEXPECTED, "Error: CoInternetCombineUrlEx returned 0x%08x, expected 0x%08x.\n",
10497             hr, E_UNEXPECTED);
10498         ok(!result, "Error: Expected 'result' to be NULL was %p instead.\n", result);
10499     }
10500
10501     result = (void*) 0xdeadbeef;
10502     hr = pCoInternetCombineUrlEx(NULL, http_urlW, 0, &result, 0);
10503     ok(hr == E_INVALIDARG, "Error: CoInternetCombineUrlEx returned 0x%08x, expected 0x%08x.\n",
10504         hr, E_INVALIDARG);
10505     ok(!result, "Error: Expected 'result' to be NULL, but was %p instead.\n", result);
10506
10507     result = (void*) 0xdeadbeef;
10508     hr = pCoInternetCombineUrlEx(NULL, NULL, 0, &result, 0);
10509     ok(hr == E_UNEXPECTED, "Error: CoInternetCombineUrlEx returned 0x%08x, expected 0x%08x.\n",
10510         hr, E_UNEXPECTED);
10511     ok(!result, "Error: Expected 'result' to be NULL, but was %p instead.\n", result);
10512
10513     hr = pCoInternetCombineUrlEx(base, http_urlW, 0, NULL, 0);
10514     ok(hr == E_POINTER, "Error: CoInternetCombineUrlEx returned 0x%08x, expected 0x%08x.\n",
10515         hr, E_POINTER);
10516     if(base) IUri_Release(base);
10517
10518     for(i = 0; i < sizeof(uri_combine_tests)/sizeof(uri_combine_tests[0]); ++i) {
10519         LPWSTR baseW = a2w(uri_combine_tests[i].base_uri);
10520
10521         hr = pCreateUri(baseW, uri_combine_tests[i].base_create_flags, 0, &base);
10522         ok(SUCCEEDED(hr), "Error: CreateUri returned 0x%08x on uri_combine_tests[%d].\n", hr, i);
10523         if(SUCCEEDED(hr)) {
10524             LPWSTR relativeW = a2w(uri_combine_tests[i].relative_uri);
10525
10526             hr = pCoInternetCombineUrlEx(base, relativeW, uri_combine_tests[i].combine_flags,
10527                                          &result, 0);
10528             if(uri_combine_tests[i].todo) {
10529                 todo_wine {
10530                     ok(hr == uri_combine_tests[i].expected,
10531                         "Error: CoInternetCombineUrlEx returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].\n",
10532                         hr, uri_combine_tests[i].expected, i);
10533                 }
10534             } else {
10535                 ok(hr == uri_combine_tests[i].expected,
10536                     "Error: CoInternetCombineUrlEx returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].\n",
10537                     hr, uri_combine_tests[i]. expected, i);
10538             }
10539             if(SUCCEEDED(hr)) {
10540                 DWORD j;
10541
10542                 for(j = 0; j < sizeof(uri_combine_tests[i].str_props)/sizeof(uri_combine_tests[i].str_props[0]); ++j) {
10543                     uri_combine_str_property prop = uri_combine_tests[i].str_props[j];
10544                     BSTR received;
10545                     LPCSTR value = (prop.value_ex) ? prop.value_ex : prop.value;
10546
10547                     hr = IUri_GetPropertyBSTR(result, j, &received, 0);
10548                     if(prop.todo) {
10549                         todo_wine {
10550                             ok(hr == prop.expected,
10551                                 "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].str_props[%d].\n",
10552                                 hr, prop.expected, i, j);
10553                         }
10554                         todo_wine {
10555                             ok(!strcmp_aw(value, received) ||
10556                                broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
10557                                 "Error: Expected %s but got %s instead on uri_combine_tests[%d].str_props[%d].\n",
10558                                 value, wine_dbgstr_w(received), i, j);
10559                         }
10560                     } else {
10561                         ok(hr == prop.expected,
10562                             "Error: IUri_GetPropertyBSTR returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].str_props[%d].\n",
10563                             hr, prop.expected, i, j);
10564                         ok(!strcmp_aw(value, received) ||
10565                            broken(prop.broken_value && !strcmp_aw(prop.broken_value, received)),
10566                             "Error: Expected %s but got %s instead on uri_combine_tests[%d].str_props[%d].\n",
10567                             value, wine_dbgstr_w(received), i, j);
10568                     }
10569                     SysFreeString(received);
10570                 }
10571
10572                 for(j = 0; j < sizeof(uri_combine_tests[i].dword_props)/sizeof(uri_combine_tests[i].dword_props[0]); ++j) {
10573                     uri_dword_property prop = uri_combine_tests[i].dword_props[j];
10574                     DWORD received;
10575
10576                     hr = IUri_GetPropertyDWORD(result, j+Uri_PROPERTY_DWORD_START, &received, 0);
10577                     if(prop.todo) {
10578                         todo_wine {
10579                             ok(hr == prop.expected,
10580                                 "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].dword_props[%d].\n",
10581                                 hr, prop.expected, i, j);
10582                         }
10583                         todo_wine {
10584                             ok(prop.value == received, "Error: Expected %d, but got %d instead on uri_combine_tests[%d].dword_props[%d].\n",
10585                                 prop.value, received, i, j);
10586                         }
10587                     } else {
10588                         ok(hr == prop.expected || broken(prop.broken_combine_hres && hr == S_FALSE),
10589                             "Error: IUri_GetPropertyDWORD returned 0x%08x, expected 0x%08x on uri_combine_tests[%d].dword_props[%d].\n",
10590                             hr, prop.expected, i, j);
10591                         if(!prop.broken_combine_hres || hr != S_FALSE)
10592                             ok(prop.value == received, "Error: Expected %d, but got %d instead on uri_combine_tests[%d].dword_props[%d].\n",
10593                                 prop.value, received, i, j);
10594                     }
10595                 }
10596             }
10597             if(result) IUri_Release(result);
10598             heap_free(relativeW);
10599         }
10600         if(base) IUri_Release(base);
10601         heap_free(baseW);
10602     }
10603 }
10604
10605 static void test_CoInternetCombineUrlEx_Pluggable(void) {
10606     HRESULT hr;
10607     IUri *base = NULL;
10608
10609     hr = pCreateUri(combine_baseW, 0, 0, &base);
10610     ok(SUCCEEDED(hr), "Error: CreateUri returned 0x%08x.\n", hr);
10611     if(SUCCEEDED(hr)) {
10612         IUri *result = NULL;
10613
10614         SET_EXPECT(CombineUrl);
10615
10616         hr = pCoInternetCombineUrlEx(base, combine_relativeW, URL_DONT_SIMPLIFY|URL_FILE_USE_PATHURL|URL_DONT_UNESCAPE_EXTRA_INFO,
10617                                      &result, 0);
10618         ok(hr == S_OK, "Error: CoInternetCombineUrlEx returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
10619
10620         CHECK_CALLED(CombineUrl);
10621
10622         if(SUCCEEDED(hr)) {
10623             BSTR received = NULL;
10624             hr = IUri_GetAbsoluteUri(result, &received);
10625             ok(hr == S_OK, "Error: Expected S_OK, but got 0x%08x instead.\n", hr);
10626             if(SUCCEEDED(hr)) {
10627                 ok(!lstrcmpW(combine_resultW, received), "Error: Expected %s, but got %s.\n",
10628                     wine_dbgstr_w(combine_resultW), wine_dbgstr_w(received));
10629             }
10630             SysFreeString(received);
10631         }
10632         if(result) IUri_Release(result);
10633     }
10634     if(base) IUri_Release(base);
10635 }
10636
10637 static void test_CoInternetParseIUri_InvalidArgs(void) {
10638     HRESULT hr;
10639     IUri *uri = NULL;
10640     WCHAR tmp[3];
10641     DWORD result = -1;
10642
10643     hr = pCoInternetParseIUri(NULL, PARSE_CANONICALIZE, 0, tmp, 3, &result, 0);
10644     ok(hr == E_INVALIDARG, "Error: CoInternetParseIUri returned 0x%08x, expected 0x%08x.\n",
10645         hr, E_INVALIDARG);
10646     ok(!result, "Error: Expected 'result' to be 0, but was %d.\n", result);
10647
10648     hr = pCreateUri(http_urlW, 0, 0, &uri);
10649     ok(SUCCEEDED(hr), "Error: CreateUri returned 0x%08x.\n", hr);
10650     if(SUCCEEDED(hr)) {
10651         DWORD expected_len;
10652
10653         result = -1;
10654         hr = pCoInternetParseIUri(uri, PARSE_CANONICALIZE, 0, NULL, 0, &result, 0);
10655         ok(hr == E_INVALIDARG, "Error: CoInternetParseIUri returned 0x%08x, expected 0x%08x.\n",
10656             hr, E_INVALIDARG);
10657         ok(!result, "Error: Expected 'result' to be 0, but was %d.\n", result);
10658
10659         hr = pCoInternetParseIUri(uri, PARSE_CANONICALIZE, 0, tmp, 3, NULL, 0);
10660         ok(hr == E_POINTER, "Error: CoInternetParseIUri returned 0x%08x, expected 0x%08x.\n",
10661             hr, E_POINTER);
10662
10663         result = -1;
10664         hr = pCoInternetParseIUri(uri, PARSE_SECURITY_URL, 0, tmp, 3, &result, 0);
10665         ok(hr == E_FAIL, "Error: CoInternetParseIUri returned 0x%08x expected 0x%08x.\n",
10666             hr, E_FAIL);
10667         ok(!result, "Error: Expected 'result' to be 0, but was %d.\n", result);
10668
10669         result = -1;
10670         hr = pCoInternetParseIUri(uri, PARSE_MIME, 0, tmp, 3, &result, 0);
10671         ok(hr == E_FAIL, "Error: CoInternetParseIUri returned 0x%08x, expected 0x%08x.\n",
10672             hr, E_FAIL);
10673         ok(!result, "Error: Expected 'result' to be 0, but was %d.\n", result);
10674
10675         result = -1;
10676         hr = pCoInternetParseIUri(uri, PARSE_SERVER, 0, tmp, 3, &result, 0);
10677         ok(hr == E_FAIL, "Error: CoInternetParseIUri returned 0x%08x, expected 0x%08x.\n",
10678             hr, E_FAIL);
10679         ok(!result, "Error: Expected 'result' to be 0, but was %d.\n", result);
10680
10681         result = -1;
10682         hr = pCoInternetParseIUri(uri, PARSE_SECURITY_DOMAIN, 0, tmp, 3, &result, 0);
10683         ok(hr == E_FAIL, "Error: CoInternetParseIUri returned 0x%08x, expected 0x%08x.\n",
10684             hr, E_FAIL);
10685         ok(!result, "Error: Expected 'result' to be 0, but was %d.\n", result);
10686
10687         expected_len = lstrlenW(http_urlW);
10688         result = -1;
10689         hr = pCoInternetParseIUri(uri, PARSE_CANONICALIZE, 0, tmp, 3, &result, 0);
10690         ok(hr == STRSAFE_E_INSUFFICIENT_BUFFER,
10691             "Error: CoInternetParseIUri returned 0x%08x, expected 0x%08x.\n",
10692             hr, STRSAFE_E_INSUFFICIENT_BUFFER);
10693         ok(result == expected_len, "Error: Expected 'result' to be %d, but was %d instead.\n",
10694             expected_len, result);
10695     }
10696     if(uri) IUri_Release(uri);
10697 }
10698
10699 static void test_CoInternetParseIUri(void) {
10700     DWORD i;
10701
10702     for(i = 0; i < sizeof(uri_parse_tests)/sizeof(uri_parse_tests[0]); ++i) {
10703         HRESULT hr;
10704         IUri *uri;
10705         LPWSTR uriW;
10706         uri_parse_test test = uri_parse_tests[i];
10707
10708         uriW = a2w(test.uri);
10709         hr = pCreateUri(uriW, test.uri_flags, 0, &uri);
10710         ok(SUCCEEDED(hr), "Error: CreateUri returned 0x%08x on uri_parse_tests[%d].\n", hr, i);
10711         if(SUCCEEDED(hr)) {
10712             WCHAR result[INTERNET_MAX_URL_LENGTH+1];
10713             DWORD result_len = -1;
10714
10715             hr = pCoInternetParseIUri(uri, test.action, test.flags, result, INTERNET_MAX_URL_LENGTH+1, &result_len, 0);
10716             if(test.todo) {
10717                 todo_wine {
10718                     ok(hr == test.expected,
10719                         "Error: CoInternetParseIUri returned 0x%08x, expected 0x%08x on uri_parse_tests[%d].\n",
10720                         hr, test.expected, i);
10721                 }
10722             } else {
10723                 ok(hr == test.expected,
10724                     "Error: CoInternetParseIUri returned 0x%08x, expected 0x%08x on uri_parse_tests[%d].\n",
10725                     hr, test.expected, i);
10726             }
10727             if(SUCCEEDED(hr)) {
10728                 DWORD len = lstrlenA(test.property);
10729                 ok(!strcmp_aw(test.property, result),
10730                     "Error: Expected %s but got %s instead on uri_parse_tests[%d].\n",
10731                     test.property, wine_dbgstr_w(result), i);
10732                 ok(len == result_len,
10733                     "Error: Expected %d, but got %d instead on uri_parse_tests[%d].\n",
10734                     len, result_len, i);
10735             } else {
10736                 ok(!result_len,
10737                     "Error: Expected 'result_len' to be 0, but was %d on uri_parse_tests[%d].\n",
10738                     result_len, i);
10739             }
10740         }
10741         if(uri) IUri_Release(uri);
10742         heap_free(uriW);
10743     }
10744 }
10745
10746 static void test_CoInternetParseIUri_Pluggable(void) {
10747     HRESULT hr;
10748     IUri *uri = NULL;
10749
10750     hr = pCreateUri(parse_urlW, 0, 0, &uri);
10751     ok(SUCCEEDED(hr), "Error: Expected CreateUri to succeed, but got 0x%08x.\n", hr);
10752     if(SUCCEEDED(hr)) {
10753         WCHAR result[200];
10754         DWORD result_len;
10755
10756         SET_EXPECT(ParseUrl);
10757
10758         parse_action = PARSE_CANONICALIZE;
10759         parse_flags = URL_UNESCAPE|URL_ESCAPE_UNSAFE;
10760
10761         hr = pCoInternetParseIUri(uri, parse_action, parse_flags, result, 200, &result_len, 0);
10762         ok(hr == S_OK, "Error: CoInternetParseIUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
10763
10764         CHECK_CALLED(ParseUrl);
10765
10766         if(SUCCEEDED(hr)) {
10767             ok(result_len == lstrlenW(parse_resultW), "Error: Expected %d, but got %d.\n",
10768                 lstrlenW(parse_resultW), result_len);
10769             ok(!lstrcmpW(result, parse_resultW), "Error: Expected %s, but got %s.\n",
10770                 wine_dbgstr_w(parse_resultW), wine_dbgstr_w(result));
10771         }
10772     }
10773     if(uri) IUri_Release(uri);
10774 }
10775
10776 typedef struct {
10777     const char *url;
10778     DWORD uri_flags;
10779     const char *base_url;
10780     DWORD base_uri_flags;
10781     const char *legacy_url;
10782     const char *uniform_url;
10783     const char *no_canon_url;
10784     const char *uri_url;
10785 } create_urlmon_test_t;
10786
10787 static const create_urlmon_test_t create_urlmon_tests[] = {
10788     {
10789         "http://www.winehq.org",Uri_CREATE_NO_CANONICALIZE,
10790         NULL,0,
10791         "http://www.winehq.org/",
10792         "http://www.winehq.org/",
10793         "http://www.winehq.org",
10794         "http://www.winehq.org"
10795     },
10796     {
10797         "file://c:\\dir\\file.txt",Uri_CREATE_NO_CANONICALIZE,
10798         NULL,0,
10799         "file://c:\\dir\\file.txt",
10800         "file:///c:/dir/file.txt",
10801         "file:///c:/dir/file.txt",
10802         "file:///c:/dir/file.txt"
10803     },
10804     {
10805         "file://c:\\dir\\file.txt",Uri_CREATE_FILE_USE_DOS_PATH,
10806         NULL,0,
10807         "file://c:\\dir\\file.txt",
10808         "file:///c:/dir/file.txt",
10809         "file:///c:/dir/file.txt",
10810         "file://c:\\dir\\file.txt"
10811     },
10812     {
10813         "dat%61",Uri_CREATE_ALLOW_RELATIVE,
10814         "http://www.winehq.org",0,
10815         "http://www.winehq.org/data",
10816         "http://www.winehq.org/data",
10817         "http://www.winehq.org:80/data",
10818     },
10819     {
10820         "file.txt",Uri_CREATE_ALLOW_RELATIVE,
10821         "file://c:\\dir\\x.txt",Uri_CREATE_NO_CANONICALIZE,
10822         "file://c:\\dir\\file.txt",
10823         "file:///c:/dir/file.txt",
10824         "file:///c:/dir/file.txt",
10825     },
10826     {
10827         "",Uri_CREATE_ALLOW_RELATIVE,
10828         NULL,0,
10829         "",
10830         "",
10831         "",
10832         ""
10833     },
10834     {
10835         "test",Uri_CREATE_ALLOW_RELATIVE,
10836         NULL,0,
10837         "test",
10838         "test",
10839         "test",
10840         "test"
10841     },
10842     {
10843         "c:\\dir\\file.txt",Uri_CREATE_ALLOW_IMPLICIT_FILE_SCHEME,
10844         NULL,0,
10845         "file://c:\\dir\\file.txt",
10846         "file:///c:/dir/file.txt",
10847         "file:///c:/dir/file.txt",
10848         "file:///c:/dir/file.txt",
10849     }
10850 };
10851
10852 #define test_urlmon_display_name(a,b) _test_urlmon_display_name(__LINE__,a,b)
10853 static void _test_urlmon_display_name(unsigned line, IMoniker *mon, const char *exurl)
10854 {
10855     WCHAR *display_name;
10856     HRESULT hres;
10857
10858     hres = IMoniker_GetDisplayName(mon, NULL, NULL, &display_name);
10859     ok_(__FILE__,line)(hres == S_OK, "GetDisplayName failed: %08x\n", hres);
10860     ok_(__FILE__,line)(!strcmp_aw(exurl, display_name), "unexpected display name: %s, expected %s\n",
10861             wine_dbgstr_w(display_name), exurl);
10862
10863     CoTaskMemFree(display_name);
10864 }
10865
10866 #define test_display_uri(a,b) _test_display_uri(__LINE__,a,b)
10867 static void _test_display_uri(unsigned line, IMoniker *mon, const char *exurl)
10868 {
10869     IUriContainer *uri_container;
10870     IUri *uri;
10871     BSTR display_uri;
10872     HRESULT hres;
10873
10874     hres = IMoniker_QueryInterface(mon, &IID_IUriContainer, (void**)&uri_container);
10875     ok(hres == S_OK, "Could not get IUriContainer iface: %08x\n", hres);
10876
10877     uri = NULL;
10878     hres = IUriContainer_GetIUri(uri_container, &uri);
10879     IUriContainer_Release(uri_container);
10880     ok(hres == S_OK, "GetIUri failed: %08x\n", hres);
10881     ok(uri != NULL, "uri == NULL\n");
10882
10883     hres = IUri_GetDisplayUri(uri, &display_uri);
10884     IUri_Release(uri);
10885     ok(hres == S_OK, "GetDisplayUri failed: %08x\n", hres);
10886     ok_(__FILE__,line)(!strcmp_aw(exurl, display_uri), "unexpected display uri: %s, expected %s\n",
10887             wine_dbgstr_w(display_uri), exurl);
10888     SysFreeString(display_uri);
10889 }
10890
10891 static void test_CreateURLMoniker(void)
10892 {
10893     const create_urlmon_test_t *test;
10894     IMoniker *mon, *base_mon;
10895     WCHAR *url, *base_url;
10896     IUri *uri, *base_uri;
10897     HRESULT hres;
10898
10899     for(test = create_urlmon_tests; test < create_urlmon_tests + sizeof(create_urlmon_tests)/sizeof(*create_urlmon_tests); test++) {
10900         url = a2w(test->url);
10901         base_url = a2w(test->base_url);
10902
10903         if(base_url) {
10904             hres = pCreateUri(base_url, test->base_uri_flags, 0, &base_uri);
10905             ok(hres == S_OK, "CreateUri failed: %08x\n", hres);
10906
10907             hres = pCreateURLMonikerEx2(NULL, base_uri, &base_mon, URL_MK_NO_CANONICALIZE);
10908             ok(hres == S_OK, "CreateURLMonikerEx2 failed: %08x\n", hres);
10909         }else {
10910             base_uri = NULL;
10911             base_mon = NULL;
10912         }
10913
10914         hres = CreateURLMoniker(base_mon, url, &mon);
10915         ok(hres == S_OK, "CreateURLMoniker failed: %08x\n", hres);
10916         test_urlmon_display_name(mon, test->legacy_url);
10917         test_display_uri(mon, test->legacy_url);
10918         IMoniker_Release(mon);
10919
10920         hres = pCreateURLMonikerEx(base_mon, url, &mon, URL_MK_LEGACY);
10921         ok(hres == S_OK, "CreateURLMoniker failed: %08x\n", hres);
10922         test_urlmon_display_name(mon, test->legacy_url);
10923         test_display_uri(mon, test->legacy_url);
10924         IMoniker_Release(mon);
10925
10926         hres = pCreateURLMonikerEx(base_mon, url, &mon, URL_MK_UNIFORM);
10927         ok(hres == S_OK, "CreateURLMoniker failed: %08x\n", hres);
10928         test_urlmon_display_name(mon, test->uniform_url);
10929         test_display_uri(mon, test->uniform_url);
10930         IMoniker_Release(mon);
10931
10932         hres = pCreateURLMonikerEx(base_mon, url, &mon, URL_MK_NO_CANONICALIZE);
10933         ok(hres == S_OK, "CreateURLMoniker failed: %08x\n", hres);
10934         test_urlmon_display_name(mon, test->no_canon_url);
10935         test_display_uri(mon, test->no_canon_url);
10936         IMoniker_Release(mon);
10937
10938         hres = pCreateUri(url, test->uri_flags, 0, &uri);
10939         ok(hres == S_OK, "CreateUri failed: %08x\n", hres);
10940
10941         hres = pCreateURLMonikerEx2(base_mon, uri, &mon, URL_MK_LEGACY);
10942         ok(hres == S_OK, "CreateURLMonikerEx2 failed: %08x\n", hres);
10943         test_urlmon_display_name(mon, base_url ? test->legacy_url : test->uri_url);
10944         test_display_uri(mon, base_url ? test->legacy_url : test->uri_url);
10945         IMoniker_Release(mon);
10946
10947         hres = pCreateURLMonikerEx2(base_mon, uri, &mon, URL_MK_UNIFORM);
10948         ok(hres == S_OK, "CreateURLMonikerEx2 failed: %08x\n", hres);
10949         test_urlmon_display_name(mon, base_url ? test->uniform_url : test->uri_url);
10950         test_display_uri(mon, base_url ? test->uniform_url : test->uri_url);
10951         IMoniker_Release(mon);
10952
10953         hres = pCreateURLMonikerEx2(base_mon, uri, &mon, URL_MK_NO_CANONICALIZE);
10954         ok(hres == S_OK, "CreateURLMonikerEx2 failed: %08x\n", hres);
10955         test_urlmon_display_name(mon, base_url ? test->no_canon_url : test->uri_url);
10956         test_display_uri(mon, base_url ? test->no_canon_url : test->uri_url);
10957         IMoniker_Release(mon);
10958
10959         IUri_Release(uri);
10960         heap_free(url);
10961         heap_free(base_url);
10962         if(base_uri)
10963             IUri_Release(base_uri);
10964         if(base_mon)
10965             IMoniker_Release(base_mon);
10966     }
10967 }
10968
10969 static int add_default_flags(DWORD flags) {
10970     if(!(flags & Uri_CREATE_NO_CANONICALIZE))
10971         flags |= Uri_CREATE_CANONICALIZE;
10972     if(!(flags & Uri_CREATE_NO_DECODE_EXTRA_INFO))
10973         flags |= Uri_CREATE_DECODE_EXTRA_INFO;
10974     if(!(flags & Uri_CREATE_NO_CRACK_UNKNOWN_SCHEMES))
10975         flags |= Uri_CREATE_CRACK_UNKNOWN_SCHEMES;
10976     if(!(flags & Uri_CREATE_NO_PRE_PROCESS_HTML_URI))
10977         flags |= Uri_CREATE_PRE_PROCESS_HTML_URI;
10978     if(!(flags & Uri_CREATE_IE_SETTINGS))
10979         flags |= Uri_CREATE_NO_IE_SETTINGS;
10980
10981     return flags;
10982 }
10983
10984 static void test_IPersistStream(void)
10985 {
10986     int i, props_order[Uri_PROPERTY_DWORD_LAST+1] = { 0 };
10987
10988     props_order[Uri_PROPERTY_RAW_URI] = 1;
10989     props_order[Uri_PROPERTY_FRAGMENT] = 2;
10990     props_order[Uri_PROPERTY_HOST] = 3;
10991     props_order[Uri_PROPERTY_PASSWORD] = 4;
10992     props_order[Uri_PROPERTY_PATH] = 5;
10993     props_order[Uri_PROPERTY_PORT] = 6;
10994     props_order[Uri_PROPERTY_QUERY] = 7;
10995     props_order[Uri_PROPERTY_SCHEME_NAME] = 8;
10996     props_order[Uri_PROPERTY_USER_NAME] = 9;
10997
10998     for(i=0; i<sizeof(uri_tests)/sizeof(*uri_tests); i++) {
10999         const uri_properties *test = uri_tests+i;
11000         LPWSTR uriW;
11001         IUri *uri;
11002         IPersistStream *persist_stream;
11003         IStream *stream;
11004         IMarshal *marshal;
11005         DWORD props, props_no, dw_data[6];
11006         WCHAR str_data[1024];
11007         ULARGE_INTEGER size, max_size;
11008         LARGE_INTEGER no_off;
11009         CLSID curi;
11010         BSTR raw_uri;
11011         HRESULT hr;
11012
11013         if(test->create_todo || test->create_expected!=S_OK)
11014             continue;
11015
11016         uriW = a2w(test->uri);
11017         hr = pCreateUri(uriW, test->create_flags, 0, &uri);
11018         ok(hr == S_OK, "%d) CreateUri failed 0x%08x, expected S_OK..\n", i, hr);
11019
11020         hr = IUri_QueryInterface(uri, &IID_IPersistStream, (void**)&persist_stream);
11021         ok(hr == S_OK, "%d) QueryInterface failed 0x%08x, expected S_OK.\n", i, hr);
11022
11023         hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
11024         ok(hr == S_OK, "CreateStreamOnHGlobal failed 0x%08x.\n", hr);
11025         hr = IPersistStream_IsDirty(persist_stream);
11026         ok(hr == S_FALSE, "%d) IsDirty returned 0x%08x, expected S_FALSE.\n", i, hr);
11027         hr = IPersistStream_Save(persist_stream, stream, FALSE);
11028         ok(hr == S_OK, "%d) Save failed 0x%08x, expected S_OK.\n", i, hr);
11029         hr = IPersistStream_IsDirty(persist_stream);
11030         ok(hr == S_FALSE, "%d) IsDirty returned 0x%08x, expected S_FALSE.\n", i, hr);
11031         no_off.QuadPart = 0;
11032         hr = IStream_Seek(stream, no_off, STREAM_SEEK_CUR, &size);
11033         ok(hr == S_OK, "%d) Seek failed 0x%08x, expected S_OK.\n", i, hr);
11034         hr = IStream_Seek(stream, no_off, STREAM_SEEK_SET, NULL);
11035         ok(hr == S_OK, "%d) Seek failed 0x%08x, expected S_OK.\n", i, hr);
11036         hr = IPersistStream_GetSizeMax(persist_stream, &max_size);
11037         ok(hr == S_OK, "%d) GetSizeMax failed 0x%08x, expected S_OK.\n", i, hr);
11038         ok(U(size).LowPart+2 == U(max_size).LowPart,
11039                 "%d) Written data size is %d, max_size %d.\n",
11040                 i, U(size).LowPart, U(max_size).LowPart);
11041
11042         hr = IStream_Read(stream, (void*)dw_data, sizeof(DWORD), NULL);
11043         ok(hr == S_OK, "%d) Read failed 0x%08x, expected S_OK.\n", i, hr);
11044         ok(dw_data[0]-2 == U(size).LowPart, "%d) Structure size is %d, expected %d\n",
11045                 i, dw_data[0]-2, U(size).LowPart);
11046         hr = IStream_Read(stream, (void*)dw_data, 6*sizeof(DWORD), NULL);
11047         ok(hr == S_OK, "%d) Read failed 0x%08x, expected S_OK.\n", i, hr);
11048         ok(dw_data[0] == 0, "%d) Incorrect value %x, expected 0 (unknown).\n", i, dw_data[0]);
11049         ok(dw_data[1] == 0, "%d) Incorrect value %x, expected 0 (unknown).\n", i, dw_data[1]);
11050         ok(dw_data[2] == add_default_flags(test->create_flags),
11051                 "%d) Incorrect value %x, expected %x (creation flags).\n",
11052                 i, dw_data[2], add_default_flags(test->create_flags));
11053         ok(dw_data[3] == 0, "%d) Incorrect value %x, expected 0 (unknown).\n", i, dw_data[3]);
11054         ok(dw_data[4] == 0, "%d) Incorrect value %x, expected 0 (unknown).\n", i, dw_data[4]);
11055         ok(dw_data[5] == 0, "%d) Incorrect value %x, expected 0 (unknown).\n", i, dw_data[5]);
11056
11057         props_no = 0;
11058         for(props=0; props<=Uri_PROPERTY_DWORD_LAST; props++) {
11059             if(!props_order[props])
11060                 continue;
11061
11062             if(props <= Uri_PROPERTY_STRING_LAST) {
11063                 if(test->str_props[props].expected == S_OK)
11064                     props_no++;
11065             } else {
11066                 if(test->dword_props[props-Uri_PROPERTY_DWORD_START].expected == S_OK)
11067                     props_no++;
11068             }
11069         }
11070         if(test->dword_props[Uri_PROPERTY_SCHEME-Uri_PROPERTY_DWORD_START].value != URL_SCHEME_HTTP
11071                 && test->dword_props[Uri_PROPERTY_SCHEME-Uri_PROPERTY_DWORD_START].value != URL_SCHEME_FTP
11072                 && test->dword_props[Uri_PROPERTY_SCHEME-Uri_PROPERTY_DWORD_START].value != URL_SCHEME_HTTPS)
11073             props_no = 1;
11074
11075         hr = IStream_Read(stream, (void*)&props, sizeof(DWORD), NULL);
11076         ok(hr == S_OK, "%d) Read failed 0x%08x, expected S_OK.\n", i, hr);
11077         ok(props == props_no, "%d) Properties no is %d, expected %d.\n", i, props, props_no);
11078
11079         dw_data[2] = 0;
11080         dw_data[3] = -1;
11081         while(props) {
11082             hr = IStream_Read(stream, (void*)dw_data, 2*sizeof(DWORD), NULL);
11083             ok(hr == S_OK, "%d) Read failed 0x%08x, expected S_OK.\n", i, hr);
11084             props--;
11085             ok(dw_data[2]<props_order[dw_data[0]],
11086                     "%d) Incorrect properties order (%d, %d)\n",
11087                     i, dw_data[0], dw_data[3]);
11088             dw_data[2] = props_order[dw_data[0]];
11089             dw_data[3] = dw_data[0];
11090
11091             if(dw_data[0]<=Uri_PROPERTY_STRING_LAST) {
11092                 const uri_str_property *prop = test->str_props+dw_data[0];
11093                 hr = IStream_Read(stream, (void*)str_data, dw_data[1], NULL);
11094                 ok(hr == S_OK, "%d) Read failed 0x%08x, expected S_OK.\n", i, hr);
11095                 ok(!strcmp_aw(prop->value, str_data) || broken(prop->broken_value && !strcmp_aw(prop->broken_value, str_data)),
11096                         "%d) Expected %s but got %s (%d).\n", i, prop->value, wine_dbgstr_w(str_data), dw_data[0]);
11097             } else if(dw_data[0]>=Uri_PROPERTY_DWORD_START && dw_data[0]<=Uri_PROPERTY_DWORD_LAST) {
11098                 const uri_dword_property *prop = test->dword_props+dw_data[0]-Uri_PROPERTY_DWORD_START;
11099                 ok(dw_data[1] == sizeof(DWORD), "%d) Size of dword property is %d (%d)\n", i, dw_data[1], dw_data[0]);
11100                 hr = IStream_Read(stream, (void*)&dw_data[1], sizeof(DWORD), NULL);
11101                 ok(hr == S_OK, "%d) Read failed 0x%08x, expected S_OK.\n", i, hr);
11102                 ok(prop->value == dw_data[1], "%d) Expected %d but got %d (%d).\n", i, prop->value, dw_data[1], dw_data[0]);
11103             } else {
11104                 ok(FALSE, "%d) Incorrect property type (%d)\n", i, dw_data[0]);
11105                 break;
11106             }
11107         }
11108         ok(props == 0, "%d) No all properties were processed %d. Next property type: %d\n",
11109                 i, props, dw_data[0]);
11110
11111         IPersistStream_Release(persist_stream);
11112         IUri_Release(uri);
11113
11114         hr = IStream_Seek(stream, no_off, STREAM_SEEK_SET, NULL);
11115         ok(hr == S_OK, "%d) Seek failed 0x%08x, expected S_OK.\n", i, hr);
11116         hr = IPersistStream_GetClassID(persist_stream, &curi);
11117         ok(hr == S_OK, "%d) GetClassID failed 0x%08x, expected S_OK.\n", i, hr);
11118         ok(IsEqualCLSID(&curi, &CLSID_CUri), "%d) GetClassID returned incorrect CLSID.\n", i);
11119         hr = CoCreateInstance(&curi, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
11120                 &IID_IUri, (void**)&uri);
11121         ok(hr == S_OK, "%d) Error creating uninitialized Uri: 0x%08x.\n", i, hr);
11122         hr = IUri_QueryInterface(uri, &IID_IPersistStream, (void**)&persist_stream);
11123         ok(hr == S_OK, "%d) QueryInterface failed 0x%08x, expected S_OK.\n", i, hr);
11124         hr = IPersistStream_Load(persist_stream, stream);
11125         ok(hr == S_OK, "%d) Load failed 0x%08x, expected S_OK.\n", i, hr);
11126         hr = IUri_GetRawUri(uri, &raw_uri);
11127         ok(hr == S_OK, "%d) GetRawUri failed 0x%08x, expected S_OK.\n", i, hr);
11128         ok(!strcmp_aw(test->str_props[Uri_PROPERTY_RAW_URI].value, raw_uri)
11129                 || broken(test->str_props[Uri_PROPERTY_RAW_URI].broken_value
11130                     && !strcmp_aw(test->str_props[Uri_PROPERTY_RAW_URI].broken_value, raw_uri)),
11131                 "%d) Expected %s but got %s.\n", i, test->str_props[Uri_PROPERTY_RAW_URI].value,
11132                 wine_dbgstr_w(raw_uri));
11133         SysFreeString(raw_uri);
11134
11135         hr = IUri_QueryInterface(uri, &IID_IMarshal, (void**)&marshal);
11136         ok(hr == S_OK, "%d) QueryInterface(IID_IMarshal) failed 0x%08x, expected S_OK.\n", i, hr);
11137         hr = IStream_Seek(stream, no_off, STREAM_SEEK_SET, NULL);
11138         ok(hr == S_OK, "%d) Seek failed 0x%08x, expected S_OK.\n", i, hr);
11139         hr = IMarshal_MarshalInterface(marshal, stream, &IID_IUri, (void*)uri,
11140                 MSHCTX_DIFFERENTMACHINE, NULL, MSHLFLAGS_NORMAL);
11141         ok(hr == E_INVALIDARG, "%d) MarshalInterface returned 0x%08x, expected E_INVALIDARG.\n", i, hr);
11142         hr = IMarshal_MarshalInterface(marshal, stream, &IID_IUri, (void*)uri,
11143                 MSHCTX_CROSSCTX, NULL, MSHLFLAGS_NORMAL);
11144         ok(hr == E_INVALIDARG, "%d) MarshalInterface returned 0x%08x, expected E_INVALIDARG.\n", i, hr);
11145         hr = IMarshal_MarshalInterface(marshal, stream, &IID_IUri, (void*)uri,
11146                 MSHCTX_LOCAL, NULL, MSHLFLAGS_TABLESTRONG);
11147         ok(hr == E_INVALIDARG, "%d) MarshalInterface returned 0x%08x, expected E_INVALIDARG.\n", i, hr);
11148         hr = IMarshal_MarshalInterface(marshal, stream, &IID_IUri, (void*)uri,
11149                 MSHCTX_LOCAL, NULL, MSHLFLAGS_TABLEWEAK);
11150         ok(hr == E_INVALIDARG, "%d) MarshalInterface returned 0x%08x, expected E_INVALIDARG.\n", i, hr);
11151         hr = IMarshal_MarshalInterface(marshal, stream, &IID_IUri, (void*)uri,
11152                 MSHCTX_LOCAL, NULL, MSHLFLAGS_NOPING);
11153         ok(hr == E_INVALIDARG, "%d) MarshalInterface returned 0x%08x, expected E_INVALIDARG.\n", i, hr);
11154         hr = IMarshal_MarshalInterface(marshal, stream, &IID_IUri, (void*)uri,
11155                 MSHCTX_LOCAL, NULL, MSHLFLAGS_NORMAL);
11156         ok(hr == S_OK, "%d) MarshalInterface failed 0x%08x, expected S_OK.\n", i, hr);
11157         hr = IMarshal_GetUnmarshalClass(marshal, &IID_IUri, (void*)uri,
11158                 MSHCTX_CROSSCTX, NULL, MSHLFLAGS_NORMAL, &curi);
11159         ok(hr == E_INVALIDARG, "%d) GetUnmarshalClass returned 0x%08x, expected E_INVALIDARG.\n", i, hr);
11160         hr = IMarshal_GetUnmarshalClass(marshal, &IID_IUri, (void*)uri,
11161                 MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL, &curi);
11162         ok(hr == S_OK, "%d) GetUnmarshalClass failed 0x%08x, expected S_OK.\n", i, hr);
11163         ok(IsEqualCLSID(&curi, &CLSID_CUri), "%d) GetUnmarshalClass returned incorrect CLSID.\n", i);
11164
11165         hr = IStream_Seek(stream, no_off, STREAM_SEEK_CUR, &size);
11166         ok(hr == S_OK, "%d) Seek failed 0x%08x, expected S_OK.\n", i, hr);
11167         hr = IStream_Seek(stream, no_off, STREAM_SEEK_SET, NULL);
11168         ok(hr == S_OK, "%d) Seek failed 0x%08x, expected S_OK.\n", i, hr);
11169         hr = IStream_Read(stream, (void*)dw_data, 3*sizeof(DWORD), NULL);
11170         ok(hr == S_OK, "%d) Read failed 0x%08x, expected S_OK.\n", i, hr);
11171         ok(dw_data[0]-2 == U(size).LowPart, "%d) Structure size is %d, expected %d\n",
11172                 i, dw_data[0]-2, U(size).LowPart);
11173         ok(dw_data[1] == MSHCTX_LOCAL, "%d) Incorrect value %d, expected MSHCTX_LOCAL.\n",
11174                 i, dw_data[1]);
11175         ok(dw_data[2] == dw_data[0]-8, "%d) Incorrect value %d, expected %d (PersistStream size).\n",
11176                 i, dw_data[2], dw_data[0]-8);
11177         if(!test->str_props[Uri_PROPERTY_PATH].value[0] &&
11178                 (test->dword_props[Uri_PROPERTY_SCHEME-Uri_PROPERTY_DWORD_START].value == URL_SCHEME_HTTP
11179                  || test->dword_props[Uri_PROPERTY_SCHEME-Uri_PROPERTY_DWORD_START].value == URL_SCHEME_FTP
11180                  || test->dword_props[Uri_PROPERTY_SCHEME-Uri_PROPERTY_DWORD_START].value == URL_SCHEME_HTTPS))
11181             U(max_size).LowPart += 3*sizeof(DWORD);
11182         ok(dw_data[2] == U(max_size).LowPart, "%d) Incorrect value %d, expected %d (PersistStream size).\n",
11183                 i, dw_data[2], U(max_size).LowPart);
11184         IMarshal_Release(marshal);
11185         IUri_Release(uri);
11186
11187         hr = IStream_Seek(stream, no_off, STREAM_SEEK_SET, NULL);
11188         ok(hr == S_OK, "%d) Seek failed 0x%08x, expected S_OK.\n", i, hr);
11189         hr = CoCreateInstance(&curi, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
11190                 &IID_IUri, (void**)&uri);
11191         ok(hr == S_OK, "%d) Error creating uninitialized Uri: 0x%08x.\n", i, hr);
11192         hr = IUri_QueryInterface(uri, &IID_IMarshal, (void**)&marshal);
11193         ok(hr == S_OK, "%d) QueryInterface failed 0x%08x, expected S_OK.\n", i, hr);
11194         hr = IMarshal_UnmarshalInterface(marshal, stream, &IID_IUri, (void**)&uri);
11195         ok(hr == S_OK, "%d) UnmarshalInterface failed 0x%08x, expected S_OK.\n", i, hr);
11196         hr = IUri_GetRawUri(uri, &raw_uri);
11197         ok(hr == S_OK, "%d) GetRawUri failed 0x%08x, expected S_OK.\n", i, hr);
11198         ok(!strcmp_aw(test->str_props[Uri_PROPERTY_RAW_URI].value, raw_uri)
11199                 || broken(test->str_props[Uri_PROPERTY_RAW_URI].broken_value
11200                     && !strcmp_aw(test->str_props[Uri_PROPERTY_RAW_URI].broken_value, raw_uri)),
11201                 "%d) Expected %s but got %s.\n", i, test->str_props[Uri_PROPERTY_RAW_URI].value,
11202                 wine_dbgstr_w(raw_uri));
11203         SysFreeString(raw_uri);
11204
11205         IMarshal_Release(marshal);
11206         IStream_Release(stream);
11207         IPersistStream_Release(persist_stream);
11208         IUri_Release(uri);
11209         heap_free(uriW);
11210     }
11211 }
11212
11213 static void test_UninitializedUri(void)
11214 {
11215     IUri *uri;
11216     IUriBuilderFactory *ubf;
11217     IPersistStream *ps;
11218     IUriBuilder *ub;
11219     BSTR bstr;
11220     DWORD dword;
11221     BOOL eq;
11222     ULARGE_INTEGER ui;
11223     HRESULT hr;
11224
11225     hr = CoCreateInstance(&CLSID_CUri, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
11226             &IID_IUri, (void**)&uri);
11227     if(FAILED(hr)) {
11228         win_skip("Skipping uninitialized Uri tests.\n");
11229         return;
11230     }
11231
11232     hr = IUri_QueryInterface(uri, &IID_IUriBuilderFactory, (void**)&ubf);
11233     ok(hr == S_OK, "QueryInterface(IID_IUriBuillderFactory) failed: %x.\n", hr);
11234     hr = IUri_QueryInterface(uri, &IID_IPersistStream, (void**)&ps);
11235     ok(hr == S_OK, "QueryInterface(IID_IPersistStream) failed: %x.\n", hr);
11236
11237     hr = IUri_GetAbsoluteUri(uri, NULL);
11238     ok(hr == E_UNEXPECTED, "GetAbsoluteUri returned %x, expected E_UNEXPECTED.\n", hr);
11239     hr = IUri_GetAbsoluteUri(uri, &bstr);
11240     ok(hr == E_UNEXPECTED, "GetAbsoluteUri returned %x, expected E_UNEXPECTED.\n", hr);
11241     hr = IUri_GetAuthority(uri, &bstr);
11242     ok(hr == E_UNEXPECTED, "GetAuthority returned %x, expected E_UNEXPECTED.\n", hr);
11243     hr = IUri_GetDisplayUri(uri, &bstr);
11244     ok(hr == E_UNEXPECTED, "GetDisplayUri returned %x, expected E_UNEXPECTED.\n", hr);
11245     hr = IUri_GetDomain(uri, &bstr);
11246     ok(hr == E_UNEXPECTED, "GetDomain returned %x, expected E_UNEXPECTED.\n", hr);
11247     hr = IUri_GetExtension(uri, &bstr);
11248     ok(hr == E_UNEXPECTED, "GetExtension returned %x, expected E_UNEXPECTED.\n", hr);
11249     hr = IUri_GetFragment(uri, &bstr);
11250     ok(hr == E_UNEXPECTED, "GetFragment returned %x, expected E_UNEXPECTED.\n", hr);
11251     hr = IUri_GetHost(uri, &bstr);
11252     ok(hr == E_UNEXPECTED, "GetHost returned %x, expected E_UNEXPECTED.\n", hr);
11253     hr = IUri_GetHostType(uri, &dword);
11254     ok(hr == E_UNEXPECTED, "GetHostType returned %x, expected E_UNEXPECTED.\n", hr);
11255     hr = IUri_GetPassword(uri, &bstr);
11256     ok(hr == E_UNEXPECTED, "GetPassword returned %x, expected E_UNEXPECTED.\n", hr);
11257     hr = IUri_GetPassword(uri, &bstr);
11258     ok(hr == E_UNEXPECTED, "GetPassword returned %x, expected E_UNEXPECTED.\n", hr);
11259     hr = IUri_GetPathAndQuery(uri, &bstr);
11260     ok(hr == E_UNEXPECTED, "GetPathAndQuery returned %x, expected E_UNEXPECTED.\n", hr);
11261     hr = IUri_GetPort(uri, &dword);
11262     ok(hr == E_UNEXPECTED, "GetPort returned %x, expected E_UNEXPECTED.\n", hr);
11263     hr = IUri_GetProperties(uri, &dword);
11264     ok(hr == E_UNEXPECTED, "GetProperties returned %x, expected E_UNEXPECTED.\n", hr);
11265     hr = IUri_GetPropertyBSTR(uri, Uri_PROPERTY_RAW_URI, &bstr, 0);
11266     ok(hr == E_UNEXPECTED, "GetPropertyBSTR returned %x, expected E_UNEXPECTED.\n", hr);
11267     hr = IUri_GetPropertyDWORD(uri, Uri_PROPERTY_PORT, &dword, 0);
11268     ok(hr == E_UNEXPECTED, "GetPropertyDWORD returned %x, expected E_UNEXPECTED.\n", hr);
11269     hr = IUri_GetPropertyLength(uri, Uri_PROPERTY_RAW_URI, &dword, 0);
11270     ok(hr == E_UNEXPECTED, "GetPropertyLength returned %x, expected E_UNEXPECTED.\n", hr);
11271     hr = IUri_GetQuery(uri, &bstr);
11272     ok(hr == E_UNEXPECTED, "GetQuery returned %x, expected E_UNEXPECTED.\n", hr);
11273     hr = IUri_GetRawUri(uri, &bstr);
11274     ok(hr == E_UNEXPECTED, "GetRawUri returned %x, expected E_UNEXPECTED.\n", hr);
11275     hr = IUri_GetScheme(uri, &dword);
11276     ok(hr == E_UNEXPECTED, "GetScheme returned %x, expected E_UNEXPECTED.\n", hr);
11277     hr = IUri_GetSchemeName(uri, &bstr);
11278     ok(hr == E_UNEXPECTED, "GetSchemeName returned %x, expected E_UNEXPECTED.\n", hr);
11279     hr = IUri_GetUserInfo(uri, &bstr);
11280     ok(hr == E_UNEXPECTED, "GetUserInfo returned %x, expected E_UNEXPECTED.\n", hr);
11281     hr = IUri_GetUserName(uri, &bstr);
11282     ok(hr == E_UNEXPECTED, "GetUserName returned %x, expected E_UNEXPECTED.\n", hr);
11283     hr = IUri_GetZone(uri, &dword);
11284     ok(hr == E_UNEXPECTED, "GetZone returned %x, expected E_UNEXPECTED.\n", hr);
11285     hr = IUri_IsEqual(uri, uri, &eq);
11286     ok(hr == E_UNEXPECTED, "IsEqual returned %x, expected E_UNEXPECTED.\n", hr);
11287
11288     hr = IUriBuilderFactory_CreateInitializedIUriBuilder(ubf, 0, 0, &ub);
11289     ok(hr == E_UNEXPECTED, "CreateInitializedIUriBuilder returned %x, expected E_UNEXPECTED.\n", hr);
11290     hr = IUriBuilderFactory_CreateIUriBuilder(ubf, 0, 0, &ub);
11291     ok(hr == S_OK, "CreateIUriBuilder returned %x, expected S_OK.\n", hr);
11292     IUriBuilder_Release(ub);
11293
11294     hr = IPersistStream_GetSizeMax(ps, &ui);
11295     ok(hr == S_OK, "GetSizeMax returned %x, expected S_OK.\n", hr);
11296     ok(ui.u.LowPart == 34, "ui.LowPart = %d, expected 34.\n", ui.u.LowPart);
11297     hr = IPersistStream_IsDirty(ps);
11298     ok(hr == S_FALSE, "IsDirty returned %x, expected S_FALSE.\n", hr);
11299
11300     IPersistStream_Release(ps);
11301     IUriBuilderFactory_Release(ubf);
11302     IUri_Release(uri);
11303 }
11304
11305 START_TEST(uri) {
11306     HMODULE hurlmon;
11307
11308     hurlmon = GetModuleHandle("urlmon.dll");
11309     pCoInternetGetSession = (void*) GetProcAddress(hurlmon, "CoInternetGetSession");
11310     pCreateUri = (void*) GetProcAddress(hurlmon, "CreateUri");
11311     pCreateUriWithFragment = (void*) GetProcAddress(hurlmon, "CreateUriWithFragment");
11312     pCreateIUriBuilder = (void*) GetProcAddress(hurlmon, "CreateIUriBuilder");
11313     pCoInternetCombineIUri = (void*) GetProcAddress(hurlmon, "CoInternetCombineIUri");
11314     pCoInternetCombineUrlEx = (void*) GetProcAddress(hurlmon, "CoInternetCombineUrlEx");
11315     pCoInternetParseIUri = (void*) GetProcAddress(hurlmon, "CoInternetParseIUri");
11316     pCreateURLMonikerEx = (void*) GetProcAddress(hurlmon, "CreateURLMonikerEx");
11317     pCreateURLMonikerEx2 = (void*) GetProcAddress(hurlmon, "CreateURLMonikerEx2");
11318
11319     if(!pCreateUri) {
11320         win_skip("CreateUri is not present, skipping tests.\n");
11321         return;
11322     }
11323
11324     trace("test CreateUri invalid flags...\n");
11325     test_CreateUri_InvalidFlags();
11326
11327     trace("test CreateUri invalid args...\n");
11328     test_CreateUri_InvalidArgs();
11329
11330     trace("test CreateUri invalid URIs...\n");
11331     test_CreateUri_InvalidUri();
11332
11333     trace("test IUri_GetPropertyBSTR...\n");
11334     test_IUri_GetPropertyBSTR();
11335
11336     trace("test IUri_GetPropertyDWORD...\n");
11337     test_IUri_GetPropertyDWORD();
11338
11339     trace("test IUri_GetStrProperties...\n");
11340     test_IUri_GetStrProperties();
11341
11342     trace("test IUri_GetDwordProperties...\n");
11343     test_IUri_GetDwordProperties();
11344
11345     trace("test IUri_GetPropertyLength...\n");
11346     test_IUri_GetPropertyLength();
11347
11348     trace("test IUri_GetProperties...\n");
11349     test_IUri_GetProperties();
11350
11351     trace("test IUri_HasProperty...\n");
11352     test_IUri_HasProperty();
11353
11354     trace("test IUri_IsEqual...\n");
11355     test_IUri_IsEqual();
11356
11357     trace("test CreateUriWithFragment invalid args...\n");
11358     test_CreateUriWithFragment_InvalidArgs();
11359
11360     trace("test CreateUriWithFragment invalid flags...\n");
11361     test_CreateUriWithFragment_InvalidFlags();
11362
11363     trace("test CreateUriWithFragment...\n");
11364     test_CreateUriWithFragment();
11365
11366     trace("test CreateIUriBuilder...\n");
11367     test_CreateIUriBuilder();
11368
11369     trace("test IUriBuilder_CreateInvalidArgs...\n");
11370     test_IUriBuilder_CreateInvalidArgs();
11371
11372     trace("test IUriBuilder...\n");
11373     test_IUriBuilder();
11374
11375     trace("test IUriBuilder_GetInvalidArgs...\n");
11376     test_IUriBuilder_GetInvalidArgs();
11377
11378     trace("test IUriBuilder_HasBeenModified...\n");
11379     test_IUriBuilder_HasBeenModified();
11380
11381     trace("test IUriBuilder_IUriProperty...\n");
11382     test_IUriBuilder_IUriProperty();
11383
11384     trace("test IUriBuilder_RemoveProperties...\n");
11385     test_IUriBuilder_RemoveProperties();
11386
11387     trace("test IUriBuilder miscellaneous...\n");
11388     test_IUriBuilder_Misc();
11389
11390     trace("test IUriBuilderFactory...\n");
11391     test_IUriBuilderFactory();
11392
11393     trace("test CoInternetCombineIUri...\n");
11394     test_CoInternetCombineIUri();
11395
11396     trace("test CoInternetCombineUrlEx...\n");
11397     test_CoInternetCombineUrlEx();
11398
11399     trace("test CoInternetParseIUri Invalid Args...\n");
11400     test_CoInternetParseIUri_InvalidArgs();
11401
11402     trace("test CoInternetParseIUri...\n");
11403     test_CoInternetParseIUri();
11404
11405     register_protocols();
11406
11407     trace("test CoInternetCombineIUri pluggable...\n");
11408     test_CoInternetCombineIUri_Pluggable();
11409
11410     trace("test CoInternetCombineUrlEx Pluggable...\n");
11411     test_CoInternetCombineUrlEx_Pluggable();
11412
11413     trace("test CoInternetParseIUri pluggable...\n");
11414     test_CoInternetParseIUri_Pluggable();
11415
11416     trace("test CreateURLMoniker...\n");
11417     test_CreateURLMoniker();
11418
11419     CoInitialize(NULL);
11420
11421     trace("test IPersistStream...\n");
11422     test_IPersistStream();
11423
11424     trace("test uninitialized Uri...\n");
11425     test_UninitializedUri();
11426
11427     CoUninitialize();
11428     unregister_protocols();
11429 }