urlmon/tests: Added tests for IUri_GetPropertyLength.
[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     DWORD i;
446
447     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
448         uri_properties test = uri_tests[i];
449         HRESULT hr;
450         IUri *uri = NULL;
451         LPWSTR uriW;
452
453         uriW = a2w(test.uri);
454         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
455         if(test.create_todo) {
456             todo_wine {
457                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x. Failed on uri_tests[%d].\n",
458                         hr, test.create_expected, i);
459             }
460         } else {
461             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x. Failed on uri_tests[%d].\n",
462                     hr, test.create_expected, i);
463         }
464
465         if(SUCCEEDED(hr)) {
466             DWORD j;
467
468             /* Checks all the string properties of the uri. */
469             for(j = Uri_PROPERTY_STRING_START; j <= Uri_PROPERTY_STRING_LAST; ++j) {
470                 BSTR received = NULL;
471                 uri_str_property prop = test.str_props[j];
472
473                 hr = IUri_GetPropertyBSTR(uri, j, &received, 0);
474                 if(prop.todo) {
475                     todo_wine {
476                         ok(hr == prop.expected, "GetPropertyBSTR returned 0x%08x, expected 0x%08x. On uri_tests[%d].str_props[%d].\n",
477                                 hr, prop.expected, i, j);
478                     }
479                     todo_wine {
480                         ok(!strcmp_aw(prop.value, received), "Expected %s but got %s on uri_tests[%d].str_props[%d].\n",
481                                 prop.value, wine_dbgstr_w(received), i, j);
482                     }
483                 } else {
484                     ok(hr == prop.expected, "GetPropertyBSTR returned 0x%08x, expected 0x%08x. On uri_tests[%d].str_props[%d].\n",
485                             hr, prop.expected, i, j);
486                     ok(!strcmp_aw(prop.value, received), "Expected %s but got %s on uri_tests[%d].str_props[%d].\n",
487                             prop.value, wine_dbgstr_w(received), i, j);
488                 }
489
490                 SysFreeString(received);
491             }
492         }
493
494         if(uri) IUri_Release(uri);
495
496         heap_free(uriW);
497     }
498 }
499
500 static void test_IUri_GetPropertyDWORD(void) {
501     IUri *uri = NULL;
502     HRESULT hr;
503     DWORD i;
504
505     hr = pCreateUri(http_urlW, 0, 0, &uri);
506     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
507     if(SUCCEEDED(hr)) {
508         hr = IUri_GetPropertyDWORD(uri, Uri_PROPERTY_DWORD_START, NULL, 0);
509         ok(hr == E_INVALIDARG, "Error: GetPropertyDWORD returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
510     }
511     if(uri) IUri_Release(uri);
512
513     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
514         uri_properties test = uri_tests[i];
515         LPWSTR uriW;
516         uri = NULL;
517
518         uriW = a2w(test.uri);
519         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
520         if(test.create_todo) {
521             todo_wine {
522                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x. Failed on uri_tests[%d].\n",
523                         hr, test.create_expected, i);
524             }
525         } else {
526             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x. Failed on uri_tests[%d].\n",
527                     hr, test.create_expected, i);
528         }
529
530         if(SUCCEEDED(hr)) {
531             DWORD j;
532
533             /* Checks all the DWORD properties of the uri. */
534             for(j = 0; j < sizeof(test.dword_props)/sizeof(test.dword_props[0]); ++j) {
535                 DWORD received;
536                 uri_dword_property prop = test.dword_props[j];
537
538                 hr = IUri_GetPropertyDWORD(uri, j+Uri_PROPERTY_DWORD_START, &received, 0);
539                 if(prop.todo) {
540                     todo_wine {
541                         ok(hr == prop.expected, "GetPropertyDWORD returned 0x%08x, expected 0x%08x. On uri_tests[%d].dword_props[%d].\n",
542                                 hr, prop.expected, i, j);
543                     }
544                     todo_wine {
545                         ok(prop.value == received, "Expected %d but got %d on uri_tests[%d].dword_props[%d].\n",
546                                 prop.value, received, i, j);
547                     }
548                 } else {
549                     ok(hr == prop.expected, "GetPropertyDWORD returned 0x%08x, expected 0x%08x. On uri_tests[%d].dword_props[%d].\n",
550                             hr, prop.expected, i, j);
551                     ok(prop.value == received, "Expected %d but got %d on uri_tests[%d].dword_props[%d].\n",
552                             prop.value, received, i, j);
553                 }
554             }
555         }
556
557         if(uri) IUri_Release(uri);
558
559         heap_free(uriW);
560     }
561 }
562
563 /* Tests all the 'Get*' property functions which deal with strings. */
564 static void test_IUri_GetStrProperties(void) {
565     IUri *uri = NULL;
566     HRESULT hr;
567     DWORD i;
568
569     /* Make sure all the 'Get*' string property functions handle invalid args correctly. */
570     hr = pCreateUri(http_urlW, 0, 0, &uri);
571     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
572     if(SUCCEEDED(hr)) {
573         hr = IUri_GetAbsoluteUri(uri, NULL);
574         ok(hr == E_POINTER, "Error: GetAbsoluteUri returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
575
576         hr = IUri_GetAuthority(uri, NULL);
577         ok(hr == E_POINTER, "Error: GetAuthority returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
578
579         hr = IUri_GetDisplayUri(uri, NULL);
580         ok(hr == E_POINTER, "Error: GetDisplayUri returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
581
582         hr = IUri_GetDomain(uri, NULL);
583         ok(hr == E_POINTER, "Error: GetDomain returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
584
585         hr = IUri_GetExtension(uri, NULL);
586         ok(hr == E_POINTER, "Error: GetExtension returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
587
588         hr = IUri_GetFragment(uri, NULL);
589         ok(hr == E_POINTER, "Error: GetFragment returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
590
591         hr = IUri_GetPassword(uri, NULL);
592         ok(hr == E_POINTER, "Error: GetPassword returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
593
594         hr = IUri_GetPath(uri, NULL);
595         ok(hr == E_POINTER, "Error: GetPath returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
596
597         hr = IUri_GetPathAndQuery(uri, NULL);
598         ok(hr == E_POINTER, "Error: GetPathAndQuery returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
599
600         hr = IUri_GetQuery(uri, NULL);
601         ok(hr == E_POINTER, "Error: GetQuery returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
602
603         hr = IUri_GetRawUri(uri, NULL);
604         ok(hr == E_POINTER, "Error: GetRawUri returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
605
606         hr = IUri_GetSchemeName(uri, NULL);
607         ok(hr == E_POINTER, "Error: GetSchemeName returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
608
609         hr = IUri_GetUserInfo(uri, NULL);
610         ok(hr == E_POINTER, "Error: GetUserInfo returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
611
612         hr = IUri_GetUserName(uri, NULL);
613         ok(hr == E_POINTER, "Error: GetUserName returned 0x%08x, expected 0x%08x.\n", hr, E_POINTER);
614     }
615     if(uri) IUri_Release(uri);
616
617     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
618         uri_properties test = uri_tests[i];
619         LPWSTR uriW;
620         uri = NULL;
621
622         uriW = a2w(test.uri);
623         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
624         if(test.create_todo) {
625             todo_wine {
626                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
627                         hr, test.create_expected, i);
628             }
629         } else {
630             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
631                     hr, test.create_expected, i);
632         }
633
634         if(SUCCEEDED(hr)) {
635             uri_str_property prop;
636             BSTR received = NULL;
637
638             /* GetAbsoluteUri() tests. */
639             prop = test.str_props[Uri_PROPERTY_ABSOLUTE_URI];
640             hr = IUri_GetAbsoluteUri(uri, &received);
641             if(prop.todo) {
642                 todo_wine {
643                     ok(hr == prop.expected, "Error: GetAbsoluteUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
644                             hr, prop.expected, i);
645                 }
646                 todo_wine {
647                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
648                             prop.value, wine_dbgstr_w(received), i);
649                 }
650             } else {
651                 ok(hr == prop.expected, "Error: GetAbsoluteUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
652                         hr, prop.expected, i);
653                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
654                         prop.value, wine_dbgstr_w(received), i);
655             }
656             SysFreeString(received);
657             received = NULL;
658
659             /* GetAuthority() tests. */
660             prop = test.str_props[Uri_PROPERTY_AUTHORITY];
661             hr = IUri_GetAuthority(uri, &received);
662             if(prop.todo) {
663                 todo_wine {
664                     ok(hr == prop.expected, "Error: GetAuthority returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
665                             hr, prop.expected, i);
666                 }
667                 todo_wine {
668                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
669                             prop.value, wine_dbgstr_w(received), i);
670                 }
671             } else {
672                 ok(hr == prop.expected, "Error: GetAuthority returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
673                         hr, prop.expected, i);
674                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
675                         prop.value, wine_dbgstr_w(received), i);
676             }
677             SysFreeString(received);
678             received = NULL;
679
680             /* GetDisplayUri() tests. */
681             prop = test.str_props[Uri_PROPERTY_DISPLAY_URI];
682             hr = IUri_GetDisplayUri(uri, &received);
683             if(prop.todo) {
684                 todo_wine {
685                     ok(hr == prop.expected, "Error: GetDisplayUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
686                             hr, prop.expected, i);
687                 }
688                 todo_wine {
689                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_test[%d].\n",
690                             prop.value, wine_dbgstr_w(received), i);
691                 }
692             } else {
693                 ok(hr == prop.expected, "Error: GetDisplayUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
694                         hr, prop.expected, i);
695                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
696                         prop.value, wine_dbgstr_w(received), i);
697             }
698             SysFreeString(received);
699             received = NULL;
700
701             /* GetDomain() tests. */
702             prop = test.str_props[Uri_PROPERTY_DOMAIN];
703             hr = IUri_GetDomain(uri, &received);
704             if(prop.todo) {
705                 todo_wine {
706                     ok(hr == prop.expected, "Error: GetDomain returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
707                             hr, prop.expected, i);
708                 }
709                 todo_wine {
710                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
711                             prop.value, wine_dbgstr_w(received), i);
712                 }
713             } else {
714                 ok(hr == prop.expected, "Error: GetDomain returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
715                         hr, prop.expected, i);
716                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
717                         prop.value, wine_dbgstr_w(received), i);
718             }
719             SysFreeString(received);
720             received = NULL;
721
722             /* GetExtension() tests. */
723             prop = test.str_props[Uri_PROPERTY_EXTENSION];
724             hr = IUri_GetExtension(uri, &received);
725             if(prop.todo) {
726                 todo_wine {
727                     ok(hr == prop.expected, "Error: GetExtension returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
728                             hr, prop.expected, i);
729                 }
730                 todo_wine {
731                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
732                             prop.value, wine_dbgstr_w(received), i);
733                 }
734             } else {
735                 ok(hr == prop.expected, "Error: GetExtension returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
736                         hr, prop.expected, i);
737                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
738                         prop.value, wine_dbgstr_w(received), i);
739             }
740             SysFreeString(received);
741             received = NULL;
742
743             /* GetFragment() tests. */
744             prop = test.str_props[Uri_PROPERTY_FRAGMENT];
745             hr = IUri_GetFragment(uri, &received);
746             if(prop.todo) {
747                 todo_wine {
748                     ok(hr == prop.expected, "Error: GetFragment returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
749                             hr, prop.expected, i);
750                 }
751                 todo_wine {
752                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
753                             prop.value, wine_dbgstr_w(received), i);
754                 }
755             } else {
756                 ok(hr == prop.expected, "Error: GetFragment returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
757                         hr, prop.expected, i);
758                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
759                         prop.value, wine_dbgstr_w(received), i);
760             }
761             SysFreeString(received);
762             received = NULL;
763
764             /* GetPassword() tests. */
765             prop = test.str_props[Uri_PROPERTY_PASSWORD];
766             hr = IUri_GetPassword(uri, &received);
767             if(prop.todo) {
768                 todo_wine {
769                     ok(hr == prop.expected, "Error: GetPassword returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
770                             hr, prop.expected, i);
771                 }
772                 todo_wine {
773                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
774                             prop.value, wine_dbgstr_w(received), i);
775                 }
776             } else {
777                 ok(hr == prop.expected, "Error: GetPassword returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
778                         hr, prop.expected, i);
779                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
780                         prop.value, wine_dbgstr_w(received), i);
781             }
782             SysFreeString(received);
783             received = NULL;
784
785             /* GetPath() tests. */
786             prop = test.str_props[Uri_PROPERTY_PATH];
787             hr = IUri_GetPath(uri, &received);
788             if(prop.todo) {
789                 todo_wine {
790                     ok(hr == prop.expected, "Error: GetPath returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
791                             hr, prop.expected, i);
792                 }
793                 todo_wine {
794                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
795                             prop.value, wine_dbgstr_w(received), i);
796                 }
797             } else {
798                 ok(hr == prop.expected, "Error: GetPath returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
799                         hr, prop.expected, i);
800                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
801                         prop.value, wine_dbgstr_w(received), i);
802             }
803             SysFreeString(received);
804             received = NULL;
805
806             /* GetPathAndQuery() tests. */
807             prop = test.str_props[Uri_PROPERTY_PATH_AND_QUERY];
808             hr = IUri_GetPathAndQuery(uri, &received);
809             if(prop.todo) {
810                 todo_wine {
811                     ok(hr == prop.expected, "Error: GetPathAndQuery returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
812                             hr, prop.expected, i);
813                 }
814                 todo_wine {
815                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
816                             prop.value, wine_dbgstr_w(received), i);
817                 }
818             } else {
819                 ok(hr == prop.expected, "Error: GetPathAndQuery returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
820                         hr, prop.expected, i);
821                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
822                         prop.value, wine_dbgstr_w(received), i);
823             }
824             SysFreeString(received);
825             received = NULL;
826
827             /* GetQuery() tests. */
828             prop = test.str_props[Uri_PROPERTY_QUERY];
829             hr = IUri_GetQuery(uri, &received);
830             if(prop.todo) {
831                 todo_wine {
832                     ok(hr == prop.expected, "Error: GetQuery returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
833                             hr, prop.expected, i);
834                 }
835                 todo_wine {
836                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
837                             prop.value, wine_dbgstr_w(received), i);
838                 }
839             } else {
840                 ok(hr == prop.expected, "Error: GetQuery returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
841                         hr, prop.expected, i);
842                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
843                         prop.value, wine_dbgstr_w(received), i);
844             }
845             SysFreeString(received);
846             received = NULL;
847
848             /* GetRawUri() tests. */
849             prop = test.str_props[Uri_PROPERTY_RAW_URI];
850             hr = IUri_GetRawUri(uri, &received);
851             if(prop.todo) {
852                 todo_wine {
853                     ok(hr == prop.expected, "Error: GetRawUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
854                             hr, prop.expected, i);
855                 }
856                 todo_wine {
857                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
858                             prop.value, wine_dbgstr_w(received), i);
859                 }
860             } else {
861                 ok(hr == prop.expected, "Error: GetRawUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
862                         hr, prop.expected, i);
863                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
864                         prop.value, wine_dbgstr_w(received), i);
865             }
866             SysFreeString(received);
867             received = NULL;
868
869             /* GetSchemeName() tests. */
870             prop = test.str_props[Uri_PROPERTY_SCHEME_NAME];
871             hr = IUri_GetSchemeName(uri, &received);
872             if(prop.todo) {
873                 todo_wine {
874                     ok(hr == prop.expected, "Error: GetSchemeName returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
875                             hr, prop.expected, i);
876                 }
877                 todo_wine {
878                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
879                             prop.value, wine_dbgstr_w(received), i);
880                 }
881             } else {
882                 ok(hr == prop.expected, "Error: GetSchemeName returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
883                         hr, prop.expected, i);
884                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
885                         prop.value, wine_dbgstr_w(received), i);
886             }
887             SysFreeString(received);
888             received = NULL;
889
890             /* GetUserInfo() tests. */
891             prop = test.str_props[Uri_PROPERTY_USER_INFO];
892             hr = IUri_GetUserInfo(uri, &received);
893             if(prop.todo) {
894                 todo_wine {
895                     ok(hr == prop.expected, "Error: GetUserInfo returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
896                             hr, prop.expected, i);
897                 }
898                 todo_wine {
899                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
900                             prop.value, wine_dbgstr_w(received), i);
901                 }
902             } else {
903                 ok(hr == prop.expected, "Error: GetUserInfo returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
904                         hr, prop.expected, i);
905                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
906                         prop.value, wine_dbgstr_w(received), i);
907             }
908             SysFreeString(received);
909             received = NULL;
910
911             /* GetUserName() tests. */
912             prop = test.str_props[Uri_PROPERTY_USER_NAME];
913             hr = IUri_GetUserName(uri, &received);
914             if(prop.todo) {
915                 todo_wine {
916                     ok(hr == prop.expected, "Error: GetUserName returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
917                             hr, prop.expected, i);
918                 }
919                 todo_wine {
920                     ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
921                             prop.value, wine_dbgstr_w(received), i);
922                 }
923             } else {
924                 ok(hr == prop.expected, "Error: GetUserName returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
925                         hr, prop.expected, i);
926                 ok(!strcmp_aw(prop.value, received), "Error: Expected %s but got %s on uri_tests[%d].\n",
927                         prop.value, wine_dbgstr_w(received), i);
928             }
929             SysFreeString(received);
930         }
931
932         if(uri) IUri_Release(uri);
933
934         heap_free(uriW);
935     }
936 }
937
938 static void test_IUri_GetDwordProperties(void) {
939     IUri *uri = NULL;
940     HRESULT hr;
941     DWORD i;
942
943     /* Make sure all the 'Get*' dword property functions handle invalid args correctly. */
944     hr = pCreateUri(http_urlW, 0, 0, &uri);
945     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
946     if(SUCCEEDED(hr)) {
947         hr = IUri_GetHostType(uri, NULL);
948         ok(hr == E_INVALIDARG, "Error: GetHostType returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
949
950         hr = IUri_GetPort(uri, NULL);
951         ok(hr == E_INVALIDARG, "Error: GetPort returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
952
953         hr = IUri_GetScheme(uri, NULL);
954         ok(hr == E_INVALIDARG, "Error: GetScheme returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
955
956         hr = IUri_GetZone(uri, NULL);
957         ok(hr == E_INVALIDARG, "Error: GetZone returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
958     }
959     if(uri) IUri_Release(uri);
960
961     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
962         uri_properties test = uri_tests[i];
963         LPWSTR uriW;
964         uri = NULL;
965
966         uriW = a2w(test.uri);
967         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
968         if(test.create_todo) {
969             todo_wine {
970                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
971                         hr, test.create_expected, i);
972             }
973         } else {
974             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
975                     hr, test.create_expected, i);
976         }
977
978         if(SUCCEEDED(hr)) {
979             uri_dword_property prop;
980             DWORD received;
981
982             /* Assign an insane value so tests don't accidentally pass when
983              * they shouldn't!
984              */
985             received = -9999999;
986
987             /* GetHostType() tests. */
988             prop = test.dword_props[Uri_PROPERTY_HOST_TYPE-Uri_PROPERTY_DWORD_START];
989             hr = IUri_GetHostType(uri, &received);
990             if(prop.todo) {
991                 todo_wine {
992                     ok(hr == prop.expected, "Error: GetHostType returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
993                             hr, prop.expected, i);
994                 }
995                 todo_wine {
996                     ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
997                 }
998             } else {
999                 ok(hr == prop.expected, "Error: GetHostType returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
1000                         hr, prop.expected, i);
1001                 ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
1002             }
1003             received = -9999999;
1004
1005             /* GetPort() tests. */
1006             prop = test.dword_props[Uri_PROPERTY_PORT-Uri_PROPERTY_DWORD_START];
1007             hr = IUri_GetPort(uri, &received);
1008             if(prop.todo) {
1009                 todo_wine {
1010                     ok(hr == prop.expected, "Error: GetPort returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
1011                             hr, prop.expected, i);
1012                 }
1013                 todo_wine {
1014                     ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
1015                 }
1016             } else {
1017                 ok(hr == prop.expected, "Error: GetPort returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
1018                         hr, prop.expected, i);
1019                 ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
1020             }
1021             received = -9999999;
1022
1023             /* GetScheme() tests. */
1024             prop = test.dword_props[Uri_PROPERTY_SCHEME-Uri_PROPERTY_DWORD_START];
1025             hr = IUri_GetScheme(uri, &received);
1026             if(prop.todo) {
1027                 todo_wine {
1028                     ok(hr == prop.expected, "Error: GetScheme returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
1029                             hr, prop.expected, i);
1030                 }
1031                 todo_wine {
1032                     ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
1033                 }
1034             } else {
1035                 ok(hr == prop.expected, "Error: GetScheme returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
1036                         hr, prop.expected, i);
1037                 ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
1038             }
1039             received = -9999999;
1040
1041             /* GetZone() tests. */
1042             prop = test.dword_props[Uri_PROPERTY_ZONE-Uri_PROPERTY_DWORD_START];
1043             hr = IUri_GetZone(uri, &received);
1044             if(prop.todo) {
1045                 todo_wine {
1046                     ok(hr == prop.expected, "Error: GetZone returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
1047                             hr, prop.expected, i);
1048                 }
1049                 todo_wine {
1050                     ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
1051                 }
1052             } else {
1053                 ok(hr == prop.expected, "Error: GetZone returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
1054                         hr, prop.expected, i);
1055                 ok(received == prop.value, "Error: Expected %d but got %d on uri_tests[%d].\n", prop.value, received, i);
1056             }
1057         }
1058
1059         if(uri) IUri_Release(uri);
1060
1061         heap_free(uriW);
1062     }
1063 }
1064
1065 static void test_IUri_GetPropertyLength(void) {
1066     IUri *uri = NULL;
1067     HRESULT hr;
1068     DWORD i;
1069
1070     /* Make sure it handles invalid args correctly. */
1071     hr = pCreateUri(http_urlW, 0, 0, &uri);
1072     ok(hr == S_OK, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
1073     if(SUCCEEDED(hr)) {
1074         DWORD received = 0xdeadbeef;
1075
1076         hr = IUri_GetPropertyLength(uri, Uri_PROPERTY_STRING_START, NULL, 0);
1077         ok(hr == E_INVALIDARG, "Error: GetPropertyLength returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
1078
1079         hr = IUri_GetPropertyLength(uri, Uri_PROPERTY_DWORD_START, &received, 0);
1080         ok(hr == E_INVALIDARG, "Error: GetPropertyLength return 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
1081         ok(received == 0xdeadbeef, "Error: Expected 0xdeadbeef but got 0x%08x.\n", received);
1082     }
1083     if(uri) IUri_Release(uri);
1084
1085     for(i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); ++i) {
1086         uri_properties test = uri_tests[i];
1087         LPWSTR uriW;
1088         uri = NULL;
1089
1090         uriW = a2w(test.uri);
1091         hr = pCreateUri(uriW, test.create_flags, 0, &uri);
1092         if(test.create_todo) {
1093             todo_wine {
1094                 ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_tests[%d].\n",
1095                         hr, test.create_expected, i);
1096             }
1097         } else {
1098             ok(hr == test.create_expected, "Error: CreateUri returned 0x%08x, expected 0x%08x on uri_test[%d].\n",
1099                     hr, test.create_expected, i);
1100         }
1101
1102         if(SUCCEEDED(hr)) {
1103             DWORD j;
1104
1105             for(j = Uri_PROPERTY_STRING_START; j <= Uri_PROPERTY_STRING_LAST; ++j) {
1106                 DWORD expectedLen, receivedLen;
1107                 uri_str_property prop = test.str_props[j];
1108
1109                 expectedLen = lstrlen(prop.value);
1110
1111                 /* This won't be neccessary once GetPropertyLength is implemented. */
1112                 receivedLen = -1;
1113
1114                 hr = IUri_GetPropertyLength(uri, j, &receivedLen, 0);
1115                 if(prop.todo) {
1116                     todo_wine {
1117                         ok(hr == prop.expected, "Error: GetPropertyLength returned 0x%08x, expected 0x%08x on uri_tests[%d].str_props[%d].\n",
1118                                 hr, prop.expected, i, j);
1119                     }
1120                     todo_wine {
1121                         ok(receivedLen == expectedLen, "Error: Expected a length of %d but got %d on uri_tests[%d].str_props[%d].\n",
1122                                 expectedLen, receivedLen, i, j);
1123                     }
1124                 } else {
1125                     ok(hr == prop.expected, "Error: GetPropertyLength returned 0x%08x, expected 0x%08x on uri_tests[%d].str_props[%d].\n",
1126                             hr, prop.expected, i, j);
1127                     ok(receivedLen == expectedLen, "Error: Expected a length of %d but %d on uri_tests[%d].str_props[%d].\n",
1128                             expectedLen, receivedLen, i, j);
1129                 }
1130             }
1131         }
1132
1133         if(uri) IUri_Release(uri);
1134
1135         heap_free(uriW);
1136     }
1137 }
1138
1139 START_TEST(uri) {
1140     HMODULE hurlmon;
1141
1142     hurlmon = GetModuleHandle("urlmon.dll");
1143     pCreateUri = (void*) GetProcAddress(hurlmon, "CreateUri");
1144
1145     if(!pCreateUri) {
1146         win_skip("CreateUri is not present, skipping tests.\n");
1147         return;
1148     }
1149
1150     trace("test CreateUri invalid flags...\n");
1151     test_CreateUri_InvalidFlags();
1152
1153     trace("test CreateUri invalid args...\n");
1154     test_CreateUri_InvalidArgs();
1155
1156     trace("test IUri_GetPropertyBSTR...\n");
1157     test_IUri_GetPropertyBSTR();
1158
1159     trace("test IUri_GetPropertyDWORD...\n");
1160     test_IUri_GetPropertyDWORD();
1161
1162     trace("test IUri_GetStrProperties...\n");
1163     test_IUri_GetStrProperties();
1164
1165     trace("test IUri_GetDwordProperties...\n");
1166     test_IUri_GetDwordProperties();
1167
1168     trace("test IUri_GetPropertyLength...\n");
1169     test_IUri_GetPropertyLength();
1170 }