wininet: Test sticky url cache entries.
[wine] / dlls / wininet / tests / url.c
1 /*
2  * Wininet - URL tests
3  *
4  * Copyright 2002 Aric Stewart
5  * Copyright 2004 Mike McCormack
6  * Copyright 2005 Hans Leidekker
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21  */
22
23 #include <stdarg.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27
28 #include "windef.h"
29 #include "winbase.h"
30 #include "winnls.h"
31 #include "wininet.h"
32
33 #include "wine/test.h"
34
35 #define TEST_URL "http://www.winehq.org/site/about#hi"
36 #define TEST_URL3 "file:///C:/Program%20Files/Atmel/AVR%20Tools/STK500/STK500.xml"
37
38 #define CREATE_URL1 "http://username:password@www.winehq.org/site/about"
39 #define CREATE_URL2 "http://username@www.winehq.org/site/about"
40 #define CREATE_URL3 "http://username:"
41 #define CREATE_URL4 "http://www.winehq.org/site/about"
42 #define CREATE_URL5 "http://"
43 #define CREATE_URL6 "nhttp://username:password@www.winehq.org:80/site/about"
44 #define CREATE_URL7 "http://username:password@www.winehq.org:42/site/about"
45 #define CREATE_URL8 "https://username:password@www.winehq.org/site/about"
46 #define CREATE_URL9 "about:blank"
47 #define CREATE_URL10 "about://host/blank"
48 #define CREATE_URL11 "about:"
49 #define CREATE_URL12 "http://www.winehq.org:65535"
50 #define CREATE_URL13 "http://localhost/?test=123"
51
52 static void copy_compsA(
53     URL_COMPONENTSA *src, 
54     URL_COMPONENTSA *dst, 
55     DWORD scheLen,
56     DWORD hostLen,
57     DWORD userLen,
58     DWORD passLen,
59     DWORD pathLen,
60     DWORD extrLen )
61 {
62     *dst = *src;
63     dst->dwSchemeLength    = scheLen;
64     dst->dwHostNameLength  = hostLen;
65     dst->dwUserNameLength  = userLen;
66     dst->dwPasswordLength  = passLen;
67     dst->dwUrlPathLength   = pathLen;
68     dst->dwExtraInfoLength = extrLen;
69     SetLastError(0xfaceabad);
70 }
71
72 static void zero_compsA(
73     URL_COMPONENTSA *dst, 
74     DWORD scheLen,
75     DWORD hostLen,
76     DWORD userLen,
77     DWORD passLen,
78     DWORD pathLen,
79     DWORD extrLen )
80 {
81     ZeroMemory(dst, sizeof(URL_COMPONENTSA));
82     dst->dwStructSize = sizeof(URL_COMPONENTSA);
83     dst->dwSchemeLength    = scheLen;
84     dst->dwHostNameLength  = hostLen;
85     dst->dwUserNameLength  = userLen;
86     dst->dwPasswordLength  = passLen;
87     dst->dwUrlPathLength   = pathLen;
88     dst->dwExtraInfoLength = extrLen;
89     SetLastError(0xfaceabad);
90 }
91
92 typedef struct {
93     const char *url;
94     int scheme_off;
95     int scheme_len;
96     INTERNET_SCHEME scheme;
97     int host_off;
98     int host_len;
99     int host_skip_broken;
100     INTERNET_PORT port;
101     int user_off;
102     int user_len;
103     int pass_off;
104     int pass_len;
105     int path_off;
106     int path_len;
107     int extra_off;
108     int extra_len;
109     const char *exp_scheme;
110     const char *exp_hostname;
111     const char *exp_username;
112     const char *exp_password;
113     const char *exp_urlpath;
114     const char *exp_extrainfo;
115 } crack_url_test_t;
116
117 static const crack_url_test_t crack_url_tests[] = {
118     {"http://www.winehq.org/site/about#hi",
119         0, 4, INTERNET_SCHEME_HTTP, 7, 14, -1, 80, -1, 0, -1, 0, 21, 11, 32, 3,
120         "http", "www.winehq.org", "", "", "/site/about", "#hi"},
121     {"http://www.myserver.com/myscript.php?arg=1",
122         0, 4, INTERNET_SCHEME_HTTP, 7, 16, -1, 80, -1, 0, -1, 0, 23, 13, 36, 6,
123         "http", "www.myserver.com", "", "", "/myscript.php", "?arg=1"},
124     {"http://www.winehq.org?test=123",
125         0, 4, INTERNET_SCHEME_HTTP, 7, 14, 23, 80, -1, 0, -1, 0, 21, 0, 21, 9,
126         "http", "www.winehq.org", "", "", "", "?test=123"},
127     {"file:///C:/Program%20Files/Atmel/AVR%20Tools/STK500/STK500.xml",
128         0, 4, INTERNET_SCHEME_FILE, -1, 0, -1, 0, -1, 0, -1, 0, 7, 55, -1, 0,
129         "file", "", "", "", "C:\\Program Files\\Atmel\\AVR Tools\\STK500\\STK500.xml", ""},
130     {"fide:///C:/Program%20Files/Atmel/AVR%20Tools/STK500/STK500.xml",
131         0, 4, INTERNET_SCHEME_UNKNOWN, 7, 0, -1, 0, -1, 0, -1, 0, 7, 55, -1, 0,
132         "fide", "", "", "", "/C:/Program%20Files/Atmel/AVR%20Tools/STK500/STK500.xml", ""},
133     {"file://C:/Program%20Files/Atmel/AVR%20Tools/STK500/STK500.xml",
134         0, 4, INTERNET_SCHEME_FILE, -1, 0, -1, 0, -1, 0, -1, 0, 7, 54, -1, 0,
135         "file", "", "", "", "C:\\Program%20Files\\Atmel\\AVR%20Tools\\STK500\\STK500.xml", ""},
136     {"file://C:/Program%20Files/Atmel/..",
137         0, 4, INTERNET_SCHEME_FILE, -1, 0, -1, 0, -1, 0, -1, 0, 7, 27, -1, 0,
138         "file", "", "", "", "C:\\Program%20Files\\Atmel\\..\\", ""},
139     {"file://C:/Program%20Files/Atmel/../Asdf.xml",
140         0, 4, INTERNET_SCHEME_FILE, -1, 0, -1, 0, -1, 0, -1, 0, 7, 36, -1, 0,
141         "file", "", "", "", "C:\\Program%20Files\\Atmel\\..\\Asdf.xml", ""},
142     {"file:///C:/Program%20Files/Atmel/..",
143         0, 4, INTERNET_SCHEME_FILE, -1, 0, -1, 0, -1, 0, -1, 0, 7, 28, -1, 0,
144         "file", "", "", "", "C:\\Program Files\\Atmel\\..\\", ""},
145     {"file:///C:/Program%20Files/Atmel/../Asdf.xml",
146         0, 4, INTERNET_SCHEME_FILE, -1, 0, -1, 0, -1, 0, -1, 0, 7, 37, -1, 0,
147         "file", "", "", "", "C:\\Program Files\\Atmel\\..\\Asdf.xml", ""},
148     {"file://C:/Program%20Files/Atmel/.",
149         0, 4, INTERNET_SCHEME_FILE, -1, 0, -1, 0, -1, 0, -1, 0, 7, 26, -1, 0,
150         "file", "", "", "", "C:\\Program%20Files\\Atmel\\.\\", ""},
151     {"file://C:/Program%20Files/Atmel/./Asdf.xml",
152         0, 4, INTERNET_SCHEME_FILE, -1, 0, -1, 0, -1, 0, -1, 0, 7, 35, -1, 0,
153         "file", "", "", "", "C:\\Program%20Files\\Atmel\\.\\Asdf.xml", ""},
154     {"file:///C:/Program%20Files/Atmel/.",
155         0, 4, INTERNET_SCHEME_FILE, -1, 0, -1, 0, -1, 0, -1, 0, 7, 27, -1, 0,
156         "file", "", "", "", "C:\\Program Files\\Atmel\\.\\", ""},
157     {"file:///C:/Program%20Files/Atmel/./Asdf.xml",
158         0, 4, INTERNET_SCHEME_FILE, -1, 0, -1, 0, -1, 0, -1, 0, 7, 36, -1, 0,
159         "file", "", "", "", "C:\\Program Files\\Atmel\\.\\Asdf.xml", ""},
160 };
161
162 static const WCHAR *w_str_of(const char *str)
163 {
164     static WCHAR buf[512];
165     MultiByteToWideChar(CP_ACP, 0, str, -1, buf, sizeof(buf)/sizeof(buf[0]));
166     return buf;
167 }
168
169 static void test_crack_url(const crack_url_test_t *test)
170 {
171     WCHAR buf[INTERNET_MAX_URL_LENGTH];
172     URL_COMPONENTSW urlw;
173     URL_COMPONENTSA url;
174     char scheme[32], hostname[1024], username[1024];
175     char password[1024], extrainfo[1024], urlpath[1024];
176     BOOL b;
177
178     /* test InternetCrackUrlA with NULL buffers */
179     zero_compsA(&url, 1, 1, 1, 1, 1, 1);
180
181     b = InternetCrackUrlA(test->url, strlen(test->url), 0, &url);
182     ok(b, "InternetCrackUrl failed with error %d\n", GetLastError());
183
184     if(test->scheme_off == -1)
185         ok(!url.lpszScheme, "[%s] url.lpszScheme = %p, expected NULL\n", test->url, url.lpszScheme);
186     else
187         ok(url.lpszScheme == test->url+test->scheme_off, "[%s] url.lpszScheme = %p, expected %p\n",
188            test->url, url.lpszScheme, test->url+test->scheme_off);
189     ok(url.dwSchemeLength == test->scheme_len, "[%s] url.lpszSchemeLength = %d, expected %d\n",
190        test->url, url.dwSchemeLength, test->scheme_len);
191
192     ok(url.nScheme == test->scheme, "[%s] url.nScheme = %d, expected %d\n", test->url, url.nScheme, test->scheme);
193
194     if(test->host_off == -1)
195         ok(!url.lpszHostName, "[%s] url.lpszHostName = %p, expected NULL\n", test->url, url.lpszHostName);
196     else
197         ok(url.lpszHostName == test->url+test->host_off, "[%s] url.lpszHostName = %p, expected %p\n",
198            test->url, url.lpszHostName, test->url+test->host_off);
199     if(test->host_skip_broken != -1 && url.dwHostNameLength == test->host_skip_broken) {
200         win_skip("skipping broken dwHostNameLength result\n");
201         return;
202     }
203     ok(url.dwHostNameLength == test->host_len, "[%s] url.lpszHostNameLength = %d, expected %d\n",
204        test->url, url.dwHostNameLength, test->host_len);
205
206     ok(url.nPort == test->port, "[%s] nPort = %d, expected %d\n", test->url, url.nPort, test->port);
207
208     if(test->user_off == -1)
209         ok(!url.lpszUserName, "[%s] url.lpszUserName = %p\n", test->url, url.lpszUserName);
210     else
211         ok(url.lpszUserName == test->url+test->user_off, "[%s] url.lpszUserName = %p, expected %p\n",
212            test->url, url.lpszUserName, test->url+test->user_off);
213     ok(url.dwUserNameLength == test->user_len, "[%s] url.lpszUserNameLength = %d, expected %d\n",
214        test->url, url.dwUserNameLength, test->user_len);
215
216     if(test->pass_off == -1)
217         ok(!url.lpszPassword, "[%s] url.lpszPassword = %p\n", test->url, url.lpszPassword);
218     else
219         ok(url.lpszPassword == test->url+test->pass_off, "[%s] url.lpszPassword = %p, expected %p\n",
220            test->url, url.lpszPassword, test->url+test->pass_off);
221     ok(url.dwPasswordLength == test->pass_len, "[%s] url.lpszPasswordLength = %d, expected %d\n",
222        test->url, url.dwPasswordLength, test->pass_len);
223
224     if(test->path_off == -1)
225         ok(!url.lpszUrlPath, "[%s] url.lpszPath = %p, expected NULL\n", test->url, url.lpszUrlPath);
226     else
227         ok(url.lpszUrlPath == test->url+test->path_off, "[%s] url.lpszPath = %p, expected %p\n",
228            test->url, url.lpszUrlPath, test->url+test->path_off);
229     ok(url.dwUrlPathLength == test->path_len, "[%s] url.lpszUrlPathLength = %d, expected %d\n",
230        test->url, url.dwUrlPathLength, test->path_len);
231
232     if(test->extra_off == -1)
233         ok(!url.lpszExtraInfo, "[%s] url.lpszExtraInfo = %p, expected NULL\n", test->url, url.lpszExtraInfo);
234     else
235         ok(url.lpszExtraInfo == test->url+test->extra_off, "[%s] url.lpszExtraInfo = %p, expected %p\n",
236            test->url, url.lpszExtraInfo, test->url+test->extra_off);
237     ok(url.dwExtraInfoLength == test->extra_len, "[%s] url.lpszExtraInfoLength = %d, expected %d\n",
238        test->url, url.dwExtraInfoLength, test->extra_len);
239
240     /* test InternetCrackUrlW with NULL buffers */
241     memset(&urlw, 0, sizeof(URL_COMPONENTSW));
242     urlw.dwStructSize = sizeof(URL_COMPONENTSW);
243     urlw.dwSchemeLength = 1;
244     urlw.dwHostNameLength = 1;
245     urlw.dwUserNameLength = 1;
246     urlw.dwPasswordLength = 1;
247     urlw.dwUrlPathLength = 1;
248     urlw.dwExtraInfoLength = 1;
249
250     MultiByteToWideChar(CP_ACP, 0, test->url, -1, buf, sizeof(buf)/sizeof(buf[0]));
251     b = InternetCrackUrlW(buf, lstrlenW(buf), 0, &urlw);
252     if(!b && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) {
253         win_skip("InternetCrackUrlW is not implemented\n");
254         return;
255     }
256     ok(b, "InternetCrackUrl failed with error %d\n", GetLastError());
257
258     if(test->scheme_off == -1)
259         ok(!urlw.lpszScheme, "[%s] urlw.lpszScheme = %p, expected NULL\n", test->url, urlw.lpszScheme);
260     else
261         ok(urlw.lpszScheme == buf+test->scheme_off, "[%s] urlw.lpszScheme = %p, expected %p\n",
262            test->url, urlw.lpszScheme, buf+test->scheme_off);
263     ok(urlw.dwSchemeLength == test->scheme_len, "[%s] urlw.lpszSchemeLength = %d, expected %d\n",
264        test->url, urlw.dwSchemeLength, test->scheme_len);
265
266     ok(urlw.nScheme == test->scheme, "[%s] urlw.nScheme = %d, expected %d\n", test->url, urlw.nScheme, test->scheme);
267
268     if(test->host_off == -1) {
269         ok(!urlw.lpszHostName, "[%s] urlw.lpszHostName = %p, expected NULL\n", test->url, urlw.lpszHostName);
270         ok(urlw.dwHostNameLength == 0 || broken(urlw.dwHostNameLength == 1), "[%s] urlw.lpszHostNameLength = %d, expected %d\n",
271            test->url, urlw.dwHostNameLength, test->host_len);
272     }else {
273         ok(urlw.lpszHostName == buf+test->host_off, "[%s] urlw.lpszHostName = %p, expected %p\n",
274            test->url, urlw.lpszHostName, test->url+test->host_off);
275         ok(urlw.dwHostNameLength == test->host_len, "[%s] urlw.lpszHostNameLength = %d, expected %d\n",
276            test->url, urlw.dwHostNameLength, test->host_len);
277     }
278
279     ok(urlw.nPort == test->port, "[%s] nPort = %d, expected %d\n", test->url, urlw.nPort, test->port);
280
281     if(test->user_off == -1) {
282         ok(!urlw.lpszUserName, "[%s] urlw.lpszUserName = %p\n", test->url, urlw.lpszUserName);
283         ok(urlw.dwUserNameLength == 0 || broken(urlw.dwUserNameLength == 1), "[%s] urlw.lpszUserNameLength = %d, expected %d\n",
284            test->url, urlw.dwUserNameLength, test->user_len);
285     }else {
286         ok(urlw.lpszUserName == buf+test->user_off, "[%s] urlw.lpszUserName = %p, expected %p\n",
287            test->url, urlw.lpszUserName, buf+test->user_off);
288         ok(urlw.dwUserNameLength == test->user_len, "[%s] urlw.lpszUserNameLength = %d, expected %d\n",
289            test->url, urlw.dwUserNameLength, test->user_len);
290     }
291
292     if(test->pass_off == -1) {
293         ok(!urlw.lpszPassword, "[%s] urlw.lpszPassword = %p\n", test->url, urlw.lpszPassword);
294         ok(urlw.dwPasswordLength == 0 || broken(urlw.dwPasswordLength), "[%s] urlw.lpszPasswordLength = %d, expected %d\n",
295            test->url, urlw.dwPasswordLength, test->pass_len);
296     }else {
297         ok(urlw.lpszPassword == buf+test->pass_off, "[%s] urlw.lpszPassword = %p, expected %p\n",
298            test->url, urlw.lpszPassword, buf+test->pass_off);
299         ok(urlw.dwPasswordLength == test->pass_len, "[%s] urlw.lpszPasswordLength = %d, expected %d\n",
300            test->url, urlw.dwPasswordLength, test->pass_len);
301     }
302
303     if(test->path_off == -1)
304         ok(!urlw.lpszUrlPath, "[%s] urlw.lpszPath = %p, expected NULL\n", test->url, urlw.lpszUrlPath);
305     else
306         ok(urlw.lpszUrlPath == buf+test->path_off, "[%s] urlw.lpszPath = %p, expected %p\n",
307            test->url, urlw.lpszUrlPath, buf+test->path_off);
308     ok(urlw.dwUrlPathLength == test->path_len, "[%s] urlw.lpszUrlPathLength = %d, expected %d\n",
309        test->url, urlw.dwUrlPathLength, test->path_len);
310
311     if(test->extra_off == -1) {
312         ok(!urlw.lpszExtraInfo, "[%s] url.lpszExtraInfo = %p, expected NULL\n", test->url, urlw.lpszExtraInfo);
313         ok(urlw.dwExtraInfoLength == 0 || broken(urlw.dwExtraInfoLength == 1), "[%s] urlw.lpszExtraInfoLength = %d, expected %d\n",
314            test->url, urlw.dwExtraInfoLength, test->extra_len);
315     }else {
316         ok(urlw.lpszExtraInfo == buf+test->extra_off, "[%s] urlw.lpszExtraInfo = %p, expected %p\n",
317            test->url, urlw.lpszExtraInfo, buf+test->extra_off);
318         ok(urlw.dwExtraInfoLength == test->extra_len, "[%s] urlw.lpszExtraInfoLength = %d, expected %d\n",
319            test->url, urlw.dwExtraInfoLength, test->extra_len);
320     }
321
322     /* test InternetCrackUrlA with valid buffers */
323     memset(&url, 0, sizeof(URL_COMPONENTSA));
324     url.dwStructSize = sizeof(URL_COMPONENTSA);
325     url.lpszScheme = scheme;
326     url.dwSchemeLength = sizeof(scheme);
327     url.lpszHostName = hostname;
328     url.dwHostNameLength = sizeof(hostname);
329     url.lpszUserName = username;
330     url.dwUserNameLength = sizeof(username);
331     url.lpszPassword = password;
332     url.dwPasswordLength = sizeof(password);
333     url.lpszUrlPath = urlpath;
334     url.dwUrlPathLength = sizeof(urlpath);
335     url.lpszExtraInfo = extrainfo;
336     url.dwExtraInfoLength = sizeof(extrainfo);
337
338     b = InternetCrackUrlA(test->url, strlen(test->url), 0, &url);
339     ok(b, "InternetCrackUrlA failed with error %d\n", GetLastError());
340
341     ok(url.dwSchemeLength == strlen(test->exp_scheme), "[%s] Got wrong scheme length: %d\n",
342             test->url, url.dwSchemeLength);
343     ok(!strcmp(scheme, test->exp_scheme), "[%s] Got wrong scheme, expected: %s, got: %s\n",
344             test->url, test->exp_scheme, scheme);
345
346     ok(url.nScheme == test->scheme, "[%s] Got wrong nScheme, expected: %d, got: %d\n",
347             test->url, test->scheme, url.nScheme);
348
349     ok(url.dwHostNameLength == strlen(test->exp_hostname), "[%s] Got wrong hostname length: %d\n",
350             test->url, url.dwHostNameLength);
351     ok(!strcmp(hostname, test->exp_hostname), "[%s] Got wrong hostname, expected: %s, got: %s\n",
352             test->url, test->exp_hostname, hostname);
353
354     ok(url.nPort == test->port, "[%s] Got wrong port, expected: %d, got: %d\n",
355             test->url, test->port, url.nPort);
356
357     ok(url.dwUserNameLength == strlen(test->exp_username), "[%s] Got wrong username length: %d\n",
358             test->url, url.dwUserNameLength);
359     ok(!strcmp(username, test->exp_username), "[%s] Got wrong username, expected: %s, got: %s\n",
360             test->url, test->exp_username, username);
361
362     ok(url.dwPasswordLength == strlen(test->exp_password), "[%s] Got wrong password length: %d\n",
363             test->url, url.dwPasswordLength);
364     ok(!strcmp(password, test->exp_password), "[%s] Got wrong password, expected: %s, got: %s\n",
365             test->url, test->exp_password, password);
366
367     ok(url.dwUrlPathLength == strlen(test->exp_urlpath), "[%s] Got wrong urlpath length: %d\n",
368             test->url, url.dwUrlPathLength);
369     ok(!strcmp(urlpath, test->exp_urlpath), "[%s] Got wrong urlpath, expected: %s, got: %s\n",
370             test->url, test->exp_urlpath, urlpath);
371
372     ok(url.dwExtraInfoLength == strlen(test->exp_extrainfo), "[%s] Got wrong extrainfo length: %d\n",
373             test->url, url.dwExtraInfoLength);
374     ok(!strcmp(extrainfo, test->exp_extrainfo), "[%s] Got wrong extrainfo, expected: %s, got: %s\n",
375             test->url, test->exp_extrainfo, extrainfo);
376
377     /* test InternetCrackUrlW with valid buffers */
378     memset(&urlw, 0, sizeof(URL_COMPONENTSW));
379     urlw.dwStructSize = sizeof(URL_COMPONENTSW);
380     urlw.lpszScheme = (WCHAR*)scheme;
381     urlw.dwSchemeLength = sizeof(scheme) / sizeof(WCHAR);
382     urlw.lpszHostName = (WCHAR*)hostname;
383     urlw.dwHostNameLength = sizeof(hostname) / sizeof(WCHAR);
384     urlw.lpszUserName = (WCHAR*)username;
385     urlw.dwUserNameLength = sizeof(username) / sizeof(WCHAR);
386     urlw.lpszPassword = (WCHAR*)password;
387     urlw.dwPasswordLength = sizeof(password) / sizeof(WCHAR);
388     urlw.lpszUrlPath = (WCHAR*)urlpath;
389     urlw.dwUrlPathLength = sizeof(urlpath) / sizeof(WCHAR);
390     urlw.lpszExtraInfo = (WCHAR*)extrainfo;
391     urlw.dwExtraInfoLength = sizeof(extrainfo) / sizeof(WCHAR);
392
393     b = InternetCrackUrlW(buf, lstrlenW(buf), 0, &urlw);
394     ok(b, "InternetCrackUrlW failed with error %d\n", GetLastError());
395
396     ok(urlw.dwSchemeLength == strlen(test->exp_scheme), "[%s] Got wrong scheme length: %d\n",
397             test->url, urlw.dwSchemeLength);
398     ok(!lstrcmpW((WCHAR*)scheme, w_str_of(test->exp_scheme)), "[%s] Got wrong scheme, expected: %s, got: %s\n",
399             test->url, test->exp_scheme, wine_dbgstr_w((WCHAR*)scheme));
400
401     ok(urlw.nScheme == test->scheme, "[%s] Got wrong nScheme, expected: %d, got: %d\n",
402             test->url, test->scheme, urlw.nScheme);
403
404     ok(urlw.dwHostNameLength == strlen(test->exp_hostname), "[%s] Got wrong hostname length: %d\n",
405             test->url, urlw.dwHostNameLength);
406     ok(!lstrcmpW((WCHAR*)hostname, w_str_of(test->exp_hostname)), "[%s] Got wrong hostname, expected: %s, got: %s\n",
407             test->url, test->exp_hostname, wine_dbgstr_w((WCHAR*)hostname));
408
409     ok(urlw.nPort == test->port, "[%s] Got wrong port, expected: %d, got: %d\n",
410             test->url, test->port, urlw.nPort);
411
412     ok(urlw.dwUserNameLength == strlen(test->exp_username), "[%s] Got wrong username length: %d\n",
413             test->url, urlw.dwUserNameLength);
414     ok(!lstrcmpW((WCHAR*)username, w_str_of(test->exp_username)), "[%s] Got wrong username, expected: %s, got: %s\n",
415             test->url, test->exp_username, wine_dbgstr_w((WCHAR*)username));
416
417     ok(urlw.dwPasswordLength == strlen(test->exp_password), "[%s] Got wrong password length: %d\n",
418             test->url, urlw.dwPasswordLength);
419     ok(!lstrcmpW((WCHAR*)password, w_str_of(test->exp_password)), "[%s] Got wrong password, expected: %s, got: %s\n",
420             test->url, test->exp_password, wine_dbgstr_w((WCHAR*)password));
421
422     ok(urlw.dwUrlPathLength == strlen(test->exp_urlpath), "[%s] Got wrong urlpath length: %d\n",
423             test->url, urlw.dwUrlPathLength);
424     ok(!lstrcmpW((WCHAR*)urlpath, w_str_of(test->exp_urlpath)), "[%s] Got wrong urlpath, expected: %s, got: %s\n",
425             test->url, test->exp_urlpath, wine_dbgstr_w((WCHAR*)urlpath));
426
427     ok(urlw.dwExtraInfoLength == strlen(test->exp_extrainfo), "[%s] Got wrong extrainfo length: %d\n",
428             test->url, urlw.dwExtraInfoLength);
429     ok(!lstrcmpW((WCHAR*)extrainfo, w_str_of(test->exp_extrainfo)), "[%s] Got wrong extrainfo, expected: %s, got: %s\n",
430             test->url, test->exp_extrainfo, wine_dbgstr_w((WCHAR*)extrainfo));
431 }
432
433 static void InternetCrackUrl_test(void)
434 {
435   URL_COMPONENTSA urlSrc, urlComponents;
436   char protocol[32], hostName[1024], userName[1024];
437   char password[1024], extra[1024], path[1024];
438   BOOL ret, firstret;
439   DWORD GLE, firstGLE;
440
441   ZeroMemory(&urlSrc, sizeof(urlSrc));
442   urlSrc.dwStructSize = sizeof(urlSrc);
443   urlSrc.lpszScheme = protocol;
444   urlSrc.lpszHostName = hostName;
445   urlSrc.lpszUserName = userName;
446   urlSrc.lpszPassword = password;
447   urlSrc.lpszUrlPath = path;
448   urlSrc.lpszExtraInfo = extra;
449
450   /* Tests for lpsz* members pointing to real strings while 
451    * some corresponding length members are set to zero.
452    * As of IE7 (wininet 7.0*?) all members are checked. So we
453    * run the first test and expect the outcome to be the same
454    * for the first four (scheme, hostname, username and password).
455    * The last two (path and extrainfo) are the same for all versions
456    * of the wininet.dll.
457    */
458   copy_compsA(&urlSrc, &urlComponents, 0, 1024, 1024, 1024, 2048, 1024);
459   SetLastError(0xdeadbeef);
460   firstret = InternetCrackUrlA(TEST_URL3, 0, ICU_DECODE, &urlComponents);
461   firstGLE = GetLastError();
462
463   copy_compsA(&urlSrc, &urlComponents, 32, 0, 1024, 1024, 2048, 1024);
464   SetLastError(0xdeadbeef);
465   ret = InternetCrackUrlA(TEST_URL3, 0, ICU_DECODE, &urlComponents);
466   GLE = GetLastError();
467   ok(ret==firstret && (GLE==firstGLE), "InternetCrackUrl returned %d with GLE=%d (expected to return %d)\n",
468     ret, GLE, firstret);
469
470   copy_compsA(&urlSrc, &urlComponents, 32, 1024, 0, 1024, 2048, 1024);
471   SetLastError(0xdeadbeef);
472   ret = InternetCrackUrlA(TEST_URL3, 0, ICU_DECODE, &urlComponents);
473   GLE = GetLastError();
474   ok(ret==firstret && (GLE==firstGLE), "InternetCrackUrl returned %d with GLE=%d (expected to return %d)\n",
475     ret, GLE, firstret);
476
477   copy_compsA(&urlSrc, &urlComponents, 32, 1024, 1024, 0, 2048, 1024);
478   SetLastError(0xdeadbeef);
479   ret = InternetCrackUrlA(TEST_URL3, 0, ICU_DECODE, &urlComponents);
480   GLE = GetLastError();
481   ok(ret==firstret && (GLE==firstGLE), "InternetCrackUrl returned %d with GLE=%d (expected to return %d)\n",
482     ret, GLE, firstret);
483
484   copy_compsA(&urlSrc, &urlComponents, 32, 1024, 1024, 1024, 0, 1024);
485   SetLastError(0xdeadbeef);
486   ret = InternetCrackUrlA(TEST_URL3, 0, ICU_DECODE, &urlComponents);
487   GLE = GetLastError();
488   todo_wine
489   ok(ret==0 && (GLE==ERROR_INVALID_HANDLE || GLE==ERROR_INSUFFICIENT_BUFFER),
490      "InternetCrackUrl returned %d with GLE=%d (expected to return 0 and ERROR_INVALID_HANDLE or ERROR_INSUFFICIENT_BUFFER)\n",
491     ret, GLE);
492
493   copy_compsA(&urlSrc, &urlComponents, 32, 1024, 1024, 1024, 2048, 0);
494   SetLastError(0xdeadbeef);
495   ret = InternetCrackUrlA(TEST_URL3, 0, ICU_DECODE, &urlComponents);
496   GLE = GetLastError();
497   todo_wine
498   ok(ret==0 && (GLE==ERROR_INVALID_HANDLE || GLE==ERROR_INSUFFICIENT_BUFFER),
499      "InternetCrackUrl returned %d with GLE=%d (expected to return 0 and ERROR_INVALID_HANDLE or ERROR_INSUFFICIENT_BUFFER)\n",
500     ret, GLE);
501
502   copy_compsA(&urlSrc, &urlComponents, 0, 0, 0, 0, 0, 0);
503   ret = InternetCrackUrlA(TEST_URL3, 0, ICU_DECODE, &urlComponents);
504   GLE = GetLastError();
505   todo_wine
506   ok(ret==0 && GLE==ERROR_INVALID_PARAMETER,
507      "InternetCrackUrl returned %d with GLE=%d (expected to return 0 and ERROR_INVALID_PARAMETER)\n",
508     ret, GLE);
509
510   copy_compsA(&urlSrc, &urlComponents, 32, 1024, 1024, 1024, 2048, 1024);
511   ret = InternetCrackUrl("about://host/blank", 0,0,&urlComponents);
512   ok(ret, "InternetCrackUrl failed with %d\n", GetLastError());
513   ok(!strcmp(urlComponents.lpszScheme, "about"), "lpszScheme was \"%s\" instead of \"about\"\n", urlComponents.lpszScheme);
514   ok(!strcmp(urlComponents.lpszHostName, "host"), "lpszHostName was \"%s\" instead of \"host\"\n", urlComponents.lpszHostName);
515   ok(!strcmp(urlComponents.lpszUrlPath, "/blank"), "lpszUrlPath was \"%s\" instead of \"/blank\"\n", urlComponents.lpszUrlPath);
516
517   /* try a NULL lpszUrl */
518   SetLastError(0xdeadbeef);
519   copy_compsA(&urlSrc, &urlComponents, 32, 1024, 1024, 1024, 2048, 1024);
520   ret = InternetCrackUrl(NULL, 0, 0, &urlComponents);
521   GLE = GetLastError();
522   ok(ret == FALSE, "Expected InternetCrackUrl to fail\n");
523   ok(GLE == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GLE);
524
525   /* try an empty lpszUrl, GetLastError returns 12006, whatever that means
526    * we just need to fail and not return success
527    */
528   SetLastError(0xdeadbeef);
529   copy_compsA(&urlSrc, &urlComponents, 32, 1024, 1024, 1024, 2048, 1024);
530   ret = InternetCrackUrl("", 0, 0, &urlComponents);
531   GLE = GetLastError();
532   ok(ret == FALSE, "Expected InternetCrackUrl to fail\n");
533   ok(GLE != 0xdeadbeef && GLE != ERROR_SUCCESS, "Expected GLE to represent a failure\n");
534
535   /* Invalid Call: must set size of components structure (Windows only
536    * enforces this on the InternetCrackUrlA version of the call) */
537   copy_compsA(&urlSrc, &urlComponents, 0, 1024, 1024, 1024, 2048, 1024);
538   SetLastError(0xdeadbeef);
539   urlComponents.dwStructSize = 0;
540   ret = InternetCrackUrlA(TEST_URL, 0, 0, &urlComponents);
541   ok(ret == FALSE, "Expected InternetCrackUrl to fail\n");
542   ok(GLE != 0xdeadbeef && GLE != ERROR_SUCCESS, "Expected GLE to represent a failure\n");
543
544   /* Invalid Call: size of dwStructSize must be one of the "standard" sizes
545    * of the URL_COMPONENTS structure (Windows only enforces this on the
546    * InternetCrackUrlA version of the call) */
547   copy_compsA(&urlSrc, &urlComponents, 0, 1024, 1024, 1024, 2048, 1024);
548   SetLastError(0xdeadbeef);
549   urlComponents.dwStructSize = sizeof(urlComponents) + 1;
550   ret = InternetCrackUrlA(TEST_URL, 0, 0, &urlComponents);
551   ok(ret == FALSE, "Expected InternetCrackUrl to fail\n");
552   ok(GLE != 0xdeadbeef && GLE != ERROR_SUCCESS, "Expected GLE to represent a failure\n");
553 }
554
555 static void InternetCrackUrlW_test(void)
556 {
557     WCHAR url[] = {
558         'h','t','t','p',':','/','/','1','9','2','.','1','6','8','.','0','.','2','2','/',
559         'C','F','I','D','E','/','m','a','i','n','.','c','f','m','?','C','F','S','V','R',
560         '=','I','D','E','&','A','C','T','I','O','N','=','I','D','E','_','D','E','F','A',
561         'U','L','T', 0 };
562     static const WCHAR url2[] = { '.','.','/','R','i','t','z','.','x','m','l',0 };
563     static const WCHAR url3[] = { 'h','t','t','p',':','/','/','x','.','o','r','g',0 };
564     URL_COMPONENTSW comp;
565     WCHAR scheme[20], host[20], user[20], pwd[20], urlpart[50], extra[50];
566     DWORD error;
567     BOOL r;
568
569     urlpart[0]=0;
570     scheme[0]=0;
571     extra[0]=0;
572     host[0]=0;
573     user[0]=0;
574     pwd[0]=0;
575     memset(&comp, 0, sizeof comp);
576     comp.dwStructSize = sizeof(comp);
577     comp.lpszScheme = scheme;
578     comp.dwSchemeLength = sizeof(scheme)/sizeof(scheme[0]);
579     comp.lpszHostName = host;
580     comp.dwHostNameLength = sizeof(host)/sizeof(host[0]);
581     comp.lpszUserName = user;
582     comp.dwUserNameLength = sizeof(user)/sizeof(user[0]);
583     comp.lpszPassword = pwd;
584     comp.dwPasswordLength = sizeof(pwd)/sizeof(pwd[0]);
585     comp.lpszUrlPath = urlpart;
586     comp.dwUrlPathLength = sizeof(urlpart)/sizeof(urlpart[0]);
587     comp.lpszExtraInfo = extra;
588     comp.dwExtraInfoLength = sizeof(extra)/sizeof(extra[0]);
589
590     SetLastError(0xdeadbeef);
591     r = InternetCrackUrlW(NULL, 0, 0, &comp );
592     error = GetLastError();
593     if (!r && error == ERROR_CALL_NOT_IMPLEMENTED)
594     {
595         win_skip("InternetCrackUrlW is not implemented\n");
596         return;
597     }
598     ok( !r, "InternetCrackUrlW succeeded unexpectedly\n");
599     ok( error == ERROR_INVALID_PARAMETER ||
600         broken(error == ERROR_INTERNET_UNRECOGNIZED_SCHEME), /* IE5 */
601         "expected ERROR_INVALID_PARAMETER got %u\n", error);
602
603     if (error == ERROR_INVALID_PARAMETER)
604     {
605         /* Crashes on IE5 */
606         SetLastError(0xdeadbeef);
607         r = InternetCrackUrlW(url, 0, 0, NULL );
608         error = GetLastError();
609         ok( !r, "InternetCrackUrlW succeeded unexpectedly\n");
610         ok( error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER got %u\n", error);
611     }
612
613     r = InternetCrackUrlW(url, 0, 0, &comp );
614     ok( r, "failed to crack url\n");
615     ok( comp.dwSchemeLength == 4, "scheme length wrong\n");
616     ok( comp.dwHostNameLength == 12, "host length wrong\n");
617     ok( comp.dwUserNameLength == 0, "user length wrong\n");
618     ok( comp.dwPasswordLength == 0, "password length wrong\n");
619     ok( comp.dwUrlPathLength == 15, "url length wrong\n");
620     ok( comp.dwExtraInfoLength == 29, "extra length wrong\n");
621  
622     urlpart[0]=0;
623     scheme[0]=0;
624     extra[0]=0;
625     host[0]=0;
626     user[0]=0;
627     pwd[0]=0;
628     memset(&comp, 0, sizeof comp);
629     comp.dwStructSize = sizeof comp;
630     comp.lpszHostName = host;
631     comp.dwHostNameLength = sizeof(host)/sizeof(host[0]);
632     comp.lpszUrlPath = urlpart;
633     comp.dwUrlPathLength = sizeof(urlpart)/sizeof(urlpart[0]);
634
635     r = InternetCrackUrlW(url, 0, 0, &comp );
636     ok( r, "failed to crack url\n");
637     ok( comp.dwSchemeLength == 0, "scheme length wrong\n");
638     ok( comp.dwHostNameLength == 12, "host length wrong\n");
639     ok( comp.dwUserNameLength == 0, "user length wrong\n");
640     ok( comp.dwPasswordLength == 0, "password length wrong\n");
641     ok( comp.dwUrlPathLength == 44, "url length wrong\n");
642     ok( comp.dwExtraInfoLength == 0, "extra length wrong\n");
643
644     urlpart[0]=0;
645     scheme[0]=0;
646     extra[0]=0;
647     host[0]=0;
648     user[0]=0;
649     pwd[0]=0;
650     memset(&comp, 0, sizeof comp);
651     comp.dwStructSize = sizeof comp;
652     comp.lpszHostName = host;
653     comp.dwHostNameLength = sizeof(host)/sizeof(host[0]);
654     comp.lpszUrlPath = urlpart;
655     comp.dwUrlPathLength = sizeof(urlpart)/sizeof(urlpart[0]);
656     comp.lpszExtraInfo = NULL;
657     comp.dwExtraInfoLength = sizeof(extra)/sizeof(extra[0]);
658
659     r = InternetCrackUrlW(url, 0, 0, &comp );
660     ok( r, "failed to crack url\n");
661     ok( comp.dwSchemeLength == 0, "scheme length wrong\n");
662     ok( comp.dwHostNameLength == 12, "host length wrong\n");
663     ok( comp.dwUserNameLength == 0, "user length wrong\n");
664     ok( comp.dwPasswordLength == 0, "password length wrong\n");
665     ok( comp.dwUrlPathLength == 15, "url length wrong\n");
666     ok( comp.dwExtraInfoLength == 29, "extra length wrong\n");
667
668     urlpart[0]=0;
669     scheme[0]=0;
670     extra[0]=0;
671     host[0]=0;
672     user[0]=0;
673     pwd[0]=0;
674     memset(&comp, 0, sizeof(comp));
675     comp.dwStructSize = sizeof(comp);
676     comp.lpszScheme = scheme;
677     comp.dwSchemeLength = sizeof(scheme)/sizeof(scheme[0]);
678     comp.lpszHostName = host;
679     comp.dwHostNameLength = sizeof(host)/sizeof(host[0]);
680     comp.lpszUserName = user;
681     comp.dwUserNameLength = sizeof(user)/sizeof(user[0]);
682     comp.lpszPassword = pwd;
683     comp.dwPasswordLength = sizeof(pwd)/sizeof(pwd[0]);
684     comp.lpszUrlPath = urlpart;
685     comp.dwUrlPathLength = sizeof(urlpart)/sizeof(urlpart[0]);
686     comp.lpszExtraInfo = extra;
687     comp.dwExtraInfoLength = sizeof(extra)/sizeof(extra[0]);
688
689     r = InternetCrackUrlW(url2, 0, 0, &comp);
690     todo_wine {
691     ok(!r, "InternetCrackUrl should have failed\n");
692     ok(GetLastError() == ERROR_INTERNET_UNRECOGNIZED_SCHEME,
693         "InternetCrackUrl should have failed with error ERROR_INTERNET_UNRECOGNIZED_SCHEME instead of error %d\n",
694         GetLastError());
695     }
696
697     /* Test to see whether cracking a URL without a filename initializes urlpart */
698     urlpart[0]=0xba;
699     scheme[0]=0;
700     extra[0]=0;
701     host[0]=0;
702     user[0]=0;
703     pwd[0]=0;
704     memset(&comp, 0, sizeof comp);
705     comp.dwStructSize = sizeof comp;
706     comp.lpszScheme = scheme;
707     comp.dwSchemeLength = sizeof(scheme)/sizeof(scheme[0]);
708     comp.lpszHostName = host;
709     comp.dwHostNameLength = sizeof(host)/sizeof(host[0]);
710     comp.lpszUserName = user;
711     comp.dwUserNameLength = sizeof(user)/sizeof(user[0]);
712     comp.lpszPassword = pwd;
713     comp.dwPasswordLength = sizeof(pwd)/sizeof(pwd[0]);
714     comp.lpszUrlPath = urlpart;
715     comp.dwUrlPathLength = sizeof(urlpart)/sizeof(urlpart[0]);
716     comp.lpszExtraInfo = extra;
717     comp.dwExtraInfoLength = sizeof(extra)/sizeof(extra[0]);
718     r = InternetCrackUrlW(url3, 0, 0, &comp );
719     ok( r, "InternetCrackUrlW failed unexpectedly\n");
720     ok( host[0] == 'x', "host should be x.org\n");
721     ok( urlpart[0] == 0, "urlpart should be empty\n");
722 }
723
724 static void fill_url_components(LPURL_COMPONENTS lpUrlComponents)
725 {
726     static CHAR http[]       = "http",
727                 winehq[]     = "www.winehq.org",
728                 username[]   = "username",
729                 password[]   = "password",
730                 site_about[] = "/site/about",
731                 empty[]      = "";
732
733     lpUrlComponents->dwStructSize = sizeof(URL_COMPONENTS);
734     lpUrlComponents->lpszScheme = http;
735     lpUrlComponents->dwSchemeLength = strlen(lpUrlComponents->lpszScheme);
736     lpUrlComponents->nScheme = INTERNET_SCHEME_HTTP;
737     lpUrlComponents->lpszHostName = winehq;
738     lpUrlComponents->dwHostNameLength = strlen(lpUrlComponents->lpszHostName);
739     lpUrlComponents->nPort = 80;
740     lpUrlComponents->lpszUserName = username;
741     lpUrlComponents->dwUserNameLength = strlen(lpUrlComponents->lpszUserName);
742     lpUrlComponents->lpszPassword = password;
743     lpUrlComponents->dwPasswordLength = strlen(lpUrlComponents->lpszPassword);
744     lpUrlComponents->lpszUrlPath = site_about;
745     lpUrlComponents->dwUrlPathLength = strlen(lpUrlComponents->lpszUrlPath);
746     lpUrlComponents->lpszExtraInfo = empty;
747     lpUrlComponents->dwExtraInfoLength = strlen(lpUrlComponents->lpszExtraInfo);
748 }
749
750 static void InternetCreateUrlA_test(void)
751 {
752         URL_COMPONENTS urlComp;
753         LPSTR szUrl;
754         DWORD len = -1;
755         BOOL ret;
756         static CHAR empty[]      = "",
757                     nhttp[]      = "nhttp",
758                     http[]       = "http",
759                     https[]      = "https",
760                     winehq[]     = "www.winehq.org",
761                     localhost[]  = "localhost",
762                     username[]   = "username",
763                     password[]   = "password",
764                     root[]       = "/",
765                     site_about[] = "/site/about",
766                     extra_info[] = "?test=123",
767                     about[]      = "about",
768                     blank[]      = "blank",
769                     host[]       = "host";
770
771         /* test NULL lpUrlComponents */
772         SetLastError(0xdeadbeef);
773         ret = InternetCreateUrlA(NULL, 0, NULL, &len);
774         ok(!ret, "Expected failure\n");
775         ok(GetLastError() == ERROR_INVALID_PARAMETER,
776                 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
777         ok(len == -1, "Expected len -1, got %d\n", len);
778
779         /* test zero'ed lpUrlComponents */
780         ZeroMemory(&urlComp, sizeof(URL_COMPONENTS));
781         SetLastError(0xdeadbeef);
782         ret = InternetCreateUrlA(&urlComp, 0, NULL, &len);
783         ok(!ret, "Expected failure\n");
784         ok(GetLastError() == ERROR_INVALID_PARAMETER,
785                 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
786         ok(len == -1, "Expected len -1, got %d\n", len);
787
788         /* test valid lpUrlComponents, NULL lpdwUrlLength */
789         fill_url_components(&urlComp);
790         SetLastError(0xdeadbeef);
791         ret = InternetCreateUrlA(&urlComp, 0, NULL, NULL);
792         ok(!ret, "Expected failure\n");
793         ok(GetLastError() == ERROR_INVALID_PARAMETER,
794                 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
795         ok(len == -1, "Expected len -1, got %d\n", len);
796
797         /* test valid lpUrlComponents, empty szUrl
798          * lpdwUrlLength is size of buffer required on exit, including
799          * the terminating null when GLE == ERROR_INSUFFICIENT_BUFFER
800          */
801         SetLastError(0xdeadbeef);
802         ret = InternetCreateUrlA(&urlComp, 0, NULL, &len);
803         ok(!ret, "Expected failure\n");
804         ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
805                 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
806         ok(len == 51, "Expected len 51, got %d\n", len);
807
808         /* test correct size, NULL szUrl */
809         fill_url_components(&urlComp);
810         SetLastError(0xdeadbeef);
811         ret = InternetCreateUrlA(&urlComp, 0, NULL, &len);
812         ok(!ret, "Expected failure\n");
813         ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
814                 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
815         ok(len == 51, "Expected len 51, got %d\n", len);
816
817         /* test valid lpUrlComponents, alloc-ed szUrl, small size */
818         SetLastError(0xdeadbeef);
819         szUrl = HeapAlloc(GetProcessHeap(), 0, len);
820         len -= 2;
821         ret = InternetCreateUrlA(&urlComp, 0, szUrl, &len);
822         ok(!ret, "Expected failure\n");
823         ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
824                 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
825         ok(len == 51, "Expected len 51, got %d\n", len);
826
827         /* alloc-ed szUrl, NULL lpszScheme
828          * shows that it uses nScheme instead
829          */
830         SetLastError(0xdeadbeef);
831         urlComp.lpszScheme = NULL;
832         ret = InternetCreateUrlA(&urlComp, 0, szUrl, &len);
833         ok(ret, "Expected success\n");
834         ok(GetLastError() == 0xdeadbeef,
835                 "Expected 0xdeadbeef, got %d\n", GetLastError());
836         ok(len == 50, "Expected len 50, got %d\n", len);
837         ok(!strcmp(szUrl, CREATE_URL1), "Expected %s, got %s\n", CREATE_URL1, szUrl);
838
839         /* alloc-ed szUrl, invalid nScheme
840          * any nScheme out of range seems ignored
841          */
842         fill_url_components(&urlComp);
843         SetLastError(0xdeadbeef);
844         urlComp.nScheme = -3;
845         len++;
846         ret = InternetCreateUrlA(&urlComp, 0, szUrl, &len);
847         ok(ret, "Expected success\n");
848         ok(GetLastError() == 0xdeadbeef,
849                 "Expected 0xdeadbeef, got %d\n", GetLastError());
850         ok(len == 50, "Expected len 50, got %d\n", len);
851
852         /* test valid lpUrlComponents, alloc-ed szUrl */
853         fill_url_components(&urlComp);
854         SetLastError(0xdeadbeef);
855         len = 51;
856         ret = InternetCreateUrlA(&urlComp, 0, szUrl, &len);
857         ok(ret, "Expected success\n");
858         ok(GetLastError() == 0xdeadbeef,
859                 "Expected 0xdeadbeef, got %d\n", GetLastError());
860         ok(len == 50, "Expected len 50, got %d\n", len);
861         ok(strstr(szUrl, "80") == NULL, "Didn't expect to find 80 in szUrl\n");
862         ok(!strcmp(szUrl, CREATE_URL1), "Expected %s, got %s\n", CREATE_URL1, szUrl);
863
864         /* valid username, NULL password */
865         fill_url_components(&urlComp);
866         SetLastError(0xdeadbeef);
867         urlComp.lpszPassword = NULL;
868         len = 42;
869         ret = InternetCreateUrlA(&urlComp, 0, szUrl, &len);
870         ok(ret, "Expected success\n");
871         ok(GetLastError() == 0xdeadbeef,
872                 "Expected 0xdeadbeef, got %d\n", GetLastError());
873         ok(len == 41, "Expected len 41, got %d\n", len);
874         ok(!strcmp(szUrl, CREATE_URL2), "Expected %s, got %s\n", CREATE_URL2, szUrl);
875
876         /* valid username, empty password */
877         fill_url_components(&urlComp);
878         SetLastError(0xdeadbeef);
879         urlComp.lpszPassword = empty;
880         len = 51;
881         ret = InternetCreateUrlA(&urlComp, 0, szUrl, &len);
882         ok(ret, "Expected success\n");
883         ok(GetLastError() == 0xdeadbeef,
884                 "Expected 0xdeadbeef, got %d\n", GetLastError());
885         ok(len == 50, "Expected len 50, got %d\n", len);
886         ok(!strcmp(szUrl, CREATE_URL3), "Expected %s, got %s\n", CREATE_URL3, szUrl);
887
888         /* valid password, NULL username
889          * if password is provided, username has to exist
890          */
891         fill_url_components(&urlComp);
892         SetLastError(0xdeadbeef);
893         urlComp.lpszUserName = NULL;
894         len = 42;
895         ret = InternetCreateUrlA(&urlComp, 0, szUrl, &len);
896         ok(!ret, "Expected failure\n");
897         ok(GetLastError() == ERROR_INVALID_PARAMETER,
898                 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
899         ok(len == 42, "Expected len 42, got %d\n", len);
900         ok(!strcmp(szUrl, CREATE_URL3), "Expected %s, got %s\n", CREATE_URL3, szUrl);
901
902         /* valid password, empty username
903          * if password is provided, username has to exist
904          */
905         fill_url_components(&urlComp);
906         SetLastError(0xdeadbeef);
907         urlComp.lpszUserName = empty;
908         len = 51;
909         ret = InternetCreateUrlA(&urlComp, 0, szUrl, &len);
910         ok(ret, "Expected success\n");
911         ok(GetLastError() == 0xdeadbeef,
912                 "Expected 0xdeadbeef, got %d\n", GetLastError());
913         ok(len == 50, "Expected len 50, got %d\n", len);
914         ok(!strcmp(szUrl, CREATE_URL5), "Expected %s, got %s\n", CREATE_URL5, szUrl);
915
916         /* NULL username, NULL password */
917         fill_url_components(&urlComp);
918         SetLastError(0xdeadbeef);
919         urlComp.lpszUserName = NULL;
920         urlComp.lpszPassword = NULL;
921         len = 42;
922         ret = InternetCreateUrlA(&urlComp, 0, szUrl, &len);
923         ok(ret, "Expected success\n");
924         ok(GetLastError() == 0xdeadbeef,
925                 "Expected 0xdeadbeef, got %d\n", GetLastError());
926         ok(len == 32, "Expected len 32, got %d\n", len);
927         ok(!strcmp(szUrl, CREATE_URL4), "Expected %s, got %s\n", CREATE_URL4, szUrl);
928
929         /* empty username, empty password */
930         fill_url_components(&urlComp);
931         SetLastError(0xdeadbeef);
932         urlComp.lpszUserName = empty;
933         urlComp.lpszPassword = empty;
934         len = 51;
935         ret = InternetCreateUrlA(&urlComp, 0, szUrl, &len);
936         ok(ret, "Expected success\n");
937         ok(GetLastError() == 0xdeadbeef,
938                 "Expected 0xdeadbeef, got %d\n", GetLastError());
939         ok(len == 50, "Expected len 50, got %d\n", len);
940         ok(!strcmp(szUrl, CREATE_URL5), "Expected %s, got %s\n", CREATE_URL5, szUrl);
941
942         /* shows that nScheme is ignored, as the appearance of the port number
943          * depends on lpszScheme and the string copied depends on lpszScheme.
944          */
945         fill_url_components(&urlComp);
946         HeapFree(GetProcessHeap(), 0, szUrl);
947         urlComp.lpszScheme = nhttp;
948         urlComp.dwSchemeLength = strlen(urlComp.lpszScheme);
949         len = strlen(CREATE_URL6) + 1;
950         szUrl = HeapAlloc(GetProcessHeap(), 0, len);
951         ret = InternetCreateUrlA(&urlComp, ICU_ESCAPE, szUrl, &len);
952         ok(ret, "Expected success\n");
953         ok(len == strlen(CREATE_URL6), "Expected len %d, got %d\n", lstrlenA(CREATE_URL6) + 1, len);
954         ok(!strcmp(szUrl, CREATE_URL6), "Expected %s, got %s\n", CREATE_URL6, szUrl);
955
956         /* if lpszScheme != "http" or nPort != 80, display nPort */
957         HeapFree(GetProcessHeap(), 0, szUrl);
958         urlComp.lpszScheme = http;
959         urlComp.dwSchemeLength = strlen(urlComp.lpszScheme);
960         urlComp.nPort = 42;
961         szUrl = HeapAlloc(GetProcessHeap(), 0, ++len);
962         ret = InternetCreateUrlA(&urlComp, ICU_ESCAPE, szUrl, &len);
963         ok(ret, "Expected success\n");
964         ok(len == 53, "Expected len 53, got %d\n", len);
965         ok(strstr(szUrl, "42") != NULL, "Expected to find 42 in szUrl\n");
966         ok(!strcmp(szUrl, CREATE_URL7), "Expected %s, got %s\n", CREATE_URL7, szUrl);
967
968         HeapFree(GetProcessHeap(), 0, szUrl);
969
970         memset(&urlComp, 0, sizeof(urlComp));
971         urlComp.dwStructSize = sizeof(URL_COMPONENTS);
972         urlComp.lpszScheme = http;
973         urlComp.dwSchemeLength = 0;
974         urlComp.nScheme = INTERNET_SCHEME_HTTP;
975         urlComp.lpszHostName = winehq;
976         urlComp.dwHostNameLength = 0;
977         urlComp.nPort = 80;
978         urlComp.lpszUserName = username;
979         urlComp.dwUserNameLength = 0;
980         urlComp.lpszPassword = password;
981         urlComp.dwPasswordLength = 0;
982         urlComp.lpszUrlPath = site_about;
983         urlComp.dwUrlPathLength = 0;
984         urlComp.lpszExtraInfo = empty;
985         urlComp.dwExtraInfoLength = 0;
986         len = strlen(CREATE_URL1);
987         szUrl = HeapAlloc(GetProcessHeap(), 0, ++len);
988         ret = InternetCreateUrlA(&urlComp, ICU_ESCAPE, szUrl, &len);
989         ok(ret, "Expected success\n");
990         ok(len == strlen(CREATE_URL1), "Expected len %d, got %d\n", lstrlenA(CREATE_URL1), len);
991         ok(!strcmp(szUrl, CREATE_URL1), "Expected %s, got %s\n", CREATE_URL1, szUrl);
992
993         HeapFree(GetProcessHeap(), 0, szUrl);
994
995         memset(&urlComp, 0, sizeof(urlComp));
996         urlComp.dwStructSize = sizeof(URL_COMPONENTS);
997         urlComp.lpszScheme = https;
998         urlComp.dwSchemeLength = 0;
999         urlComp.nScheme = INTERNET_SCHEME_HTTP;
1000         urlComp.lpszHostName = winehq;
1001         urlComp.dwHostNameLength = 0;
1002         urlComp.nPort = 443;
1003         urlComp.lpszUserName = username;
1004         urlComp.dwUserNameLength = 0;
1005         urlComp.lpszPassword = password;
1006         urlComp.dwPasswordLength = 0;
1007         urlComp.lpszUrlPath = site_about;
1008         urlComp.dwUrlPathLength = 0;
1009         urlComp.lpszExtraInfo = empty;
1010         urlComp.dwExtraInfoLength = 0;
1011         len = strlen(CREATE_URL8);
1012         szUrl = HeapAlloc(GetProcessHeap(), 0, ++len);
1013         ret = InternetCreateUrlA(&urlComp, ICU_ESCAPE, szUrl, &len);
1014         ok(ret, "Expected success\n");
1015         ok(len == strlen(CREATE_URL8), "Expected len %d, got %d\n", lstrlenA(CREATE_URL8), len);
1016         ok(!strcmp(szUrl, CREATE_URL8), "Expected %s, got %s\n", CREATE_URL8, szUrl);
1017
1018         HeapFree(GetProcessHeap(), 0, szUrl);
1019
1020         memset(&urlComp, 0, sizeof(urlComp));
1021         urlComp.dwStructSize = sizeof(URL_COMPONENTS);
1022         urlComp.lpszScheme = about;
1023         urlComp.dwSchemeLength = 5;
1024         urlComp.lpszUrlPath = blank;
1025         urlComp.dwUrlPathLength = 5;
1026         len = strlen(CREATE_URL9);
1027         len++; /* work around bug in native wininet */
1028         szUrl = HeapAlloc(GetProcessHeap(), 0, ++len);
1029         ret = InternetCreateUrlA(&urlComp, ICU_ESCAPE, szUrl, &len);
1030         ok(ret, "Expected success\n");
1031         ok(len == strlen(CREATE_URL9), "Expected len %d, got %d\n", lstrlenA(CREATE_URL9), len);
1032         ok(!strcmp(szUrl, CREATE_URL9), "Expected %s, got %s\n", CREATE_URL9, szUrl);
1033
1034         HeapFree(GetProcessHeap(), 0, szUrl);
1035
1036         memset(&urlComp, 0, sizeof(urlComp));
1037         urlComp.dwStructSize = sizeof(URL_COMPONENTS);
1038         urlComp.lpszScheme = about;
1039         urlComp.lpszHostName = host;
1040         urlComp.lpszUrlPath = blank;
1041         len = strlen(CREATE_URL10);
1042         len++; /* work around bug in native wininet */
1043         szUrl = HeapAlloc(GetProcessHeap(), 0, ++len);
1044         ret = InternetCreateUrlA(&urlComp, ICU_ESCAPE, szUrl, &len);
1045         ok(ret, "Expected success\n");
1046         ok(len == strlen(CREATE_URL10), "Expected len %d, got %d\n", lstrlenA(CREATE_URL10), len);
1047         ok(!strcmp(szUrl, CREATE_URL10), "Expected %s, got %s\n", CREATE_URL10, szUrl);
1048
1049         HeapFree(GetProcessHeap(), 0, szUrl);
1050
1051         memset(&urlComp, 0, sizeof(urlComp));
1052         urlComp.dwStructSize = sizeof(URL_COMPONENTS);
1053         urlComp.nPort = 8080;
1054         urlComp.lpszScheme = about;
1055         len = strlen(CREATE_URL11);
1056         szUrl = HeapAlloc(GetProcessHeap(), 0, ++len);
1057         ret = InternetCreateUrlA(&urlComp, ICU_ESCAPE, szUrl, &len);
1058         ok(ret, "Expected success\n");
1059         ok(len == strlen(CREATE_URL11), "Expected len %d, got %d\n", lstrlenA(CREATE_URL11), len);
1060         ok(!strcmp(szUrl, CREATE_URL11), "Expected %s, got %s\n", CREATE_URL11, szUrl);
1061
1062         HeapFree(GetProcessHeap(), 0, szUrl);
1063
1064         memset(&urlComp, 0, sizeof(urlComp));
1065         urlComp.dwStructSize = sizeof(URL_COMPONENTS);
1066         urlComp.lpszScheme = http;
1067         urlComp.dwSchemeLength = 0;
1068         urlComp.nScheme = INTERNET_SCHEME_HTTP;
1069         urlComp.lpszHostName = winehq;
1070         urlComp.dwHostNameLength = 0;
1071         urlComp.nPort = 65535;
1072         len = strlen(CREATE_URL12);
1073         szUrl = HeapAlloc(GetProcessHeap(), 0, ++len);
1074         ret = InternetCreateUrlA(&urlComp, ICU_ESCAPE, szUrl, &len);
1075         ok(ret, "Expected success\n");
1076         ok(len == strlen(CREATE_URL12), "Expected len %d, got %d\n", lstrlenA(CREATE_URL12), len);
1077         ok(!strcmp(szUrl, CREATE_URL12), "Expected %s, got %s\n", CREATE_URL12, szUrl);
1078
1079         HeapFree(GetProcessHeap(), 0, szUrl);
1080
1081     memset(&urlComp, 0, sizeof(urlComp));
1082     urlComp.dwStructSize = sizeof(URL_COMPONENTS);
1083     urlComp.lpszScheme = http;
1084     urlComp.dwSchemeLength = strlen(urlComp.lpszScheme);
1085     urlComp.lpszHostName = localhost;
1086     urlComp.dwHostNameLength = strlen(urlComp.lpszHostName);
1087     urlComp.nPort = 80;
1088     urlComp.lpszUrlPath = root;
1089     urlComp.dwUrlPathLength = strlen(urlComp.lpszUrlPath);
1090     urlComp.lpszExtraInfo = extra_info;
1091     urlComp.dwExtraInfoLength = strlen(urlComp.lpszExtraInfo);
1092     len = 256;
1093     szUrl = HeapAlloc(GetProcessHeap(), 0, len);
1094     InternetCreateUrlA(&urlComp, ICU_ESCAPE, szUrl, &len);
1095     ok(ret, "Expected success\n");
1096     ok(len == strlen(CREATE_URL13), "Got len %u\n", len);
1097     ok(!strcmp(szUrl, CREATE_URL13), "Expected \"%s\", got \"%s\"\n", CREATE_URL13, szUrl);
1098
1099     HeapFree(GetProcessHeap(), 0, szUrl);
1100 }
1101
1102 START_TEST(url)
1103 {
1104     int i;
1105
1106     if(!GetProcAddress(GetModuleHandleA("wininet.dll"), "InternetGetCookieExW")) {
1107         win_skip("Too old IE (older than 6.0)\n");
1108         return;
1109     }
1110
1111     for(i=0; i < sizeof(crack_url_tests)/sizeof(*crack_url_tests); i++)
1112         test_crack_url(crack_url_tests+i);
1113
1114     InternetCrackUrl_test();
1115     InternetCrackUrlW_test();
1116     InternetCreateUrlA_test();
1117 }