Release 1.4.1.
[wine] / dlls / winhttp / tests / url.c
1 /*
2  * Copyright 2008 Hans Leidekker
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  */
18
19 #include <stdarg.h>
20
21 #include "windef.h"
22 #include "winbase.h"
23 #include "winnls.h"
24 #include "winhttp.h"
25
26 #include "wine/test.h"
27
28 static WCHAR empty[]    = {0};
29 static WCHAR ftp[]      = {'f','t','p',0};
30 static WCHAR http[]     = {'h','t','t','p',0};
31 static WCHAR winehq[]   = {'w','w','w','.','w','i','n','e','h','q','.','o','r','g',0};
32 static WCHAR username[] = {'u','s','e','r','n','a','m','e',0};
33 static WCHAR password[] = {'p','a','s','s','w','o','r','d',0};
34 static WCHAR about[]    = {'/','s','i','t','e','/','a','b','o','u','t',0};
35 static WCHAR query[]    = {'?','q','u','e','r','y',0};
36 static WCHAR escape[]   = {' ','!','"','#','$','%','&','\'','(',')','*','+',',','-','.','/',':',';','<','=','>','?','@','[','\\',']','^','_','`','{','|','}','~',0};
37
38 static const WCHAR url1[]  =
39     {'h','t','t','p',':','/','/','u','s','e','r','n','a','m','e',':','p','a','s','s','w','o','r','d',
40      '@','w','w','w','.','w','i','n','e','h','q','.','o','r','g','/','s','i','t','e','/','a','b','o','u','t','?','q','u','e','r','y',0};
41 static const WCHAR url2[] =
42     {'h','t','t','p',':','/','/','u','s','e','r','n','a','m','e',
43      '@','w','w','w','.','w','i','n','e','h','q','.','o','r','g','/','s','i','t','e','/','a','b','o','u','t','?','q','u','e','r','y',0};
44 static const WCHAR url3[] = {'h','t','t','p',':','/','/','u','s','e','r','n','a','m','e',':',0};
45 static const WCHAR url4[] =
46     {'h','t','t','p',':','/','/','w','w','w','.','w','i','n','e','h','q','.','o','r','g','/','s','i','t','e','/','a','b','o','u','t','?','q','u','e','r','y',0};
47 static const WCHAR url5[] = {'h','t','t','p',':','/','/',0};
48 static const WCHAR url6[] =
49     {'f','t','p',':','/','/','u','s','e','r','n','a','m','e',':','p','a','s','s','w','o','r','d',
50      '@','w','w','w','.','w','i','n','e','h','q','.','o','r','g',':','8','0','/','s','i','t','e','/','a','b','o','u','t','?','q','u','e','r','y',0};
51 static const WCHAR url7[] =
52     {'h','t','t','p',':','/','/','u','s','e','r','n','a','m','e',':','p','a','s','s','w','o','r','d',
53      '@','w','w','w','.','w','i','n','e','h','q','.','o','r','g',':','4','2','/','s','i','t','e','/','a','b','o','u','t','?','q','u','e','r','y',0};
54 static const WCHAR url8[] =
55     {'h','t','t','p',':','/','/','u','s','e','r','n','a','m','e',':','p','a','s','s','w','o','r','d',
56      '@','w','w','w','.','w','i','n','e','h','q','.','o','r','g','/','s','i','t','e','/','a','b','o','u','t',
57      '%','2','0','!','%','2','2','%','2','3','$','%','2','5','&','\'','(',')','*','+',',','-','.','/',':',';','%','3','C','=','%','3','E','?','@','%',
58      '5','B','%','5','C','%','5','D','%','5','E','_','%','6','0','%','7','B','%','7','C','%','7','D','%','7','E',0};
59 static const WCHAR url9[] =
60     {'h','t','t','p',':','/','/','u','s','e','r','n','a','m','e',':','p','a','s','s','w','o','r','d',
61      '@','w','w','w','.','w','i','n','e','h','q','.','o','r','g',':','0','/','s','i','t','e','/','a','b','o','u','t','?','q','u','e','r','y',0};
62 static const WCHAR url10[] =
63     {'h','t','t','p',':','/','/','u','s','e','r','n','a','m','e',':','p','a','s','s','w','o','r','d',
64      '@','w','w','w','.','w','i','n','e','h','q','.','o','r','g',':','8','0','/','s','i','t','e','/','a','b','o','u','t','?','q','u','e','r','y',0};
65 static const WCHAR url11[] =
66     {'h','t','t','p','s',':','/','/','u','s','e','r','n','a','m','e',':','p','a','s','s','w','o','r','d',
67      '@','w','w','w','.','w','i','n','e','h','q','.','o','r','g',':','4','4','3','/','s','i','t','e','/','a','b','o','u','t','?','q','u','e','r','y',0};
68 static const WCHAR url12[] =
69     {'h','t','t','p',':','/','/','e','x','a','m','p','l','e','.','n','e','t','/','p','a','t','h','?','v','a','r','1','=','e','x','a','m','p','l','e','@','e','x','a','m','p','l','e','.','c','o','m','&','v','a','r','2','=','x','&','v','a','r','3','=','y', 0};
70 static const WCHAR url13[] =
71     {'h','t','t','p','s',':','/','/','t','o','o','l','s','.','g','o','o','g','l','e','.','c','o','m','/','s','e','r','v','i','c','e','/','u','p','d','a','t','e','2','?','w','=','3',':','B','x','D','H','o','W','y','8','e','z','M',0};
72 static const WCHAR url14[] =
73     {'h','t','t','p',':','/','/','w','i','n','e','h','q','.','o',' ','g','/','p','a','t','h',' ','w','i','t','h',' ','s','p','a','c','e','s',0};
74
75 static const WCHAR url_k1[]  =
76     {'h','t','t','p',':','/','/','u','s','e','r','n','a','m','e',':','p','a','s','s','w','o','r','d',
77      '@','w','w','w','.','w','i','n','e','h','q','.','o','r','g','/','s','i','t','e','/','a','b','o','u','t',0};
78 static const WCHAR url_k2[]  =
79     {'h','t','t','p',':','/','/','w','w','w','.','w','i','n','e','h','q','.','o','r','g',0};
80 static const WCHAR url_k3[]  =
81     {'h','t','t','p','s',':','/','/','w','w','w','.','w','i','n','e','h','q','.','o','r','g','/','p','o','s','t','?',0};
82 static const WCHAR url_k4[]  =
83     {'H','T','T','P',':','w','w','w','.','w','i','n','e','h','q','.','o','r','g',0};
84 static const WCHAR url_k5[]  =
85     {'h','t','t','p',':','/','w','w','w','.','w','i','n','e','h','q','.','o','r','g',0};
86 static const WCHAR url_k6[]  =
87     {'w','w','w','.','w','i','n','e','h','q','.','o','r','g',0};
88 static const WCHAR url_k7[]  =
89     {'w','w','w',0};
90 static const WCHAR url_k8[]  =
91     {'h','t','t','p',0};
92 static const WCHAR url_k9[]  =
93     {'h','t','t','p',':','/','/','w','i','n','e','h','q','?',0};
94 static const WCHAR url_k10[]  =
95     {'h','t','t','p',':','/','/','w','i','n','e','h','q','/','p','o','s','t',';','a',0};
96
97 static void fill_url_components( URL_COMPONENTS *uc )
98 {
99     uc->dwStructSize = sizeof(URL_COMPONENTS);
100     uc->lpszScheme = http;
101     uc->dwSchemeLength = lstrlenW( uc->lpszScheme );
102     uc->nScheme = INTERNET_SCHEME_HTTP;
103     uc->lpszHostName = winehq;
104     uc->dwHostNameLength = lstrlenW( uc->lpszHostName );
105     uc->nPort = 80;
106     uc->lpszUserName = username;
107     uc->dwUserNameLength = lstrlenW( uc->lpszUserName );
108     uc->lpszPassword = password;
109     uc->dwPasswordLength = lstrlenW( uc->lpszPassword );
110     uc->lpszUrlPath = about;
111     uc->dwUrlPathLength = lstrlenW( uc->lpszUrlPath );
112     uc->lpszExtraInfo = query;
113     uc->dwExtraInfoLength = lstrlenW( uc->lpszExtraInfo );
114 }
115
116 static void WinHttpCreateUrl_test( void )
117 {
118     URL_COMPONENTS uc;
119     WCHAR *url;
120     DWORD len;
121     BOOL ret;
122
123     /* NULL components */
124     len = ~0u;
125     SetLastError( 0xdeadbeef );
126     ret = WinHttpCreateUrl( NULL, 0, NULL, &len );
127     ok( !ret, "expected failure\n" );
128     ok( GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER got %u\n", GetLastError() );
129     ok( len == ~0u, "expected len ~0u got %u\n", len );
130
131     /* zero'ed components */
132     memset( &uc, 0, sizeof(URL_COMPONENTS) );
133     SetLastError( 0xdeadbeef );
134     ret = WinHttpCreateUrl( &uc, 0, NULL, &len );
135     ok( !ret, "expected failure\n" );
136     ok( GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER got %u\n", GetLastError() );
137     ok( len == ~0u, "expected len ~0u got %u\n", len );
138
139     /* valid components, NULL url, NULL length */
140     fill_url_components( &uc );
141     SetLastError( 0xdeadbeef );
142     ret = WinHttpCreateUrl( &uc, 0, NULL, NULL );
143     ok( !ret, "expected failure\n" );
144     ok( GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER got %u\n", GetLastError() );
145     ok( len == ~0u, "expected len ~0u got %u\n", len );
146
147     /* valid components, NULL url */
148     SetLastError( 0xdeadbeef );
149     ret = WinHttpCreateUrl( &uc, 0, NULL, &len );
150     ok( !ret, "expected failure\n" );
151     ok( GetLastError() == ERROR_INSUFFICIENT_BUFFER ||
152         GetLastError() == ERROR_INVALID_PARAMETER,
153         "expected ERROR_INSUFFICIENT_BUFFER or ERROR_INVALID_PARAMETER got %u\n", GetLastError() );
154
155     /* correct size, NULL url */
156     fill_url_components( &uc );
157     SetLastError( 0xdeadbeef );
158     ret = WinHttpCreateUrl( &uc, 0, NULL, &len );
159     ok( !ret, "expected failure\n" );
160     ok( GetLastError() == ERROR_INSUFFICIENT_BUFFER ||
161         GetLastError() == ERROR_INVALID_PARAMETER,
162         "expected ERROR_INSUFFICIENT_BUFFER or ERROR_INVALID_PARAMETER got %u\n", GetLastError() );
163
164     /* valid components, allocated url, short length */
165     SetLastError( 0xdeadbeef );
166     url = HeapAlloc( GetProcessHeap(), 0, 256 * sizeof(WCHAR) );
167     url[0] = 0;
168     len = 2;
169     ret = WinHttpCreateUrl( &uc, 0, url, &len );
170     ok( !ret, "expected failure\n" );
171     ok( GetLastError() == ERROR_INSUFFICIENT_BUFFER, "expected ERROR_INSUFFICIENT_BUFFER got %u\n", GetLastError() );
172     ok( len == 57, "expected len 57 got %u\n", len );
173
174     /* allocated url, NULL scheme */
175     uc.lpszScheme = NULL;
176     url[0] = 0;
177     len = 256;
178     ret = WinHttpCreateUrl( &uc, 0, url, &len );
179     ok( ret, "expected success\n" );
180     ok( len == 56, "expected len 56 got %u\n", len );
181     ok( !lstrcmpW( url, url1 ), "url doesn't match\n" );
182
183     /* allocated url, 0 scheme */
184     fill_url_components( &uc );
185     uc.nScheme = 0;
186     url[0] = 0;
187     len = 256;
188     ret = WinHttpCreateUrl( &uc, 0, url, &len );
189     ok( ret, "expected success\n" );
190     ok( len == 56, "expected len 56 got %u\n", len );
191
192     /* valid components, allocated url */
193     fill_url_components( &uc );
194     url[0] = 0;
195     len = 256;
196     ret = WinHttpCreateUrl( &uc, 0, url, &len );
197     ok( ret, "expected success\n" );
198     ok( len == 56, "expected len 56 got %d\n", len );
199     ok( !lstrcmpW( url, url1 ), "url doesn't match\n" );
200
201     /* valid username, NULL password */
202     fill_url_components( &uc );
203     uc.lpszPassword = NULL;
204     url[0] = 0;
205     len = 256;
206     ret = WinHttpCreateUrl( &uc, 0, url, &len );
207     ok( ret, "expected success\n" );
208
209     /* valid username, empty password */
210     fill_url_components( &uc );
211     uc.lpszPassword = empty;
212     url[0] = 0;
213     len = 256;
214     ret = WinHttpCreateUrl( &uc, 0, url, &len );
215     ok( ret, "expected success\n" );
216     ok( len == 56, "expected len 56 got %u\n", len );
217     ok( !lstrcmpW( url, url3 ), "url doesn't match\n" );
218
219     /* valid password, NULL username */
220     fill_url_components( &uc );
221     SetLastError( 0xdeadbeef );
222     uc.lpszUserName = NULL;
223     url[0] = 0;
224     len = 256;
225     ret = WinHttpCreateUrl( &uc, 0, url, &len );
226     ok( !ret, "expected failure\n" );
227     ok( GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER got %u\n", GetLastError() );
228
229     /* valid password, empty username */
230     fill_url_components( &uc );
231     uc.lpszUserName = empty;
232     url[0] = 0;
233     len = 256;
234     ret = WinHttpCreateUrl( &uc, 0, url, &len );
235     ok( ret, "expected success\n");
236
237     /* NULL username, NULL password */
238     fill_url_components( &uc );
239     uc.lpszUserName = NULL;
240     uc.lpszPassword = NULL;
241     url[0] = 0;
242     len = 256;
243     ret = WinHttpCreateUrl( &uc, 0, url, &len );
244     ok( ret, "expected success\n" );
245     ok( len == 38, "expected len 38 got %u\n", len );
246     ok( !lstrcmpW( url, url4 ), "url doesn't match\n" );
247
248     /* empty username, empty password */
249     fill_url_components( &uc );
250     uc.lpszUserName = empty;
251     uc.lpszPassword = empty;
252     url[0] = 0;
253     len = 256;
254     ret = WinHttpCreateUrl( &uc, 0, url, &len );
255     ok( ret, "expected success\n" );
256     ok( len == 56, "expected len 56 got %u\n", len );
257     ok( !lstrcmpW( url, url5 ), "url doesn't match\n" );
258
259     /* nScheme has lower precedence than lpszScheme */
260     fill_url_components( &uc );
261     uc.lpszScheme = ftp;
262     uc.dwSchemeLength = lstrlenW( uc.lpszScheme );
263     url[0] = 0;
264     len = 256;
265     ret = WinHttpCreateUrl( &uc, 0, url, &len );
266     ok( ret, "expected success\n" );
267     ok( len == lstrlenW( url6 ), "expected len %d got %u\n", lstrlenW( url6 ) + 1, len );
268     ok( !lstrcmpW( url, url6 ), "url doesn't match\n" );
269
270     /* non-standard port */
271     uc.lpszScheme = http;
272     uc.dwSchemeLength = lstrlenW( uc.lpszScheme );
273     uc.nPort = 42;
274     url[0] = 0;
275     len = 256;
276     ret = WinHttpCreateUrl( &uc, 0, url, &len );
277     ok( ret, "expected success\n" );
278     ok( len == 59, "expected len 59 got %u\n", len );
279     ok( !lstrcmpW( url, url7 ), "url doesn't match\n" );
280
281     /* escape extra info */
282     fill_url_components( &uc );
283     uc.lpszExtraInfo = escape;
284     uc.dwExtraInfoLength = lstrlenW( uc.lpszExtraInfo );
285     url[0] = 0;
286     len = 256;
287     ret = WinHttpCreateUrl( &uc, ICU_ESCAPE, url, &len );
288     ok( ret, "expected success\n" );
289     ok( len == 113, "expected len 113 got %u\n", len );
290     ok( !lstrcmpW( url, url8 ), "url doesn't match\n" );
291
292     /* NULL lpszScheme, 0 nScheme and nPort */
293     fill_url_components( &uc );
294     uc.lpszScheme = NULL;
295     uc.dwSchemeLength = 0;
296     uc.nScheme = 0;
297     uc.nPort = 0;
298     url[0] = 0;
299     len = 256;
300     ret = WinHttpCreateUrl( &uc, 0, url, &len );
301     ok( ret, "expected success\n" );
302     ok( len == 58, "expected len 58 got %u\n", len );
303     ok( !lstrcmpW( url, url9 ), "url doesn't match\n" );
304
305     HeapFree( GetProcessHeap(), 0, url );
306 }
307
308 static void reset_url_components( URL_COMPONENTS *uc )
309 {
310     memset( uc, 0, sizeof(URL_COMPONENTS) );
311     uc->dwStructSize = sizeof(URL_COMPONENTS);
312     uc->dwSchemeLength    = ~0u;
313     uc->dwHostNameLength  = ~0u;
314     uc->nPort             =  0;
315     uc->dwUserNameLength  = ~0u;
316     uc->dwPasswordLength  = ~0u;
317     uc->dwUrlPathLength   = ~0u;
318     uc->dwExtraInfoLength = ~0u;
319 }
320
321 static void WinHttpCrackUrl_test( void )
322 {
323     static const WCHAR hostnameW[] =
324         {'w','i','n','e','h','q','.','o',' ','g',0};
325     static const WCHAR pathW[] =
326         {'/','p','a','t','h','%','2','0','w','i','t','h','%','2','0','s','p','a','c','e','s',0};
327     URL_COMPONENTSW uc;
328     WCHAR scheme[20], user[20], pass[20], host[20], path[80], extra[40];
329     DWORD error;
330     BOOL ret;
331
332     /* buffers of sufficient length */
333     scheme[0] = 0;
334     user[0] = 0;
335     pass[0] = 0;
336     host[0] = 0;
337     path[0] = 0;
338     extra[0] = 0;
339
340     uc.dwStructSize = sizeof(URL_COMPONENTS);
341     uc.nScheme = 0;
342     uc.lpszScheme = scheme;
343     uc.dwSchemeLength = 20;
344     uc.lpszUserName = user;
345     uc.dwUserNameLength = 20;
346     uc.lpszPassword = pass;
347     uc.dwPasswordLength = 20;
348     uc.lpszHostName = host;
349     uc.dwHostNameLength = 20;
350     uc.nPort = 0;
351     uc.lpszUrlPath = path;
352     uc.dwUrlPathLength = 40;
353     uc.lpszExtraInfo = extra;
354     uc.dwExtraInfoLength = 20;
355
356     ret = WinHttpCrackUrl( url1, 0, 0, &uc );
357     ok( ret, "WinHttpCrackUrl failed\n" );
358     ok( uc.nScheme == INTERNET_SCHEME_HTTP, "unexpected scheme\n" );
359     ok( !memcmp( uc.lpszScheme, http, sizeof(http) ), "unexpected scheme\n" );
360     ok( uc.dwSchemeLength == 4, "unexpected scheme length\n" );
361     ok( !memcmp( uc.lpszUserName, username, sizeof(username) ), "unexpected username\n" );
362     ok( uc.dwUserNameLength == 8, "unexpected username length\n" );
363     ok( !memcmp( uc.lpszPassword, password, sizeof(password) ), "unexpected password\n" );
364     ok( uc.dwPasswordLength == 8, "unexpected password length\n" );
365     ok( !memcmp( uc.lpszHostName, winehq, sizeof(winehq) ), "unexpected hostname\n" );
366     ok( uc.dwHostNameLength == 14, "unexpected hostname length\n" );
367     ok( uc.nPort == 80, "unexpected port: %u\n", uc.nPort );
368     ok( !memcmp( uc.lpszUrlPath, about, sizeof(about) ), "unexpected path\n" );
369     ok( uc.dwUrlPathLength == 11, "unexpected path length\n" );
370     ok( !memcmp( uc.lpszExtraInfo, query, sizeof(query) ), "unexpected extra info\n" );
371     ok( uc.dwExtraInfoLength == 6, "unexpected extra info length\n" );
372
373     /* buffer of insufficient length */
374     scheme[0] = 0;
375     uc.dwSchemeLength = 1;
376
377     SetLastError( 0xdeadbeef );
378     ret = WinHttpCrackUrl( url1, 0, 0, &uc );
379     error = GetLastError();
380     ok( !ret, "WinHttpCrackUrl failed\n" );
381     ok( error == ERROR_INSUFFICIENT_BUFFER, "WinHttpCrackUrl failed\n" );
382     ok( uc.dwSchemeLength == 5, "unexpected scheme length: %u\n", uc.dwSchemeLength );
383
384     /* no buffers */
385     reset_url_components( &uc );
386     ret = WinHttpCrackUrl( url_k1, 0, 0,&uc);
387
388     ok( ret, "WinHttpCrackUrl failed\n" );
389     ok( uc.nScheme == INTERNET_SCHEME_HTTP, "unexpected scheme\n" );
390     ok( uc.lpszScheme == url_k1,"unexpected scheme\n" );
391     ok( uc.dwSchemeLength == 4, "unexpected scheme length\n" );
392     ok( uc.lpszUserName == url_k1 + 7, "unexpected username\n" );
393     ok( uc.dwUserNameLength == 8, "unexpected username length\n" );
394     ok( uc.lpszPassword == url_k1 + 16, "unexpected password\n" );
395     ok( uc.dwPasswordLength == 8, "unexpected password length\n" );
396     ok( uc.lpszHostName == url_k1 + 25, "unexpected hostname\n" );
397     ok( uc.dwHostNameLength == 14, "unexpected hostname length\n" );
398     ok( uc.nPort == 80, "unexpected port: %u\n", uc.nPort );
399     ok( uc.lpszUrlPath == url_k1 + 39, "unexpected path\n" );
400     ok( uc.dwUrlPathLength == 11, "unexpected path length\n" );
401     ok( uc.lpszExtraInfo == url_k1 + 50, "unexpected extra info\n" );
402     ok( uc.dwExtraInfoLength == 0, "unexpected extra info length\n" );
403
404     reset_url_components( &uc );
405     ret = WinHttpCrackUrl( url_k2, 0, 0,&uc);
406
407     ok( ret, "WinHttpCrackUrl failed\n" );
408     ok( uc.nScheme == INTERNET_SCHEME_HTTP, "unexpected scheme\n" );
409     ok( uc.lpszScheme == url_k2, "unexpected scheme\n" );
410     ok( uc.dwSchemeLength == 4, "unexpected scheme length\n" );
411     ok( uc.lpszUserName == NULL ,"unexpected username\n" );
412     ok( uc.dwUserNameLength == 0, "unexpected username length\n" );
413     ok( uc.lpszPassword == NULL, "unexpected password\n" );
414     ok( uc.dwPasswordLength == 0, "unexpected password length\n" );
415     ok( uc.lpszHostName == url_k2 + 7, "unexpected hostname\n" );
416     ok( uc.dwHostNameLength == 14, "unexpected hostname length\n" );
417     ok( uc.nPort == 80, "unexpected port: %u\n", uc.nPort );
418     ok( uc.lpszUrlPath == url_k2 + 21, "unexpected path\n" );
419     ok( uc.dwUrlPathLength == 0, "unexpected path length\n" );
420     ok( uc.lpszExtraInfo == url_k2 + 21, "unexpected extra info\n" );
421     ok( uc.dwExtraInfoLength == 0, "unexpected extra info length\n" );
422
423     reset_url_components( &uc );
424     ret = WinHttpCrackUrl( url_k3, 0, 0, &uc );
425
426     ok( ret, "WinHttpCrackUrl failed\n" );
427     ok( uc.nScheme == INTERNET_SCHEME_HTTPS, "unexpected scheme\n" );
428     ok( uc.lpszScheme == url_k3, "unexpected scheme\n" );
429     ok( uc.dwSchemeLength == 5, "unexpected scheme length\n" );
430     ok( uc.lpszUserName == NULL, "unexpected username\n" );
431     ok( uc.dwUserNameLength == 0, "unexpected username length\n" );
432     ok( uc.lpszPassword == NULL, "unexpected password\n" );
433     ok( uc.dwPasswordLength == 0, "unexpected password length\n" );
434     ok( uc.lpszHostName == url_k3 + 8, "unexpected hostname\n" );
435     ok( uc.dwHostNameLength == 14, "unexpected hostname length\n" );
436     ok( uc.nPort == 443, "unexpected port: %u\n", uc.nPort );
437     ok( uc.lpszUrlPath == url_k3 + 22, "unexpected path\n" );
438     ok( uc.dwUrlPathLength == 5, "unexpected path length\n" );
439     ok( uc.lpszExtraInfo == url_k3 + 27, "unexpected extra info\n" );
440     ok( uc.dwExtraInfoLength == 1, "unexpected extra info length\n" );
441
442     /* bad parameters */
443     reset_url_components( &uc );
444     ret = WinHttpCrackUrl( url_k4, 0, 0, &uc );
445     ok( !ret, "WinHttpCrackUrl failed\n" );
446
447     reset_url_components( &uc );
448     ret = WinHttpCrackUrl( url_k5, 0, 0, &uc );
449     ok( !ret, "WinHttpCrackUrl failed\n" );
450
451     reset_url_components( &uc );
452     ret = WinHttpCrackUrl( url_k6, 0, 0, &uc );
453     ok( !ret, "WinHttpCrackUrl failed\n" );
454
455     reset_url_components( &uc );
456     ret = WinHttpCrackUrl( url_k7, 0, 0, &uc );
457     ok( !ret, "WinHttpCrackUrl failed\n" );
458
459     reset_url_components( &uc );
460     ret = WinHttpCrackUrl( url_k8, 0, 0, &uc );
461     ok( !ret, "WinHttpCrackUrl failed\n" );
462
463     reset_url_components( &uc );
464     ret = WinHttpCrackUrl( url_k9, 0, 0, &uc );
465     ok( ret, "WinHttpCrackUrl failed\n" );
466     ok( uc.lpszUrlPath == url_k9 + 14, "unexpected path\n" );
467     ok( uc.dwUrlPathLength == 0, "unexpected path length\n" );
468     ok( uc.lpszExtraInfo == url_k9 + 14, "unexpected extra info\n" );
469     ok( uc.dwExtraInfoLength == 0, "unexpected extra info length\n" );
470
471     reset_url_components( &uc );
472     ret = WinHttpCrackUrl( url_k10, 0, 0, &uc );
473     ok( ret, "WinHttpCrackUrl failed\n" );
474     ok( uc.lpszUrlPath == url_k10 + 13, "unexpected path\n" );
475     ok( uc.dwUrlPathLength == 7, "unexpected path length\n" );
476     ok( uc.lpszExtraInfo == url_k10 + 20, "unexpected extra info\n" );
477     ok( uc.dwExtraInfoLength == 0, "unexpected extra info length\n" );
478
479     reset_url_components( &uc );
480     ret = WinHttpCrackUrl( url5, 0, 0, &uc );
481     ok( !ret, "WinHttpCrackUrl failed\n" );
482
483     reset_url_components( &uc );
484     ret = WinHttpCrackUrl( empty, 0, 0, &uc );
485     ok( !ret, "WinHttpCrackUrl failed\n" );
486
487     ret = WinHttpCrackUrl( url1, 0, 0, NULL );
488     ok( !ret, "WinHttpCrackUrl failed\n" );
489
490     ret = WinHttpCrackUrl( NULL, 0, 0, &uc );
491     ok( !ret, "WinHttpCrackUrl failed\n" );
492
493     /* decoding without buffers */
494     reset_url_components( &uc );
495     SetLastError(0xdeadbeef);
496     ret = WinHttpCrackUrl( url8, 0, ICU_DECODE, &uc );
497     error = GetLastError();
498     ok( !ret, "WinHttpCrackUrl failed\n" );
499     ok( error == ERROR_INVALID_PARAMETER, "WinHttpCrackUrl failed\n" );
500
501     /* decoding with buffers */
502     uc.lpszScheme = scheme;
503     uc.dwSchemeLength = 20;
504     uc.lpszUserName = user;
505     uc.dwUserNameLength = 20;
506     uc.lpszPassword = pass;
507     uc.dwPasswordLength = 20;
508     uc.lpszHostName = host;
509     uc.dwHostNameLength = 20;
510     uc.nPort = 0;
511     uc.lpszUrlPath = path;
512     uc.dwUrlPathLength = 80;
513     uc.lpszExtraInfo = extra;
514     uc.dwExtraInfoLength = 40;
515     path[0] = 0;
516
517     ret = WinHttpCrackUrl( url8, 0, ICU_DECODE, &uc );
518     ok( ret, "WinHttpCrackUrl failed %u\n", GetLastError() );
519     ok( !memcmp( uc.lpszUrlPath + 11, escape, 21 * sizeof(WCHAR) ), "unexpected path\n" );
520     ok( uc.dwUrlPathLength == 32, "unexpected path length %u\n", uc.dwUrlPathLength );
521     ok( !memcmp( uc.lpszExtraInfo, escape + 21, 12 * sizeof(WCHAR) ), "unexpected extra info\n" );
522     ok( uc.dwExtraInfoLength == 12, "unexpected extra info length %u\n", uc.dwExtraInfoLength );
523
524     /* Urls with specified port numbers */
525     /* decoding with buffers */
526     uc.lpszScheme = scheme;
527     uc.dwSchemeLength = 20;
528     uc.lpszUserName = user;
529     uc.dwUserNameLength = 20;
530     uc.lpszPassword = pass;
531     uc.dwPasswordLength = 20;
532     uc.lpszHostName = host;
533     uc.dwHostNameLength = 20;
534     uc.nPort = 0;
535     uc.lpszUrlPath = path;
536     uc.dwUrlPathLength = 40;
537     uc.lpszExtraInfo = extra;
538     uc.dwExtraInfoLength = 20;
539     path[0] = 0;
540
541     ret = WinHttpCrackUrl( url7, 0, 0, &uc );
542     ok( ret, "WinHttpCrackUrl failed\n" );
543     ok( !memcmp( uc.lpszHostName, winehq, sizeof(winehq) ), "unexpected host name: %s\n", wine_dbgstr_w(uc.lpszHostName) );
544     ok( uc.dwHostNameLength == 14, "unexpected host name length: %d\n", uc.dwHostNameLength );
545     ok( uc.nPort == 42, "unexpected port: %u\n", uc.nPort );
546
547     /* decoding without buffers */
548     reset_url_components( &uc );
549     ret = WinHttpCrackUrl( url9, 0, 0, &uc );
550     ok( ret, "WinHttpCrackUrl failed\n" );
551     ok( uc.nPort == 0, "unexpected port: %u\n", uc.nPort );
552
553     reset_url_components( &uc );
554     ret = WinHttpCrackUrl( url10, 0, 0, &uc );
555     ok( ret, "WinHttpCrackUrl failed\n" );
556     ok( uc.nPort == 80, "unexpected port: %u\n", uc.nPort );
557
558     reset_url_components( &uc );
559     ret = WinHttpCrackUrl( url11, 0, 0, &uc );
560     ok( ret, "WinHttpCrackUrl failed\n" );
561     ok( uc.nPort == 443, "unexpected port: %u\n", uc.nPort );
562
563     reset_url_components( &uc );
564     SetLastError( 0xdeadbeef );
565     ret = WinHttpCrackUrl( empty, 0, 0, &uc );
566     error = GetLastError();
567     ok( !ret, "WinHttpCrackUrl succeeded\n" );
568     ok( error == ERROR_WINHTTP_UNRECOGNIZED_SCHEME, "got %u, expected ERROR_WINHTTP_UNRECOGNIZED_SCHEME\n", error );
569
570     reset_url_components( &uc );
571     SetLastError( 0xdeadbeef );
572     ret = WinHttpCrackUrl( http, 0, 0, &uc );
573     error = GetLastError();
574     ok( !ret, "WinHttpCrackUrl succeeded\n" );
575     ok( error == ERROR_WINHTTP_UNRECOGNIZED_SCHEME, "got %u, expected ERROR_WINHTTP_UNRECOGNIZED_SCHEME\n", error );
576
577     reset_url_components( &uc );
578     ret = WinHttpCrackUrl( url12, 0, 0, &uc);
579     ok( ret, "WinHttpCrackUrl failed\n" );
580     ok( uc.nScheme == INTERNET_SCHEME_HTTP, "unexpected scheme\n" );
581     ok( uc.lpszScheme == url12,"unexpected scheme\n" );
582     ok( uc.dwSchemeLength == 4, "unexpected scheme length\n" );
583     ok( uc.lpszUserName == NULL, "unexpected username\n" );
584     ok( uc.lpszPassword == NULL, "unexpected password\n" );
585     ok( uc.lpszHostName == url12 + 7, "unexpected hostname\n" );
586     ok( uc.dwHostNameLength == 11, "unexpected hostname length\n" );
587     ok( uc.nPort == 80, "unexpected port: %u\n", uc.nPort );
588     ok( uc.lpszUrlPath == url12 + 18, "unexpected path\n" );
589     ok( uc.dwUrlPathLength == 5, "unexpected path length\n" );
590     ok( uc.lpszExtraInfo == url12 + 23, "unexpected extra info\n" );
591     ok( uc.dwExtraInfoLength == 39, "unexpected extra info length\n" );
592
593     uc.lpszScheme = scheme;
594     uc.dwSchemeLength = 20;
595     uc.lpszHostName = host;
596     uc.dwHostNameLength = 20;
597     uc.lpszUserName = NULL;
598     uc.dwUserNameLength = 0;
599     uc.lpszPassword = NULL;
600     uc.dwPasswordLength = 0;
601     uc.lpszUrlPath = path;
602     uc.dwUrlPathLength = 40;
603     uc.lpszExtraInfo = NULL;
604     uc.dwExtraInfoLength = 0;
605     uc.nPort = 0;
606     ret = WinHttpCrackUrl( url13, 0, ICU_DECODE, &uc );
607     ok( ret, "WinHttpCrackUrl failed\n" );
608
609     uc.lpszScheme = scheme;
610     uc.dwSchemeLength = 20;
611     uc.lpszHostName = host;
612     uc.dwHostNameLength = 20;
613     uc.lpszUserName = NULL;
614     uc.dwUserNameLength = 0;
615     uc.lpszPassword = NULL;
616     uc.dwPasswordLength = 0;
617     uc.lpszUrlPath = path;
618     uc.dwUrlPathLength = 40;
619     uc.lpszExtraInfo = NULL;
620     uc.dwExtraInfoLength = 0;
621     uc.nPort = 0;
622     ret = WinHttpCrackUrl( url14, 0, ICU_ESCAPE|ICU_DECODE, &uc );
623     ok( ret, "WinHttpCrackUrl failed\n" );
624     ok( !lstrcmpW( uc.lpszHostName, hostnameW ), "unexpected host name\n" );
625     ok( !lstrcmpW( uc.lpszUrlPath, pathW ), "unexpected path\n" );
626 }
627
628 START_TEST(url)
629 {
630     WinHttpCreateUrl_test();
631     WinHttpCrackUrl_test();
632 }