1 /* Unit test suite for Path functions
3 * Copyright 2002 Matthew Mastracci
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 #include "wine/test.h"
28 #include "wine/unicode.h"
33 static HMODULE hShlwapi;
34 static HRESULT (WINAPI *pPathIsValidCharA)(char,DWORD);
35 static HRESULT (WINAPI *pPathIsValidCharW)(WCHAR,DWORD);
37 const char* TEST_URL_1 = "http://www.winehq.org/tests?date=10/10/1923";
38 const char* TEST_URL_2 = "http://localhost:8080/tests%2e.html?date=Mon%2010/10/1923";
39 const char* TEST_URL_3 = "http://foo:bar@localhost:21/internal.php?query=x&return=y";
41 typedef struct _TEST_URL_CANONICALIZE {
46 } TEST_URL_CANONICALIZE;
48 const TEST_URL_CANONICALIZE TEST_CANONICALIZE[] = {
49 /*FIXME {"http://www.winehq.org/tests/../tests/../..", 0, S_OK, "http://www.winehq.org/"},*/
50 {"http://www.winehq.org/tests/../tests", 0, S_OK, "http://www.winehq.org/tests"},
51 {"http://www.winehq.org/tests\n", URL_WININET_COMPATIBILITY|URL_ESCAPE_SPACES_ONLY|URL_ESCAPE_UNSAFE, S_OK, "http://www.winehq.org/tests"},
52 {"http://www.winehq.org/tests\r", URL_WININET_COMPATIBILITY|URL_ESCAPE_SPACES_ONLY|URL_ESCAPE_UNSAFE, S_OK, "http://www.winehq.org/tests"},
53 {"http://www.winehq.org/tests\r", 0, S_OK, "http://www.winehq.org/tests"},
54 {"http://www.winehq.org/tests\r", URL_DONT_SIMPLIFY, S_OK, "http://www.winehq.org/tests"},
55 {"http://www.winehq.org/tests/../tests/", 0, S_OK, "http://www.winehq.org/tests/"},
56 {"http://www.winehq.org/tests/../tests/..", 0, S_OK, "http://www.winehq.org/"},
57 {"http://www.winehq.org/tests/../tests/../", 0, S_OK, "http://www.winehq.org/"},
58 {"http://www.winehq.org/tests/..", 0, S_OK, "http://www.winehq.org/"},
59 {"http://www.winehq.org/tests/../", 0, S_OK, "http://www.winehq.org/"},
60 {"http://www.winehq.org/tests/..?query=x&return=y", 0, S_OK, "http://www.winehq.org/?query=x&return=y"},
61 {"http://www.winehq.org/tests/../?query=x&return=y", 0, S_OK, "http://www.winehq.org/?query=x&return=y"},
62 {"http://www.winehq.org/tests/..#example", 0, S_OK, "http://www.winehq.org/#example"},
63 {"http://www.winehq.org/tests/../#example", 0, S_OK, "http://www.winehq.org/#example"},
64 {"http://www.winehq.org/tests/../#example", URL_DONT_SIMPLIFY, S_OK, "http://www.winehq.org/tests/../#example"},
67 typedef struct _TEST_URL_ESCAPE {
75 const TEST_URL_ESCAPE TEST_ESCAPE[] = {
76 {"http://www.winehq.org/tests0", 0, 0, S_OK, "http://www.winehq.org/tests0"},
77 {"http://www.winehq.org/tests1\n", 0, 0, S_OK, "http://www.winehq.org/tests1%0A"},
78 {"http://www.winehq.org/tests2\r", 0, 0, S_OK, "http://www.winehq.org/tests2%0D"},
79 {"http://www.winehq.org/tests3\r", URL_ESCAPE_SPACES_ONLY|URL_ESCAPE_UNSAFE, 0, S_OK, "http://www.winehq.org/tests3\r"},
80 {"http://www.winehq.org/tests4\r", URL_ESCAPE_SPACES_ONLY, 0, S_OK, "http://www.winehq.org/tests4\r"},
81 {"http://www.winehq.org/tests5\r", URL_WININET_COMPATIBILITY|URL_ESCAPE_SPACES_ONLY, 0, S_OK, "http://www.winehq.org/tests5\r"},
82 {"/direct/swhelp/series6/6.2i_latestservicepack.dat\r", URL_ESCAPE_SPACES_ONLY, 0, S_OK, "/direct/swhelp/series6/6.2i_latestservicepack.dat\r"},
84 {"file://////foo/bar\\baz", 0, 0, S_OK, "file://foo/bar/baz"},
85 {"file://///foo/bar\\baz", 0, 0, S_OK, "file://foo/bar/baz"},
86 {"file:////foo/bar\\baz", 0, 0, S_OK, "file://foo/bar/baz"},
87 {"file:///localhost/foo/bar\\baz", 0, 0, S_OK, "file:///localhost/foo/bar/baz"},
88 {"file:///foo/bar\\baz", 0, 0, S_OK, "file:///foo/bar/baz"},
89 {"file://loCalHost/foo/bar\\baz", 0, 0, S_OK, "file:///foo/bar/baz"},
90 {"file://foo/bar\\baz", 0, 0, S_OK, "file://foo/bar/baz"},
91 {"file:/localhost/foo/bar\\baz", 0, 0, S_OK, "file:///localhost/foo/bar/baz"},
92 {"file:/foo/bar\\baz", 0, 0, S_OK, "file:///foo/bar/baz"},
93 {"file:foo/bar\\baz", 0, 0, S_OK, "file:foo/bar/baz"},
94 {"file:\\foo/bar\\baz", 0, 0, S_OK, "file:///foo/bar/baz"},
95 {"file:\\\\foo/bar\\baz", 0, 0, S_OK, "file://foo/bar/baz"},
96 {"file:\\\\\\foo/bar\\baz", 0, 0, S_OK, "file:///foo/bar/baz"},
97 {"file:\\\\localhost\\foo/bar\\baz", 0, 0, S_OK, "file:///foo/bar/baz"},
98 {"file:///f oo/b?a r\\baz", 0, 0, S_OK, "file:///f%20oo/b?a r\\baz"},
99 {"file:///foo/b#a r\\baz", 0, 0, S_OK, "file:///foo/b%23a%20r/baz"},
100 {"file:///f o^&`{}|][\"<>\\%o/b#a r\\baz", 0, 0, S_OK, "file:///f%20o%5E%26%60%7B%7D%7C%5D%5B%22%3C%3E/%o/b%23a%20r/baz"},
101 {"file:///f o%o/b?a r\\b%az", URL_ESCAPE_PERCENT, 0, S_OK, "file:///f%20o%25o/b?a r\\b%az"},
102 {"file:/foo/bar\\baz", URL_ESCAPE_SEGMENT_ONLY, 0, S_OK, "file:%2Ffoo%2Fbar%5Cbaz"},
104 {"foo/b%ar\\ba?z\\", URL_ESCAPE_SEGMENT_ONLY, 0, S_OK, "foo%2Fb%ar%5Cba%3Fz%5C"},
105 {"foo/b%ar\\ba?z\\", URL_ESCAPE_PERCENT | URL_ESCAPE_SEGMENT_ONLY, 0, S_OK, "foo%2Fb%25ar%5Cba%3Fz%5C"},
106 {"foo/bar\\ba?z\\", 0, 0, S_OK, "foo/bar%5Cba?z\\"},
107 {"/foo/bar\\ba?z\\", 0, 0, S_OK, "/foo/bar%5Cba?z\\"},
108 {"/foo/bar\\ba#z\\", 0, 0, S_OK, "/foo/bar%5Cba#z\\"},
109 {"/foo/%5C", 0, 0, S_OK, "/foo/%5C"},
110 {"/foo/%5C", URL_ESCAPE_PERCENT, 0, S_OK, "/foo/%255C"},
112 {"http://////foo/bar\\baz", 0, 0, S_OK, "http://////foo/bar/baz"},
113 {"http://///foo/bar\\baz", 0, 0, S_OK, "http://///foo/bar/baz"},
114 {"http:////foo/bar\\baz", 0, 0, S_OK, "http:////foo/bar/baz"},
115 {"http:///foo/bar\\baz", 0, 0, S_OK, "http:///foo/bar/baz"},
116 {"http://localhost/foo/bar\\baz", 0, 0, S_OK, "http://localhost/foo/bar/baz"},
117 {"http://foo/bar\\baz", 0, 0, S_OK, "http://foo/bar/baz"},
118 {"http:/foo/bar\\baz", 0, 0, S_OK, "http:/foo/bar/baz"},
119 {"http:foo/bar\\ba?z\\", 0, 0, S_OK, "http:foo%2Fbar%2Fba?z\\"},
120 {"http:foo/bar\\ba#z\\", 0, 0, S_OK, "http:foo%2Fbar%2Fba#z\\"},
121 {"http:\\foo/bar\\baz", 0, 0, S_OK, "http:/foo/bar/baz"},
122 {"http:\\\\foo/bar\\baz", 0, 0, S_OK, "http://foo/bar/baz"},
123 {"http:\\\\\\foo/bar\\baz", 0, 0, S_OK, "http:///foo/bar/baz"},
124 {"http:\\\\\\\\foo/bar\\baz", 0, 0, S_OK, "http:////foo/bar/baz"},
125 {"http:/fo ?o/b ar\\baz", 0, 0, S_OK, "http:/fo%20?o/b ar\\baz"},
126 {"http:fo ?o/b ar\\baz", 0, 0, S_OK, "http:fo%20?o/b ar\\baz"},
127 {"http:/foo/bar\\baz", URL_ESCAPE_SEGMENT_ONLY, 0, S_OK, "http:%2Ffoo%2Fbar%5Cbaz"},
129 {"https://foo/bar\\baz", 0, 0, S_OK, "https://foo/bar/baz"},
130 {"https:/foo/bar\\baz", 0, 0, S_OK, "https:/foo/bar/baz"},
131 {"https:\\foo/bar\\baz", 0, 0, S_OK, "https:/foo/bar/baz"},
133 {"foo:////foo/bar\\baz", 0, 0, S_OK, "foo:////foo/bar%5Cbaz"},
134 {"foo:///foo/bar\\baz", 0, 0, S_OK, "foo:///foo/bar%5Cbaz"},
135 {"foo://localhost/foo/bar\\baz", 0, 0, S_OK, "foo://localhost/foo/bar%5Cbaz"},
136 {"foo://foo/bar\\baz", 0, 0, S_OK, "foo://foo/bar%5Cbaz"},
137 {"foo:/foo/bar\\baz", 0, 0, S_OK, "foo:/foo/bar%5Cbaz"},
138 {"foo:foo/bar\\baz", 0, 0, S_OK, "foo:foo%2Fbar%5Cbaz"},
139 {"foo:\\foo/bar\\baz", 0, 0, S_OK, "foo:%5Cfoo%2Fbar%5Cbaz"},
140 {"foo:/foo/bar\\ba?\\z", 0, 0, S_OK, "foo:/foo/bar%5Cba?\\z"},
141 {"foo:/foo/bar\\ba#\\z", 0, 0, S_OK, "foo:/foo/bar%5Cba#\\z"},
143 {"mailto:/fo/o@b\\%a?\\r.b#\\az", 0, 0, S_OK, "mailto:%2Ffo%2Fo@b%5C%a%3F%5Cr.b%23%5Caz"},
144 {"mailto:fo/o@b\\%a?\\r.b#\\az", 0, 0, S_OK, "mailto:fo%2Fo@b%5C%a%3F%5Cr.b%23%5Caz"},
145 {"mailto:fo/o@b\\%a?\\r.b#\\az", URL_ESCAPE_PERCENT, 0, S_OK, "mailto:fo%2Fo@b%5C%25a%3F%5Cr.b%23%5Caz"},
147 {"ftp:fo/o@bar.baz/foo/bar", 0, 0, S_OK, "ftp:fo%2Fo@bar.baz%2Ffoo%2Fbar"},
148 {"ftp:/fo/o@bar.baz/foo/bar", 0, 0, S_OK, "ftp:/fo/o@bar.baz/foo/bar"},
149 {"ftp://fo/o@bar.baz/fo?o\\bar", 0, 0, S_OK, "ftp://fo/o@bar.baz/fo?o\\bar"},
150 {"ftp://fo/o@bar.baz/fo#o\\bar", 0, 0, S_OK, "ftp://fo/o@bar.baz/fo#o\\bar"},
151 {"ftp://localhost/o@bar.baz/fo#o\\bar", 0, 0, S_OK, "ftp://localhost/o@bar.baz/fo#o\\bar"},
152 {"ftp:///fo/o@bar.baz/foo/bar", 0, 0, S_OK, "ftp:///fo/o@bar.baz/foo/bar"},
153 {"ftp:////fo/o@bar.baz/foo/bar", 0, 0, S_OK, "ftp:////fo/o@bar.baz/foo/bar"}
156 typedef struct _TEST_URL_COMBINE {
164 const TEST_URL_COMBINE TEST_COMBINE[] = {
165 {"http://www.winehq.org/tests", "tests1", 0, S_OK, "http://www.winehq.org/tests1"},
166 /*FIXME {"http://www.winehq.org/tests", "../tests2", 0, S_OK, "http://www.winehq.org/tests2"},*/
167 {"http://www.winehq.org/tests/", "../tests3", 0, S_OK, "http://www.winehq.org/tests3"},
168 {"http://www.winehq.org/tests/../tests", "tests4", 0, S_OK, "http://www.winehq.org/tests4"},
169 {"http://www.winehq.org/tests/../tests/", "tests5", 0, S_OK, "http://www.winehq.org/tests/tests5"},
170 {"http://www.winehq.org/tests/../tests/", "/tests6/..", 0, S_OK, "http://www.winehq.org/"},
171 {"http://www.winehq.org/tests/../tests/..", "tests7/..", 0, S_OK, "http://www.winehq.org/"},
172 {"http://www.winehq.org/tests/?query=x&return=y", "tests8", 0, S_OK, "http://www.winehq.org/tests/tests8"},
173 {"http://www.winehq.org/tests/#example", "tests9", 0, S_OK, "http://www.winehq.org/tests/tests9"},
174 {"http://www.winehq.org/tests/../tests/", "/tests10/..", URL_DONT_SIMPLIFY, S_OK, "http://www.winehq.org/tests10/.."},
175 {"http://www.winehq.org/tests/../", "tests11", URL_DONT_SIMPLIFY, S_OK, "http://www.winehq.org/tests/../tests11"},
182 } TEST_URLFROMPATH [] = {
183 {"foo", "file:foo", S_OK},
184 {"foo\\bar", "file:foo/bar", S_OK},
185 {"\\foo\\bar", "file:///foo/bar", S_OK},
186 {"c:\\foo\\bar", "file:///c:/foo/bar", S_OK},
187 {"c:foo\\bar", "file:///c:foo/bar", S_OK},
188 {"c:\\foo/b a%r", "file:///c:/foo/b%20a%25r", S_OK},
190 /* The following test fails on native shlwapi as distributed with Win95/98.
191 * Wine matches the behaviour of later versions.
193 {"xx:c:\\foo\\bar", "xx:c:\\foo\\bar", S_FALSE}
201 } TEST_PATHFROMURL[] = {
202 {"file:///c:/foo/ba%5Cr", "c:\\foo\\ba\\r", S_OK},
203 {"file:///c:/foo/../ba%5Cr", "c:\\foo\\..\\ba\\r", S_OK},
204 {"file:///host/c:/foo/bar", "\\host\\c:\\foo\\bar", S_OK},
205 {"file://host/c:/foo/bar", "\\\\hostc:\\foo\\bar", S_OK},
206 {"file://host/c:/foo/bar", "\\\\hostc:\\foo\\bar", S_OK},
207 {"file:\\\\host\\c:\\foo\\bar", "\\\\hostc:\\foo\\bar", S_OK},
208 {"file:\\\\host\\ca\\foo\\bar", "\\\\host\\ca\\foo\\bar", S_OK},
209 {"file:\\\\host\\c|\\foo\\bar", "\\\\hostc|\\foo\\bar", S_OK},
210 {"file:\\%5Chost\\c:\\foo\\bar", "\\\\host\\c:\\foo\\bar", S_OK},
211 {"file:\\\\host\\cx:\\foo\\bar", "\\\\host\\cx:\\foo\\bar", S_OK},
212 {"file://c:/foo/bar", "c:\\foo\\bar", S_OK},
213 {"file://c:/d:/foo/bar", "c:\\d:\\foo\\bar", S_OK},
214 {"file://c|/d|/foo/bar", "c:\\d|\\foo\\bar", S_OK},
215 {"file://host/foo/bar", "\\\\host\\foo\\bar", S_OK},
216 {"file:/foo/bar", "\\foo\\bar", S_OK},
217 {"file:/foo/bar/", "\\foo\\bar\\", S_OK},
218 {"file:foo/bar", "foo\\bar", S_OK},
219 {"file:c:/foo/bar", "c:\\foo\\bar", S_OK},
220 {"file:c|/foo/bar", "c:\\foo\\bar", S_OK},
221 {"file:cx|/foo/bar", "cx|\\foo\\bar", S_OK},
222 {"file:////c:/foo/bar", "c:\\foo\\bar", S_OK},
224 {"c:\\foo\\bar", NULL, E_INVALIDARG},
225 {"foo/bar", NULL, E_INVALIDARG},
226 {"http://foo/bar", NULL, E_INVALIDARG},
233 } TEST_URL_UNESCAPE[] = {
234 {"file://foo/bar", "file://foo/bar"},
235 {"file://fo%20o%5Ca/bar", "file://fo o\\a/bar"}
242 } TEST_PATH_IS_URL[] = {
243 {"http://foo/bar", TRUE},
244 {"c:\\foo\\bar", FALSE},
245 {"foo://foo/bar", TRUE},
248 {"bogusscheme:", TRUE},
249 {"http:partial", TRUE}
256 } TEST_URLIS_ATTRIBS[] = {
257 { "ftp:", FALSE, FALSE },
258 { "http:", FALSE, FALSE },
259 { "gopher:", FALSE, FALSE },
260 { "mailto:", TRUE, FALSE },
261 { "news:", FALSE, FALSE },
262 { "nntp:", FALSE, FALSE },
263 { "telnet:", FALSE, FALSE },
264 { "wais:", FALSE, FALSE },
265 { "file:", FALSE, TRUE },
266 { "mk:", FALSE, FALSE },
267 { "https:", FALSE, FALSE },
268 { "shell:", TRUE, FALSE },
269 { "https:", FALSE, FALSE },
270 { "snews:", FALSE, FALSE },
271 { "local:", FALSE, FALSE },
272 { "javascript:", TRUE, FALSE },
273 { "vbscript:", TRUE, FALSE },
274 { "about:", TRUE, FALSE },
275 { "res:", FALSE, FALSE },
276 { "bogusscheme:", FALSE, FALSE },
277 { "file:\\\\e:\\b\\c", FALSE, TRUE },
278 { "file://e:/b/c", FALSE, TRUE },
279 { "http:partial", FALSE, FALSE },
280 { "mailto://www.winehq.org/test.html", TRUE, FALSE },
281 { "file:partial", FALSE, TRUE }
285 static LPWSTR GetWideString(const char* szString)
287 LPWSTR wszString = (LPWSTR) HeapAlloc(GetProcessHeap(), 0,
288 (2*INTERNET_MAX_URL_LENGTH) * sizeof(WCHAR));
290 MultiByteToWideChar(0, 0, szString, -1, wszString, INTERNET_MAX_URL_LENGTH);
295 static void FreeWideString(LPWSTR wszString)
297 HeapFree(GetProcessHeap(), 0, wszString);
300 static void hash_url(const char* szUrl)
302 LPCSTR szTestUrl = szUrl;
303 LPWSTR wszTestUrl = GetWideString(szTestUrl);
305 DWORD cbSize = sizeof(DWORD);
306 DWORD dwHash1, dwHash2;
307 ok(UrlHashA(szTestUrl, (LPBYTE)&dwHash1, cbSize) == S_OK, "UrlHashA didn't return S_OK\n");
308 ok(UrlHashW(wszTestUrl, (LPBYTE)&dwHash2, cbSize) == S_OK, "UrlHashW didn't return S_OK\n");
310 FreeWideString(wszTestUrl);
312 ok(dwHash1 == dwHash2, "Hashes didn't compare\n");
315 static void test_UrlHash(void)
317 hash_url(TEST_URL_1);
318 hash_url(TEST_URL_2);
319 hash_url(TEST_URL_3);
322 static void test_url_part(const char* szUrl, DWORD dwPart, DWORD dwFlags, const char* szExpected)
324 CHAR szPart[INTERNET_MAX_URL_LENGTH];
325 WCHAR wszPart[INTERNET_MAX_URL_LENGTH];
326 LPWSTR wszUrl = GetWideString(szUrl);
327 LPWSTR wszConvertedPart;
331 dwSize = INTERNET_MAX_URL_LENGTH;
332 ok( UrlGetPartA(szUrl, szPart, &dwSize, dwPart, dwFlags) == S_OK, "UrlGetPartA for \"%s\" part 0x%08lx didn't return S_OK but \"%s\"\n", szUrl, dwPart, szPart);
333 dwSize = INTERNET_MAX_URL_LENGTH;
334 ok( UrlGetPartW(wszUrl, wszPart, &dwSize, dwPart, dwFlags) == S_OK, "UrlGetPartW didn't return S_OK\n" );
336 wszConvertedPart = GetWideString(szPart);
338 ok(strcmpW(wszPart,wszConvertedPart)==0, "Strings didn't match between ascii and unicode UrlGetPart!\n");
340 FreeWideString(wszUrl);
341 FreeWideString(wszConvertedPart);
343 /* Note that v6.0 and later don't return '?' with the query */
344 ok(strcmp(szPart,szExpected)==0 ||
345 (*szExpected=='?' && !strcmp(szPart,szExpected+1)),
346 "Expected %s, but got %s\n", szExpected, szPart);
349 static void test_UrlGetPart(void)
351 test_url_part(TEST_URL_3, URL_PART_HOSTNAME, 0, "localhost");
352 test_url_part(TEST_URL_3, URL_PART_PORT, 0, "21");
353 test_url_part(TEST_URL_3, URL_PART_USERNAME, 0, "foo");
354 test_url_part(TEST_URL_3, URL_PART_PASSWORD, 0, "bar");
355 test_url_part(TEST_URL_3, URL_PART_SCHEME, 0, "http");
356 test_url_part(TEST_URL_3, URL_PART_QUERY, 0, "?query=x&return=y");
359 static void test_url_escape(const char *szUrl, DWORD dwFlags, HRESULT dwExpectReturn, const char *szExpectUrl)
361 CHAR szReturnUrl[INTERNET_MAX_URL_LENGTH];
363 WCHAR ret_urlW[INTERNET_MAX_URL_LENGTH];
364 WCHAR *urlW, *expected_urlW;
365 dwEscaped=INTERNET_MAX_URL_LENGTH;
367 ok(UrlEscapeA(szUrl, szReturnUrl, &dwEscaped, dwFlags) == dwExpectReturn, "UrlEscapeA didn't return 0x%08lx from \"%s\"\n", dwExpectReturn, szUrl);
368 ok(strcmp(szReturnUrl,szExpectUrl)==0, "Expected \"%s\", but got \"%s\" from \"%s\"\n", szExpectUrl, szReturnUrl, szUrl);
370 dwEscaped = INTERNET_MAX_URL_LENGTH;
371 urlW = GetWideString(szUrl);
372 expected_urlW = GetWideString(szExpectUrl);
373 ok(UrlEscapeW(urlW, ret_urlW, &dwEscaped, dwFlags) == dwExpectReturn, "UrlEscapeW didn't return 0x%08lx from \"%s\"\n", dwExpectReturn, szUrl);
374 WideCharToMultiByte(CP_ACP,0,ret_urlW,-1,szReturnUrl,INTERNET_MAX_URL_LENGTH,0,0);
375 ok(strcmpW(ret_urlW, expected_urlW)==0, "Expected \"%s\", but got \"%s\" from \"%s\" flags %08lx\n", szExpectUrl, szReturnUrl, szUrl, dwFlags);
376 FreeWideString(urlW);
377 FreeWideString(expected_urlW);
381 static void test_url_canonicalize(const char *szUrl, DWORD dwFlags, HRESULT dwExpectReturn, const char *szExpectUrl)
383 CHAR szReturnUrl[INTERNET_MAX_URL_LENGTH];
384 WCHAR wszReturnUrl[INTERNET_MAX_URL_LENGTH];
385 LPWSTR wszUrl = GetWideString(szUrl);
386 LPWSTR wszExpectUrl = GetWideString(szExpectUrl);
387 LPWSTR wszConvertedUrl;
391 dwSize = INTERNET_MAX_URL_LENGTH;
392 ok(UrlCanonicalizeA(szUrl, szReturnUrl, &dwSize, dwFlags) == dwExpectReturn, "UrlCanonicalizeA didn't return 0x%08lx\n", dwExpectReturn);
393 ok(strcmp(szReturnUrl,szExpectUrl)==0, "Expected %s, but got %s\n", szExpectUrl, szReturnUrl);
395 dwSize = INTERNET_MAX_URL_LENGTH;
396 ok(UrlCanonicalizeW(wszUrl, wszReturnUrl, &dwSize, dwFlags) == dwExpectReturn, "UrlCanonicalizeW didn't return 0x%08lx\n", dwExpectReturn);
397 wszConvertedUrl = GetWideString(szReturnUrl);
398 ok(strcmpW(wszReturnUrl, wszConvertedUrl)==0, "Strings didn't match between ascii and unicode UrlCanonicalize!\n");
399 FreeWideString(wszConvertedUrl);
402 FreeWideString(wszUrl);
403 FreeWideString(wszExpectUrl);
407 static void test_UrlEscape(void)
410 for(i=0; i<sizeof(TEST_ESCAPE)/sizeof(TEST_ESCAPE[0]); i++) {
411 test_url_escape(TEST_ESCAPE[i].url, TEST_ESCAPE[i].flags,
412 TEST_ESCAPE[i].expectret, TEST_ESCAPE[i].expecturl);
416 static void test_UrlCanonicalize(void)
419 for(i=0; i<sizeof(TEST_CANONICALIZE)/sizeof(TEST_CANONICALIZE[0]); i++) {
420 test_url_canonicalize(TEST_CANONICALIZE[i].url, TEST_CANONICALIZE[i].flags,
421 TEST_CANONICALIZE[i].expectret, TEST_CANONICALIZE[i].expecturl);
425 static void test_url_combine(const char *szUrl1, const char *szUrl2, DWORD dwFlags, HRESULT dwExpectReturn, const char *szExpectUrl)
428 CHAR szReturnUrl[INTERNET_MAX_URL_LENGTH];
429 WCHAR wszReturnUrl[INTERNET_MAX_URL_LENGTH];
430 LPWSTR wszUrl1 = GetWideString(szUrl1);
431 LPWSTR wszUrl2 = GetWideString(szUrl2);
432 LPWSTR wszExpectUrl = GetWideString(szExpectUrl);
433 LPWSTR wszConvertedUrl;
436 DWORD dwExpectLen = lstrlen(szExpectUrl);
438 hr = UrlCombineA(szUrl1, szUrl2, NULL, NULL, dwFlags);
439 ok(hr == E_INVALIDARG, "UrlCombineA returned 0x%08lx, expected 0x%08lx\n", hr, E_INVALIDARG);
442 hr = UrlCombineA(szUrl1, szUrl2, NULL, &dwSize, dwFlags);
443 ok(hr == E_POINTER, "Checking length of string, return was 0x%08lx, expected 0x%08lx\n", hr, E_POINTER);
444 ok(dwSize == dwExpectLen+1, "Got length %ld, expected %ld\n", dwSize, dwExpectLen+1);
447 hr = UrlCombineA(szUrl1, szUrl2, szReturnUrl, &dwSize, dwFlags);
448 ok(hr == E_POINTER, "UrlCombineA returned 0x%08lx, expected 0x%08lx\n", hr, E_POINTER);
449 ok(dwSize == dwExpectLen+1, "Got length %ld, expected %ld\n", dwSize, dwExpectLen+1);
451 hr = UrlCombineA(szUrl1, szUrl2, szReturnUrl, &dwSize, dwFlags);
452 ok(hr == dwExpectReturn, "UrlCombineA returned 0x%08lx, expected 0x%08lx\n", hr, dwExpectReturn);
453 ok(dwSize == dwExpectLen, "Got length %ld, expected %ld\n", dwSize, dwExpectLen);
455 ok(strcmp(szReturnUrl,szExpectUrl)==0, "Expected %s, but got %s\n", szExpectUrl, szReturnUrl);
459 hr = UrlCombineW(wszUrl1, wszUrl2, NULL, &dwSize, dwFlags);
460 ok(hr == E_POINTER, "Checking length of string, return was 0x%08lx, expected 0x%08lx\n", hr, E_POINTER);
461 ok(dwSize == dwExpectLen+1, "Got length %ld, expected %ld\n", dwSize, dwExpectLen+1);
464 hr = UrlCombineW(wszUrl1, wszUrl2, wszReturnUrl, &dwSize, dwFlags);
465 ok(hr == E_POINTER, "UrlCombineA returned 0x%08lx, expected 0x%08lx\n", hr, E_POINTER);
466 ok(dwSize == dwExpectLen+1, "Got length %ld, expected %ld\n", dwSize, dwExpectLen+1);
468 hr = UrlCombineW(wszUrl1, wszUrl2, wszReturnUrl, &dwSize, dwFlags);
469 ok(hr == dwExpectReturn, "UrlCombineW returned 0x%08lx, expected 0x%08lx\n", hr, dwExpectReturn);
470 ok(dwSize == dwExpectLen, "Got length %ld, expected %ld\n", dwSize, dwExpectLen);
472 wszConvertedUrl = GetWideString(szReturnUrl);
473 ok(strcmpW(wszReturnUrl, wszConvertedUrl)==0, "Strings didn't match between ascii and unicode UrlCombine!\n");
474 FreeWideString(wszConvertedUrl);
477 FreeWideString(wszUrl1);
478 FreeWideString(wszUrl2);
479 FreeWideString(wszExpectUrl);
482 static void test_UrlCombine(void)
485 for(i=0; i<sizeof(TEST_COMBINE)/sizeof(TEST_COMBINE[0]); i++) {
486 test_url_combine(TEST_COMBINE[i].url1, TEST_COMBINE[i].url2, TEST_COMBINE[i].flags,
487 TEST_COMBINE[i].expectret, TEST_COMBINE[i].expecturl);
491 static void test_UrlCreateFromPath(void)
494 char ret_url[INTERNET_MAX_URL_LENGTH];
496 WCHAR ret_urlW[INTERNET_MAX_URL_LENGTH];
499 for(i = 0; i < sizeof(TEST_URLFROMPATH) / sizeof(TEST_URLFROMPATH[0]); i++) {
500 len = INTERNET_MAX_URL_LENGTH;
501 ret = UrlCreateFromPathA(TEST_URLFROMPATH[i].path, ret_url, &len, 0);
502 ok(ret == TEST_URLFROMPATH[i].ret, "ret %08lx from path %s\n", ret, TEST_URLFROMPATH[i].path);
503 ok(!lstrcmpi(ret_url, TEST_URLFROMPATH[i].url), "url %s from path %s\n", ret_url, TEST_URLFROMPATH[i].path);
504 ok(len == strlen(ret_url), "ret len %ld from path %s\n", len, TEST_URLFROMPATH[i].path);
506 len = INTERNET_MAX_URL_LENGTH;
507 pathW = GetWideString(TEST_URLFROMPATH[i].path);
508 urlW = GetWideString(TEST_URLFROMPATH[i].url);
509 ret = UrlCreateFromPathW(pathW, ret_urlW, &len, 0);
510 WideCharToMultiByte(CP_ACP, 0, ret_urlW, -1, ret_url, sizeof(ret_url),0,0);
511 ok(ret == TEST_URLFROMPATH[i].ret, "ret %08lx from path L\"%s\", expected %08lx\n",
512 ret, TEST_URLFROMPATH[i].path, TEST_URLFROMPATH[i].ret);
513 ok(!lstrcmpiW(ret_urlW, urlW), "got %s expected %s from path L\"%s\"\n", ret_url, TEST_URLFROMPATH[i].url, TEST_URLFROMPATH[i].path);
514 ok(len == strlenW(ret_urlW), "ret len %ld from path L\"%s\"\n", len, TEST_URLFROMPATH[i].path);
515 FreeWideString(urlW);
516 FreeWideString(pathW);
520 static void test_UrlIs(void)
526 for(i = 0; i < sizeof(TEST_PATH_IS_URL) / sizeof(TEST_PATH_IS_URL[0]); i++) {
527 MultiByteToWideChar(CP_ACP, 0, TEST_PATH_IS_URL[i].path, -1, wurl, 80);
529 ret = UrlIsA( TEST_PATH_IS_URL[i].path, URLIS_URL );
530 ok( ret == TEST_PATH_IS_URL[i].expect,
531 "returned %d from path %s, expected %d\n", ret, TEST_PATH_IS_URL[i].path,
532 TEST_PATH_IS_URL[i].expect );
534 ret = UrlIsW( wurl, URLIS_URL );
535 ok( ret == TEST_PATH_IS_URL[i].expect,
536 "returned %d from path (UrlIsW) %s, expected %d\n", ret, TEST_PATH_IS_URL[i].path,
537 TEST_PATH_IS_URL[i].expect );
539 for(i = 0; i < sizeof(TEST_URLIS_ATTRIBS) / sizeof(TEST_URLIS_ATTRIBS[0]); i++) {
540 MultiByteToWideChar(CP_ACP, 0, TEST_URLIS_ATTRIBS[i].url, -1, wurl, 80);
542 ret = UrlIsA( TEST_URLIS_ATTRIBS[i].url, URLIS_OPAQUE);
543 ok( ret == TEST_URLIS_ATTRIBS[i].expectOpaque,
544 "returned %d for URLIS_OPAQUE, url \"%s\", expected %d\n", ret, TEST_URLIS_ATTRIBS[i].url,
545 TEST_URLIS_ATTRIBS[i].expectOpaque );
546 ret = UrlIsA( TEST_URLIS_ATTRIBS[i].url, URLIS_FILEURL);
547 ok( ret == TEST_URLIS_ATTRIBS[i].expectFile,
548 "returned %d for URLIS_FILEURL, url \"%s\", expected %d\n", ret, TEST_URLIS_ATTRIBS[i].url,
549 TEST_URLIS_ATTRIBS[i].expectFile );
551 ret = UrlIsW( wurl, URLIS_OPAQUE);
552 ok( ret == TEST_URLIS_ATTRIBS[i].expectOpaque,
553 "returned %d for URLIS_OPAQUE (UrlIsW), url \"%s\", expected %d\n", ret, TEST_URLIS_ATTRIBS[i].url,
554 TEST_URLIS_ATTRIBS[i].expectOpaque );
555 ret = UrlIsW( wurl, URLIS_FILEURL);
556 ok( ret == TEST_URLIS_ATTRIBS[i].expectFile,
557 "returned %d for URLIS_FILEURL (UrlIsW), url \"%s\", expected %d\n", ret, TEST_URLIS_ATTRIBS[i].url,
558 TEST_URLIS_ATTRIBS[i].expectFile );
562 static void test_UrlUnescape(void)
564 CHAR szReturnUrl[INTERNET_MAX_URL_LENGTH];
565 WCHAR ret_urlW[INTERNET_MAX_URL_LENGTH];
566 WCHAR *urlW, *expected_urlW;
570 for(i=0; i<sizeof(TEST_URL_UNESCAPE)/sizeof(TEST_URL_UNESCAPE[0]); i++) {
571 dwEscaped=INTERNET_MAX_URL_LENGTH;
572 ok(UrlUnescapeA(TEST_URL_UNESCAPE[i].url, szReturnUrl, &dwEscaped, 0) == S_OK, "UrlEscapeA didn't return 0x%08lx from \"%s\"\n", S_OK, TEST_URL_UNESCAPE[i].url);
573 ok(strcmp(szReturnUrl,TEST_URL_UNESCAPE[i].expect)==0, "Expected \"%s\", but got \"%s\" from \"%s\"\n", TEST_URL_UNESCAPE[i].expect, szReturnUrl, TEST_URL_UNESCAPE[i].url);
575 dwEscaped = INTERNET_MAX_URL_LENGTH;
576 urlW = GetWideString(TEST_URL_UNESCAPE[i].url);
577 expected_urlW = GetWideString(TEST_URL_UNESCAPE[i].expect);
578 ok(UrlUnescapeW(urlW, ret_urlW, &dwEscaped, 0) == S_OK, "UrlEscapeW didn't return 0x%08lx from \"%s\"\n", S_OK, TEST_URL_UNESCAPE[i].url);
579 WideCharToMultiByte(CP_ACP,0,ret_urlW,-1,szReturnUrl,INTERNET_MAX_URL_LENGTH,0,0);
580 ok(strcmpW(ret_urlW, expected_urlW)==0, "Expected \"%s\", but got \"%s\" from \"%s\" flags %08lx\n", TEST_URL_UNESCAPE[i].expect, szReturnUrl, TEST_URL_UNESCAPE[i].url, 0L);
581 FreeWideString(urlW);
582 FreeWideString(expected_urlW);
587 static void test_PathSearchAndQualify(void)
589 WCHAR path1[] = {'c',':','\\','f','o','o',0};
590 WCHAR expect1[] = {'c',':','\\','f','o','o',0};
591 WCHAR path2[] = {'c',':','f','o','o',0};
592 WCHAR c_drive[] = {'c',':',0};
593 WCHAR foo[] = {'f','o','o',0};
594 WCHAR path3[] = {'\\','f','o','o',0};
595 WCHAR winini[] = {'w','i','n','.','i','n','i',0};
597 WCHAR cur_dir[MAX_PATH];
598 WCHAR dot[] = {'.',0};
601 ok(PathSearchAndQualifyW(path1, out, MAX_PATH) != 0,
602 "PathSearchAndQualify rets 0\n");
603 ok(!lstrcmpiW(out, expect1), "strings don't match\n");
606 ok(PathSearchAndQualifyW(path2, out, MAX_PATH) != 0,
607 "PathSearchAndQualify rets 0\n");
608 GetFullPathNameW(c_drive, MAX_PATH, cur_dir, NULL);
609 PathAddBackslashW(cur_dir);
610 strcatW(cur_dir, foo);
611 ok(!lstrcmpiW(out, cur_dir), "strings don't match\n");
614 ok(PathSearchAndQualifyW(foo, out, MAX_PATH) != 0,
615 "PathSearchAndQualify rets 0\n");
616 GetFullPathNameW(dot, MAX_PATH, cur_dir, NULL);
617 PathAddBackslashW(cur_dir);
618 strcatW(cur_dir, foo);
619 ok(!lstrcmpiW(out, cur_dir), "strings don't match\n");
622 ok(PathSearchAndQualifyW(path3, out, MAX_PATH) != 0,
623 "PathSearchAndQualify rets 0\n");
624 GetFullPathNameW(dot, MAX_PATH, cur_dir, NULL);
625 strcpyW(cur_dir + 2, path3);
626 ok(!lstrcmpiW(out, cur_dir), "strings don't match\n");
629 ok(PathSearchAndQualifyW(winini, out, MAX_PATH) != 0,
630 "PathSearchAndQualify rets 0\n");
631 if(!SearchPathW(NULL, winini, NULL, MAX_PATH, cur_dir, NULL))
632 GetFullPathNameW(winini, MAX_PATH, cur_dir, NULL);
633 ok(!lstrcmpiW(out, cur_dir), "strings don't match\n");
637 static void test_PathCreateFromUrl(void)
640 char ret_path[INTERNET_MAX_URL_LENGTH];
642 WCHAR ret_pathW[INTERNET_MAX_URL_LENGTH];
645 for(i = 0; i < sizeof(TEST_PATHFROMURL) / sizeof(TEST_PATHFROMURL[0]); i++) {
646 len = INTERNET_MAX_URL_LENGTH;
647 ret = PathCreateFromUrlA(TEST_PATHFROMURL[i].url, ret_path, &len, 0);
648 ok(ret == TEST_PATHFROMURL[i].ret, "ret %08lx from url %s\n", ret, TEST_PATHFROMURL[i].url);
649 if(TEST_PATHFROMURL[i].path) {
650 ok(!lstrcmpi(ret_path, TEST_PATHFROMURL[i].path), "got %s expected %s from url %s\n", ret_path, TEST_PATHFROMURL[i].path, TEST_PATHFROMURL[i].url);
651 ok(len == strlen(ret_path), "ret len %ld from url %s\n", len, TEST_PATHFROMURL[i].url);
653 len = INTERNET_MAX_URL_LENGTH;
654 pathW = GetWideString(TEST_PATHFROMURL[i].path);
655 urlW = GetWideString(TEST_PATHFROMURL[i].url);
656 ret = PathCreateFromUrlW(urlW, ret_pathW, &len, 0);
657 WideCharToMultiByte(CP_ACP, 0, ret_pathW, -1, ret_path, sizeof(ret_path),0,0);
658 ok(ret == TEST_PATHFROMURL[i].ret, "ret %08lx from url L\"%s\"\n", ret, TEST_PATHFROMURL[i].url);
659 if(TEST_PATHFROMURL[i].path) {
660 ok(!lstrcmpiW(ret_pathW, pathW), "got %s expected %s from url L\"%s\"\n", ret_path, TEST_PATHFROMURL[i].path, TEST_PATHFROMURL[i].url);
661 ok(len == strlenW(ret_pathW), "ret len %ld from url L\"%s\"\n", len, TEST_PATHFROMURL[i].url);
663 FreeWideString(urlW);
664 FreeWideString(pathW);
669 static void test_PathIsUrl(void)
674 for(i = 0; i < sizeof(TEST_PATH_IS_URL)/sizeof(TEST_PATH_IS_URL[0]); i++) {
675 ret = PathIsURLA(TEST_PATH_IS_URL[i].path);
676 ok(ret == TEST_PATH_IS_URL[i].expect,
677 "returned %d from path %s, expected %d\n", ret, TEST_PATH_IS_URL[i].path,
678 TEST_PATH_IS_URL[i].expect);
682 static const DWORD SHELL_charclass[] =
684 0x00000000, 0x00000000, 0x00000000, 0x00000000,
685 0x00000000, 0x00000000, 0x00000000, 0x00000000,
686 0x00000000, 0x00000000, 0x00000000, 0x00000000,
687 0x00000000, 0x00000000, 0x00000000, 0x00000000,
688 0x00000000, 0x00000000, 0x00000000, 0x00000000,
689 0x00000000, 0x00000000, 0x00000000, 0x00000000,
690 0x00000000, 0x00000000, 0x00000000, 0x00000000,
691 0x00000000, 0x00000000, 0x00000000, 0x00000000,
692 0x00000080, 0x00000100, 0x00000200, 0x00000100,
693 0x00000100, 0x00000100, 0x00000100, 0x00000100,
694 0x00000100, 0x00000100, 0x00000002, 0x00000100,
695 0x00000040, 0x00000100, 0x00000004, 0x00000000,
696 0x00000100, 0x00000100, 0x00000100, 0x00000100,
697 0x00000100, 0x00000100, 0x00000100, 0x00000100,
698 0x00000100, 0x00000100, 0x00000010, 0x00000020,
699 0x00000000, 0x00000100, 0x00000000, 0x00000001,
700 0x00000100, 0xffffffff, 0xffffffff, 0xffffffff,
701 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
702 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
703 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
704 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
705 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
706 0xffffffff, 0xffffffff, 0xffffffff, 0x00000100,
707 0x00000008, 0x00000100, 0x00000100, 0x00000100,
708 0x00000100, 0xffffffff, 0xffffffff, 0xffffffff,
709 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
710 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
711 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
712 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
713 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
714 0xffffffff, 0xffffffff, 0xffffffff, 0x00000100,
715 0x00000000, 0x00000100, 0x00000100
718 static void test_PathIsValidCharA(void)
723 ret = pPathIsValidCharA( 0x7f, 0 );
724 ok ( !ret, "PathIsValidCharA succeeded: 0x%08lx\n", (DWORD)ret );
726 ret = pPathIsValidCharA( 0x7f, 1 );
727 ok ( !ret, "PathIsValidCharA succeeded: 0x%08lx\n", (DWORD)ret );
729 for (c = 0; c < 0x7f; c++)
731 ret = pPathIsValidCharA( c, ~0U );
732 ok ( ret == SHELL_charclass[c] || (ret == 1 && SHELL_charclass[c] == 0xffffffff),
733 "PathIsValidCharA failed: 0x%02x got 0x%08lx expected 0x%08lx\n",
734 c, (DWORD)ret, SHELL_charclass[c] );
737 for (c = 0x7f; c <= 0xff; c++)
739 ret = pPathIsValidCharA( c, ~0U );
740 ok ( ret == 0x00000100,
741 "PathIsValidCharA failed: 0x%02x got 0x%08lx expected 0x00000100\n",
746 static void test_PathIsValidCharW(void)
751 ret = pPathIsValidCharW( 0x7f, 0 );
752 ok ( !ret, "PathIsValidCharW succeeded: 0x%08lx\n", (DWORD)ret );
754 ret = pPathIsValidCharW( 0x7f, 1 );
755 ok ( !ret, "PathIsValidCharW succeeded: 0x%08lx\n", (DWORD)ret );
757 for (c = 0; c < 0x7f; c++)
759 ret = pPathIsValidCharW( c, ~0U );
760 ok ( ret == SHELL_charclass[c] || (ret == 1 && SHELL_charclass[c] == 0xffffffff),
761 "PathIsValidCharW failed: 0x%02x got 0x%08lx expected 0x%08lx\n",
762 c, (DWORD)ret, SHELL_charclass[c] );
765 for (c = 0x007f; c <= 0xffff; c++)
767 ret = pPathIsValidCharW( c, ~0U );
768 ok ( ret == 0x00000100,
769 "PathIsValidCharW failed: 0x%02x got 0x%08lx expected 0x00000100\n",
774 static void test_PathMakePretty(void)
778 ok (PathMakePrettyA(NULL) == FALSE, "PathMakePretty: NULL path succeeded\n");
780 ok (PathMakePrettyA(buff) == TRUE, "PathMakePretty: Empty path failed\n");
782 strcpy(buff, "C:\\A LONG FILE NAME WITH \\SPACES.TXT");
783 ok (PathMakePrettyA(buff) == TRUE, "PathMakePretty: Long UC name failed\n");
784 ok (strcmp(buff, "C:\\a long file name with \\spaces.txt") == 0,
785 "PathMakePretty: Long UC name not changed\n");
787 strcpy(buff, "C:\\A LONG FILE NAME WITH \\MixedCase.TXT");
788 ok (PathMakePrettyA(buff) == FALSE, "PathMakePretty: Long MC name succeeded\n");
789 ok (strcmp(buff, "C:\\A LONG FILE NAME WITH \\MixedCase.TXT") == 0,
790 "PathMakePretty: Failed but modified path\n");
792 strcpy(buff, "TEST");
793 ok (PathMakePrettyA(buff) == TRUE, "PathMakePretty: Short name failed\n");
794 ok (strcmp(buff, "Test") == 0, "PathMakePretty: 1st char lowercased %s\n", buff);
799 hShlwapi = LoadLibraryA("shlwapi.dll");
800 if (!hShlwapi) return;
804 test_UrlCanonicalize();
807 test_UrlCreateFromPath();
811 test_PathSearchAndQualify();
812 test_PathCreateFromUrl();
815 test_PathMakePretty();
817 /* For whatever reason, PathIsValidCharA and PathAppendA share the same
818 * ordinal number in some native versions. Check this to prevent a crash.
820 pPathIsValidCharA = (void*)GetProcAddress(hShlwapi, (LPSTR)455);
821 if (pPathIsValidCharA && pPathIsValidCharA != (void*)GetProcAddress(hShlwapi, "PathAppendA"))
823 test_PathIsValidCharA();
825 pPathIsValidCharW = (void*)GetProcAddress(hShlwapi, (LPSTR)456);
826 if (pPathIsValidCharW) test_PathIsValidCharW();