msi/tests: Skip some source tests if a required product key cannot be created.
[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,TRUE},                                          /* 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,TRUE},   /* RAW_URI */
108             {"http",S_OK,TRUE},                                         /* SCHEME_NAME */
109             {"",S_FALSE,TRUE},                                          /* USER_INFO */
110             {"",S_FALSE,TRUE}                                           /* 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,TRUE},                                /* 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,TRUE},
133             {"/tests",S_OK,TRUE},
134             {"/tests",S_OK,TRUE},
135             {"",S_FALSE,TRUE},
136             {"http://winehq.org/tests/.././tests",S_OK,TRUE},
137             {"http",S_OK,TRUE},
138             {"",S_FALSE,TRUE},
139             {"",S_FALSE,TRUE}
140         },
141         {
142             {Uri_HOST_DNS,S_OK,TRUE},
143             {80,S_OK,TRUE},
144             {URL_SCHEME_HTTP,S_OK,TRUE},
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,TRUE},
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,TRUE},
166             {"http",S_OK,TRUE},
167             {"",S_FALSE,TRUE},
168             {"",S_FALSE,TRUE}
169         },
170         {
171             {Uri_HOST_DNS,S_OK,TRUE},
172             {80,S_OK,TRUE},
173             {URL_SCHEME_HTTP,S_OK,TRUE},
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,TRUE},
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,TRUE},
195             {"http",S_OK,TRUE},
196             {"usEr%3Ainfo",S_OK,TRUE},
197             {"usEr%3Ainfo",S_OK,TRUE}
198         },
199         {
200             {Uri_HOST_DNS,S_OK,TRUE},
201             {80,S_OK,TRUE},
202             {URL_SCHEME_HTTP,S_OK,TRUE},
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,TRUE},
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,TRUE},
225             {"ftp",S_OK,TRUE},
226             {"winepass:wine",S_OK,TRUE},
227             {"winepass",S_OK,TRUE}
228         },
229         {
230             {Uri_HOST_DNS,S_OK,TRUE},
231             {9999,S_OK,TRUE},
232             {URL_SCHEME_FTP,S_OK,TRUE},
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,TRUE},
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,TRUE},
253             {"file",S_OK,TRUE},
254             {"",S_FALSE,TRUE},
255             {"",S_FALSE,TRUE}
256         },
257         {
258             {Uri_HOST_UNKNOWN,S_OK,TRUE},
259             {0,S_FALSE,TRUE},
260             {URL_SCHEME_FILE,S_OK,TRUE},
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,TRUE},
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,TRUE},
281             {"file",S_OK,TRUE},
282             {"",S_FALSE,TRUE},
283             {"",S_FALSE,TRUE}
284         },
285         {
286             {Uri_HOST_UNKNOWN,S_OK,TRUE},
287             {0,S_FALSE,TRUE},
288             {URL_SCHEME_FILE,S_OK,TRUE},
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,TRUE},
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,TRUE},
309             {"urn",S_OK,TRUE},
310             {"",S_FALSE,TRUE},
311             {"",S_FALSE,TRUE}
312         },
313         {
314             {Uri_HOST_UNKNOWN,S_OK,TRUE},
315             {0,S_FALSE,TRUE},
316             {URL_SCHEME_UNKNOWN,S_OK,TRUE},
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,TRUE},
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,TRUE},
338             {"http",S_OK,TRUE},
339             {"",S_FALSE,TRUE},
340             {"",S_FALSE,TRUE}
341         },
342         {
343             {Uri_HOST_IPV4,S_OK,TRUE},
344             {80,S_OK,TRUE},
345             {URL_SCHEME_HTTP,S_OK,TRUE},
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,TRUE},
363             {"/",S_OK,TRUE},
364             {"/",S_OK,TRUE},
365             {"",S_FALSE,TRUE},
366             {"http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]",S_OK,TRUE},
367             {"http",S_OK,TRUE},
368             {"",S_FALSE,TRUE},
369             {"",S_FALSE,TRUE}
370         },
371         {
372             {Uri_HOST_IPV6,S_OK,TRUE},
373             {80,S_OK,TRUE},
374             {URL_SCHEME_HTTP,S_OK,TRUE},
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,TRUE},
392             {"/",S_OK,TRUE},
393             {"/",S_OK,TRUE},
394             {"",S_FALSE,TRUE},
395             {"ftp://[::13.1.68.3]",S_OK,TRUE},
396             {"ftp",S_OK,TRUE},
397             {"",S_FALSE,TRUE},
398             {"",S_FALSE,TRUE}
399         },
400         {
401             {Uri_HOST_IPV6,S_OK,TRUE},
402             {21,S_OK,TRUE},
403             {URL_SCHEME_FTP,S_OK,TRUE},
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,TRUE},
421             {"/",S_OK,TRUE},
422             {"/",S_OK,TRUE},
423             {"",S_FALSE,TRUE},
424             {"http://[FEDC:BA98:0:0:0:0:0:3210]",S_OK,TRUE},
425             {"http",S_OK,TRUE},
426             {"",S_FALSE,TRUE},
427             {"",S_FALSE,TRUE},
428         },
429         {
430             {Uri_HOST_IPV6,S_OK,TRUE},
431             {80,S_OK,TRUE},
432             {URL_SCHEME_HTTP,S_OK,TRUE},
433             {URLZONE_INVALID,E_NOTIMPL,FALSE}
434         }
435     }
436 };
437
438 typedef struct _uri_equality {
439     const char* a;
440     DWORD       create_flags_a;
441     BOOL        create_todo_a;
442     const char* b;
443     DWORD       create_flags_b;
444     BOOL        create_todo_b;
445     BOOL        equal;
446     BOOL        todo;
447 } uri_equality;
448
449 static const uri_equality equality_tests[] = {
450     {
451         "HTTP://www.winehq.org/test dir/./",0,FALSE,
452         "http://www.winehq.org/test dir/../test dir/",0,FALSE,
453         TRUE, TRUE
454     },
455     {
456         /* http://www.winehq.org/test%20dir */
457         "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,
458         "http://www.winehq.org/test dir",0,FALSE,
459         TRUE, TRUE,
460     },
461     {
462         "c:\\test.mp3",Uri_CREATE_ALLOW_IMPLICIT_FILE_SCHEME,FALSE,
463         "file:///c:/test.mp3",0,FALSE,
464         TRUE,TRUE
465     },
466     {
467         "ftp://ftp.winehq.org/",0,FALSE,
468         "ftp://ftp.winehq.org",0,FALSE,
469         TRUE, TRUE
470     },
471     {
472         "ftp://ftp.winehq.org/test/test2/../../testB/",0,FALSE,
473         "ftp://ftp.winehq.org/t%45stB/",0,FALSE,
474         FALSE, TRUE
475     }
476 };
477
478 static inline LPWSTR a2w(LPCSTR str) {
479     LPWSTR ret = NULL;
480
481     if(str) {
482         DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
483         ret = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
484         MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len);
485     }
486
487     return ret;
488 }
489
490 static inline BOOL heap_free(void* mem) {
491     return HeapFree(GetProcessHeap(), 0, mem);
492 }
493
494 static inline DWORD strcmp_aw(LPCSTR strA, LPCWSTR strB) {
495     LPWSTR strAW = a2w(strA);
496     DWORD ret = lstrcmpW(strAW, strB);
497     heap_free(strAW);
498     return ret;
499 }
500
501 /*
502  * Simple tests to make sure the CreateUri function handles invalid flag combinations
503  * correctly.
504  */
505 static void test_CreateUri_InvalidFlags(void) {
506     DWORD i;
507
508     for(i = 0; i < sizeof(invalid_flag_tests)/sizeof(invalid_flag_tests[0]); ++i) {
509         HRESULT hr;
510         IUri *uri = (void*) 0xdeadbeef;
511
512         hr = pCreateUri(http_urlW, invalid_flag_tests[i].flags, 0, &uri);
513         todo_wine {
514             ok(hr == invalid_flag_tests[i].expected, "Error: CreateUri returned 0x%08x, expected 0x%08x, flags=0x%08x\n",
515                     hr, invalid_flag_tests[i].expected, invalid_flag_tests[i].flags);
516         }
517         todo_wine { ok(uri == NULL, "Error: expected the IUri to be NULL, but it was %p instead\n", uri); }
518     }
519 }
520
521 static void test_CreateUri_InvalidArgs(void) {
522     HRESULT hr;
523     IUri *uri = (void*) 0xdeadbeef;
524
525     hr = pCreateUri(http_urlW, 0, 0, NULL);
526     ok(hr == E_INVALIDARG, "Error: CreateUri returned 0x%08x, expected 0x%08x\n", hr, E_INVALIDARG);
527
528     hr = pCreateUri(NULL, 0, 0, &uri);
529     ok(hr == E_INVALIDARG, "Error: CreateUri returned 0x%08x, expected 0x%08x\n", hr, E_INVALIDARG);
530     ok(uri == NULL, "Error: Expected the IUri to be NULL, but it was %p instead\n", uri);
531 }
532
533 static void test_IUri_GetPropertyBSTR(void) {
534     IUri *uri = NULL;
535     HRESULT hr;
536     DWORD i;
537
538     /* Make sure GetPropertyBSTR handles invalid args correctly. */
539     hr = pCreateUri(http_urlW, 0, 0, &uri);
540     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
541     if(SUCCEEDED(hr)) {
542         BSTR received = NULL;
543
544         hr = IUri_GetPropertyBSTR(uri, Uri_PROPERTY_RAW_URI, NULL, 0);
545         ok(hr == E_POINTER, "Error: GetPropertyBSTR returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
546
547         /* Make sure it handles a invalid Uri_PROPERTY's correctly. */
548         hr = IUri_GetPropertyBSTR(uri, Uri_PROPERTY_PORT, &received, 0);
549         ok(hr == S_OK, "Error: GetPropertyBSTR returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
550         ok(received != NULL, "Error: Expected the string not to be NULL.\n");
551         ok(!SysStringLen(received), "Error: Expected the string to be of len=0 but it was %d instead.\n", SysStringLen(received));
552         SysFreeString(received);
553
554         /* Make sure it handles the ZONE property correctly. */
555         received = NULL;
556         hr = IUri_GetPropertyBSTR(uri, Uri_PROPERTY_ZONE, &received, 0);
557         ok(hr == S_FALSE, "Error: GetPropertyBSTR returned 0x%08x, expected 0x%08x.\n", hr, S_FALSE);
558         ok(received != NULL, "Error: Expected the string not to be NULL.\n");
559         ok(!SysStringLen(received), "Error: Expected the string to be of len=0 but it was %d instead.\n", SysStringLen(received));
560         SysFreeString(received);
561     }
562     if(uri) IUri_Release(uri);
563
564     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
565         uri_properties test = uri_tests[i];
566         LPWSTR uriW;
567         uri = NULL;
568
569         uriW = a2w(test.uri);
570         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
571         if(test.create_todo) {
572             todo_wine {
573                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x. Failed on uri_tests[%d].\n",
574                         hr, test.create_expected, i);
575             }
576         } else {
577             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x. Failed on uri_tests[%d].\n",
578                     hr, test.create_expected, i);
579         }
580
581         if(SUCCEEDED(hr)) {
582             DWORD j;
583
584             /* Checks all the string properties of the uri. */
585             for(j = Uri_PROPERTY_STRING_START; j <= Uri_PROPERTY_STRING_LAST; ++j) {
586                 BSTR received = NULL;
587                 uri_str_property prop = test.str_props[j];
588
589                 hr = IUri_GetPropertyBSTR(uri, j, &received, 0);
590                 if(prop.todo) {
591                     todo_wine {
592                         ok(hr == prop.expected, "GetPropertyBSTR returned 0x%08x, expected 0x%08x. On uri_tests[%d].str_props[%d].\n",
593                                 hr, prop.expected, i, j);
594                     }
595                     todo_wine {
596                         ok(!strcmp_aw(prop.value, received), "Expected %s but got %s on uri_tests[%d].str_props[%d].\n",
597                                 prop.value, wine_dbgstr_w(received), i, j);
598                     }
599                 } else {
600                     ok(hr == prop.expected, "GetPropertyBSTR returned 0x%08x, expected 0x%08x. On uri_tests[%d].str_props[%d].\n",
601                             hr, prop.expected, i, j);
602                     ok(!strcmp_aw(prop.value, received), "Expected %s but got %s on uri_tests[%d].str_props[%d].\n",
603                             prop.value, wine_dbgstr_w(received), i, j);
604                 }
605
606                 SysFreeString(received);
607             }
608         }
609
610         if(uri) IUri_Release(uri);
611
612         heap_free(uriW);
613     }
614 }
615
616 static void test_IUri_GetPropertyDWORD(void) {
617     IUri *uri = NULL;
618     HRESULT hr;
619     DWORD i;
620
621     hr = pCreateUri(http_urlW, 0, 0, &uri);
622     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
623     if(SUCCEEDED(hr)) {
624         DWORD received = 0xdeadbeef;
625
626         hr = IUri_GetPropertyDWORD(uri, Uri_PROPERTY_DWORD_START, NULL, 0);
627         ok(hr == E_INVALIDARG, "Error: GetPropertyDWORD returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
628
629         hr = IUri_GetPropertyDWORD(uri, Uri_PROPERTY_ABSOLUTE_URI, &received, 0);
630         ok(hr == E_INVALIDARG, "Error: GetPropertyDWORD returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
631         ok(received == 0, "Error: Expected received=%d but instead received=%d.\n", 0, received);
632     }
633     if(uri) IUri_Release(uri);
634
635     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
636         uri_properties test = uri_tests[i];
637         LPWSTR uriW;
638         uri = NULL;
639
640         uriW = a2w(test.uri);
641         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
642         if(test.create_todo) {
643             todo_wine {
644                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x. Failed on uri_tests[%d].\n",
645                         hr, test.create_expected, i);
646             }
647         } else {
648             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x. Failed on uri_tests[%d].\n",
649                     hr, test.create_expected, i);
650         }
651
652         if(SUCCEEDED(hr)) {
653             DWORD j;
654
655             /* Checks all the DWORD properties of the uri. */
656             for(j = 0; j < sizeof(test.dword_props)/sizeof(test.dword_props[0]); ++j) {
657                 DWORD received;
658                 uri_dword_property prop = test.dword_props[j];
659
660                 hr = IUri_GetPropertyDWORD(uri, j+Uri_PROPERTY_DWORD_START, &received, 0);
661                 if(prop.todo) {
662                     todo_wine {
663                         ok(hr == prop.expected, "GetPropertyDWORD returned 0x%08x, expected 0x%08x. On uri_tests[%d].dword_props[%d].\n",
664                                 hr, prop.expected, i, j);
665                     }
666                     todo_wine {
667                         ok(prop.value == received, "Expected %d but got %d on uri_tests[%d].dword_props[%d].\n",
668                                 prop.value, received, i, j);
669                     }
670                 } else {
671                     ok(hr == prop.expected, "GetPropertyDWORD returned 0x%08x, expected 0x%08x. On uri_tests[%d].dword_props[%d].\n",
672                             hr, prop.expected, i, j);
673                     ok(prop.value == received, "Expected %d but got %d on uri_tests[%d].dword_props[%d].\n",
674                             prop.value, received, i, j);
675                 }
676             }
677         }
678
679         if(uri) IUri_Release(uri);
680
681         heap_free(uriW);
682     }
683 }
684
685 /* Tests all the 'Get*' property functions which deal with strings. */
686 static void test_IUri_GetStrProperties(void) {
687     IUri *uri = NULL;
688     HRESULT hr;
689     DWORD i;
690
691     /* Make sure all the 'Get*' string property functions handle invalid args correctly. */
692     hr = pCreateUri(http_urlW, 0, 0, &uri);
693     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
694     if(SUCCEEDED(hr)) {
695         hr = IUri_GetAbsoluteUri(uri, NULL);
696         ok(hr == E_POINTER, "Error: GetAbsoluteUri returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
697
698         hr = IUri_GetAuthority(uri, NULL);
699         ok(hr == E_POINTER, "Error: GetAuthority returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
700
701         hr = IUri_GetDisplayUri(uri, NULL);
702         ok(hr == E_POINTER, "Error: GetDisplayUri returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
703
704         hr = IUri_GetDomain(uri, NULL);
705         ok(hr == E_POINTER, "Error: GetDomain returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
706
707         hr = IUri_GetExtension(uri, NULL);
708         ok(hr == E_POINTER, "Error: GetExtension returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
709
710         hr = IUri_GetFragment(uri, NULL);
711         ok(hr == E_POINTER, "Error: GetFragment returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
712
713         hr = IUri_GetHost(uri, NULL);
714         ok(hr == E_POINTER, "Error: GetHost returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
715
716         hr = IUri_GetPassword(uri, NULL);
717         ok(hr == E_POINTER, "Error: GetPassword returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
718
719         hr = IUri_GetPath(uri, NULL);
720         ok(hr == E_POINTER, "Error: GetPath returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
721
722         hr = IUri_GetPathAndQuery(uri, NULL);
723         ok(hr == E_POINTER, "Error: GetPathAndQuery returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
724
725         hr = IUri_GetQuery(uri, NULL);
726         ok(hr == E_POINTER, "Error: GetQuery returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
727
728         hr = IUri_GetRawUri(uri, NULL);
729         ok(hr == E_POINTER, "Error: GetRawUri returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
730
731         hr = IUri_GetSchemeName(uri, NULL);
732         ok(hr == E_POINTER, "Error: GetSchemeName returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
733
734         hr = IUri_GetUserInfo(uri, NULL);
735         ok(hr == E_POINTER, "Error: GetUserInfo returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
736
737         hr = IUri_GetUserName(uri, NULL);
738         ok(hr == E_POINTER, "Error: GetUserName returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
739     }
740     if(uri) IUri_Release(uri);
741
742     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
743         uri_properties test = uri_tests[i];
744         LPWSTR uriW;
745         uri = NULL;
746
747         uriW = a2w(test.uri);
748         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
749         if(test.create_todo) {
750             todo_wine {
751                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
752                         hr, test.create_expected, i);
753             }
754         } else {
755             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
756                     hr, test.create_expected, i);
757         }
758
759         if(SUCCEEDED(hr)) {
760             uri_str_property prop;
761             BSTR received = NULL;
762
763             /* GetAbsoluteUri() tests. */
764             prop = test.str_props[Uri_PROPERTY_ABSOLUTE_URI];
765             hr = IUri_GetAbsoluteUri(uri, &received);
766             if(prop.todo) {
767                 todo_wine {
768                     ok(hr == prop.expected, "Error: GetAbsoluteUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
769                             hr, prop.expected, i);
770                 }
771                 todo_wine {
772                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
773                             prop.value, wine_dbgstr_w(received), i);
774                 }
775             } else {
776                 ok(hr == prop.expected, "Error: GetAbsoluteUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
777                         hr, prop.expected, i);
778                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
779                         prop.value, wine_dbgstr_w(received), i);
780             }
781             SysFreeString(received);
782             received = NULL;
783
784             /* GetAuthority() tests. */
785             prop = test.str_props[Uri_PROPERTY_AUTHORITY];
786             hr = IUri_GetAuthority(uri, &received);
787             if(prop.todo) {
788                 todo_wine {
789                     ok(hr == prop.expected, "Error: GetAuthority returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
790                             hr, prop.expected, i);
791                 }
792                 todo_wine {
793                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
794                             prop.value, wine_dbgstr_w(received), i);
795                 }
796             } else {
797                 ok(hr == prop.expected, "Error: GetAuthority returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
798                         hr, prop.expected, i);
799                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
800                         prop.value, wine_dbgstr_w(received), i);
801             }
802             SysFreeString(received);
803             received = NULL;
804
805             /* GetDisplayUri() tests. */
806             prop = test.str_props[Uri_PROPERTY_DISPLAY_URI];
807             hr = IUri_GetDisplayUri(uri, &received);
808             if(prop.todo) {
809                 todo_wine {
810                     ok(hr == prop.expected, "Error: GetDisplayUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
811                             hr, prop.expected, i);
812                 }
813                 todo_wine {
814                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_test[%d].\n",
815                             prop.value, wine_dbgstr_w(received), i);
816                 }
817             } else {
818                 ok(hr == prop.expected, "Error: GetDisplayUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
819                         hr, prop.expected, i);
820                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
821                         prop.value, wine_dbgstr_w(received), i);
822             }
823             SysFreeString(received);
824             received = NULL;
825
826             /* GetDomain() tests. */
827             prop = test.str_props[Uri_PROPERTY_DOMAIN];
828             hr = IUri_GetDomain(uri, &received);
829             if(prop.todo) {
830                 todo_wine {
831                     ok(hr == prop.expected, "Error: GetDomain returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
832                             hr, prop.expected, i);
833                 }
834                 todo_wine {
835                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
836                             prop.value, wine_dbgstr_w(received), i);
837                 }
838             } else {
839                 ok(hr == prop.expected, "Error: GetDomain returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
840                         hr, prop.expected, i);
841                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
842                         prop.value, wine_dbgstr_w(received), i);
843             }
844             SysFreeString(received);
845             received = NULL;
846
847             /* GetExtension() tests. */
848             prop = test.str_props[Uri_PROPERTY_EXTENSION];
849             hr = IUri_GetExtension(uri, &received);
850             if(prop.todo) {
851                 todo_wine {
852                     ok(hr == prop.expected, "Error: GetExtension returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
853                             hr, prop.expected, i);
854                 }
855                 todo_wine {
856                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
857                             prop.value, wine_dbgstr_w(received), i);
858                 }
859             } else {
860                 ok(hr == prop.expected, "Error: GetExtension returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
861                         hr, prop.expected, i);
862                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
863                         prop.value, wine_dbgstr_w(received), i);
864             }
865             SysFreeString(received);
866             received = NULL;
867
868             /* GetFragment() tests. */
869             prop = test.str_props[Uri_PROPERTY_FRAGMENT];
870             hr = IUri_GetFragment(uri, &received);
871             if(prop.todo) {
872                 todo_wine {
873                     ok(hr == prop.expected, "Error: GetFragment returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
874                             hr, prop.expected, i);
875                 }
876                 todo_wine {
877                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
878                             prop.value, wine_dbgstr_w(received), i);
879                 }
880             } else {
881                 ok(hr == prop.expected, "Error: GetFragment returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
882                         hr, prop.expected, i);
883                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
884                         prop.value, wine_dbgstr_w(received), i);
885             }
886             SysFreeString(received);
887             received = NULL;
888
889             /* GetHost() tests. */
890             prop = test.str_props[Uri_PROPERTY_HOST];
891             hr = IUri_GetHost(uri, &received);
892             if(prop.todo) {
893                 todo_wine {
894                     ok(hr == prop.expected, "Error: GetHost returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
895                             hr, prop.expected, i);
896                 }
897                 todo_wine {
898                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
899                             prop.value, wine_dbgstr_w(received), i);
900                 }
901             } else {
902                 ok(hr == prop.expected, "Error: GetHost returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
903                         hr, prop.expected, i);
904                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
905                         prop.value, wine_dbgstr_w(received), i);
906             }
907             SysFreeString(received);
908             received = NULL;
909
910             /* GetPassword() tests. */
911             prop = test.str_props[Uri_PROPERTY_PASSWORD];
912             hr = IUri_GetPassword(uri, &received);
913             if(prop.todo) {
914                 todo_wine {
915                     ok(hr == prop.expected, "Error: GetPassword returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
916                             hr, prop.expected, i);
917                 }
918                 todo_wine {
919                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
920                             prop.value, wine_dbgstr_w(received), i);
921                 }
922             } else {
923                 ok(hr == prop.expected, "Error: GetPassword returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
924                         hr, prop.expected, i);
925                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
926                         prop.value, wine_dbgstr_w(received), i);
927             }
928             SysFreeString(received);
929             received = NULL;
930
931             /* GetPath() tests. */
932             prop = test.str_props[Uri_PROPERTY_PATH];
933             hr = IUri_GetPath(uri, &received);
934             if(prop.todo) {
935                 todo_wine {
936                     ok(hr == prop.expected, "Error: GetPath returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
937                             hr, prop.expected, i);
938                 }
939                 todo_wine {
940                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
941                             prop.value, wine_dbgstr_w(received), i);
942                 }
943             } else {
944                 ok(hr == prop.expected, "Error: GetPath returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
945                         hr, prop.expected, i);
946                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
947                         prop.value, wine_dbgstr_w(received), i);
948             }
949             SysFreeString(received);
950             received = NULL;
951
952             /* GetPathAndQuery() tests. */
953             prop = test.str_props[Uri_PROPERTY_PATH_AND_QUERY];
954             hr = IUri_GetPathAndQuery(uri, &received);
955             if(prop.todo) {
956                 todo_wine {
957                     ok(hr == prop.expected, "Error: GetPathAndQuery returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
958                             hr, prop.expected, i);
959                 }
960                 todo_wine {
961                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
962                             prop.value, wine_dbgstr_w(received), i);
963                 }
964             } else {
965                 ok(hr == prop.expected, "Error: GetPathAndQuery returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
966                         hr, prop.expected, i);
967                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
968                         prop.value, wine_dbgstr_w(received), i);
969             }
970             SysFreeString(received);
971             received = NULL;
972
973             /* GetQuery() tests. */
974             prop = test.str_props[Uri_PROPERTY_QUERY];
975             hr = IUri_GetQuery(uri, &received);
976             if(prop.todo) {
977                 todo_wine {
978                     ok(hr == prop.expected, "Error: GetQuery returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
979                             hr, prop.expected, i);
980                 }
981                 todo_wine {
982                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
983                             prop.value, wine_dbgstr_w(received), i);
984                 }
985             } else {
986                 ok(hr == prop.expected, "Error: GetQuery returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
987                         hr, prop.expected, i);
988                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
989                         prop.value, wine_dbgstr_w(received), i);
990             }
991             SysFreeString(received);
992             received = NULL;
993
994             /* GetRawUri() tests. */
995             prop = test.str_props[Uri_PROPERTY_RAW_URI];
996             hr = IUri_GetRawUri(uri, &received);
997             if(prop.todo) {
998                 todo_wine {
999                     ok(hr == prop.expected, "Error: GetRawUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
1000                             hr, prop.expected, i);
1001                 }
1002                 todo_wine {
1003                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
1004                             prop.value, wine_dbgstr_w(received), i);
1005                 }
1006             } else {
1007                 ok(hr == prop.expected, "Error: GetRawUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
1008                         hr, prop.expected, i);
1009                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
1010                         prop.value, wine_dbgstr_w(received), i);
1011             }
1012             SysFreeString(received);
1013             received = NULL;
1014
1015             /* GetSchemeName() tests. */
1016             prop = test.str_props[Uri_PROPERTY_SCHEME_NAME];
1017             hr = IUri_GetSchemeName(uri, &received);
1018             if(prop.todo) {
1019                 todo_wine {
1020                     ok(hr == prop.expected, "Error: GetSchemeName returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
1021                             hr, prop.expected, i);
1022                 }
1023                 todo_wine {
1024                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
1025                             prop.value, wine_dbgstr_w(received), i);
1026                 }
1027             } else {
1028                 ok(hr == prop.expected, "Error: GetSchemeName returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
1029                         hr, prop.expected, i);
1030                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
1031                         prop.value, wine_dbgstr_w(received), i);
1032             }
1033             SysFreeString(received);
1034             received = NULL;
1035
1036             /* GetUserInfo() tests. */
1037             prop = test.str_props[Uri_PROPERTY_USER_INFO];
1038             hr = IUri_GetUserInfo(uri, &received);
1039             if(prop.todo) {
1040                 todo_wine {
1041                     ok(hr == prop.expected, "Error: GetUserInfo returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
1042                             hr, prop.expected, i);
1043                 }
1044                 todo_wine {
1045                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
1046                             prop.value, wine_dbgstr_w(received), i);
1047                 }
1048             } else {
1049                 ok(hr == prop.expected, "Error: GetUserInfo returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
1050                         hr, prop.expected, i);
1051                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
1052                         prop.value, wine_dbgstr_w(received), i);
1053             }
1054             SysFreeString(received);
1055             received = NULL;
1056
1057             /* GetUserName() tests. */
1058             prop = test.str_props[Uri_PROPERTY_USER_NAME];
1059             hr = IUri_GetUserName(uri, &received);
1060             if(prop.todo) {
1061                 todo_wine {
1062                     ok(hr == prop.expected, "Error: GetUserName returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
1063                             hr, prop.expected, i);
1064                 }
1065                 todo_wine {
1066                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
1067                             prop.value, wine_dbgstr_w(received), i);
1068                 }
1069             } else {
1070                 ok(hr == prop.expected, "Error: GetUserName returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
1071                         hr, prop.expected, i);
1072                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
1073                         prop.value, wine_dbgstr_w(received), i);
1074             }
1075             SysFreeString(received);
1076         }
1077
1078         if(uri) IUri_Release(uri);
1079
1080         heap_free(uriW);
1081     }
1082 }
1083
1084 static void test_IUri_GetDwordProperties(void) {
1085     IUri *uri = NULL;
1086     HRESULT hr;
1087     DWORD i;
1088
1089     /* Make sure all the 'Get*' dword property functions handle invalid args correctly. */
1090     hr = pCreateUri(http_urlW, 0, 0, &uri);
1091     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
1092     if(SUCCEEDED(hr)) {
1093         hr = IUri_GetHostType(uri, NULL);
1094         ok(hr == E_INVALIDARG, "Error: GetHostType returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
1095
1096         hr = IUri_GetPort(uri, NULL);
1097         ok(hr == E_INVALIDARG, "Error: GetPort returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
1098
1099         hr = IUri_GetScheme(uri, NULL);
1100         ok(hr == E_INVALIDARG, "Error: GetScheme returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
1101
1102         hr = IUri_GetZone(uri, NULL);
1103         ok(hr == E_INVALIDARG, "Error: GetZone returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
1104     }
1105     if(uri) IUri_Release(uri);
1106
1107     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
1108         uri_properties test = uri_tests[i];
1109         LPWSTR uriW;
1110         uri = NULL;
1111
1112         uriW = a2w(test.uri);
1113         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
1114         if(test.create_todo) {
1115             todo_wine {
1116                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
1117                         hr, test.create_expected, i);
1118             }
1119         } else {
1120             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
1121                     hr, test.create_expected, i);
1122         }
1123
1124         if(SUCCEEDED(hr)) {
1125             uri_dword_property prop;
1126             DWORD received;
1127
1128             /* Assign an insane value so tests don't accidentally pass when
1129              * they shouldn't!
1130              */
1131             received = -9999999;
1132
1133             /* GetHostType() tests. */
1134             prop = test.dword_props[Uri_PROPERTY_HOST_TYPE-Uri_PROPERTY_DWORD_START];
1135             hr = IUri_GetHostType(uri, &received);
1136             if(prop.todo) {
1137                 todo_wine {
1138                     ok(hr == prop.expected, "Error: GetHostType returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
1139                             hr, prop.expected, i);
1140                 }
1141                 todo_wine {
1142                     ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
1143                 }
1144             } else {
1145                 ok(hr == prop.expected, "Error: GetHostType returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
1146                         hr, prop.expected, i);
1147                 ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
1148             }
1149             received = -9999999;
1150
1151             /* GetPort() tests. */
1152             prop = test.dword_props[Uri_PROPERTY_PORT-Uri_PROPERTY_DWORD_START];
1153             hr = IUri_GetPort(uri, &received);
1154             if(prop.todo) {
1155                 todo_wine {
1156                     ok(hr == prop.expected, "Error: GetPort returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
1157                             hr, prop.expected, i);
1158                 }
1159                 todo_wine {
1160                     ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
1161                 }
1162             } else {
1163                 ok(hr == prop.expected, "Error: GetPort returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
1164                         hr, prop.expected, i);
1165                 ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
1166             }
1167             received = -9999999;
1168
1169             /* GetScheme() tests. */
1170             prop = test.dword_props[Uri_PROPERTY_SCHEME-Uri_PROPERTY_DWORD_START];
1171             hr = IUri_GetScheme(uri, &received);
1172             if(prop.todo) {
1173                 todo_wine {
1174                     ok(hr == prop.expected, "Error: GetScheme returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
1175                             hr, prop.expected, i);
1176                 }
1177                 todo_wine {
1178                     ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
1179                 }
1180             } else {
1181                 ok(hr == prop.expected, "Error: GetScheme returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
1182                         hr, prop.expected, i);
1183                 ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
1184             }
1185             received = -9999999;
1186
1187             /* GetZone() tests. */
1188             prop = test.dword_props[Uri_PROPERTY_ZONE-Uri_PROPERTY_DWORD_START];
1189             hr = IUri_GetZone(uri, &received);
1190             if(prop.todo) {
1191                 todo_wine {
1192                     ok(hr == prop.expected, "Error: GetZone returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
1193                             hr, prop.expected, i);
1194                 }
1195                 todo_wine {
1196                     ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
1197                 }
1198             } else {
1199                 ok(hr == prop.expected, "Error: GetZone returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
1200                         hr, prop.expected, i);
1201                 ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
1202             }
1203         }
1204
1205         if(uri) IUri_Release(uri);
1206
1207         heap_free(uriW);
1208     }
1209 }
1210
1211 static void test_IUri_GetPropertyLength(void) {
1212     IUri *uri = NULL;
1213     HRESULT hr;
1214     DWORD i;
1215
1216     /* Make sure it handles invalid args correctly. */
1217     hr = pCreateUri(http_urlW, 0, 0, &uri);
1218     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
1219     if(SUCCEEDED(hr)) {
1220         DWORD received = 0xdeadbeef;
1221
1222         hr = IUri_GetPropertyLength(uri, Uri_PROPERTY_STRING_START, NULL, 0);
1223         ok(hr == E_INVALIDARG, "Error: GetPropertyLength returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
1224
1225         hr = IUri_GetPropertyLength(uri, Uri_PROPERTY_DWORD_START, &received, 0);
1226         ok(hr == E_INVALIDARG, "Error: GetPropertyLength return 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
1227         ok(received == 0xdeadbeef, "Error: Expected 0xdeadbeef but got 0x%08x.\n", received);
1228     }
1229     if(uri) IUri_Release(uri);
1230
1231     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
1232         uri_properties test = uri_tests[i];
1233         LPWSTR uriW;
1234         uri = NULL;
1235
1236         uriW = a2w(test.uri);
1237         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
1238         if(test.create_todo) {
1239             todo_wine {
1240                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
1241                         hr, test.create_expected, i);
1242             }
1243         } else {
1244             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_test[%d].\n",
1245                     hr, test.create_expected, i);
1246         }
1247
1248         if(SUCCEEDED(hr)) {
1249             DWORD j;
1250
1251             for(j = Uri_PROPERTY_STRING_START; j <= Uri_PROPERTY_STRING_LAST; ++j) {
1252                 DWORD expectedLen, receivedLen;
1253                 uri_str_property prop = test.str_props[j];
1254
1255                 expectedLen = lstrlen(prop.value);
1256
1257                 /* This won't be necessary once GetPropertyLength is implemented. */
1258                 receivedLen = -1;
1259
1260                 hr = IUri_GetPropertyLength(uri, j, &receivedLen, 0);
1261                 if(prop.todo) {
1262                     todo_wine {
1263                         ok(hr == prop.expected, "Error: GetPropertyLength returned 0x%08x, expected 0x%08x on uri_tests[%d].str_props[%d].\n",
1264                                 hr, prop.expected, i, j);
1265                     }
1266                     todo_wine {
1267                         ok(receivedLen == expectedLen, "Error: Expected a length of %d but got %d on uri_tests[%d].str_props[%d].\n",
1268                                 expectedLen, receivedLen, i, j);
1269                     }
1270                 } else {
1271                     ok(hr == prop.expected, "Error: GetPropertyLength returned 0x%08x, expected 0x%08x on uri_tests[%d].str_props[%d].\n",
1272                             hr, prop.expected, i, j);
1273                     ok(receivedLen == expectedLen, "Error: Expected a length of %d but got %d on uri_tests[%d].str_props[%d].\n",
1274                             expectedLen, receivedLen, i, j);
1275                 }
1276             }
1277         }
1278
1279         if(uri) IUri_Release(uri);
1280
1281         heap_free(uriW);
1282     }
1283 }
1284
1285 static void test_IUri_GetProperties(void) {
1286     IUri *uri = NULL;
1287     HRESULT hr;
1288     DWORD i;
1289
1290     hr = pCreateUri(http_urlW, 0, 0, &uri);
1291     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
1292     if(SUCCEEDED(hr)) {
1293         hr = IUri_GetProperties(uri, NULL);
1294         ok(hr == E_INVALIDARG, "Error: GetProperties returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
1295     }
1296     if(uri) IUri_Release(uri);
1297
1298     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
1299         uri_properties test = uri_tests[i];
1300         LPWSTR uriW;
1301         uri = NULL;
1302
1303         uriW = a2w(test.uri);
1304         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
1305         if(test.create_todo) {
1306             todo_wine {
1307                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, test.create_expected);
1308             }
1309         } else {
1310             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, test.create_expected);
1311         }
1312
1313         if(SUCCEEDED(hr)) {
1314             DWORD received = 0;
1315             DWORD j;
1316
1317             hr = IUri_GetProperties(uri, &received);
1318             if(test.props_todo) {
1319                 todo_wine {
1320                     ok(hr == S_OK, "Error: GetProperties returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
1321                 }
1322             } else {
1323                 ok(hr == S_OK, "Error: GetProperties returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
1324             }
1325
1326             for(j = 0; j <= Uri_PROPERTY_DWORD_LAST; ++j) {
1327                 /* (1 << j) converts a Uri_PROPERTY to its corresponding Uri_HAS_* flag mask. */
1328                 if(test.props & (1 << j)) {
1329                     if(test.props_todo) {
1330                         todo_wine {
1331                             ok(received & (1 << j), "Error: Expected flag for property %d on uri_tests[%d].\n", j, i);
1332                         }
1333                     } else {
1334                         ok(received & (1 << j), "Error: Expected flag for property %d on uri_tests[%d].\n", j, i);
1335                     }
1336                 } else {
1337                     /* NOTE: Since received is initialized to 0, this test will always pass while
1338                      * GetProperties is unimplemented.
1339                      */
1340                     ok(!(received & (1 << j)), "Error: Received flag for property %d when not expected on uri_tests[%d].\n", j, i);
1341                 }
1342             }
1343         }
1344
1345         if(uri) IUri_Release(uri);
1346
1347         heap_free(uriW);
1348     }
1349 }
1350
1351 static void test_IUri_HasProperty(void) {
1352     IUri *uri = NULL;
1353     HRESULT hr;
1354     DWORD i;
1355
1356     hr = pCreateUri(http_urlW, 0, 0, &uri);
1357     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
1358     if(SUCCEEDED(hr)) {
1359         hr = IUri_HasProperty(uri, Uri_PROPERTY_RAW_URI, NULL);
1360         ok(hr == E_INVALIDARG, "Error: HasProperty returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
1361     }
1362     if(uri) IUri_Release(uri);
1363
1364     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
1365         uri_properties test = uri_tests[i];
1366         LPWSTR uriW;
1367         uri = NULL;
1368
1369         uriW = a2w(test.uri);
1370
1371         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
1372         if(test.create_todo) {
1373             todo_wine {
1374                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, test.create_expected);
1375             }
1376         } else {
1377             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, test.create_expected);
1378         }
1379
1380         if(SUCCEEDED(hr)) {
1381             DWORD j;
1382
1383             for(j = 0; j <= Uri_PROPERTY_DWORD_LAST; ++j) {
1384                 /* Assign -1, then explicitly test for TRUE or FALSE later. */
1385                 BOOL received = -1;
1386
1387                 hr = IUri_HasProperty(uri, j, &received);
1388                 if(test.props_todo) {
1389                     todo_wine {
1390                         ok(hr == S_OK, "Error: HasProperty returned 0x%08x, expected 0x%08x for property %d on uri_tests[%d].\n",
1391                                 hr, S_OK, j, i);
1392                     }
1393
1394                     /* Check if the property should be true. */
1395                     if(test.props & (1 << j)) {
1396                         todo_wine {
1397                             ok(received == TRUE, "Error: Expected to have property %d on uri_tests[%d].\n", j, i);
1398                         }
1399                     } else {
1400                         todo_wine {
1401                             ok(received == FALSE, "Error: Wasn't expecting to have property %d on uri_tests[%d].\n", j, i);
1402                         }
1403                     }
1404                 } else {
1405                     ok(hr == S_OK, "Error: HasProperty returned 0x%08x, expected 0x%08x for property %d on uri_tests[%d].\n",
1406                             hr, S_OK, j, i);
1407
1408                     if(test.props & (1 << j)) {
1409                         ok(received == TRUE, "Error: Expected to have property %d on uri_tests[%d].\n", j, i);
1410                     } else {
1411                         ok(received == FALSE, "Error: Wasn't expecting to have property %d on uri_tests[%d].\n", j, i);
1412                     }
1413                 }
1414             }
1415         }
1416
1417         if(uri) IUri_Release(uri);
1418
1419         heap_free(uriW);
1420     }
1421 }
1422
1423 static void test_IUri_IsEqual(void) {
1424     IUri *uriA, *uriB;
1425     HRESULT hrA, hrB;
1426     DWORD i;
1427
1428     uriA = uriB = NULL;
1429
1430     /* Make sure IsEqual handles invalid args correctly. */
1431     hrA = pCreateUri(http_urlW, 0, 0, &uriA);
1432     hrB = pCreateUri(http_urlW, 0, 0, &uriB);
1433     ok(hrA == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hrA, S_OK);
1434     ok(hrB == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hrB, S_OK);
1435     if(SUCCEEDED(hrA) && SUCCEEDED(hrB)) {
1436         BOOL equal = -1;
1437         hrA = IUri_IsEqual(uriA, NULL, &equal);
1438         ok(hrA == S_OK, "Error: IsEqual returned 0x%08x, expected 0x%08x.\n", hrA, S_OK);
1439         ok(equal == FALSE, "Error: Expected equal to be FALSE, but was %d instead.\n", equal);
1440
1441         hrA = IUri_IsEqual(uriA, uriB, NULL);
1442         ok(hrA == E_POINTER, "Error: IsEqual returned 0x%08x, expected 0x%08x.\n", hrA, E_POINTER);
1443     }
1444     if(uriA) IUri_Release(uriA);
1445     if(uriB) IUri_Release(uriB);
1446
1447     for(i = 0; i < sizeof(equality_tests)/sizeof(equality_tests[0]); ++i) {
1448         uri_equality test = equality_tests[i];
1449         LPWSTR uriA_W, uriB_W;
1450
1451         uriA = uriB = NULL;
1452
1453         uriA_W = a2w(test.a);
1454         uriB_W = a2w(test.b);
1455
1456         hrA = pCreateUri(uriA_W, test.create_flags_a, 0, &uriA);
1457         if(test.create_todo_a) {
1458             todo_wine {
1459                 ok(hrA == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x on equality_tests[%d].a\n",
1460                         hrA, S_OK, i);
1461             }
1462         } else {
1463             ok(hrA == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x on equality_tests[%d].a\n",
1464                     hrA, S_OK, i);
1465         }
1466
1467         hrB = pCreateUri(uriB_W, test.create_flags_b, 0, &uriB);
1468         if(test.create_todo_b) {
1469             todo_wine {
1470                 ok(hrB == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x on equality_tests[%d].b\n",
1471                         hrB, S_OK, i);
1472             }
1473         } else {
1474             ok(hrB == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x on equality_tests[%d].b\n",
1475                     hrB, S_OK, i);
1476         }
1477
1478         if(SUCCEEDED(hrA) && SUCCEEDED(hrB)) {
1479             BOOL equal = -1;
1480
1481             hrA = IUri_IsEqual(uriA, uriB, &equal);
1482             if(test.todo) {
1483                 todo_wine {
1484                     ok(hrA == S_OK, "Error: IsEqual returned 0x%08x, expected 0x%08x on equality_tests[%d].\n",
1485                             hrA, S_OK, i);
1486                 }
1487                 todo_wine {
1488                     ok(equal == test.equal, "Error: Expected the comparison to be %d on equality_tests[%d].\n", test.equal, i);
1489                 }
1490             } else {
1491                 ok(hrA == S_OK, "Error: IsEqual returned 0x%08x, expected 0x%08x on equality_tests[%d].\n", hrA, S_OK, i);
1492                 ok(equal == test.equal, "Error: Expected the comparison to be %d on equality_tests[%d].\n", test.equal, i);
1493             }
1494         }
1495         if(uriA) IUri_Release(uriA);
1496         if(uriB) IUri_Release(uriB);
1497
1498         heap_free(uriA_W);
1499         heap_free(uriB_W);
1500     }
1501 }
1502
1503 START_TEST(uri) {
1504     HMODULE hurlmon;
1505
1506     hurlmon = GetModuleHandle("urlmon.dll");
1507     pCreateUri = (void*) GetProcAddress(hurlmon, "CreateUri");
1508
1509     if(!pCreateUri) {
1510         win_skip("CreateUri is not present, skipping tests.\n");
1511         return;
1512     }
1513
1514     trace("test CreateUri invalid flags...\n");
1515     test_CreateUri_InvalidFlags();
1516
1517     trace("test CreateUri invalid args...\n");
1518     test_CreateUri_InvalidArgs();
1519
1520     trace("test IUri_GetPropertyBSTR...\n");
1521     test_IUri_GetPropertyBSTR();
1522
1523     trace("test IUri_GetPropertyDWORD...\n");
1524     test_IUri_GetPropertyDWORD();
1525
1526     trace("test IUri_GetStrProperties...\n");
1527     test_IUri_GetStrProperties();
1528
1529     trace("test IUri_GetDwordProperties...\n");
1530     test_IUri_GetDwordProperties();
1531
1532     trace("test IUri_GetPropertyLength...\n");
1533     test_IUri_GetPropertyLength();
1534
1535     trace("test IUri_GetProperties...\n");
1536     test_IUri_GetProperties();
1537
1538     trace("test IUri_HasProperty...\n");
1539     test_IUri_HasProperty();
1540
1541     trace("test IUri_IsEqual...\n");
1542     test_IUri_IsEqual();
1543 }