urlmon/tests: Added test for invalid args to IUri_GetPropertyBSTR and IUri_GetPropert...
[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
82     uri_str_property    str_props[URI_STR_PROPERTY_COUNT];
83     uri_dword_property  dword_props[URI_DWORD_PROPERTY_COUNT];
84 } uri_properties;
85
86 static const uri_properties uri_tests[] = {
87     {   "http://www.winehq.org/tests/../tests/../..", 0, S_OK, FALSE,
88         {
89             {"http://www.winehq.org/",S_OK,TRUE},                       /* ABSOLUTE_URI */
90             {"www.winehq.org",S_OK,TRUE},                               /* AUTHORITY */
91             {"http://www.winehq.org/",S_OK,TRUE},                       /* DISPLAY_URI */
92             {"winehq.org",S_OK,TRUE},                                   /* DOMAIN */
93             {"",S_FALSE,TRUE},                                          /* EXTENSION */
94             {"",S_FALSE,TRUE},                                          /* FRAGMENT */
95             {"www.winehq.org",S_OK,TRUE},                               /* HOST */
96             {"",S_FALSE,TRUE},                                          /* PASSWORD */
97             {"/",S_OK,TRUE},                                            /* PATH */
98             {"/",S_OK,TRUE},                                            /* PATH_AND_QUERY */
99             {"",S_FALSE,TRUE},                                          /* QUERY */
100             {"http://www.winehq.org/tests/../tests/../..",S_OK,TRUE},   /* RAW_URI */
101             {"http",S_OK,TRUE},                                         /* SCHEME_NAME */
102             {"",S_FALSE,TRUE},                                          /* USER_INFO */
103             {"",S_FALSE,TRUE}                                           /* USER_NAME */
104         },
105         {
106             {Uri_HOST_DNS,S_OK,TRUE},                                   /* HOST_TYPE */
107             {80,S_OK,TRUE},                                             /* PORT */
108             {URL_SCHEME_HTTP,S_OK,TRUE},                                /* SCHEME */
109             {URLZONE_INVALID,E_NOTIMPL,FALSE}                           /* ZONE */
110         }
111     },
112     {   "http://winehq.org/tests/.././tests", 0, S_OK, FALSE,
113         {
114             {"http://winehq.org/tests",S_OK,TRUE},
115             {"winehq.org",S_OK,TRUE},
116             {"http://winehq.org/tests",S_OK,TRUE},
117             {"winehq.org",S_OK,TRUE},
118             {"",S_FALSE,TRUE},
119             {"",S_FALSE,TRUE},
120             {"winehq.org",S_OK,TRUE},
121             {"",S_FALSE,TRUE},
122             {"/tests",S_OK,TRUE},
123             {"/tests",S_OK,TRUE},
124             {"",S_FALSE,TRUE},
125             {"http://winehq.org/tests/.././tests",S_OK,TRUE},
126             {"http",S_OK,TRUE},
127             {"",S_FALSE,TRUE},
128             {"",S_FALSE,TRUE}
129         },
130         {
131             {Uri_HOST_DNS,S_OK,TRUE},
132             {80,S_OK,TRUE},
133             {URL_SCHEME_HTTP,S_OK,TRUE},
134             {URLZONE_INVALID,E_NOTIMPL,FALSE}
135         }
136     },
137     {   "HtTp://www.winehq.org/tests/..?query=x&return=y", 0, S_OK, FALSE,
138         {
139             {"http://www.winehq.org/?query=x&return=y",S_OK,TRUE},
140             {"www.winehq.org",S_OK,TRUE},
141             {"http://www.winehq.org/?query=x&return=y",S_OK,TRUE},
142             {"winehq.org",S_OK,TRUE},
143             {"",S_FALSE,TRUE},
144             {"",S_FALSE,TRUE},
145             {"www.winehq.org",S_OK,TRUE},
146             {"",S_FALSE,TRUE},
147             {"/",S_OK,TRUE},
148             {"/?query=x&return=y",S_OK,TRUE},
149             {"?query=x&return=y",S_OK,TRUE},
150             {"HtTp://www.winehq.org/tests/..?query=x&return=y",S_OK,TRUE},
151             {"http",S_OK,TRUE},
152             {"",S_FALSE,TRUE},
153             {"",S_FALSE,TRUE}
154         },
155         {
156             {Uri_HOST_DNS,S_OK,TRUE},
157             {80,S_OK,TRUE},
158             {URL_SCHEME_HTTP,S_OK,TRUE},
159             {URLZONE_INVALID,E_NOTIMPL,FALSE},
160         }
161     },
162     {   "hTTp://us%45r%3Ainfo@examp%4CE.com:80/path/a/b/./c/../%2E%2E/Forbidden'<|> Characters", 0, S_OK, FALSE,
163         {
164             {"http://usEr%3Ainfo@example.com/path/a/Forbidden'%3C%7C%3E%20Characters",S_OK,TRUE},
165             {"usEr%3Ainfo@example.com",S_OK,TRUE},
166             {"http://example.com/path/a/Forbidden'%3C%7C%3E%20Characters",S_OK,TRUE},
167             {"example.com",S_OK,TRUE},
168             {"",S_FALSE,TRUE},
169             {"",S_FALSE,TRUE},
170             {"example.com",S_OK,TRUE},
171             {"",S_FALSE,TRUE},
172             {"/path/a/Forbidden'%3C%7C%3E%20Characters",S_OK,TRUE},
173             {"/path/a/Forbidden'%3C%7C%3E%20Characters",S_OK,TRUE},
174             {"",S_FALSE,TRUE},
175             {"hTTp://us%45r%3Ainfo@examp%4CE.com:80/path/a/b/./c/../%2E%2E/Forbidden'<|> Characters",S_OK,TRUE},
176             {"http",S_OK,TRUE},
177             {"usEr%3Ainfo",S_OK,TRUE},
178             {"usEr%3Ainfo",S_OK,TRUE}
179         },
180         {
181             {Uri_HOST_DNS,S_OK,TRUE},
182             {80,S_OK,TRUE},
183             {URL_SCHEME_HTTP,S_OK,TRUE},
184             {URLZONE_INVALID,E_NOTIMPL,FALSE},
185         }
186     },
187     {   "ftp://winepass:wine@ftp.winehq.org:9999/dir/foo bar.txt", 0, S_OK, FALSE,
188         {
189             {"ftp://winepass:wine@ftp.winehq.org:9999/dir/foo%20bar.txt",S_OK,TRUE},
190             {"winepass:wine@ftp.winehq.org:9999",S_OK,TRUE},
191             {"ftp://ftp.winehq.org:9999/dir/foo%20bar.txt",S_OK,TRUE},
192             {"winehq.org",S_OK,TRUE},
193             {".txt",S_OK,TRUE},
194             {"",S_FALSE,TRUE},
195             {"ftp.winehq.org",S_OK,TRUE},
196             {"wine",S_OK,TRUE},
197             {"/dir/foo%20bar.txt",S_OK,TRUE},
198             {"/dir/foo%20bar.txt",S_OK,TRUE},
199             {"",S_FALSE,TRUE},
200             {"ftp://winepass:wine@ftp.winehq.org:9999/dir/foo bar.txt",S_OK,TRUE},
201             {"ftp",S_OK,TRUE},
202             {"winepass:wine",S_OK,TRUE},
203             {"winepass",S_OK,TRUE}
204         },
205         {
206             {Uri_HOST_DNS,S_OK,TRUE},
207             {9999,S_OK,TRUE},
208             {URL_SCHEME_FTP,S_OK,TRUE},
209             {URLZONE_INVALID,E_NOTIMPL,FALSE}
210         }
211     },
212     {   "file://c:\\tests\\../tests/foo%20bar.mp3", 0, S_OK, FALSE,
213         {
214             {"file:///c:/tests/foo%2520bar.mp3",S_OK,TRUE},
215             {"",S_FALSE,TRUE},
216             {"file:///c:/tests/foo%2520bar.mp3",S_OK,TRUE},
217             {"",S_FALSE,TRUE},
218             {".mp3",S_OK,TRUE},
219             {"",S_FALSE,TRUE},
220             {"",S_FALSE,TRUE},
221             {"",S_FALSE,TRUE},
222             {"/c:/tests/foo%2520bar.mp3",S_OK,TRUE},
223             {"/c:/tests/foo%2520bar.mp3",S_OK,TRUE},
224             {"",S_FALSE,TRUE},
225             {"file://c:\\tests\\../tests/foo%20bar.mp3",S_OK,TRUE},
226             {"file",S_OK,TRUE},
227             {"",S_FALSE,TRUE},
228             {"",S_FALSE,TRUE}
229         },
230         {
231             {Uri_HOST_UNKNOWN,S_OK,TRUE},
232             {0,S_FALSE,TRUE},
233             {URL_SCHEME_FILE,S_OK,TRUE},
234             {URLZONE_INVALID,E_NOTIMPL,FALSE}
235         }
236     },
237     {   "FILE://localhost/test dir\\../tests/test%20file.README.txt", 0, S_OK, FALSE,
238         {
239             {"file:///tests/test%20file.README.txt",S_OK,TRUE},
240             {"",S_FALSE,TRUE},
241             {"file:///tests/test%20file.README.txt",S_OK,TRUE},
242             {"",S_FALSE,TRUE},
243             {".txt",S_OK,TRUE},
244             {"",S_FALSE,TRUE},
245             {"",S_FALSE,TRUE},
246             {"",S_FALSE,TRUE},
247             {"/tests/test%20file.README.txt",S_OK,TRUE},
248             {"/tests/test%20file.README.txt",S_OK,TRUE},
249             {"",S_FALSE,TRUE},
250             {"FILE://localhost/test dir\\../tests/test%20file.README.txt",S_OK,TRUE},
251             {"file",S_OK,TRUE},
252             {"",S_FALSE,TRUE},
253             {"",S_FALSE,TRUE}
254         },
255         {
256             {Uri_HOST_UNKNOWN,S_OK,TRUE},
257             {0,S_FALSE,TRUE},
258             {URL_SCHEME_FILE,S_OK,TRUE},
259             {URLZONE_INVALID,E_NOTIMPL,FALSE}
260         }
261     },
262     {   "urn:nothing:should:happen here", 0, S_OK, FALSE,
263         {
264             {"urn:nothing:should:happen here",S_OK,TRUE},
265             {"",S_FALSE,TRUE},
266             {"urn:nothing:should:happen here",S_OK,TRUE},
267             {"",S_FALSE,TRUE},
268             {"",S_FALSE,TRUE},
269             {"",S_FALSE,TRUE},
270             {"",S_FALSE,TRUE},
271             {"",S_FALSE,TRUE},
272             {"nothing:should:happen here",S_OK,TRUE},
273             {"nothing:should:happen here",S_OK,TRUE},
274             {"",S_FALSE,TRUE},
275             {"urn:nothing:should:happen here",S_OK,TRUE},
276             {"urn",S_OK,TRUE},
277             {"",S_FALSE,TRUE},
278             {"",S_FALSE,TRUE}
279         },
280         {
281             {Uri_HOST_UNKNOWN,S_OK,TRUE},
282             {0,S_FALSE,TRUE},
283             {URL_SCHEME_UNKNOWN,S_OK,TRUE},
284             {URLZONE_INVALID,E_NOTIMPL,FALSE}
285         }
286     },
287     {   "http://127.0.0.1/tests/../test dir/./test.txt", 0, S_OK, FALSE,
288         {
289             {"http://127.0.0.1/test%20dir/test.txt",S_OK,TRUE},
290             {"127.0.0.1",S_OK,TRUE},
291             {"http://127.0.0.1/test%20dir/test.txt",S_OK,TRUE},
292             {"",S_FALSE,TRUE},
293             {".txt",S_OK,TRUE},
294             {"",S_FALSE,TRUE},
295             {"127.0.0.1",S_OK,TRUE},
296             {"",S_FALSE,TRUE},
297             {"/test%20dir/test.txt",S_OK,TRUE},
298             {"/test%20dir/test.txt",S_OK,TRUE},
299             {"",S_FALSE,TRUE},
300             {"http://127.0.0.1/tests/../test dir/./test.txt",S_OK,TRUE},
301             {"http",S_OK,TRUE},
302             {"",S_FALSE,TRUE},
303             {"",S_FALSE,TRUE}
304         },
305         {
306             {Uri_HOST_IPV4,S_OK,TRUE},
307             {80,S_OK,TRUE},
308             {URL_SCHEME_HTTP,S_OK,TRUE},
309             {URLZONE_INVALID,E_NOTIMPL,FALSE}
310         }
311     },
312     {   "http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]", 0, S_OK, FALSE,
313         {
314             {"http://[fedc:ba98:7654:3210:fedc:ba98:7654:3210]/",S_OK,TRUE},
315             {"[fedc:ba98:7654:3210:fedc:ba98:7654:3210]",S_OK,TRUE},
316             {"http://[fedc:ba98:7654:3210:fedc:ba98:7654:3210]/",S_OK,TRUE},
317             {"",S_FALSE,TRUE},
318             {"",S_FALSE,TRUE},
319             {"",S_FALSE,TRUE},
320             {"fedc:ba98:7654:3210:fedc:ba98:7654:3210",S_OK,TRUE},
321             {"",S_FALSE,TRUE},
322             {"/",S_OK,TRUE},
323             {"/",S_OK,TRUE},
324             {"",S_FALSE,TRUE},
325             {"http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]",S_OK,TRUE},
326             {"http",S_OK,TRUE},
327             {"",S_FALSE,TRUE},
328             {"",S_FALSE,TRUE}
329         },
330         {
331             {Uri_HOST_IPV6,S_OK,TRUE},
332             {80,S_OK,TRUE},
333             {URL_SCHEME_HTTP,S_OK,TRUE},
334             {URLZONE_INVALID,E_NOTIMPL,FALSE}
335         }
336     },
337     {   "ftp://[::13.1.68.3]", 0, S_OK, FALSE,
338         {
339             {"ftp://[::13.1.68.3]/",S_OK,TRUE},
340             {"[::13.1.68.3]",S_OK,TRUE},
341             {"ftp://[::13.1.68.3]/",S_OK,TRUE},
342             {"",S_FALSE,TRUE},
343             {"",S_FALSE,TRUE},
344             {"",S_FALSE,TRUE},
345             {"::13.1.68.3",S_OK,TRUE},
346             {"",S_FALSE,TRUE},
347             {"/",S_OK,TRUE},
348             {"/",S_OK,TRUE},
349             {"",S_FALSE,TRUE},
350             {"ftp://[::13.1.68.3]",S_OK,TRUE},
351             {"ftp",S_OK,TRUE},
352             {"",S_FALSE,TRUE},
353             {"",S_FALSE,TRUE}
354         },
355         {
356             {Uri_HOST_IPV6,S_OK,TRUE},
357             {21,S_OK,TRUE},
358             {URL_SCHEME_FTP,S_OK,TRUE},
359             {URLZONE_INVALID,E_NOTIMPL,FALSE}
360         }
361     },
362     {   "http://[FEDC:BA98:0:0:0:0:0:3210]", 0, S_OK, FALSE,
363         {
364             {"http://[fedc:ba98::3210]/",S_OK,TRUE},
365             {"[fedc:ba98::3210]",S_OK,TRUE},
366             {"http://[fedc:ba98::3210]/",S_OK,TRUE},
367             {"",S_FALSE,TRUE},
368             {"",S_FALSE,TRUE},
369             {"",S_FALSE,TRUE},
370             {"fedc:ba98::3210",S_OK,TRUE},
371             {"",S_FALSE,TRUE},
372             {"/",S_OK,TRUE},
373             {"/",S_OK,TRUE},
374             {"",S_FALSE,TRUE},
375             {"http://[FEDC:BA98:0:0:0:0:0:3210]",S_OK,TRUE},
376             {"http",S_OK,TRUE},
377             {"",S_FALSE,TRUE},
378             {"",S_FALSE,TRUE},
379         },
380         {
381             {Uri_HOST_IPV6,S_OK,TRUE},
382             {80,S_OK,TRUE},
383             {URL_SCHEME_HTTP,S_OK,TRUE},
384             {URLZONE_INVALID,E_NOTIMPL,FALSE}
385         }
386     }
387 };
388
389 static inline LPWSTR a2w(LPCSTR str) {
390     LPWSTR ret = NULL;
391
392     if(str) {
393         DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
394         ret = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
395         MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len);
396     }
397
398     return ret;
399 }
400
401 static inline BOOL heap_free(void* mem) {
402     return HeapFree(GetProcessHeap(), 0, mem);
403 }
404
405 static inline DWORD strcmp_aw(LPCSTR strA, LPCWSTR strB) {
406     LPWSTR strAW = a2w(strA);
407     DWORD ret = lstrcmpW(strAW, strB);
408     heap_free(strAW);
409     return ret;
410 }
411
412 /*
413  * Simple tests to make sure the CreateUri function handles invalid flag combinations
414  * correctly.
415  */
416 static void test_CreateUri_InvalidFlags(void) {
417     DWORD i;
418
419     for(i = 0; i < sizeof(invalid_flag_tests)/sizeof(invalid_flag_tests[0]); ++i) {
420         HRESULT hr;
421         IUri *uri = (void*) 0xdeadbeef;
422
423         hr = pCreateUri(http_urlW, invalid_flag_tests[i].flags, 0, &uri);
424         todo_wine {
425             ok(hr == invalid_flag_tests[i].expected, "Error: CreateUri returned 0x%08x, expected 0x%08x, flags=0x%08x\n",
426                     hr, invalid_flag_tests[i].expected, invalid_flag_tests[i].flags);
427         }
428         todo_wine { ok(uri == NULL, "Error: expected the IUri to be NULL, but it was %p instead\n", uri); }
429     }
430 }
431
432 static void test_CreateUri_InvalidArgs(void) {
433     HRESULT hr;
434     IUri *uri = (void*) 0xdeadbeef;
435
436     hr = pCreateUri(http_urlW, 0, 0, NULL);
437     ok(hr == E_INVALIDARG, "Error: CreateUri returned 0x%08x, expected 0x%08x\n", hr, E_INVALIDARG);
438
439     hr = pCreateUri(NULL, 0, 0, &uri);
440     ok(hr == E_INVALIDARG, "Error: CreateUri returned 0x%08x, expected 0x%08x\n", hr, E_INVALIDARG);
441     ok(uri == NULL, "Error: Expected the IUri to be NULL, but it was %p instead\n", uri);
442 }
443
444 static void test_IUri_GetPropertyBSTR(void) {
445     IUri *uri = NULL;
446     HRESULT hr;
447     DWORD i;
448
449     /* Make sure GetPropertyBSTR handles invalid args correctly. */
450     hr = pCreateUri(http_urlW, 0, 0, &uri);
451     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
452     if(SUCCEEDED(hr)) {
453         BSTR received = NULL;
454
455         hr = IUri_GetPropertyBSTR(uri, Uri_PROPERTY_RAW_URI, NULL, 0);
456         ok(hr == E_POINTER, "Error: GetPropertyBSTR returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
457
458         /* Make sure it handles a invalid Uri_PROPERTY's correctly. */
459         hr = IUri_GetPropertyBSTR(uri, Uri_PROPERTY_PORT, &received, 0);
460         ok(hr == S_OK, "Error: GetPropertyBSTR returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
461         ok(received != NULL, "Error: Expected the string not to be NULL.\n");
462         ok(!SysStringLen(received), "Error: Expected the string to be of len=0 but it was %d instead.\n", SysStringLen(received));
463         SysFreeString(received);
464
465         /* Make sure it handles the ZONE property correctly. */
466         received = NULL;
467         hr = IUri_GetPropertyBSTR(uri, Uri_PROPERTY_ZONE, &received, 0);
468         ok(hr == S_FALSE, "Error: GetPropertyBSTR returned 0x%08x, expected 0x%08x.\n", hr, S_FALSE);
469         ok(received != NULL, "Error: Expected the string not to be NULL.\n");
470         ok(!SysStringLen(received), "Error: Expected the string to be of len=0 but it was %d instead.\n", SysStringLen(received));
471         SysFreeString(received);
472     }
473     if(uri) IUri_Release(uri);
474
475     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
476         uri_properties test = uri_tests[i];
477         LPWSTR uriW;
478         uri = NULL;
479
480         uriW = a2w(test.uri);
481         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
482         if(test.create_todo) {
483             todo_wine {
484                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x. Failed on uri_tests[%d].\n",
485                         hr, test.create_expected, i);
486             }
487         } else {
488             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x. Failed on uri_tests[%d].\n",
489                     hr, test.create_expected, i);
490         }
491
492         if(SUCCEEDED(hr)) {
493             DWORD j;
494
495             /* Checks all the string properties of the uri. */
496             for(j = Uri_PROPERTY_STRING_START; j <= Uri_PROPERTY_STRING_LAST; ++j) {
497                 BSTR received = NULL;
498                 uri_str_property prop = test.str_props[j];
499
500                 hr = IUri_GetPropertyBSTR(uri, j, &received, 0);
501                 if(prop.todo) {
502                     todo_wine {
503                         ok(hr == prop.expected, "GetPropertyBSTR returned 0x%08x, expected 0x%08x. On uri_tests[%d].str_props[%d].\n",
504                                 hr, prop.expected, i, j);
505                     }
506                     todo_wine {
507                         ok(!strcmp_aw(prop.value, received), "Expected %s but got %s on uri_tests[%d].str_props[%d].\n",
508                                 prop.value, wine_dbgstr_w(received), i, j);
509                     }
510                 } else {
511                     ok(hr == prop.expected, "GetPropertyBSTR returned 0x%08x, expected 0x%08x. On uri_tests[%d].str_props[%d].\n",
512                             hr, prop.expected, i, j);
513                     ok(!strcmp_aw(prop.value, received), "Expected %s but got %s on uri_tests[%d].str_props[%d].\n",
514                             prop.value, wine_dbgstr_w(received), i, j);
515                 }
516
517                 SysFreeString(received);
518             }
519         }
520
521         if(uri) IUri_Release(uri);
522
523         heap_free(uriW);
524     }
525 }
526
527 static void test_IUri_GetPropertyDWORD(void) {
528     IUri *uri = NULL;
529     HRESULT hr;
530     DWORD i;
531
532     hr = pCreateUri(http_urlW, 0, 0, &uri);
533     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
534     if(SUCCEEDED(hr)) {
535         DWORD received = 0xdeadbeef;
536
537         hr = IUri_GetPropertyDWORD(uri, Uri_PROPERTY_DWORD_START, NULL, 0);
538         ok(hr == E_INVALIDARG, "Error: GetPropertyDWORD returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
539
540         hr = IUri_GetPropertyDWORD(uri, Uri_PROPERTY_ABSOLUTE_URI, &received, 0);
541         ok(hr == E_INVALIDARG, "Error: GetPropertyDWORD returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
542         ok(received == 0, "Error: Expected received=%d but instead received=%d.\n", 0, received);
543     }
544     if(uri) IUri_Release(uri);
545
546     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
547         uri_properties test = uri_tests[i];
548         LPWSTR uriW;
549         uri = NULL;
550
551         uriW = a2w(test.uri);
552         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
553         if(test.create_todo) {
554             todo_wine {
555                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x. Failed on uri_tests[%d].\n",
556                         hr, test.create_expected, i);
557             }
558         } else {
559             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x. Failed on uri_tests[%d].\n",
560                     hr, test.create_expected, i);
561         }
562
563         if(SUCCEEDED(hr)) {
564             DWORD j;
565
566             /* Checks all the DWORD properties of the uri. */
567             for(j = 0; j < sizeof(test.dword_props)/sizeof(test.dword_props[0]); ++j) {
568                 DWORD received;
569                 uri_dword_property prop = test.dword_props[j];
570
571                 hr = IUri_GetPropertyDWORD(uri, j+Uri_PROPERTY_DWORD_START, &received, 0);
572                 if(prop.todo) {
573                     todo_wine {
574                         ok(hr == prop.expected, "GetPropertyDWORD returned 0x%08x, expected 0x%08x. On uri_tests[%d].dword_props[%d].\n",
575                                 hr, prop.expected, i, j);
576                     }
577                     todo_wine {
578                         ok(prop.value == received, "Expected %d but got %d on uri_tests[%d].dword_props[%d].\n",
579                                 prop.value, received, i, j);
580                     }
581                 } else {
582                     ok(hr == prop.expected, "GetPropertyDWORD returned 0x%08x, expected 0x%08x. On uri_tests[%d].dword_props[%d].\n",
583                             hr, prop.expected, i, j);
584                     ok(prop.value == received, "Expected %d but got %d on uri_tests[%d].dword_props[%d].\n",
585                             prop.value, received, i, j);
586                 }
587             }
588         }
589
590         if(uri) IUri_Release(uri);
591
592         heap_free(uriW);
593     }
594 }
595
596 /* Tests all the 'Get*' property functions which deal with strings. */
597 static void test_IUri_GetStrProperties(void) {
598     IUri *uri = NULL;
599     HRESULT hr;
600     DWORD i;
601
602     /* Make sure all the 'Get*' string property functions handle invalid args correctly. */
603     hr = pCreateUri(http_urlW, 0, 0, &uri);
604     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
605     if(SUCCEEDED(hr)) {
606         hr = IUri_GetAbsoluteUri(uri, NULL);
607         ok(hr == E_POINTER, "Error: GetAbsoluteUri returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
608
609         hr = IUri_GetAuthority(uri, NULL);
610         ok(hr == E_POINTER, "Error: GetAuthority returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
611
612         hr = IUri_GetDisplayUri(uri, NULL);
613         ok(hr == E_POINTER, "Error: GetDisplayUri returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
614
615         hr = IUri_GetDomain(uri, NULL);
616         ok(hr == E_POINTER, "Error: GetDomain returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
617
618         hr = IUri_GetExtension(uri, NULL);
619         ok(hr == E_POINTER, "Error: GetExtension returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
620
621         hr = IUri_GetFragment(uri, NULL);
622         ok(hr == E_POINTER, "Error: GetFragment returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
623
624         hr = IUri_GetPassword(uri, NULL);
625         ok(hr == E_POINTER, "Error: GetPassword returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
626
627         hr = IUri_GetPath(uri, NULL);
628         ok(hr == E_POINTER, "Error: GetPath returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
629
630         hr = IUri_GetPathAndQuery(uri, NULL);
631         ok(hr == E_POINTER, "Error: GetPathAndQuery returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
632
633         hr = IUri_GetQuery(uri, NULL);
634         ok(hr == E_POINTER, "Error: GetQuery returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
635
636         hr = IUri_GetRawUri(uri, NULL);
637         ok(hr == E_POINTER, "Error: GetRawUri returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
638
639         hr = IUri_GetSchemeName(uri, NULL);
640         ok(hr == E_POINTER, "Error: GetSchemeName returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
641
642         hr = IUri_GetUserInfo(uri, NULL);
643         ok(hr == E_POINTER, "Error: GetUserInfo returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
644
645         hr = IUri_GetUserName(uri, NULL);
646         ok(hr == E_POINTER, "Error: GetUserName returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
647     }
648     if(uri) IUri_Release(uri);
649
650     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
651         uri_properties test = uri_tests[i];
652         LPWSTR uriW;
653         uri = NULL;
654
655         uriW = a2w(test.uri);
656         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
657         if(test.create_todo) {
658             todo_wine {
659                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
660                         hr, test.create_expected, i);
661             }
662         } else {
663             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
664                     hr, test.create_expected, i);
665         }
666
667         if(SUCCEEDED(hr)) {
668             uri_str_property prop;
669             BSTR received = NULL;
670
671             /* GetAbsoluteUri() tests. */
672             prop = test.str_props[Uri_PROPERTY_ABSOLUTE_URI];
673             hr = IUri_GetAbsoluteUri(uri, &received);
674             if(prop.todo) {
675                 todo_wine {
676                     ok(hr == prop.expected, "Error: GetAbsoluteUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
677                             hr, prop.expected, i);
678                 }
679                 todo_wine {
680                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
681                             prop.value, wine_dbgstr_w(received), i);
682                 }
683             } else {
684                 ok(hr == prop.expected, "Error: GetAbsoluteUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
685                         hr, prop.expected, i);
686                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
687                         prop.value, wine_dbgstr_w(received), i);
688             }
689             SysFreeString(received);
690             received = NULL;
691
692             /* GetAuthority() tests. */
693             prop = test.str_props[Uri_PROPERTY_AUTHORITY];
694             hr = IUri_GetAuthority(uri, &received);
695             if(prop.todo) {
696                 todo_wine {
697                     ok(hr == prop.expected, "Error: GetAuthority returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
698                             hr, prop.expected, i);
699                 }
700                 todo_wine {
701                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
702                             prop.value, wine_dbgstr_w(received), i);
703                 }
704             } else {
705                 ok(hr == prop.expected, "Error: GetAuthority returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
706                         hr, prop.expected, i);
707                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
708                         prop.value, wine_dbgstr_w(received), i);
709             }
710             SysFreeString(received);
711             received = NULL;
712
713             /* GetDisplayUri() tests. */
714             prop = test.str_props[Uri_PROPERTY_DISPLAY_URI];
715             hr = IUri_GetDisplayUri(uri, &received);
716             if(prop.todo) {
717                 todo_wine {
718                     ok(hr == prop.expected, "Error: GetDisplayUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
719                             hr, prop.expected, i);
720                 }
721                 todo_wine {
722                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_test[%d].\n",
723                             prop.value, wine_dbgstr_w(received), i);
724                 }
725             } else {
726                 ok(hr == prop.expected, "Error: GetDisplayUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
727                         hr, prop.expected, i);
728                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
729                         prop.value, wine_dbgstr_w(received), i);
730             }
731             SysFreeString(received);
732             received = NULL;
733
734             /* GetDomain() tests. */
735             prop = test.str_props[Uri_PROPERTY_DOMAIN];
736             hr = IUri_GetDomain(uri, &received);
737             if(prop.todo) {
738                 todo_wine {
739                     ok(hr == prop.expected, "Error: GetDomain returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
740                             hr, prop.expected, i);
741                 }
742                 todo_wine {
743                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
744                             prop.value, wine_dbgstr_w(received), i);
745                 }
746             } else {
747                 ok(hr == prop.expected, "Error: GetDomain returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
748                         hr, prop.expected, i);
749                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
750                         prop.value, wine_dbgstr_w(received), i);
751             }
752             SysFreeString(received);
753             received = NULL;
754
755             /* GetExtension() tests. */
756             prop = test.str_props[Uri_PROPERTY_EXTENSION];
757             hr = IUri_GetExtension(uri, &received);
758             if(prop.todo) {
759                 todo_wine {
760                     ok(hr == prop.expected, "Error: GetExtension returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
761                             hr, prop.expected, i);
762                 }
763                 todo_wine {
764                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
765                             prop.value, wine_dbgstr_w(received), i);
766                 }
767             } else {
768                 ok(hr == prop.expected, "Error: GetExtension returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
769                         hr, prop.expected, i);
770                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
771                         prop.value, wine_dbgstr_w(received), i);
772             }
773             SysFreeString(received);
774             received = NULL;
775
776             /* GetFragment() tests. */
777             prop = test.str_props[Uri_PROPERTY_FRAGMENT];
778             hr = IUri_GetFragment(uri, &received);
779             if(prop.todo) {
780                 todo_wine {
781                     ok(hr == prop.expected, "Error: GetFragment returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
782                             hr, prop.expected, i);
783                 }
784                 todo_wine {
785                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
786                             prop.value, wine_dbgstr_w(received), i);
787                 }
788             } else {
789                 ok(hr == prop.expected, "Error: GetFragment returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
790                         hr, prop.expected, i);
791                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
792                         prop.value, wine_dbgstr_w(received), i);
793             }
794             SysFreeString(received);
795             received = NULL;
796
797             /* GetPassword() tests. */
798             prop = test.str_props[Uri_PROPERTY_PASSWORD];
799             hr = IUri_GetPassword(uri, &received);
800             if(prop.todo) {
801                 todo_wine {
802                     ok(hr == prop.expected, "Error: GetPassword returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
803                             hr, prop.expected, i);
804                 }
805                 todo_wine {
806                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
807                             prop.value, wine_dbgstr_w(received), i);
808                 }
809             } else {
810                 ok(hr == prop.expected, "Error: GetPassword returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
811                         hr, prop.expected, i);
812                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
813                         prop.value, wine_dbgstr_w(received), i);
814             }
815             SysFreeString(received);
816             received = NULL;
817
818             /* GetPath() tests. */
819             prop = test.str_props[Uri_PROPERTY_PATH];
820             hr = IUri_GetPath(uri, &received);
821             if(prop.todo) {
822                 todo_wine {
823                     ok(hr == prop.expected, "Error: GetPath returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
824                             hr, prop.expected, i);
825                 }
826                 todo_wine {
827                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
828                             prop.value, wine_dbgstr_w(received), i);
829                 }
830             } else {
831                 ok(hr == prop.expected, "Error: GetPath returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
832                         hr, prop.expected, i);
833                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
834                         prop.value, wine_dbgstr_w(received), i);
835             }
836             SysFreeString(received);
837             received = NULL;
838
839             /* GetPathAndQuery() tests. */
840             prop = test.str_props[Uri_PROPERTY_PATH_AND_QUERY];
841             hr = IUri_GetPathAndQuery(uri, &received);
842             if(prop.todo) {
843                 todo_wine {
844                     ok(hr == prop.expected, "Error: GetPathAndQuery returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
845                             hr, prop.expected, i);
846                 }
847                 todo_wine {
848                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
849                             prop.value, wine_dbgstr_w(received), i);
850                 }
851             } else {
852                 ok(hr == prop.expected, "Error: GetPathAndQuery returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
853                         hr, prop.expected, i);
854                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
855                         prop.value, wine_dbgstr_w(received), i);
856             }
857             SysFreeString(received);
858             received = NULL;
859
860             /* GetQuery() tests. */
861             prop = test.str_props[Uri_PROPERTY_QUERY];
862             hr = IUri_GetQuery(uri, &received);
863             if(prop.todo) {
864                 todo_wine {
865                     ok(hr == prop.expected, "Error: GetQuery returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
866                             hr, prop.expected, i);
867                 }
868                 todo_wine {
869                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
870                             prop.value, wine_dbgstr_w(received), i);
871                 }
872             } else {
873                 ok(hr == prop.expected, "Error: GetQuery returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
874                         hr, prop.expected, i);
875                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
876                         prop.value, wine_dbgstr_w(received), i);
877             }
878             SysFreeString(received);
879             received = NULL;
880
881             /* GetRawUri() tests. */
882             prop = test.str_props[Uri_PROPERTY_RAW_URI];
883             hr = IUri_GetRawUri(uri, &received);
884             if(prop.todo) {
885                 todo_wine {
886                     ok(hr == prop.expected, "Error: GetRawUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
887                             hr, prop.expected, i);
888                 }
889                 todo_wine {
890                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
891                             prop.value, wine_dbgstr_w(received), i);
892                 }
893             } else {
894                 ok(hr == prop.expected, "Error: GetRawUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
895                         hr, prop.expected, i);
896                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
897                         prop.value, wine_dbgstr_w(received), i);
898             }
899             SysFreeString(received);
900             received = NULL;
901
902             /* GetSchemeName() tests. */
903             prop = test.str_props[Uri_PROPERTY_SCHEME_NAME];
904             hr = IUri_GetSchemeName(uri, &received);
905             if(prop.todo) {
906                 todo_wine {
907                     ok(hr == prop.expected, "Error: GetSchemeName returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
908                             hr, prop.expected, i);
909                 }
910                 todo_wine {
911                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
912                             prop.value, wine_dbgstr_w(received), i);
913                 }
914             } else {
915                 ok(hr == prop.expected, "Error: GetSchemeName returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
916                         hr, prop.expected, i);
917                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
918                         prop.value, wine_dbgstr_w(received), i);
919             }
920             SysFreeString(received);
921             received = NULL;
922
923             /* GetUserInfo() tests. */
924             prop = test.str_props[Uri_PROPERTY_USER_INFO];
925             hr = IUri_GetUserInfo(uri, &received);
926             if(prop.todo) {
927                 todo_wine {
928                     ok(hr == prop.expected, "Error: GetUserInfo returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
929                             hr, prop.expected, i);
930                 }
931                 todo_wine {
932                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
933                             prop.value, wine_dbgstr_w(received), i);
934                 }
935             } else {
936                 ok(hr == prop.expected, "Error: GetUserInfo returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
937                         hr, prop.expected, i);
938                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
939                         prop.value, wine_dbgstr_w(received), i);
940             }
941             SysFreeString(received);
942             received = NULL;
943
944             /* GetUserName() tests. */
945             prop = test.str_props[Uri_PROPERTY_USER_NAME];
946             hr = IUri_GetUserName(uri, &received);
947             if(prop.todo) {
948                 todo_wine {
949                     ok(hr == prop.expected, "Error: GetUserName returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
950                             hr, prop.expected, i);
951                 }
952                 todo_wine {
953                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
954                             prop.value, wine_dbgstr_w(received), i);
955                 }
956             } else {
957                 ok(hr == prop.expected, "Error: GetUserName returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
958                         hr, prop.expected, i);
959                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
960                         prop.value, wine_dbgstr_w(received), i);
961             }
962             SysFreeString(received);
963         }
964
965         if(uri) IUri_Release(uri);
966
967         heap_free(uriW);
968     }
969 }
970
971 static void test_IUri_GetDwordProperties(void) {
972     IUri *uri = NULL;
973     HRESULT hr;
974     DWORD i;
975
976     /* Make sure all the 'Get*' dword property functions handle invalid args correctly. */
977     hr = pCreateUri(http_urlW, 0, 0, &uri);
978     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
979     if(SUCCEEDED(hr)) {
980         hr = IUri_GetHostType(uri, NULL);
981         ok(hr == E_INVALIDARG, "Error: GetHostType returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
982
983         hr = IUri_GetPort(uri, NULL);
984         ok(hr == E_INVALIDARG, "Error: GetPort returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
985
986         hr = IUri_GetScheme(uri, NULL);
987         ok(hr == E_INVALIDARG, "Error: GetScheme returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
988
989         hr = IUri_GetZone(uri, NULL);
990         ok(hr == E_INVALIDARG, "Error: GetZone returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
991     }
992     if(uri) IUri_Release(uri);
993
994     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
995         uri_properties test = uri_tests[i];
996         LPWSTR uriW;
997         uri = NULL;
998
999         uriW = a2w(test.uri);
1000         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
1001         if(test.create_todo) {
1002             todo_wine {
1003                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
1004                         hr, test.create_expected, i);
1005             }
1006         } else {
1007             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
1008                     hr, test.create_expected, i);
1009         }
1010
1011         if(SUCCEEDED(hr)) {
1012             uri_dword_property prop;
1013             DWORD received;
1014
1015             /* Assign an insane value so tests don't accidentally pass when
1016              * they shouldn't!
1017              */
1018             received = -9999999;
1019
1020             /* GetHostType() tests. */
1021             prop = test.dword_props[Uri_PROPERTY_HOST_TYPE-Uri_PROPERTY_DWORD_START];
1022             hr = IUri_GetHostType(uri, &received);
1023             if(prop.todo) {
1024                 todo_wine {
1025                     ok(hr == prop.expected, "Error: GetHostType returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
1026                             hr, prop.expected, i);
1027                 }
1028                 todo_wine {
1029                     ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
1030                 }
1031             } else {
1032                 ok(hr == prop.expected, "Error: GetHostType returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
1033                         hr, prop.expected, i);
1034                 ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
1035             }
1036             received = -9999999;
1037
1038             /* GetPort() tests. */
1039             prop = test.dword_props[Uri_PROPERTY_PORT-Uri_PROPERTY_DWORD_START];
1040             hr = IUri_GetPort(uri, &received);
1041             if(prop.todo) {
1042                 todo_wine {
1043                     ok(hr == prop.expected, "Error: GetPort returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
1044                             hr, prop.expected, i);
1045                 }
1046                 todo_wine {
1047                     ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
1048                 }
1049             } else {
1050                 ok(hr == prop.expected, "Error: GetPort returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
1051                         hr, prop.expected, i);
1052                 ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
1053             }
1054             received = -9999999;
1055
1056             /* GetScheme() tests. */
1057             prop = test.dword_props[Uri_PROPERTY_SCHEME-Uri_PROPERTY_DWORD_START];
1058             hr = IUri_GetScheme(uri, &received);
1059             if(prop.todo) {
1060                 todo_wine {
1061                     ok(hr == prop.expected, "Error: GetScheme returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
1062                             hr, prop.expected, i);
1063                 }
1064                 todo_wine {
1065                     ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
1066                 }
1067             } else {
1068                 ok(hr == prop.expected, "Error: GetScheme returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
1069                         hr, prop.expected, i);
1070                 ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
1071             }
1072             received = -9999999;
1073
1074             /* GetZone() tests. */
1075             prop = test.dword_props[Uri_PROPERTY_ZONE-Uri_PROPERTY_DWORD_START];
1076             hr = IUri_GetZone(uri, &received);
1077             if(prop.todo) {
1078                 todo_wine {
1079                     ok(hr == prop.expected, "Error: GetZone returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
1080                             hr, prop.expected, i);
1081                 }
1082                 todo_wine {
1083                     ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
1084                 }
1085             } else {
1086                 ok(hr == prop.expected, "Error: GetZone returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
1087                         hr, prop.expected, i);
1088                 ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
1089             }
1090         }
1091
1092         if(uri) IUri_Release(uri);
1093
1094         heap_free(uriW);
1095     }
1096 }
1097
1098 static void test_IUri_GetPropertyLength(void) {
1099     IUri *uri = NULL;
1100     HRESULT hr;
1101     DWORD i;
1102
1103     /* Make sure it handles invalid args correctly. */
1104     hr = pCreateUri(http_urlW, 0, 0, &uri);
1105     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
1106     if(SUCCEEDED(hr)) {
1107         DWORD received = 0xdeadbeef;
1108
1109         hr = IUri_GetPropertyLength(uri, Uri_PROPERTY_STRING_START, NULL, 0);
1110         ok(hr == E_INVALIDARG, "Error: GetPropertyLength returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
1111
1112         hr = IUri_GetPropertyLength(uri, Uri_PROPERTY_DWORD_START, &received, 0);
1113         ok(hr == E_INVALIDARG, "Error: GetPropertyLength return 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
1114         ok(received == 0xdeadbeef, "Error: Expected 0xdeadbeef but got 0x%08x.\n", received);
1115     }
1116     if(uri) IUri_Release(uri);
1117
1118     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
1119         uri_properties test = uri_tests[i];
1120         LPWSTR uriW;
1121         uri = NULL;
1122
1123         uriW = a2w(test.uri);
1124         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
1125         if(test.create_todo) {
1126             todo_wine {
1127                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
1128                         hr, test.create_expected, i);
1129             }
1130         } else {
1131             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_test[%d].\n",
1132                     hr, test.create_expected, i);
1133         }
1134
1135         if(SUCCEEDED(hr)) {
1136             DWORD j;
1137
1138             for(j = Uri_PROPERTY_STRING_START; j <= Uri_PROPERTY_STRING_LAST; ++j) {
1139                 DWORD expectedLen, receivedLen;
1140                 uri_str_property prop = test.str_props[j];
1141
1142                 expectedLen = lstrlen(prop.value);
1143
1144                 /* This won't be neccessary once GetPropertyLength is implemented. */
1145                 receivedLen = -1;
1146
1147                 hr = IUri_GetPropertyLength(uri, j, &receivedLen, 0);
1148                 if(prop.todo) {
1149                     todo_wine {
1150                         ok(hr == prop.expected, "Error: GetPropertyLength returned 0x%08x, expected 0x%08x on uri_tests[%d].str_props[%d].\n",
1151                                 hr, prop.expected, i, j);
1152                     }
1153                     todo_wine {
1154                         ok(receivedLen == expectedLen, "Error: Expected a length of %d but got %d on uri_tests[%d].str_props[%d].\n",
1155                                 expectedLen, receivedLen, i, j);
1156                     }
1157                 } else {
1158                     ok(hr == prop.expected, "Error: GetPropertyLength returned 0x%08x, expected 0x%08x on uri_tests[%d].str_props[%d].\n",
1159                             hr, prop.expected, i, j);
1160                     ok(receivedLen == expectedLen, "Error: Expected a length of %d but %d on uri_tests[%d].str_props[%d].\n",
1161                             expectedLen, receivedLen, i, j);
1162                 }
1163             }
1164         }
1165
1166         if(uri) IUri_Release(uri);
1167
1168         heap_free(uriW);
1169     }
1170 }
1171
1172 START_TEST(uri) {
1173     HMODULE hurlmon;
1174
1175     hurlmon = GetModuleHandle("urlmon.dll");
1176     pCreateUri = (void*) GetProcAddress(hurlmon, "CreateUri");
1177
1178     if(!pCreateUri) {
1179         win_skip("CreateUri is not present, skipping tests.\n");
1180         return;
1181     }
1182
1183     trace("test CreateUri invalid flags...\n");
1184     test_CreateUri_InvalidFlags();
1185
1186     trace("test CreateUri invalid args...\n");
1187     test_CreateUri_InvalidArgs();
1188
1189     trace("test IUri_GetPropertyBSTR...\n");
1190     test_IUri_GetPropertyBSTR();
1191
1192     trace("test IUri_GetPropertyDWORD...\n");
1193     test_IUri_GetPropertyDWORD();
1194
1195     trace("test IUri_GetStrProperties...\n");
1196     test_IUri_GetStrProperties();
1197
1198     trace("test IUri_GetDwordProperties...\n");
1199     test_IUri_GetDwordProperties();
1200
1201     trace("test IUri_GetPropertyLength...\n");
1202     test_IUri_GetPropertyLength();
1203 }