url.c 46.8 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
/*
 * Wininet - URL tests
 *
 * Copyright 2002 Aric Stewart
 * Copyright 2004 Mike McCormack
 * Copyright 2005 Hans Leidekker
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * 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 24 25
 */

#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
26
#include <string.h>
27 28 29

#include "windef.h"
#include "winbase.h"
30
#include "winnls.h"
31 32 33 34
#include "wininet.h"

#include "wine/test.h"

35
#define TEST_URL "http://www.winehq.org/site/about#hi"
36 37 38 39 40 41 42 43 44 45 46 47 48 49
#define TEST_URL3 "file:///C:/Program%20Files/Atmel/AVR%20Tools/STK500/STK500.xml"

#define CREATE_URL1 "http://username:password@www.winehq.org/site/about"
#define CREATE_URL2 "http://username@www.winehq.org/site/about"
#define CREATE_URL3 "http://username:"
#define CREATE_URL4 "http://www.winehq.org/site/about"
#define CREATE_URL5 "http://"
#define CREATE_URL6 "nhttp://username:password@www.winehq.org:80/site/about"
#define CREATE_URL7 "http://username:password@www.winehq.org:42/site/about"
#define CREATE_URL8 "https://username:password@www.winehq.org/site/about"
#define CREATE_URL9 "about:blank"
#define CREATE_URL10 "about://host/blank"
#define CREATE_URL11 "about:"
#define CREATE_URL12 "http://www.winehq.org:65535"
50
#define CREATE_URL13 "http://localhost/?test=123"
51

52
static void copy_compsA(
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
    URL_COMPONENTSA *src, 
    URL_COMPONENTSA *dst, 
    DWORD scheLen,
    DWORD hostLen,
    DWORD userLen,
    DWORD passLen,
    DWORD pathLen,
    DWORD extrLen )
{
    *dst = *src;
    dst->dwSchemeLength    = scheLen;
    dst->dwHostNameLength  = hostLen;
    dst->dwUserNameLength  = userLen;
    dst->dwPasswordLength  = passLen;
    dst->dwUrlPathLength   = pathLen;
    dst->dwExtraInfoLength = extrLen;
    SetLastError(0xfaceabad);
}

72
static void zero_compsA(
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
    URL_COMPONENTSA *dst, 
    DWORD scheLen,
    DWORD hostLen,
    DWORD userLen,
    DWORD passLen,
    DWORD pathLen,
    DWORD extrLen )
{
    ZeroMemory(dst, sizeof(URL_COMPONENTSA));
    dst->dwStructSize = sizeof(URL_COMPONENTSA);
    dst->dwSchemeLength    = scheLen;
    dst->dwHostNameLength  = hostLen;
    dst->dwUserNameLength  = userLen;
    dst->dwPasswordLength  = passLen;
    dst->dwUrlPathLength   = pathLen;
    dst->dwExtraInfoLength = extrLen;
    SetLastError(0xfaceabad);
}

92 93 94 95 96 97 98
typedef struct {
    const char *url;
    int scheme_off;
    int scheme_len;
    INTERNET_SCHEME scheme;
    int host_off;
    int host_len;
99
    int host_skip_broken;
100 101 102 103 104 105 106 107 108
    INTERNET_PORT port;
    int user_off;
    int user_len;
    int pass_off;
    int pass_len;
    int path_off;
    int path_len;
    int extra_off;
    int extra_len;
109 110 111 112 113 114
    const char *exp_scheme;
    const char *exp_hostname;
    const char *exp_username;
    const char *exp_password;
    const char *exp_urlpath;
    const char *exp_extrainfo;
115 116 117 118
} crack_url_test_t;

static const crack_url_test_t crack_url_tests[] = {
    {"http://www.winehq.org/site/about#hi",
119 120
        0, 4, INTERNET_SCHEME_HTTP, 7, 14, -1, 80, -1, 0, -1, 0, 21, 11, 32, 3,
        "http", "www.winehq.org", "", "", "/site/about", "#hi"},
121
    {"http://www.myserver.com/myscript.php?arg=1",
122 123
        0, 4, INTERNET_SCHEME_HTTP, 7, 16, -1, 80, -1, 0, -1, 0, 23, 13, 36, 6,
        "http", "www.myserver.com", "", "", "/myscript.php", "?arg=1"},
124
    {"http://www.winehq.org?test=123",
125 126
        0, 4, INTERNET_SCHEME_HTTP, 7, 14, 23, 80, -1, 0, -1, 0, 21, 0, 21, 9,
        "http", "www.winehq.org", "", "", "", "?test=123"},
127
    {"file:///C:/Program%20Files/Atmel/AVR%20Tools/STK500/STK500.xml",
128 129
        0, 4, INTERNET_SCHEME_FILE, -1, 0, -1, 0, -1, 0, -1, 0, 7, 55, -1, 0,
        "file", "", "", "", "C:\\Program Files\\Atmel\\AVR Tools\\STK500\\STK500.xml", ""},
130
    {"fide:///C:/Program%20Files/Atmel/AVR%20Tools/STK500/STK500.xml",
131 132
        0, 4, INTERNET_SCHEME_UNKNOWN, 7, 0, -1, 0, -1, 0, -1, 0, 7, 55, -1, 0,
        "fide", "", "", "", "/C:/Program%20Files/Atmel/AVR%20Tools/STK500/STK500.xml", ""},
133
    {"file://C:/Program%20Files/Atmel/AVR%20Tools/STK500/STK500.xml",
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
        0, 4, INTERNET_SCHEME_FILE, -1, 0, -1, 0, -1, 0, -1, 0, 7, 54, -1, 0,
        "file", "", "", "", "C:\\Program%20Files\\Atmel\\AVR%20Tools\\STK500\\STK500.xml", ""},
    {"file://C:/Program%20Files/Atmel/..",
        0, 4, INTERNET_SCHEME_FILE, -1, 0, -1, 0, -1, 0, -1, 0, 7, 27, -1, 0,
        "file", "", "", "", "C:\\Program%20Files\\Atmel\\..\\", ""},
    {"file://C:/Program%20Files/Atmel/../Asdf.xml",
        0, 4, INTERNET_SCHEME_FILE, -1, 0, -1, 0, -1, 0, -1, 0, 7, 36, -1, 0,
        "file", "", "", "", "C:\\Program%20Files\\Atmel\\..\\Asdf.xml", ""},
    {"file:///C:/Program%20Files/Atmel/..",
        0, 4, INTERNET_SCHEME_FILE, -1, 0, -1, 0, -1, 0, -1, 0, 7, 28, -1, 0,
        "file", "", "", "", "C:\\Program Files\\Atmel\\..\\", ""},
    {"file:///C:/Program%20Files/Atmel/../Asdf.xml",
        0, 4, INTERNET_SCHEME_FILE, -1, 0, -1, 0, -1, 0, -1, 0, 7, 37, -1, 0,
        "file", "", "", "", "C:\\Program Files\\Atmel\\..\\Asdf.xml", ""},
    {"file://C:/Program%20Files/Atmel/.",
        0, 4, INTERNET_SCHEME_FILE, -1, 0, -1, 0, -1, 0, -1, 0, 7, 26, -1, 0,
        "file", "", "", "", "C:\\Program%20Files\\Atmel\\.\\", ""},
    {"file://C:/Program%20Files/Atmel/./Asdf.xml",
        0, 4, INTERNET_SCHEME_FILE, -1, 0, -1, 0, -1, 0, -1, 0, 7, 35, -1, 0,
        "file", "", "", "", "C:\\Program%20Files\\Atmel\\.\\Asdf.xml", ""},
    {"file:///C:/Program%20Files/Atmel/.",
        0, 4, INTERNET_SCHEME_FILE, -1, 0, -1, 0, -1, 0, -1, 0, 7, 27, -1, 0,
        "file", "", "", "", "C:\\Program Files\\Atmel\\.\\", ""},
    {"file:///C:/Program%20Files/Atmel/./Asdf.xml",
        0, 4, INTERNET_SCHEME_FILE, -1, 0, -1, 0, -1, 0, -1, 0, 7, 36, -1, 0,
        "file", "", "", "", "C:\\Program Files\\Atmel\\.\\Asdf.xml", ""},
160 161
};

