wininet/tests: Fix a test with IE8.
[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
27 #include "windef.h"
28 #include "winbase.h"
29 #include "wininet.h"
30
31 #include "wine/test.h"
32
33 #define TEST_URL "http://www.winehq.org/site/about"
34 #define TEST_URL_HOST "www.winehq.org"
35 #define TEST_URL_PATH "/site/about"
36 #define TEST_URL2 "http://www.myserver.com/myscript.php?arg=1"
37 #define TEST_URL2_SERVER "www.myserver.com"
38 #define TEST_URL2_PATH "/myscript.php"
39 #define TEST_URL2_PATHEXTRA "/myscript.php?arg=1"
40 #define TEST_URL2_EXTRA "?arg=1"
41 #define TEST_URL3 "file:///C:/Program%20Files/Atmel/AVR%20Tools/STK500/STK500.xml"
42
43 #define CREATE_URL1 "http://username:password@www.winehq.org/site/about"
44 #define CREATE_URL2 "http://username@www.winehq.org/site/about"
45 #define CREATE_URL3 "http://username:"
46 #define CREATE_URL4 "http://www.winehq.org/site/about"
47 #define CREATE_URL5 "http://"
48 #define CREATE_URL6 "nhttp://username:password@www.winehq.org:80/site/about"
49 #define CREATE_URL7 "http://username:password@www.winehq.org:42/site/about"
50 #define CREATE_URL8 "https://username:password@www.winehq.org/site/about"
51 #define CREATE_URL9 "about:blank"
52 #define CREATE_URL10 "about://host/blank"
53 #define CREATE_URL11 "about:"
54 #define CREATE_URL12 "http://www.winehq.org:65535"
55 #define CREATE_URL13 "http://localhost/?test=123"
56
57 static void copy_compsA(
58     URL_COMPONENTSA *src, 
59     URL_COMPONENTSA *dst, 
60     DWORD scheLen,
61     DWORD hostLen,
62     DWORD userLen,
63     DWORD passLen,
64     DWORD pathLen,
65     DWORD extrLen )
66 {
67     *dst = *src;
68     dst->dwSchemeLength    = scheLen;
69     dst->dwHostNameLength  = hostLen;
70     dst->dwUserNameLength  = userLen;
71     dst->dwPasswordLength  = passLen;
72     dst->dwUrlPathLength   = pathLen;
73     dst->dwExtraInfoLength = extrLen;
74     SetLastError(0xfaceabad);
75 }
76
77 static void zero_compsA(
78     URL_COMPONENTSA *dst, 
79     DWORD scheLen,
80     DWORD hostLen,
81     DWORD userLen,
82     DWORD passLen,
83     DWORD pathLen,
84     DWORD extrLen )
85 {
86     ZeroMemory(dst, sizeof(URL_COMPONENTSA));
87     dst->dwStructSize = sizeof(URL_COMPONENTSA);
88     dst->dwSchemeLength    = scheLen;
89     dst->dwHostNameLength  = hostLen;
90     dst->dwUserNameLength  = userLen;
91     dst->dwPasswordLength  = passLen;
92     dst->dwUrlPathLength   = pathLen;
93     dst->dwExtraInfoLength = extrLen;
94     SetLastError(0xfaceabad);
95 }
96
97 static void InternetCrackUrl_test(void)
98 {
99   URL_COMPONENTSA urlSrc, urlComponents;
100   char protocol[32], hostName[1024], userName[1024];
101   char password[1024], extra[1024], path[1024];
102   BOOL ret, firstret;
103   DWORD GLE, firstGLE;
104
105   ZeroMemory(&urlSrc, sizeof(urlSrc));
106   urlSrc.dwStructSize = sizeof(urlSrc);
107   urlSrc.lpszScheme = protocol;
108   urlSrc.lpszHostName = hostName;
109   urlSrc.lpszUserName = userName;
110   urlSrc.lpszPassword = password;
111   urlSrc.lpszUrlPath = path;
112   urlSrc.lpszExtraInfo = extra;
113
114   copy_compsA(&urlSrc, &urlComponents, 32, 1024, 1024, 1024, 2048, 1024);
115   ret = InternetCrackUrl(TEST_URL, 0,0,&urlComponents);
116   ok( ret, "InternetCrackUrl failed, error %d\n",GetLastError());
117   ok((strcmp(TEST_URL_PATH,path) == 0),"path cracked wrong\n");
118
119   /* Bug 1805: Confirm the returned lengths are correct:                     */
120   /* 1. When extra info split out explicitly */
121   zero_compsA(&urlComponents, 0, 1, 0, 0, 1, 1);
122   ok(InternetCrackUrlA(TEST_URL2, 0, 0, &urlComponents),"InternetCrackUrl failed, error %d\n", GetLastError());
123   ok(urlComponents.dwUrlPathLength == strlen(TEST_URL2_PATH),".dwUrlPathLength should be %d, but is %d\n", (DWORD)strlen(TEST_URL2_PATH), urlComponents.dwUrlPathLength);
124   ok(!strncmp(urlComponents.lpszUrlPath,TEST_URL2_PATH,strlen(TEST_URL2_PATH)),"lpszUrlPath should be %s but is %s\n", TEST_URL2_PATH, urlComponents.lpszUrlPath);
125   ok(urlComponents.dwHostNameLength == strlen(TEST_URL2_SERVER),".dwHostNameLength should be %d, but is %d\n", (DWORD)strlen(TEST_URL2_SERVER), urlComponents.dwHostNameLength);
126   ok(!strncmp(urlComponents.lpszHostName,TEST_URL2_SERVER,strlen(TEST_URL2_SERVER)),"lpszHostName should be %s but is %s\n", TEST_URL2_SERVER, urlComponents.lpszHostName);
127   ok(urlComponents.dwExtraInfoLength == strlen(TEST_URL2_EXTRA),".dwExtraInfoLength should be %d, but is %d\n", (DWORD)strlen(TEST_URL2_EXTRA), urlComponents.dwExtraInfoLength);
128   ok(!strncmp(urlComponents.lpszExtraInfo,TEST_URL2_EXTRA,strlen(TEST_URL2_EXTRA)),"lpszExtraInfo should be %s but is %s\n", TEST_URL2_EXTRA, urlComponents.lpszHostName);
129
130   /* 2. When extra info is not split out explicitly and is in url path */
131   zero_compsA(&urlComponents, 0, 1, 0, 0, 1, 0);
132   ok(InternetCrackUrlA(TEST_URL2, 0, 0, &urlComponents),"InternetCrackUrl failed with GLE %d\n",GetLastError());
133   ok(urlComponents.dwUrlPathLength == strlen(TEST_URL2_PATHEXTRA),".dwUrlPathLength should be %d, but is %d\n", (DWORD)strlen(TEST_URL2_PATHEXTRA), urlComponents.dwUrlPathLength);
134   ok(!strncmp(urlComponents.lpszUrlPath,TEST_URL2_PATHEXTRA,strlen(TEST_URL2_PATHEXTRA)),"lpszUrlPath should be %s but is %s\n", TEST_URL2_PATHEXTRA, urlComponents.lpszUrlPath);
135   ok(urlComponents.dwHostNameLength == strlen(TEST_URL2_SERVER),".dwHostNameLength should be %d, but is %d\n", (DWORD)strlen(TEST_URL2_SERVER), urlComponents.dwHostNameLength);
136   ok(!strncmp(urlComponents.lpszHostName,TEST_URL2_SERVER,strlen(TEST_URL2_SERVER)),"lpszHostName should be %s but is %s\n", TEST_URL2_SERVER, urlComponents.lpszHostName);
137   ok(urlComponents.nPort == INTERNET_DEFAULT_HTTP_PORT,"urlComponents->nPort should have been 80 instead of %d\n", urlComponents.nPort);
138   ok(urlComponents.nScheme == INTERNET_SCHEME_HTTP,"urlComponents->nScheme should have been INTERNET_SCHEME_HTTP instead of %d\n", urlComponents.nScheme);
139
140   zero_compsA(&urlComponents, 1, 1, 1, 1, 1, 1);
141   ok(InternetCrackUrlA(TEST_URL, strlen(TEST_URL), 0, &urlComponents),"InternetCrackUrl failed with GLE %d\n",GetLastError());
142   ok(urlComponents.dwUrlPathLength == strlen(TEST_URL_PATH),".dwUrlPathLength should be %d, but is %d\n", lstrlenA(TEST_URL_PATH), urlComponents.dwUrlPathLength);
143   ok(!strncmp(urlComponents.lpszUrlPath,TEST_URL_PATH,strlen(TEST_URL_PATH)),"lpszUrlPath should be %s but is %s\n", TEST_URL_PATH, urlComponents.lpszUrlPath);
144   ok(urlComponents.dwHostNameLength == strlen(TEST_URL_HOST),".dwHostNameLength should be %d, but is %d\n", lstrlenA(TEST_URL_HOST), urlComponents.dwHostNameLength);
145   ok(!strncmp(urlComponents.lpszHostName,TEST_URL_HOST,strlen(TEST_URL_HOST)),"lpszHostName should be %s but is %s\n", TEST_URL_HOST, urlComponents.lpszHostName);
146   ok(urlComponents.nPort == INTERNET_DEFAULT_HTTP_PORT,"urlComponents->nPort should have been 80 instead of %d\n", urlComponents.nPort);
147   ok(urlComponents.nScheme == INTERNET_SCHEME_HTTP,"urlComponents->nScheme should have been INTERNET_SCHEME_HTTP instead of %d\n", urlComponents.nScheme);
148   ok(!urlComponents.lpszUserName, ".lpszUserName should have been set to NULL\n");
149   ok(!urlComponents.lpszPassword, ".lpszPassword should have been set to NULL\n");
150   ok(!urlComponents.lpszExtraInfo, ".lpszExtraInfo should have been set to NULL\n");
151   ok(!urlComponents.dwUserNameLength,".dwUserNameLength should be 0, but is %d\n", urlComponents.dwUserNameLength);
152   ok(!urlComponents.dwPasswordLength,".dwPasswordLength should be 0, but is %d\n", urlComponents.dwPasswordLength);
153   ok(!urlComponents.dwExtraInfoLength,".dwExtraInfoLength should be 0, but is %d\n", urlComponents.dwExtraInfoLength);
154
155   /*3. Check for %20 */
156   copy_compsA(&urlSrc, &urlComponents, 32, 1024, 1024, 1024, 2048, 1024);
157   ok(InternetCrackUrlA(TEST_URL3, 0, ICU_DECODE, &urlComponents),"InternetCrackUrl failed with GLE %d\n",GetLastError());
158
159   /* Tests for lpsz* members pointing to real strings while 
160    * some corresponding length members are set to zero.
161    * As of IE7 (wininet 7.0*?) all members are checked. So we
162    * run the first test and expect the outcome to be the same
163    * for the first four (scheme, hostname, username and password).
164    * The last two (path and extrainfo) are the same for all versions
165    * of the wininet.dll.
166    */
167   copy_compsA(&urlSrc, &urlComponents, 0, 1024, 1024, 1024, 2048, 1024);
168   SetLastError(0xdeadbeef);
169   firstret = InternetCrackUrlA(TEST_URL3, 0, ICU_DECODE, &urlComponents);
170   firstGLE = GetLastError();
171
172   copy_compsA(&urlSrc, &urlComponents, 32, 0, 1024, 1024, 2048, 1024);
173   SetLastError(0xdeadbeef);
174   ret = InternetCrackUrlA(TEST_URL3, 0, ICU_DECODE, &urlComponents);
175   GLE = GetLastError();
176   ok(ret==firstret && (GLE==firstGLE), "InternetCrackUrl returned %d with GLE=%d (expected to return %d)\n",
177     ret, GetLastError(), firstret);
178
179   copy_compsA(&urlSrc, &urlComponents, 32, 1024, 0, 1024, 2048, 1024);
180   SetLastError(0xdeadbeef);
181   ret = InternetCrackUrlA(TEST_URL3, 0, ICU_DECODE, &urlComponents);
182   GLE = GetLastError();
183   ok(ret==firstret && (GLE==firstGLE), "InternetCrackUrl returned %d with GLE=%d (expected to return %d)\n",
184     ret, GetLastError(), firstret);
185
186   copy_compsA(&urlSrc, &urlComponents, 32, 1024, 1024, 0, 2048, 1024);
187   SetLastError(0xdeadbeef);
188   ret = InternetCrackUrlA(TEST_URL3, 0, ICU_DECODE, &urlComponents);
189   GLE = GetLastError();
190   ok(ret==firstret && (GLE==firstGLE), "InternetCrackUrl returned %d with GLE=%d (expected to return %d)\n",
191     ret, GetLastError(), firstret);
192
193   copy_compsA(&urlSrc, &urlComponents, 32, 1024, 1024, 1024, 0, 1024);
194   SetLastError(0xdeadbeef);
195   ret = InternetCrackUrlA(TEST_URL3, 0, ICU_DECODE, &urlComponents);
196   GLE = GetLastError();
197   todo_wine
198   ok(ret==0 && (GLE==ERROR_INVALID_HANDLE || GLE==ERROR_INSUFFICIENT_BUFFER),
199      "InternetCrackUrl returned %d with GLE=%d (expected to return 0 and ERROR_INVALID_HANDLE or ERROR_INSUFFICIENT_BUFFER)\n",
200     ret, GLE);
201
202   copy_compsA(&urlSrc, &urlComponents, 32, 1024, 1024, 1024, 2048, 0);
203   SetLastError(0xdeadbeef);
204   ret = InternetCrackUrlA(TEST_URL3, 0, ICU_DECODE, &urlComponents);
205   GLE = GetLastError();
206   todo_wine
207   ok(ret==0 && (GLE==ERROR_INVALID_HANDLE || GLE==ERROR_INSUFFICIENT_BUFFER),
208      "InternetCrackUrl returned %d with GLE=%d (expected to return 0 and ERROR_INVALID_HANDLE or ERROR_INSUFFICIENT_BUFFER)\n",
209     ret, GLE);
210
211   copy_compsA(&urlSrc, &urlComponents, 0, 0, 0, 0, 0, 0);
212   ret = InternetCrackUrlA(TEST_URL3, 0, ICU_DECODE, &urlComponents);
213   GLE = GetLastError();
214   todo_wine
215   ok(ret==0 && GLE==ERROR_INVALID_PARAMETER,
216      "InternetCrackUrl returned %d with GLE=%d (expected to return 0 and ERROR_INVALID_PARAMETER)\n",
217     ret, GLE);
218
219   copy_compsA(&urlSrc, &urlComponents, 32, 1024, 1024, 1024, 2048, 1024);
220   ret = InternetCrackUrl("about://host/blank", 0,0,&urlComponents);
221   ok(ret, "InternetCrackUrl failed with %d\n", GetLastError());
222   ok(!strcmp(urlComponents.lpszScheme, "about"), "lpszScheme was \"%s\" instead of \"about\"\n", urlComponents.lpszScheme);
223   ok(!strcmp(urlComponents.lpszHostName, "host"), "lpszHostName was \"%s\" instead of \"host\"\n", urlComponents.lpszHostName);
224   ok(!strcmp(urlComponents.lpszUrlPath, "/blank"), "lpszUrlPath was \"%s\" instead of \"/blank\"\n", urlComponents.lpszUrlPath);
225
226   /* try a NULL lpszUrl */
227   SetLastError(0xdeadbeef);
228   copy_compsA(&urlSrc, &urlComponents, 32, 1024, 1024, 1024, 2048, 1024);
229   ret = InternetCrackUrl(NULL, 0, 0, &urlComponents);
230   GLE = GetLastError();
231   ok(ret == FALSE, "Expected InternetCrackUrl to fail\n");
232   ok(GLE == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GLE);
233
234   /* try an empty lpszUrl, GetLastError returns 12006, whatever that means
235    * we just need to fail and not return success
236    */
237   SetLastError(0xdeadbeef);
238   copy_compsA(&urlSrc, &urlComponents, 32, 1024, 1024, 1024, 2048, 1024);
239   ret = InternetCrackUrl("", 0, 0, &urlComponents);
240   GLE = GetLastError();
241   ok(ret == FALSE, "Expected InternetCrackUrl to fail\n");
242   ok(GLE != 0xdeadbeef && GLE != ERROR_SUCCESS, "Expected GLE to represent a failure\n");
243
244   /* Invalid Call: must set size of components structure (Windows only
245    * enforces this on the InternetCrackUrlA version of the call) */
246   copy_compsA(&urlSrc, &urlComponents, 0, 1024, 1024, 1024, 2048, 1024);
247   SetLastError(0xdeadbeef);
248   urlComponents.dwStructSize = 0;
249   ret = InternetCrackUrlA(TEST_URL, 0, 0, &urlComponents);
250   ok(ret == FALSE, "Expected InternetCrackUrl to fail\n");
251   ok(GLE != 0xdeadbeef && GLE != ERROR_SUCCESS, "Expected GLE to represent a failure\n");
252
253   /* Invalid Call: size of dwStructSize must be one of the "standard" sizes
254    * of the URL_COMPONENTS structure (Windows only enforces this on the
255    * InternetCrackUrlA version of the call) */
256   copy_compsA(&urlSrc, &urlComponents, 0, 1024, 1024, 1024, 2048, 1024);
257   SetLastError(0xdeadbeef);
258   urlComponents.dwStructSize = sizeof(urlComponents) + 1;
259   ret = InternetCrackUrlA(TEST_URL, 0, 0, &urlComponents);
260   ok(ret == FALSE, "Expected InternetCrackUrl to fail\n");
261   ok(GLE != 0xdeadbeef && GLE != ERROR_SUCCESS, "Expected GLE to represent a failure\n");
262 }
263
264 static void InternetCrackUrlW_test(void)
265 {
266     WCHAR url[] = {
267         'h','t','t','p',':','/','/','1','9','2','.','1','6','8','.','0','.','2','2','/',
268         'C','F','I','D','E','/','m','a','i','n','.','c','f','m','?','C','F','S','V','R',
269         '=','I','D','E','&','A','C','T','I','O','N','=','I','D','E','_','D','E','F','A',
270         'U','L','T', 0 };
271     static const WCHAR url2[] = { '.','.','/','R','i','t','z','.','x','m','l',0 };
272     static const WCHAR url3[] = { 'h','t','t','p',':','/','/','x','.','o','r','g',0 };
273     URL_COMPONENTSW comp;
274     WCHAR scheme[20], host[20], user[20], pwd[20], urlpart[50], extra[50];
275     DWORD error;
276     BOOL r;
277
278     urlpart[0]=0;
279     scheme[0]=0;
280     extra[0]=0;
281     host[0]=0;
282     user[0]=0;
283     pwd[0]=0;
284     memset(&comp, 0, sizeof comp);
285     comp.dwStructSize = sizeof comp;
286     comp.lpszScheme = scheme;
287     comp.dwSchemeLength = sizeof scheme;
288     comp.lpszHostName = host;
289     comp.dwHostNameLength = sizeof host;
290     comp.lpszUserName = user;
291     comp.dwUserNameLength = sizeof user;
292     comp.lpszPassword = pwd;
293     comp.dwPasswordLength = sizeof pwd;
294     comp.lpszUrlPath = urlpart;
295     comp.dwUrlPathLength = sizeof urlpart;
296     comp.lpszExtraInfo = extra;
297     comp.dwExtraInfoLength = sizeof extra;
298
299     SetLastError(0xdeadbeef);
300     r = InternetCrackUrlW(NULL, 0, 0, &comp );
301     error = GetLastError();
302     if (!r && error == ERROR_CALL_NOT_IMPLEMENTED)
303     {
304         win_skip("InternetCrackUrlW is not implemented\n");
305         return;
306     }
307     ok( !r, "InternetCrackUrlW succeeded unexpectedly\n");
308     ok( error == ERROR_INVALID_PARAMETER ||
309         broken(error == ERROR_INTERNET_UNRECOGNIZED_SCHEME), /* IE5 */
310         "expected ERROR_INVALID_PARAMETER got %u\n", error);
311
312     if (error == ERROR_INVALID_PARAMETER)
313     {
314         /* Crashes on IE5 */
315         SetLastError(0xdeadbeef);
316         r = InternetCrackUrlW(url, 0, 0, NULL );
317         error = GetLastError();
318         ok( !r, "InternetCrackUrlW succeeded unexpectedly\n");
319         ok( error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER got %u\n", error);
320     }
321
322     r = InternetCrackUrlW(url, 0, 0, &comp );
323     ok( r, "failed to crack url\n");
324     ok( comp.dwSchemeLength == 4, "scheme length wrong\n");
325     ok( comp.dwHostNameLength == 12, "host length wrong\n");
326     ok( comp.dwUserNameLength == 0, "user length wrong\n");
327     ok( comp.dwPasswordLength == 0, "password length wrong\n");
328     ok( comp.dwUrlPathLength == 15, "url length wrong\n");
329     ok( comp.dwExtraInfoLength == 29, "extra length wrong\n");
330  
331     urlpart[0]=0;
332     scheme[0]=0;
333     extra[0]=0;
334     host[0]=0;
335     user[0]=0;
336     pwd[0]=0;
337     memset(&comp, 0, sizeof comp);
338     comp.dwStructSize = sizeof comp;
339     comp.lpszHostName = host;
340     comp.dwHostNameLength = sizeof host;
341     comp.lpszUrlPath = urlpart;
342     comp.dwUrlPathLength = sizeof urlpart;
343
344     r = InternetCrackUrlW(url, 0, 0, &comp );
345     ok( r, "failed to crack url\n");
346     ok( comp.dwSchemeLength == 0, "scheme length wrong\n");
347     ok( comp.dwHostNameLength == 12, "host length wrong\n");
348     ok( comp.dwUserNameLength == 0, "user length wrong\n");
349     ok( comp.dwPasswordLength == 0, "password length wrong\n");
350     ok( comp.dwUrlPathLength == 44, "url length wrong\n");
351     ok( comp.dwExtraInfoLength == 0, "extra length wrong\n");
352
353     urlpart[0]=0;
354     scheme[0]=0;
355     extra[0]=0;
356     host[0]=0;
357     user[0]=0;
358     pwd[0]=0;
359     memset(&comp, 0, sizeof comp);
360     comp.dwStructSize = sizeof comp;
361     comp.lpszHostName = host;
362     comp.dwHostNameLength = sizeof host;
363     comp.lpszUrlPath = urlpart;
364     comp.dwUrlPathLength = sizeof urlpart;
365     comp.lpszExtraInfo = NULL;
366     comp.dwExtraInfoLength = sizeof extra;
367
368     r = InternetCrackUrlW(url, 0, 0, &comp );
369     ok( r, "failed to crack url\n");
370     ok( comp.dwSchemeLength == 0, "scheme length wrong\n");
371     ok( comp.dwHostNameLength == 12, "host length wrong\n");
372     ok( comp.dwUserNameLength == 0, "user length wrong\n");
373     ok( comp.dwPasswordLength == 0, "password length wrong\n");
374     ok( comp.dwUrlPathLength == 15, "url length wrong\n");
375     ok( comp.dwExtraInfoLength == 29, "extra length wrong\n");
376
377     urlpart[0]=0;
378     scheme[0]=0;
379     extra[0]=0;
380     host[0]=0;
381     user[0]=0;
382     pwd[0]=0;
383     memset(&comp, 0, sizeof(comp));
384     comp.dwStructSize = sizeof(comp);
385     comp.lpszScheme = scheme;
386     comp.dwSchemeLength = sizeof(scheme)/sizeof(scheme[0]);
387     comp.lpszHostName = host;
388     comp.dwHostNameLength = sizeof(host)/sizeof(host[0]);
389     comp.lpszUserName = user;
390     comp.dwUserNameLength = sizeof(user)/sizeof(user[0]);
391     comp.lpszPassword = pwd;
392     comp.dwPasswordLength = sizeof(pwd)/sizeof(pwd[0]);
393     comp.lpszUrlPath = urlpart;
394     comp.dwUrlPathLength = sizeof(urlpart)/sizeof(urlpart[0]);
395     comp.lpszExtraInfo = extra;
396     comp.dwExtraInfoLength = sizeof(extra)/sizeof(extra[0]);
397
398     r = InternetCrackUrlW(url2, 0, 0, &comp);
399     todo_wine {
400     ok(!r, "InternetCrackUrl should have failed\n");
401     ok(GetLastError() == ERROR_INTERNET_UNRECOGNIZED_SCHEME,
402         "InternetCrackUrl should have failed with error ERROR_INTERNET_UNRECOGNIZED_SCHEME instead of error %d\n",
403         GetLastError());
404     }
405
406     /* Test to see whether cracking a URL without a filename initializes urlpart */
407     urlpart[0]=0xba;
408     scheme[0]=0;
409     extra[0]=0;
410     host[0]=0;
411     user[0]=0;
412     pwd[0]=0;
413     memset(&comp, 0, sizeof comp);
414     comp.dwStructSize = sizeof comp;
415     comp.lpszScheme = scheme;
416     comp.dwSchemeLength = sizeof scheme;
417     comp.lpszHostName = host;
418     comp.dwHostNameLength = sizeof host;
419     comp.lpszUserName = user;
420     comp.dwUserNameLength = sizeof user;
421     comp.lpszPassword = pwd;
422     comp.dwPasswordLength = sizeof pwd;
423     comp.lpszUrlPath = urlpart;
424     comp.dwUrlPathLength = sizeof urlpart;
425     comp.lpszExtraInfo = extra;
426     comp.dwExtraInfoLength = sizeof extra;
427     r = InternetCrackUrlW(url3, 0, 0, &comp );
428     ok( r, "InternetCrackUrlW failed unexpectedly\n");
429     ok( host[0] == 'x', "host should be x.org\n");
430     ok( urlpart[0] == 0, "urlpart should be empty\n");
431 }
432
433 static void fill_url_components(LPURL_COMPONENTS lpUrlComponents)
434 {
435     static CHAR http[]       = "http",
436                 winehq[]     = "www.winehq.org",
437                 username[]   = "username",
438                 password[]   = "password",
439                 site_about[] = "/site/about",
440                 empty[]      = "";
441
442     lpUrlComponents->dwStructSize = sizeof(URL_COMPONENTS);
443     lpUrlComponents->lpszScheme = http;
444     lpUrlComponents->dwSchemeLength = strlen(lpUrlComponents->lpszScheme);
445     lpUrlComponents->nScheme = INTERNET_SCHEME_HTTP;
446     lpUrlComponents->lpszHostName = winehq;
447     lpUrlComponents->dwHostNameLength = strlen(lpUrlComponents->lpszHostName);
448     lpUrlComponents->nPort = 80;
449     lpUrlComponents->lpszUserName = username;
450     lpUrlComponents->dwUserNameLength = strlen(lpUrlComponents->lpszUserName);
451     lpUrlComponents->lpszPassword = password;
452     lpUrlComponents->dwPasswordLength = strlen(lpUrlComponents->lpszPassword);
453     lpUrlComponents->lpszUrlPath = site_about;
454     lpUrlComponents->dwUrlPathLength = strlen(lpUrlComponents->lpszUrlPath);
455     lpUrlComponents->lpszExtraInfo = empty;
456     lpUrlComponents->dwExtraInfoLength = strlen(lpUrlComponents->lpszExtraInfo);
457 }
458
459 static void InternetCreateUrlA_test(void)
460 {
461         URL_COMPONENTS urlComp;
462         LPSTR szUrl;
463         DWORD len = -1;
464         BOOL ret;
465         static CHAR empty[]      = "",
466                     nhttp[]      = "nhttp",
467                     http[]       = "http",
468                     https[]      = "https",
469                     winehq[]     = "www.winehq.org",
470                     localhost[]  = "localhost",
471                     username[]   = "username",
472                     password[]   = "password",
473                     root[]       = "/",
474                     site_about[] = "/site/about",
475                     extra_info[] = "?test=123",
476                     about[]      = "about",
477                     blank[]      = "blank",
478                     host[]       = "host";
479
480         /* test NULL lpUrlComponents */
481         SetLastError(0xdeadbeef);
482         ret = InternetCreateUrlA(NULL, 0, NULL, &len);
483         ok(!ret, "Expected failure\n");
484         ok(GetLastError() == ERROR_INVALID_PARAMETER,
485                 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
486         ok(len == -1, "Expected len -1, got %d\n", len);
487
488         /* test zero'ed lpUrlComponents */
489         ZeroMemory(&urlComp, sizeof(URL_COMPONENTS));
490         SetLastError(0xdeadbeef);
491         ret = InternetCreateUrlA(&urlComp, 0, NULL, &len);
492         ok(!ret, "Expected failure\n");
493         ok(GetLastError() == ERROR_INVALID_PARAMETER,
494                 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
495         ok(len == -1, "Expected len -1, got %d\n", len);
496
497         /* test valid lpUrlComponents, NULL lpdwUrlLength */
498         fill_url_components(&urlComp);
499         SetLastError(0xdeadbeef);
500         ret = InternetCreateUrlA(&urlComp, 0, NULL, NULL);
501         ok(!ret, "Expected failure\n");
502         ok(GetLastError() == ERROR_INVALID_PARAMETER,
503                 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
504         ok(len == -1, "Expected len -1, got %d\n", len);
505
506         /* test valid lpUrlComponents, empty szUrl
507          * lpdwUrlLength is size of buffer required on exit, including
508          * the terminating null when GLE == ERROR_INSUFFICIENT_BUFFER
509          */
510         SetLastError(0xdeadbeef);
511         ret = InternetCreateUrlA(&urlComp, 0, NULL, &len);
512         ok(!ret, "Expected failure\n");
513         ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
514                 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
515         ok(len == 51, "Expected len 51, got %d\n", len);
516
517         /* test correct size, NULL szUrl */
518         fill_url_components(&urlComp);
519         SetLastError(0xdeadbeef);
520         ret = InternetCreateUrlA(&urlComp, 0, NULL, &len);
521         ok(!ret, "Expected failure\n");
522         ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
523                 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
524         ok(len == 51, "Expected len 51, got %d\n", len);
525
526         /* test valid lpUrlComponents, alloc-ed szUrl, small size */
527         SetLastError(0xdeadbeef);
528         szUrl = HeapAlloc(GetProcessHeap(), 0, len);
529         len -= 2;
530         ret = InternetCreateUrlA(&urlComp, 0, szUrl, &len);
531         ok(!ret, "Expected failure\n");
532         ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
533                 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
534         ok(len == 51, "Expected len 51, got %d\n", len);
535
536         /* alloc-ed szUrl, NULL lpszScheme
537          * shows that it uses nScheme instead
538          */
539         SetLastError(0xdeadbeef);
540         urlComp.lpszScheme = NULL;
541         ret = InternetCreateUrlA(&urlComp, 0, szUrl, &len);
542         ok(ret, "Expected success\n");
543         ok(GetLastError() == 0xdeadbeef,
544                 "Expected 0xdeadbeef, got %d\n", GetLastError());
545         ok(len == 50, "Expected len 50, got %d\n", len);
546         ok(!strcmp(szUrl, CREATE_URL1), "Expected %s, got %s\n", CREATE_URL1, szUrl);
547
548         /* alloc-ed szUrl, invalid nScheme
549          * any nScheme out of range seems ignored
550          */
551         fill_url_components(&urlComp);
552         SetLastError(0xdeadbeef);
553         urlComp.nScheme = -3;
554         len++;
555         ret = InternetCreateUrlA(&urlComp, 0, szUrl, &len);
556         ok(ret, "Expected success\n");
557         ok(GetLastError() == 0xdeadbeef,
558                 "Expected 0xdeadbeef, got %d\n", GetLastError());
559         ok(len == 50, "Expected len 50, got %d\n", len);
560
561         /* test valid lpUrlComponents, alloc-ed szUrl */
562         fill_url_components(&urlComp);
563         SetLastError(0xdeadbeef);
564         len = 51;
565         ret = InternetCreateUrlA(&urlComp, 0, szUrl, &len);
566         ok(ret, "Expected success\n");
567         ok(GetLastError() == 0xdeadbeef,
568                 "Expected 0xdeadbeef, got %d\n", GetLastError());
569         ok(len == 50, "Expected len 50, got %d\n", len);
570         ok(strstr(szUrl, "80") == NULL, "Didn't expect to find 80 in szUrl\n");
571         ok(!strcmp(szUrl, CREATE_URL1), "Expected %s, got %s\n", CREATE_URL1, szUrl);
572
573         /* valid username, NULL password */
574         fill_url_components(&urlComp);
575         SetLastError(0xdeadbeef);
576         urlComp.lpszPassword = NULL;
577         len = 42;
578         ret = InternetCreateUrlA(&urlComp, 0, szUrl, &len);
579         ok(ret, "Expected success\n");
580         ok(GetLastError() == 0xdeadbeef,
581                 "Expected 0xdeadbeef, got %d\n", GetLastError());
582         ok(len == 41, "Expected len 41, got %d\n", len);
583         ok(!strcmp(szUrl, CREATE_URL2), "Expected %s, got %s\n", CREATE_URL2, szUrl);
584
585         /* valid username, empty password */
586         fill_url_components(&urlComp);
587         SetLastError(0xdeadbeef);
588         urlComp.lpszPassword = empty;
589         len = 51;
590         ret = InternetCreateUrlA(&urlComp, 0, szUrl, &len);
591         ok(ret, "Expected success\n");
592         ok(GetLastError() == 0xdeadbeef,
593                 "Expected 0xdeadbeef, got %d\n", GetLastError());
594         ok(len == 50, "Expected len 50, got %d\n", len);
595         ok(!strcmp(szUrl, CREATE_URL3), "Expected %s, got %s\n", CREATE_URL3, szUrl);
596
597         /* valid password, NULL username
598          * if password is provided, username has to exist
599          */
600         fill_url_components(&urlComp);
601         SetLastError(0xdeadbeef);
602         urlComp.lpszUserName = NULL;
603         len = 42;
604         ret = InternetCreateUrlA(&urlComp, 0, szUrl, &len);
605         ok(!ret, "Expected failure\n");
606         ok(GetLastError() == ERROR_INVALID_PARAMETER,
607                 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
608         ok(len == 42, "Expected len 42, got %d\n", len);
609         ok(!strcmp(szUrl, CREATE_URL3), "Expected %s, got %s\n", CREATE_URL3, szUrl);
610
611         /* valid password, empty username
612          * if password is provided, username has to exist
613          */
614         fill_url_components(&urlComp);
615         SetLastError(0xdeadbeef);
616         urlComp.lpszUserName = empty;
617         len = 51;
618         ret = InternetCreateUrlA(&urlComp, 0, szUrl, &len);
619         ok(ret, "Expected success\n");
620         ok(GetLastError() == 0xdeadbeef,
621                 "Expected 0xdeadbeef, got %d\n", GetLastError());
622         ok(len == 50, "Expected len 50, got %d\n", len);
623         ok(!strcmp(szUrl, CREATE_URL5), "Expected %s, got %s\n", CREATE_URL5, szUrl);
624
625         /* NULL username, NULL password */
626         fill_url_components(&urlComp);
627         SetLastError(0xdeadbeef);
628         urlComp.lpszUserName = NULL;
629         urlComp.lpszPassword = NULL;
630         len = 42;
631         ret = InternetCreateUrlA(&urlComp, 0, szUrl, &len);
632         ok(ret, "Expected success\n");
633         ok(GetLastError() == 0xdeadbeef,
634                 "Expected 0xdeadbeef, got %d\n", GetLastError());
635         ok(len == 32, "Expected len 32, got %d\n", len);
636         ok(!strcmp(szUrl, CREATE_URL4), "Expected %s, got %s\n", CREATE_URL4, szUrl);
637
638         /* empty username, empty password */
639         fill_url_components(&urlComp);
640         SetLastError(0xdeadbeef);
641         urlComp.lpszUserName = empty;
642         urlComp.lpszPassword = empty;
643         len = 51;
644         ret = InternetCreateUrlA(&urlComp, 0, szUrl, &len);
645         ok(ret, "Expected success\n");
646         ok(GetLastError() == 0xdeadbeef,
647                 "Expected 0xdeadbeef, got %d\n", GetLastError());
648         ok(len == 50, "Expected len 50, got %d\n", len);
649         ok(!strcmp(szUrl, CREATE_URL5), "Expected %s, got %s\n", CREATE_URL5, szUrl);
650
651         /* shows that nScheme is ignored, as the appearance of the port number
652          * depends on lpszScheme and the string copied depends on lpszScheme.
653          */
654         fill_url_components(&urlComp);
655         HeapFree(GetProcessHeap(), 0, szUrl);
656         urlComp.lpszScheme = nhttp;
657         urlComp.dwSchemeLength = strlen(urlComp.lpszScheme);
658         len = strlen(CREATE_URL6) + 1;
659         szUrl = HeapAlloc(GetProcessHeap(), 0, len);
660         ret = InternetCreateUrlA(&urlComp, ICU_ESCAPE, szUrl, &len);
661         ok(ret, "Expected success\n");
662         ok(len == strlen(CREATE_URL6), "Expected len %d, got %d\n", lstrlenA(CREATE_URL6) + 1, len);
663         ok(!strcmp(szUrl, CREATE_URL6), "Expected %s, got %s\n", CREATE_URL6, szUrl);
664
665         /* if lpszScheme != "http" or nPort != 80, display nPort */
666         HeapFree(GetProcessHeap(), 0, szUrl);
667         urlComp.lpszScheme = http;
668         urlComp.dwSchemeLength = strlen(urlComp.lpszScheme);
669         urlComp.nPort = 42;
670         szUrl = HeapAlloc(GetProcessHeap(), 0, ++len);
671         ret = InternetCreateUrlA(&urlComp, ICU_ESCAPE, szUrl, &len);
672         ok(ret, "Expected success\n");
673         ok(len == 53, "Expected len 53, got %d\n", len);
674         ok(strstr(szUrl, "42") != NULL, "Expected to find 42 in szUrl\n");
675         ok(!strcmp(szUrl, CREATE_URL7), "Expected %s, got %s\n", CREATE_URL7, szUrl);
676
677         HeapFree(GetProcessHeap(), 0, szUrl);
678
679         memset(&urlComp, 0, sizeof(urlComp));
680         urlComp.dwStructSize = sizeof(URL_COMPONENTS);
681         urlComp.lpszScheme = http;
682         urlComp.dwSchemeLength = 0;
683         urlComp.nScheme = INTERNET_SCHEME_HTTP;
684         urlComp.lpszHostName = winehq;
685         urlComp.dwHostNameLength = 0;
686         urlComp.nPort = 80;
687         urlComp.lpszUserName = username;
688         urlComp.dwUserNameLength = 0;
689         urlComp.lpszPassword = password;
690         urlComp.dwPasswordLength = 0;
691         urlComp.lpszUrlPath = site_about;
692         urlComp.dwUrlPathLength = 0;
693         urlComp.lpszExtraInfo = empty;
694         urlComp.dwExtraInfoLength = 0;
695         len = strlen(CREATE_URL1);
696         szUrl = HeapAlloc(GetProcessHeap(), 0, ++len);
697         ret = InternetCreateUrlA(&urlComp, ICU_ESCAPE, szUrl, &len);
698         ok(ret, "Expected success\n");
699         ok(len == strlen(CREATE_URL1), "Expected len %d, got %d\n", lstrlenA(CREATE_URL1), len);
700         ok(!strcmp(szUrl, CREATE_URL1), "Expected %s, got %s\n", CREATE_URL1, szUrl);
701
702         HeapFree(GetProcessHeap(), 0, szUrl);
703
704         memset(&urlComp, 0, sizeof(urlComp));
705         urlComp.dwStructSize = sizeof(URL_COMPONENTS);
706         urlComp.lpszScheme = https;
707         urlComp.dwSchemeLength = 0;
708         urlComp.nScheme = INTERNET_SCHEME_HTTP;
709         urlComp.lpszHostName = winehq;
710         urlComp.dwHostNameLength = 0;
711         urlComp.nPort = 443;
712         urlComp.lpszUserName = username;
713         urlComp.dwUserNameLength = 0;
714         urlComp.lpszPassword = password;
715         urlComp.dwPasswordLength = 0;
716         urlComp.lpszUrlPath = site_about;
717         urlComp.dwUrlPathLength = 0;
718         urlComp.lpszExtraInfo = empty;
719         urlComp.dwExtraInfoLength = 0;
720         len = strlen(CREATE_URL8);
721         szUrl = HeapAlloc(GetProcessHeap(), 0, ++len);
722         ret = InternetCreateUrlA(&urlComp, ICU_ESCAPE, szUrl, &len);
723         ok(ret, "Expected success\n");
724         ok(len == strlen(CREATE_URL8), "Expected len %d, got %d\n", lstrlenA(CREATE_URL8), len);
725         ok(!strcmp(szUrl, CREATE_URL8), "Expected %s, got %s\n", CREATE_URL8, szUrl);
726
727         HeapFree(GetProcessHeap(), 0, szUrl);
728
729         memset(&urlComp, 0, sizeof(urlComp));
730         urlComp.dwStructSize = sizeof(URL_COMPONENTS);
731         urlComp.lpszScheme = about;
732         urlComp.dwSchemeLength = 5;
733         urlComp.lpszUrlPath = blank;
734         urlComp.dwUrlPathLength = 5;
735         len = strlen(CREATE_URL9);
736         len++; /* work around bug in native wininet */
737         szUrl = HeapAlloc(GetProcessHeap(), 0, ++len);
738         ret = InternetCreateUrlA(&urlComp, ICU_ESCAPE, szUrl, &len);
739         ok(ret, "Expected success\n");
740         ok(len == strlen(CREATE_URL9), "Expected len %d, got %d\n", lstrlenA(CREATE_URL9), len);
741         ok(!strcmp(szUrl, CREATE_URL9), "Expected %s, got %s\n", CREATE_URL9, szUrl);
742
743         HeapFree(GetProcessHeap(), 0, szUrl);
744
745         memset(&urlComp, 0, sizeof(urlComp));
746         urlComp.dwStructSize = sizeof(URL_COMPONENTS);
747         urlComp.lpszScheme = about;
748         urlComp.lpszHostName = host;
749         urlComp.lpszUrlPath = blank;
750         len = strlen(CREATE_URL10);
751         len++; /* work around bug in native wininet */
752         szUrl = HeapAlloc(GetProcessHeap(), 0, ++len);
753         ret = InternetCreateUrlA(&urlComp, ICU_ESCAPE, szUrl, &len);
754         ok(ret, "Expected success\n");
755         ok(len == strlen(CREATE_URL10), "Expected len %d, got %d\n", lstrlenA(CREATE_URL10), len);
756         ok(!strcmp(szUrl, CREATE_URL10), "Expected %s, got %s\n", CREATE_URL10, szUrl);
757
758         HeapFree(GetProcessHeap(), 0, szUrl);
759
760         memset(&urlComp, 0, sizeof(urlComp));
761         urlComp.dwStructSize = sizeof(URL_COMPONENTS);
762         urlComp.nPort = 8080;
763         urlComp.lpszScheme = about;
764         len = strlen(CREATE_URL11);
765         szUrl = HeapAlloc(GetProcessHeap(), 0, ++len);
766         ret = InternetCreateUrlA(&urlComp, ICU_ESCAPE, szUrl, &len);
767         ok(ret, "Expected success\n");
768         ok(len == strlen(CREATE_URL11), "Expected len %d, got %d\n", lstrlenA(CREATE_URL11), len);
769         ok(!strcmp(szUrl, CREATE_URL11), "Expected %s, got %s\n", CREATE_URL11, szUrl);
770
771         HeapFree(GetProcessHeap(), 0, szUrl);
772
773         memset(&urlComp, 0, sizeof(urlComp));
774         urlComp.dwStructSize = sizeof(URL_COMPONENTS);
775         urlComp.lpszScheme = http;
776         urlComp.dwSchemeLength = 0;
777         urlComp.nScheme = INTERNET_SCHEME_HTTP;
778         urlComp.lpszHostName = winehq;
779         urlComp.dwHostNameLength = 0;
780         urlComp.nPort = 65535;
781         len = strlen(CREATE_URL12);
782         szUrl = HeapAlloc(GetProcessHeap(), 0, ++len);
783         ret = InternetCreateUrlA(&urlComp, ICU_ESCAPE, szUrl, &len);
784         ok(ret, "Expected success\n");
785         ok(len == strlen(CREATE_URL12), "Expected len %d, got %d\n", lstrlenA(CREATE_URL12), len);
786         ok(!strcmp(szUrl, CREATE_URL12), "Expected %s, got %s\n", CREATE_URL12, szUrl);
787
788         HeapFree(GetProcessHeap(), 0, szUrl);
789
790     memset(&urlComp, 0, sizeof(urlComp));
791     urlComp.dwStructSize = sizeof(URL_COMPONENTS);
792     urlComp.lpszScheme = http;
793     urlComp.dwSchemeLength = strlen(urlComp.lpszScheme);
794     urlComp.lpszHostName = localhost;
795     urlComp.dwHostNameLength = strlen(urlComp.lpszHostName);
796     urlComp.nPort = 80;
797     urlComp.lpszUrlPath = root;
798     urlComp.dwUrlPathLength = strlen(urlComp.lpszUrlPath);
799     urlComp.lpszExtraInfo = extra_info;
800     urlComp.dwExtraInfoLength = strlen(urlComp.lpszExtraInfo);
801     len = 256;
802     szUrl = HeapAlloc(GetProcessHeap(), 0, len);
803     InternetCreateUrlA(&urlComp, ICU_ESCAPE, szUrl, &len);
804     ok(ret, "Expected success\n");
805     ok(len == strlen(CREATE_URL13), "Got len %u\n", len);
806     ok(!strcmp(szUrl, CREATE_URL13), "Expected \"%s\", got \"%s\"\n", CREATE_URL13, szUrl);
807
808     HeapFree(GetProcessHeap(), 0, szUrl);
809 }
810
811 START_TEST(url)
812 {
813     InternetCrackUrl_test();
814     InternetCrackUrlW_test();
815     InternetCreateUrlA_test();
816 }