wordpad: Allow objects & images to be added with native riched20.
[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 /*
22  * IUri testing framework goals:
23  *  - Test invalid args
24  *      - invalid flags
25  *      - invalid args (IUri, uri string)
26  *  - Test parsing for components when no canonicalization occurs
27  *  - Test parsing for components when canonicalization occurs.
28  *  - More tests...
29  */
30
31 #include <wine/test.h>
32 #include <stdarg.h>
33 #include <stddef.h>
34
35 #define COBJMACROS
36
37 #include "windef.h"
38 #include "winbase.h"
39 #include "urlmon.h"
40 #include "shlwapi.h"
41
42 #define URI_STR_PROPERTY_COUNT Uri_PROPERTY_STRING_LAST+1
43 #define URI_DWORD_PROPERTY_COUNT (Uri_PROPERTY_DWORD_LAST - Uri_PROPERTY_DWORD_START)+1
44
45 static HRESULT (WINAPI *pCreateUri)(LPCWSTR, DWORD, DWORD_PTR, IUri**);
46
47 static const WCHAR http_urlW[] = { 'h','t','t','p',':','/','/','w','w','w','.','w','i','n','e','h','q',
48         '.','o','r','g','/',0};
49
50 typedef struct _uri_create_flag_test {
51     DWORD   flags;
52     HRESULT expected;
53 } uri_create_flag_test;
54
55 static const uri_create_flag_test invalid_flag_tests[] = {
56     /* Set of invalid flag combinations to test for. */
57     {Uri_CREATE_DECODE_EXTRA_INFO | Uri_CREATE_NO_DECODE_EXTRA_INFO, E_INVALIDARG},
58     {Uri_CREATE_CANONICALIZE | Uri_CREATE_NO_CANONICALIZE, E_INVALIDARG},
59     {Uri_CREATE_CRACK_UNKNOWN_SCHEMES | Uri_CREATE_NO_CRACK_UNKNOWN_SCHEMES, E_INVALIDARG},
60     {Uri_CREATE_PRE_PROCESS_HTML_URI | Uri_CREATE_NO_PRE_PROCESS_HTML_URI, E_INVALIDARG},
61     {Uri_CREATE_IE_SETTINGS | Uri_CREATE_NO_IE_SETTINGS, E_INVALIDARG}
62 };
63
64 typedef struct _uri_str_property {
65     const char* value;
66     HRESULT     expected;
67     BOOL        todo;
68 } uri_str_property;
69
70 typedef struct _uri_dword_property {
71     DWORD   value;
72     HRESULT expected;
73     BOOL    todo;
74 } uri_dword_property;
75
76 typedef struct _uri_properties {
77     const char*         uri;
78     DWORD               create_flags;
79     HRESULT             create_expected;
80     BOOL                create_todo;
81     DWORD               props;
82     BOOL                props_todo;
83
84     uri_str_property    str_props[URI_STR_PROPERTY_COUNT];
85     uri_dword_property  dword_props[URI_DWORD_PROPERTY_COUNT];
86 } uri_properties;
87
88 static const uri_properties uri_tests[] = {
89     {   "http://www.winehq.org/tests/../tests/../..", 0, S_OK, FALSE,
90         /* A flag bitmap containing all the Uri_HAS_* flags that correspond to this uri. */
91         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_HOST|
92         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|
93         Uri_HAS_PORT|Uri_HAS_SCHEME,
94         TRUE,
95         {
96             {"http://www.winehq.org/",S_OK,TRUE},                       /* ABSOLUTE_URI */
97             {"www.winehq.org",S_OK,TRUE},                               /* AUTHORITY */
98             {"http://www.winehq.org/",S_OK,TRUE},                       /* DISPLAY_URI */
99             {"winehq.org",S_OK,TRUE},                                   /* DOMAIN */
100             {"",S_FALSE,TRUE},                                          /* EXTENSION */
101             {"",S_FALSE,TRUE},                                          /* FRAGMENT */
102             {"www.winehq.org",S_OK,TRUE},                               /* HOST */
103             {"",S_FALSE,FALSE},                                         /* PASSWORD */
104             {"/",S_OK,TRUE},                                            /* PATH */
105             {"/",S_OK,TRUE},                                            /* PATH_AND_QUERY */
106             {"",S_FALSE,TRUE},                                          /* QUERY */
107             {"http://www.winehq.org/tests/../tests/../..",S_OK,FALSE},  /* RAW_URI */
108             {"http",S_OK,FALSE},                                        /* SCHEME_NAME */
109             {"",S_FALSE,FALSE},                                         /* USER_INFO */
110             {"",S_FALSE,FALSE}                                          /* USER_NAME */
111         },
112         {
113             {Uri_HOST_DNS,S_OK,TRUE},                                   /* HOST_TYPE */
114             {80,S_OK,TRUE},                                             /* PORT */
115             {URL_SCHEME_HTTP,S_OK,FALSE},                               /* SCHEME */
116             {URLZONE_INVALID,E_NOTIMPL,FALSE}                           /* ZONE */
117         }
118     },
119     {   "http://winehq.org/tests/.././tests", 0, S_OK, FALSE,
120         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_HOST|
121         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|
122         Uri_HAS_PORT|Uri_HAS_SCHEME,
123         TRUE,
124         {
125             {"http://winehq.org/tests",S_OK,TRUE},
126             {"winehq.org",S_OK,TRUE},
127             {"http://winehq.org/tests",S_OK,TRUE},
128             {"winehq.org",S_OK,TRUE},
129             {"",S_FALSE,TRUE},
130             {"",S_FALSE,TRUE},
131             {"winehq.org",S_OK,TRUE},
132             {"",S_FALSE,FALSE},
133             {"/tests",S_OK,TRUE},
134             {"/tests",S_OK,TRUE},
135             {"",S_FALSE,TRUE},
136             {"http://winehq.org/tests/.././tests",S_OK,FALSE},
137             {"http",S_OK,FALSE},
138             {"",S_FALSE,FALSE},
139             {"",S_FALSE,FALSE}
140         },
141         {
142             {Uri_HOST_DNS,S_OK,TRUE},
143             {80,S_OK,TRUE},
144             {URL_SCHEME_HTTP,S_OK,FALSE},
145             {URLZONE_INVALID,E_NOTIMPL,FALSE}
146         }
147     },
148     {   "HtTp://www.winehq.org/tests/..?query=x&return=y", 0, S_OK, FALSE,
149         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_HOST|
150         Uri_HAS_DOMAIN|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_QUERY|Uri_HAS_RAW_URI|
151         Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
152         TRUE,
153         {
154             {"http://www.winehq.org/?query=x&return=y",S_OK,TRUE},
155             {"www.winehq.org",S_OK,TRUE},
156             {"http://www.winehq.org/?query=x&return=y",S_OK,TRUE},
157             {"winehq.org",S_OK,TRUE},
158             {"",S_FALSE,TRUE},
159             {"",S_FALSE,TRUE},
160             {"www.winehq.org",S_OK,TRUE},
161             {"",S_FALSE,FALSE},
162             {"/",S_OK,TRUE},
163             {"/?query=x&return=y",S_OK,TRUE},
164             {"?query=x&return=y",S_OK,TRUE},
165             {"HtTp://www.winehq.org/tests/..?query=x&return=y",S_OK,FALSE},
166             {"http",S_OK,FALSE},
167             {"",S_FALSE,FALSE},
168             {"",S_FALSE,FALSE}
169         },
170         {
171             {Uri_HOST_DNS,S_OK,TRUE},
172             {80,S_OK,TRUE},
173             {URL_SCHEME_HTTP,S_OK,FALSE},
174             {URLZONE_INVALID,E_NOTIMPL,FALSE},
175         }
176     },
177     {   "hTTp://us%45r%3Ainfo@examp%4CE.com:80/path/a/b/./c/../%2E%2E/Forbidden'<|> Characters", 0, S_OK, FALSE,
178         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_HOST|Uri_HAS_PATH|
179         Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_USER_INFO|Uri_HAS_USER_NAME|
180         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
181         TRUE,
182         {
183             {"http://usEr%3Ainfo@example.com/path/a/Forbidden'%3C%7C%3E%20Characters",S_OK,TRUE},
184             {"usEr%3Ainfo@example.com",S_OK,TRUE},
185             {"http://example.com/path/a/Forbidden'%3C%7C%3E%20Characters",S_OK,TRUE},
186             {"example.com",S_OK,TRUE},
187             {"",S_FALSE,TRUE},
188             {"",S_FALSE,TRUE},
189             {"example.com",S_OK,TRUE},
190             {"",S_FALSE,FALSE},
191             {"/path/a/Forbidden'%3C%7C%3E%20Characters",S_OK,TRUE},
192             {"/path/a/Forbidden'%3C%7C%3E%20Characters",S_OK,TRUE},
193             {"",S_FALSE,TRUE},
194             {"hTTp://us%45r%3Ainfo@examp%4CE.com:80/path/a/b/./c/../%2E%2E/Forbidden'<|> Characters",S_OK,FALSE},
195             {"http",S_OK,FALSE},
196             {"usEr%3Ainfo",S_OK,FALSE},
197             {"usEr%3Ainfo",S_OK,FALSE}
198         },
199         {
200             {Uri_HOST_DNS,S_OK,TRUE},
201             {80,S_OK,TRUE},
202             {URL_SCHEME_HTTP,S_OK,FALSE},
203             {URLZONE_INVALID,E_NOTIMPL,FALSE},
204         }
205     },
206     {   "ftp://winepass:wine@ftp.winehq.org:9999/dir/foo bar.txt", 0, S_OK, FALSE,
207         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_EXTENSION|
208         Uri_HAS_HOST|Uri_HAS_PASSWORD|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
209         Uri_HAS_SCHEME_NAME|Uri_HAS_USER_INFO|Uri_HAS_USER_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|
210         Uri_HAS_SCHEME,
211         TRUE,
212         {
213             {"ftp://winepass:wine@ftp.winehq.org:9999/dir/foo%20bar.txt",S_OK,TRUE},
214             {"winepass:wine@ftp.winehq.org:9999",S_OK,TRUE},
215             {"ftp://ftp.winehq.org:9999/dir/foo%20bar.txt",S_OK,TRUE},
216             {"winehq.org",S_OK,TRUE},
217             {".txt",S_OK,TRUE},
218             {"",S_FALSE,TRUE},
219             {"ftp.winehq.org",S_OK,TRUE},
220             {"wine",S_OK,FALSE},
221             {"/dir/foo%20bar.txt",S_OK,TRUE},
222             {"/dir/foo%20bar.txt",S_OK,TRUE},
223             {"",S_FALSE,TRUE},
224             {"ftp://winepass:wine@ftp.winehq.org:9999/dir/foo bar.txt",S_OK,FALSE},
225             {"ftp",S_OK,FALSE},
226             {"winepass:wine",S_OK,FALSE},
227             {"winepass",S_OK,FALSE}
228         },
229         {
230             {Uri_HOST_DNS,S_OK,TRUE},
231             {9999,S_OK,TRUE},
232             {URL_SCHEME_FTP,S_OK,FALSE},
233             {URLZONE_INVALID,E_NOTIMPL,FALSE}
234         }
235     },
236     {   "file://c:\\tests\\../tests/foo%20bar.mp3", 0, S_OK, FALSE,
237         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH|
238         Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
239         TRUE,
240         {
241             {"file:///c:/tests/foo%2520bar.mp3",S_OK,TRUE},
242             {"",S_FALSE,TRUE},
243             {"file:///c:/tests/foo%2520bar.mp3",S_OK,TRUE},
244             {"",S_FALSE,TRUE},
245             {".mp3",S_OK,TRUE},
246             {"",S_FALSE,TRUE},
247             {"",S_FALSE,TRUE},
248             {"",S_FALSE,FALSE},
249             {"/c:/tests/foo%2520bar.mp3",S_OK,TRUE},
250             {"/c:/tests/foo%2520bar.mp3",S_OK,TRUE},
251             {"",S_FALSE,TRUE},
252             {"file://c:\\tests\\../tests/foo%20bar.mp3",S_OK,FALSE},
253             {"file",S_OK,FALSE},
254             {"",S_FALSE,FALSE},
255             {"",S_FALSE,FALSE}
256         },
257         {
258             {Uri_HOST_UNKNOWN,S_OK,TRUE},
259             {0,S_FALSE,TRUE},
260             {URL_SCHEME_FILE,S_OK,FALSE},
261             {URLZONE_INVALID,E_NOTIMPL,FALSE}
262         }
263     },
264     {   "FILE://localhost/test dir\\../tests/test%20file.README.txt", 0, S_OK, FALSE,
265         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH|
266         Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
267         TRUE,
268         {
269             {"file:///tests/test%20file.README.txt",S_OK,TRUE},
270             {"",S_FALSE,TRUE},
271             {"file:///tests/test%20file.README.txt",S_OK,TRUE},
272             {"",S_FALSE,TRUE},
273             {".txt",S_OK,TRUE},
274             {"",S_FALSE,TRUE},
275             {"",S_FALSE,TRUE},
276             {"",S_FALSE,FALSE},
277             {"/tests/test%20file.README.txt",S_OK,TRUE},
278             {"/tests/test%20file.README.txt",S_OK,TRUE},
279             {"",S_FALSE,TRUE},
280             {"FILE://localhost/test dir\\../tests/test%20file.README.txt",S_OK,FALSE},
281             {"file",S_OK,FALSE},
282             {"",S_FALSE,FALSE},
283             {"",S_FALSE,FALSE}
284         },
285         {
286             {Uri_HOST_UNKNOWN,S_OK,TRUE},
287             {0,S_FALSE,TRUE},
288             {URL_SCHEME_FILE,S_OK,FALSE},
289             {URLZONE_INVALID,E_NOTIMPL,FALSE}
290         }
291     },
292     {   "urn:nothing:should:happen here", 0, S_OK, FALSE,
293         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|
294         Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
295         TRUE,
296         {
297             {"urn:nothing:should:happen here",S_OK,TRUE},
298             {"",S_FALSE,TRUE},
299             {"urn:nothing:should:happen here",S_OK,TRUE},
300             {"",S_FALSE,TRUE},
301             {"",S_FALSE,TRUE},
302             {"",S_FALSE,TRUE},
303             {"",S_FALSE,TRUE},
304             {"",S_FALSE,FALSE},
305             {"nothing:should:happen here",S_OK,TRUE},
306             {"nothing:should:happen here",S_OK,TRUE},
307             {"",S_FALSE,TRUE},
308             {"urn:nothing:should:happen here",S_OK,FALSE},
309             {"urn",S_OK,FALSE},
310             {"",S_FALSE,FALSE},
311             {"",S_FALSE,FALSE}
312         },
313         {
314             {Uri_HOST_UNKNOWN,S_OK,TRUE},
315             {0,S_FALSE,TRUE},
316             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
317             {URLZONE_INVALID,E_NOTIMPL,FALSE}
318         }
319     },
320     {   "http://127.0.0.1/tests/../test dir/./test.txt", 0, S_OK, FALSE,
321         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|
322         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
323         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
324         TRUE,
325         {
326             {"http://127.0.0.1/test%20dir/test.txt",S_OK,TRUE},
327             {"127.0.0.1",S_OK,TRUE},
328             {"http://127.0.0.1/test%20dir/test.txt",S_OK,TRUE},
329             {"",S_FALSE,TRUE},
330             {".txt",S_OK,TRUE},
331             {"",S_FALSE,TRUE},
332             {"127.0.0.1",S_OK,TRUE},
333             {"",S_FALSE,FALSE},
334             {"/test%20dir/test.txt",S_OK,TRUE},
335             {"/test%20dir/test.txt",S_OK,TRUE},
336             {"",S_FALSE,TRUE},
337             {"http://127.0.0.1/tests/../test dir/./test.txt",S_OK,FALSE},
338             {"http",S_OK,FALSE},
339             {"",S_FALSE,FALSE},
340             {"",S_FALSE,FALSE}
341         },
342         {
343             {Uri_HOST_IPV4,S_OK,TRUE},
344             {80,S_OK,TRUE},
345             {URL_SCHEME_HTTP,S_OK,FALSE},
346             {URLZONE_INVALID,E_NOTIMPL,FALSE}
347         }
348     },
349     {   "http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]", 0, S_OK, FALSE,
350         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
351         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
352         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
353         TRUE,
354         {
355             {"http://[fedc:ba98:7654:3210:fedc:ba98:7654:3210]/",S_OK,TRUE},
356             {"[fedc:ba98:7654:3210:fedc:ba98:7654:3210]",S_OK,TRUE},
357             {"http://[fedc:ba98:7654:3210:fedc:ba98:7654:3210]/",S_OK,TRUE},
358             {"",S_FALSE,TRUE},
359             {"",S_FALSE,TRUE},
360             {"",S_FALSE,TRUE},
361             {"fedc:ba98:7654:3210:fedc:ba98:7654:3210",S_OK,TRUE},
362             {"",S_FALSE,FALSE},
363             {"/",S_OK,TRUE},
364             {"/",S_OK,TRUE},
365             {"",S_FALSE,TRUE},
366             {"http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]",S_OK,FALSE},
367             {"http",S_OK,FALSE},
368             {"",S_FALSE,FALSE},
369             {"",S_FALSE,FALSE}
370         },
371         {
372             {Uri_HOST_IPV6,S_OK,TRUE},
373             {80,S_OK,TRUE},
374             {URL_SCHEME_HTTP,S_OK,FALSE},
375             {URLZONE_INVALID,E_NOTIMPL,FALSE}
376         }
377     },
378     {   "ftp://[::13.1.68.3]", 0, S_OK, FALSE,
379         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
380         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
381         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
382         TRUE,
383         {
384             {"ftp://[::13.1.68.3]/",S_OK,TRUE},
385             {"[::13.1.68.3]",S_OK,TRUE},
386             {"ftp://[::13.1.68.3]/",S_OK,TRUE},
387             {"",S_FALSE,TRUE},
388             {"",S_FALSE,TRUE},
389             {"",S_FALSE,TRUE},
390             {"::13.1.68.3",S_OK,TRUE},
391             {"",S_FALSE,FALSE},
392             {"/",S_OK,TRUE},
393             {"/",S_OK,TRUE},
394             {"",S_FALSE,TRUE},
395             {"ftp://[::13.1.68.3]",S_OK,FALSE},
396             {"ftp",S_OK,FALSE},
397             {"",S_FALSE,FALSE},
398             {"",S_FALSE,FALSE}
399         },
400         {
401             {Uri_HOST_IPV6,S_OK,TRUE},
402             {21,S_OK,TRUE},
403             {URL_SCHEME_FTP,S_OK,FALSE},
404             {URLZONE_INVALID,E_NOTIMPL,FALSE}
405         }
406     },
407     {   "http://[FEDC:BA98:0:0:0:0:0:3210]", 0, S_OK, FALSE,
408         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
409         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
410         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
411         TRUE,
412         {
413             {"http://[fedc:ba98::3210]/",S_OK,TRUE},
414             {"[fedc:ba98::3210]",S_OK,TRUE},
415             {"http://[fedc:ba98::3210]/",S_OK,TRUE},
416             {"",S_FALSE,TRUE},
417             {"",S_FALSE,TRUE},
418             {"",S_FALSE,TRUE},
419             {"fedc:ba98::3210",S_OK,TRUE},
420             {"",S_FALSE,FALSE},
421             {"/",S_OK,TRUE},
422             {"/",S_OK,TRUE},
423             {"",S_FALSE,TRUE},
424             {"http://[FEDC:BA98:0:0:0:0:0:3210]",S_OK,FALSE},
425             {"http",S_OK,FALSE},
426             {"",S_FALSE,FALSE},
427             {"",S_FALSE,FALSE},
428         },
429         {
430             {Uri_HOST_IPV6,S_OK,TRUE},
431             {80,S_OK,TRUE},
432             {URL_SCHEME_HTTP,S_OK,FALSE},
433             {URLZONE_INVALID,E_NOTIMPL,FALSE}
434         }
435     },
436     {   "1234://www.winehq.org", 0, S_OK, FALSE,
437         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
438         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
439         Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
440         TRUE,
441         {
442             {"1234://www.winehq.org/",S_OK,TRUE},
443             {"www.winehq.org",S_OK,TRUE},
444             {"1234://www.winehq.org/",S_OK,TRUE},
445             {"winehq.org",S_OK,TRUE},
446             {"",S_FALSE,TRUE},
447             {"",S_FALSE,TRUE},
448             {"www.winehq.org",S_OK,TRUE},
449             {"",S_FALSE,FALSE},
450             {"/",S_OK,TRUE},
451             {"/",S_OK,TRUE},
452             {"",S_FALSE,TRUE},
453             {"1234://www.winehq.org",S_OK,FALSE},
454             {"1234",S_OK,FALSE},
455             {"",S_FALSE,FALSE},
456             {"",S_FALSE,FALSE}
457         },
458         {
459             {Uri_HOST_DNS,S_OK,TRUE},
460             {0,S_FALSE,TRUE},
461             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
462             {URLZONE_INVALID,E_NOTIMPL,FALSE}
463         }
464     },
465     {   "://www.winehq.org", 0, E_INVALIDARG, FALSE,
466         0, TRUE,
467         {
468             {"",S_FALSE,TRUE},
469             {"",S_FALSE,TRUE},
470             {"",S_FALSE,TRUE},
471             {"",S_FALSE,TRUE},
472             {"",S_FALSE,TRUE},
473             {"",S_FALSE,TRUE},
474             {"",S_FALSE,TRUE},
475             {"",S_FALSE,TRUE},
476             {"",S_FALSE,TRUE},
477             {"",S_FALSE,TRUE},
478             {"",S_FALSE,TRUE},
479             {"",S_FALSE,TRUE},
480             {"",S_FALSE,TRUE},
481             {"",S_FALSE,TRUE},
482             {"",S_FALSE,TRUE}
483         },
484         {
485             {Uri_HOST_UNKNOWN,S_FALSE,TRUE},
486             {0,S_FALSE,TRUE},
487             {URL_SCHEME_UNKNOWN,S_FALSE,FALSE},
488             {URLZONE_INVALID,E_NOTIMPL,FALSE}
489         }
490     },
491     /* Window's doesn't like URI's which are implicitly file paths without the ALLOW_IMPLICIT_FILE_SCHEME flag set. */
492     {   "C:/test/test.mp3", 0, E_INVALIDARG, FALSE,
493         0, TRUE,
494         {
495             {"",S_FALSE,FALSE},
496             {"",S_FALSE,FALSE},
497             {"",S_FALSE,FALSE},
498             {"",S_FALSE,FALSE},
499             {"",S_FALSE,FALSE},
500             {"",S_FALSE,FALSE},
501             {"",S_FALSE,FALSE},
502             {"",S_FALSE,FALSE},
503             {"",S_FALSE,FALSE},
504             {"",S_FALSE,FALSE},
505             {"",S_FALSE,FALSE},
506             {"",S_FALSE,FALSE},
507             {"",S_FALSE,FALSE},
508             {"",S_FALSE,FALSE},
509             {"",S_FALSE,FALSE}
510         },
511         {
512             {Uri_HOST_UNKNOWN,S_FALSE,FALSE},
513             {0,S_FALSE,FALSE},
514             {URL_SCHEME_INVALID,S_FALSE,FALSE},
515             {URLZONE_INVALID,E_NOTIMPL,FALSE}
516         }
517     },
518     /* Window's doesn't like URI's which are implicitly file paths without the ALLOW_IMPLICIT_FILE_SCHEME flag set. */
519     {   "\\\\Server/test/test.mp3", 0, E_INVALIDARG, FALSE,
520         0, TRUE,
521         {
522             {"",S_FALSE,FALSE},
523             {"",S_FALSE,FALSE},
524             {"",S_FALSE,FALSE},
525             {"",S_FALSE,FALSE},
526             {"",S_FALSE,FALSE},
527             {"",S_FALSE,FALSE},
528             {"",S_FALSE,FALSE},
529             {"",S_FALSE,FALSE},
530             {"",S_FALSE,FALSE},
531             {"",S_FALSE,FALSE},
532             {"",S_FALSE,FALSE},
533             {"",S_FALSE,FALSE},
534             {"",S_FALSE,FALSE},
535             {"",S_FALSE,FALSE},
536             {"",S_FALSE,FALSE}
537         },
538         {
539             {Uri_HOST_UNKNOWN,S_FALSE,FALSE},
540             {0,S_FALSE,FALSE},
541             {URL_SCHEME_INVALID,S_FALSE,FALSE},
542             {URLZONE_INVALID,E_NOTIMPL,FALSE}
543         }
544     },
545     /* Window's doesn't like URI's which are implicitly file paths without the ALLOW_IMPLICIT_FILE_SCHEME flag set. */
546     {   "\\\\Server/test/test.mp3", Uri_CREATE_ALLOW_RELATIVE, E_INVALIDARG, FALSE,
547         0, TRUE,
548         {
549             {"",S_FALSE,FALSE},
550             {"",S_FALSE,FALSE},
551             {"",S_FALSE,FALSE},
552             {"",S_FALSE,FALSE},
553             {"",S_FALSE,FALSE},
554             {"",S_FALSE,FALSE},
555             {"",S_FALSE,FALSE},
556             {"",S_FALSE,FALSE},
557             {"",S_FALSE,FALSE},
558             {"",S_FALSE,FALSE},
559             {"",S_FALSE,FALSE},
560             {"",S_FALSE,FALSE},
561             {"",S_FALSE,FALSE},
562             {"",S_FALSE,FALSE},
563             {"",S_FALSE,FALSE}
564         },
565         {
566             {Uri_HOST_UNKNOWN,S_FALSE,FALSE},
567             {0,S_FALSE,FALSE},
568             {URL_SCHEME_INVALID,S_FALSE,FALSE},
569             {URLZONE_INVALID,E_NOTIMPL,FALSE}
570         }
571     },
572     /* Window's doesn't like URI's which are implicitly file paths without the ALLOW_IMPLICIT_FILE_SCHEME flag set. */
573     {   "C:/test/test.mp3", Uri_CREATE_ALLOW_IMPLICIT_WILDCARD_SCHEME, E_INVALIDARG, FALSE,
574         0, TRUE,
575         {
576             {"",S_FALSE,FALSE},
577             {"",S_FALSE,FALSE},
578             {"",S_FALSE,FALSE},
579             {"",S_FALSE,FALSE},
580             {"",S_FALSE,FALSE},
581             {"",S_FALSE,FALSE},
582             {"",S_FALSE,FALSE},
583             {"",S_FALSE,FALSE},
584             {"",S_FALSE,FALSE},
585             {"",S_FALSE,FALSE},
586             {"",S_FALSE,FALSE},
587             {"",S_FALSE,FALSE},
588             {"",S_FALSE,FALSE},
589             {"",S_FALSE,FALSE},
590             {"",S_FALSE,FALSE}
591         },
592         {
593             {Uri_HOST_UNKNOWN,S_FALSE,FALSE},
594             {0,S_FALSE,FALSE},
595             {URL_SCHEME_INVALID,S_FALSE,FALSE},
596             {URLZONE_INVALID,E_NOTIMPL,FALSE}
597         }
598     },
599     /* Test's to make sure the parser/canonicalizer handles implicit file schemes correctly. */
600     {   "C:/test/test.mp3", Uri_CREATE_ALLOW_IMPLICIT_FILE_SCHEME, S_OK, FALSE,
601         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH|
602         Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
603         TRUE,
604         {
605             {"file:///C:/test/test.mp3",S_OK,TRUE},
606             {"",S_FALSE,TRUE},
607             {"file:///C:/test/test.mp3",S_OK,TRUE},
608             {"",S_FALSE,TRUE},
609             {".mp3",S_OK,TRUE},
610             {"",S_FALSE,TRUE},
611             {"",S_FALSE,TRUE},
612             {"",S_FALSE,FALSE},
613             {"/C:/test/test.mp3",S_OK,TRUE},
614             {"/C:/test/test.mp3",S_OK,TRUE},
615             {"",S_FALSE,TRUE},
616             {"C:/test/test.mp3",S_OK,FALSE},
617             {"file",S_OK,FALSE},
618             {"",S_FALSE,FALSE},
619             {"",S_FALSE,FALSE}
620         },
621         {
622             {Uri_HOST_UNKNOWN,S_OK,TRUE},
623             {0,S_FALSE,TRUE},
624             {URL_SCHEME_FILE,S_OK,FALSE},
625             {URLZONE_INVALID,E_NOTIMPL,FALSE}
626         }
627     },
628     /* Test's to make sure the parser/canonicalizer handles implicit file schemes correctly. */
629     {   "\\\\Server/test.mp3", Uri_CREATE_ALLOW_IMPLICIT_FILE_SCHEME, S_OK, FALSE,
630         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|
631         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_HOST|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
632         Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
633         TRUE,
634         {
635             {"file://server/test.mp3",S_OK,TRUE},
636             {"server",S_OK,TRUE},
637             {"file://server/test.mp3",S_OK,TRUE},
638             {"",S_FALSE,TRUE},
639             {".mp3",S_OK,TRUE},
640             {"",S_FALSE,TRUE},
641             {"server",S_OK,TRUE},
642             {"",S_FALSE,FALSE},
643             {"/test.mp3",S_OK,TRUE},
644             {"/test.mp3",S_OK,TRUE},
645             {"",S_FALSE,TRUE},
646             {"\\\\Server/test.mp3",S_OK,FALSE},
647             {"file",S_OK,FALSE},
648             {"",S_FALSE,FALSE},
649             {"",S_FALSE,FALSE}
650         },
651         {
652             {Uri_HOST_DNS,S_OK,TRUE},
653             {0,S_FALSE,TRUE},
654             {URL_SCHEME_FILE,S_OK,FALSE},
655             {URLZONE_INVALID,E_NOTIMPL,FALSE}
656         }
657     },
658     {   "www.winehq.org/test", Uri_CREATE_ALLOW_IMPLICIT_WILDCARD_SCHEME, S_OK, FALSE,
659         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_HOST|
660         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|
661         Uri_HAS_SCHEME,
662         TRUE,
663         {
664             {"*:www.winehq.org/test",S_OK,TRUE},
665             {"www.winehq.org",S_OK,TRUE},
666             {"*:www.winehq.org/test",S_OK,TRUE},
667             {"winehq.org",S_OK,TRUE},
668             {"",S_FALSE,TRUE},
669             {"",S_FALSE,TRUE},
670             {"www.winehq.org",S_OK,TRUE},
671             {"",S_FALSE,FALSE},
672             {"/test",S_OK,TRUE},
673             {"/test",S_OK,TRUE},
674             {"",S_FALSE,TRUE},
675             {"www.winehq.org/test",S_OK,FALSE},
676             {"*",S_OK,FALSE},
677             {"",S_FALSE,FALSE},
678             {"",S_FALSE,FALSE}
679         },
680         {
681             {Uri_HOST_DNS,S_OK,TRUE},
682             {0,S_FALSE,TRUE},
683             {URL_SCHEME_WILDCARD,S_OK,FALSE},
684             {URLZONE_INVALID,E_NOTIMPL,FALSE}
685         }
686     },
687     /* Valid since the '*' is the only character in the scheme name. */
688     {   "*:www.winehq.org/test", 0, S_OK, FALSE,
689         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_HOST|
690         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|
691         Uri_HAS_SCHEME,
692         TRUE,
693         {
694             {"*:www.winehq.org/test",S_OK,TRUE},
695             {"www.winehq.org",S_OK,TRUE},
696             {"*:www.winehq.org/test",S_OK,TRUE},
697             {"winehq.org",S_OK,TRUE},
698             {"",S_FALSE,TRUE},
699             {"",S_FALSE,TRUE},
700             {"www.winehq.org",S_OK,TRUE},
701             {"",S_FALSE,FALSE},
702             {"/test",S_OK,TRUE},
703             {"/test",S_OK,TRUE},
704             {"",S_FALSE,TRUE},
705             {"*:www.winehq.org/test",S_OK,FALSE},
706             {"*",S_OK,FALSE},
707             {"",S_FALSE,FALSE},
708             {"",S_FALSE,FALSE}
709         },
710         {
711             {Uri_HOST_DNS,S_OK,TRUE},
712             {0,S_FALSE,TRUE},
713             {URL_SCHEME_WILDCARD,S_OK,FALSE},
714             {URLZONE_INVALID,E_NOTIMPL,FALSE}
715         }
716     },
717     /* Not valid since a '*' is only allowed to appear if its the only character in scheme. */
718     {   "*abcd://not.valid.com", 0, E_INVALIDARG, FALSE,
719         0, TRUE,
720         {
721             {"",S_FALSE,FALSE},
722             {"",S_FALSE,FALSE},
723             {"",S_FALSE,FALSE},
724             {"",S_FALSE,FALSE},
725             {"",S_FALSE,FALSE},
726             {"",S_FALSE,FALSE},
727             {"",S_FALSE,FALSE},
728             {"",S_FALSE,FALSE},
729             {"",S_FALSE,FALSE},
730             {"",S_FALSE,FALSE},
731             {"",S_FALSE,FALSE},
732             {"",S_FALSE,FALSE},
733             {"",S_FALSE,FALSE},
734             {"",S_FALSE,FALSE},
735             {"",S_FALSE,FALSE}
736         },
737         {
738             {Uri_HOST_UNKNOWN,S_FALSE,FALSE},
739             {0,S_FALSE,FALSE},
740             {URL_SCHEME_INVALID,S_FALSE,FALSE},
741             {URLZONE_INVALID,E_NOTIMPL,FALSE}
742         }
743     },
744     /* Not valid since a '*' is only allowed to appear if its the only character in scheme. */
745     {   "*a*b*c*d://not.valid.com", 0, E_INVALIDARG, FALSE,
746         0, TRUE,
747         {
748             {"",S_FALSE,FALSE},
749             {"",S_FALSE,FALSE},
750             {"",S_FALSE,FALSE},
751             {"",S_FALSE,FALSE},
752             {"",S_FALSE,FALSE},
753             {"",S_FALSE,FALSE},
754             {"",S_FALSE,FALSE},
755             {"",S_FALSE,FALSE},
756             {"",S_FALSE,FALSE},
757             {"",S_FALSE,FALSE},
758             {"",S_FALSE,FALSE},
759             {"",S_FALSE,FALSE},
760             {"",S_FALSE,FALSE},
761             {"",S_FALSE,FALSE},
762             {"",S_FALSE,FALSE}
763         },
764         {
765             {Uri_HOST_UNKNOWN,S_FALSE,FALSE},
766             {0,S_FALSE,FALSE},
767             {URL_SCHEME_INVALID,S_FALSE,FALSE},
768             {URLZONE_INVALID,E_NOTIMPL,FALSE}
769         }
770     },
771     {   "/../some dir/test.ext", Uri_CREATE_ALLOW_RELATIVE, S_OK, FALSE,
772         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH|
773         Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
774         TRUE,
775         {
776             {"/../some dir/test.ext",S_OK,TRUE},
777             {"",S_FALSE,TRUE},
778             {"/../some dir/test.ext",S_OK,TRUE},
779             {"",S_FALSE,TRUE},
780             {".ext",S_OK,TRUE},
781             {"",S_FALSE,TRUE},
782             {"",S_FALSE,TRUE},
783             {"",S_FALSE,FALSE},
784             {"/../some dir/test.ext",S_OK,TRUE},
785             {"/../some dir/test.ext",S_OK,TRUE},
786             {"",S_FALSE,TRUE},
787             {"/../some dir/test.ext",S_OK,FALSE},
788             {"",S_FALSE,FALSE},
789             {"",S_FALSE,FALSE},
790             {"",S_FALSE,FALSE}
791         },
792         {
793             {Uri_HOST_UNKNOWN,S_OK,TRUE},
794             {0,S_FALSE,TRUE},
795             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
796             {URLZONE_INVALID,E_NOTIMPL,FALSE}
797         }
798     },
799     {   "//implicit/wildcard/uri scheme", Uri_CREATE_ALLOW_RELATIVE|Uri_CREATE_ALLOW_IMPLICIT_WILDCARD_SCHEME, S_OK, FALSE,
800         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|Uri_HAS_PATH|
801         Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
802         TRUE,
803         {
804             {"*://implicit/wildcard/uri%20scheme",S_OK,TRUE},
805             {"",S_OK,TRUE},
806             {"*://implicit/wildcard/uri%20scheme",S_OK,TRUE},
807             {"",S_FALSE,TRUE},
808             {"",S_FALSE,TRUE},
809             {"",S_FALSE,TRUE},
810             {"",S_OK,TRUE},
811             {"",S_FALSE,FALSE},
812             {"//implicit/wildcard/uri%20scheme",S_OK,TRUE},
813             {"//implicit/wildcard/uri%20scheme",S_OK,TRUE},
814             {"",S_FALSE,TRUE},
815             {"//implicit/wildcard/uri scheme",S_OK,FALSE},
816             {"*",S_OK,FALSE},
817             {"",S_FALSE,FALSE},
818             {"",S_FALSE,FALSE},
819         },
820         {
821             {Uri_HOST_UNKNOWN,S_OK,TRUE},
822             {0,S_FALSE,TRUE},
823             {URL_SCHEME_WILDCARD,S_OK,FALSE},
824             {URLZONE_INVALID,E_NOTIMPL,FALSE}
825         }
826     },
827     /* URI is considered opaque since CREATE_NO_CRACK_UNKNOWN_SCHEMES is set and its an unknown scheme. */
828     {   "zip://google.com", Uri_CREATE_NO_CRACK_UNKNOWN_SCHEMES, S_OK, FALSE,
829         Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH|
830         Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME_NAME|
831         Uri_HAS_SCHEME,
832         TRUE,
833         {
834             {"zip:/.//google.com",S_OK,TRUE},
835             {"",S_FALSE,TRUE},
836             {"zip:/.//google.com",S_OK,TRUE},
837             {"",S_FALSE,TRUE},
838             {".com",S_OK,TRUE},
839             {"",S_FALSE,TRUE},
840             {"",S_FALSE,TRUE},
841             {"",S_FALSE,FALSE},
842             {"/.//google.com",S_OK,TRUE},
843             {"/.//google.com",S_OK,TRUE},
844             {"",S_FALSE,TRUE},
845             {"zip://google.com",S_OK,FALSE},
846             {"zip",S_OK,FALSE},
847             {"",S_FALSE,FALSE},
848             {"",S_FALSE,FALSE}
849         },
850         {
851             {Uri_HOST_UNKNOWN,S_OK,TRUE},
852             {0,S_FALSE,TRUE},
853             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
854             {URLZONE_INVALID,E_NOTIMPL,FALSE}
855         }
856     },
857     /* Windows uses the first occurence of ':' to delimit the userinfo. */
858     {   "ftp://user:pass:word@winehq.org/", 0, S_OK, FALSE,
859         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
860         Uri_HAS_HOST|Uri_HAS_PASSWORD|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
861         Uri_HAS_SCHEME_NAME|Uri_HAS_USER_INFO|Uri_HAS_USER_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|
862         Uri_HAS_SCHEME,
863         TRUE,
864         {
865             {"ftp://user:pass:word@winehq.org/",S_OK,TRUE},
866             {"user:pass:word@winehq.org",S_OK,TRUE},
867             {"ftp://winehq.org/",S_OK,TRUE},
868             {"winehq.org",S_OK,TRUE},
869             {"",S_FALSE,TRUE},
870             {"",S_FALSE,TRUE},
871             {"winehq.org",S_OK,TRUE},
872             {"pass:word",S_OK,FALSE},
873             {"/",S_OK,TRUE},
874             {"/",S_OK,TRUE},
875             {"",S_FALSE,TRUE},
876             {"ftp://user:pass:word@winehq.org/",S_OK,FALSE},
877             {"ftp",S_OK,FALSE},
878             {"user:pass:word",S_OK,FALSE},
879             {"user",S_OK,FALSE}
880         },
881         {
882             {Uri_HOST_DNS,S_OK,TRUE},
883             {21,S_OK,TRUE},
884             {URL_SCHEME_FTP,S_OK,FALSE},
885             {URLZONE_INVALID,E_NOTIMPL,FALSE}
886         }
887     },
888     /* Make sure % encoded unreserved characters are decoded. */
889     {   "ftp://w%49%4Ee:PA%53%53@ftp.google.com/", 0, S_OK, FALSE,
890         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
891         Uri_HAS_HOST|Uri_HAS_PASSWORD|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
892         Uri_HAS_SCHEME_NAME|Uri_HAS_USER_INFO|Uri_HAS_USER_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|
893         Uri_HAS_SCHEME,
894         TRUE,
895         {
896             {"ftp://wINe:PASS@ftp.google.com/",S_OK,TRUE},
897             {"wINe:PASS@ftp.google.com",S_OK,TRUE},
898             {"ftp://ftp.google.com/",S_OK,TRUE},
899             {"google.com",S_OK,TRUE},
900             {"",S_FALSE,TRUE},
901             {"",S_FALSE,TRUE},
902             {"ftp.google.com",S_OK,TRUE},
903             {"PASS",S_OK,FALSE},
904             {"/",S_OK,TRUE},
905             {"/",S_OK,TRUE},
906             {"",S_FALSE,TRUE},
907             {"ftp://w%49%4Ee:PA%53%53@ftp.google.com/",S_OK,FALSE},
908             {"ftp",S_OK,FALSE},
909             {"wINe:PASS",S_OK,FALSE},
910             {"wINe",S_OK,FALSE}
911         },
912         {
913             {Uri_HOST_DNS,S_OK,TRUE},
914             {21,S_OK,TRUE},
915             {URL_SCHEME_FTP,S_OK,FALSE},
916             {URLZONE_INVALID,E_NOTIMPL,FALSE}
917         }
918     },
919     /* Make sure % encoded characters which are NOT unreserved are NOT decoded. */
920     {   "ftp://w%5D%5Be:PA%7B%7D@ftp.google.com/", 0, S_OK, FALSE,
921         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
922         Uri_HAS_HOST|Uri_HAS_PASSWORD|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
923         Uri_HAS_SCHEME_NAME|Uri_HAS_USER_INFO|Uri_HAS_USER_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|
924         Uri_HAS_SCHEME,
925         TRUE,
926         {
927             {"ftp://w%5D%5Be:PA%7B%7D@ftp.google.com/",S_OK,TRUE},
928             {"w%5D%5Be:PA%7B%7D@ftp.google.com",S_OK,TRUE},
929             {"ftp://ftp.google.com/",S_OK,TRUE},
930             {"google.com",S_OK,TRUE},
931             {"",S_FALSE,TRUE},
932             {"",S_FALSE,TRUE},
933             {"ftp.google.com",S_OK,TRUE},
934             {"PA%7B%7D",S_OK,FALSE},
935             {"/",S_OK,TRUE},
936             {"/",S_OK,TRUE},
937             {"",S_FALSE,TRUE},
938             {"ftp://w%5D%5Be:PA%7B%7D@ftp.google.com/",S_OK,FALSE},
939             {"ftp",S_OK,FALSE},
940             {"w%5D%5Be:PA%7B%7D",S_OK,FALSE},
941             {"w%5D%5Be",S_OK,FALSE}
942         },
943         {
944             {Uri_HOST_DNS,S_OK,TRUE},
945             {21,S_OK,TRUE},
946             {URL_SCHEME_FTP,S_OK,FALSE},
947             {URLZONE_INVALID,E_NOTIMPL,FALSE}
948         }
949     },
950     /* You're allowed to have an empty password portion in the userinfo section. */
951     {   "ftp://empty:@ftp.google.com/", 0, S_OK, FALSE,
952         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
953         Uri_HAS_HOST|Uri_HAS_PASSWORD|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
954         Uri_HAS_SCHEME_NAME|Uri_HAS_USER_INFO|Uri_HAS_USER_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|
955         Uri_HAS_SCHEME,
956         TRUE,
957         {
958             {"ftp://empty:@ftp.google.com/",S_OK,TRUE},
959             {"empty:@ftp.google.com",S_OK,TRUE},
960             {"ftp://ftp.google.com/",S_OK,TRUE},
961             {"google.com",S_OK,TRUE},
962             {"",S_FALSE,TRUE},
963             {"",S_FALSE,TRUE},
964             {"ftp.google.com",S_OK,TRUE},
965             {"",S_OK,FALSE},
966             {"/",S_OK,TRUE},
967             {"/",S_OK,TRUE},
968             {"",S_FALSE,TRUE},
969             {"ftp://empty:@ftp.google.com/",S_OK,FALSE},
970             {"ftp",S_OK,FALSE},
971             {"empty:",S_OK,FALSE},
972             {"empty",S_OK,FALSE}
973         },
974         {
975             {Uri_HOST_DNS,S_OK,TRUE},
976             {21,S_OK,TRUE},
977             {URL_SCHEME_FTP,S_OK,FALSE},
978             {URLZONE_INVALID,E_NOTIMPL,FALSE}
979         }
980     },
981     /* Make sure forbidden characters in "userinfo" get encoded. */
982     {   "ftp://\" \"weird@ftp.google.com/", 0, S_OK, FALSE,
983         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
984         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
985         Uri_HAS_SCHEME_NAME|Uri_HAS_USER_INFO|Uri_HAS_USER_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|
986         Uri_HAS_SCHEME,
987         TRUE,
988         {
989             {"ftp://%22%20%22weird@ftp.google.com/",S_OK,TRUE},
990             {"%22%20%22weird@ftp.google.com",S_OK,TRUE},
991             {"ftp://ftp.google.com/",S_OK,TRUE},
992             {"google.com",S_OK,TRUE},
993             {"",S_FALSE,TRUE},
994             {"",S_FALSE,TRUE},
995             {"ftp.google.com",S_OK,TRUE},
996             {"",S_FALSE,FALSE},
997             {"/",S_OK,TRUE},
998             {"/",S_OK,TRUE},
999             {"",S_FALSE,TRUE},
1000             {"ftp://\" \"weird@ftp.google.com/",S_OK,FALSE},
1001             {"ftp",S_OK,FALSE},
1002             {"%22%20%22weird",S_OK,FALSE},
1003             {"%22%20%22weird",S_OK,FALSE}
1004         },
1005         {
1006             {Uri_HOST_DNS,S_OK,TRUE},
1007             {21,S_OK,TRUE},
1008             {URL_SCHEME_FTP,S_OK,FALSE},
1009             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1010         }
1011     },
1012     /* Make sure the forbidden characters don't get percent encoded. */
1013     {   "ftp://\" \"weird@ftp.google.com/", Uri_CREATE_NO_ENCODE_FORBIDDEN_CHARACTERS, S_OK, FALSE,
1014         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
1015         Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
1016         Uri_HAS_SCHEME_NAME|Uri_HAS_USER_INFO|Uri_HAS_USER_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|
1017         Uri_HAS_SCHEME,
1018         TRUE,
1019         {
1020             {"ftp://\" \"weird@ftp.google.com/",S_OK,TRUE},
1021             {"\" \"weird@ftp.google.com",S_OK,TRUE},
1022             {"ftp://ftp.google.com/",S_OK,TRUE},
1023             {"google.com",S_OK,TRUE},
1024             {"",S_FALSE,TRUE},
1025             {"",S_FALSE,TRUE},
1026             {"ftp.google.com",S_OK,TRUE},
1027             {"",S_FALSE,FALSE},
1028             {"/",S_OK,TRUE},
1029             {"/",S_OK,TRUE},
1030             {"",S_FALSE,TRUE},
1031             {"ftp://\" \"weird@ftp.google.com/",S_OK,FALSE},
1032             {"ftp",S_OK,FALSE},
1033             {"\" \"weird",S_OK,FALSE},
1034             {"\" \"weird",S_OK,FALSE}
1035         },
1036         {
1037             {Uri_HOST_DNS,S_OK,TRUE},
1038             {21,S_OK,TRUE},
1039             {URL_SCHEME_FTP,S_OK,FALSE},
1040             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1041         }
1042     },
1043     /* Allowed to have invalid % encoded because its an unknown scheme type. */
1044     {   "zip://%xy:word@winehq.org/", 0, S_OK, FALSE,
1045         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
1046         Uri_HAS_HOST|Uri_HAS_PASSWORD|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
1047         Uri_HAS_SCHEME_NAME|Uri_HAS_USER_INFO|Uri_HAS_USER_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
1048         TRUE,
1049         {
1050             {"zip://%xy:word@winehq.org/",S_OK,TRUE},
1051             {"%xy:word@winehq.org",S_OK,TRUE},
1052             {"zip://%xy:word@winehq.org/",S_OK,TRUE},
1053             {"winehq.org",S_OK,TRUE},
1054             {"",S_FALSE,TRUE},
1055             {"",S_FALSE,TRUE},
1056             {"winehq.org",S_OK,TRUE},
1057             {"word",S_OK,FALSE},
1058             {"/",S_OK,TRUE},
1059             {"/",S_OK,TRUE},
1060             {"",S_FALSE,TRUE},
1061             {"zip://%xy:word@winehq.org/",S_OK,FALSE},
1062             {"zip",S_OK,FALSE},
1063             {"%xy:word",S_OK,FALSE},
1064             {"%xy",S_OK,FALSE}
1065         },
1066         {
1067             {Uri_HOST_DNS,S_OK,TRUE},
1068             {0,S_FALSE,TRUE},
1069             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1070             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1071         }
1072     },
1073     /* Unreserved, percent encoded characters aren't decoded in the userinfo becuase the scheme
1074      * isn't known.
1075      */
1076     {   "zip://%2E:%52%53ord@winehq.org/", 0, S_OK, FALSE,
1077         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
1078         Uri_HAS_HOST|Uri_HAS_PASSWORD|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
1079         Uri_HAS_SCHEME_NAME|Uri_HAS_USER_INFO|Uri_HAS_USER_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
1080         TRUE,
1081         {
1082             {"zip://%2E:%52%53ord@winehq.org/",S_OK,TRUE},
1083             {"%2E:%52%53ord@winehq.org",S_OK,TRUE},
1084             {"zip://%2E:%52%53ord@winehq.org/",S_OK,TRUE},
1085             {"winehq.org",S_OK,TRUE},
1086             {"",S_FALSE,TRUE},
1087             {"",S_FALSE,TRUE},
1088             {"winehq.org",S_OK,TRUE},
1089             {"%52%53ord",S_OK,FALSE},
1090             {"/",S_OK,TRUE},
1091             {"/",S_OK,TRUE},
1092             {"",S_FALSE,TRUE},
1093             {"zip://%2E:%52%53ord@winehq.org/",S_OK,FALSE},
1094             {"zip",S_OK,FALSE},
1095             {"%2E:%52%53ord",S_OK,FALSE},
1096             {"%2E",S_OK,FALSE}
1097         },
1098         {
1099             {Uri_HOST_DNS,S_OK,TRUE},
1100             {0,S_FALSE,TRUE},
1101             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1102             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1103         }
1104     },
1105     {   "ftp://[](),'test':word@winehq.org/", 0, S_OK, FALSE,
1106         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|
1107         Uri_HAS_HOST|Uri_HAS_PASSWORD|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|
1108         Uri_HAS_SCHEME_NAME|Uri_HAS_USER_INFO|Uri_HAS_USER_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_PORT|
1109         Uri_HAS_SCHEME,
1110         TRUE,
1111         {
1112             {"ftp://[](),'test':word@winehq.org/",S_OK,TRUE},
1113             {"[](),'test':word@winehq.org",S_OK,TRUE},
1114             {"ftp://winehq.org/",S_OK,TRUE},
1115             {"winehq.org",S_OK,TRUE},
1116             {"",S_FALSE,TRUE},
1117             {"",S_FALSE,TRUE},
1118             {"winehq.org",S_OK,TRUE},
1119             {"word",S_OK,FALSE},
1120             {"/",S_OK,TRUE},
1121             {"/",S_OK,TRUE},
1122             {"",S_FALSE,TRUE},
1123             {"ftp://[](),'test':word@winehq.org/",S_OK,FALSE},
1124             {"ftp",S_OK,FALSE},
1125             {"[](),'test':word",S_OK,FALSE},
1126             {"[](),'test'",S_OK,FALSE}
1127         },
1128         {
1129             {Uri_HOST_DNS,S_OK,TRUE},
1130             {21,S_OK,TRUE},
1131             {URL_SCHEME_FTP,S_OK,FALSE},
1132             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1133         }
1134     },
1135     {   "ftp://test?:word@winehq.org/", 0, S_OK, FALSE,
1136         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_HOST|
1137         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1138         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1139         TRUE,
1140         {
1141             {"ftp://test/?:word@winehq.org/",S_OK,TRUE},
1142             {"test",S_OK,TRUE},
1143             {"ftp://test/?:word@winehq.org/",S_OK,TRUE},
1144             {"",S_FALSE,TRUE},
1145             {"",S_FALSE,TRUE},
1146             {"",S_FALSE,TRUE},
1147             {"test",S_OK,TRUE},
1148             {"",S_FALSE,FALSE},
1149             {"/",S_OK,TRUE},
1150             {"/?:word@winehq.org/",S_OK,TRUE},
1151             {"?:word@winehq.org/",S_OK,TRUE},
1152             {"ftp://test?:word@winehq.org/",S_OK,FALSE},
1153             {"ftp",S_OK,FALSE},
1154             {"",S_FALSE,FALSE},
1155             {"",S_FALSE,FALSE}
1156         },
1157         {
1158             {Uri_HOST_DNS,S_OK,TRUE},
1159             {21,S_OK,TRUE},
1160             {URL_SCHEME_FTP,S_OK,FALSE},
1161             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1162         }
1163     },
1164     {   "ftp://test#:word@winehq.org/", 0, S_OK, FALSE,
1165         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_FRAGMENT|Uri_HAS_HOST|
1166         Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1167         Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME,
1168         TRUE,
1169         {
1170             {"ftp://test/#:word@winehq.org/",S_OK,TRUE},
1171             {"test",S_OK,TRUE},
1172             {"ftp://test/#:word@winehq.org/",S_OK,TRUE},
1173             {"",S_FALSE,TRUE},
1174             {"",S_FALSE,TRUE},
1175             {"#:word@winehq.org/",S_OK,TRUE},
1176             {"test",S_OK,TRUE},
1177             {"",S_FALSE,FALSE},
1178             {"/",S_OK,TRUE},
1179             {"/",S_OK,TRUE},
1180             {"",S_FALSE,TRUE},
1181             {"ftp://test#:word@winehq.org/",S_OK,FALSE},
1182             {"ftp",S_OK,FALSE},
1183             {"",S_FALSE,FALSE},
1184             {"",S_FALSE,FALSE}
1185         },
1186         {
1187             {Uri_HOST_DNS,S_OK,TRUE},
1188             {21,S_OK,TRUE},
1189             {URL_SCHEME_FTP,S_OK,FALSE},
1190             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1191         }
1192     },
1193     /* Allowed to have a backslash in the userinfo since it's an unknown scheme. */
1194     {   "zip://test\\:word@winehq.org/", 0, S_OK, FALSE,
1195         Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN|Uri_HAS_HOST|
1196         Uri_HAS_PASSWORD|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|
1197         Uri_HAS_USER_INFO|Uri_HAS_USER_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME,
1198         TRUE,
1199         {
1200             {"zip://test\\:word@winehq.org/",S_OK,TRUE},
1201             {"test\\:word@winehq.org",S_OK,TRUE},
1202             {"zip://test\\:word@winehq.org/",S_OK,TRUE},
1203             {"winehq.org",S_OK,TRUE},
1204             {"",S_FALSE,TRUE},
1205             {"",S_FALSE,TRUE},
1206             {"winehq.org",S_OK,TRUE},
1207             {"word",S_OK,FALSE},
1208             {"/",S_OK,TRUE},
1209             {"/",S_OK,TRUE},
1210             {"",S_FALSE,TRUE},
1211             {"zip://test\\:word@winehq.org/",S_OK,FALSE},
1212             {"zip",S_OK,FALSE},
1213             {"test\\:word",S_OK,FALSE},
1214             {"test\\",S_OK,FALSE}
1215         },
1216         {
1217             {Uri_HOST_DNS,S_OK,TRUE},
1218             {0,S_FALSE,TRUE},
1219             {URL_SCHEME_UNKNOWN,S_OK,FALSE},
1220             {URLZONE_INVALID,E_NOTIMPL,FALSE}
1221         }
1222     }
1223 };
1224
1225 typedef struct _uri_equality {
1226     const char* a;
1227     DWORD       create_flags_a;
1228     BOOL        create_todo_a;
1229     const char* b;
1230     DWORD       create_flags_b;
1231     BOOL        create_todo_b;
1232     BOOL        equal;
1233     BOOL        todo;
1234 } uri_equality;
1235
1236 static const uri_equality equality_tests[] = {
1237     {
1238         "HTTP://www.winehq.org/test dir/./",0,FALSE,
1239         "http://www.winehq.org/test dir/../test dir/",0,FALSE,
1240         TRUE, TRUE
1241     },
1242     {
1243         /* http://www.winehq.org/test%20dir */
1244         "http://%77%77%77%2E%77%69%6E%65%68%71%2E%6F%72%67/%74%65%73%74%20%64%69%72",0,FALSE,
1245         "http://www.winehq.org/test dir",0,FALSE,
1246         TRUE, TRUE,
1247     },
1248     {
1249         "c:\\test.mp3",Uri_CREATE_ALLOW_IMPLICIT_FILE_SCHEME,FALSE,
1250         "file:///c:/test.mp3",0,FALSE,
1251         TRUE,TRUE
1252     },
1253     {
1254         "ftp://ftp.winehq.org/",0,FALSE,
1255         "ftp://ftp.winehq.org",0,FALSE,
1256         TRUE, TRUE
1257     },
1258     {
1259         "ftp://ftp.winehq.org/test/test2/../../testB/",0,FALSE,
1260         "ftp://ftp.winehq.org/t%45stB/",0,FALSE,
1261         FALSE, TRUE
1262     }
1263 };
1264
1265 static inline LPWSTR a2w(LPCSTR str) {
1266     LPWSTR ret = NULL;
1267
1268     if(str) {
1269         DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
1270         ret = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
1271         MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len);
1272     }
1273
1274     return ret;
1275 }
1276
1277 static inline BOOL heap_free(void* mem) {
1278     return HeapFree(GetProcessHeap(), 0, mem);
1279 }
1280
1281 static inline DWORD strcmp_aw(LPCSTR strA, LPCWSTR strB) {
1282     LPWSTR strAW = a2w(strA);
1283     DWORD ret = lstrcmpW(strAW, strB);
1284     heap_free(strAW);
1285     return ret;
1286 }
1287
1288 /*
1289  * Simple tests to make sure the CreateUri function handles invalid flag combinations
1290  * correctly.
1291  */
1292 static void test_CreateUri_InvalidFlags(void) {
1293     DWORD i;
1294
1295     for(i = 0; i < sizeof(invalid_flag_tests)/sizeof(invalid_flag_tests[0]); ++i) {
1296         HRESULT hr;
1297         IUri *uri = (void*) 0xdeadbeef;
1298
1299         hr = pCreateUri(http_urlW, invalid_flag_tests[i].flags, 0, &uri);
1300         todo_wine {
1301             ok(hr == invalid_flag_tests[i].expected, "Error: CreateUri returned 0x%08x, expected 0x%08x, flags=0x%08x\n",
1302                     hr, invalid_flag_tests[i].expected, invalid_flag_tests[i].flags);
1303         }
1304         todo_wine { ok(uri == NULL, "Error: expected the IUri to be NULL, but it was %p instead\n", uri); }
1305     }
1306 }
1307
1308 static void test_CreateUri_InvalidArgs(void) {
1309     HRESULT hr;
1310     IUri *uri = (void*) 0xdeadbeef;
1311
1312     const WCHAR invalidW[] = {'i','n','v','a','l','i','d',0};
1313
1314     hr = pCreateUri(http_urlW, 0, 0, NULL);
1315     ok(hr == E_INVALIDARG, "Error: CreateUri returned 0x%08x, expected 0x%08x\n", hr, E_INVALIDARG);
1316
1317     hr = pCreateUri(NULL, 0, 0, &uri);
1318     ok(hr == E_INVALIDARG, "Error: CreateUri returned 0x%08x, expected 0x%08x\n", hr, E_INVALIDARG);
1319     ok(uri == NULL, "Error: Expected the IUri to be NULL, but it was %p instead\n", uri);
1320
1321     uri = (void*) 0xdeadbeef;
1322     hr = pCreateUri(invalidW, 0, 0, &uri);
1323     ok(hr == E_INVALIDARG, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
1324     ok(uri == NULL, "Error: Expected the IUri to be NULL, but it was %p instead\n", uri);
1325 }
1326
1327 static void test_IUri_GetPropertyBSTR(void) {
1328     IUri *uri = NULL;
1329     HRESULT hr;
1330     DWORD i;
1331
1332     /* Make sure GetPropertyBSTR handles invalid args correctly. */
1333     hr = pCreateUri(http_urlW, 0, 0, &uri);
1334     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
1335     if(SUCCEEDED(hr)) {
1336         BSTR received = NULL;
1337
1338         hr = IUri_GetPropertyBSTR(uri, Uri_PROPERTY_RAW_URI, NULL, 0);
1339         ok(hr == E_POINTER, "Error: GetPropertyBSTR returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
1340
1341         /* Make sure it handles a invalid Uri_PROPERTY's correctly. */
1342         hr = IUri_GetPropertyBSTR(uri, Uri_PROPERTY_PORT, &received, 0);
1343         ok(hr == S_OK, "Error: GetPropertyBSTR returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
1344         ok(received != NULL, "Error: Expected the string not to be NULL.\n");
1345         ok(!SysStringLen(received), "Error: Expected the string to be of len=0 but it was %d instead.\n", SysStringLen(received));
1346         SysFreeString(received);
1347
1348         /* Make sure it handles the ZONE property correctly. */
1349         received = NULL;
1350         hr = IUri_GetPropertyBSTR(uri, Uri_PROPERTY_ZONE, &received, 0);
1351         ok(hr == S_FALSE, "Error: GetPropertyBSTR returned 0x%08x, expected 0x%08x.\n", hr, S_FALSE);
1352         ok(received != NULL, "Error: Expected the string not to be NULL.\n");
1353         ok(!SysStringLen(received), "Error: Expected the string to be of len=0 but it was %d instead.\n", SysStringLen(received));
1354         SysFreeString(received);
1355     }
1356     if(uri) IUri_Release(uri);
1357
1358     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
1359         uri_properties test = uri_tests[i];
1360         LPWSTR uriW;
1361         uri = NULL;
1362
1363         uriW = a2w(test.uri);
1364         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
1365         if(test.create_todo) {
1366             todo_wine {
1367                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x. Failed on uri_tests[%d].\n",
1368                         hr, test.create_expected, i);
1369             }
1370         } else {
1371             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x. Failed on uri_tests[%d].\n",
1372                     hr, test.create_expected, i);
1373         }
1374
1375         if(SUCCEEDED(hr)) {
1376             DWORD j;
1377
1378             /* Checks all the string properties of the uri. */
1379             for(j = Uri_PROPERTY_STRING_START; j <= Uri_PROPERTY_STRING_LAST; ++j) {
1380                 BSTR received = NULL;
1381                 uri_str_property prop = test.str_props[j];
1382
1383                 hr = IUri_GetPropertyBSTR(uri, j, &received, 0);
1384                 if(prop.todo) {
1385                     todo_wine {
1386                         ok(hr == prop.expected, "GetPropertyBSTR returned 0x%08x, expected 0x%08x. On uri_tests[%d].str_props[%d].\n",
1387                                 hr, prop.expected, i, j);
1388                     }
1389                     todo_wine {
1390                         ok(!strcmp_aw(prop.value, received), "Expected %s but got %s on uri_tests[%d].str_props[%d].\n",
1391                                 prop.value, wine_dbgstr_w(received), i, j);
1392                     }
1393                 } else {
1394                     ok(hr == prop.expected, "GetPropertyBSTR returned 0x%08x, expected 0x%08x. On uri_tests[%d].str_props[%d].\n",
1395                             hr, prop.expected, i, j);
1396                     ok(!strcmp_aw(prop.value, received), "Expected %s but got %s on uri_tests[%d].str_props[%d].\n",
1397                             prop.value, wine_dbgstr_w(received), i, j);
1398                 }
1399
1400                 SysFreeString(received);
1401             }
1402         }
1403
1404         if(uri) IUri_Release(uri);
1405
1406         heap_free(uriW);
1407     }
1408 }
1409
1410 static void test_IUri_GetPropertyDWORD(void) {
1411     IUri *uri = NULL;
1412     HRESULT hr;
1413     DWORD i;
1414
1415     hr = pCreateUri(http_urlW, 0, 0, &uri);
1416     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
1417     if(SUCCEEDED(hr)) {
1418         DWORD received = 0xdeadbeef;
1419
1420         hr = IUri_GetPropertyDWORD(uri, Uri_PROPERTY_DWORD_START, NULL, 0);
1421         ok(hr == E_INVALIDARG, "Error: GetPropertyDWORD returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
1422
1423         hr = IUri_GetPropertyDWORD(uri, Uri_PROPERTY_ABSOLUTE_URI, &received, 0);
1424         ok(hr == E_INVALIDARG, "Error: GetPropertyDWORD returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
1425         ok(received == 0, "Error: Expected received=%d but instead received=%d.\n", 0, received);
1426     }
1427     if(uri) IUri_Release(uri);
1428
1429     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
1430         uri_properties test = uri_tests[i];
1431         LPWSTR uriW;
1432         uri = NULL;
1433
1434         uriW = a2w(test.uri);
1435         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
1436         if(test.create_todo) {
1437             todo_wine {
1438                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x. Failed on uri_tests[%d].\n",
1439                         hr, test.create_expected, i);
1440             }
1441         } else {
1442             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x. Failed on uri_tests[%d].\n",
1443                     hr, test.create_expected, i);
1444         }
1445
1446         if(SUCCEEDED(hr)) {
1447             DWORD j;
1448
1449             /* Checks all the DWORD properties of the uri. */
1450             for(j = 0; j < sizeof(test.dword_props)/sizeof(test.dword_props[0]); ++j) {
1451                 DWORD received;
1452                 uri_dword_property prop = test.dword_props[j];
1453
1454                 hr = IUri_GetPropertyDWORD(uri, j+Uri_PROPERTY_DWORD_START, &received, 0);
1455                 if(prop.todo) {
1456                     todo_wine {
1457                         ok(hr == prop.expected, "GetPropertyDWORD returned 0x%08x, expected 0x%08x. On uri_tests[%d].dword_props[%d].\n",
1458                                 hr, prop.expected, i, j);
1459                     }
1460                     todo_wine {
1461                         ok(prop.value == received, "Expected %d but got %d on uri_tests[%d].dword_props[%d].\n",
1462                                 prop.value, received, i, j);
1463                     }
1464                 } else {
1465                     ok(hr == prop.expected, "GetPropertyDWORD returned 0x%08x, expected 0x%08x. On uri_tests[%d].dword_props[%d].\n",
1466                             hr, prop.expected, i, j);
1467                     ok(prop.value == received, "Expected %d but got %d on uri_tests[%d].dword_props[%d].\n",
1468                             prop.value, received, i, j);
1469                 }
1470             }
1471         }
1472
1473         if(uri) IUri_Release(uri);
1474
1475         heap_free(uriW);
1476     }
1477 }
1478
1479 /* Tests all the 'Get*' property functions which deal with strings. */
1480 static void test_IUri_GetStrProperties(void) {
1481     IUri *uri = NULL;
1482     HRESULT hr;
1483     DWORD i;
1484
1485     /* Make sure all the 'Get*' string property functions handle invalid args correctly. */
1486     hr = pCreateUri(http_urlW, 0, 0, &uri);
1487     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
1488     if(SUCCEEDED(hr)) {
1489         hr = IUri_GetAbsoluteUri(uri, NULL);
1490         ok(hr == E_POINTER, "Error: GetAbsoluteUri returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
1491
1492         hr = IUri_GetAuthority(uri, NULL);
1493         ok(hr == E_POINTER, "Error: GetAuthority returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
1494
1495         hr = IUri_GetDisplayUri(uri, NULL);
1496         ok(hr == E_POINTER, "Error: GetDisplayUri returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
1497
1498         hr = IUri_GetDomain(uri, NULL);
1499         ok(hr == E_POINTER, "Error: GetDomain returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
1500
1501         hr = IUri_GetExtension(uri, NULL);
1502         ok(hr == E_POINTER, "Error: GetExtension returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
1503
1504         hr = IUri_GetFragment(uri, NULL);
1505         ok(hr == E_POINTER, "Error: GetFragment returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
1506
1507         hr = IUri_GetHost(uri, NULL);
1508         ok(hr == E_POINTER, "Error: GetHost returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
1509
1510         hr = IUri_GetPassword(uri, NULL);
1511         ok(hr == E_POINTER, "Error: GetPassword returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
1512
1513         hr = IUri_GetPath(uri, NULL);
1514         ok(hr == E_POINTER, "Error: GetPath returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
1515
1516         hr = IUri_GetPathAndQuery(uri, NULL);
1517         ok(hr == E_POINTER, "Error: GetPathAndQuery returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
1518
1519         hr = IUri_GetQuery(uri, NULL);
1520         ok(hr == E_POINTER, "Error: GetQuery returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
1521
1522         hr = IUri_GetRawUri(uri, NULL);
1523         ok(hr == E_POINTER, "Error: GetRawUri returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
1524
1525         hr = IUri_GetSchemeName(uri, NULL);
1526         ok(hr == E_POINTER, "Error: GetSchemeName returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
1527
1528         hr = IUri_GetUserInfo(uri, NULL);
1529         ok(hr == E_POINTER, "Error: GetUserInfo returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
1530
1531         hr = IUri_GetUserName(uri, NULL);
1532         ok(hr == E_POINTER, "Error: GetUserName returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
1533     }
1534     if(uri) IUri_Release(uri);
1535
1536     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
1537         uri_properties test = uri_tests[i];
1538         LPWSTR uriW;
1539         uri = NULL;
1540
1541         uriW = a2w(test.uri);
1542         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
1543         if(test.create_todo) {
1544             todo_wine {
1545                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
1546                         hr, test.create_expected, i);
1547             }
1548         } else {
1549             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
1550                     hr, test.create_expected, i);
1551         }
1552
1553         if(SUCCEEDED(hr)) {
1554             uri_str_property prop;
1555             BSTR received = NULL;
1556
1557             /* GetAbsoluteUri() tests. */
1558             prop = test.str_props[Uri_PROPERTY_ABSOLUTE_URI];
1559             hr = IUri_GetAbsoluteUri(uri, &received);
1560             if(prop.todo) {
1561                 todo_wine {
1562                     ok(hr == prop.expected, "Error: GetAbsoluteUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
1563                             hr, prop.expected, i);
1564                 }
1565                 todo_wine {
1566                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
1567                             prop.value, wine_dbgstr_w(received), i);
1568                 }
1569             } else {
1570                 ok(hr == prop.expected, "Error: GetAbsoluteUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
1571                         hr, prop.expected, i);
1572                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
1573                         prop.value, wine_dbgstr_w(received), i);
1574             }
1575             SysFreeString(received);
1576             received = NULL;
1577
1578             /* GetAuthority() tests. */
1579             prop = test.str_props[Uri_PROPERTY_AUTHORITY];
1580             hr = IUri_GetAuthority(uri, &received);
1581             if(prop.todo) {
1582                 todo_wine {
1583                     ok(hr == prop.expected, "Error: GetAuthority returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
1584                             hr, prop.expected, i);
1585                 }
1586                 todo_wine {
1587                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
1588                             prop.value, wine_dbgstr_w(received), i);
1589                 }
1590             } else {
1591                 ok(hr == prop.expected, "Error: GetAuthority returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
1592                         hr, prop.expected, i);
1593                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
1594                         prop.value, wine_dbgstr_w(received), i);
1595             }
1596             SysFreeString(received);
1597             received = NULL;
1598
1599             /* GetDisplayUri() tests. */
1600             prop = test.str_props[Uri_PROPERTY_DISPLAY_URI];
1601             hr = IUri_GetDisplayUri(uri, &received);
1602             if(prop.todo) {
1603                 todo_wine {
1604                     ok(hr == prop.expected, "Error: GetDisplayUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
1605                             hr, prop.expected, i);
1606                 }
1607                 todo_wine {
1608                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_test[%d].\n",
1609                             prop.value, wine_dbgstr_w(received), i);
1610                 }
1611             } else {
1612                 ok(hr == prop.expected, "Error: GetDisplayUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
1613                         hr, prop.expected, i);
1614                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
1615                         prop.value, wine_dbgstr_w(received), i);
1616             }
1617             SysFreeString(received);
1618             received = NULL;
1619
1620             /* GetDomain() tests. */
1621             prop = test.str_props[Uri_PROPERTY_DOMAIN];
1622             hr = IUri_GetDomain(uri, &received);
1623             if(prop.todo) {
1624                 todo_wine {
1625                     ok(hr == prop.expected, "Error: GetDomain returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
1626                             hr, prop.expected, i);
1627                 }
1628                 todo_wine {
1629                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
1630                             prop.value, wine_dbgstr_w(received), i);
1631                 }
1632             } else {
1633                 ok(hr == prop.expected, "Error: GetDomain returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
1634                         hr, prop.expected, i);
1635                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
1636                         prop.value, wine_dbgstr_w(received), i);
1637             }
1638             SysFreeString(received);
1639             received = NULL;
1640
1641             /* GetExtension() tests. */
1642             prop = test.str_props[Uri_PROPERTY_EXTENSION];
1643             hr = IUri_GetExtension(uri, &received);
1644             if(prop.todo) {
1645                 todo_wine {
1646                     ok(hr == prop.expected, "Error: GetExtension returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
1647                             hr, prop.expected, i);
1648                 }
1649                 todo_wine {
1650                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
1651                             prop.value, wine_dbgstr_w(received), i);
1652                 }
1653             } else {
1654                 ok(hr == prop.expected, "Error: GetExtension returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
1655                         hr, prop.expected, i);
1656                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
1657                         prop.value, wine_dbgstr_w(received), i);
1658             }
1659             SysFreeString(received);
1660             received = NULL;
1661
1662             /* GetFragment() tests. */
1663             prop = test.str_props[Uri_PROPERTY_FRAGMENT];
1664             hr = IUri_GetFragment(uri, &received);
1665             if(prop.todo) {
1666                 todo_wine {
1667                     ok(hr == prop.expected, "Error: GetFragment returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
1668                             hr, prop.expected, i);
1669                 }
1670                 todo_wine {
1671                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
1672                             prop.value, wine_dbgstr_w(received), i);
1673                 }
1674             } else {
1675                 ok(hr == prop.expected, "Error: GetFragment returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
1676                         hr, prop.expected, i);
1677                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
1678                         prop.value, wine_dbgstr_w(received), i);
1679             }
1680             SysFreeString(received);
1681             received = NULL;
1682
1683             /* GetHost() tests. */
1684             prop = test.str_props[Uri_PROPERTY_HOST];
1685             hr = IUri_GetHost(uri, &received);
1686             if(prop.todo) {
1687                 todo_wine {
1688                     ok(hr == prop.expected, "Error: GetHost returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
1689                             hr, prop.expected, i);
1690                 }
1691                 todo_wine {
1692                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
1693                             prop.value, wine_dbgstr_w(received), i);
1694                 }
1695             } else {
1696                 ok(hr == prop.expected, "Error: GetHost returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
1697                         hr, prop.expected, i);
1698                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
1699                         prop.value, wine_dbgstr_w(received), i);
1700             }
1701             SysFreeString(received);
1702             received = NULL;
1703
1704             /* GetPassword() tests. */
1705             prop = test.str_props[Uri_PROPERTY_PASSWORD];
1706             hr = IUri_GetPassword(uri, &received);
1707             if(prop.todo) {
1708                 todo_wine {
1709                     ok(hr == prop.expected, "Error: GetPassword returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
1710                             hr, prop.expected, i);
1711                 }
1712                 todo_wine {
1713                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
1714                             prop.value, wine_dbgstr_w(received), i);
1715                 }
1716             } else {
1717                 ok(hr == prop.expected, "Error: GetPassword returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
1718                         hr, prop.expected, i);
1719                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
1720                         prop.value, wine_dbgstr_w(received), i);
1721             }
1722             SysFreeString(received);
1723             received = NULL;
1724
1725             /* GetPath() tests. */
1726             prop = test.str_props[Uri_PROPERTY_PATH];
1727             hr = IUri_GetPath(uri, &received);
1728             if(prop.todo) {
1729                 todo_wine {
1730                     ok(hr == prop.expected, "Error: GetPath returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
1731                             hr, prop.expected, i);
1732                 }
1733                 todo_wine {
1734                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
1735                             prop.value, wine_dbgstr_w(received), i);
1736                 }
1737             } else {
1738                 ok(hr == prop.expected, "Error: GetPath returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
1739                         hr, prop.expected, i);
1740                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
1741                         prop.value, wine_dbgstr_w(received), i);
1742             }
1743             SysFreeString(received);
1744             received = NULL;
1745
1746             /* GetPathAndQuery() tests. */
1747             prop = test.str_props[Uri_PROPERTY_PATH_AND_QUERY];
1748             hr = IUri_GetPathAndQuery(uri, &received);
1749             if(prop.todo) {
1750                 todo_wine {
1751                     ok(hr == prop.expected, "Error: GetPathAndQuery returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
1752                             hr, prop.expected, i);
1753                 }
1754                 todo_wine {
1755                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
1756                             prop.value, wine_dbgstr_w(received), i);
1757                 }
1758             } else {
1759                 ok(hr == prop.expected, "Error: GetPathAndQuery returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
1760                         hr, prop.expected, i);
1761                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
1762                         prop.value, wine_dbgstr_w(received), i);
1763             }
1764             SysFreeString(received);
1765             received = NULL;
1766
1767             /* GetQuery() tests. */
1768             prop = test.str_props[Uri_PROPERTY_QUERY];
1769             hr = IUri_GetQuery(uri, &received);
1770             if(prop.todo) {
1771                 todo_wine {
1772                     ok(hr == prop.expected, "Error: GetQuery returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
1773                             hr, prop.expected, i);
1774                 }
1775                 todo_wine {
1776                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
1777                             prop.value, wine_dbgstr_w(received), i);
1778                 }
1779             } else {
1780                 ok(hr == prop.expected, "Error: GetQuery returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
1781                         hr, prop.expected, i);
1782                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
1783                         prop.value, wine_dbgstr_w(received), i);
1784             }
1785             SysFreeString(received);
1786             received = NULL;
1787
1788             /* GetRawUri() tests. */
1789             prop = test.str_props[Uri_PROPERTY_RAW_URI];
1790             hr = IUri_GetRawUri(uri, &received);
1791             if(prop.todo) {
1792                 todo_wine {
1793                     ok(hr == prop.expected, "Error: GetRawUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
1794                             hr, prop.expected, i);
1795                 }
1796                 todo_wine {
1797                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
1798                             prop.value, wine_dbgstr_w(received), i);
1799                 }
1800             } else {
1801                 ok(hr == prop.expected, "Error: GetRawUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
1802                         hr, prop.expected, i);
1803                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
1804                         prop.value, wine_dbgstr_w(received), i);
1805             }
1806             SysFreeString(received);
1807             received = NULL;
1808
1809             /* GetSchemeName() tests. */
1810             prop = test.str_props[Uri_PROPERTY_SCHEME_NAME];
1811             hr = IUri_GetSchemeName(uri, &received);
1812             if(prop.todo) {
1813                 todo_wine {
1814                     ok(hr == prop.expected, "Error: GetSchemeName returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
1815                             hr, prop.expected, i);
1816                 }
1817                 todo_wine {
1818                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
1819                             prop.value, wine_dbgstr_w(received), i);
1820                 }
1821             } else {
1822                 ok(hr == prop.expected, "Error: GetSchemeName returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
1823                         hr, prop.expected, i);
1824                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
1825                         prop.value, wine_dbgstr_w(received), i);
1826             }
1827             SysFreeString(received);
1828             received = NULL;
1829
1830             /* GetUserInfo() tests. */
1831             prop = test.str_props[Uri_PROPERTY_USER_INFO];
1832             hr = IUri_GetUserInfo(uri, &received);
1833             if(prop.todo) {
1834                 todo_wine {
1835                     ok(hr == prop.expected, "Error: GetUserInfo returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
1836                             hr, prop.expected, i);
1837                 }
1838                 todo_wine {
1839                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
1840                             prop.value, wine_dbgstr_w(received), i);
1841                 }
1842             } else {
1843                 ok(hr == prop.expected, "Error: GetUserInfo returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
1844                         hr, prop.expected, i);
1845                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
1846                         prop.value, wine_dbgstr_w(received), i);
1847             }
1848             SysFreeString(received);
1849             received = NULL;
1850
1851             /* GetUserName() tests. */
1852             prop = test.str_props[Uri_PROPERTY_USER_NAME];
1853             hr = IUri_GetUserName(uri, &received);
1854             if(prop.todo) {
1855                 todo_wine {
1856                     ok(hr == prop.expected, "Error: GetUserName returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
1857                             hr, prop.expected, i);
1858                 }
1859                 todo_wine {
1860                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
1861                             prop.value, wine_dbgstr_w(received), i);
1862                 }
1863             } else {
1864                 ok(hr == prop.expected, "Error: GetUserName returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
1865                         hr, prop.expected, i);
1866                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
1867                         prop.value, wine_dbgstr_w(received), i);
1868             }
1869             SysFreeString(received);
1870         }
1871
1872         if(uri) IUri_Release(uri);
1873
1874         heap_free(uriW);
1875     }
1876 }
1877
1878 static void test_IUri_GetDwordProperties(void) {
1879     IUri *uri = NULL;
1880     HRESULT hr;
1881     DWORD i;
1882
1883     /* Make sure all the 'Get*' dword property functions handle invalid args correctly. */
1884     hr = pCreateUri(http_urlW, 0, 0, &uri);
1885     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
1886     if(SUCCEEDED(hr)) {
1887         hr = IUri_GetHostType(uri, NULL);
1888         ok(hr == E_INVALIDARG, "Error: GetHostType returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
1889
1890         hr = IUri_GetPort(uri, NULL);
1891         ok(hr == E_INVALIDARG, "Error: GetPort returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
1892
1893         hr = IUri_GetScheme(uri, NULL);
1894         ok(hr == E_INVALIDARG, "Error: GetScheme returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
1895
1896         hr = IUri_GetZone(uri, NULL);
1897         ok(hr == E_INVALIDARG, "Error: GetZone returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
1898     }
1899     if(uri) IUri_Release(uri);
1900
1901     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
1902         uri_properties test = uri_tests[i];
1903         LPWSTR uriW;
1904         uri = NULL;
1905
1906         uriW = a2w(test.uri);
1907         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
1908         if(test.create_todo) {
1909             todo_wine {
1910                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
1911                         hr, test.create_expected, i);
1912             }
1913         } else {
1914             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
1915                     hr, test.create_expected, i);
1916         }
1917
1918         if(SUCCEEDED(hr)) {
1919             uri_dword_property prop;
1920             DWORD received;
1921
1922             /* Assign an insane value so tests don't accidentally pass when
1923              * they shouldn't!
1924              */
1925             received = -9999999;
1926
1927             /* GetHostType() tests. */
1928             prop = test.dword_props[Uri_PROPERTY_HOST_TYPE-Uri_PROPERTY_DWORD_START];
1929             hr = IUri_GetHostType(uri, &received);
1930             if(prop.todo) {
1931                 todo_wine {
1932                     ok(hr == prop.expected, "Error: GetHostType returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
1933                             hr, prop.expected, i);
1934                 }
1935                 todo_wine {
1936                     ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
1937                 }
1938             } else {
1939                 ok(hr == prop.expected, "Error: GetHostType returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
1940                         hr, prop.expected, i);
1941                 ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
1942             }
1943             received = -9999999;
1944
1945             /* GetPort() tests. */
1946             prop = test.dword_props[Uri_PROPERTY_PORT-Uri_PROPERTY_DWORD_START];
1947             hr = IUri_GetPort(uri, &received);
1948             if(prop.todo) {
1949                 todo_wine {
1950                     ok(hr == prop.expected, "Error: GetPort returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
1951                             hr, prop.expected, i);
1952                 }
1953                 todo_wine {
1954                     ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
1955                 }
1956             } else {
1957                 ok(hr == prop.expected, "Error: GetPort returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
1958                         hr, prop.expected, i);
1959                 ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
1960             }
1961             received = -9999999;
1962
1963             /* GetScheme() tests. */
1964             prop = test.dword_props[Uri_PROPERTY_SCHEME-Uri_PROPERTY_DWORD_START];
1965             hr = IUri_GetScheme(uri, &received);
1966             if(prop.todo) {
1967                 todo_wine {
1968                     ok(hr == prop.expected, "Error: GetScheme returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
1969                             hr, prop.expected, i);
1970                 }
1971                 todo_wine {
1972                     ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
1973                 }
1974             } else {
1975                 ok(hr == prop.expected, "Error: GetScheme returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
1976                         hr, prop.expected, i);
1977                 ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
1978             }
1979             received = -9999999;
1980
1981             /* GetZone() tests. */
1982             prop = test.dword_props[Uri_PROPERTY_ZONE-Uri_PROPERTY_DWORD_START];
1983             hr = IUri_GetZone(uri, &received);
1984             if(prop.todo) {
1985                 todo_wine {
1986                     ok(hr == prop.expected, "Error: GetZone returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
1987                             hr, prop.expected, i);
1988                 }
1989                 todo_wine {
1990                     ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
1991                 }
1992             } else {
1993                 ok(hr == prop.expected, "Error: GetZone returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
1994                         hr, prop.expected, i);
1995                 ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
1996             }
1997         }
1998
1999         if(uri) IUri_Release(uri);
2000
2001         heap_free(uriW);
2002     }
2003 }
2004
2005 static void test_IUri_GetPropertyLength(void) {
2006     IUri *uri = NULL;
2007     HRESULT hr;
2008     DWORD i;
2009
2010     /* Make sure it handles invalid args correctly. */
2011     hr = pCreateUri(http_urlW, 0, 0, &uri);
2012     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
2013     if(SUCCEEDED(hr)) {
2014         DWORD received = 0xdeadbeef;
2015
2016         hr = IUri_GetPropertyLength(uri, Uri_PROPERTY_STRING_START, NULL, 0);
2017         ok(hr == E_INVALIDARG, "Error: GetPropertyLength returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
2018
2019         hr = IUri_GetPropertyLength(uri, Uri_PROPERTY_DWORD_START, &received, 0);
2020         ok(hr == E_INVALIDARG, "Error: GetPropertyLength return 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
2021         ok(received == 0xdeadbeef, "Error: Expected 0xdeadbeef but got 0x%08x.\n", received);
2022     }
2023     if(uri) IUri_Release(uri);
2024
2025     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
2026         uri_properties test = uri_tests[i];
2027         LPWSTR uriW;
2028         uri = NULL;
2029
2030         uriW = a2w(test.uri);
2031         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
2032         if(test.create_todo) {
2033             todo_wine {
2034                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
2035                         hr, test.create_expected, i);
2036             }
2037         } else {
2038             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_test[%d].\n",
2039                     hr, test.create_expected, i);
2040         }
2041
2042         if(SUCCEEDED(hr)) {
2043             DWORD j;
2044
2045             for(j = Uri_PROPERTY_STRING_START; j <= Uri_PROPERTY_STRING_LAST; ++j) {
2046                 DWORD expectedLen, receivedLen;
2047                 uri_str_property prop = test.str_props[j];
2048
2049                 expectedLen = lstrlen(prop.value);
2050
2051                 /* This won't be necessary once GetPropertyLength is implemented. */
2052                 receivedLen = -1;
2053
2054                 hr = IUri_GetPropertyLength(uri, j, &receivedLen, 0);
2055                 if(prop.todo) {
2056                     todo_wine {
2057                         ok(hr == prop.expected, "Error: GetPropertyLength returned 0x%08x, expected 0x%08x on uri_tests[%d].str_props[%d].\n",
2058                                 hr, prop.expected, i, j);
2059                     }
2060                     todo_wine {
2061                         ok(receivedLen == expectedLen, "Error: Expected a length of %d but got %d on uri_tests[%d].str_props[%d].\n",
2062                                 expectedLen, receivedLen, i, j);
2063                     }
2064                 } else {
2065                     ok(hr == prop.expected, "Error: GetPropertyLength returned 0x%08x, expected 0x%08x on uri_tests[%d].str_props[%d].\n",
2066                             hr, prop.expected, i, j);
2067                     ok(receivedLen == expectedLen, "Error: Expected a length of %d but got %d on uri_tests[%d].str_props[%d].\n",
2068                             expectedLen, receivedLen, i, j);
2069                 }
2070             }
2071         }
2072
2073         if(uri) IUri_Release(uri);
2074
2075         heap_free(uriW);
2076     }
2077 }
2078
2079 static void test_IUri_GetProperties(void) {
2080     IUri *uri = NULL;
2081     HRESULT hr;
2082     DWORD i;
2083
2084     hr = pCreateUri(http_urlW, 0, 0, &uri);
2085     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
2086     if(SUCCEEDED(hr)) {
2087         hr = IUri_GetProperties(uri, NULL);
2088         ok(hr == E_INVALIDARG, "Error: GetProperties returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
2089     }
2090     if(uri) IUri_Release(uri);
2091
2092     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
2093         uri_properties test = uri_tests[i];
2094         LPWSTR uriW;
2095         uri = NULL;
2096
2097         uriW = a2w(test.uri);
2098         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
2099         if(test.create_todo) {
2100             todo_wine {
2101                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, test.create_expected);
2102             }
2103         } else {
2104             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, test.create_expected);
2105         }
2106
2107         if(SUCCEEDED(hr)) {
2108             DWORD received = 0;
2109             DWORD j;
2110
2111             hr = IUri_GetProperties(uri, &received);
2112             if(test.props_todo) {
2113                 todo_wine {
2114                     ok(hr == S_OK, "Error: GetProperties returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
2115                 }
2116             } else {
2117                 ok(hr == S_OK, "Error: GetProperties returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
2118             }
2119
2120             for(j = 0; j <= Uri_PROPERTY_DWORD_LAST; ++j) {
2121                 /* (1 << j) converts a Uri_PROPERTY to its corresponding Uri_HAS_* flag mask. */
2122                 if(test.props & (1 << j)) {
2123                     if(test.props_todo) {
2124                         todo_wine {
2125                             ok(received & (1 << j), "Error: Expected flag for property %d on uri_tests[%d].\n", j, i);
2126                         }
2127                     } else {
2128                         ok(received & (1 << j), "Error: Expected flag for property %d on uri_tests[%d].\n", j, i);
2129                     }
2130                 } else {
2131                     /* NOTE: Since received is initialized to 0, this test will always pass while
2132                      * GetProperties is unimplemented.
2133                      */
2134                     ok(!(received & (1 << j)), "Error: Received flag for property %d when not expected on uri_tests[%d].\n", j, i);
2135                 }
2136             }
2137         }
2138
2139         if(uri) IUri_Release(uri);
2140
2141         heap_free(uriW);
2142     }
2143 }
2144
2145 static void test_IUri_HasProperty(void) {
2146     IUri *uri = NULL;
2147     HRESULT hr;
2148     DWORD i;
2149
2150     hr = pCreateUri(http_urlW, 0, 0, &uri);
2151     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
2152     if(SUCCEEDED(hr)) {
2153         hr = IUri_HasProperty(uri, Uri_PROPERTY_RAW_URI, NULL);
2154         ok(hr == E_INVALIDARG, "Error: HasProperty returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
2155     }
2156     if(uri) IUri_Release(uri);
2157
2158     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
2159         uri_properties test = uri_tests[i];
2160         LPWSTR uriW;
2161         uri = NULL;
2162
2163         uriW = a2w(test.uri);
2164
2165         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
2166         if(test.create_todo) {
2167             todo_wine {
2168                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, test.create_expected);
2169             }
2170         } else {
2171             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, test.create_expected);
2172         }
2173
2174         if(SUCCEEDED(hr)) {
2175             DWORD j;
2176
2177             for(j = 0; j <= Uri_PROPERTY_DWORD_LAST; ++j) {
2178                 /* Assign -1, then explicitly test for TRUE or FALSE later. */
2179                 BOOL received = -1;
2180
2181                 hr = IUri_HasProperty(uri, j, &received);
2182                 if(test.props_todo) {
2183                     todo_wine {
2184                         ok(hr == S_OK, "Error: HasProperty returned 0x%08x, expected 0x%08x for property %d on uri_tests[%d].\n",
2185                                 hr, S_OK, j, i);
2186                     }
2187
2188                     /* Check if the property should be true. */
2189                     if(test.props & (1 << j)) {
2190                         todo_wine {
2191                             ok(received == TRUE, "Error: Expected to have property %d on uri_tests[%d].\n", j, i);
2192                         }
2193                     } else {
2194                         todo_wine {
2195                             ok(received == FALSE, "Error: Wasn't expecting to have property %d on uri_tests[%d].\n", j, i);
2196                         }
2197                     }
2198                 } else {
2199                     ok(hr == S_OK, "Error: HasProperty returned 0x%08x, expected 0x%08x for property %d on uri_tests[%d].\n",
2200                             hr, S_OK, j, i);
2201
2202                     if(test.props & (1 << j)) {
2203                         ok(received == TRUE, "Error: Expected to have property %d on uri_tests[%d].\n", j, i);
2204                     } else {
2205                         ok(received == FALSE, "Error: Wasn't expecting to have property %d on uri_tests[%d].\n", j, i);
2206                     }
2207                 }
2208             }
2209         }
2210
2211         if(uri) IUri_Release(uri);
2212
2213         heap_free(uriW);
2214     }
2215 }
2216
2217 static void test_IUri_IsEqual(void) {
2218     IUri *uriA, *uriB;
2219     HRESULT hrA, hrB;
2220     DWORD i;
2221
2222     uriA = uriB = NULL;
2223
2224     /* Make sure IsEqual handles invalid args correctly. */
2225     hrA = pCreateUri(http_urlW, 0, 0, &uriA);
2226     hrB = pCreateUri(http_urlW, 0, 0, &uriB);
2227     ok(hrA == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hrA, S_OK);
2228     ok(hrB == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hrB, S_OK);
2229     if(SUCCEEDED(hrA) && SUCCEEDED(hrB)) {
2230         BOOL equal = -1;
2231         hrA = IUri_IsEqual(uriA, NULL, &equal);
2232         ok(hrA == S_OK, "Error: IsEqual returned 0x%08x, expected 0x%08x.\n", hrA, S_OK);
2233         ok(equal == FALSE, "Error: Expected equal to be FALSE, but was %d instead.\n", equal);
2234
2235         hrA = IUri_IsEqual(uriA, uriB, NULL);
2236         ok(hrA == E_POINTER, "Error: IsEqual returned 0x%08x, expected 0x%08x.\n", hrA, E_POINTER);
2237     }
2238     if(uriA) IUri_Release(uriA);
2239     if(uriB) IUri_Release(uriB);
2240
2241     for(i = 0; i < sizeof(equality_tests)/sizeof(equality_tests[0]); ++i) {
2242         uri_equality test = equality_tests[i];
2243         LPWSTR uriA_W, uriB_W;
2244
2245         uriA = uriB = NULL;
2246
2247         uriA_W = a2w(test.a);
2248         uriB_W = a2w(test.b);
2249
2250         hrA = pCreateUri(uriA_W, test.create_flags_a, 0, &uriA);
2251         if(test.create_todo_a) {
2252             todo_wine {
2253                 ok(hrA == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x on equality_tests[%d].a\n",
2254                         hrA, S_OK, i);
2255             }
2256         } else {
2257             ok(hrA == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x on equality_tests[%d].a\n",
2258                     hrA, S_OK, i);
2259         }
2260
2261         hrB = pCreateUri(uriB_W, test.create_flags_b, 0, &uriB);
2262         if(test.create_todo_b) {
2263             todo_wine {
2264                 ok(hrB == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x on equality_tests[%d].b\n",
2265                         hrB, S_OK, i);
2266             }
2267         } else {
2268             ok(hrB == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x on equality_tests[%d].b\n",
2269                     hrB, S_OK, i);
2270         }
2271
2272         if(SUCCEEDED(hrA) && SUCCEEDED(hrB)) {
2273             BOOL equal = -1;
2274
2275             hrA = IUri_IsEqual(uriA, uriB, &equal);
2276             if(test.todo) {
2277                 todo_wine {
2278                     ok(hrA == S_OK, "Error: IsEqual returned 0x%08x, expected 0x%08x on equality_tests[%d].\n",
2279                             hrA, S_OK, i);
2280                 }
2281                 todo_wine {
2282                     ok(equal == test.equal, "Error: Expected the comparison to be %d on equality_tests[%d].\n", test.equal, i);
2283                 }
2284             } else {
2285                 ok(hrA == S_OK, "Error: IsEqual returned 0x%08x, expected 0x%08x on equality_tests[%d].\n", hrA, S_OK, i);
2286                 ok(equal == test.equal, "Error: Expected the comparison to be %d on equality_tests[%d].\n", test.equal, i);
2287             }
2288         }
2289         if(uriA) IUri_Release(uriA);
2290         if(uriB) IUri_Release(uriB);
2291
2292         heap_free(uriA_W);
2293         heap_free(uriB_W);
2294     }
2295 }
2296
2297 START_TEST(uri) {
2298     HMODULE hurlmon;
2299
2300     hurlmon = GetModuleHandle("urlmon.dll");
2301     pCreateUri = (void*) GetProcAddress(hurlmon, "CreateUri");
2302
2303     if(!pCreateUri) {
2304         win_skip("CreateUri is not present, skipping tests.\n");
2305         return;
2306     }
2307
2308     trace("test CreateUri invalid flags...\n");
2309     test_CreateUri_InvalidFlags();
2310
2311     trace("test CreateUri invalid args...\n");
2312     test_CreateUri_InvalidArgs();
2313
2314     trace("test IUri_GetPropertyBSTR...\n");
2315     test_IUri_GetPropertyBSTR();
2316
2317     trace("test IUri_GetPropertyDWORD...\n");
2318     test_IUri_GetPropertyDWORD();
2319
2320     trace("test IUri_GetStrProperties...\n");
2321     test_IUri_GetStrProperties();
2322
2323     trace("test IUri_GetDwordProperties...\n");
2324     test_IUri_GetDwordProperties();
2325
2326     trace("test IUri_GetPropertyLength...\n");
2327     test_IUri_GetPropertyLength();
2328
2329     trace("test IUri_GetProperties...\n");
2330     test_IUri_GetProperties();
2331
2332     trace("test IUri_HasProperty...\n");
2333     test_IUri_HasProperty();
2334
2335     trace("test IUri_IsEqual...\n");
2336     test_IUri_IsEqual();
2337 }