162 163 164 165 166 167 168
static const WCHAR *w_str_of(const char *str)
{
    static WCHAR buf[512];
    MultiByteToWideChar(CP_ACP, 0, str, -1, buf, sizeof(buf)/sizeof(buf[0]));
    return buf;
}

169 170
static void test_crack_url(const crack_url_test_t *test)
{
171 172
    WCHAR buf[INTERNET_MAX_URL_LENGTH];
    URL_COMPONENTSW urlw;
173
    URL_COMPONENTSA url;
174 175
    char scheme[32], hostname[1024], username[1024];
    char password[1024], extrainfo[1024], urlpath[1024];
176 177
    BOOL b;

178
    /* test InternetCrackUrlA with NULL buffers */
179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198
    zero_compsA(&url, 1, 1, 1, 1, 1, 1);

    b = InternetCrackUrlA(test->url, strlen(test->url), 0, &url);
    ok(b, "InternetCrackUrl failed with error %d\n", GetLastError());

    if(test->scheme_off == -1)
        ok(!url.lpszScheme, "[%s] url.lpszScheme = %p, expected NULL\n", test->url, url.lpszScheme);
    else
        ok(url.lpszScheme == test->url+test->scheme_off, "[%s] url.lpszScheme = %p, expected %p\n",
           test->url, url.lpszScheme, test->url+test->scheme_off);
    ok(url.dwSchemeLength == test->scheme_len, "[%s] url.lpszSchemeLength = %d, expected %d\n",
       test->url, url.dwSchemeLength, test->scheme_len);

    ok(url.nScheme == test->scheme, "[%s] url.nScheme = %d, expected %d\n", test->url, url.nScheme, test->scheme);

    if(test->host_off == -1)
        ok(!url.lpszHostName, "[%s] url.lpszHostName = %p, expected NULL\n", test->url, url.lpszHostName);
    else
        ok(url.lpszHostName == test->url+test->host_off, "[%s] url.lpszHostName = %p, expected %p\n",
           test->url, url.lpszHostName, test->url+test->host_off);
199 200 201 202
    if(test->host_skip_broken != -1 && url.dwHostNameLength == test->host_skip_broken) {
        win_skip("skipping broken dwHostNameLength result\n");
        return;
    }
203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238
    ok(url.dwHostNameLength == test->host_len, "[%s] url.lpszHostNameLength = %d, expected %d\n",
       test->url, url.dwHostNameLength, test->host_len);

    ok(url.nPort == test->port, "[%s] nPort = %d, expected %d\n", test->url, url.nPort, test->port);

    if(test->user_off == -1)
        ok(!url.lpszUserName, "[%s] url.lpszUserName = %p\n", test->url, url.lpszUserName);
    else
        ok(url.lpszUserName == test->url+test->user_off, "[%s] url.lpszUserName = %p, expected %p\n",
           test->url, url.lpszUserName, test->url+test->user_off);
    ok(url.dwUserNameLength == test->user_len, "[%s] url.lpszUserNameLength = %d, expected %d\n",
       test->url, url.dwUserNameLength, test->user_len);

    if(test->pass_off == -1)
        ok(!url.lpszPassword, "[%s] url.lpszPassword = %p\n", test->url, url.lpszPassword);
    else
        ok(url.lpszPassword == test->url+test->pass_off, "[%s] url.lpszPassword = %p, expected %p\n",
           test->url, url.lpszPassword, test->url+test->pass_off);
    ok(url.dwPasswordLength == test->pass_len, "[%s] url.lpszPasswordLength = %d, expected %d\n",
       test->url, url.dwPasswordLength, test->pass_len);

    if(test->path_off == -1)
        ok(!url.lpszUrlPath, "[%s] url.lpszPath = %p, expected NULL\n", test->url, url.lpszUrlPath);
    else
        ok(url.lpszUrlPath == test->url+test->path_off, "[%s] url.lpszPath = %p, expected %p\n",
           test->url, url.lpszUrlPath, test->url+test->path_off);
    ok(url.dwUrlPathLength == test->path_len, "[%s] url.lpszUrlPathLength = %d, expected %d\n",
       test->url, url.dwUrlPathLength, test->path_len);

    if(test->extra_off == -1)
        ok(!url.lpszExtraInfo, "[%s] url.lpszExtraInfo = %p, expected NULL\n", test->url, url.lpszExtraInfo);
    else
        ok(url.lpszExtraInfo == test->url+test->extra_off, "[%s] url.lpszExtraInfo = %p, expected %p\n",
           test->url, url.lpszExtraInfo, test->url+test->extra_off);
    ok(url.dwExtraInfoLength == test->extra_len, "[%s] url.lpszExtraInfoLength = %d, expected %d\n",
       test->url, url.dwExtraInfoLength, test->extra_len);
239

240
    /* test InternetCrackUrlW with NULL buffers */
241 242 243 244 245 246 247 248 249
    memset(&urlw, 0, sizeof(URL_COMPONENTSW));
    urlw.dwStructSize = sizeof(URL_COMPONENTSW);
    urlw.dwSchemeLength = 1;
    urlw.dwHostNameLength = 1;
    urlw.dwUserNameLength = 1;
    urlw.dwPasswordLength = 1;
    urlw.dwUrlPathLength = 1;
    urlw.dwExtraInfoLength = 1;

250
    MultiByteToWideChar(CP_ACP, 0, test->url, -1, buf, sizeof(buf)/sizeof(buf[0]));
251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267
    b = InternetCrackUrlW(buf, lstrlenW(buf), 0, &urlw);
    if(!b && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) {
        win_skip("InternetCrackUrlW is not implemented\n");
        return;
    }
    ok(b, "InternetCrackUrl failed with error %d\n", GetLastError());

    if(test->scheme_off == -1)
        ok(!urlw.lpszScheme, "[%s] urlw.lpszScheme = %p, expected NULL\n", test->url, urlw.lpszScheme);
    else
        ok(urlw.lpszScheme == buf+test->scheme_off, "[%s] urlw.lpszScheme = %p, expected %p\n",
           test->url, urlw.lpszScheme, buf+test->scheme_off);
    ok(urlw.dwSchemeLength == test->scheme_len, "[%s] urlw.lpszSchemeLength = %d, expected %d\n",
       test->url, urlw.dwSchemeLength, test->scheme_len);

    ok(urlw.nScheme == test->scheme, "[%s] urlw.nScheme = %d, expected %d\n", test->url, urlw.nScheme, test->scheme);

268
    if(test->host_off == -1) {
269
        ok(!urlw.lpszHostName, "[%s] urlw.lpszHostName = %p, expected NULL\n", test->url, urlw.lpszHostName);
270 271 272
        ok(urlw.dwHostNameLength == 0 || broken(urlw.dwHostNameLength == 1), "[%s] urlw.lpszHostNameLength = %d, expected %d\n",
           test->url, urlw.dwHostNameLength, test->host_len);
    }else {
273 274
        ok(urlw.lpszHostName == buf+test->host_off, "[%s] urlw.lpszHostName = %p, expected %p\n",
           test->url, urlw.lpszHostName, test->url+test->host_off);
275 276
        ok(urlw.dwHostNameLength == test->host_len, "[%s] urlw.lpszHostNameLength = %d, expected %d\n",
           test->url, urlw.dwHostNameLength, test->host_len);
277 278 279 280
    }

    ok(urlw.nPort == test->port, "[%s] nPort = %d, expected %d\n", test->url, urlw.nPort, test->port);

281
    if(test->user_off == -1) {
282
        ok(!urlw.lpszUserName, "[%s] urlw.lpszUserName = %p\n", test->url, urlw.lpszUserName);
283 284 285
        ok(urlw.dwUserNameLength == 0 || broken(urlw.dwUserNameLength == 1), "[%s] urlw.lpszUserNameLength = %d, expected %d\n",
           test->url, urlw.dwUserNameLength, test->user_len);
    }else {
286 287
        ok(urlw.lpszUserName == buf+test->user_off, "[%s] urlw.lpszUserName = %p, expected %p\n",
           test->url, urlw.lpszUserName, buf+test->user_off);
288 289 290
        ok(urlw.dwUserNameLength == test->user_len, "[%s] urlw.lpszUserNameLength = %d, expected %d\n",
           test->url, urlw.dwUserNameLength, test->user_len);
    }
291

292
    if(test->pass_off == -1) {
293
        ok(!urlw.lpszPassword, "[%s] urlw.lpszPassword = %p\n", test->url, urlw.lpszPassword);
294 295 296
        ok(urlw.dwPasswordLength == 0 || broken(urlw.dwPasswordLength), "[%s] urlw.lpszPasswordLength = %d, expected %d\n",
           test->url, urlw.dwPasswordLength, test->pass_len);
    }else {
297 298
        ok(urlw.lpszPassword == buf+test->pass_off, "[%s] urlw.lpszPassword = %p, expected %p\n",
           test->url, urlw.lpszPassword, buf+test->pass_off);
299 300 301
        ok(urlw.dwPasswordLength == test->pass_len, "[%s] urlw.lpszPasswordLength = %d, expected %d\n",
           test->url, urlw.dwPasswordLength, test->pass_len);
    }
302 303 304 305 306 307 308 309 310

    if(test->path_off == -1)
        ok(!urlw.lpszUrlPath, "[%s] urlw.lpszPath = %p, expected NULL\n", test->url, urlw.lpszUrlPath);
    else
        ok(urlw.lpszUrlPath == buf+test->path_off, "[%s] urlw.lpszPath = %p, expected %p\n",
           test->url, urlw.lpszUrlPath, buf+test->path_off);
    ok(urlw.dwUrlPathLength == test->path_len, "[%s] urlw.lpszUrlPathLength = %d, expected %d\n",
       test->url, urlw.dwUrlPathLength, test->path_len);

311
    if(test->extra_off == -1) {
312
        ok(!urlw.lpszExtraInfo, "[%s] url.lpszExtraInfo = %p, expected NULL\n", test->url, urlw.lpszExtraInfo);
313 314 315
        ok(urlw.dwExtraInfoLength == 0 || broken(urlw.dwExtraInfoLength == 1), "[%s] urlw.lpszExtraInfoLength = %d, expected %d\n",
           test->url, urlw.dwExtraInfoLength, test->extra_len);
    }else {
316 317
        ok(urlw.lpszExtraInfo == buf+test->extra_off, "[%s] urlw.lpszExtraInfo = %p, expected %p\n",
           test->url, urlw.lpszExtraInfo, buf+test->extra_off);
318 319 320
        ok(urlw.dwExtraInfoLength == test->extra_len, "[%s] urlw.lpszExtraInfoLength = %d, expected %d\n",
           test->url, urlw.dwExtraInfoLength, test->extra_len);
    }
321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345

    /* test InternetCrackUrlA with valid buffers */
    memset(&url, 0, sizeof(URL_COMPONENTSA));
    url.dwStructSize = sizeof(URL_COMPONENTSA);
    url.lpszScheme = scheme;
    url.dwSchemeLength = sizeof(scheme);
    url.lpszHostName = hostname;
    url.dwHostNameLength = sizeof(hostname);
    url.lpszUserName = username;
    url.dwUserNameLength = sizeof(username);
    url.lpszPassword = password;
    url.dwPasswordLength = sizeof(password);
    url.lpszUrlPath = urlpath;
    url.dwUrlPathLength = sizeof(urlpath);
    url.lpszExtraInfo = extrainfo;
    url.dwExtraInfoLength = sizeof(extrainfo);

    b = InternetCrackUrlA(test->url, strlen(test->url), 0, &url);
    ok(b, "InternetCrackUrlA failed with error %d\n", GetLastError());

    ok(url.dwSchemeLength == strlen(test->exp_scheme), "[%s] Got wrong scheme length: %d\n",
            test->url, url.dwSchemeLength);
    ok(!strcmp(scheme, test->exp_scheme), "[%s] Got wrong scheme, expected: %s, got: %s\n",
            test->url, test->exp_scheme, scheme);

346
    ok(url.nScheme == test->scheme, "[%s] Got wrong nScheme, expected: %d, got: %d\n",
347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400
            test->url, test->scheme, url.nScheme);

    ok(url.dwHostNameLength == strlen(test->exp_hostname), "[%s] Got wrong hostname length: %d\n",
            test->url, url.dwHostNameLength);
    ok(!strcmp(hostname, test->exp_hostname), "[%s] Got wrong hostname, expected: %s, got: %s\n",
            test->url, test->exp_hostname, hostname);

    ok(url.nPort == test->port, "[%s] Got wrong port, expected: %d, got: %d\n",
            test->url, test->port, url.nPort);

    ok(url.dwUserNameLength == strlen(test->exp_username), "[%s] Got wrong username length: %d\n",
            test->url, url.dwUserNameLength);
    ok(!strcmp(username, test->exp_username), "[%s] Got wrong username, expected: %s, got: %s\n",
            test->url, test->exp_username, username);

    ok(url.dwPasswordLength == strlen(test->exp_password), "[%s] Got wrong password length: %d\n",
            test->url, url.dwPasswordLength);
    ok(!strcmp(password, test->exp_password), "[%s] Got wrong password, expected: %s, got: %s\n",
            test->url, test->exp_password, password);

    ok(url.dwUrlPathLength == strlen(test->exp_urlpath), "[%s] Got wrong urlpath length: %d\n",
            test->url, url.dwUrlPathLength);
    ok(!strcmp(urlpath, test->exp_urlpath), "[%s] Got wrong urlpath, expected: %s, got: %s\n",
            test->url, test->exp_urlpath, urlpath);

    ok(url.dwExtraInfoLength == strlen(test->exp_extrainfo), "[%s] Got wrong extrainfo length: %d\n",
            test->url, url.dwExtraInfoLength);
    ok(!strcmp(extrainfo, test->exp_extrainfo), "[%s] Got wrong extrainfo, expected: %s, got: %s\n",
            test->url, test->exp_extrainfo, extrainfo);

    /* test InternetCrackUrlW with valid buffers */
    memset(&urlw, 0, sizeof(URL_COMPONENTSW));
    urlw.dwStructSize = sizeof(URL_COMPONENTSW);
    urlw.lpszScheme = (WCHAR*)scheme;
    urlw.dwSchemeLength = sizeof(scheme) / sizeof(WCHAR);
    urlw.lpszHostName = (WCHAR*)hostname;
    urlw.dwHostNameLength = sizeof(hostname) / sizeof(WCHAR);
    urlw.lpszUserName = (WCHAR*)username;
    urlw.dwUserNameLength = sizeof(username) / sizeof(WCHAR);
    urlw.lpszPassword = (WCHAR*)password;
    urlw.dwPasswordLength = sizeof(password) / sizeof(WCHAR);
    urlw.lpszUrlPath = (WCHAR*)urlpath;
    urlw.dwUrlPathLength = sizeof(urlpath) / sizeof(WCHAR);
    urlw.lpszExtraInfo = (WCHAR*)extrainfo;
    urlw.dwExtraInfoLength = sizeof(extrainfo) / sizeof(WCHAR);

    b = InternetCrackUrlW(buf, lstrlenW(buf), 0, &urlw);
    ok(b, "InternetCrackUrlW failed with error %d\n", GetLastError());

    ok(urlw.dwSchemeLength == strlen(test->exp_scheme), "[%s] Got wrong scheme length: %d\n",
            test->url, urlw.dwSchemeLength);
    ok(!lstrcmpW((WCHAR*)scheme, w_str_of(test->exp_scheme)), "[%s] Got wrong scheme, expected: %s, got: %s\n",
            test->url, test->exp_scheme, wine_dbgstr_w((WCHAR*)scheme));

401
    ok(urlw.nScheme == test->scheme, "[%s] Got wrong nScheme, expected: %d, got: %d\n",
402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430
            test->url, test->scheme, urlw.nScheme);

    ok(urlw.dwHostNameLength == strlen(test->exp_hostname), "[%s] Got wrong hostname length: %d\n",
            test->url, urlw.dwHostNameLength);
    ok(!lstrcmpW((WCHAR*)hostname, w_str_of(test->exp_hostname)), "[%s] Got wrong hostname, expected: %s, got: %s\n",
            test->url, test->exp_hostname, wine_dbgstr_w((WCHAR*)hostname));

    ok(urlw.nPort == test->port, "[%s] Got wrong port, expected: %d, got: %d\n",
            test->url, test->port, urlw.nPort);

    ok(urlw.dwUserNameLength == strlen(test->exp_username), "[%s] Got wrong username length: %d\n",
            test->url, urlw.dwUserNameLength);
    ok(!lstrcmpW((WCHAR*)username, w_str_of(test->exp_username)), "[%s] Got wrong username, expected: %s, got: %s\n",
            test->url, test->exp_username, wine_dbgstr_w((WCHAR*)username));

    ok(urlw.dwPasswordLength == strlen(test->exp_password), "[%s] Got wrong password length: %d\n",
            test->url, urlw.dwPasswordLength);
    ok(!lstrcmpW((WCHAR*)password, w_str_of(test->exp_password)), "[%s] Got wrong password, expected: %s, got: %s\n",
            test->url, test->exp_password, wine_dbgstr_w((WCHAR*)password));

    ok(urlw.dwUrlPathLength == strlen(test->exp_urlpath), "[%s] Got wrong urlpath length: %d\n",
            test->url, urlw.dwUrlPathLength);
    ok(!lstrcmpW((WCHAR*)urlpath, w_str_of(test->exp_urlpath)), "[%s] Got wrong urlpath, expected: %s, got: %s\n",
            test->url, test->exp_urlpath, wine_dbgstr_w((WCHAR*)urlpath));

    ok(urlw.dwExtraInfoLength == strlen(test->exp_extrainfo), "[%s] Got wrong extrainfo length: %d\n",
            test->url, urlw.dwExtraInfoLength);
    ok(!lstrcmpW((WCHAR*)extrainfo, w_str_of(test->exp_extrainfo)), "[%s] Got wrong extrainfo, expected: %s, got: %s\n",
            test->url, test->exp_extrainfo, wine_dbgstr_w((WCHAR*)extrainfo));
431 432
}

