Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/kernelbase/path.c | 34 ++++++++++++++++++---------------- dlls/shlwapi/tests/url.c | 6 +++--- 2 files changed, 21 insertions(+), 19 deletions(-)
diff --git a/dlls/kernelbase/path.c b/dlls/kernelbase/path.c index b753ce3dd2e..28717c25f79 100644 --- a/dlls/kernelbase/path.c +++ b/dlls/kernelbase/path.c @@ -4329,6 +4329,24 @@ HRESULT WINAPI UrlGetPartW(const WCHAR *url, WCHAR *out, DWORD *out_len, DWORD p
hr = parse_url(url, &pl);
+ switch (scheme) + { + case URL_SCHEME_FILE: + case URL_SCHEME_FTP: + case URL_SCHEME_GOPHER: + case URL_SCHEME_HTTP: + case URL_SCHEME_HTTPS: + case URL_SCHEME_TELNET: + case URL_SCHEME_NEWS: + case URL_SCHEME_NNTP: + case URL_SCHEME_SNEWS: + break; + + default: + if (part != URL_PART_SCHEME && part != URL_PART_QUERY) + return E_FAIL; + } + switch (part) { case URL_PART_SCHEME: @@ -4344,22 +4362,6 @@ HRESULT WINAPI UrlGetPartW(const WCHAR *url, WCHAR *out, DWORD *out_len, DWORD p break;
case URL_PART_HOSTNAME: - switch (scheme) - { - case URL_SCHEME_FILE: - case URL_SCHEME_FTP: - case URL_SCHEME_GOPHER: - case URL_SCHEME_HTTP: - case URL_SCHEME_HTTPS: - case URL_SCHEME_TELNET: - case URL_SCHEME_NEWS: - case URL_SCHEME_NNTP: - case URL_SCHEME_SNEWS: - break; - default: - return E_FAIL; - } - if (scheme == URL_SCHEME_FILE && (!pl.hostname_len || (pl.hostname_len == 1 && *(pl.hostname + 1) == ':'))) { *out = '\0'; diff --git a/dlls/shlwapi/tests/url.c b/dlls/shlwapi/tests/url.c index 729b069a772..904d3e7bb5b 100644 --- a/dlls/shlwapi/tests/url.c +++ b/dlls/shlwapi/tests/url.c @@ -601,10 +601,10 @@ static void test_UrlGetPart(void) tests[] = { {"hi", URL_PART_SCHEME, 0, S_FALSE, ""}, - {"hi", URL_PART_USERNAME, 0, E_FAIL, .todo_hr = TRUE}, - {"hi", URL_PART_PASSWORD, 0, E_FAIL, .todo_hr = TRUE}, + {"hi", URL_PART_USERNAME, 0, E_FAIL}, + {"hi", URL_PART_PASSWORD, 0, E_FAIL}, {"hi", URL_PART_HOSTNAME, 0, E_FAIL}, - {"hi", URL_PART_PORT, 0, E_FAIL, .todo_hr = TRUE}, + {"hi", URL_PART_PORT, 0, E_FAIL}, {"hi", URL_PART_QUERY, 0, S_FALSE, ""},
{"http://foo:bar@localhost:21/internal.php?query=x&return=y", URL_PART_SCHEME, 0, S_OK, "http"},
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/kernelbase/path.c | 26 +++++++++++++------------- dlls/shlwapi/tests/url.c | 2 +- 2 files changed, 14 insertions(+), 14 deletions(-)
diff --git a/dlls/kernelbase/path.c b/dlls/kernelbase/path.c index 28717c25f79..954faf47a99 100644 --- a/dlls/kernelbase/path.c +++ b/dlls/kernelbase/path.c @@ -77,7 +77,6 @@ struct parsed_url enum url_scan_type { SCHEME, - HOST, PORT, USERPASS, }; @@ -4221,14 +4220,6 @@ static const WCHAR * scan_url(const WCHAR *start, DWORD *size, enum url_scan_typ } break;
- case HOST: - while (isalnum(*start) || *start == '-' || *start == '.' || *start == ' ' || *start == '*') - { - start++; - (*size)++; - } - break; - default: FIXME("unknown type %d\n", type); return L""; @@ -4237,6 +4228,15 @@ static const WCHAR * scan_url(const WCHAR *start, DWORD *size, enum url_scan_typ return start; }
+static const WCHAR *parse_url_element( const WCHAR *url, const WCHAR *separators ) +{ + const WCHAR *p; + + if ((p = wcspbrk( url, separators ))) + return p; + return url + wcslen( url ); +} + static LONG parse_url(const WCHAR *url, struct parsed_url *pl) { const WCHAR *work; @@ -4280,10 +4280,10 @@ static LONG parse_url(const WCHAR *url, struct parsed_url *pl) } else goto ErrorExit;
- /* now start parsing hostname or hostnumber */ - work++; - pl->hostname = work; - work = scan_url(pl->hostname, &pl->hostname_len, HOST); + pl->hostname = work + 1; + work = parse_url_element( pl->hostname, L":/\?#" ); + pl->hostname_len = work - pl->hostname; + if (*work == ':') { /* parse port */ diff --git a/dlls/shlwapi/tests/url.c b/dlls/shlwapi/tests/url.c index 904d3e7bb5b..07d3ebfa331 100644 --- a/dlls/shlwapi/tests/url.c +++ b/dlls/shlwapi/tests/url.c @@ -655,7 +655,7 @@ static void test_UrlGetPart(void) {"http://user:pass:q@host", URL_PART_USERNAME, 0, S_OK, "user", .todo_hr = TRUE}, {"http://user:pass:q@host", URL_PART_PASSWORD, 0, S_OK, "pass:q", .todo_hr = TRUE}, {"http://user@host@q", URL_PART_USERNAME, 0, S_OK, "user"}, - {"http://user@host@q", URL_PART_HOSTNAME, 0, S_OK, "host@q", .todo_result = TRUE}, + {"http://user@host@q", URL_PART_HOSTNAME, 0, S_OK, "host@q"},
{"http:localhost/index.html", URL_PART_HOSTNAME, 0, E_FAIL, .todo_hr = TRUE}, {"http:/localhost/index.html", URL_PART_HOSTNAME, 0, E_FAIL, .todo_hr = TRUE},
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/kernelbase/path.c | 16 +++------------- dlls/shlwapi/tests/url.c | 6 +++--- 2 files changed, 6 insertions(+), 16 deletions(-)
diff --git a/dlls/kernelbase/path.c b/dlls/kernelbase/path.c index 954faf47a99..dfb37006da8 100644 --- a/dlls/kernelbase/path.c +++ b/dlls/kernelbase/path.c @@ -77,7 +77,6 @@ struct parsed_url enum url_scan_type { SCHEME, - PORT, USERPASS, };
@@ -4212,14 +4211,6 @@ static const WCHAR * scan_url(const WCHAR *start, DWORD *size, enum url_scan_typ } break;
- case PORT: - while (*start >= '0' && *start <= '9') - { - start++; - (*size)++; - } - break; - default: FIXME("unknown type %d\n", type); return L""; @@ -4286,10 +4277,9 @@ static LONG parse_url(const WCHAR *url, struct parsed_url *pl)
if (*work == ':') { - /* parse port */ - work++; - pl->port = work; - work = scan_url(pl->port, &pl->port_len, PORT); + pl->port = work + 1; + work = parse_url_element( pl->port, L"/\?#" ); + pl->port_len = work - pl->port; } if (*work == '/') { diff --git a/dlls/shlwapi/tests/url.c b/dlls/shlwapi/tests/url.c index 07d3ebfa331..c4afb1375e9 100644 --- a/dlls/shlwapi/tests/url.c +++ b/dlls/shlwapi/tests/url.c @@ -630,7 +630,7 @@ static void test_UrlGetPart(void) {"http://localhost:port/", URL_PART_USERNAME, 0, E_INVALIDARG, .todo_hr = TRUE}, {"http://localhost:port/", URL_PART_PASSWORD, 0, E_INVALIDARG, .todo_hr = TRUE}, {"http://localhost:port/", URL_PART_HOSTNAME, 0, S_OK, "localhost"}, - {"http://localhost:port/", URL_PART_PORT, 0, S_OK, "port", .todo_hr = TRUE}, + {"http://localhost:port/", URL_PART_PORT, 0, S_OK, "port"}, {"http://:", URL_PART_HOSTNAME, 0, S_FALSE, ""}, {"http://:", URL_PART_PORT, 0, S_FALSE, ""},
@@ -651,7 +651,7 @@ static void test_UrlGetPart(void) {"http://:@", URL_PART_HOSTNAME, 0, S_FALSE, ""},
{"http://host:port:q", URL_PART_HOSTNAME, 0, S_OK, "host"}, - {"http://host:port:q", URL_PART_PORT, 0, S_OK, "port:q", .todo_hr = TRUE}, + {"http://host:port:q", URL_PART_PORT, 0, S_OK, "port:q"}, {"http://user:pass:q@host", URL_PART_USERNAME, 0, S_OK, "user", .todo_hr = TRUE}, {"http://user:pass:q@host", URL_PART_PASSWORD, 0, S_OK, "pass:q", .todo_hr = TRUE}, {"http://user@host@q", URL_PART_USERNAME, 0, S_OK, "user"}, @@ -678,7 +678,7 @@ static void test_UrlGetPart(void) {"http:// !"$%&'()*+,-.;<=>[]^_`{|~}\x01\x7f\xff:pass@host", URL_PART_USERNAME, 0, S_OK, " !"$%&'()*+,-.;<=>[]^_`{|~}\x01\x7f\xff", .todo_hr = TRUE}, {"http://user: !"$%&'()*+,-.;<=>[]^_`{|~}\x01\x7f\xff@host", URL_PART_PASSWORD, 0, S_OK, " !"$%&'()*+,-.;<=>[]^_`{|~}\x01\x7f\xff", .todo_hr = TRUE}, {"http:// !"$%&'()*+,-.;<=>[]^_`{|~}\x01\x7f\xff", URL_PART_HOSTNAME, 0, S_OK, " !"$%&'()*+,-.;<=>[]^_`{|~}\x01\x7f\xff", .todo_hr = TRUE}, - {"http://host: !"$%&'()*+,-.;<=>[]^_`{|~}\x01\x7f\xff", URL_PART_PORT, 0, S_OK, " !"$%&'()*+,-.;<=>[]^_`{|~}\x01\x7f\xff", .todo_hr = TRUE}, + {"http://host: !"$%&'()*+,-.;<=>[]^_`{|~}\x01\x7f\xff", URL_PART_PORT, 0, S_OK, " !"$%&'()*+,-.;<=>[]^_`{|~}\x01\x7f\xff"},
{"http:///index.html", URL_PART_HOSTNAME, 0, S_FALSE, ""}, {"http:///index.html", URL_PART_HOSTNAME, URL_PARTFLAG_KEEPSCHEME, S_OK, "http:", .todo_hr = TRUE},
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/kernelbase/path.c | 52 ++++++---------------------------------- dlls/shlwapi/tests/url.c | 27 ++++++++++----------- 2 files changed, 19 insertions(+), 60 deletions(-)
diff --git a/dlls/kernelbase/path.c b/dlls/kernelbase/path.c index dfb37006da8..823fb51a68e 100644 --- a/dlls/kernelbase/path.c +++ b/dlls/kernelbase/path.c @@ -77,7 +77,6 @@ struct parsed_url enum url_scan_type { SCHEME, - USERPASS, };
static WCHAR *heap_strdupAtoW(const char *str) @@ -4175,42 +4174,6 @@ static const WCHAR * scan_url(const WCHAR *start, DWORD *size, enum url_scan_typ *size = 0; break;
- case USERPASS: - for (;;) - { - if (isalnum(*start) || - /* user/password only characters */ - (*start == ';') || - (*start == '?') || - (*start == '&') || - (*start == '=') || - /* *extra* characters */ - (*start == '!') || - (*start == '*') || - (*start == ''') || - (*start == '(') || - (*start == ')') || - (*start == ',') || - /* *safe* characters */ - (*start == '$') || - (*start == '_') || - (*start == '+') || - (*start == '-') || - (*start == '.') || - (*start == ' ')) - { - start++; - (*size)++; - } - else if (*start == '%' && isxdigit(start[1]) && isxdigit(start[2])) - { - start += 3; - *size += 3; - } - else break; - } - break; - default: FIXME("unknown type %d\n", type); return L""; @@ -4240,13 +4203,13 @@ static LONG parse_url(const WCHAR *url, struct parsed_url *pl) if ((*work != '/') || (*(work+1) != '/')) goto SuccessExit;
pl->username = work + 2; - work = scan_url(pl->username, &pl->username_len, USERPASS); - if (*work == ':' ) + work = parse_url_element( pl->username, L":@/\?#" ); + pl->username_len = work - pl->username; + if (*work == ':') { - /* parse password */ - work++; - pl->password = work; - work = scan_url(pl->password, &pl->password_len, USERPASS); + pl->password = work + 1; + work = parse_url_element( pl->password, L"@/\?#" ); + pl->password_len = work - pl->password; if (*work != '@') { /* what we just parsed must be the hostname and port @@ -4262,14 +4225,13 @@ static LONG parse_url(const WCHAR *url, struct parsed_url *pl) pl->password_len = 0; pl->password = 0; } - else if (!*work || *work == '/' || *work == '.') + else { /* what was parsed was hostname, so reset pointers and let it parse */ pl->username_len = pl->password_len = 0; work = pl->username - 1; pl->username = pl->password = 0; } - else goto ErrorExit;
pl->hostname = work + 1; work = parse_url_element( pl->hostname, L":/\?#" ); diff --git a/dlls/shlwapi/tests/url.c b/dlls/shlwapi/tests/url.c index c4afb1375e9..18ff5021986 100644 --- a/dlls/shlwapi/tests/url.c +++ b/dlls/shlwapi/tests/url.c @@ -652,32 +652,32 @@ static void test_UrlGetPart(void)
{"http://host:port:q", URL_PART_HOSTNAME, 0, S_OK, "host"}, {"http://host:port:q", URL_PART_PORT, 0, S_OK, "port:q"}, - {"http://user:pass:q@host", URL_PART_USERNAME, 0, S_OK, "user", .todo_hr = TRUE}, - {"http://user:pass:q@host", URL_PART_PASSWORD, 0, S_OK, "pass:q", .todo_hr = TRUE}, + {"http://user:pass:q@host", URL_PART_USERNAME, 0, S_OK, "user"}, + {"http://user:pass:q@host", URL_PART_PASSWORD, 0, S_OK, "pass:q"}, {"http://user@host@q", URL_PART_USERNAME, 0, S_OK, "user"}, {"http://user@host@q", URL_PART_HOSTNAME, 0, S_OK, "host@q"},
{"http:localhost/index.html", URL_PART_HOSTNAME, 0, E_FAIL, .todo_hr = TRUE}, {"http:/localhost/index.html", URL_PART_HOSTNAME, 0, E_FAIL, .todo_hr = TRUE},
- {"http://localhost%5C%5Cindex.html", URL_PART_HOSTNAME, 0, S_OK, "localhost", .todo_hr = TRUE}, + {"http://localhost%5C%5Cindex.html", URL_PART_HOSTNAME, 0, S_OK, "localhost"}, {"http:/\localhost/index.html", URL_PART_HOSTNAME, 0, S_OK, "localhost", .todo_hr = TRUE}, {"http:\/localhost/index.html", URL_PART_HOSTNAME, 0, S_OK, "localhost", .todo_hr = TRUE},
- {"ftp://localhost\index.html", URL_PART_HOSTNAME, 0, S_OK, "localhost", .todo_hr = TRUE}, + {"ftp://localhost\index.html", URL_PART_HOSTNAME, 0, S_OK, "localhost"}, {"ftp:/\localhost/index.html", URL_PART_HOSTNAME, 0, S_OK, "localhost", .todo_hr = TRUE}, {"ftp:\/localhost/index.html", URL_PART_HOSTNAME, 0, S_OK, "localhost", .todo_hr = TRUE},
- {"http://host?a:b@c:d", URL_PART_HOSTNAME, 0, S_OK, "host", .todo_result = TRUE}, + {"http://host?a:b@c:d", URL_PART_HOSTNAME, 0, S_OK, "host"}, {"http://host?a:b@c:d", URL_PART_QUERY, 0, S_OK, "a:b@c:d", .todo_hr = TRUE}, - {"http://host#a:b@c:d", URL_PART_HOSTNAME, 0, S_OK, "host", .todo_hr = TRUE}, + {"http://host#a:b@c:d", URL_PART_HOSTNAME, 0, S_OK, "host"}, {"http://host#a:b@c:d", URL_PART_QUERY, 0, S_FALSE, ""},
/* All characters, other than those with special meaning, are allowed. */ {"http://foo:bar@google.*.com:21/internal.php?query=x&return=y", URL_PART_HOSTNAME, 0, S_OK, "google.*.com"}, - {"http:// !"$%&'()*+,-.;<=>[]^_`{|~}\x01\x7f\xff:pass@host", URL_PART_USERNAME, 0, S_OK, " !"$%&'()*+,-.;<=>[]^_`{|~}\x01\x7f\xff", .todo_hr = TRUE}, - {"http://user: !"$%&'()*+,-.;<=>[]^_`{|~}\x01\x7f\xff@host", URL_PART_PASSWORD, 0, S_OK, " !"$%&'()*+,-.;<=>[]^_`{|~}\x01\x7f\xff", .todo_hr = TRUE}, - {"http:// !"$%&'()*+,-.;<=>[]^_`{|~}\x01\x7f\xff", URL_PART_HOSTNAME, 0, S_OK, " !"$%&'()*+,-.;<=>[]^_`{|~}\x01\x7f\xff", .todo_hr = TRUE}, + {"http:// !"$%&'()*+,-.;<=>[]^_`{|~}\x01\x7f\xff:pass@host", URL_PART_USERNAME, 0, S_OK, " !"$%&'()*+,-.;<=>[]^_`{|~}\x01\x7f\xff"}, + {"http://user: !"$%&'()*+,-.;<=>[]^_`{|~}\x01\x7f\xff@host", URL_PART_PASSWORD, 0, S_OK, " !"$%&'()*+,-.;<=>[]^_`{|~}\x01\x7f\xff"}, + {"http:// !"$%&'()*+,-.;<=>[]^_`{|~}\x01\x7f\xff", URL_PART_HOSTNAME, 0, S_OK, " !"$%&'()*+,-.;<=>[]^_`{|~}\x01\x7f\xff"}, {"http://host: !"$%&'()*+,-.;<=>[]^_`{|~}\x01\x7f\xff", URL_PART_PORT, 0, S_OK, " !"$%&'()*+,-.;<=>[]^_`{|~}\x01\x7f\xff"},
{"http:///index.html", URL_PART_HOSTNAME, 0, S_FALSE, ""}, @@ -837,7 +837,7 @@ static void test_UrlGetPart(void) size = 1; wcscpy(bufferW, L"x"); hr = UrlGetPartW(urlW, bufferW, &size, part, flags); - todo_wine_if ((tests[i].todo_hr || tests[i].hr == S_FALSE) && !(strchr(url, '"') && part == URL_PART_USERNAME)) + todo_wine_if (tests[i].todo_hr || tests[i].hr == S_FALSE) { if (tests[i].hr == S_OK) ok(hr == E_POINTER, "Got hr %#x.\n", hr); @@ -880,11 +880,8 @@ static void test_UrlGetPart(void) } else { - todo_wine_if (strchr(url, '"') && part == URL_PART_USERNAME) - { - ok(size == ARRAY_SIZE(bufferW), "Got size %u.\n", size); - ok(!wcscmp(bufferW, L"x"), "Got result %s.\n", debugstr_w(bufferW)); - } + ok(size == ARRAY_SIZE(bufferW), "Got size %u.\n", size); + ok(!wcscmp(bufferW, L"x"), "Got result %s.\n", debugstr_w(bufferW)); }
winetest_pop_context();
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/kernelbase/path.c | 7 +++++-- dlls/shlwapi/tests/url.c | 6 +++--- 2 files changed, 8 insertions(+), 5 deletions(-)
diff --git a/dlls/kernelbase/path.c b/dlls/kernelbase/path.c index 823fb51a68e..d14316f05ee 100644 --- a/dlls/kernelbase/path.c +++ b/dlls/kernelbase/path.c @@ -4246,8 +4246,11 @@ static LONG parse_url(const WCHAR *url, struct parsed_url *pl) if (*work == '/') { /* see if query string */ - pl->query = wcschr(work, '?'); - if (pl->query) pl->query_len = lstrlenW(pl->query); + if ((pl->query = wcschr( work, '?' ))) + { + ++pl->query; + pl->query_len = lstrlenW(pl->query); + } } SuccessExit: TRACE("parse successful: scheme=%p(%ld), user=%p(%ld), pass=%p(%ld), host=%p(%ld), port=%p(%ld), query=%p(%ld)\n", diff --git a/dlls/shlwapi/tests/url.c b/dlls/shlwapi/tests/url.c index 18ff5021986..1b26204a94f 100644 --- a/dlls/shlwapi/tests/url.c +++ b/dlls/shlwapi/tests/url.c @@ -612,14 +612,14 @@ static void test_UrlGetPart(void) {"http://foo:bar@localhost:21/internal.php?query=x&return=y", URL_PART_PASSWORD, 0, S_OK, "bar"}, {"http://foo:bar@localhost:21/internal.php?query=x&return=y", URL_PART_HOSTNAME, 0, S_OK, "localhost"}, {"http://foo:bar@localhost:21/internal.php?query=x&return=y", URL_PART_PORT, 0, S_OK, "21"}, - {"http://foo:bar@localhost:21/internal.php?query=x&return=y", URL_PART_QUERY, 0, S_OK, "query=x&return=y", .todo_result = TRUE}, + {"http://foo:bar@localhost:21/internal.php?query=x&return=y", URL_PART_QUERY, 0, S_OK, "query=x&return=y"}, {"http://foo:bar@localhost:21/internal.php#anchor", URL_PART_QUERY, 0, S_FALSE, ""}, {"http://foo:bar@localhost:21/internal.php?query=x&return=y", URL_PART_SCHEME, URL_PARTFLAG_KEEPSCHEME, S_OK, "http"}, {"http://foo:bar@localhost:21/internal.php?query=x&return=y", URL_PART_USERNAME, URL_PARTFLAG_KEEPSCHEME, S_OK, "http:foo"}, {"http://foo:bar@localhost:21/internal.php?query=x&return=y", URL_PART_PASSWORD, URL_PARTFLAG_KEEPSCHEME, S_OK, "http:bar"}, {"http://foo:bar@localhost:21/internal.php?query=x&return=y", URL_PART_HOSTNAME, URL_PARTFLAG_KEEPSCHEME, S_OK, "http:localhost"}, {"http://foo:bar@localhost:21/internal.php?query=x&return=y", URL_PART_PORT, URL_PARTFLAG_KEEPSCHEME, S_OK, "http:21"}, - {"http://foo:bar@localhost:21/internal.php?query=x&return=y", URL_PART_QUERY, URL_PARTFLAG_KEEPSCHEME, S_OK, "query=x&return=y", .todo_result = TRUE}, + {"http://foo:bar@localhost:21/internal.php?query=x&return=y", URL_PART_QUERY, URL_PARTFLAG_KEEPSCHEME, S_OK, "query=x&return=y"},
{"http://localhost/", URL_PART_USERNAME, 0, E_INVALIDARG, .todo_hr = TRUE}, {"http://localhost/", URL_PART_PASSWORD, 0, E_INVALIDARG, .todo_hr = TRUE}, @@ -688,7 +688,7 @@ static void test_UrlGetPart(void) {"file://foo:bar@localhost:21/file?query=x", URL_PART_PASSWORD, 0, E_FAIL, .todo_hr = TRUE}, {"file://foo:bar@localhost:21/file?query=x", URL_PART_HOSTNAME, 0, S_OK, "foo:bar@localhost:21", .todo_result = TRUE}, {"file://foo:bar@localhost:21/file?query=x", URL_PART_PORT, 0, E_FAIL, .todo_hr = TRUE}, - {"file://foo:bar@localhost:21/file?query=x", URL_PART_QUERY, 0, S_OK, "query=x", .todo_result = TRUE}, + {"file://foo:bar@localhost:21/file?query=x", URL_PART_QUERY, 0, S_OK, "query=x"}, {"http://user:pass 123@www.wine hq.org", URL_PART_HOSTNAME, 0, S_OK, "www.wine hq.org"}, {"http://user:pass 123@www.wine hq.org", URL_PART_PASSWORD, 0, S_OK, "pass 123"}, {"about:blank", URL_PART_SCHEME, 0, S_OK, "about"},