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 static WCHAR escape2[]  = {'\r',0x1f,' ','\n',0x7f,'\r','\n',0};
38 static WCHAR escape3[]  = {'?','t','e','x','t','=',0xfb00,0};
39 static WCHAR escape4[]  = {'/','t','e','x','t','=',0xfb00,0};
40 
41 static const WCHAR url1[]  =
42     {'h','t','t','p',':','/','/','u','s','e','r','n','a','m','e',':','p','a','s','s','w','o','r','d',
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 url2[] = {'h','t','t','p',':','/','/','u','s','e','r','n','a','m','e',':',0};
45 static const WCHAR url3[] =
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 url4[] = {'h','t','t','p',':','/','/',0};
48 static const WCHAR url5[] =
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 url6[] =
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 url7[] =
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 url8[] =
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 url9[] =
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 url10[] =
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 url11[] =
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 url12[] =
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 url13[] =
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 static const WCHAR url14[] = {'h','t','t','p',':','/','/','w','w','w','.','w','i','n','e','h','q','.','o','r','g','/','t','e','s','t',0};
75 static const WCHAR url15[] = {'h','t','t','p',':','/','/','w','i','n','e','h','q','.','o','r','g',':','6','5','5','3','6',0};
76 static const WCHAR url16[] = {'h','t','t','p',':','/','/','w','i','n','e','h','q','.','o','r','g',':','0',0};
77 static const WCHAR url17[] = {'h','t','t','p',':','/','/','w','i','n','e','h','q','.','o','r','g',':',0};
78 static const WCHAR url18[] =
79     {'h','t','t','p',':','/','/','%','0','D','%','1','F','%','2','0','%','0','A','%','7','F','%','0','D','%','0','A',0};
80 static const WCHAR url19[] =
81     {'h','t','t','p',':','/','/','?','t','e','x','t','=',0xfb00,0};
82 static const WCHAR url20[] =
83     {'h','t','t','p',':','/','/','/','t','e','x','t','=',0xfb00,0};
84 static const WCHAR url21[] =
85     {'h','t','t','p','s',':','/','/','n','b','a','2','k','1','9','-','w','s','.','2','k','s','p','o','r','t','s','.','c','o','m',':','1','9','1','3','3',
86      '/','n','b','a','/','v','4','/','A','c','c','o','u','n','t','s','/','g','e','t','_','a','c','c','o','u','n','t','?','x','=','3','7','8','9','5','2',
87      '6','7','7','5','2','6','5','6','6','3','8','7','6',0};
88 
89 static const WCHAR url_k1[]  =
90     {'h','t','t','p',':','/','/','u','s','e','r','n','a','m','e',':','p','a','s','s','w','o','r','d',
91      '@','w','w','w','.','w','i','n','e','h','q','.','o','r','g','/','s','i','t','e','/','a','b','o','u','t',0};
92 static const WCHAR url_k2[]  =
93     {'h','t','t','p',':','/','/','w','w','w','.','w','i','n','e','h','q','.','o','r','g',0};
94 static const WCHAR url_k3[]  =
95     {'h','t','t','p','s',':','/','/','w','w','w','.','w','i','n','e','h','q','.','o','r','g','/','p','o','s','t','?',0};
96 static const WCHAR url_k4[]  =
97     {'H','T','T','P',':','w','w','w','.','w','i','n','e','h','q','.','o','r','g',0};
98 static const WCHAR url_k5[]  =
99     {'h','t','t','p',':','/','w','w','w','.','w','i','n','e','h','q','.','o','r','g',0};
100 static const WCHAR url_k6[]  =
101     {'w','w','w','.','w','i','n','e','h','q','.','o','r','g',0};
102 static const WCHAR url_k7[]  =
103     {'w','w','w',0};
104 static const WCHAR url_k8[]  =
105     {'h','t','t','p',0};
106 static const WCHAR url_k9[]  =
107     {'h','t','t','p',':','/','/','w','i','n','e','h','q','?',0};
108 static const WCHAR url_k10[]  =
109     {'h','t','t','p',':','/','/','w','i','n','e','h','q','/','p','o','s','t',';','a',0};
110 
111 static void fill_url_components( URL_COMPONENTS *uc )
112 {
113     uc->dwStructSize = sizeof(URL_COMPONENTS);
114     uc->lpszScheme = http;
115     uc->dwSchemeLength = lstrlenW( uc->lpszScheme );
116     uc->nScheme = INTERNET_SCHEME_HTTP;
117     uc->lpszHostName = winehq;
118     uc->dwHostNameLength = lstrlenW( uc->lpszHostName );
119     uc->nPort = 80;
120     uc->lpszUserName = username;
121     uc->dwUserNameLength = lstrlenW( uc->lpszUserName );
122     uc->lpszPassword = password;
123     uc->dwPasswordLength = lstrlenW( uc->lpszPassword );
124     uc->lpszUrlPath = about;
125     uc->dwUrlPathLength = lstrlenW( uc->lpszUrlPath );
126     uc->lpszExtraInfo = query;
127     uc->dwExtraInfoLength = lstrlenW( uc->lpszExtraInfo );
128 }
129 
130 static void WinHttpCreateUrl_test( void )
131 {
132     URL_COMPONENTS uc;
133     WCHAR *url;
134     DWORD len, err;
135     BOOL ret;
136 
137     /* NULL components */
138     len = ~0u;
139     SetLastError( 0xdeadbeef );
140     ret = WinHttpCreateUrl( NULL, 0, NULL, &len );
141     ok( !ret, "expected failure\n" );
142     ok( GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER got %u\n", GetLastError() );
143     ok( len == ~0u, "expected len ~0u got %u\n", len );
144 
145     /* zero'ed components */
146     memset( &uc, 0, sizeof(URL_COMPONENTS) );
147     SetLastError( 0xdeadbeef );
148     ret = WinHttpCreateUrl( &uc, 0, NULL, &len );
149     ok( !ret, "expected failure\n" );
150     ok( GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER got %u\n", GetLastError() );
151     ok( len == ~0u, "expected len ~0u got %u\n", len );
152 
153     /* valid components, NULL url, NULL length */
154     fill_url_components( &uc );
155     SetLastError( 0xdeadbeef );
156     ret = WinHttpCreateUrl( &uc, 0, NULL, NULL );
157     ok( !ret, "expected failure\n" );
158     ok( GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER got %u\n", GetLastError() );
159 
160     /* valid components, NULL url, insufficient length */
161     len = 0;
162     SetLastError( 0xdeadbeef );
163     ret = WinHttpCreateUrl( &uc, 0, NULL, &len );
164     ok( !ret, "expected failure\n" );
165     ok( GetLastError() == ERROR_INSUFFICIENT_BUFFER, "expected ERROR_INSUFFICIENT_BUFFER got %u\n", GetLastError() );
166     ok( len == 57, "expected len 57 got %u\n", len );
167 
168     /* valid components, NULL url, sufficient length */
169     SetLastError( 0xdeadbeef );
170     len = 256;
171     ret = WinHttpCreateUrl( &uc, 0, NULL, &len );
172     err = GetLastError();
173     ok( !ret, "expected failure\n" );
174     ok( err == ERROR_INVALID_PARAMETER || broken(err == ERROR_INSUFFICIENT_BUFFER) /* < win7 */,
175         "expected ERROR_INVALID_PARAMETER got %u\n", GetLastError() );
176     ok( len == 256 || broken(len == 57) /* < win7 */, "expected len 256 got %u\n", len );
177 
178     /* correct size, NULL url */
179     fill_url_components( &uc );
180     SetLastError( 0xdeadbeef );
181     ret = WinHttpCreateUrl( &uc, 0, NULL, &len );
182     err = GetLastError();
183     ok( !ret, "expected failure\n" );
184     ok( err == ERROR_INVALID_PARAMETER || broken(err == ERROR_INSUFFICIENT_BUFFER) /* < win7 */,
185         "expected ERROR_INVALID_PARAMETER got %u\n", GetLastError() );
186     ok( len == 256 || broken(len == 57) /* < win7 */, "expected len 256 got %u\n", len );
187 
188     /* valid components, allocated url, short length */
189     SetLastError( 0xdeadbeef );
190     url = HeapAlloc( GetProcessHeap(), 0, 256 * sizeof(WCHAR) );
191     url[0] = 0;
192     len = 2;
193     ret = WinHttpCreateUrl( &uc, 0, url, &len );
194     ok( !ret, "expected failure\n" );
195     ok( GetLastError() == ERROR_INSUFFICIENT_BUFFER, "expected ERROR_INSUFFICIENT_BUFFER got %u\n", GetLastError() );
196     ok( len == 57, "expected len 57 got %u\n", len );
197 
198     /* allocated url, NULL scheme */
199     SetLastError( 0xdeadbeef );
200     uc.lpszScheme = NULL;
201     url[0] = 0;
202     len = 256;
203     ret = WinHttpCreateUrl( &uc, 0, url, &len );
204     ok( ret, "expected success\n" );
205     ok( GetLastError() == ERROR_SUCCESS || broken(GetLastError() == 0xdeadbeef) /* < win7 */,
206         "expected ERROR_SUCCESS got %u\n", GetLastError() );
207     ok( len == 56, "expected len 56 got %u\n", len );
208     ok( !lstrcmpW( url, url1 ), "url doesn't match\n" );
209 
210     /* allocated url, 0 scheme */
211     fill_url_components( &uc );
212     uc.nScheme = 0;
213     url[0] = 0;
214     len = 256;
215     ret = WinHttpCreateUrl( &uc, 0, url, &len );
216     ok( ret, "expected success\n" );
217     ok( len == 56, "expected len 56 got %u\n", len );
218 
219     /* valid components, allocated url */
220     fill_url_components( &uc );
221     url[0] = 0;
222     len = 256;
223     ret = WinHttpCreateUrl( &uc, 0, url, &len );
224     ok( ret, "expected success\n" );
225     ok( len == 56, "expected len 56 got %d\n", len );
226     ok( !lstrcmpW( url, url1 ), "url doesn't match\n" );
227 
228     /* valid username, NULL password */
229     fill_url_components( &uc );
230     uc.lpszPassword = NULL;
231     url[0] = 0;
232     len = 256;
233     ret = WinHttpCreateUrl( &uc, 0, url, &len );
234     ok( ret, "expected success\n" );
235 
236     /* valid username, empty password */
237     fill_url_components( &uc );
238     uc.lpszPassword = empty;
239     url[0] = 0;
240     len = 256;
241     ret = WinHttpCreateUrl( &uc, 0, url, &len );
242     ok( ret, "expected success\n" );
243     ok( len == 56, "expected len 56 got %u\n", len );
244     ok( !lstrcmpW( url, url2 ), "url doesn't match\n" );
245 
246     /* valid password, NULL username */
247     fill_url_components( &uc );
248     SetLastError( 0xdeadbeef );
249     uc.lpszUserName = NULL;
250     url[0] = 0;
251     len = 256;
252     ret = WinHttpCreateUrl( &uc, 0, url, &len );
253     ok( !ret, "expected failure\n" );
254     ok( GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER got %u\n", GetLastError() );
255 
256     /* valid password, empty username */
257     fill_url_components( &uc );
258     uc.lpszUserName = empty;
259     url[0] = 0;
260     len = 256;
261     ret = WinHttpCreateUrl( &uc, 0, url, &len );
262     ok( ret, "expected success\n");
263 
264     /* NULL username, NULL password */
265     fill_url_components( &uc );
266     uc.lpszUserName = NULL;
267     uc.lpszPassword = NULL;
268     url[0] = 0;
269     len = 256;
270     ret = WinHttpCreateUrl( &uc, 0, url, &len );
271     ok( ret, "expected success\n" );
272     ok( len == 38, "expected len 38 got %u\n", len );
273     ok( !lstrcmpW( url, url3 ), "url doesn't match\n" );
274 
275     /* empty username, empty password */
276     fill_url_components( &uc );
277     uc.lpszUserName = empty;
278     uc.lpszPassword = empty;
279     url[0] = 0;
280     len = 256;
281     ret = WinHttpCreateUrl( &uc, 0, url, &len );
282     ok( ret, "expected success\n" );
283     ok( len == 56, "expected len 56 got %u\n", len );
284     ok( !lstrcmpW( url, url4 ), "url doesn't match\n" );
285 
286     /* nScheme has lower precedence than lpszScheme */
287     fill_url_components( &uc );
288     uc.lpszScheme = ftp;
289     uc.dwSchemeLength = lstrlenW( uc.lpszScheme );
290     url[0] = 0;
291     len = 256;
292     ret = WinHttpCreateUrl( &uc, 0, url, &len );
293     ok( ret, "expected success\n" );
294     ok( len == lstrlenW( url5 ), "expected len %d got %u\n", lstrlenW( url5 ) + 1, len );
295     ok( !lstrcmpW( url, url5 ), "url doesn't match\n" );
296 
297     /* non-standard port */
298     uc.lpszScheme = http;
299     uc.dwSchemeLength = lstrlenW( uc.lpszScheme );
300     uc.nPort = 42;
301     url[0] = 0;
302     len = 256;
303     ret = WinHttpCreateUrl( &uc, 0, url, &len );
304     ok( ret, "expected success\n" );
305     ok( len == 59, "expected len 59 got %u\n", len );
306     ok( !lstrcmpW( url, url6 ), "url doesn't match\n" );
307 
308     /* escape extra info */
309     fill_url_components( &uc );
310     uc.lpszExtraInfo = escape;
311     uc.dwExtraInfoLength = lstrlenW( uc.lpszExtraInfo );
312     url[0] = 0;
313     len = 256;
314     ret = WinHttpCreateUrl( &uc, ICU_ESCAPE, url, &len );
315     ok( ret, "expected success\n" );
316     ok( len == 113, "expected len 113 got %u\n", len );
317     ok( !lstrcmpW( url, url7 ), "url doesn't match %s\n", wine_dbgstr_w(url) );
318 
319     /* escape extra info */
320     memset( &uc, 0, sizeof(uc) );
321     uc.dwStructSize = sizeof(uc);
322     uc.lpszExtraInfo = escape2;
323     uc.dwExtraInfoLength = lstrlenW( uc.lpszExtraInfo );
324     url[0] = 0;
325     len = 256;
326     ret = WinHttpCreateUrl( &uc, ICU_ESCAPE, url, &len );
327     ok( ret, "expected success\n" );
328     ok( len == lstrlenW(url18), "expected len %u got %u\n", lstrlenW(url18), len );
329     ok( !lstrcmpW( url, url18 ), "url doesn't match\n" );
330 
331     /* extra info with Unicode characters */
332     memset( &uc, 0, sizeof(uc) );
333     uc.dwStructSize = sizeof(uc);
334     uc.lpszExtraInfo = escape3;
335     uc.dwExtraInfoLength = lstrlenW( uc.lpszExtraInfo );
336     url[0] = 0;
337     len = 256;
338     SetLastError( 0xdeadbeef );
339     ret = WinHttpCreateUrl( &uc, ICU_ESCAPE, url, &len );
340     err = GetLastError();
341     ok( !ret, "expected failure\n" );
342     ok( err == ERROR_INVALID_PARAMETER, "got %u\n", err );
343 
344     /* extra info with Unicode characters, no ICU_ESCAPE */
345     memset( &uc, 0, sizeof(uc) );
346     uc.dwStructSize = sizeof(uc);
347     uc.lpszExtraInfo = escape3;
348     uc.dwExtraInfoLength = lstrlenW( uc.lpszExtraInfo );
349     url[0] = 0;
350     len = 256;
351     ret = WinHttpCreateUrl( &uc, 0, url, &len );
352     ok( ret || broken(!ret) /* < win7 */, "expected success\n" );
353     if (ret)
354     {
355         ok( len == lstrlenW(url19), "expected len %u got %u\n", lstrlenW(url19), len );
356         ok( !lstrcmpW( url, url19 ), "url doesn't match %s\n", wine_dbgstr_w(url) );
357     }
358 
359     /* escape path */
360     memset( &uc, 0, sizeof(uc) );
361     uc.dwStructSize = sizeof(uc);
362     uc.lpszUrlPath = escape2;
363     uc.dwUrlPathLength = lstrlenW( uc.lpszUrlPath );
364     url[0] = 0;
365     len = 256;
366     ret = WinHttpCreateUrl( &uc, ICU_ESCAPE, url, &len );
367     ok( ret, "expected success\n" );
368     ok( len == lstrlenW(url18), "expected len %u got %u\n", lstrlenW(url18), len );
369     ok( !lstrcmpW( url, url18 ), "url doesn't match\n" );
370 
371     /* path with Unicode characters */
372     memset( &uc, 0, sizeof(uc) );
373     uc.dwStructSize = sizeof(uc);
374     uc.lpszUrlPath = escape4;
375     uc.dwUrlPathLength = lstrlenW( uc.lpszUrlPath );
376     url[0] = 0;
377     len = 256;
378     SetLastError( 0xdeadbeef );
379     ret = WinHttpCreateUrl( &uc, ICU_ESCAPE, url, &len );
380     err = GetLastError();
381     ok( !ret, "expected failure\n" );
382     ok( err == ERROR_INVALID_PARAMETER, "got %u\n", err );
383 
384     /* path with Unicode characters, no ICU_ESCAPE */
385     memset( &uc, 0, sizeof(uc) );
386     uc.dwStructSize = sizeof(uc);
387     uc.lpszUrlPath = escape4;
388     uc.dwUrlPathLength = lstrlenW( uc.lpszUrlPath );
389     url[0] = 0;
390     len = 256;
391     ret = WinHttpCreateUrl( &uc, 0, url, &len );
392     ok( ret || broken(!ret) /* < win7 */, "expected success\n" );
393     if (ret)
394     {
395         ok( len == lstrlenW(url20), "expected len %u got %u\n", lstrlenW(url20), len );
396         ok( !lstrcmpW( url, url20 ), "url doesn't match %s\n", wine_dbgstr_w(url) );
397     }
398 
399     /* NULL lpszScheme, 0 nScheme and nPort */
400     fill_url_components( &uc );
401     uc.lpszScheme = NULL;
402     uc.dwSchemeLength = 0;
403     uc.nScheme = 0;
404     uc.nPort = 0;
405     url[0] = 0;
406     len = 256;
407     ret = WinHttpCreateUrl( &uc, 0, url, &len );
408     ok( ret, "expected success\n" );
409     ok( len == 58, "expected len 58 got %u\n", len );
410     ok( !lstrcmpW( url, url8 ), "url doesn't match\n" );
411 
412     HeapFree( GetProcessHeap(), 0, url );
413 }
414 
415 static void reset_url_components( URL_COMPONENTS *uc )
416 {
417     memset( uc, 0, sizeof(URL_COMPONENTS) );
418     uc->dwStructSize = sizeof(URL_COMPONENTS);
419     uc->dwSchemeLength    = ~0u;
420     uc->dwHostNameLength  = 1;
421     uc->nPort             =  0;
422     uc->dwUserNameLength  = ~0u;
423     uc->dwPasswordLength  = ~0u;
424     uc->dwUrlPathLength   = ~0u;
425     uc->dwExtraInfoLength = ~0u;
426 }
427 
428 static void WinHttpCrackUrl_test( void )
429 {
430     static const WCHAR hostnameW[] =
431         {'w','i','n','e','h','q','.','o',' ','g',0};
432     static const WCHAR pathW[] =
433         {'/','p','a','t','h','%','2','0','w','i','t','h','%','2','0','s','p','a','c','e','s',0};
434     URL_COMPONENTSW uc;
435     WCHAR scheme[20], user[20], pass[20], host[40], path[80], extra[40];
436     DWORD error;
437     BOOL ret;
438 
439     /* buffers of sufficient length */
440     scheme[0] = user[0] = pass[0] = host[0] = path[0] = extra[0] = 0;
441 
442     uc.dwStructSize = sizeof(URL_COMPONENTS);
443     uc.nScheme = 0;
444     uc.lpszScheme = scheme;
445     uc.dwSchemeLength = 20;
446     uc.lpszUserName = user;
447     uc.dwUserNameLength = 20;
448     uc.lpszPassword = pass;
449     uc.dwPasswordLength = 20;
450     uc.lpszHostName = host;
451     uc.dwHostNameLength = 20;
452     uc.nPort = 0;
453     uc.lpszUrlPath = path;
454     uc.dwUrlPathLength = 40;
455     uc.lpszExtraInfo = extra;
456     uc.dwExtraInfoLength = 20;
457 
458     ret = WinHttpCrackUrl( url1, 0, 0, &uc );
459     ok( ret, "WinHttpCrackUrl failed le=%u\n", GetLastError() );
460     ok( uc.nScheme == INTERNET_SCHEME_HTTP, "unexpected scheme: %u\n", uc.nScheme );
461     ok( !memcmp( uc.lpszScheme, http, sizeof(http) ), "unexpected scheme: %s\n", wine_dbgstr_w(uc.lpszScheme) );
462     ok( uc.dwSchemeLength == 4, "unexpected scheme length: %u\n", uc.dwSchemeLength );
463     ok( !memcmp( uc.lpszUserName, username, sizeof(username) ), "unexpected username: %s\n", wine_dbgstr_w(uc.lpszUserName) );
464     ok( uc.dwUserNameLength == 8, "unexpected username length: %u\n", uc.dwUserNameLength );
465     ok( !memcmp( uc.lpszPassword, password, sizeof(password) ), "unexpected password: %s\n", wine_dbgstr_w(uc.lpszPassword) );
466     ok( uc.dwPasswordLength == 8, "unexpected password length: %u\n", uc.dwPasswordLength );
467     ok( !memcmp( uc.lpszHostName, winehq, sizeof(winehq) ), "unexpected hostname: %s\n", wine_dbgstr_w(uc.lpszHostName) );
468     ok( uc.dwHostNameLength == 14, "unexpected hostname length: %u\n", uc.dwHostNameLength );
469     ok( uc.nPort == 80, "unexpected port: %u\n", uc.nPort );
470     ok( !memcmp( uc.lpszUrlPath, about, sizeof(about) ), "unexpected path: %s\n", wine_dbgstr_w(uc.lpszUrlPath) );
471     ok( uc.dwUrlPathLength == 11, "unexpected path length: %u\n", uc.dwUrlPathLength );
472     ok( !memcmp( uc.lpszExtraInfo, query, sizeof(query) ), "unexpected extra info: %s\n", wine_dbgstr_w(uc.lpszExtraInfo) );
473     ok( uc.dwExtraInfoLength == 6, "unexpected extra info length: %u\n", uc.dwExtraInfoLength );
474 
475     /* buffers of insufficient length */
476     uc.dwSchemeLength   = 1;
477     uc.dwHostNameLength = 1;
478     uc.dwUrlPathLength  = 40; /* sufficient */
479     SetLastError( 0xdeadbeef );
480     ret = WinHttpCrackUrl( url1, 0, 0, &uc );
481     error = GetLastError();
482     ok( !ret, "WinHttpCrackUrl succeeded\n" );
483     ok( error == ERROR_INSUFFICIENT_BUFFER, "got %u, expected ERROR_INSUFFICIENT_BUFFER\n", error );
484     ok( uc.dwSchemeLength == 5, "unexpected scheme length: %u\n", uc.dwSchemeLength );
485     ok( uc.dwHostNameLength == 15, "unexpected hostname length: %u\n", uc.dwHostNameLength );
486     ok( uc.dwUrlPathLength == 11, "unexpected path length: %u\n", uc.dwUrlPathLength );
487 
488     /* no buffers */
489     reset_url_components( &uc );
490     SetLastError( 0xdeadbeef );
491     ret = WinHttpCrackUrl( url_k1, 0, 0, &uc);
492     error = GetLastError();
493     ok( ret, "WinHttpCrackUrl failed le=%u\n", error );
494     ok( error == ERROR_SUCCESS || broken(error == ERROR_INVALID_PARAMETER) /* < win7 */,
495         "got %u, expected ERROR_SUCCESS\n", error );
496     ok( uc.nScheme == INTERNET_SCHEME_HTTP, "unexpected scheme\n" );
497     ok( uc.lpszScheme == url_k1,"unexpected scheme\n" );
498     ok( uc.dwSchemeLength == 4, "unexpected scheme length\n" );
499     ok( uc.lpszUserName == url_k1 + 7, "unexpected username\n" );
500     ok( uc.dwUserNameLength == 8, "unexpected username length\n" );
501     ok( uc.lpszPassword == url_k1 + 16, "unexpected password\n" );
502     ok( uc.dwPasswordLength == 8, "unexpected password length\n" );
503     ok( uc.lpszHostName == url_k1 + 25, "unexpected hostname\n" );
504     ok( uc.dwHostNameLength == 14, "unexpected hostname length\n" );
505     ok( uc.nPort == 80, "unexpected port: %u\n", uc.nPort );
506     ok( uc.lpszUrlPath == url_k1 + 39, "unexpected path\n" );
507     ok( uc.dwUrlPathLength == 11, "unexpected path length\n" );
508     ok( uc.lpszExtraInfo == url_k1 + 50, "unexpected extra info\n" );
509     ok( uc.dwExtraInfoLength == 0, "unexpected extra info length\n" );
510 
511     reset_url_components( &uc );
512     uc.dwSchemeLength = uc.dwHostNameLength = uc.dwUserNameLength = 1;
513     uc.dwPasswordLength = uc.dwUrlPathLength = uc.dwExtraInfoLength = 1;
514     ret = WinHttpCrackUrl( url_k2, 0, 0,&uc);
515     ok( ret, "WinHttpCrackUrl failed le=%u\n", GetLastError() );
516     ok( uc.nScheme == INTERNET_SCHEME_HTTP, "unexpected scheme\n" );
517     ok( uc.lpszScheme == url_k2, "unexpected scheme\n" );
518     ok( uc.dwSchemeLength == 4, "unexpected scheme length\n" );
519     ok( uc.lpszUserName == NULL ,"unexpected username\n" );
520     ok( uc.dwUserNameLength == 0, "unexpected username length\n" );
521     ok( uc.lpszPassword == NULL, "unexpected password\n" );
522     ok( uc.dwPasswordLength == 0, "unexpected password length\n" );
523     ok( uc.lpszHostName == url_k2 + 7, "unexpected hostname\n" );
524     ok( uc.dwHostNameLength == 14, "unexpected hostname length\n" );
525     ok( uc.nPort == 80, "unexpected port: %u\n", uc.nPort );
526     ok( uc.lpszUrlPath == url_k2 + 21, "unexpected path\n" );
527     ok( uc.dwUrlPathLength == 0, "unexpected path length\n" );
528     ok( uc.lpszExtraInfo == url_k2 + 21, "unexpected extra info\n" );
529     ok( uc.dwExtraInfoLength == 0, "unexpected extra info length\n" );
530 
531     reset_url_components( &uc );
532     ret = WinHttpCrackUrl( url_k3, 0, 0, &uc );
533     ok( ret, "WinHttpCrackUrl failed le=%u\n", GetLastError() );
534     ok( uc.nScheme == INTERNET_SCHEME_HTTPS, "unexpected scheme\n" );
535     ok( uc.lpszScheme == url_k3, "unexpected scheme\n" );
536     ok( uc.dwSchemeLength == 5, "unexpected scheme length\n" );
537     ok( uc.lpszUserName == NULL, "unexpected username\n" );
538     ok( uc.dwUserNameLength == 0, "unexpected username length\n" );
539     ok( uc.lpszPassword == NULL, "unexpected password\n" );
540     ok( uc.dwPasswordLength == 0, "unexpected password length\n" );
541     ok( uc.lpszHostName == url_k3 + 8, "unexpected hostname\n" );
542     ok( uc.dwHostNameLength == 14, "unexpected hostname length\n" );
543     ok( uc.nPort == 443, "unexpected port: %u\n", uc.nPort );
544     ok( uc.lpszUrlPath == url_k3 + 22, "unexpected path\n" );
545     ok( uc.dwUrlPathLength == 5, "unexpected path length\n" );
546     ok( uc.lpszExtraInfo == url_k3 + 27, "unexpected extra info\n" );
547     ok( uc.dwExtraInfoLength == 1, "unexpected extra info length\n" );
548 
549     /* bad parameters */
550     reset_url_components( &uc );
551     SetLastError( 0xdeadbeef );
552     ret = WinHttpCrackUrl( url_k4, 0, 0, &uc );
553     ok( !ret, "WinHttpCrackUrl succeeded\n" );
554     error = GetLastError();
555     ok( error == ERROR_WINHTTP_INVALID_URL, "got %u\n", error );
556 
557     reset_url_components( &uc );
558     SetLastError( 0xdeadbeef );
559     ret = WinHttpCrackUrl( url_k5, 0, 0, &uc );
560     ok( !ret, "WinHttpCrackUrl succeeded\n" );
561     error = GetLastError();
562     ok( error == ERROR_WINHTTP_INVALID_URL, "got %u\n", error );
563 
564     reset_url_components( &uc );
565     SetLastError( 0xdeadbeef );
566     ret = WinHttpCrackUrl( url_k6, 0, 0, &uc );
567     ok( !ret, "WinHttpCrackUrl succeeded\n" );
568     error = GetLastError();
569     ok( error == ERROR_WINHTTP_UNRECOGNIZED_SCHEME, "got %u\n", error );
570 
571     reset_url_components( &uc );
572     SetLastError( 0xdeadbeef );
573     ret = WinHttpCrackUrl( url_k7, 0, 0, &uc );
574     ok( !ret, "WinHttpCrackUrl succeeded\n" );
575     error = GetLastError();
576     ok( error == ERROR_WINHTTP_UNRECOGNIZED_SCHEME, "got %u\n", error );
577 
578     reset_url_components( &uc );
579     SetLastError( 0xdeadbeef );
580     ret = WinHttpCrackUrl( url_k8, 0, 0, &uc );
581     error = GetLastError();
582     ok( !ret, "WinHttpCrackUrl succeeded\n" );
583     ok( error == ERROR_WINHTTP_UNRECOGNIZED_SCHEME, "got %u\n", error );
584 
585     reset_url_components( &uc );
586     ret = WinHttpCrackUrl( url_k9, 0, 0, &uc );
587     ok( ret, "WinHttpCrackUrl failed le=%u\n", GetLastError() );
588     ok( uc.lpszUrlPath == url_k9 + 14 || broken(uc.lpszUrlPath == url_k9 + 13) /* win8 */,
589         "unexpected path: %s\n", wine_dbgstr_w(uc.lpszUrlPath) );
590     ok( uc.dwUrlPathLength == 0, "unexpected path length: %u\n", uc.dwUrlPathLength );
591     ok( uc.lpszExtraInfo == url_k9 + 14 || broken(uc.lpszExtraInfo == url_k9 + 13) /* win8 */,
592         "unexpected extra info: %s\n", wine_dbgstr_w(uc.lpszExtraInfo) );
593     ok( uc.dwExtraInfoLength == 0 || broken(uc.dwExtraInfoLength == 1) /* win8 */,
594         "unexpected extra info length: %u\n", uc.dwExtraInfoLength );
595 
596     reset_url_components( &uc );
597     ret = WinHttpCrackUrl( url_k10, 0, 0, &uc );
598     ok( ret, "WinHttpCrackUrl failed le=%u\n", GetLastError() );
599     ok( uc.lpszUrlPath == url_k10 + 13, "unexpected path: %s\n", wine_dbgstr_w(uc.lpszUrlPath) );
600     ok( uc.dwUrlPathLength == 7, "unexpected path length: %u\n", uc.dwUrlPathLength );
601     ok( uc.lpszExtraInfo == url_k10 + 20, "unexpected extra info: %s\n", wine_dbgstr_w(uc.lpszExtraInfo) );
602     ok( uc.dwExtraInfoLength == 0, "unexpected extra info length: %u\n", uc.dwExtraInfoLength );
603 
604     reset_url_components( &uc );
605     SetLastError( 0xdeadbeef );
606     ret = WinHttpCrackUrl( url4, 0, 0, &uc );
607     error = GetLastError();
608     ok( !ret, "WinHttpCrackUrl succeeded\n" );
609     ok( error == ERROR_WINHTTP_INVALID_URL, "got %u\n", error );
610 
611     reset_url_components( &uc );
612     SetLastError( 0xdeadbeef );
613     ret = WinHttpCrackUrl( empty, 0, 0, &uc );
614     error = GetLastError();
615     ok( !ret, "WinHttpCrackUrl succeeded\n" );
616     ok( error == ERROR_WINHTTP_UNRECOGNIZED_SCHEME, "got %u\n", error );
617 
618     SetLastError( 0xdeadbeef );
619     ret = WinHttpCrackUrl( url1, 0, 0, NULL );
620     error = GetLastError();
621     ok( !ret, "WinHttpCrackUrl succeeded\n" );
622     ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
623 
624     SetLastError( 0xdeadbeef );
625     ret = WinHttpCrackUrl( NULL, 0, 0, &uc );
626     error = GetLastError();
627     ok( !ret, "WinHttpCrackUrl succeeded\n" );
628     ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
629 
630     /* decoding without buffers */
631     reset_url_components( &uc );
632     SetLastError(0xdeadbeef);
633     ret = WinHttpCrackUrl( url7, 0, ICU_DECODE, &uc );
634     error = GetLastError();
635     ok( !ret, "WinHttpCrackUrl succeeded\n" );
636     ok( error == ERROR_INVALID_PARAMETER, "got %u, expected ERROR_INVALID_PARAMETER\n", error );
637 
638     /* decoding with buffers */
639     uc.lpszScheme = scheme;
640     uc.dwSchemeLength = 20;
641     uc.lpszUserName = user;
642     uc.dwUserNameLength = 20;
643     uc.lpszPassword = pass;
644     uc.dwPasswordLength = 20;
645     uc.lpszHostName = host;
646     uc.dwHostNameLength = 20;
647     uc.nPort = 0;
648     uc.lpszUrlPath = path;
649     uc.dwUrlPathLength = 80;
650     uc.lpszExtraInfo = extra;
651     uc.dwExtraInfoLength = 40;
652     path[0] = 0;
653 
654     ret = WinHttpCrackUrl( url7, 0, ICU_DECODE, &uc );
655     ok( ret, "WinHttpCrackUrl failed %u\n", GetLastError() );
656     ok( !memcmp( uc.lpszUrlPath + 11, escape, 21 * sizeof(WCHAR) ), "unexpected path\n" );
657     ok( uc.dwUrlPathLength == 32, "unexpected path length %u\n", uc.dwUrlPathLength );
658     ok( !memcmp( uc.lpszExtraInfo, escape + 21, 12 * sizeof(WCHAR) ), "unexpected extra info\n" );
659     ok( uc.dwExtraInfoLength == 12, "unexpected extra info length %u\n", uc.dwExtraInfoLength );
660 
661     /* Urls with specified port numbers */
662     /* decoding with buffers */
663     uc.lpszScheme = scheme;
664     uc.dwSchemeLength = 20;
665     uc.lpszUserName = user;
666     uc.dwUserNameLength = 20;
667     uc.lpszPassword = pass;
668     uc.dwPasswordLength = 20;
669     uc.lpszHostName = host;
670     uc.dwHostNameLength = 20;
671     uc.nPort = 0;
672     uc.lpszUrlPath = path;
673     uc.dwUrlPathLength = 40;
674     uc.lpszExtraInfo = extra;
675     uc.dwExtraInfoLength = 20;
676     path[0] = 0;
677 
678     ret = WinHttpCrackUrl( url6, 0, 0, &uc );
679     ok( ret, "WinHttpCrackUrl failed le=%u\n", GetLastError() );
680     ok( !memcmp( uc.lpszHostName, winehq, sizeof(winehq) ), "unexpected host name: %s\n", wine_dbgstr_w(uc.lpszHostName) );
681     ok( uc.dwHostNameLength == 14, "unexpected host name length: %d\n", uc.dwHostNameLength );
682     ok( uc.nPort == 42, "unexpected port: %u\n", uc.nPort );
683 
684     /* decoding without buffers */
685     reset_url_components( &uc );
686     ret = WinHttpCrackUrl( url8, 0, 0, &uc );
687     ok( ret, "WinHttpCrackUrl failed le=%u\n", GetLastError() );
688     ok( uc.nPort == 0, "unexpected port: %u\n", uc.nPort );
689 
690     reset_url_components( &uc );
691     ret = WinHttpCrackUrl( url9, 0, 0, &uc );
692     ok( ret, "WinHttpCrackUrl failed le=%u\n", GetLastError() );
693     ok( uc.nPort == 80, "unexpected port: %u\n", uc.nPort );
694 
695     reset_url_components( &uc );
696     ret = WinHttpCrackUrl( url10, 0, 0, &uc );
697     ok( ret, "WinHttpCrackUrl failed le=%u\n", GetLastError() );
698     ok( uc.nPort == 443, "unexpected port: %u\n", uc.nPort );
699 
700     reset_url_components( &uc );
701     SetLastError( 0xdeadbeef );
702     ret = WinHttpCrackUrl( empty, 0, 0, &uc );
703     error = GetLastError();
704     ok( !ret, "WinHttpCrackUrl succeeded\n" );
705     ok( error == ERROR_WINHTTP_UNRECOGNIZED_SCHEME, "got %u, expected ERROR_WINHTTP_UNRECOGNIZED_SCHEME\n", error );
706 
707     reset_url_components( &uc );
708     SetLastError( 0xdeadbeef );
709     ret = WinHttpCrackUrl( http, 0, 0, &uc );
710     error = GetLastError();
711     ok( !ret, "WinHttpCrackUrl succeeded\n" );
712     ok( error == ERROR_WINHTTP_UNRECOGNIZED_SCHEME, "got %u, expected ERROR_WINHTTP_UNRECOGNIZED_SCHEME\n", error );
713 
714     reset_url_components( &uc );
715     ret = WinHttpCrackUrl( url11, 0, 0, &uc);
716     ok( ret, "WinHttpCrackUrl failed le=%u\n", GetLastError() );
717     ok( uc.nScheme == INTERNET_SCHEME_HTTP, "unexpected scheme\n" );
718     ok( uc.lpszScheme == url11,"unexpected scheme\n" );
719     ok( uc.dwSchemeLength == 4, "unexpected scheme length\n" );
720     ok( uc.lpszUserName == NULL, "unexpected username\n" );
721     ok( uc.lpszPassword == NULL, "unexpected password\n" );
722     ok( uc.lpszHostName == url11 + 7, "unexpected hostname\n" );
723     ok( uc.dwHostNameLength == 11, "unexpected hostname length\n" );
724     ok( uc.nPort == 80, "unexpected port: %u\n", uc.nPort );
725     ok( uc.lpszUrlPath == url11 + 18, "unexpected path\n" );
726     ok( uc.dwUrlPathLength == 5, "unexpected path length\n" );
727     ok( uc.lpszExtraInfo == url11 + 23, "unexpected extra info\n" );
728     ok( uc.dwExtraInfoLength == 39, "unexpected extra info length\n" );
729 
730     uc.lpszScheme = scheme;
731     uc.dwSchemeLength = 20;
732     uc.lpszHostName = host;
733     uc.dwHostNameLength = 20;
734     uc.lpszUserName = NULL;
735     uc.dwUserNameLength = 0;
736     uc.lpszPassword = NULL;
737     uc.dwPasswordLength = 0;
738     uc.lpszUrlPath = path;
739     uc.dwUrlPathLength = 40;
740     uc.lpszExtraInfo = NULL;
741     uc.dwExtraInfoLength = 0;
742     uc.nPort = 0;
743     ret = WinHttpCrackUrl( url12, 0, ICU_DECODE, &uc );
744     ok( ret, "WinHttpCrackUrl failed le=%u\n", GetLastError() );
745 
746     uc.lpszScheme = scheme;
747     uc.dwSchemeLength = 20;
748     uc.lpszHostName = host;
749     uc.dwHostNameLength = 20;
750     uc.lpszUserName = NULL;
751     uc.dwUserNameLength = 0;
752     uc.lpszPassword = NULL;
753     uc.dwPasswordLength = 0;
754     uc.lpszUrlPath = path;
755     uc.dwUrlPathLength = 40;
756     uc.lpszExtraInfo = NULL;
757     uc.dwExtraInfoLength = 0;
758     uc.nPort = 0;
759     ret = WinHttpCrackUrl( url13, 0, ICU_ESCAPE|ICU_DECODE, &uc );
760     ok( ret, "WinHttpCrackUrl failed le=%u\n", GetLastError() );
761     ok( !lstrcmpW( uc.lpszHostName, hostnameW ), "unexpected host name\n" );
762     ok( !lstrcmpW( uc.lpszUrlPath, pathW ), "unexpected path\n" );
763     ok( uc.dwUrlPathLength == lstrlenW(pathW), "got %u\n", uc.dwUrlPathLength );
764 
765     uc.dwStructSize = sizeof(uc);
766     uc.lpszScheme = NULL;
767     uc.dwSchemeLength = 0;
768     uc.nScheme = 0;
769     uc.lpszHostName = NULL;
770     uc.dwHostNameLength = ~0u;
771     uc.nPort = 0;
772     uc.lpszUserName = NULL;
773     uc.dwUserNameLength = ~0u;
774     uc.lpszPassword = NULL;
775     uc.dwPasswordLength = ~0u;
776     uc.lpszUrlPath = NULL;
777     uc.dwUrlPathLength = ~0u;
778     uc.lpszExtraInfo = NULL;
779     uc.dwExtraInfoLength = ~0u;
780     ret = WinHttpCrackUrl( url14, 0, 0, &uc );
781     ok( ret, "WinHttpCrackUrl failed le=%u\n", GetLastError() );
782     ok( !uc.lpszScheme, "unexpected scheme %s\n", wine_dbgstr_w(uc.lpszScheme) );
783     ok( !uc.dwSchemeLength, "unexpected length %u\n", uc.dwSchemeLength );
784     ok( uc.nScheme == INTERNET_SCHEME_HTTP, "unexpected scheme %u\n", uc.nScheme );
785     ok( !lstrcmpW( uc.lpszHostName, url14 + 7 ), "unexpected hostname %s\n", wine_dbgstr_w(uc.lpszHostName) );
786     ok( uc.dwHostNameLength == 14, "unexpected length %u\n", uc.dwHostNameLength );
787     ok( uc.nPort == 80, "unexpected port %u\n", uc.nPort );
788     ok( !uc.lpszUserName, "unexpected username\n" );
789     ok( !uc.dwUserNameLength, "unexpected length %u\n", uc.dwUserNameLength );
790     ok( !uc.lpszPassword, "unexpected password\n" );
791     ok( !uc.dwPasswordLength, "unexpected length %u\n", uc.dwPasswordLength );
792     ok( !lstrcmpW( uc.lpszUrlPath, url14 + 21 ), "unexpected path %s\n", wine_dbgstr_w(uc.lpszUrlPath) );
793     ok( uc.dwUrlPathLength == 5, "unexpected length %u\n", uc.dwUrlPathLength );
794     ok( !uc.lpszExtraInfo[0], "unexpected extra info %s\n", wine_dbgstr_w(uc.lpszExtraInfo) );
795     ok( uc.dwExtraInfoLength == 0, "unexpected length %u\n", uc.dwExtraInfoLength );
796 
797     uc.dwStructSize = sizeof(uc);
798     uc.lpszScheme = scheme;
799     uc.dwSchemeLength = 0;
800     uc.nScheme = 0;
801     uc.lpszHostName = NULL;
802     uc.dwHostNameLength = 0;
803     uc.nPort = 0;
804     uc.lpszUserName = NULL;
805     uc.dwUserNameLength = ~0u;
806     uc.lpszPassword = NULL;
807     uc.dwPasswordLength = ~0u;
808     uc.lpszUrlPath = NULL;
809     uc.dwUrlPathLength = 0;
810     uc.lpszExtraInfo = NULL;
811     uc.dwExtraInfoLength = 0;
812     SetLastError( 0xdeadbeef );
813     ret = WinHttpCrackUrl( url14, 0, 0, &uc );
814     error = GetLastError();
815     ok( !ret, "WinHttpCrackUrl succeeded\n" );
816     ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
817     ok( !lstrcmpW( uc.lpszScheme, http ), "unexpected scheme %s\n", wine_dbgstr_w(uc.lpszScheme) );
818     ok( !uc.dwSchemeLength, "unexpected length %u\n", uc.dwSchemeLength );
819     ok( uc.nScheme == 0, "unexpected scheme %u\n", uc.nScheme );
820     ok( !uc.lpszHostName, "unexpected hostname %s\n", wine_dbgstr_w(uc.lpszHostName) );
821     ok( uc.dwHostNameLength == 0, "unexpected length %u\n", uc.dwHostNameLength );
822     ok( uc.nPort == 0, "unexpected port %u\n", uc.nPort );
823     ok( !uc.lpszUserName, "unexpected username\n" );
824     ok( uc.dwUserNameLength == ~0u, "unexpected length %u\n", uc.dwUserNameLength );
825     ok( !uc.lpszPassword, "unexpected password\n" );
826     ok( uc.dwPasswordLength == ~0u, "unexpected length %u\n", uc.dwPasswordLength );
827     ok( !uc.lpszUrlPath, "unexpected path %s\n", wine_dbgstr_w(uc.lpszUrlPath) );
828     ok( uc.dwUrlPathLength == 0, "unexpected length %u\n", uc.dwUrlPathLength );
829     ok( !uc.lpszExtraInfo, "unexpected extra info %s\n", wine_dbgstr_w(uc.lpszExtraInfo) );
830     ok( uc.dwExtraInfoLength == 0, "unexpected length %u\n", uc.dwExtraInfoLength );
831 
832     reset_url_components( &uc );
833     SetLastError( 0xdeadbeef );
834     ret = WinHttpCrackUrl( url15, 0, 0, &uc );
835     error = GetLastError();
836     ok( !ret, "WinHttpCrackUrl succeeded\n" );
837     ok( error == ERROR_WINHTTP_INVALID_URL, "got %u\n", error );
838 
839     reset_url_components( &uc );
840     uc.nPort = 1;
841     ret = WinHttpCrackUrl( url16, 0, 0, &uc );
842     ok( ret, "got %u\n", GetLastError() );
843     ok( !uc.nPort, "got %u\n", uc.nPort );
844 
845     reset_url_components( &uc );
846     uc.nPort = 1;
847     ret = WinHttpCrackUrl( url17, 0, 0, &uc );
848     ok( ret, "got %u\n", GetLastError() );
849     todo_wine ok( uc.nPort == 80, "got %u\n", uc.nPort );
850 
851     memset( &uc, 0, sizeof(uc) );
852     uc.dwStructSize      = sizeof(uc);
853     uc.lpszScheme        = scheme;
854     uc.dwSchemeLength    = ARRAY_SIZE(scheme);
855     uc.lpszHostName      = host;
856     uc.dwHostNameLength  = ARRAY_SIZE(host);
857     uc.lpszUrlPath       = path;
858     uc.dwUrlPathLength   = ARRAY_SIZE(path);
859     ret = WinHttpCrackUrl( url21, 0, 0, &uc );
860     ok( ret, "got %u\n", GetLastError() );
861     ok( !lstrcmpW( uc.lpszUrlPath, url21 + 37 ), "unexpected path %s\n", wine_dbgstr_w(uc.lpszUrlPath) );
862     ok( uc.dwUrlPathLength == 50, "unexpected length %u\n", uc.dwUrlPathLength );
863 }
864 
865 START_TEST(url)
866 {
867     WinHttpCreateUrl_test();
868     WinHttpCrackUrl_test();
869 }
870