433 434 435 436 437
static void InternetCrackUrl_test(void)
{
  URL_COMPONENTSA urlSrc, urlComponents;
  char protocol[32], hostName[1024], userName[1024];
  char password[1024], extra[1024], path[1024];
438 439
  BOOL ret, firstret;
  DWORD GLE, firstGLE;
440 441 442 443 444 445 446 447 448 449 450

  ZeroMemory(&urlSrc, sizeof(urlSrc));
  urlSrc.dwStructSize = sizeof(urlSrc);
  urlSrc.lpszScheme = protocol;
  urlSrc.lpszHostName = hostName;
  urlSrc.lpszUserName = userName;
  urlSrc.lpszPassword = password;
  urlSrc.lpszUrlPath = path;
  urlSrc.lpszExtraInfo = extra;

  /* Tests for lpsz* members pointing to real strings while 
451 452 453 454 455 456 457
   * some corresponding length members are set to zero.
   * As of IE7 (wininet 7.0*?) all members are checked. So we
   * run the first test and expect the outcome to be the same
   * for the first four (scheme, hostname, username and password).
   * The last two (path and extrainfo) are the same for all versions
   * of the wininet.dll.
   */
458
  copy_compsA(&urlSrc, &urlComponents, 0, 1024, 1024, 1024, 2048, 1024);
459 460 461
  SetLastError(0xdeadbeef);
  firstret = InternetCrackUrlA(TEST_URL3, 0, ICU_DECODE, &urlComponents);
  firstGLE = GetLastError();
462 463

  copy_compsA(&urlSrc, &urlComponents, 32, 0, 1024, 1024, 2048, 1024);
464
  SetLastError(0xdeadbeef);
465
  ret = InternetCrackUrlA(TEST_URL3, 0, ICU_DECODE, &urlComponents);
466 467 468
  GLE = GetLastError();
  ok(ret==firstret && (GLE==firstGLE), "InternetCrackUrl returned %d with GLE=%d (expected to return %d)\n",
    ret, GetLastError(), firstret);
469 470

  copy_compsA(&urlSrc, &urlComponents, 32, 1024, 0, 1024, 2048, 1024);
471
  SetLastError(0xdeadbeef);
472
  ret = InternetCrackUrlA(TEST_URL3, 0, ICU_DECODE, &urlComponents);
473 474 475
  GLE = GetLastError();
  ok(ret==firstret && (GLE==firstGLE), "InternetCrackUrl returned %d with GLE=%d (expected to return %d)\n",
    ret, GetLastError(), firstret);
476 477

  copy_compsA(&urlSrc, &urlComponents, 32, 1024, 1024, 0, 2048, 1024);
478
  SetLastError(0xdeadbeef);
479
  ret = InternetCrackUrlA(TEST_URL3, 0, ICU_DECODE, &urlComponents);
480 481 482
  GLE = GetLastError();
  ok(ret==firstret && (GLE==firstGLE), "InternetCrackUrl returned %d with GLE=%d (expected to return %d)\n",
    ret, GetLastError(), firstret);
483 484

  copy_compsA(&urlSrc, &urlComponents, 32, 1024, 1024, 1024, 0, 1024);
485
  SetLastError(0xdeadbeef);
486 487 488 489
  ret = InternetCrackUrlA(TEST_URL3, 0, ICU_DECODE, &urlComponents);
  GLE = GetLastError();
  todo_wine
  ok(ret==0 && (GLE==ERROR_INVALID_HANDLE || GLE==ERROR_INSUFFICIENT_BUFFER),
490
     "InternetCrackUrl returned %d with GLE=%d (expected to return 0 and ERROR_INVALID_HANDLE or ERROR_INSUFFICIENT_BUFFER)\n",
491 492 493
    ret, GLE);

  copy_compsA(&urlSrc, &urlComponents, 32, 1024, 1024, 1024, 2048, 0);
494
  SetLastError(0xdeadbeef);
495 496 497 498
  ret = InternetCrackUrlA(TEST_URL3, 0, ICU_DECODE, &urlComponents);
  GLE = GetLastError();
  todo_wine
  ok(ret==0 && (GLE==ERROR_INVALID_HANDLE || GLE==ERROR_INSUFFICIENT_BUFFER),
499
     "InternetCrackUrl returned %d with GLE=%d (expected to return 0 and ERROR_INVALID_HANDLE or ERROR_INSUFFICIENT_BUFFER)\n",
500 501 502 503 504 505 506
    ret, GLE);

  copy_compsA(&urlSrc, &urlComponents, 0, 0, 0, 0, 0, 0);
  ret = InternetCrackUrlA(TEST_URL3, 0, ICU_DECODE, &urlComponents);
  GLE = GetLastError();
  todo_wine
  ok(ret==0 && GLE==ERROR_INVALID_PARAMETER,
507
     "InternetCrackUrl returned %d with GLE=%d (expected to return 0 and ERROR_INVALID_PARAMETER)\n",
508 509 510 511
    ret, GLE);

  copy_compsA(&urlSrc, &urlComponents, 32, 1024, 1024, 1024, 2048, 1024);
  ret = InternetCrackUrl("about://host/blank", 0,0,&urlComponents);
512
  ok(ret, "InternetCrackUrl failed with %d\n", GetLastError());
513 514 515
  ok(!strcmp(urlComponents.lpszScheme, "about"), "lpszScheme was \"%s\" instead of \"about\"\n", urlComponents.lpszScheme);
  ok(!strcmp(urlComponents.lpszHostName, "host"), "lpszHostName was \"%s\" instead of \"host\"\n", urlComponents.lpszHostName);
  ok(!strcmp(urlComponents.lpszUrlPath, "/blank"), "lpszUrlPath was \"%s\" instead of \"/blank\"\n", urlComponents.lpszUrlPath);
516 517 518 519 520 521 522

  /* try a NULL lpszUrl */
  SetLastError(0xdeadbeef);
  copy_compsA(&urlSrc, &urlComponents, 32, 1024, 1024, 1024, 2048, 1024);
  ret = InternetCrackUrl(NULL, 0, 0, &urlComponents);
  GLE = GetLastError();
  ok(ret == FALSE, "Expected InternetCrackUrl to fail\n");
523
  ok(GLE == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GLE);
524 525 526 527 528 529 530 531 532 533

  /* try an empty lpszUrl, GetLastError returns 12006, whatever that means
   * we just need to fail and not return success
   */
  SetLastError(0xdeadbeef);
  copy_compsA(&urlSrc, &urlComponents, 32, 1024, 1024, 1024, 2048, 1024);
  ret = InternetCrackUrl("", 0, 0, &urlComponents);
  GLE = GetLastError();
  ok(ret == FALSE, "Expected InternetCrackUrl to fail\n");
  ok(GLE != 0xdeadbeef && GLE != ERROR_SUCCESS, "Expected GLE to represent a failure\n");
534 535

  /* Invalid Call: must set size of components structure (Windows only
Austin English's avatar
Austin English committed
536
   * enforces this on the InternetCrackUrlA version of the call) */
537 538 539 540 541 542 543 544
  copy_compsA(&urlSrc, &urlComponents, 0, 1024, 1024, 1024, 2048, 1024);
  SetLastError(0xdeadbeef);
  urlComponents.dwStructSize = 0;
  ret = InternetCrackUrlA(TEST_URL, 0, 0, &urlComponents);
  ok(ret == FALSE, "Expected InternetCrackUrl to fail\n");
  ok(GLE != 0xdeadbeef && GLE != ERROR_SUCCESS, "Expected GLE to represent a failure\n");

  /* Invalid Call: size of dwStructSize must be one of the "standard" sizes
Austin English's avatar
Austin English committed
545
   * of the URL_COMPONENTS structure (Windows only enforces this on the
546 547 548 549 550 551 552
   * InternetCrackUrlA version of the call) */
  copy_compsA(&urlSrc, &urlComponents, 0, 1024, 1024, 1024, 2048, 1024);
  SetLastError(0xdeadbeef);
  urlComponents.dwStructSize = sizeof(urlComponents) + 1;
  ret = InternetCrackUrlA(TEST_URL, 0, 0, &urlComponents);
  ok(ret == FALSE, "Expected InternetCrackUrl to fail\n");
  ok(GLE != 0xdeadbeef && GLE != ERROR_SUCCESS, "Expected GLE to represent a failure\n");
553 554 555 556 557 558 559 560 561 562
}

