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