wininet: Implement PER_CONN_FLAGS option.
[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 } crack_url_test_t;
110
111 static const crack_url_test_t crack_url_tests[] = {
112     {"http://www.winehq.org/site/about#hi",
113         0, 4, INTERNET_SCHEME_HTTP, 7, 14, -1, 80, -1, 0, -1, 0, 21, 11, 32, 3},
114     {"http://www.myserver.com/myscript.php?arg=1",
115         0, 4, INTERNET_SCHEME_HTTP, 7, 16, -1, 80, -1, 0, -1, 0, 23, 13, 36, 6},
116     {"http://www.winehq.org?test=123",
117         0, 4, INTERNET_SCHEME_HTTP, 7, 14, 23, 80, -1, 0, -1, 0, 21, 0, 21, 9},
118     {"file:///C:/Program%20Files/Atmel/AVR%20Tools/STK500/STK500.xml",
119         0, 4, INTERNET_SCHEME_FILE, -1, 0, -1, 0, -1, 0, -1, 0, 7, 55, -1, 0},
120     {"fide:///C:/Program%20Files/Atmel/AVR%20Tools/STK500/STK500.xml",
121         0, 4, INTERNET_SCHEME_UNKNOWN, 7, 0, -1, 0, -1, 0, -1, 0, 7, 55, -1, 0},
122     {"file://C:/Program%20Files/Atmel/AVR%20Tools/STK500/STK500.xml",
123         0, 4, INTERNET_SCHEME_FILE, -1, 0, -1, 0, -1, 0, -1, 0, 7, 54, -1, 0},
124 };
125
126 static void test_crack_url(const crack_url_test_t *test)
127 {
128     WCHAR buf[INTERNET_MAX_URL_LENGTH];
129     URL_COMPONENTSW urlw;
130     URL_COMPONENTSA url;
131     BOOL b;
132
133     zero_compsA(&url, 1, 1, 1, 1, 1, 1);
134
135     b = InternetCrackUrlA(test->url, strlen(test->url), 0, &url);
136     ok(b, "InternetCrackUrl failed with error %d\n", GetLastError());
137
138     if(test->scheme_off == -1)
139         ok(!url.lpszScheme, "[%s] url.lpszScheme = %p, expected NULL\n", test->url, url.lpszScheme);
140     else
141         ok(url.lpszScheme == test->url+test->scheme_off, "[%s] url.lpszScheme = %p, expected %p\n",
142            test->url, url.lpszScheme, test->url+test->scheme_off);
143     ok(url.dwSchemeLength == test->scheme_len, "[%s] url.lpszSchemeLength = %d, expected %d\n",
144        test->url, url.dwSchemeLength, test->scheme_len);
145
146     ok(url.nScheme == test->scheme, "[%s] url.nScheme = %d, expected %d\n", test->url, url.nScheme, test->scheme);
147
148     if(test->host_off == -1)
149         ok(!url.lpszHostName, "[%s] url.lpszHostName = %p, expected NULL\n", test->url, url.lpszHostName);
150     else
151         ok(url.lpszHostName == test->url+test->host_off, "[%s] url.lpszHostName = %p, expected %p\n",
152            test->url, url.lpszHostName, test->url+test->host_off);
153     if(test->host_skip_broken != -1 && url.dwHostNameLength == test->host_skip_broken) {
154         win_skip("skipping broken dwHostNameLength result\n");
155         return;
156     }
157     ok(url.dwHostNameLength == test->host_len, "[%s] url.lpszHostNameLength = %d, expected %d\n",
158        test->url, url.dwHostNameLength, test->host_len);
159
160     ok(url.nPort == test->port, "[%s] nPort = %d, expected %d\n", test->url, url.nPort, test->port);
161
162     if(test->user_off == -1)
163         ok(!url.lpszUserName, "[%s] url.lpszUserName = %p\n", test->url, url.lpszUserName);
164     else
165         ok(url.lpszUserName == test->url+test->user_off, "[%s] url.lpszUserName = %p, expected %p\n",
166            test->url, url.lpszUserName, test->url+test->user_off);
167     ok(url.dwUserNameLength == test->user_len, "[%s] url.lpszUserNameLength = %d, expected %d\n",
168        test->url, url.dwUserNameLength, test->user_len);
169
170     if(test->pass_off == -1)
171         ok(!url.lpszPassword, "[%s] url.lpszPassword = %p\n", test->url, url.lpszPassword);
172     else
173         ok(url.lpszPassword == test->url+test->pass_off, "[%s] url.lpszPassword = %p, expected %p\n",
174            test->url, url.lpszPassword, test->url+test->pass_off);
175     ok(url.dwPasswordLength == test->pass_len, "[%s] url.lpszPasswordLength = %d, expected %d\n",
176        test->url, url.dwPasswordLength, test->pass_len);
177
178     if(test->path_off == -1)
179         ok(!url.lpszUrlPath, "[%s] url.lpszPath = %p, expected NULL\n", test->url, url.lpszUrlPath);
180     else
181         ok(url.lpszUrlPath == test->url+test->path_off, "[%s] url.lpszPath = %p, expected %p\n",
182            test->url, url.lpszUrlPath, test->url+test->path_off);
183     ok(url.dwUrlPathLength == test->path_len, "[%s] url.lpszUrlPathLength = %d, expected %d\n",
184        test->url, url.dwUrlPathLength, test->path_len);
185
186     if(test->extra_off == -1)
187         ok(!url.lpszExtraInfo, "[%s] url.lpszExtraInfo = %p, expected NULL\n", test->url, url.lpszExtraInfo);
188     else
189         ok(url.lpszExtraInfo == test->url+test->extra_off, "[%s] url.lpszExtraInfo = %p, expected %p\n",
190            test->url, url.lpszExtraInfo, test->url+test->extra_off);
191     ok(url.dwExtraInfoLength == test->extra_len, "[%s] url.lpszExtraInfoLength = %d, expected %d\n",
192        test->url, url.dwExtraInfoLength, test->extra_len);
193
194     memset(&urlw, 0, sizeof(URL_COMPONENTSW));
195     urlw.dwStructSize = sizeof(URL_COMPONENTSW);
196     urlw.dwSchemeLength = 1;
197     urlw.dwHostNameLength = 1;
198     urlw.dwUserNameLength = 1;
199     urlw.dwPasswordLength = 1;
200     urlw.dwUrlPathLength = 1;
201     urlw.dwExtraInfoLength = 1;
202
203     MultiByteToWideChar(CP_ACP, 0, test->url, -1, buf, sizeof(buf));
204     b = InternetCrackUrlW(buf, lstrlenW(buf), 0, &urlw);
205     if(!b && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) {
206         win_skip("InternetCrackUrlW is not implemented\n");
207         return;
208     }
209     ok(b, "InternetCrackUrl failed with error %d\n", GetLastError());
210
211     if(test->scheme_off == -1)
212         ok(!urlw.lpszScheme, "[%s] urlw.lpszScheme = %p, expected NULL\n", test->url, urlw.lpszScheme);
213     else
214         ok(urlw.lpszScheme == buf+test->scheme_off, "[%s] urlw.lpszScheme = %p, expected %p\n",
215            test->url, urlw.lpszScheme, buf+test->scheme_off);
216     ok(urlw.dwSchemeLength == test->scheme_len, "[%s] urlw.lpszSchemeLength = %d, expected %d\n",
217        test->url, urlw.dwSchemeLength, test->scheme_len);
218
219     ok(urlw.nScheme == test->scheme, "[%s] urlw.nScheme = %d, expected %d\n", test->url, urlw.nScheme, test->scheme);
220
221     if(test->host_off == -1) {
222         ok(!urlw.lpszHostName, "[%s] urlw.lpszHostName = %p, expected NULL\n", test->url, urlw.lpszHostName);
223         ok(urlw.dwHostNameLength == 0 || broken(urlw.dwHostNameLength == 1), "[%s] urlw.lpszHostNameLength = %d, expected %d\n",
224            test->url, urlw.dwHostNameLength, test->host_len);
225     }else {
226         ok(urlw.lpszHostName == buf+test->host_off, "[%s] urlw.lpszHostName = %p, expected %p\n",
227            test->url, urlw.lpszHostName, test->url+test->host_off);
228         ok(urlw.dwHostNameLength == test->host_len, "[%s] urlw.lpszHostNameLength = %d, expected %d\n",
229            test->url, urlw.dwHostNameLength, test->host_len);
230     }
231
232     ok(urlw.nPort == test->port, "[%s] nPort = %d, expected %d\n", test->url, urlw.nPort, test->port);
233
234     if(test->user_off == -1) {
235         ok(!urlw.lpszUserName, "[%s] urlw.lpszUserName = %p\n", test->url, urlw.lpszUserName);
236         ok(urlw.dwUserNameLength == 0 || broken(urlw.dwUserNameLength == 1), "[%s] urlw.lpszUserNameLength = %d, expected %d\n",
237            test->url, urlw.dwUserNameLength, test->user_len);
238     }else {
239         ok(urlw.lpszUserName == buf+test->user_off, "[%s] urlw.lpszUserName = %p, expected %p\n",
240            test->url, urlw.lpszUserName, buf+test->user_off);
241         ok(urlw.dwUserNameLength == test->user_len, "[%s] urlw.lpszUserNameLength = %d, expected %d\n",
242            test->url, urlw.dwUserNameLength, test->user_len);
243     }
244
245     if(test->pass_off == -1) {
246         ok(!urlw.lpszPassword, "[%s] urlw.lpszPassword = %p\n", test->url, urlw.lpszPassword);
247         ok(urlw.dwPasswordLength == 0 || broken(urlw.dwPasswordLength), "[%s] urlw.lpszPasswordLength = %d, expected %d\n",
248            test->url, urlw.dwPasswordLength, test->pass_len);
249     }else {
250         ok(urlw.lpszPassword == buf+test->pass_off, "[%s] urlw.lpszPassword = %p, expected %p\n",
251            test->url, urlw.lpszPassword, buf+test->pass_off);
252         ok(urlw.dwPasswordLength == test->pass_len, "[%s] urlw.lpszPasswordLength = %d, expected %d\n",
253            test->url, urlw.dwPasswordLength, test->pass_len);
254     }
255
256     if(test->path_off == -1)
257         ok(!urlw.lpszUrlPath, "[%s] urlw.lpszPath = %p, expected NULL\n", test->url, urlw.lpszUrlPath);
258     else
259         ok(urlw.lpszUrlPath == buf+test->path_off, "[%s] urlw.lpszPath = %p, expected %p\n",
260            test->url, urlw.lpszUrlPath, buf+test->path_off);
261     ok(urlw.dwUrlPathLength == test->path_len, "[%s] urlw.lpszUrlPathLength = %d, expected %d\n",
262        test->url, urlw.dwUrlPathLength, test->path_len);
263
264     if(test->extra_off == -1) {
265         ok(!urlw.lpszExtraInfo, "[%s] url.lpszExtraInfo = %p, expected NULL\n", test->url, urlw.lpszExtraInfo);
266         ok(urlw.dwExtraInfoLength == 0 || broken(urlw.dwExtraInfoLength == 1), "[%s] urlw.lpszExtraInfoLength = %d, expected %d\n",
267            test->url, urlw.dwExtraInfoLength, test->extra_len);
268     }else {
269         ok(urlw.lpszExtraInfo == buf+test->extra_off, "[%s] urlw.lpszExtraInfo = %p, expected %p\n",
270            test->url, urlw.lpszExtraInfo, buf+test->extra_off);
271         ok(urlw.dwExtraInfoLength == test->extra_len, "[%s] urlw.lpszExtraInfoLength = %d, expected %d\n",
272            test->url, urlw.dwExtraInfoLength, test->extra_len);
273     }
274 }
275
276 static void InternetCrackUrl_test(void)
277 {
278   URL_COMPONENTSA urlSrc, urlComponents;
279   char protocol[32], hostName[1024], userName[1024];
280   char password[1024], extra[1024], path[1024];
281   BOOL ret, firstret;
282   DWORD GLE, firstGLE;
283
284   ZeroMemory(&urlSrc, sizeof(urlSrc));
285   urlSrc.dwStructSize = sizeof(urlSrc);
286   urlSrc.lpszScheme = protocol;
287   urlSrc.lpszHostName = hostName;
288   urlSrc.lpszUserName = userName;
289   urlSrc.lpszPassword = password;
290   urlSrc.lpszUrlPath = path;
291   urlSrc.lpszExtraInfo = extra;
292
293   /* Tests for lpsz* members pointing to real strings while 
294    * some corresponding length members are set to zero.
295    * As of IE7 (wininet 7.0*?) all members are checked. So we
296    * run the first test and expect the outcome to be the same
297    * for the first four (scheme, hostname, username and password).
298    * The last two (path and extrainfo) are the same for all versions
299    * of the wininet.dll.
300    */
301   copy_compsA(&urlSrc, &urlComponents, 0, 1024, 1024, 1024, 2048, 1024);
302   SetLastError(0xdeadbeef);
303   firstret = InternetCrackUrlA(TEST_URL3, 0, ICU_DECODE, &urlComponents);
304   firstGLE = GetLastError();
305
306   copy_compsA(&urlSrc, &urlComponents, 32, 0, 1024, 1024, 2048, 1024);
307   SetLastError(0xdeadbeef);
308   ret = InternetCrackUrlA(TEST_URL3, 0, ICU_DECODE, &urlComponents);
309   GLE = GetLastError();
310   ok(ret==firstret && (GLE==firstGLE), "InternetCrackUrl returned %d with GLE=%d (expected to return %d)\n",
311     ret, GetLastError(), firstret);
312
313   copy_compsA(&urlSrc, &urlComponents, 32, 1024, 0, 1024, 2048, 1024);
314   SetLastError(0xdeadbeef);
315   ret = InternetCrackUrlA(TEST_URL3, 0, ICU_DECODE, &urlComponents);
316   GLE = GetLastError();
317   ok(ret==firstret && (GLE==firstGLE), "InternetCrackUrl returned %d with GLE=%d (expected to return %d)\n",
318     ret, GetLastError(), firstret);
319
320   copy_compsA(&urlSrc, &urlComponents, 32, 1024, 1024, 0, 2048, 1024);
321   SetLastError(0xdeadbeef);
322   ret = InternetCrackUrlA(TEST_URL3, 0, ICU_DECODE, &urlComponents);
323   GLE = GetLastError();
324   ok(ret==firstret && (GLE==firstGLE), "InternetCrackUrl returned %d with GLE=%d (expected to return %d)\n",
325     ret, GetLastError(), firstret);
326
327   copy_compsA(&urlSrc, &urlComponents, 32, 1024, 1024, 1024, 0, 1024);
328   SetLastError(0xdeadbeef);
329   ret = InternetCrackUrlA(TEST_URL3, 0, ICU_DECODE, &urlComponents);
330   GLE = GetLastError();
331   todo_wine
332   ok(ret==0 && (GLE==ERROR_INVALID_HANDLE || GLE==ERROR_INSUFFICIENT_BUFFER),
333      "InternetCrackUrl returned %d with GLE=%d (expected to return 0 and ERROR_INVALID_HANDLE or ERROR_INSUFFICIENT_BUFFER)\n",
334     ret, GLE);
335
336   copy_compsA(&urlSrc, &urlComponents, 32, 1024, 1024, 1024, 2048, 0);
337   SetLastError(0xdeadbeef);
338   ret = InternetCrackUrlA(TEST_URL3, 0, ICU_DECODE, &urlComponents);
339   GLE = GetLastError();
340   todo_wine
341   ok(ret==0 && (GLE==ERROR_INVALID_HANDLE || GLE==ERROR_INSUFFICIENT_BUFFER),
342      "InternetCrackUrl returned %d with GLE=%d (expected to return 0 and ERROR_INVALID_HANDLE or ERROR_INSUFFICIENT_BUFFER)\n",
343     ret, GLE);
344
345   copy_compsA(&urlSrc, &urlComponents, 0, 0, 0, 0, 0, 0);
346   ret = InternetCrackUrlA(TEST_URL3, 0, ICU_DECODE, &urlComponents);
347   GLE = GetLastError();
348   todo_wine
349   ok(ret==0 && GLE==ERROR_INVALID_PARAMETER,
350      "InternetCrackUrl returned %d with GLE=%d (expected to return 0 and ERROR_INVALID_PARAMETER)\n",
351     ret, GLE);
352
353   copy_compsA(&urlSrc, &urlComponents, 32, 1024, 1024, 1024, 2048, 1024);
354   ret = InternetCrackUrl("about://host/blank", 0,0,&urlComponents);
355   ok(ret, "InternetCrackUrl failed with %d\n", GetLastError());
356   ok(!strcmp(urlComponents.lpszScheme, "about"), "lpszScheme was \"%s\" instead of \"about\"\n", urlComponents.lpszScheme);
357   ok(!strcmp(urlComponents.lpszHostName, "host"), "lpszHostName was \"%s\" instead of \"host\"\n", urlComponents.lpszHostName);
358   ok(!strcmp(urlComponents.lpszUrlPath, "/blank"), "lpszUrlPath was \"%s\" instead of \"/blank\"\n", urlComponents.lpszUrlPath);
359
360   /* try a NULL lpszUrl */
361   SetLastError(0xdeadbeef);
362   copy_compsA(&urlSrc, &urlComponents, 32, 1024, 1024, 1024, 2048, 1024);
363   ret = InternetCrackUrl(NULL, 0, 0, &urlComponents);
364   GLE = GetLastError();
365   ok(ret == FALSE, "Expected InternetCrackUrl to fail\n");
366   ok(GLE == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GLE);
367
368   /* try an empty lpszUrl, GetLastError returns 12006, whatever that means
369    * we just need to fail and not return success
370    */
371   SetLastError(0xdeadbeef);
372   copy_compsA(&urlSrc, &urlComponents, 32, 1024, 1024, 1024, 2048, 1024);
373   ret = InternetCrackUrl("", 0, 0, &urlComponents);
374   GLE = GetLastError();
375   ok(ret == FALSE, "Expected InternetCrackUrl to fail\n");
376   ok(GLE != 0xdeadbeef && GLE != ERROR_SUCCESS, "Expected GLE to represent a failure\n");
377
378   /* Invalid Call: must set size of components structure (Windows only
379    * enforces this on the InternetCrackUrlA version of the call) */
380   copy_compsA(&urlSrc, &urlComponents, 0, 1024, 1024, 1024, 2048, 1024);
381   SetLastError(0xdeadbeef);
382   urlComponents.dwStructSize = 0;
383   ret = InternetCrackUrlA(TEST_URL, 0, 0, &urlComponents);
384   ok(ret == FALSE, "Expected InternetCrackUrl to fail\n");
385   ok(GLE != 0xdeadbeef && GLE != ERROR_SUCCESS, "Expected GLE to represent a failure\n");
386
387   /* Invalid Call: size of dwStructSize must be one of the "standard" sizes
388    * of the URL_COMPONENTS structure (Windows only enforces this on the
389    * InternetCrackUrlA version of the call) */
390   copy_compsA(&urlSrc, &urlComponents, 0, 1024, 1024, 1024, 2048, 1024);
391   SetLastError(0xdeadbeef);
392   urlComponents.dwStructSize = sizeof(urlComponents) + 1;
393   ret = InternetCrackUrlA(TEST_URL, 0, 0, &urlComponents);
394   ok(ret == FALSE, "Expected InternetCrackUrl to fail\n");
395   ok(GLE != 0xdeadbeef && GLE != ERROR_SUCCESS, "Expected GLE to represent a failure\n");
396 }
397
398 static void InternetCrackUrlW_test(void)
399 {
400     WCHAR url[] = {
401         'h','t','t','p',':','/','/','1','9','2','.','1','6','8','.','0','.','2','2','/',
402         'C','F','I','D','E','/','m','a','i','n','.','c','f','m','?','C','F','S','V','R',
403         '=','I','D','E','&','A','C','T','I','O','N','=','I','D','E','_','D','E','F','A',
404         'U','L','T', 0 };
405     static const WCHAR url2[] = { '.','.','/','R','i','t','z','.','x','m','l',0 };
406     static const WCHAR url3[] = { 'h','t','t','p',':','/','/','x','.','o','r','g',0 };
407     URL_COMPONENTSW comp;
408     WCHAR scheme[20], host[20], user[20], pwd[20], urlpart[50], extra[50];
409     DWORD error;
410     BOOL r;
411
412     urlpart[0]=0;
413     scheme[0]=0;
414     extra[0]=0;
415     host[0]=0;
416     user[0]=0;
417     pwd[0]=0;
418     memset(&comp, 0, sizeof comp);
419     comp.dwStructSize = sizeof comp;
420     comp.lpszScheme = scheme;
421     comp.dwSchemeLength = sizeof scheme;
422     comp.lpszHostName = host;
423     comp.dwHostNameLength = sizeof host;
424     comp.lpszUserName = user;
425     comp.dwUserNameLength = sizeof user;
426     comp.lpszPassword = pwd;
427     comp.dwPasswordLength = sizeof pwd;
428     comp.lpszUrlPath = urlpart;
429     comp.dwUrlPathLength = sizeof urlpart;
430     comp.lpszExtraInfo = extra;
431     comp.dwExtraInfoLength = sizeof extra;
432
433     SetLastError(0xdeadbeef);
434     r = InternetCrackUrlW(NULL, 0, 0, &comp );
435     error = GetLastError();
436     if (!r && error == ERROR_CALL_NOT_IMPLEMENTED)
437     {
438         win_skip("InternetCrackUrlW is not implemented\n");
439         return;
440     }
441     ok( !r, "InternetCrackUrlW succeeded unexpectedly\n");
442     ok( error == ERROR_INVALID_PARAMETER ||
443         broken(error == ERROR_INTERNET_UNRECOGNIZED_SCHEME), /* IE5 */
444         "expected ERROR_INVALID_PARAMETER got %u\n", error);
445
446     if (error == ERROR_INVALID_PARAMETER)
447     {
448         /* Crashes on IE5 */
449         SetLastError(0xdeadbeef);
450         r = InternetCrackUrlW(url, 0, 0, NULL );
451         error = GetLastError();
452         ok( !r, "InternetCrackUrlW succeeded unexpectedly\n");
453         ok( error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER got %u\n", error);
454     }
455
456     r = InternetCrackUrlW(url, 0, 0, &comp );
457     ok( r, "failed to crack url\n");
458     ok( comp.dwSchemeLength == 4, "scheme length wrong\n");
459     ok( comp.dwHostNameLength == 12, "host length wrong\n");
460     ok( comp.dwUserNameLength == 0, "user length wrong\n");
461     ok( comp.dwPasswordLength == 0, "password length wrong\n");
462     ok( comp.dwUrlPathLength == 15, "url length wrong\n");
463     ok( comp.dwExtraInfoLength == 29, "extra length wrong\n");
464  
465     urlpart[0]=0;
466     scheme[0]=0;
467     extra[0]=0;
468     host[0]=0;
469     user[0]=0;
470     pwd[0]=0;
471     memset(&comp, 0, sizeof comp);
472     comp.dwStructSize = sizeof comp;
473     comp.lpszHostName = host;
474     comp.dwHostNameLength = sizeof host;
475     comp.lpszUrlPath = urlpart;
476     comp.dwUrlPathLength = sizeof urlpart;
477
478     r = InternetCrackUrlW(url, 0, 0, &comp );
479     ok( r, "failed to crack url\n");
480     ok( comp.dwSchemeLength == 0, "scheme length wrong\n");
481     ok( comp.dwHostNameLength == 12, "host length wrong\n");
482     ok( comp.dwUserNameLength == 0, "user length wrong\n");
483     ok( comp.dwPasswordLength == 0, "password length wrong\n");
484     ok( comp.dwUrlPathLength == 44, "url length wrong\n");
485     ok( comp.dwExtraInfoLength == 0, "extra length wrong\n");
486
487     urlpart[0]=0;
488     scheme[0]=0;
489     extra[0]=0;
490     host[0]=0;
491     user[0]=0;
492     pwd[0]=0;
493     memset(&comp, 0, sizeof comp);
494     comp.dwStructSize = sizeof comp;
495     comp.lpszHostName = host;
496     comp.dwHostNameLength = sizeof host;
497     comp.lpszUrlPath = urlpart;
498     comp.dwUrlPathLength = sizeof urlpart;
499     comp.lpszExtraInfo = NULL;
500     comp.dwExtraInfoLength = sizeof extra;
501
502     r = InternetCrackUrlW(url, 0, 0, &comp );
503     ok( r, "failed to crack url\n");
504     ok( comp.dwSchemeLength == 0, "scheme length wrong\n");
505     ok( comp.dwHostNameLength == 12, "host length wrong\n");
506     ok( comp.dwUserNameLength == 0, "user length wrong\n");
507     ok( comp.dwPasswordLength == 0, "password length wrong\n");
508     ok( comp.dwUrlPathLength == 15, "url length wrong\n");
509     ok( comp.dwExtraInfoLength == 29, "extra length wrong\n");
510
511     urlpart[0]=0;
512     scheme[0]=0;
513     extra[0]=0;
514     host[0]=0;
515     user[0]=0;
516     pwd[0]=0;
517     memset(&comp, 0, sizeof(comp));
518     comp.dwStructSize = sizeof(comp);
519     comp.lpszScheme = scheme;
520     comp.dwSchemeLength = sizeof(scheme)/sizeof(scheme[0]);
521     comp.lpszHostName = host;
522     comp.dwHostNameLength = sizeof(host)/sizeof(host[0]);
523     comp.lpszUserName = user;
524     comp.dwUserNameLength = sizeof(user)/sizeof(user[0]);
525     comp.lpszPassword = pwd;
526     comp.dwPasswordLength = sizeof(pwd)/sizeof(pwd[0]);
527     comp.lpszUrlPath = urlpart;
528     comp.dwUrlPathLength = sizeof(urlpart)/sizeof(urlpart[0]);
529     comp.lpszExtraInfo = extra;
530     comp.dwExtraInfoLength = sizeof(extra)/sizeof(extra[0]);
531
532     r = InternetCrackUrlW(url2, 0, 0, &comp);
533     todo_wine {
534     ok(!r, "InternetCrackUrl should have failed\n");
535     ok(GetLastError() == ERROR_INTERNET_UNRECOGNIZED_SCHEME,
536         "InternetCrackUrl should have failed with error ERROR_INTERNET_UNRECOGNIZED_SCHEME instead of error %d\n",
537         GetLastError());
538     }
539
540     /* Test to see whether cracking a URL without a filename initializes urlpart */
541     urlpart[0]=0xba;
542     scheme[0]=0;
543     extra[0]=0;
544     host[0]=0;
545     user[0]=0;
546     pwd[0]=0;
547     memset(&comp, 0, sizeof comp);
548     comp.dwStructSize = sizeof comp;
549     comp.lpszScheme = scheme;
550     comp.dwSchemeLength = sizeof scheme;
551     comp.lpszHostName = host;
552     comp.dwHostNameLength = sizeof host;
553     comp.lpszUserName = user;
554     comp.dwUserNameLength = sizeof user;
555     comp.lpszPassword = pwd;
556     comp.dwPasswordLength = sizeof pwd;
557     comp.lpszUrlPath = urlpart;
558     comp.dwUrlPathLength = sizeof urlpart;
559     comp.lpszExtraInfo = extra;
560     comp.dwExtraInfoLength = sizeof extra;
561     r = InternetCrackUrlW(url3, 0, 0, &comp );
562     ok( r, "InternetCrackUrlW failed unexpectedly\n");
563     ok( host[0] == 'x', "host should be x.org\n");
564     ok( urlpart[0] == 0, "urlpart should be empty\n");
565 }
566
567 static void fill_url_components(LPURL_COMPONENTS lpUrlComponents)
568 {
569     static CHAR http[]       = "http",
570                 winehq[]     = "www.winehq.org",
571                 username[]   = "username",
572                 password[]   = "password",
573                 site_about[] = "/site/about",
574                 empty[]      = "";
575
576     lpUrlComponents->dwStructSize = sizeof(URL_COMPONENTS);
577     lpUrlComponents->lpszScheme = http;
578     lpUrlComponents->dwSchemeLength = strlen(lpUrlComponents->lpszScheme);
579     lpUrlComponents->nScheme = INTERNET_SCHEME_HTTP;
580     lpUrlComponents->lpszHostName = winehq;
581     lpUrlComponents->dwHostNameLength = strlen(lpUrlComponents->lpszHostName);
582     lpUrlComponents->nPort = 80;
583     lpUrlComponents->lpszUserName = username;
584     lpUrlComponents->dwUserNameLength = strlen(lpUrlComponents->lpszUserName);
585     lpUrlComponents->lpszPassword = password;
586     lpUrlComponents->dwPasswordLength = strlen(lpUrlComponents->lpszPassword);
587     lpUrlComponents->lpszUrlPath = site_about;
588     lpUrlComponents->dwUrlPathLength = strlen(lpUrlComponents->lpszUrlPath);
589     lpUrlComponents->lpszExtraInfo = empty;
590     lpUrlComponents->dwExtraInfoLength = strlen(lpUrlComponents->lpszExtraInfo);
591 }
592
593 static void InternetCreateUrlA_test(void)
594 {
595         URL_COMPONENTS urlComp;
596         LPSTR szUrl;
597         DWORD len = -1;
598         BOOL ret;
599         static CHAR empty[]      = "",
600                     nhttp[]      = "nhttp",
601                     http[]       = "http",
602                     https[]      = "https",
603                     winehq[]     = "www.winehq.org",
604                     localhost[]  = "localhost",
605                     username[]   = "username",
606                     password[]   = "password",
607                     root[]       = "/",
608                     site_about[] = "/site/about",
609                     extra_info[] = "?test=123",
610                     about[]      = "about",
611                     blank[]      = "blank",
612                     host[]       = "host";
613
614         /* test NULL lpUrlComponents */
615         SetLastError(0xdeadbeef);
616         ret = InternetCreateUrlA(NULL, 0, NULL, &len);
617         ok(!ret, "Expected failure\n");
618         ok(GetLastError() == ERROR_INVALID_PARAMETER,
619                 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
620         ok(len == -1, "Expected len -1, got %d\n", len);
621
622         /* test zero'ed lpUrlComponents */
623         ZeroMemory(&urlComp, sizeof(URL_COMPONENTS));
624         SetLastError(0xdeadbeef);
625         ret = InternetCreateUrlA(&urlComp, 0, NULL, &len);
626         ok(!ret, "Expected failure\n");
627         ok(GetLastError() == ERROR_INVALID_PARAMETER,
628                 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
629         ok(len == -1, "Expected len -1, got %d\n", len);
630
631         /* test valid lpUrlComponents, NULL lpdwUrlLength */
632         fill_url_components(&urlComp);
633         SetLastError(0xdeadbeef);
634         ret = InternetCreateUrlA(&urlComp, 0, NULL, NULL);
635         ok(!ret, "Expected failure\n");
636         ok(GetLastError() == ERROR_INVALID_PARAMETER,
637                 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
638         ok(len == -1, "Expected len -1, got %d\n", len);
639
640         /* test valid lpUrlComponents, empty szUrl
641          * lpdwUrlLength is size of buffer required on exit, including
642          * the terminating null when GLE == ERROR_INSUFFICIENT_BUFFER
643          */
644         SetLastError(0xdeadbeef);
645         ret = InternetCreateUrlA(&urlComp, 0, NULL, &len);
646         ok(!ret, "Expected failure\n");
647         ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
648                 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
649         ok(len == 51, "Expected len 51, got %d\n", len);
650
651         /* test correct size, NULL szUrl */
652         fill_url_components(&urlComp);
653         SetLastError(0xdeadbeef);
654         ret = InternetCreateUrlA(&urlComp, 0, NULL, &len);
655         ok(!ret, "Expected failure\n");
656         ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
657                 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
658         ok(len == 51, "Expected len 51, got %d\n", len);
659
660         /* test valid lpUrlComponents, alloc-ed szUrl, small size */
661         SetLastError(0xdeadbeef);
662         szUrl = HeapAlloc(GetProcessHeap(), 0, len);
663         len -= 2;
664         ret = InternetCreateUrlA(&urlComp, 0, szUrl, &len);
665         ok(!ret, "Expected failure\n");
666         ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
667                 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
668         ok(len == 51, "Expected len 51, got %d\n", len);
669
670         /* alloc-ed szUrl, NULL lpszScheme
671          * shows that it uses nScheme instead
672          */
673         SetLastError(0xdeadbeef);
674         urlComp.lpszScheme = NULL;
675         ret = InternetCreateUrlA(&urlComp, 0, szUrl, &len);
676         ok(ret, "Expected success\n");
677         ok(GetLastError() == 0xdeadbeef,
678                 "Expected 0xdeadbeef, got %d\n", GetLastError());
679         ok(len == 50, "Expected len 50, got %d\n", len);
680         ok(!strcmp(szUrl, CREATE_URL1), "Expected %s, got %s\n", CREATE_URL1, szUrl);
681
682         /* alloc-ed szUrl, invalid nScheme
683          * any nScheme out of range seems ignored
684          */
685         fill_url_components(&urlComp);
686         SetLastError(0xdeadbeef);
687         urlComp.nScheme = -3;
688         len++;
689         ret = InternetCreateUrlA(&urlComp, 0, szUrl, &len);
690         ok(ret, "Expected success\n");
691         ok(GetLastError() == 0xdeadbeef,
692                 "Expected 0xdeadbeef, got %d\n", GetLastError());
693         ok(len == 50, "Expected len 50, got %d\n", len);
694
695         /* test valid lpUrlComponents, alloc-ed szUrl */
696         fill_url_components(&urlComp);
697         SetLastError(0xdeadbeef);
698         len = 51;
699         ret = InternetCreateUrlA(&urlComp, 0, szUrl, &len);
700         ok(ret, "Expected success\n");
701         ok(GetLastError() == 0xdeadbeef,
702                 "Expected 0xdeadbeef, got %d\n", GetLastError());
703         ok(len == 50, "Expected len 50, got %d\n", len);
704         ok(strstr(szUrl, "80") == NULL, "Didn't expect to find 80 in szUrl\n");
705         ok(!strcmp(szUrl, CREATE_URL1), "Expected %s, got %s\n", CREATE_URL1, szUrl);
706
707         /* valid username, NULL password */
708         fill_url_components(&urlComp);
709         SetLastError(0xdeadbeef);
710         urlComp.lpszPassword = NULL;
711         len = 42;
712         ret = InternetCreateUrlA(&urlComp, 0, szUrl, &len);
713         ok(ret, "Expected success\n");
714         ok(GetLastError() == 0xdeadbeef,
715                 "Expected 0xdeadbeef, got %d\n", GetLastError());
716         ok(len == 41, "Expected len 41, got %d\n", len);
717         ok(!strcmp(szUrl, CREATE_URL2), "Expected %s, got %s\n", CREATE_URL2, szUrl);
718
719         /* valid username, empty password */
720         fill_url_components(&urlComp);
721         SetLastError(0xdeadbeef);
722         urlComp.lpszPassword = empty;
723         len = 51;
724         ret = InternetCreateUrlA(&urlComp, 0, szUrl, &len);
725         ok(ret, "Expected success\n");
726         ok(GetLastError() == 0xdeadbeef,
727                 "Expected 0xdeadbeef, got %d\n", GetLastError());
728         ok(len == 50, "Expected len 50, got %d\n", len);
729         ok(!strcmp(szUrl, CREATE_URL3), "Expected %s, got %s\n", CREATE_URL3, szUrl);
730
731         /* valid password, NULL username
732          * if password is provided, username has to exist
733          */
734         fill_url_components(&urlComp);
735         SetLastError(0xdeadbeef);
736         urlComp.lpszUserName = NULL;
737         len = 42;
738         ret = InternetCreateUrlA(&urlComp, 0, szUrl, &len);
739         ok(!ret, "Expected failure\n");
740         ok(GetLastError() == ERROR_INVALID_PARAMETER,
741                 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
742         ok(len == 42, "Expected len 42, got %d\n", len);
743         ok(!strcmp(szUrl, CREATE_URL3), "Expected %s, got %s\n", CREATE_URL3, szUrl);
744
745         /* valid password, empty username
746          * if password is provided, username has to exist
747          */
748         fill_url_components(&urlComp);
749         SetLastError(0xdeadbeef);
750         urlComp.lpszUserName = empty;
751         len = 51;
752         ret = InternetCreateUrlA(&urlComp, 0, szUrl, &len);
753         ok(ret, "Expected success\n");
754         ok(GetLastError() == 0xdeadbeef,
755                 "Expected 0xdeadbeef, got %d\n", GetLastError());
756         ok(len == 50, "Expected len 50, got %d\n", len);
757         ok(!strcmp(szUrl, CREATE_URL5), "Expected %s, got %s\n", CREATE_URL5, szUrl);
758
759         /* NULL username, NULL password */
760         fill_url_components(&urlComp);
761         SetLastError(0xdeadbeef);
762         urlComp.lpszUserName = NULL;
763         urlComp.lpszPassword = NULL;
764         len = 42;
765         ret = InternetCreateUrlA(&urlComp, 0, szUrl, &len);
766         ok(ret, "Expected success\n");
767         ok(GetLastError() == 0xdeadbeef,
768                 "Expected 0xdeadbeef, got %d\n", GetLastError());
769         ok(len == 32, "Expected len 32, got %d\n", len);
770         ok(!strcmp(szUrl, CREATE_URL4), "Expected %s, got %s\n", CREATE_URL4, szUrl);
771
772         /* empty username, empty password */
773         fill_url_components(&urlComp);
774         SetLastError(0xdeadbeef);
775         urlComp.lpszUserName = empty;
776         urlComp.lpszPassword = empty;
777         len = 51;
778         ret = InternetCreateUrlA(&urlComp, 0, szUrl, &len);
779         ok(ret, "Expected success\n");
780         ok(GetLastError() == 0xdeadbeef,
781                 "Expected 0xdeadbeef, got %d\n", GetLastError());
782         ok(len == 50, "Expected len 50, got %d\n", len);
783         ok(!strcmp(szUrl, CREATE_URL5), "Expected %s, got %s\n", CREATE_URL5, szUrl);
784
785         /* shows that nScheme is ignored, as the appearance of the port number
786          * depends on lpszScheme and the string copied depends on lpszScheme.
787          */
788         fill_url_components(&urlComp);
789         HeapFree(GetProcessHeap(), 0, szUrl);
790         urlComp.lpszScheme = nhttp;
791         urlComp.dwSchemeLength = strlen(urlComp.lpszScheme);
792         len = strlen(CREATE_URL6) + 1;
793         szUrl = HeapAlloc(GetProcessHeap(), 0, len);
794         ret = InternetCreateUrlA(&urlComp, ICU_ESCAPE, szUrl, &len);
795         ok(ret, "Expected success\n");
796         ok(len == strlen(CREATE_URL6), "Expected len %d, got %d\n", lstrlenA(CREATE_URL6) + 1, len);
797         ok(!strcmp(szUrl, CREATE_URL6), "Expected %s, got %s\n", CREATE_URL6, szUrl);
798
799         /* if lpszScheme != "http" or nPort != 80, display nPort */
800         HeapFree(GetProcessHeap(), 0, szUrl);
801         urlComp.lpszScheme = http;
802         urlComp.dwSchemeLength = strlen(urlComp.lpszScheme);
803         urlComp.nPort = 42;
804         szUrl = HeapAlloc(GetProcessHeap(), 0, ++len);
805         ret = InternetCreateUrlA(&urlComp, ICU_ESCAPE, szUrl, &len);
806         ok(ret, "Expected success\n");
807         ok(len == 53, "Expected len 53, got %d\n", len);
808         ok(strstr(szUrl, "42") != NULL, "Expected to find 42 in szUrl\n");
809         ok(!strcmp(szUrl, CREATE_URL7), "Expected %s, got %s\n", CREATE_URL7, szUrl);
810
811         HeapFree(GetProcessHeap(), 0, szUrl);
812
813         memset(&urlComp, 0, sizeof(urlComp));
814         urlComp.dwStructSize = sizeof(URL_COMPONENTS);
815         urlComp.lpszScheme = http;
816         urlComp.dwSchemeLength = 0;
817         urlComp.nScheme = INTERNET_SCHEME_HTTP;
818         urlComp.lpszHostName = winehq;
819         urlComp.dwHostNameLength = 0;
820         urlComp.nPort = 80;
821         urlComp.lpszUserName = username;
822         urlComp.dwUserNameLength = 0;
823         urlComp.lpszPassword = password;
824         urlComp.dwPasswordLength = 0;
825         urlComp.lpszUrlPath = site_about;
826         urlComp.dwUrlPathLength = 0;
827         urlComp.lpszExtraInfo = empty;
828         urlComp.dwExtraInfoLength = 0;
829         len = strlen(CREATE_URL1);
830         szUrl = HeapAlloc(GetProcessHeap(), 0, ++len);
831         ret = InternetCreateUrlA(&urlComp, ICU_ESCAPE, szUrl, &len);
832         ok(ret, "Expected success\n");
833         ok(len == strlen(CREATE_URL1), "Expected len %d, got %d\n", lstrlenA(CREATE_URL1), len);
834         ok(!strcmp(szUrl, CREATE_URL1), "Expected %s, got %s\n", CREATE_URL1, szUrl);
835
836         HeapFree(GetProcessHeap(), 0, szUrl);
837
838         memset(&urlComp, 0, sizeof(urlComp));
839         urlComp.dwStructSize = sizeof(URL_COMPONENTS);
840         urlComp.lpszScheme = https;
841         urlComp.dwSchemeLength = 0;
842         urlComp.nScheme = INTERNET_SCHEME_HTTP;
843         urlComp.lpszHostName = winehq;
844         urlComp.dwHostNameLength = 0;
845         urlComp.nPort = 443;
846         urlComp.lpszUserName = username;
847         urlComp.dwUserNameLength = 0;
848         urlComp.lpszPassword = password;
849         urlComp.dwPasswordLength = 0;
850         urlComp.lpszUrlPath = site_about;
851         urlComp.dwUrlPathLength = 0;
852         urlComp.lpszExtraInfo = empty;
853         urlComp.dwExtraInfoLength = 0;
854         len = strlen(CREATE_URL8);
855         szUrl = HeapAlloc(GetProcessHeap(), 0, ++len);
856         ret = InternetCreateUrlA(&urlComp, ICU_ESCAPE, szUrl, &len);
857         ok(ret, "Expected success\n");
858         ok(len == strlen(CREATE_URL8), "Expected len %d, got %d\n", lstrlenA(CREATE_URL8), len);
859         ok(!strcmp(szUrl, CREATE_URL8), "Expected %s, got %s\n", CREATE_URL8, szUrl);
860
861         HeapFree(GetProcessHeap(), 0, szUrl);
862
863         memset(&urlComp, 0, sizeof(urlComp));
864         urlComp.dwStructSize = sizeof(URL_COMPONENTS);
865         urlComp.lpszScheme = about;
866         urlComp.dwSchemeLength = 5;
867         urlComp.lpszUrlPath = blank;
868         urlComp.dwUrlPathLength = 5;
869         len = strlen(CREATE_URL9);
870         len++; /* work around bug in native wininet */
871         szUrl = HeapAlloc(GetProcessHeap(), 0, ++len);
872         ret = InternetCreateUrlA(&urlComp, ICU_ESCAPE, szUrl, &len);
873         ok(ret, "Expected success\n");
874         ok(len == strlen(CREATE_URL9), "Expected len %d, got %d\n", lstrlenA(CREATE_URL9), len);
875         ok(!strcmp(szUrl, CREATE_URL9), "Expected %s, got %s\n", CREATE_URL9, szUrl);
876
877         HeapFree(GetProcessHeap(), 0, szUrl);
878
879         memset(&urlComp, 0, sizeof(urlComp));
880         urlComp.dwStructSize = sizeof(URL_COMPONENTS);
881         urlComp.lpszScheme = about;
882         urlComp.lpszHostName = host;
883         urlComp.lpszUrlPath = blank;
884         len = strlen(CREATE_URL10);
885         len++; /* work around bug in native wininet */
886         szUrl = HeapAlloc(GetProcessHeap(), 0, ++len);
887         ret = InternetCreateUrlA(&urlComp, ICU_ESCAPE, szUrl, &len);
888         ok(ret, "Expected success\n");
889         ok(len == strlen(CREATE_URL10), "Expected len %d, got %d\n", lstrlenA(CREATE_URL10), len);
890         ok(!strcmp(szUrl, CREATE_URL10), "Expected %s, got %s\n", CREATE_URL10, szUrl);
891
892         HeapFree(GetProcessHeap(), 0, szUrl);
893
894         memset(&urlComp, 0, sizeof(urlComp));
895         urlComp.dwStructSize = sizeof(URL_COMPONENTS);
896         urlComp.nPort = 8080;
897         urlComp.lpszScheme = about;
898         len = strlen(CREATE_URL11);
899         szUrl = HeapAlloc(GetProcessHeap(), 0, ++len);
900         ret = InternetCreateUrlA(&urlComp, ICU_ESCAPE, szUrl, &len);
901         ok(ret, "Expected success\n");
902         ok(len == strlen(CREATE_URL11), "Expected len %d, got %d\n", lstrlenA(CREATE_URL11), len);
903         ok(!strcmp(szUrl, CREATE_URL11), "Expected %s, got %s\n", CREATE_URL11, szUrl);
904
905         HeapFree(GetProcessHeap(), 0, szUrl);
906
907         memset(&urlComp, 0, sizeof(urlComp));
908         urlComp.dwStructSize = sizeof(URL_COMPONENTS);
909         urlComp.lpszScheme = http;
910         urlComp.dwSchemeLength = 0;
911         urlComp.nScheme = INTERNET_SCHEME_HTTP;
912         urlComp.lpszHostName = winehq;
913         urlComp.dwHostNameLength = 0;
914         urlComp.nPort = 65535;
915         len = strlen(CREATE_URL12);
916         szUrl = HeapAlloc(GetProcessHeap(), 0, ++len);
917         ret = InternetCreateUrlA(&urlComp, ICU_ESCAPE, szUrl, &len);
918         ok(ret, "Expected success\n");
919         ok(len == strlen(CREATE_URL12), "Expected len %d, got %d\n", lstrlenA(CREATE_URL12), len);
920         ok(!strcmp(szUrl, CREATE_URL12), "Expected %s, got %s\n", CREATE_URL12, szUrl);
921
922         HeapFree(GetProcessHeap(), 0, szUrl);
923
924     memset(&urlComp, 0, sizeof(urlComp));
925     urlComp.dwStructSize = sizeof(URL_COMPONENTS);
926     urlComp.lpszScheme = http;
927     urlComp.dwSchemeLength = strlen(urlComp.lpszScheme);
928     urlComp.lpszHostName = localhost;
929     urlComp.dwHostNameLength = strlen(urlComp.lpszHostName);
930     urlComp.nPort = 80;
931     urlComp.lpszUrlPath = root;
932     urlComp.dwUrlPathLength = strlen(urlComp.lpszUrlPath);
933     urlComp.lpszExtraInfo = extra_info;
934     urlComp.dwExtraInfoLength = strlen(urlComp.lpszExtraInfo);
935     len = 256;
936     szUrl = HeapAlloc(GetProcessHeap(), 0, len);
937     InternetCreateUrlA(&urlComp, ICU_ESCAPE, szUrl, &len);
938     ok(ret, "Expected success\n");
939     ok(len == strlen(CREATE_URL13), "Got len %u\n", len);
940     ok(!strcmp(szUrl, CREATE_URL13), "Expected \"%s\", got \"%s\"\n", CREATE_URL13, szUrl);
941
942     HeapFree(GetProcessHeap(), 0, szUrl);
943 }
944
945 START_TEST(url)
946 {
947     int i;
948
949     for(i=0; i < sizeof(crack_url_tests)/sizeof(*crack_url_tests); i++)
950         test_crack_url(crack_url_tests+i);
951
952     InternetCrackUrl_test();
953     InternetCrackUrlW_test();
954     InternetCreateUrlA_test();
955 }