static void InternetCrackUrlW_test(void)
{
    WCHAR url[] = {
        'h','t','t','p',':','/','/','1','9','2','.','1','6','8','.','0','.','2','2','/',
        'C','F','I','D','E','/','m','a','i','n','.','c','f','m','?','C','F','S','V','R',
        '=','I','D','E','&','A','C','T','I','O','N','=','I','D','E','_','D','E','F','A',
        'U','L','T', 0 };
    static const WCHAR url2[] = { '.','.','/','R','i','t','z','.','x','m','l',0 };
563
    static const WCHAR url3[] = { 'h','t','t','p',':','/','/','x','.','o','r','g',0 };
564 565
    URL_COMPONENTSW comp;
    WCHAR scheme[20], host[20], user[20], pwd[20], urlpart[50], extra[50];
566
    DWORD error;
567 568 569 570 571 572 573 574 575
    BOOL r;

    urlpart[0]=0;
    scheme[0]=0;
    extra[0]=0;
    host[0]=0;
    user[0]=0;
    pwd[0]=0;
    memset(&comp, 0, sizeof comp);
576
    comp.dwStructSize = sizeof(comp);
577
    comp.lpszScheme = scheme;
578
    comp.dwSchemeLength = sizeof(scheme)/sizeof(scheme[0]);
579
    comp.lpszHostName = host;
580
    comp.dwHostNameLength = sizeof(host)/sizeof(host[0]);
581
    comp.lpszUserName = user;
582
    comp.dwUserNameLength = sizeof(user)/sizeof(user[0]);
583
    comp.lpszPassword = pwd;
584
    comp.dwPasswordLength = sizeof(pwd)/sizeof(pwd[0]);
585
    comp.lpszUrlPath = urlpart;
586
    comp.dwUrlPathLength = sizeof(urlpart)/sizeof(urlpart[0]);
587
    comp.lpszExtraInfo = extra;
588
    comp.dwExtraInfoLength = sizeof(extra)/sizeof(extra[0]);
589

590 591 592
    SetLastError(0xdeadbeef);
    r = InternetCrackUrlW(NULL, 0, 0, &comp );
    error = GetLastError();
593 594 595 596 597
    if (!r && error == ERROR_CALL_NOT_IMPLEMENTED)
    {
        win_skip("InternetCrackUrlW is not implemented\n");
        return;
    }
598
    ok( !r, "InternetCrackUrlW succeeded unexpectedly\n");
599 600 601
    ok( error == ERROR_INVALID_PARAMETER ||
        broken(error == ERROR_INTERNET_UNRECOGNIZED_SCHEME), /* IE5 */
        "expected ERROR_INVALID_PARAMETER got %u\n", error);
602

603 604 605 606 607 608 609 610 611
    if (error == ERROR_INVALID_PARAMETER)
    {
        /* Crashes on IE5 */
        SetLastError(0xdeadbeef);
        r = InternetCrackUrlW(url, 0, 0, NULL );
        error = GetLastError();
        ok( !r, "InternetCrackUrlW succeeded unexpectedly\n");
        ok( error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER got %u\n", error);
    }
612

613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630
    r = InternetCrackUrlW(url, 0, 0, &comp );
    ok( r, "failed to crack url\n");
    ok( comp.dwSchemeLength == 4, "scheme length wrong\n");
    ok( comp.dwHostNameLength == 12, "host length wrong\n");
    ok( comp.dwUserNameLength == 0, "user length wrong\n");
    ok( comp.dwPasswordLength == 0, "password length wrong\n");
    ok( comp.dwUrlPathLength == 15, "url length wrong\n");
    ok( comp.dwExtraInfoLength == 29, "extra length wrong\n");
 
    urlpart[0]=0;
    scheme[0]=0;
    extra[0]=0;
    host[0]=0;
    user[0]=0;
    pwd[0]=0;
    memset(&comp, 0, sizeof comp);
    comp.dwStructSize = sizeof comp;
    comp.lpszHostName = host;
631
    comp.dwHostNameLength = sizeof(host)/sizeof(host[0]);
632
    comp.lpszUrlPath = urlpart;
633
    comp.dwUrlPathLength = sizeof(urlpart)/sizeof(urlpart[0]);
634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652

    r = InternetCrackUrlW(url, 0, 0, &comp );
    ok( r, "failed to crack url\n");
    ok( comp.dwSchemeLength == 0, "scheme length wrong\n");
    ok( comp.dwHostNameLength == 12, "host length wrong\n");
    ok( comp.dwUserNameLength == 0, "user length wrong\n");
    ok( comp.dwPasswordLength == 0, "password length wrong\n");
    ok( comp.dwUrlPathLength == 44, "url length wrong\n");
    ok( comp.dwExtraInfoLength == 0, "extra length wrong\n");

    urlpart[0]=0;
    scheme[0]=0;
    extra[0]=0;
    host[0]=0;
    user[0]=0;
    pwd[0]=0;
    memset(&comp, 0, sizeof comp);
    comp.dwStructSize = sizeof comp;
    comp.lpszHostName = host;
653
    comp.dwHostNameLength = sizeof(host)/sizeof(host[0]);
654
    comp.lpszUrlPath = urlpart;
655
    comp.dwUrlPathLength = sizeof(urlpart)/sizeof(urlpart[0]);
656
    comp.lpszExtraInfo = NULL;
657
    comp.dwExtraInfoLength = sizeof(extra)/sizeof(extra[0]);
658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689

    r = InternetCrackUrlW(url, 0, 0, &comp );
    ok( r, "failed to crack url\n");
    ok( comp.dwSchemeLength == 0, "scheme length wrong\n");
    ok( comp.dwHostNameLength == 12, "host length wrong\n");
    ok( comp.dwUserNameLength == 0, "user length wrong\n");
    ok( comp.dwPasswordLength == 0, "password length wrong\n");
    ok( comp.dwUrlPathLength == 15, "url length wrong\n");
    ok( comp.dwExtraInfoLength == 29, "extra length wrong\n");

    urlpart[0]=0;
    scheme[0]=0;
    extra[0]=0;
    host[0]=0;
    user[0]=0;
    pwd[0]=0;
    memset(&comp, 0, sizeof(comp));
    comp.dwStructSize = sizeof(comp);
    comp.lpszScheme = scheme;
    comp.dwSchemeLength = sizeof(scheme)/sizeof(scheme[0]);
    comp.lpszHostName = host;
    comp.dwHostNameLength = sizeof(host)/sizeof(host[0]);
    comp.lpszUserName = user;
    comp.dwUserNameLength = sizeof(user)/sizeof(user[0]);
    comp.lpszPassword = pwd;
    comp.dwPasswordLength = sizeof(pwd)/sizeof(pwd[0]);
    comp.lpszUrlPath = urlpart;
    comp.dwUrlPathLength = sizeof(urlpart)/sizeof(urlpart[0]);
    comp.lpszExtraInfo = extra;
    comp.dwExtraInfoLength = sizeof(extra)/sizeof(extra[0]);

    r = InternetCrackUrlW(url2, 0, 0, &comp);
690 691 692
    todo_wine {
    ok(!r, "InternetCrackUrl should have failed\n");
    ok(GetLastError() == ERROR_INTERNET_UNRECOGNIZED_SCHEME,
693
        "InternetCrackUrl should have failed with error ERROR_INTERNET_UNRECOGNIZED_SCHEME instead of error %d\n",
694 695
        GetLastError());
    }
696 697 698 699 700 701 702 703 704 705 706

    /* Test to see whether cracking a URL without a filename initializes urlpart */
    urlpart[0]=0xba;
    scheme[0]=0;
    extra[0]=0;
    host[0]=0;
    user[0]=0;
    pwd[0]=0;
    memset(&comp, 0, sizeof comp);
    comp.dwStructSize = sizeof comp;
    comp.lpszScheme = scheme;
707
    comp.dwSchemeLength = sizeof(scheme)/sizeof(scheme[0]);
708
    comp.lpszHostName = host;
709
    comp.dwHostNameLength = sizeof(host)/sizeof(host[0]);
710
    comp.lpszUserName = user;
711
    comp.dwUserNameLength = sizeof(user)/sizeof(user[0]);
712
    comp.lpszPassword = pwd;
713
    comp.dwPasswordLength = sizeof(pwd)/sizeof(pwd[0]);
714
    comp.lpszUrlPath = urlpart;
715
    comp.dwUrlPathLength = sizeof(urlpart)/sizeof(urlpart[0]);
716
    comp.lpszExtraInfo = extra;
717
    comp.dwExtraInfoLength = sizeof(extra)/sizeof(extra[0]);
718 719 720 721
    r = InternetCrackUrlW(url3, 0, 0, &comp );
    ok( r, "InternetCrackUrlW failed unexpectedly\n");
    ok( host[0] == 'x', "host should be x.org\n");
    ok( urlpart[0] == 0, "urlpart should be empty\n");
722 723 724 725
}

static void fill_url_components(LPURL_COMPONENTS lpUrlComponents)
{
726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747
    static CHAR http[]       = "http",
                winehq[]     = "www.winehq.org",
                username[]   = "username",
                password[]   = "password",
                site_about[] = "/site/about",
                empty[]      = "";

    lpUrlComponents->dwStructSize = sizeof(URL_COMPONENTS);
    lpUrlComponents->lpszScheme = http;
    lpUrlComponents->dwSchemeLength = strlen(lpUrlComponents->lpszScheme);
    lpUrlComponents->nScheme = INTERNET_SCHEME_HTTP;
    lpUrlComponents->lpszHostName = winehq;
    lpUrlComponents->dwHostNameLength = strlen(lpUrlComponents->lpszHostName);
    lpUrlComponents->nPort = 80;
    lpUrlComponents->lpszUserName = username;
    lpUrlComponents->dwUserNameLength = strlen(lpUrlComponents->lpszUserName);
    lpUrlComponents->lpszPassword = password;
    lpUrlComponents->dwPasswordLength = strlen(lpUrlComponents->lpszPassword);
    lpUrlComponents->lpszUrlPath = site_about;
    lpUrlComponents->dwUrlPathLength = strlen(lpUrlComponents->lpszUrlPath);
    lpUrlComponents->lpszExtraInfo = empty;
    lpUrlComponents->dwExtraInfoLength = strlen(lpUrlComponents->lpszExtraInfo);
748 749 750 751 752 753 754 755
}

static void InternetCreateUrlA_test(void)
{
	URL_COMPONENTS urlComp;
	LPSTR szUrl;
	DWORD len = -1;
	BOOL ret;
756 757 758 759 760
        static CHAR empty[]      = "",
                    nhttp[]      = "nhttp",
                    http[]       = "http",
                    https[]      = "https",
                    winehq[]     = "www.winehq.org",
761
                    localhost[]  = "localhost",
762 763
                    username[]   = "username",
                    password[]   = "password",
764
                    root[]       = "/",
765
                    site_about[] = "/site/about",
766
                    extra_info[] = "?test=123",
767 768 769
                    about[]      = "about",
                    blank[]      = "blank",
                    host[]       = "host";
770 771 772

	/* test NULL lpUrlComponents */
	SetLastError(0xdeadbeef);
773
	ret = InternetCreateUrlA(NULL, 0, NULL, &len);
774
	ok(!ret, "Expected failure\n");
775 776
	ok(GetLastError() == ERROR_INVALID_PARAMETER,
		"Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
777
	ok(len == -1, "Expected len -1, got %d\n", len);
778 779 780 781 782 783 784

	/* test zero'ed lpUrlComponents */
	ZeroMemory(&urlComp, sizeof(URL_COMPONENTS));
	SetLastError(0xdeadbeef);
	ret = InternetCreateUrlA(&urlComp, 0, NULL, &len);
	ok(!ret, "Expected failure\n");
	ok(GetLastError() == ERROR_INVALID_PARAMETER,
785 786
		"Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
	ok(len == -1, "Expected len -1, got %d\n", len);
787

788
	/* test valid lpUrlComponents, NULL lpdwUrlLength */
789 790 791 792 793
	fill_url_components(&urlComp);
	SetLastError(0xdeadbeef);
	ret = InternetCreateUrlA(&urlComp, 0, NULL, NULL);
	ok(!ret, "Expected failure\n");
	ok(GetLastError() == ERROR_INVALID_PARAMETER,
794 795
		"Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
	ok(len == -1, "Expected len -1, got %d\n", len);
796

797
	/* test valid lpUrlComponents, empty szUrl
798 799 800 801 802 803 804
	 * lpdwUrlLength is size of buffer required on exit, including
	 * the terminating null when GLE == ERROR_INSUFFICIENT_BUFFER
	 */
	SetLastError(0xdeadbeef);
	ret = InternetCreateUrlA(&urlComp, 0, NULL, &len);
	ok(!ret, "Expected failure\n");
	ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
805 806
		"Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
	ok(len == 51, "Expected len 51, got %d\n", len);
807 808 809 810 811 812 813

	/* test correct size, NULL szUrl */
	fill_url_components(&urlComp);
	SetLastError(0xdeadbeef);
	ret = InternetCreateUrlA(&urlComp, 0, NULL, &len);
	ok(!ret, "Expected failure\n");
	ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
814 815
		"Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
	ok(len == 51, "Expected len 51, got %d\n", len);
816

817
	/* test valid lpUrlComponents, alloc-ed szUrl, small size */
818 819 820 821 822 823
	SetLastError(0xdeadbeef);
	szUrl = HeapAlloc(GetProcessHeap(), 0, len);
	len -= 2;
	ret = InternetCreateUrlA(&urlComp, 0, szUrl, &len);
	ok(!ret, "Expected failure\n");
	ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
824 825
		"Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
	ok(len == 51, "Expected len 51, got %d\n", len);
826

827
	/* alloc-ed szUrl, NULL lpszScheme
828 829 830 831 832 833 834
	 * shows that it uses nScheme instead
	 */
	SetLastError(0xdeadbeef);
	urlComp.lpszScheme = NULL;
	ret = InternetCreateUrlA(&urlComp, 0, szUrl, &len);
	ok(ret, "Expected success\n");
	ok(GetLastError() == 0xdeadbeef,
835 836
		"Expected 0xdeadbeef, got %d\n", GetLastError());
	ok(len == 50, "Expected len 50, got %d\n", len);
837 838
	ok(!strcmp(szUrl, CREATE_URL1), "Expected %s, got %s\n", CREATE_URL1, szUrl);

839
	/* alloc-ed szUrl, invalid nScheme
840 841 842 843 844 845 846 847 848
	 * any nScheme out of range seems ignored
	 */
	fill_url_components(&urlComp);
	SetLastError(0xdeadbeef);
	urlComp.nScheme = -3;
	len++;
	ret = InternetCreateUrlA(&urlComp, 0, szUrl, &len);
	ok(ret, "Expected success\n");
	ok(GetLastError() == 0xdeadbeef,
849 850
		"Expected 0xdeadbeef, got %d\n", GetLastError());
	ok(len == 50, "Expected len 50, got %d\n", len);
851

852
	/* test valid lpUrlComponents, alloc-ed szUrl */
853 854 855 856 857 858
	fill_url_components(&urlComp);
	SetLastError(0xdeadbeef);
	len = 51;
	ret = InternetCreateUrlA(&urlComp, 0, szUrl, &len);
	ok(ret, "Expected success\n");
	ok(GetLastError() == 0xdeadbeef,
859 860
		"Expected 0xdeadbeef, got %d\n", GetLastError());
	ok(len == 50, "Expected len 50, got %d\n", len);
861 862 863 864 865 866 867 868 869 870 871
	ok(strstr(szUrl, "80") == NULL, "Didn't expect to find 80 in szUrl\n");
	ok(!strcmp(szUrl, CREATE_URL1), "Expected %s, got %s\n", CREATE_URL1, szUrl);

	/* valid username, NULL password */
	fill_url_components(&urlComp);
	SetLastError(0xdeadbeef);
	urlComp.lpszPassword = NULL;
	len = 42;
	ret = InternetCreateUrlA(&urlComp, 0, szUrl, &len);
	ok(ret, "Expected success\n");
	ok(GetLastError() == 0xdeadbeef,
872 873
		"Expected 0xdeadbeef, got %d\n", GetLastError());
	ok(len == 41, "Expected len 41, got %d\n", len);
874 875 876 877 878
	ok(!strcmp(szUrl, CREATE_URL2), "Expected %s, got %s\n", CREATE_URL2, szUrl);

	/* valid username, empty password */
	fill_url_components(&urlComp);
	SetLastError(0xdeadbeef);
879
	urlComp.lpszPassword = empty;
880 881 882 883
	len = 51;
	ret = InternetCreateUrlA(&urlComp, 0, szUrl, &len);
	ok(ret, "Expected success\n");
	ok(GetLastError() == 0xdeadbeef,
884 885
		"Expected 0xdeadbeef, got %d\n", GetLastError());
	ok(len == 50, "Expected len 50, got %d\n", len);
886 887 888 889 890 891 892 893 894 895 896 897
	ok(!strcmp(szUrl, CREATE_URL3), "Expected %s, got %s\n", CREATE_URL3, szUrl);

	/* valid password, NULL username
	 * if password is provided, username has to exist
	 */
	fill_url_components(&urlComp);
	SetLastError(0xdeadbeef);
	urlComp.lpszUserName = NULL;
	len = 42;
	ret = InternetCreateUrlA(&urlComp, 0, szUrl, &len);
	ok(!ret, "Expected failure\n");
	ok(GetLastError() == ERROR_INVALID_PARAMETER,
898 899
		"Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
	ok(len == 42, "Expected len 42, got %d\n", len);
900 901 902 903 904 905 906
	ok(!strcmp(szUrl, CREATE_URL3), "Expected %s, got %s\n", CREATE_URL3, szUrl);

	/* valid password, empty username
	 * if password is provided, username has to exist
	 */
	fill_url_components(&urlComp);
	SetLastError(0xdeadbeef);
907
	urlComp.lpszUserName = empty;
908 909 910 911
	len = 51;
	ret = InternetCreateUrlA(&urlComp, 0, szUrl, &len);
	ok(ret, "Expected success\n");
	ok(GetLastError() == 0xdeadbeef,
912 913
		"Expected 0xdeadbeef, got %d\n", GetLastError());
	ok(len == 50, "Expected len 50, got %d\n", len);
914 915 916 917 918 919 920 921 922 923 924
	ok(!strcmp(szUrl, CREATE_URL5), "Expected %s, got %s\n", CREATE_URL5, szUrl);

	/* NULL username, NULL password */
	fill_url_components(&urlComp);
	SetLastError(0xdeadbeef);
	urlComp.lpszUserName = NULL;
	urlComp.lpszPassword = NULL;
	len = 42;
	ret = InternetCreateUrlA(&urlComp, 0, szUrl, &len);
	ok(ret, "Expected success\n");
	ok(GetLastError() == 0xdeadbeef,
925 926
		"Expected 0xdeadbeef, got %d\n", GetLastError());
	ok(len == 32, "Expected len 32, got %d\n", len);
927 928 929 930 931
	ok(!strcmp(szUrl, CREATE_URL4), "Expected %s, got %s\n", CREATE_URL4, szUrl);

	/* empty username, empty password */
	fill_url_components(&urlComp);
	SetLastError(0xdeadbeef);
932 933
	urlComp.lpszUserName = empty;
	urlComp.lpszPassword = empty;
934 935 936 937
	len = 51;
	ret = InternetCreateUrlA(&urlComp, 0, szUrl, &len);
	ok(ret, "Expected success\n");
	ok(GetLastError() == 0xdeadbeef,
938 939
		"Expected 0xdeadbeef, got %d\n", GetLastError());
	ok(len == 50, "Expected len 50, got %d\n", len);
940 941 942 943 944 945 946
	ok(!strcmp(szUrl, CREATE_URL5), "Expected %s, got %s\n", CREATE_URL5, szUrl);

	/* shows that nScheme is ignored, as the appearance of the port number
	 * depends on lpszScheme and the string copied depends on lpszScheme.
	 */
	fill_url_components(&urlComp);
	HeapFree(GetProcessHeap(), 0, szUrl);
947
	urlComp.lpszScheme = nhttp;
948 949
	urlComp.dwSchemeLength = strlen(urlComp.lpszScheme);
	len = strlen(CREATE_URL6) + 1;
950
	szUrl = HeapAlloc(GetProcessHeap(), 0, len);
951 952
	ret = InternetCreateUrlA(&urlComp, ICU_ESCAPE, szUrl, &len);
	ok(ret, "Expected success\n");
953
	ok(len == strlen(CREATE_URL6), "Expected len %d, got %d\n", lstrlenA(CREATE_URL6) + 1, len);
954 955 956 957
	ok(!strcmp(szUrl, CREATE_URL6), "Expected %s, got %s\n", CREATE_URL6, szUrl);

	/* if lpszScheme != "http" or nPort != 80, display nPort */
	HeapFree(GetProcessHeap(), 0, szUrl);
958
        urlComp.lpszScheme = http;
959 960 961 962 963
	urlComp.dwSchemeLength = strlen(urlComp.lpszScheme);
	urlComp.nPort = 42;
	szUrl = HeapAlloc(GetProcessHeap(), 0, ++len);
	ret = InternetCreateUrlA(&urlComp, ICU_ESCAPE, szUrl, &len);
	ok(ret, "Expected success\n");
964
	ok(len == 53, "Expected len 53, got %d\n", len);
965 966 967 968 969 970 971
	ok(strstr(szUrl, "42") != NULL, "Expected to find 42 in szUrl\n");
	ok(!strcmp(szUrl, CREATE_URL7), "Expected %s, got %s\n", CREATE_URL7, szUrl);

	HeapFree(GetProcessHeap(), 0, szUrl);

	memset(&urlComp, 0, sizeof(urlComp));
	urlComp.dwStructSize = sizeof(URL_COMPONENTS);
972
	urlComp.lpszScheme = http;
973 974
	urlComp.dwSchemeLength = 0;
	urlComp.nScheme = INTERNET_SCHEME_HTTP;
975
	urlComp.lpszHostName = winehq;
976 977
	urlComp.dwHostNameLength = 0;
	urlComp.nPort = 80;
978
	urlComp.lpszUserName = username;
979
	urlComp.dwUserNameLength = 0;
980
	urlComp.lpszPassword = password;
981
	urlComp.dwPasswordLength = 0;
982
	urlComp.lpszUrlPath = site_about;
983
	urlComp.dwUrlPathLength = 0;
984
	urlComp.lpszExtraInfo = empty;
985 986
	urlComp.dwExtraInfoLength = 0;
	len = strlen(CREATE_URL1);
987
	szUrl = HeapAlloc(GetProcessHeap(), 0, ++len);
988 989
	ret = InternetCreateUrlA(&urlComp, ICU_ESCAPE, szUrl, &len);
	ok(ret, "Expected success\n");
990
	ok(len == strlen(CREATE_URL1), "Expected len %d, got %d\n", lstrlenA(CREATE_URL1), len);
991 992
	ok(!strcmp(szUrl, CREATE_URL1), "Expected %s, got %s\n", CREATE_URL1, szUrl);

993 994
	HeapFree(GetProcessHeap(), 0, szUrl);

995 996
	memset(&urlComp, 0, sizeof(urlComp));
	urlComp.dwStructSize = sizeof(URL_COMPONENTS);
997
	urlComp.lpszScheme = https;
998 999
	urlComp.dwSchemeLength = 0;
	urlComp.nScheme = INTERNET_SCHEME_HTTP;
1000
	urlComp.lpszHostName = winehq;
1001 1002
	urlComp.dwHostNameLength = 0;
	urlComp.nPort = 443;
1003
	urlComp.lpszUserName = username;
1004
	urlComp.dwUserNameLength = 0;
1005
	urlComp.lpszPassword = password;
1006
	urlComp.dwPasswordLength = 0;
1007
	urlComp.lpszUrlPath = site_about;
1008
	urlComp.dwUrlPathLength = 0;
1009
	urlComp.lpszExtraInfo = empty;
1010 1011
	urlComp.dwExtraInfoLength = 0;
	len = strlen(CREATE_URL8);
1012
	szUrl = HeapAlloc(GetProcessHeap(), 0, ++len);
1013 1014
	ret = InternetCreateUrlA(&urlComp, ICU_ESCAPE, szUrl, &len);
	ok(ret, "Expected success\n");
1015
	ok(len == strlen(CREATE_URL8), "Expected len %d, got %d\n", lstrlenA(CREATE_URL8), len);
1016 1017 1018 1019 1020 1021
	ok(!strcmp(szUrl, CREATE_URL8), "Expected %s, got %s\n", CREATE_URL8, szUrl);

	HeapFree(GetProcessHeap(), 0, szUrl);

	memset(&urlComp, 0, sizeof(urlComp));
	urlComp.dwStructSize = sizeof(URL_COMPONENTS);
1022
	urlComp.lpszScheme = about;
1023
	urlComp.dwSchemeLength = 5;
1024
	urlComp.lpszUrlPath = blank;
1025 1026 1027
	urlComp.dwUrlPathLength = 5;
	len = strlen(CREATE_URL9);
	len++; /* work around bug in native wininet */
1028
	szUrl = HeapAlloc(GetProcessHeap(), 0, ++len);
1029 1030
	ret = InternetCreateUrlA(&urlComp, ICU_ESCAPE, szUrl, &len);
	ok(ret, "Expected success\n");
1031
	ok(len == strlen(CREATE_URL9), "Expected len %d, got %d\n", lstrlenA(CREATE_URL9), len);
1032 1033 1034 1035 1036 1037
	ok(!strcmp(szUrl, CREATE_URL9), "Expected %s, got %s\n", CREATE_URL9, szUrl);

	HeapFree(GetProcessHeap(), 0, szUrl);

	memset(&urlComp, 0, sizeof(urlComp));
	urlComp.dwStructSize = sizeof(URL_COMPONENTS);
1038 1039 1040
	urlComp.lpszScheme = about;
	urlComp.lpszHostName = host;
	urlComp.lpszUrlPath = blank;
1041 1042
	len = strlen(CREATE_URL10);
	len++; /* work around bug in native wininet */
1043
	szUrl = HeapAlloc(GetProcessHeap(), 0, ++len);
1044 1045
	ret = InternetCreateUrlA(&urlComp, ICU_ESCAPE, szUrl, &len);
	ok(ret, "Expected success\n");
1046
	ok(len == strlen(CREATE_URL10), "Expected len %d, got %d\n", lstrlenA(CREATE_URL10), len);
1047 1048 1049 1050 1051 1052 1053
	ok(!strcmp(szUrl, CREATE_URL10), "Expected %s, got %s\n", CREATE_URL10, szUrl);

	HeapFree(GetProcessHeap(), 0, szUrl);

	memset(&urlComp, 0, sizeof(urlComp));
	urlComp.dwStructSize = sizeof(URL_COMPONENTS);
	urlComp.nPort = 8080;
1054
	urlComp.lpszScheme = about;
1055
	len = strlen(CREATE_URL11);
1056
	szUrl = HeapAlloc(GetProcessHeap(), 0, ++len);
1057 1058
	ret = InternetCreateUrlA(&urlComp, ICU_ESCAPE, szUrl, &len);
	ok(ret, "Expected success\n");
1059
	ok(len == strlen(CREATE_URL11), "Expected len %d, got %d\n", lstrlenA(CREATE_URL11), len);
1060 1061 1062 1063 1064 1065
	ok(!strcmp(szUrl, CREATE_URL11), "Expected %s, got %s\n", CREATE_URL11, szUrl);

	HeapFree(GetProcessHeap(), 0, szUrl);

	memset(&urlComp, 0, sizeof(urlComp));
	urlComp.dwStructSize = sizeof(URL_COMPONENTS);
1066
	urlComp.lpszScheme = http;
1067 1068
	urlComp.dwSchemeLength = 0;
	urlComp.nScheme = INTERNET_SCHEME_HTTP;
1069
	urlComp.lpszHostName = winehq;
1070 1071 1072
	urlComp.dwHostNameLength = 0;
	urlComp.nPort = 65535;
	len = strlen(CREATE_URL12);
1073
	szUrl = HeapAlloc(GetProcessHeap(), 0, ++len);
1074 1075
	ret = InternetCreateUrlA(&urlComp, ICU_ESCAPE, szUrl, &len);
	ok(ret, "Expected success\n");
1076
	ok(len == strlen(CREATE_URL12), "Expected len %d, got %d\n", lstrlenA(CREATE_URL12), len);
1077 1078 1079
	ok(!strcmp(szUrl, CREATE_URL12), "Expected %s, got %s\n", CREATE_URL12, szUrl);

	HeapFree(GetProcessHeap(), 0, szUrl);
1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095

    memset(&urlComp, 0, sizeof(urlComp));
    urlComp.dwStructSize = sizeof(URL_COMPONENTS);
    urlComp.lpszScheme = http;
    urlComp.dwSchemeLength = strlen(urlComp.lpszScheme);
    urlComp.lpszHostName = localhost;
    urlComp.dwHostNameLength = strlen(urlComp.lpszHostName);
    urlComp.nPort = 80;
    urlComp.lpszUrlPath = root;
    urlComp.dwUrlPathLength = strlen(urlComp.lpszUrlPath);
    urlComp.lpszExtraInfo = extra_info;
    urlComp.dwExtraInfoLength = strlen(urlComp.lpszExtraInfo);
    len = 256;
    szUrl = HeapAlloc(GetProcessHeap(), 0, len);
    InternetCreateUrlA(&urlComp, ICU_ESCAPE, szUrl, &len);
    ok(ret, "Expected success\n");
1096
    ok(len == strlen(CREATE_URL13), "Got len %u\n", len);
1097 1098 1099
    ok(!strcmp(szUrl, CREATE_URL13), "Expected \"%s\", got \"%s\"\n", CREATE_URL13, szUrl);

    HeapFree(GetProcessHeap(), 0, szUrl);
1100 1101 1102 1103
}

START_TEST(url)
{
1104 1105
    int i;

1106 1107 1108 1109 1110
    if(!GetProcAddress(GetModuleHandleA("wininet.dll"), "InternetGetCookieExW")) {
        win_skip("Too old IE (older than 6.0)\n");
        return;
    }

1111 1112 1113
    for(i=0; i < sizeof(crack_url_tests)/sizeof(*crack_url_tests); i++)
        test_crack_url(crack_url_tests+i);

1114 1115 1116 1117
    InternetCrackUrl_test();
    InternetCrackUrlW_test();
    InternetCreateUrlA_test();
}