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