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 = HeapAlloc(GetProcessHeap(), 0, (2*INTERNET_MAX_URL_LENGTH) * sizeof(WCHAR));
289 MultiByteToWideChar(0, 0, szString, -1, wszString, INTERNET_MAX_URL_LENGTH);
294 static void FreeWideString(LPWSTR wszString)
296 HeapFree(GetProcessHeap(), 0, wszString);
299 static void hash_url(const char* szUrl)
301 LPCSTR szTestUrl = szUrl;
302 LPWSTR wszTestUrl = GetWideString(szTestUrl);
304 DWORD cbSize = sizeof(DWORD);
305 DWORD dwHash1, dwHash2;
306 ok(UrlHashA(szTestUrl, (LPBYTE)&dwHash1, cbSize) == S_OK, "UrlHashA didn't return S_OK\n");
307 ok(UrlHashW(wszTestUrl, (LPBYTE)&dwHash2, cbSize) == S_OK, "UrlHashW didn't return S_OK\n");
309 FreeWideString(wszTestUrl);
311 ok(dwHash1 == dwHash2, "Hashes didn't compare\n");
314 static void test_UrlHash(void)
316 hash_url(TEST_URL_1);
317 hash_url(TEST_URL_2);
318 hash_url(TEST_URL_3);
321 static void test_url_part(const char* szUrl, DWORD dwPart, DWORD dwFlags, const char* szExpected)
323 CHAR szPart[INTERNET_MAX_URL_LENGTH];
324 WCHAR wszPart[INTERNET_MAX_URL_LENGTH];
325 LPWSTR wszUrl = GetWideString(szUrl);
326 LPWSTR wszConvertedPart;
330 dwSize = INTERNET_MAX_URL_LENGTH;
331 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);
332 dwSize = INTERNET_MAX_URL_LENGTH;
333 ok( UrlGetPartW(wszUrl, wszPart, &dwSize, dwPart, dwFlags) == S_OK, "UrlGetPartW didn't return S_OK\n" );
335 wszConvertedPart = GetWideString(szPart);
337 ok(strcmpW(wszPart,wszConvertedPart)==0, "Strings didn't match between ascii and unicode UrlGetPart!\n");
339 FreeWideString(wszUrl);
340 FreeWideString(wszConvertedPart);
342 /* Note that v6.0 and later don't return '?' with the query */
343 ok(strcmp(szPart,szExpected)==0 ||
344 (*szExpected=='?' && !strcmp(szPart,szExpected+1)),
345 "Expected %s, but got %s\n", szExpected, szPart);
348 static void test_UrlGetPart(void)
350 test_url_part(TEST_URL_3, URL_PART_HOSTNAME, 0, "localhost");
351 test_url_part(TEST_URL_3, URL_PART_PORT, 0, "21");
352 test_url_part(TEST_URL_3, URL_PART_USERNAME, 0, "foo");
353 test_url_part(TEST_URL_3, URL_PART_PASSWORD, 0, "bar");
354 test_url_part(TEST_URL_3, URL_PART_SCHEME, 0, "http");
355 test_url_part(TEST_URL_3, URL_PART_QUERY, 0, "?query=x&return=y");
358 static void test_url_escape(const char *szUrl, DWORD dwFlags, HRESULT dwExpectReturn, const char *szExpectUrl)
360 CHAR szReturnUrl[INTERNET_MAX_URL_LENGTH];
362 WCHAR ret_urlW[INTERNET_MAX_URL_LENGTH];
363 WCHAR *urlW, *expected_urlW;
364 dwEscaped=INTERNET_MAX_URL_LENGTH;
366 ok(UrlEscapeA(szUrl, szReturnUrl, &dwEscaped, dwFlags) == dwExpectReturn, "UrlEscapeA didn't return 0x%08lx from \"%s\"\n", dwExpectReturn, szUrl);
367 ok(strcmp(szReturnUrl,szExpectUrl)==0, "Expected \"%s\", but got \"%s\" from \"%s\"\n", szExpectUrl, szReturnUrl, szUrl);
369 dwEscaped = INTERNET_MAX_URL_LENGTH;
370 urlW = GetWideString(szUrl);
371 expected_urlW = GetWideString(szExpectUrl);
372 ok(UrlEscapeW(urlW, ret_urlW, &dwEscaped, dwFlags) == dwExpectReturn, "UrlEscapeW didn't return 0x%08lx from \"%s\"\n", dwExpectReturn, szUrl);
373 WideCharToMultiByte(CP_ACP,0,ret_urlW,-1,szReturnUrl,INTERNET_MAX_URL_LENGTH,0,0);
374 ok(strcmpW(ret_urlW, expected_urlW)==0, "Expected \"%s\", but got \"%s\" from \"%s\" flags %08lx\n", szExpectUrl, szReturnUrl, szUrl, dwFlags);
375 FreeWideString(urlW);
376 FreeWideString(expected_urlW);
380 static void test_url_canonicalize(const char *szUrl, DWORD dwFlags, HRESULT dwExpectReturn, const char *szExpectUrl)
382 CHAR szReturnUrl[INTERNET_MAX_URL_LENGTH];
383 WCHAR wszReturnUrl[INTERNET_MAX_URL_LENGTH];
384 LPWSTR wszUrl = GetWideString(szUrl);
385 LPWSTR wszExpectUrl = GetWideString(szExpectUrl);
386 LPWSTR wszConvertedUrl;
390 dwSize = INTERNET_MAX_URL_LENGTH;
391 ok(UrlCanonicalizeA(szUrl, szReturnUrl, &dwSize, dwFlags) == dwExpectReturn, "UrlCanonicalizeA didn't return 0x%08lx\n", dwExpectReturn);
392 ok(strcmp(szReturnUrl,szExpectUrl)==0, "Expected %s, but got %s\n", szExpectUrl, szReturnUrl);
394 dwSize = INTERNET_MAX_URL_LENGTH;
395 ok(UrlCanonicalizeW(wszUrl, wszReturnUrl, &dwSize, dwFlags) == dwExpectReturn, "UrlCanonicalizeW didn't return 0x%08lx\n", dwExpectReturn);
396 wszConvertedUrl = GetWideString(szReturnUrl);
397 ok(strcmpW(wszReturnUrl, wszConvertedUrl)==0, "Strings didn't match between ascii and unicode UrlCanonicalize!\n");
398 FreeWideString(wszConvertedUrl);
401 FreeWideString(wszUrl);
402 FreeWideString(wszExpectUrl);
406 static void test_UrlEscape(void)
409 for(i=0; i<sizeof(TEST_ESCAPE)/sizeof(TEST_ESCAPE[0]); i++) {
410 test_url_escape(TEST_ESCAPE[i].url, TEST_ESCAPE[i].flags,
411 TEST_ESCAPE[i].expectret, TEST_ESCAPE[i].expecturl);
415 static void test_UrlCanonicalize(void)
418 for(i=0; i<sizeof(TEST_CANONICALIZE)/sizeof(TEST_CANONICALIZE[0]); i++) {
419 test_url_canonicalize(TEST_CANONICALIZE[i].url, TEST_CANONICALIZE[i].flags,
420 TEST_CANONICALIZE[i].expectret, TEST_CANONICALIZE[i].expecturl);
424 static void test_url_combine(const char *szUrl1, const char *szUrl2, DWORD dwFlags, HRESULT dwExpectReturn, const char *szExpectUrl)
427 CHAR szReturnUrl[INTERNET_MAX_URL_LENGTH];
428 WCHAR wszReturnUrl[INTERNET_MAX_URL_LENGTH];
429 LPWSTR wszUrl1 = GetWideString(szUrl1);
430 LPWSTR wszUrl2 = GetWideString(szUrl2);
431 LPWSTR wszExpectUrl = GetWideString(szExpectUrl);
432 LPWSTR wszConvertedUrl;
435 DWORD dwExpectLen = lstrlen(szExpectUrl);
437 hr = UrlCombineA(szUrl1, szUrl2, NULL, NULL, dwFlags);
438 ok(hr == E_INVALIDARG, "UrlCombineA returned 0x%08lx, expected 0x%08lx\n", hr, E_INVALIDARG);
441 hr = UrlCombineA(szUrl1, szUrl2, NULL, &dwSize, dwFlags);
442 ok(hr == E_POINTER, "Checking length of string, return was 0x%08lx, expected 0x%08lx\n", hr, E_POINTER);
443 ok(dwSize == dwExpectLen+1, "Got length %ld, expected %ld\n", dwSize, dwExpectLen+1);
446 hr = UrlCombineA(szUrl1, szUrl2, szReturnUrl, &dwSize, dwFlags);
447 ok(hr == E_POINTER, "UrlCombineA returned 0x%08lx, expected 0x%08lx\n", hr, E_POINTER);
448 ok(dwSize == dwExpectLen+1, "Got length %ld, expected %ld\n", dwSize, dwExpectLen+1);
450 hr = UrlCombineA(szUrl1, szUrl2, szReturnUrl, &dwSize, dwFlags);
451 ok(hr == dwExpectReturn, "UrlCombineA returned 0x%08lx, expected 0x%08lx\n", hr, dwExpectReturn);
452 ok(dwSize == dwExpectLen, "Got length %ld, expected %ld\n", dwSize, dwExpectLen);
454 ok(strcmp(szReturnUrl,szExpectUrl)==0, "Expected %s, but got %s\n", szExpectUrl, szReturnUrl);
458 hr = UrlCombineW(wszUrl1, wszUrl2, NULL, &dwSize, dwFlags);
459 ok(hr == E_POINTER, "Checking length of string, return was 0x%08lx, expected 0x%08lx\n", hr, E_POINTER);
460 ok(dwSize == dwExpectLen+1, "Got length %ld, expected %ld\n", dwSize, dwExpectLen+1);
463 hr = UrlCombineW(wszUrl1, wszUrl2, wszReturnUrl, &dwSize, dwFlags);
464 ok(hr == E_POINTER, "UrlCombineA returned 0x%08lx, expected 0x%08lx\n", hr, E_POINTER);
465 ok(dwSize == dwExpectLen+1, "Got length %ld, expected %ld\n", dwSize, dwExpectLen+1);
467 hr = UrlCombineW(wszUrl1, wszUrl2, wszReturnUrl, &dwSize, dwFlags);
468 ok(hr == dwExpectReturn, "UrlCombineW returned 0x%08lx, expected 0x%08lx\n", hr, dwExpectReturn);
469 ok(dwSize == dwExpectLen, "Got length %ld, expected %ld\n", dwSize, dwExpectLen);
471 wszConvertedUrl = GetWideString(szReturnUrl);
472 ok(strcmpW(wszReturnUrl, wszConvertedUrl)==0, "Strings didn't match between ascii and unicode UrlCombine!\n");
473 FreeWideString(wszConvertedUrl);
476 FreeWideString(wszUrl1);
477 FreeWideString(wszUrl2);
478 FreeWideString(wszExpectUrl);
481 static void test_UrlCombine(void)
484 for(i=0; i<sizeof(TEST_COMBINE)/sizeof(TEST_COMBINE[0]); i++) {
485 test_url_combine(TEST_COMBINE[i].url1, TEST_COMBINE[i].url2, TEST_COMBINE[i].flags,
486 TEST_COMBINE[i].expectret, TEST_COMBINE[i].expecturl);
490 static void test_UrlCreateFromPath(void)
493 char ret_url[INTERNET_MAX_URL_LENGTH];
495 WCHAR ret_urlW[INTERNET_MAX_URL_LENGTH];
498 for(i = 0; i < sizeof(TEST_URLFROMPATH) / sizeof(TEST_URLFROMPATH[0]); i++) {
499 len = INTERNET_MAX_URL_LENGTH;
500 ret = UrlCreateFromPathA(TEST_URLFROMPATH[i].path, ret_url, &len, 0);
501 ok(ret == TEST_URLFROMPATH[i].ret, "ret %08lx from path %s\n", ret, TEST_URLFROMPATH[i].path);
502 ok(!lstrcmpi(ret_url, TEST_URLFROMPATH[i].url), "url %s from path %s\n", ret_url, TEST_URLFROMPATH[i].path);
503 ok(len == strlen(ret_url), "ret len %ld from path %s\n", len, TEST_URLFROMPATH[i].path);
505 len = INTERNET_MAX_URL_LENGTH;
506 pathW = GetWideString(TEST_URLFROMPATH[i].path);
507 urlW = GetWideString(TEST_URLFROMPATH[i].url);
508 ret = UrlCreateFromPathW(pathW, ret_urlW, &len, 0);
509 WideCharToMultiByte(CP_ACP, 0, ret_urlW, -1, ret_url, sizeof(ret_url),0,0);
510 ok(ret == TEST_URLFROMPATH[i].ret, "ret %08lx from path L\"%s\", expected %08lx\n",
511 ret, TEST_URLFROMPATH[i].path, TEST_URLFROMPATH[i].ret);
512 ok(!lstrcmpiW(ret_urlW, urlW), "got %s expected %s from path L\"%s\"\n", ret_url, TEST_URLFROMPATH[i].url, TEST_URLFROMPATH[i].path);
513 ok(len == strlenW(ret_urlW), "ret len %ld from path L\"%s\"\n", len, TEST_URLFROMPATH[i].path);
514 FreeWideString(urlW);
515 FreeWideString(pathW);
519 static void test_UrlIs(void)
525 for(i = 0; i < sizeof(TEST_PATH_IS_URL) / sizeof(TEST_PATH_IS_URL[0]); i++) {
526 MultiByteToWideChar(CP_ACP, 0, TEST_PATH_IS_URL[i].path, -1, wurl, 80);
528 ret = UrlIsA( TEST_PATH_IS_URL[i].path, URLIS_URL );
529 ok( ret == TEST_PATH_IS_URL[i].expect,
530 "returned %d from path %s, expected %d\n", ret, TEST_PATH_IS_URL[i].path,
531 TEST_PATH_IS_URL[i].expect );
533 ret = UrlIsW( wurl, URLIS_URL );
534 ok( ret == TEST_PATH_IS_URL[i].expect,
535 "returned %d from path (UrlIsW) %s, expected %d\n", ret, TEST_PATH_IS_URL[i].path,
536 TEST_PATH_IS_URL[i].expect );
538 for(i = 0; i < sizeof(TEST_URLIS_ATTRIBS) / sizeof(TEST_URLIS_ATTRIBS[0]); i++) {
539 MultiByteToWideChar(CP_ACP, 0, TEST_URLIS_ATTRIBS[i].url, -1, wurl, 80);
541 ret = UrlIsA( TEST_URLIS_ATTRIBS[i].url, URLIS_OPAQUE);
542 ok( ret == TEST_URLIS_ATTRIBS[i].expectOpaque,
543 "returned %d for URLIS_OPAQUE, url \"%s\", expected %d\n", ret, TEST_URLIS_ATTRIBS[i].url,
544 TEST_URLIS_ATTRIBS[i].expectOpaque );
545 ret = UrlIsA( TEST_URLIS_ATTRIBS[i].url, URLIS_FILEURL);
546 ok( ret == TEST_URLIS_ATTRIBS[i].expectFile,
547 "returned %d for URLIS_FILEURL, url \"%s\", expected %d\n", ret, TEST_URLIS_ATTRIBS[i].url,
548 TEST_URLIS_ATTRIBS[i].expectFile );
550 ret = UrlIsW( wurl, URLIS_OPAQUE);
551 ok( ret == TEST_URLIS_ATTRIBS[i].expectOpaque,
552 "returned %d for URLIS_OPAQUE (UrlIsW), url \"%s\", expected %d\n", ret, TEST_URLIS_ATTRIBS[i].url,
553 TEST_URLIS_ATTRIBS[i].expectOpaque );
554 ret = UrlIsW( wurl, URLIS_FILEURL);
555 ok( ret == TEST_URLIS_ATTRIBS[i].expectFile,
556 "returned %d for URLIS_FILEURL (UrlIsW), url \"%s\", expected %d\n", ret, TEST_URLIS_ATTRIBS[i].url,
557 TEST_URLIS_ATTRIBS[i].expectFile );
561 static void test_UrlUnescape(void)
563 CHAR szReturnUrl[INTERNET_MAX_URL_LENGTH];
564 WCHAR ret_urlW[INTERNET_MAX_URL_LENGTH];
565 WCHAR *urlW, *expected_urlW;
569 for(i=0; i<sizeof(TEST_URL_UNESCAPE)/sizeof(TEST_URL_UNESCAPE[0]); i++) {
570 dwEscaped=INTERNET_MAX_URL_LENGTH;
571 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);
572 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);
574 dwEscaped = INTERNET_MAX_URL_LENGTH;
575 urlW = GetWideString(TEST_URL_UNESCAPE[i].url);
576 expected_urlW = GetWideString(TEST_URL_UNESCAPE[i].expect);
577 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);
578 WideCharToMultiByte(CP_ACP,0,ret_urlW,-1,szReturnUrl,INTERNET_MAX_URL_LENGTH,0,0);
579 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);
580 FreeWideString(urlW);
581 FreeWideString(expected_urlW);
586 static void test_PathSearchAndQualify(void)
588 WCHAR path1[] = {'c',':','\\','f','o','o',0};
589 WCHAR expect1[] = {'c',':','\\','f','o','o',0};
590 WCHAR path2[] = {'c',':','f','o','o',0};
591 WCHAR c_drive[] = {'c',':',0};
592 WCHAR foo[] = {'f','o','o',0};
593 WCHAR path3[] = {'\\','f','o','o',0};
594 WCHAR winini[] = {'w','i','n','.','i','n','i',0};
596 WCHAR cur_dir[MAX_PATH];
597 WCHAR dot[] = {'.',0};
600 ok(PathSearchAndQualifyW(path1, out, MAX_PATH) != 0,
601 "PathSearchAndQualify rets 0\n");
602 ok(!lstrcmpiW(out, expect1), "strings don't match\n");
605 ok(PathSearchAndQualifyW(path2, out, MAX_PATH) != 0,
606 "PathSearchAndQualify rets 0\n");
607 GetFullPathNameW(c_drive, MAX_PATH, cur_dir, NULL);
608 PathAddBackslashW(cur_dir);
609 strcatW(cur_dir, foo);
610 ok(!lstrcmpiW(out, cur_dir), "strings don't match\n");
613 ok(PathSearchAndQualifyW(foo, out, MAX_PATH) != 0,
614 "PathSearchAndQualify rets 0\n");
615 GetFullPathNameW(dot, MAX_PATH, cur_dir, NULL);
616 PathAddBackslashW(cur_dir);
617 strcatW(cur_dir, foo);
618 ok(!lstrcmpiW(out, cur_dir), "strings don't match\n");
621 ok(PathSearchAndQualifyW(path3, out, MAX_PATH) != 0,
622 "PathSearchAndQualify rets 0\n");
623 GetFullPathNameW(dot, MAX_PATH, cur_dir, NULL);
624 strcpyW(cur_dir + 2, path3);
625 ok(!lstrcmpiW(out, cur_dir), "strings don't match\n");
628 ok(PathSearchAndQualifyW(winini, out, MAX_PATH) != 0,
629 "PathSearchAndQualify rets 0\n");
630 if(!SearchPathW(NULL, winini, NULL, MAX_PATH, cur_dir, NULL))
631 GetFullPathNameW(winini, MAX_PATH, cur_dir, NULL);
632 ok(!lstrcmpiW(out, cur_dir), "strings don't match\n");
636 static void test_PathCreateFromUrl(void)
639 char ret_path[INTERNET_MAX_URL_LENGTH];
641 WCHAR ret_pathW[INTERNET_MAX_URL_LENGTH];
644 for(i = 0; i < sizeof(TEST_PATHFROMURL) / sizeof(TEST_PATHFROMURL[0]); i++) {
645 len = INTERNET_MAX_URL_LENGTH;
646 ret = PathCreateFromUrlA(TEST_PATHFROMURL[i].url, ret_path, &len, 0);
647 ok(ret == TEST_PATHFROMURL[i].ret, "ret %08lx from url %s\n", ret, TEST_PATHFROMURL[i].url);
648 if(TEST_PATHFROMURL[i].path) {
649 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);
650 ok(len == strlen(ret_path), "ret len %ld from url %s\n", len, TEST_PATHFROMURL[i].url);
652 len = INTERNET_MAX_URL_LENGTH;
653 pathW = GetWideString(TEST_PATHFROMURL[i].path);
654 urlW = GetWideString(TEST_PATHFROMURL[i].url);
655 ret = PathCreateFromUrlW(urlW, ret_pathW, &len, 0);
656 WideCharToMultiByte(CP_ACP, 0, ret_pathW, -1, ret_path, sizeof(ret_path),0,0);
657 ok(ret == TEST_PATHFROMURL[i].ret, "ret %08lx from url L\"%s\"\n", ret, TEST_PATHFROMURL[i].url);
658 if(TEST_PATHFROMURL[i].path) {
659 ok(!lstrcmpiW(ret_pathW, pathW), "got %s expected %s from url L\"%s\"\n", ret_path, TEST_PATHFROMURL[i].path, TEST_PATHFROMURL[i].url);
660 ok(len == strlenW(ret_pathW), "ret len %ld from url L\"%s\"\n", len, TEST_PATHFROMURL[i].url);
662 FreeWideString(urlW);
663 FreeWideString(pathW);
668 static void test_PathIsUrl(void)
673 for(i = 0; i < sizeof(TEST_PATH_IS_URL)/sizeof(TEST_PATH_IS_URL[0]); i++) {
674 ret = PathIsURLA(TEST_PATH_IS_URL[i].path);
675 ok(ret == TEST_PATH_IS_URL[i].expect,
676 "returned %d from path %s, expected %d\n", ret, TEST_PATH_IS_URL[i].path,
677 TEST_PATH_IS_URL[i].expect);
681 static const DWORD SHELL_charclass[] =
683 0x00000000, 0x00000000, 0x00000000, 0x00000000,
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 0x00000080, 0x00000100, 0x00000200, 0x00000100,
692 0x00000100, 0x00000100, 0x00000100, 0x00000100,
693 0x00000100, 0x00000100, 0x00000002, 0x00000100,
694 0x00000040, 0x00000100, 0x00000004, 0x00000000,
695 0x00000100, 0x00000100, 0x00000100, 0x00000100,
696 0x00000100, 0x00000100, 0x00000100, 0x00000100,
697 0x00000100, 0x00000100, 0x00000010, 0x00000020,
698 0x00000000, 0x00000100, 0x00000000, 0x00000001,
699 0x00000100, 0xffffffff, 0xffffffff, 0xffffffff,
700 0xffffffff, 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, 0x00000100,
706 0x00000008, 0x00000100, 0x00000100, 0x00000100,
707 0x00000100, 0xffffffff, 0xffffffff, 0xffffffff,
708 0xffffffff, 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, 0x00000100,
714 0x00000000, 0x00000100, 0x00000100
717 static void test_PathIsValidCharA(void)
722 ret = pPathIsValidCharA( 0x7f, 0 );
723 ok ( !ret, "PathIsValidCharA succeeded: 0x%08lx\n", (DWORD)ret );
725 ret = pPathIsValidCharA( 0x7f, 1 );
726 ok ( !ret, "PathIsValidCharA succeeded: 0x%08lx\n", (DWORD)ret );
728 for (c = 0; c < 0x7f; c++)
730 ret = pPathIsValidCharA( c, ~0U );
731 ok ( ret == SHELL_charclass[c] || (ret == 1 && SHELL_charclass[c] == 0xffffffff),
732 "PathIsValidCharA failed: 0x%02x got 0x%08lx expected 0x%08lx\n",
733 c, (DWORD)ret, SHELL_charclass[c] );
736 for (c = 0x7f; c <= 0xff; c++)
738 ret = pPathIsValidCharA( c, ~0U );
739 ok ( ret == 0x00000100,
740 "PathIsValidCharA failed: 0x%02x got 0x%08lx expected 0x00000100\n",
745 static void test_PathIsValidCharW(void)
750 ret = pPathIsValidCharW( 0x7f, 0 );
751 ok ( !ret, "PathIsValidCharW succeeded: 0x%08lx\n", (DWORD)ret );
753 ret = pPathIsValidCharW( 0x7f, 1 );
754 ok ( !ret, "PathIsValidCharW succeeded: 0x%08lx\n", (DWORD)ret );
756 for (c = 0; c < 0x7f; c++)
758 ret = pPathIsValidCharW( c, ~0U );
759 ok ( ret == SHELL_charclass[c] || (ret == 1 && SHELL_charclass[c] == 0xffffffff),
760 "PathIsValidCharW failed: 0x%02x got 0x%08lx expected 0x%08lx\n",
761 c, (DWORD)ret, SHELL_charclass[c] );
764 for (c = 0x007f; c <= 0xffff; c++)
766 ret = pPathIsValidCharW( c, ~0U );
767 ok ( ret == 0x00000100,
768 "PathIsValidCharW failed: 0x%02x got 0x%08lx expected 0x00000100\n",
773 static void test_PathMakePretty(void)
777 ok (PathMakePrettyA(NULL) == FALSE, "PathMakePretty: NULL path succeeded\n");
779 ok (PathMakePrettyA(buff) == TRUE, "PathMakePretty: Empty path failed\n");
781 strcpy(buff, "C:\\A LONG FILE NAME WITH \\SPACES.TXT");
782 ok (PathMakePrettyA(buff) == TRUE, "PathMakePretty: Long UC name failed\n");
783 ok (strcmp(buff, "C:\\a long file name with \\spaces.txt") == 0,
784 "PathMakePretty: Long UC name not changed\n");
786 strcpy(buff, "C:\\A LONG FILE NAME WITH \\MixedCase.TXT");
787 ok (PathMakePrettyA(buff) == FALSE, "PathMakePretty: Long MC name succeeded\n");
788 ok (strcmp(buff, "C:\\A LONG FILE NAME WITH \\MixedCase.TXT") == 0,
789 "PathMakePretty: Failed but modified path\n");
791 strcpy(buff, "TEST");
792 ok (PathMakePrettyA(buff) == TRUE, "PathMakePretty: Short name failed\n");
793 ok (strcmp(buff, "Test") == 0, "PathMakePretty: 1st char lowercased %s\n", buff);
798 hShlwapi = LoadLibraryA("shlwapi.dll");
799 if (!hShlwapi) return;
803 test_UrlCanonicalize();
806 test_UrlCreateFromPath();
810 test_PathSearchAndQualify();
811 test_PathCreateFromUrl();
814 test_PathMakePretty();
816 /* For whatever reason, PathIsValidCharA and PathAppendA share the same
817 * ordinal number in some native versions. Check this to prevent a crash.
819 pPathIsValidCharA = (void*)GetProcAddress(hShlwapi, (LPSTR)455);
820 if (pPathIsValidCharA && pPathIsValidCharA != (void*)GetProcAddress(hShlwapi, "PathAppendA"))
822 test_PathIsValidCharA();
824 pPathIsValidCharW = (void*)GetProcAddress(hShlwapi, (LPSTR)456);
825 if (pPathIsValidCharW) test_PathIsValidCharW();