shlwapi: Add tests for PathFindExtensionA.
[wine/hacks.git] / dlls / shlwapi / tests / path.c
blob183c93670e302540f49097b94d8f1676c18e35df
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 #include <assert.h>
21 #include <stdarg.h>
22 #include <stdio.h>
24 #include "wine/test.h"
25 #include "windef.h"
26 #include "winbase.h"
27 #include "winreg.h"
28 #include "shlwapi.h"
29 #include "wininet.h"
31 static HMODULE hShlwapi;
32 static HRESULT (WINAPI *pPathIsValidCharA)(char,DWORD);
33 static HRESULT (WINAPI *pPathIsValidCharW)(WCHAR,DWORD);
34 static LPWSTR (WINAPI *pPathCombineW)(LPWSTR, LPCWSTR, LPCWSTR);
36 const char* TEST_URL_1 = "http://www.winehq.org/tests?date=10/10/1923";
37 const char* TEST_URL_2 = "http://localhost:8080/tests%2e.html?date=Mon%2010/10/1923";
38 const char* TEST_URL_3 = "http://foo:bar@localhost:21/internal.php?query=x&return=y";
40 typedef struct _TEST_URL_CANONICALIZE {
41 const char *url;
42 DWORD flags;
43 HRESULT expectret;
44 const char *expecturl;
45 } TEST_URL_CANONICALIZE;
47 const TEST_URL_CANONICALIZE TEST_CANONICALIZE[] = {
48 /*FIXME {"http://www.winehq.org/tests/../tests/../..", 0, S_OK, "http://www.winehq.org/"},*/
49 {"http://www.winehq.org/tests/../tests", 0, S_OK, "http://www.winehq.org/tests"},
50 {"http://www.winehq.org/tests\n", URL_WININET_COMPATIBILITY|URL_ESCAPE_SPACES_ONLY|URL_ESCAPE_UNSAFE, S_OK, "http://www.winehq.org/tests"},
51 {"http://www.winehq.org/tests\r", URL_WININET_COMPATIBILITY|URL_ESCAPE_SPACES_ONLY|URL_ESCAPE_UNSAFE, S_OK, "http://www.winehq.org/tests"},
52 {"http://www.winehq.org/tests\r", 0, S_OK, "http://www.winehq.org/tests"},
53 {"http://www.winehq.org/tests\r", URL_DONT_SIMPLIFY, S_OK, "http://www.winehq.org/tests"},
54 {"http://www.winehq.org/tests/../tests/", 0, S_OK, "http://www.winehq.org/tests/"},
55 {"http://www.winehq.org/tests/../tests/..", 0, S_OK, "http://www.winehq.org/"},
56 {"http://www.winehq.org/tests/../tests/../", 0, S_OK, "http://www.winehq.org/"},
57 {"http://www.winehq.org/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/..?query=x&return=y", 0, S_OK, "http://www.winehq.org/?query=x&return=y"},
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/..#example", 0, S_OK, "http://www.winehq.org/#example"},
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", 0, S_OK, "http://www.winehq.org/#example"},
65 {"http://www.winehq.org\\tests/../#example", 0, S_OK, "http://www.winehq.org/#example"},
66 {"http://www.winehq.org/tests/../#example", URL_DONT_SIMPLIFY, S_OK, "http://www.winehq.org/tests/../#example"},
67 {"http://www.winehq.org/tests/foo bar", URL_ESCAPE_SPACES_ONLY| URL_DONT_ESCAPE_EXTRA_INFO , S_OK, "http://www.winehq.org/tests/foo%20bar"},
68 {"http://www.winehq.org/tests/foo%20bar", URL_UNESCAPE , S_OK, "http://www.winehq.org/tests/foo bar"},
69 {"file:///c:/tests/foo%20bar", URL_UNESCAPE , S_OK, "file:///c:/tests/foo bar"},
70 {"file:///c:/tests\\foo%20bar", URL_UNESCAPE , S_OK, "file:///c:/tests/foo bar"},
71 {"file:///c:/tests/foo%20bar", URL_FILE_USE_PATHURL, S_OK, "file://c:\\tests\\foo bar"},
72 {"file://c:/tests/../tests/foo%20bar", URL_FILE_USE_PATHURL, S_OK, "file://c:\\tests\\foo bar"},
73 {"file://c:/tests\\../tests/foo%20bar", URL_FILE_USE_PATHURL, S_OK, "file://c:\\tests\\foo bar"},
74 {"file://c:/tests/foo%20bar", URL_FILE_USE_PATHURL, S_OK, "file://c:\\tests\\foo bar"},
75 {"file:///c://tests/foo%20bar", URL_FILE_USE_PATHURL, S_OK, "file://c:\\\\tests\\foo bar"},
76 {"file:///c:\\tests\\foo bar", 0, S_OK, "file:///c:/tests/foo bar"},
77 {"file:///c:\\tests\\foo bar", URL_DONT_SIMPLIFY, S_OK, "file:///c:/tests/foo bar"},
80 typedef struct _TEST_URL_ESCAPE {
81 const char *url;
82 DWORD flags;
83 DWORD expectescaped;
84 HRESULT expectret;
85 const char *expecturl;
86 } TEST_URL_ESCAPE;
88 const TEST_URL_ESCAPE TEST_ESCAPE[] = {
89 {"http://www.winehq.org/tests0", 0, 0, S_OK, "http://www.winehq.org/tests0"},
90 {"http://www.winehq.org/tests1\n", 0, 0, S_OK, "http://www.winehq.org/tests1%0A"},
91 {"http://www.winehq.org/tests2\r", 0, 0, S_OK, "http://www.winehq.org/tests2%0D"},
92 {"http://www.winehq.org/tests3\r", URL_ESCAPE_SPACES_ONLY|URL_ESCAPE_UNSAFE, 0, S_OK, "http://www.winehq.org/tests3\r"},
93 {"http://www.winehq.org/tests4\r", URL_ESCAPE_SPACES_ONLY, 0, S_OK, "http://www.winehq.org/tests4\r"},
94 {"http://www.winehq.org/tests5\r", URL_WININET_COMPATIBILITY|URL_ESCAPE_SPACES_ONLY, 0, S_OK, "http://www.winehq.org/tests5\r"},
95 {"/direct/swhelp/series6/6.2i_latestservicepack.dat\r", URL_ESCAPE_SPACES_ONLY, 0, S_OK, "/direct/swhelp/series6/6.2i_latestservicepack.dat\r"},
97 {"file://////foo/bar\\baz", 0, 0, S_OK, "file://foo/bar/baz"},
98 {"file://///foo/bar\\baz", 0, 0, S_OK, "file://foo/bar/baz"},
99 {"file:////foo/bar\\baz", 0, 0, S_OK, "file://foo/bar/baz"},
100 {"file:///localhost/foo/bar\\baz", 0, 0, S_OK, "file:///localhost/foo/bar/baz"},
101 {"file:///foo/bar\\baz", 0, 0, S_OK, "file:///foo/bar/baz"},
102 {"file://loCalHost/foo/bar\\baz", 0, 0, S_OK, "file:///foo/bar/baz"},
103 {"file://foo/bar\\baz", 0, 0, S_OK, "file://foo/bar/baz"},
104 {"file:/localhost/foo/bar\\baz", 0, 0, S_OK, "file:///localhost/foo/bar/baz"},
105 {"file:/foo/bar\\baz", 0, 0, S_OK, "file:///foo/bar/baz"},
106 {"file:foo/bar\\baz", 0, 0, S_OK, "file:foo/bar/baz"},
107 {"file:\\foo/bar\\baz", 0, 0, S_OK, "file:///foo/bar/baz"},
108 {"file:\\\\foo/bar\\baz", 0, 0, S_OK, "file://foo/bar/baz"},
109 {"file:\\\\\\foo/bar\\baz", 0, 0, S_OK, "file:///foo/bar/baz"},
110 {"file:\\\\localhost\\foo/bar\\baz", 0, 0, S_OK, "file:///foo/bar/baz"},
111 {"file:///f oo/b?a r\\baz", 0, 0, S_OK, "file:///f%20oo/b?a r\\baz"},
112 {"file:///foo/b#a r\\baz", 0, 0, S_OK, "file:///foo/b%23a%20r/baz"},
113 {"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"},
114 {"file:///f o%o/b?a r\\b%az", URL_ESCAPE_PERCENT, 0, S_OK, "file:///f%20o%25o/b?a r\\b%az"},
115 {"file:/foo/bar\\baz", URL_ESCAPE_SEGMENT_ONLY, 0, S_OK, "file:%2Ffoo%2Fbar%5Cbaz"},
117 {"foo/b%ar\\ba?z\\", URL_ESCAPE_SEGMENT_ONLY, 0, S_OK, "foo%2Fb%ar%5Cba%3Fz%5C"},
118 {"foo/b%ar\\ba?z\\", URL_ESCAPE_PERCENT | URL_ESCAPE_SEGMENT_ONLY, 0, S_OK, "foo%2Fb%25ar%5Cba%3Fz%5C"},
119 {"foo/bar\\ba?z\\", 0, 0, S_OK, "foo/bar%5Cba?z\\"},
120 {"/foo/bar\\ba?z\\", 0, 0, S_OK, "/foo/bar%5Cba?z\\"},
121 {"/foo/bar\\ba#z\\", 0, 0, S_OK, "/foo/bar%5Cba#z\\"},
122 {"/foo/%5C", 0, 0, S_OK, "/foo/%5C"},
123 {"/foo/%5C", URL_ESCAPE_PERCENT, 0, S_OK, "/foo/%255C"},
125 {"http://////foo/bar\\baz", 0, 0, S_OK, "http://////foo/bar/baz"},
126 {"http://///foo/bar\\baz", 0, 0, S_OK, "http://///foo/bar/baz"},
127 {"http:////foo/bar\\baz", 0, 0, S_OK, "http:////foo/bar/baz"},
128 {"http:///foo/bar\\baz", 0, 0, S_OK, "http:///foo/bar/baz"},
129 {"http://localhost/foo/bar\\baz", 0, 0, S_OK, "http://localhost/foo/bar/baz"},
130 {"http://foo/bar\\baz", 0, 0, S_OK, "http://foo/bar/baz"},
131 {"http:/foo/bar\\baz", 0, 0, S_OK, "http:/foo/bar/baz"},
132 {"http:foo/bar\\ba?z\\", 0, 0, S_OK, "http:foo%2Fbar%2Fba?z\\"},
133 {"http:foo/bar\\ba#z\\", 0, 0, S_OK, "http:foo%2Fbar%2Fba#z\\"},
134 {"http:\\foo/bar\\baz", 0, 0, S_OK, "http:/foo/bar/baz"},
135 {"http:\\\\foo/bar\\baz", 0, 0, S_OK, "http://foo/bar/baz"},
136 {"http:\\\\\\foo/bar\\baz", 0, 0, S_OK, "http:///foo/bar/baz"},
137 {"http:\\\\\\\\foo/bar\\baz", 0, 0, S_OK, "http:////foo/bar/baz"},
138 {"http:/fo ?o/b ar\\baz", 0, 0, S_OK, "http:/fo%20?o/b ar\\baz"},
139 {"http:fo ?o/b ar\\baz", 0, 0, S_OK, "http:fo%20?o/b ar\\baz"},
140 {"http:/foo/bar\\baz", URL_ESCAPE_SEGMENT_ONLY, 0, S_OK, "http:%2Ffoo%2Fbar%5Cbaz"},
142 {"https://foo/bar\\baz", 0, 0, S_OK, "https://foo/bar/baz"},
143 {"https:/foo/bar\\baz", 0, 0, S_OK, "https:/foo/bar/baz"},
144 {"https:\\foo/bar\\baz", 0, 0, S_OK, "https:/foo/bar/baz"},
146 {"foo:////foo/bar\\baz", 0, 0, S_OK, "foo:////foo/bar%5Cbaz"},
147 {"foo:///foo/bar\\baz", 0, 0, S_OK, "foo:///foo/bar%5Cbaz"},
148 {"foo://localhost/foo/bar\\baz", 0, 0, S_OK, "foo://localhost/foo/bar%5Cbaz"},
149 {"foo://foo/bar\\baz", 0, 0, S_OK, "foo://foo/bar%5Cbaz"},
150 {"foo:/foo/bar\\baz", 0, 0, S_OK, "foo:/foo/bar%5Cbaz"},
151 {"foo:foo/bar\\baz", 0, 0, S_OK, "foo:foo%2Fbar%5Cbaz"},
152 {"foo:\\foo/bar\\baz", 0, 0, S_OK, "foo:%5Cfoo%2Fbar%5Cbaz"},
153 {"foo:/foo/bar\\ba?\\z", 0, 0, S_OK, "foo:/foo/bar%5Cba?\\z"},
154 {"foo:/foo/bar\\ba#\\z", 0, 0, S_OK, "foo:/foo/bar%5Cba#\\z"},
156 {"mailto:/fo/o@b\\%a?\\r.b#\\az", 0, 0, S_OK, "mailto:%2Ffo%2Fo@b%5C%a%3F%5Cr.b%23%5Caz"},
157 {"mailto:fo/o@b\\%a?\\r.b#\\az", 0, 0, S_OK, "mailto:fo%2Fo@b%5C%a%3F%5Cr.b%23%5Caz"},
158 {"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"},
160 {"ftp:fo/o@bar.baz/foo/bar", 0, 0, S_OK, "ftp:fo%2Fo@bar.baz%2Ffoo%2Fbar"},
161 {"ftp:/fo/o@bar.baz/foo/bar", 0, 0, S_OK, "ftp:/fo/o@bar.baz/foo/bar"},
162 {"ftp://fo/o@bar.baz/fo?o\\bar", 0, 0, S_OK, "ftp://fo/o@bar.baz/fo?o\\bar"},
163 {"ftp://fo/o@bar.baz/fo#o\\bar", 0, 0, S_OK, "ftp://fo/o@bar.baz/fo#o\\bar"},
164 {"ftp://localhost/o@bar.baz/fo#o\\bar", 0, 0, S_OK, "ftp://localhost/o@bar.baz/fo#o\\bar"},
165 {"ftp:///fo/o@bar.baz/foo/bar", 0, 0, S_OK, "ftp:///fo/o@bar.baz/foo/bar"},
166 {"ftp:////fo/o@bar.baz/foo/bar", 0, 0, S_OK, "ftp:////fo/o@bar.baz/foo/bar"}
169 typedef struct _TEST_URL_COMBINE {
170 const char *url1;
171 const char *url2;
172 DWORD flags;
173 HRESULT expectret;
174 const char *expecturl;
175 } TEST_URL_COMBINE;
177 const TEST_URL_COMBINE TEST_COMBINE[] = {
178 {"http://www.winehq.org/tests", "tests1", 0, S_OK, "http://www.winehq.org/tests1"},
179 {"http://www.%77inehq.org/tests", "tests1", 0, S_OK, "http://www.%77inehq.org/tests1"},
180 /*FIXME {"http://www.winehq.org/tests", "../tests2", 0, S_OK, "http://www.winehq.org/tests2"},*/
181 {"http://www.winehq.org/tests/", "../tests3", 0, S_OK, "http://www.winehq.org/tests3"},
182 {"http://www.winehq.org/tests/test1", "test2", 0, S_OK, "http://www.winehq.org/tests/test2"},
183 {"http://www.winehq.org/tests/../tests", "tests4", 0, S_OK, "http://www.winehq.org/tests4"},
184 {"http://www.winehq.org/tests/../tests/", "tests5", 0, S_OK, "http://www.winehq.org/tests/tests5"},
185 {"http://www.winehq.org/tests/../tests/", "/tests6/..", 0, S_OK, "http://www.winehq.org/"},
186 {"http://www.winehq.org/tests/../tests/..", "tests7/..", 0, S_OK, "http://www.winehq.org/"},
187 {"http://www.winehq.org/tests/?query=x&return=y", "tests8", 0, S_OK, "http://www.winehq.org/tests/tests8"},
188 {"http://www.winehq.org/tests/#example", "tests9", 0, S_OK, "http://www.winehq.org/tests/tests9"},
189 {"http://www.winehq.org/tests/../tests/", "/tests10/..", URL_DONT_SIMPLIFY, S_OK, "http://www.winehq.org/tests10/.."},
190 {"http://www.winehq.org/tests/../", "tests11", URL_DONT_SIMPLIFY, S_OK, "http://www.winehq.org/tests/../tests11"},
191 {"file:///C:\\dir\\file.txt", "test.txt", 0, S_OK, "file:///C:/dir/test.txt"}
194 struct {
195 const char *path;
196 const char *url;
197 DWORD ret;
198 } TEST_URLFROMPATH [] = {
199 {"foo", "file:foo", S_OK},
200 {"foo\\bar", "file:foo/bar", S_OK},
201 {"\\foo\\bar", "file:///foo/bar", S_OK},
202 {"c:\\foo\\bar", "file:///c:/foo/bar", S_OK},
203 {"c:foo\\bar", "file:///c:foo/bar", S_OK},
204 {"c:\\foo/b a%r", "file:///c:/foo/b%20a%25r", S_OK},
205 {"c:\\foo\\foo bar", "file:///c:/foo/foo%20bar", S_OK},
206 #if 0
207 /* The following test fails on native shlwapi as distributed with Win95/98.
208 * Wine matches the behaviour of later versions.
210 {"xx:c:\\foo\\bar", "xx:c:\\foo\\bar", S_FALSE}
211 #endif
214 struct {
215 const char *url;
216 const char *path;
217 DWORD ret;
218 } TEST_PATHFROMURL[] = {
219 {"file:///c:/foo/ba%5Cr", "c:\\foo\\ba\\r", S_OK},
220 {"file:///c:/foo/../ba%5Cr", "c:\\foo\\..\\ba\\r", S_OK},
221 {"file:///host/c:/foo/bar", "\\host\\c:\\foo\\bar", S_OK},
222 {"file://host/c:/foo/bar", "\\\\hostc:\\foo\\bar", S_OK},
223 {"file://host/c:/foo/bar", "\\\\hostc:\\foo\\bar", S_OK},
224 {"file:\\\\host\\c:\\foo\\bar", "\\\\hostc:\\foo\\bar", S_OK},
225 {"file:\\\\host\\ca\\foo\\bar", "\\\\host\\ca\\foo\\bar", S_OK},
226 {"file:\\\\host\\c|\\foo\\bar", "\\\\hostc|\\foo\\bar", S_OK},
227 {"file:\\%5Chost\\c:\\foo\\bar", "\\\\host\\c:\\foo\\bar", S_OK},
228 {"file:\\\\host\\cx:\\foo\\bar", "\\\\host\\cx:\\foo\\bar", S_OK},
229 {"file://c:/foo/bar", "c:\\foo\\bar", S_OK},
230 {"file://c:/d:/foo/bar", "c:\\d:\\foo\\bar", S_OK},
231 {"file://c|/d|/foo/bar", "c:\\d|\\foo\\bar", S_OK},
232 {"file://host/foo/bar", "\\\\host\\foo\\bar", S_OK},
233 {"file:/foo/bar", "\\foo\\bar", S_OK},
234 {"file:/foo/bar/", "\\foo\\bar\\", S_OK},
235 {"file:foo/bar", "foo\\bar", S_OK},
236 {"file:c:/foo/bar", "c:\\foo\\bar", S_OK},
237 {"file:c|/foo/bar", "c:\\foo\\bar", S_OK},
238 {"file:cx|/foo/bar", "cx|\\foo\\bar", S_OK},
239 {"file:////c:/foo/bar", "c:\\foo\\bar", S_OK},
240 /* {"file:////c:/foo/foo%20bar", "c:\\foo\\foo%20bar", S_OK},*/
242 {"c:\\foo\\bar", NULL, E_INVALIDARG},
243 {"foo/bar", NULL, E_INVALIDARG},
244 {"http://foo/bar", NULL, E_INVALIDARG},
248 struct {
249 char url[30];
250 const char *expect;
251 } TEST_URL_UNESCAPE[] = {
252 {"file://foo/bar", "file://foo/bar"},
253 {"file://fo%20o%5Ca/bar", "file://fo o\\a/bar"}
257 struct {
258 const char *path;
259 BOOL expect;
260 } TEST_PATH_IS_URL[] = {
261 {"http://foo/bar", TRUE},
262 {"c:\\foo\\bar", FALSE},
263 {"foo://foo/bar", TRUE},
264 {"foo\\bar", FALSE},
265 {"foo.bar", FALSE},
266 {"bogusscheme:", TRUE},
267 {"http:partial", TRUE}
270 struct {
271 const char *url;
272 BOOL expectOpaque;
273 BOOL expectFile;
274 } TEST_URLIS_ATTRIBS[] = {
275 { "ftp:", FALSE, FALSE },
276 { "http:", FALSE, FALSE },
277 { "gopher:", FALSE, FALSE },
278 { "mailto:", TRUE, FALSE },
279 { "news:", FALSE, FALSE },
280 { "nntp:", FALSE, FALSE },
281 { "telnet:", FALSE, FALSE },
282 { "wais:", FALSE, FALSE },
283 { "file:", FALSE, TRUE },
284 { "mk:", FALSE, FALSE },
285 { "https:", FALSE, FALSE },
286 { "shell:", TRUE, FALSE },
287 { "https:", FALSE, FALSE },
288 { "snews:", FALSE, FALSE },
289 { "local:", FALSE, FALSE },
290 { "javascript:", TRUE, FALSE },
291 { "vbscript:", TRUE, FALSE },
292 { "about:", TRUE, FALSE },
293 { "res:", FALSE, FALSE },
294 { "bogusscheme:", FALSE, FALSE },
295 { "file:\\\\e:\\b\\c", FALSE, TRUE },
296 { "file://e:/b/c", FALSE, TRUE },
297 { "http:partial", FALSE, FALSE },
298 { "mailto://www.winehq.org/test.html", TRUE, FALSE },
299 { "file:partial", FALSE, TRUE }
303 static LPWSTR GetWideString(const char* szString)
305 LPWSTR wszString = HeapAlloc(GetProcessHeap(), 0, (2*INTERNET_MAX_URL_LENGTH) * sizeof(WCHAR));
307 MultiByteToWideChar(0, 0, szString, -1, wszString, INTERNET_MAX_URL_LENGTH);
309 return wszString;
312 static void FreeWideString(LPWSTR wszString)
314 HeapFree(GetProcessHeap(), 0, wszString);
317 static void hash_url(const char* szUrl)
319 LPCSTR szTestUrl = szUrl;
320 LPWSTR wszTestUrl = GetWideString(szTestUrl);
322 DWORD cbSize = sizeof(DWORD);
323 DWORD dwHash1, dwHash2;
324 ok(UrlHashA(szTestUrl, (LPBYTE)&dwHash1, cbSize) == S_OK, "UrlHashA didn't return S_OK\n");
325 ok(UrlHashW(wszTestUrl, (LPBYTE)&dwHash2, cbSize) == S_OK, "UrlHashW didn't return S_OK\n");
327 FreeWideString(wszTestUrl);
329 ok(dwHash1 == dwHash2, "Hashes didn't compare\n");
332 static void test_UrlHash(void)
334 hash_url(TEST_URL_1);
335 hash_url(TEST_URL_2);
336 hash_url(TEST_URL_3);
339 static void test_url_part(const char* szUrl, DWORD dwPart, DWORD dwFlags, const char* szExpected)
341 CHAR szPart[INTERNET_MAX_URL_LENGTH];
342 WCHAR wszPart[INTERNET_MAX_URL_LENGTH];
343 LPWSTR wszUrl = GetWideString(szUrl);
344 LPWSTR wszConvertedPart;
346 DWORD dwSize;
348 dwSize = INTERNET_MAX_URL_LENGTH;
349 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);
350 dwSize = INTERNET_MAX_URL_LENGTH;
351 ok( UrlGetPartW(wszUrl, wszPart, &dwSize, dwPart, dwFlags) == S_OK, "UrlGetPartW didn't return S_OK\n" );
353 wszConvertedPart = GetWideString(szPart);
355 ok(lstrcmpW(wszPart,wszConvertedPart)==0, "Strings didn't match between ascii and unicode UrlGetPart!\n");
357 FreeWideString(wszUrl);
358 FreeWideString(wszConvertedPart);
360 /* Note that v6.0 and later don't return '?' with the query */
361 ok(strcmp(szPart,szExpected)==0 ||
362 (*szExpected=='?' && !strcmp(szPart,szExpected+1)),
363 "Expected %s, but got %s\n", szExpected, szPart);
366 static void test_UrlGetPart(void)
368 CHAR szPart[INTERNET_MAX_URL_LENGTH];
369 DWORD dwSize;
370 HRESULT res;
372 dwSize = sizeof szPart;
373 szPart[0]='x'; szPart[1]=0;
374 res = UrlGetPartA("hi", szPart, &dwSize, URL_PART_SCHEME, 0);
375 todo_wine {
376 ok (res==S_FALSE, "UrlGetPartA(\"hi\") returned %08lX\n", res);
377 ok(szPart[0]==0, "UrlGetPartA(\"hi\") return \"%s\" instead of \"\"\n", szPart);
379 dwSize = sizeof szPart;
380 szPart[0]='x'; szPart[1]=0;
381 res = UrlGetPartA("hi", szPart, &dwSize, URL_PART_QUERY, 0);
382 todo_wine {
383 ok (res==S_FALSE, "UrlGetPartA(\"hi\") returned %08lX\n", res);
384 ok(szPart[0]==0, "UrlGetPartA(\"hi\") return \"%s\" instead of \"\"\n", szPart);
387 test_url_part(TEST_URL_3, URL_PART_HOSTNAME, 0, "localhost");
388 test_url_part(TEST_URL_3, URL_PART_PORT, 0, "21");
389 test_url_part(TEST_URL_3, URL_PART_USERNAME, 0, "foo");
390 test_url_part(TEST_URL_3, URL_PART_PASSWORD, 0, "bar");
391 test_url_part(TEST_URL_3, URL_PART_SCHEME, 0, "http");
392 test_url_part(TEST_URL_3, URL_PART_QUERY, 0, "?query=x&return=y");
395 static void test_url_escape(const char *szUrl, DWORD dwFlags, HRESULT dwExpectReturn, const char *szExpectUrl)
397 CHAR szReturnUrl[INTERNET_MAX_URL_LENGTH];
398 DWORD dwEscaped;
399 WCHAR ret_urlW[INTERNET_MAX_URL_LENGTH];
400 WCHAR *urlW, *expected_urlW;
401 dwEscaped=INTERNET_MAX_URL_LENGTH;
403 ok(UrlEscapeA(szUrl, szReturnUrl, &dwEscaped, dwFlags) == dwExpectReturn, "UrlEscapeA didn't return 0x%08lx from \"%s\"\n", dwExpectReturn, szUrl);
404 ok(strcmp(szReturnUrl,szExpectUrl)==0, "Expected \"%s\", but got \"%s\" from \"%s\"\n", szExpectUrl, szReturnUrl, szUrl);
406 dwEscaped = INTERNET_MAX_URL_LENGTH;
407 urlW = GetWideString(szUrl);
408 expected_urlW = GetWideString(szExpectUrl);
409 ok(UrlEscapeW(urlW, ret_urlW, &dwEscaped, dwFlags) == dwExpectReturn, "UrlEscapeW didn't return 0x%08lx from \"%s\"\n", dwExpectReturn, szUrl);
410 WideCharToMultiByte(CP_ACP,0,ret_urlW,-1,szReturnUrl,INTERNET_MAX_URL_LENGTH,0,0);
411 ok(lstrcmpW(ret_urlW, expected_urlW)==0, "Expected \"%s\", but got \"%s\" from \"%s\" flags %08lx\n", szExpectUrl, szReturnUrl, szUrl, dwFlags);
412 FreeWideString(urlW);
413 FreeWideString(expected_urlW);
417 static void test_url_canonicalize(const char *szUrl, DWORD dwFlags, HRESULT dwExpectReturn, const char *szExpectUrl)
419 CHAR szReturnUrl[INTERNET_MAX_URL_LENGTH];
420 WCHAR wszReturnUrl[INTERNET_MAX_URL_LENGTH];
421 LPWSTR wszUrl = GetWideString(szUrl);
422 LPWSTR wszExpectUrl = GetWideString(szExpectUrl);
423 LPWSTR wszConvertedUrl;
425 DWORD dwSize;
427 dwSize = INTERNET_MAX_URL_LENGTH;
428 ok(UrlCanonicalizeA(szUrl, NULL, &dwSize, dwFlags) != dwExpectReturn, "Unexpected return for NULL buffer\n");
429 ok(UrlCanonicalizeA(szUrl, szReturnUrl, &dwSize, dwFlags) == dwExpectReturn, "UrlCanonicalizeA didn't return 0x%08lx\n", dwExpectReturn);
430 ok(strcmp(szReturnUrl,szExpectUrl)==0, "UrlCanonicalizeA dwFlags 0x%08lx Expected %s, but got %s\n", dwFlags, szExpectUrl, szReturnUrl);
432 dwSize = INTERNET_MAX_URL_LENGTH;
433 ok(UrlCanonicalizeW(wszUrl, NULL, &dwSize, dwFlags) != dwExpectReturn, "Unexpected return for NULL buffer\n");
434 ok(UrlCanonicalizeW(wszUrl, wszReturnUrl, &dwSize, dwFlags) == dwExpectReturn, "UrlCanonicalizeW didn't return 0x%08lx\n", dwExpectReturn);
435 wszConvertedUrl = GetWideString(szReturnUrl);
436 ok(lstrcmpW(wszReturnUrl, wszConvertedUrl)==0, "Strings didn't match between ascii and unicode UrlCanonicalize!\n");
437 FreeWideString(wszConvertedUrl);
440 FreeWideString(wszUrl);
441 FreeWideString(wszExpectUrl);
445 static void test_UrlEscape(void)
447 unsigned int i;
448 for(i=0; i<sizeof(TEST_ESCAPE)/sizeof(TEST_ESCAPE[0]); i++) {
449 test_url_escape(TEST_ESCAPE[i].url, TEST_ESCAPE[i].flags,
450 TEST_ESCAPE[i].expectret, TEST_ESCAPE[i].expecturl);
454 static void test_UrlCanonicalize(void)
456 unsigned int i;
457 CHAR szReturnUrl[INTERNET_MAX_URL_LENGTH];
458 DWORD dwSize;
460 for(i=0; i<sizeof(TEST_CANONICALIZE)/sizeof(TEST_CANONICALIZE[0]); i++) {
461 test_url_canonicalize(TEST_CANONICALIZE[i].url, TEST_CANONICALIZE[i].flags,
462 TEST_CANONICALIZE[i].expectret, TEST_CANONICALIZE[i].expecturl);
465 /* move to TEST_CANONICALIZE when fixed */
466 dwSize = sizeof szReturnUrl;
467 ok(UrlCanonicalizeA("c:\\tests\\foo bar", szReturnUrl, &dwSize, 0) == S_OK, "UrlCanonicalizeA didn't return 0x%08lx\n", S_OK);
468 todo_wine {
469 ok(strcmp(szReturnUrl,"file:///c:/tests/foo%20bar")==0, "UrlCanonicalizeA got %s\n", szReturnUrl);
473 static void test_url_combine(const char *szUrl1, const char *szUrl2, DWORD dwFlags, HRESULT dwExpectReturn, const char *szExpectUrl)
475 HRESULT hr;
476 CHAR szReturnUrl[INTERNET_MAX_URL_LENGTH];
477 WCHAR wszReturnUrl[INTERNET_MAX_URL_LENGTH];
478 LPWSTR wszUrl1 = GetWideString(szUrl1);
479 LPWSTR wszUrl2 = GetWideString(szUrl2);
480 LPWSTR wszExpectUrl = GetWideString(szExpectUrl);
481 LPWSTR wszConvertedUrl;
483 DWORD dwSize;
484 DWORD dwExpectLen = lstrlen(szExpectUrl);
486 hr = UrlCombineA(szUrl1, szUrl2, NULL, NULL, dwFlags);
487 ok(hr == E_INVALIDARG, "UrlCombineA returned 0x%08lx, expected 0x%08lx\n", hr, E_INVALIDARG);
489 dwSize = 0;
490 hr = UrlCombineA(szUrl1, szUrl2, NULL, &dwSize, dwFlags);
491 ok(hr == E_POINTER, "Checking length of string, return was 0x%08lx, expected 0x%08lx\n", hr, E_POINTER);
492 ok(dwSize == dwExpectLen+1, "Got length %ld, expected %ld\n", dwSize, dwExpectLen+1);
494 dwSize--;
495 hr = UrlCombineA(szUrl1, szUrl2, szReturnUrl, &dwSize, dwFlags);
496 ok(hr == E_POINTER, "UrlCombineA returned 0x%08lx, expected 0x%08lx\n", hr, E_POINTER);
497 ok(dwSize == dwExpectLen+1, "Got length %ld, expected %ld\n", dwSize, dwExpectLen+1);
499 hr = UrlCombineA(szUrl1, szUrl2, szReturnUrl, &dwSize, dwFlags);
500 ok(hr == dwExpectReturn, "UrlCombineA returned 0x%08lx, expected 0x%08lx\n", hr, dwExpectReturn);
501 ok(dwSize == dwExpectLen, "Got length %ld, expected %ld\n", dwSize, dwExpectLen);
502 if(SUCCEEDED(hr)) {
503 ok(strcmp(szReturnUrl,szExpectUrl)==0, "Expected %s, but got %s\n", szExpectUrl, szReturnUrl);
506 dwSize = 0;
507 hr = UrlCombineW(wszUrl1, wszUrl2, NULL, &dwSize, dwFlags);
508 ok(hr == E_POINTER, "Checking length of string, return was 0x%08lx, expected 0x%08lx\n", hr, E_POINTER);
509 ok(dwSize == dwExpectLen+1, "Got length %ld, expected %ld\n", dwSize, dwExpectLen+1);
511 dwSize--;
512 hr = UrlCombineW(wszUrl1, wszUrl2, wszReturnUrl, &dwSize, dwFlags);
513 ok(hr == E_POINTER, "UrlCombineA returned 0x%08lx, expected 0x%08lx\n", hr, E_POINTER);
514 ok(dwSize == dwExpectLen+1, "Got length %ld, expected %ld\n", dwSize, dwExpectLen+1);
516 hr = UrlCombineW(wszUrl1, wszUrl2, wszReturnUrl, &dwSize, dwFlags);
517 ok(hr == dwExpectReturn, "UrlCombineW returned 0x%08lx, expected 0x%08lx\n", hr, dwExpectReturn);
518 ok(dwSize == dwExpectLen, "Got length %ld, expected %ld\n", dwSize, dwExpectLen);
519 if(SUCCEEDED(hr)) {
520 wszConvertedUrl = GetWideString(szReturnUrl);
521 ok(lstrcmpW(wszReturnUrl, wszConvertedUrl)==0, "Strings didn't match between ascii and unicode UrlCombine!\n");
522 FreeWideString(wszConvertedUrl);
525 FreeWideString(wszUrl1);
526 FreeWideString(wszUrl2);
527 FreeWideString(wszExpectUrl);
530 static void test_UrlCombine(void)
532 unsigned int i;
533 for(i=0; i<sizeof(TEST_COMBINE)/sizeof(TEST_COMBINE[0]); i++) {
534 test_url_combine(TEST_COMBINE[i].url1, TEST_COMBINE[i].url2, TEST_COMBINE[i].flags,
535 TEST_COMBINE[i].expectret, TEST_COMBINE[i].expecturl);
539 static void test_UrlCreateFromPath(void)
541 size_t i;
542 char ret_url[INTERNET_MAX_URL_LENGTH];
543 DWORD len, ret;
544 WCHAR ret_urlW[INTERNET_MAX_URL_LENGTH];
545 WCHAR *pathW, *urlW;
547 for(i = 0; i < sizeof(TEST_URLFROMPATH) / sizeof(TEST_URLFROMPATH[0]); i++) {
548 len = INTERNET_MAX_URL_LENGTH;
549 ret = UrlCreateFromPathA(TEST_URLFROMPATH[i].path, ret_url, &len, 0);
550 ok(ret == TEST_URLFROMPATH[i].ret, "ret %08lx from path %s\n", ret, TEST_URLFROMPATH[i].path);
551 ok(!lstrcmpi(ret_url, TEST_URLFROMPATH[i].url), "url %s from path %s\n", ret_url, TEST_URLFROMPATH[i].path);
552 ok(len == strlen(ret_url), "ret len %ld from path %s\n", len, TEST_URLFROMPATH[i].path);
554 len = INTERNET_MAX_URL_LENGTH;
555 pathW = GetWideString(TEST_URLFROMPATH[i].path);
556 urlW = GetWideString(TEST_URLFROMPATH[i].url);
557 ret = UrlCreateFromPathW(pathW, ret_urlW, &len, 0);
558 WideCharToMultiByte(CP_ACP, 0, ret_urlW, -1, ret_url, sizeof(ret_url),0,0);
559 ok(ret == TEST_URLFROMPATH[i].ret, "ret %08lx from path L\"%s\", expected %08lx\n",
560 ret, TEST_URLFROMPATH[i].path, TEST_URLFROMPATH[i].ret);
561 ok(!lstrcmpiW(ret_urlW, urlW), "got %s expected %s from path L\"%s\"\n", ret_url, TEST_URLFROMPATH[i].url, TEST_URLFROMPATH[i].path);
562 ok(len == lstrlenW(ret_urlW), "ret len %ld from path L\"%s\"\n", len, TEST_URLFROMPATH[i].path);
563 FreeWideString(urlW);
564 FreeWideString(pathW);
568 static void test_UrlIs(void)
570 BOOL ret;
571 size_t i;
572 WCHAR wurl[80];
574 for(i = 0; i < sizeof(TEST_PATH_IS_URL) / sizeof(TEST_PATH_IS_URL[0]); i++) {
575 MultiByteToWideChar(CP_ACP, 0, TEST_PATH_IS_URL[i].path, -1, wurl, 80);
577 ret = UrlIsA( TEST_PATH_IS_URL[i].path, URLIS_URL );
578 ok( ret == TEST_PATH_IS_URL[i].expect,
579 "returned %d from path %s, expected %d\n", ret, TEST_PATH_IS_URL[i].path,
580 TEST_PATH_IS_URL[i].expect );
582 ret = UrlIsW( wurl, URLIS_URL );
583 ok( ret == TEST_PATH_IS_URL[i].expect,
584 "returned %d from path (UrlIsW) %s, expected %d\n", ret, TEST_PATH_IS_URL[i].path,
585 TEST_PATH_IS_URL[i].expect );
587 for(i = 0; i < sizeof(TEST_URLIS_ATTRIBS) / sizeof(TEST_URLIS_ATTRIBS[0]); i++) {
588 MultiByteToWideChar(CP_ACP, 0, TEST_URLIS_ATTRIBS[i].url, -1, wurl, 80);
590 ret = UrlIsA( TEST_URLIS_ATTRIBS[i].url, URLIS_OPAQUE);
591 ok( ret == TEST_URLIS_ATTRIBS[i].expectOpaque,
592 "returned %d for URLIS_OPAQUE, url \"%s\", expected %d\n", ret, TEST_URLIS_ATTRIBS[i].url,
593 TEST_URLIS_ATTRIBS[i].expectOpaque );
594 ret = UrlIsA( TEST_URLIS_ATTRIBS[i].url, URLIS_FILEURL);
595 ok( ret == TEST_URLIS_ATTRIBS[i].expectFile,
596 "returned %d for URLIS_FILEURL, url \"%s\", expected %d\n", ret, TEST_URLIS_ATTRIBS[i].url,
597 TEST_URLIS_ATTRIBS[i].expectFile );
599 ret = UrlIsW( wurl, URLIS_OPAQUE);
600 ok( ret == TEST_URLIS_ATTRIBS[i].expectOpaque,
601 "returned %d for URLIS_OPAQUE (UrlIsW), url \"%s\", expected %d\n", ret, TEST_URLIS_ATTRIBS[i].url,
602 TEST_URLIS_ATTRIBS[i].expectOpaque );
603 ret = UrlIsW( wurl, URLIS_FILEURL);
604 ok( ret == TEST_URLIS_ATTRIBS[i].expectFile,
605 "returned %d for URLIS_FILEURL (UrlIsW), url \"%s\", expected %d\n", ret, TEST_URLIS_ATTRIBS[i].url,
606 TEST_URLIS_ATTRIBS[i].expectFile );
610 static void test_UrlUnescape(void)
612 CHAR szReturnUrl[INTERNET_MAX_URL_LENGTH];
613 WCHAR ret_urlW[INTERNET_MAX_URL_LENGTH];
614 WCHAR *urlW, *expected_urlW;
615 DWORD dwEscaped;
616 size_t i;
617 static char inplace[] = "file:///C:/Program%20Files";
618 static WCHAR inplaceW[] = {'f','i','l','e',':','/','/','/','C',':','/',
619 'P','r','o','g','r','a','m','%','2','0','F','i','l','e','s',0};
621 for(i=0; i<sizeof(TEST_URL_UNESCAPE)/sizeof(TEST_URL_UNESCAPE[0]); i++) {
622 dwEscaped=INTERNET_MAX_URL_LENGTH;
623 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);
624 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);
626 dwEscaped = INTERNET_MAX_URL_LENGTH;
627 urlW = GetWideString(TEST_URL_UNESCAPE[i].url);
628 expected_urlW = GetWideString(TEST_URL_UNESCAPE[i].expect);
629 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);
630 WideCharToMultiByte(CP_ACP,0,ret_urlW,-1,szReturnUrl,INTERNET_MAX_URL_LENGTH,0,0);
631 ok(lstrcmpW(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);
632 FreeWideString(urlW);
633 FreeWideString(expected_urlW);
636 dwEscaped = sizeof(inplace);
637 ok(UrlUnescapeA(inplace, NULL, &dwEscaped, URL_UNESCAPE_INPLACE) == S_OK, "UrlUnescapeA failed unexpectedly\n");
639 dwEscaped = sizeof(inplaceW);
640 ok(UrlUnescapeW(inplaceW, NULL, &dwEscaped, URL_UNESCAPE_INPLACE) == S_OK, "UrlUnescapeW failed unexpectedly\n");
643 static void test_PathSearchAndQualify(void)
645 WCHAR path1[] = {'c',':','\\','f','o','o',0};
646 WCHAR expect1[] = {'c',':','\\','f','o','o',0};
647 WCHAR path2[] = {'c',':','f','o','o',0};
648 WCHAR c_drive[] = {'c',':',0};
649 WCHAR foo[] = {'f','o','o',0};
650 WCHAR path3[] = {'\\','f','o','o',0};
651 WCHAR winini[] = {'w','i','n','.','i','n','i',0};
652 WCHAR out[MAX_PATH];
653 WCHAR cur_dir[MAX_PATH];
654 WCHAR dot[] = {'.',0};
656 /* c:\foo */
657 ok(PathSearchAndQualifyW(path1, out, MAX_PATH) != 0,
658 "PathSearchAndQualify rets 0\n");
659 ok(!lstrcmpiW(out, expect1), "strings don't match\n");
661 /* c:foo */
662 ok(PathSearchAndQualifyW(path2, out, MAX_PATH) != 0,
663 "PathSearchAndQualify rets 0\n");
664 GetFullPathNameW(c_drive, MAX_PATH, cur_dir, NULL);
665 PathAddBackslashW(cur_dir);
666 lstrcatW(cur_dir, foo);
667 ok(!lstrcmpiW(out, cur_dir), "strings don't match\n");
669 /* foo */
670 ok(PathSearchAndQualifyW(foo, out, MAX_PATH) != 0,
671 "PathSearchAndQualify rets 0\n");
672 GetFullPathNameW(dot, MAX_PATH, cur_dir, NULL);
673 PathAddBackslashW(cur_dir);
674 lstrcatW(cur_dir, foo);
675 ok(!lstrcmpiW(out, cur_dir), "strings don't match\n");
677 /* \foo */
678 ok(PathSearchAndQualifyW(path3, out, MAX_PATH) != 0,
679 "PathSearchAndQualify rets 0\n");
680 GetFullPathNameW(dot, MAX_PATH, cur_dir, NULL);
681 lstrcpyW(cur_dir + 2, path3);
682 ok(!lstrcmpiW(out, cur_dir), "strings don't match\n");
684 /* win.ini */
685 ok(PathSearchAndQualifyW(winini, out, MAX_PATH) != 0,
686 "PathSearchAndQualify rets 0\n");
687 if(!SearchPathW(NULL, winini, NULL, MAX_PATH, cur_dir, NULL))
688 GetFullPathNameW(winini, MAX_PATH, cur_dir, NULL);
689 ok(!lstrcmpiW(out, cur_dir), "strings don't match\n");
693 static void test_PathCreateFromUrl(void)
695 size_t i;
696 char ret_path[INTERNET_MAX_URL_LENGTH];
697 DWORD len, ret;
698 WCHAR ret_pathW[INTERNET_MAX_URL_LENGTH];
699 WCHAR *pathW, *urlW;
701 for(i = 0; i < sizeof(TEST_PATHFROMURL) / sizeof(TEST_PATHFROMURL[0]); i++) {
702 len = INTERNET_MAX_URL_LENGTH;
703 ret = PathCreateFromUrlA(TEST_PATHFROMURL[i].url, ret_path, &len, 0);
704 ok(ret == TEST_PATHFROMURL[i].ret, "ret %08lx from url %s\n", ret, TEST_PATHFROMURL[i].url);
705 if(TEST_PATHFROMURL[i].path) {
706 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);
707 ok(len == strlen(ret_path), "ret len %ld from url %s\n", len, TEST_PATHFROMURL[i].url);
709 len = INTERNET_MAX_URL_LENGTH;
710 pathW = GetWideString(TEST_PATHFROMURL[i].path);
711 urlW = GetWideString(TEST_PATHFROMURL[i].url);
712 ret = PathCreateFromUrlW(urlW, ret_pathW, &len, 0);
713 WideCharToMultiByte(CP_ACP, 0, ret_pathW, -1, ret_path, sizeof(ret_path),0,0);
714 ok(ret == TEST_PATHFROMURL[i].ret, "ret %08lx from url L\"%s\"\n", ret, TEST_PATHFROMURL[i].url);
715 if(TEST_PATHFROMURL[i].path) {
716 ok(!lstrcmpiW(ret_pathW, pathW), "got %s expected %s from url L\"%s\"\n", ret_path, TEST_PATHFROMURL[i].path, TEST_PATHFROMURL[i].url);
717 ok(len == lstrlenW(ret_pathW), "ret len %ld from url L\"%s\"\n", len, TEST_PATHFROMURL[i].url);
719 FreeWideString(urlW);
720 FreeWideString(pathW);
725 static void test_PathIsUrl(void)
727 size_t i;
728 BOOL ret;
730 for(i = 0; i < sizeof(TEST_PATH_IS_URL)/sizeof(TEST_PATH_IS_URL[0]); i++) {
731 ret = PathIsURLA(TEST_PATH_IS_URL[i].path);
732 ok(ret == TEST_PATH_IS_URL[i].expect,
733 "returned %d from path %s, expected %d\n", ret, TEST_PATH_IS_URL[i].path,
734 TEST_PATH_IS_URL[i].expect);
738 static const DWORD SHELL_charclass[] =
740 0x00000000, 0x00000000, 0x00000000, 0x00000000,
741 0x00000000, 0x00000000, 0x00000000, 0x00000000,
742 0x00000000, 0x00000000, 0x00000000, 0x00000000,
743 0x00000000, 0x00000000, 0x00000000, 0x00000000,
744 0x00000000, 0x00000000, 0x00000000, 0x00000000,
745 0x00000000, 0x00000000, 0x00000000, 0x00000000,
746 0x00000000, 0x00000000, 0x00000000, 0x00000000,
747 0x00000000, 0x00000000, 0x00000000, 0x00000000,
748 0x00000080, 0x00000100, 0x00000200, 0x00000100,
749 0x00000100, 0x00000100, 0x00000100, 0x00000100,
750 0x00000100, 0x00000100, 0x00000002, 0x00000100,
751 0x00000040, 0x00000100, 0x00000004, 0x00000000,
752 0x00000100, 0x00000100, 0x00000100, 0x00000100,
753 0x00000100, 0x00000100, 0x00000100, 0x00000100,
754 0x00000100, 0x00000100, 0x00000010, 0x00000020,
755 0x00000000, 0x00000100, 0x00000000, 0x00000001,
756 0x00000100, 0xffffffff, 0xffffffff, 0xffffffff,
757 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
758 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
759 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
760 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
761 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
762 0xffffffff, 0xffffffff, 0xffffffff, 0x00000100,
763 0x00000008, 0x00000100, 0x00000100, 0x00000100,
764 0x00000100, 0xffffffff, 0xffffffff, 0xffffffff,
765 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
766 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
767 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
768 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
769 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
770 0xffffffff, 0xffffffff, 0xffffffff, 0x00000100,
771 0x00000000, 0x00000100, 0x00000100
774 static void test_PathIsValidCharA(void)
776 BOOL ret;
777 unsigned int c;
779 ret = pPathIsValidCharA( 0x7f, 0 );
780 ok ( !ret, "PathIsValidCharA succeeded: 0x%08lx\n", (DWORD)ret );
782 ret = pPathIsValidCharA( 0x7f, 1 );
783 ok ( !ret, "PathIsValidCharA succeeded: 0x%08lx\n", (DWORD)ret );
785 for (c = 0; c < 0x7f; c++)
787 ret = pPathIsValidCharA( c, ~0U );
788 ok ( ret == SHELL_charclass[c] || (ret == 1 && SHELL_charclass[c] == 0xffffffff),
789 "PathIsValidCharA failed: 0x%02x got 0x%08lx expected 0x%08lx\n",
790 c, (DWORD)ret, SHELL_charclass[c] );
793 for (c = 0x7f; c <= 0xff; c++)
795 ret = pPathIsValidCharA( c, ~0U );
796 ok ( ret == 0x00000100,
797 "PathIsValidCharA failed: 0x%02x got 0x%08lx expected 0x00000100\n",
798 c, (DWORD)ret );
802 static void test_PathIsValidCharW(void)
804 BOOL ret;
805 unsigned int c, err_count = 0;
807 ret = pPathIsValidCharW( 0x7f, 0 );
808 ok ( !ret, "PathIsValidCharW succeeded: 0x%08lx\n", (DWORD)ret );
810 ret = pPathIsValidCharW( 0x7f, 1 );
811 ok ( !ret, "PathIsValidCharW succeeded: 0x%08lx\n", (DWORD)ret );
813 for (c = 0; c < 0x7f; c++)
815 ret = pPathIsValidCharW( c, ~0U );
816 ok ( ret == SHELL_charclass[c] || (ret == 1 && SHELL_charclass[c] == 0xffffffff),
817 "PathIsValidCharW failed: 0x%02x got 0x%08lx expected 0x%08lx\n",
818 c, (DWORD)ret, SHELL_charclass[c] );
821 for (c = 0x007f; c <= 0xffff; c++)
823 ret = pPathIsValidCharW( c, ~0U );
824 ok ( ret == 0x00000100,
825 "PathIsValidCharW failed: 0x%02x got 0x%08lx expected 0x00000100\n",
826 c, (DWORD)ret );
827 if (ret != 0x00000100)
829 if(++err_count > 100 ) {
830 trace("skipping rest of PathIsValidCharW tests "
831 "because of the current number of errors\n");
832 break;
838 static void test_PathMakePretty(void)
840 char buff[MAX_PATH];
842 ok (PathMakePrettyA(NULL) == FALSE, "PathMakePretty: NULL path succeeded\n");
843 buff[0] = '\0';
844 ok (PathMakePrettyA(buff) == TRUE, "PathMakePretty: Empty path failed\n");
846 strcpy(buff, "C:\\A LONG FILE NAME WITH \\SPACES.TXT");
847 ok (PathMakePrettyA(buff) == TRUE, "PathMakePretty: Long UC name failed\n");
848 ok (strcmp(buff, "C:\\a long file name with \\spaces.txt") == 0,
849 "PathMakePretty: Long UC name not changed\n");
851 strcpy(buff, "C:\\A LONG FILE NAME WITH \\MixedCase.TXT");
852 ok (PathMakePrettyA(buff) == FALSE, "PathMakePretty: Long MC name succeeded\n");
853 ok (strcmp(buff, "C:\\A LONG FILE NAME WITH \\MixedCase.TXT") == 0,
854 "PathMakePretty: Failed but modified path\n");
856 strcpy(buff, "TEST");
857 ok (PathMakePrettyA(buff) == TRUE, "PathMakePretty: Short name failed\n");
858 ok (strcmp(buff, "Test") == 0, "PathMakePretty: 1st char lowercased %s\n", buff);
861 static void test_PathMatchSpec(void)
863 static const char file[] = "c:\\foo\\bar\\filename.ext";
864 static const char spec1[] = ".ext";
865 static const char spec2[] = "*.ext";
866 static const char spec3[] = "*.ext ";
867 static const char spec4[] = " *.ext";
868 static const char spec5[] = "* .ext";
869 static const char spec6[] = "*. ext";
870 static const char spec7[] = "* . ext";
871 static const char spec8[] = "*.e?t";
872 static const char spec9[] = "filename.ext";
873 static const char spec10[] = "*bar\\filename.ext";
874 static const char spec11[] = " foo; *.ext";
875 static const char spec12[] = "*.ext;*.bar";
876 static const char spec13[] = "*bar*";
878 ok (PathMatchSpecA(file, spec1) == FALSE, "PathMatchSpec: Spec1 failed\n");
879 ok (PathMatchSpecA(file, spec2) == TRUE, "PathMatchSpec: Spec2 failed\n");
880 ok (PathMatchSpecA(file, spec3) == FALSE, "PathMatchSpec: Spec3 failed\n");
881 ok (PathMatchSpecA(file, spec4) == TRUE, "PathMatchSpec: Spec4 failed\n");
882 todo_wine ok (PathMatchSpecA(file, spec5) == TRUE, "PathMatchSpec: Spec5 failed\n");
883 todo_wine ok (PathMatchSpecA(file, spec6) == TRUE, "PathMatchSpec: Spec6 failed\n");
884 ok (PathMatchSpecA(file, spec7) == FALSE, "PathMatchSpec: Spec7 failed\n");
885 ok (PathMatchSpecA(file, spec8) == TRUE, "PathMatchSpec: Spec8 failed\n");
886 ok (PathMatchSpecA(file, spec9) == FALSE, "PathMatchSpec: Spec9 failed\n");
887 ok (PathMatchSpecA(file, spec10) == TRUE, "PathMatchSpec: Spec10 failed\n");
888 ok (PathMatchSpecA(file, spec11) == TRUE, "PathMatchSpec: Spec11 failed\n");
889 ok (PathMatchSpecA(file, spec12) == TRUE, "PathMatchSpec: Spec12 failed\n");
890 ok (PathMatchSpecA(file, spec13) == TRUE, "PathMatchSpec: Spec13 failed\n");
893 static void test_PathCombineW(void)
895 LPWSTR wszString, wszString2;
897 wszString2 = HeapAlloc(GetProcessHeap(), 0, MAX_PATH * sizeof(WCHAR));
899 /* NULL test */
900 wszString = pPathCombineW(NULL, NULL, NULL);
901 ok (wszString == NULL, "Expected a NULL return\n");
903 /* Some NULL */
904 wszString = pPathCombineW(wszString2, NULL, NULL);
905 ok (wszString == NULL, "Expected a NULL return\n");
907 HeapFree(GetProcessHeap(), 0, wszString2);
910 #define LONG_LEN (MAX_PATH * 2)
911 #define HALF_LEN (MAX_PATH / 2 + 1)
913 static void test_PathCombineA(void)
915 LPSTR str;
916 char dest[MAX_PATH];
917 char too_long[LONG_LEN];
918 char one[HALF_LEN], two[HALF_LEN];
920 /* try NULL dest */
921 SetLastError(0xdeadbeef);
922 str = PathCombineA(NULL, "C:\\", "one\\two\\three");
923 ok(str == NULL, "Expected NULL, got %p\n", str);
924 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
926 /* try NULL dest and NULL directory */
927 SetLastError(0xdeadbeef);
928 str = PathCombineA(NULL, NULL, "one\\two\\three");
929 ok(str == NULL, "Expected NULL, got %p\n", str);
930 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
932 /* try all NULL*/
933 SetLastError(0xdeadbeef);
934 str = PathCombineA(NULL, NULL, NULL);
935 ok(str == NULL, "Expected NULL, got %p\n", str);
936 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
938 /* try NULL file part */
939 SetLastError(0xdeadbeef);
940 lstrcpyA(dest, "control");
941 str = PathCombineA(dest, "C:\\", NULL);
942 ok(str == dest, "Expected str == dest, got %p\n", str);
943 ok(!lstrcmp(str, "C:\\"), "Expected C:\\, got %s\n", str);
944 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
946 /* try empty file part */
947 SetLastError(0xdeadbeef);
948 lstrcpyA(dest, "control");
949 str = PathCombineA(dest, "C:\\", "");
950 ok(str == dest, "Expected str == dest, got %p\n", str);
951 ok(!lstrcmp(str, "C:\\"), "Expected C:\\, got %s\n", str);
952 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
954 /* try empty directory and file part */
955 SetLastError(0xdeadbeef);
956 lstrcpyA(dest, "control");
957 str = PathCombineA(dest, "", "");
958 ok(str == dest, "Expected str == dest, got %p\n", str);
959 ok(!lstrcmp(str, "\\"), "Expected \\, got %s\n", str);
960 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
962 /* try NULL directory */
963 SetLastError(0xdeadbeef);
964 lstrcpyA(dest, "control");
965 str = PathCombineA(dest, NULL, "one\\two\\three");
966 ok(str == dest, "Expected str == dest, got %p\n", str);
967 ok(!lstrcmp(str, "one\\two\\three"), "Expected one\\two\\three, got %s\n", str);
968 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
970 /* try NULL directory and empty file part */
971 SetLastError(0xdeadbeef);
972 lstrcpyA(dest, "control");
973 str = PathCombineA(dest, NULL, "");
974 ok(str == dest, "Expected str == dest, got %p\n", str);
975 ok(!lstrcmp(str, "\\"), "Expected \\, got %s\n", str);
976 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
978 /* try NULL directory and file part */
979 SetLastError(0xdeadbeef);
980 lstrcpyA(dest, "control");
981 str = PathCombineA(dest, NULL, NULL);
982 ok(str == NULL, "Expected str == NULL, got %p\n", str);
983 todo_wine
985 ok(lstrlenA(dest) == 0, "Expected 0 length, got %i\n", lstrlenA(dest));
987 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
989 /* try directory without backslash */
990 SetLastError(0xdeadbeef);
991 lstrcpyA(dest, "control");
992 str = PathCombineA(dest, "C:", "one\\two\\three");
993 ok(str == dest, "Expected str == dest, got %p\n", str);
994 ok(!lstrcmp(str, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", str);
995 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
997 /* try directory with backslash */
998 SetLastError(0xdeadbeef);
999 lstrcpyA(dest, "control");
1000 str = PathCombineA(dest, "C:\\", "one\\two\\three");
1001 ok(str == dest, "Expected str == dest, got %p\n", str);
1002 ok(!lstrcmp(str, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", str);
1003 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
1005 /* try directory with backslash and file with prepended backslash */
1006 SetLastError(0xdeadbeef);
1007 lstrcpyA(dest, "control");
1008 str = PathCombineA(dest, "C:\\", "\\one\\two\\three");
1009 ok(str == dest, "Expected str == dest, got %p\n", str);
1010 ok(!lstrcmp(str, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", str);
1011 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
1013 /* try previous test, with backslash appended as well */
1014 SetLastError(0xdeadbeef);
1015 lstrcpyA(dest, "control");
1016 str = PathCombineA(dest, "C:\\", "\\one\\two\\three\\");
1017 ok(str == dest, "Expected str == dest, got %p\n", str);
1018 ok(!lstrcmp(str, "C:\\one\\two\\three\\"), "Expected C:\\one\\two\\three\\, got %s\n", str);
1019 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
1021 /* try a relative directory */
1022 SetLastError(0xdeadbeef);
1023 lstrcpyA(dest, "control");
1024 str = PathCombineA(dest, "relative\\dir", "\\one\\two\\three\\");
1025 ok(str == dest, "Expected str == dest, got %p\n", str);
1026 ok(!lstrcmp(str, "one\\two\\three\\"), "Expected one\\two\\three\\, got %s\n", str);
1027 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
1029 /* try forward slashes */
1030 SetLastError(0xdeadbeef);
1031 lstrcpyA(dest, "control");
1032 str = PathCombineA(dest, "C:\\", "one/two/three\\");
1033 ok(str == dest, "Expected str == dest, got %p\n", str);
1034 ok(!lstrcmp(str, "C:\\one/two/three\\"), "Expected one/two/three\\, got %s\n", str);
1035 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
1037 /* try a really weird directory */
1038 SetLastError(0xdeadbeef);
1039 lstrcpyA(dest, "control");
1040 str = PathCombineA(dest, "C:\\/\\/", "\\one\\two\\three\\");
1041 ok(str == dest, "Expected str == dest, got %p\n", str);
1042 ok(!lstrcmp(str, "C:\\one\\two\\three\\"), "Expected C:\\one\\two\\three\\, got %s\n", str);
1043 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
1045 /* try periods */
1046 SetLastError(0xdeadbeef);
1047 lstrcpyA(dest, "control");
1048 str = PathCombineA(dest, "C:\\", "one\\..\\two\\.\\three");
1049 ok(str == dest, "Expected str == dest, got %p\n", str);
1050 ok(!lstrcmp(str, "C:\\two\\three"), "Expected C:\\two\\three, got %s\n", str);
1051 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
1053 /* try .. as file */
1054 /* try forward slashes */
1055 SetLastError(0xdeadbeef);
1056 lstrcpyA(dest, "control");
1057 str = PathCombineA(dest, "C:\\", "..");
1058 ok(str == dest, "Expected str == dest, got %p\n", str);
1059 ok(!lstrcmp(str, "C:\\"), "Expected C:\\, got %s\n", str);
1060 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
1062 memset(too_long, 'a', LONG_LEN);
1063 too_long[LONG_LEN - 1] = '\0';
1065 /* try a file longer than MAX_PATH */
1066 SetLastError(0xdeadbeef);
1067 lstrcpyA(dest, "control");
1068 str = PathCombineA(dest, "C:\\", too_long);
1069 todo_wine
1071 ok(str == NULL, "Expected str == NULL, got %p\n", str);
1072 ok(lstrlenA(dest) == 0, "Expected 0 length, got %i\n", lstrlenA(dest));
1073 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
1076 /* try a directory longer than MAX_PATH */
1077 SetLastError(0xdeadbeef);
1078 lstrcpyA(dest, "control");
1079 str = PathCombineA(dest, too_long, "one\\two\\three");
1080 todo_wine
1082 ok(str == NULL, "Expected str == NULL, got %p\n", str);
1083 ok(lstrlenA(dest) == 0, "Expected 0 length, got %i\n", lstrlenA(dest));
1084 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
1087 memset(one, 'b', HALF_LEN);
1088 memset(two, 'c', HALF_LEN);
1089 one[HALF_LEN - 1] = '\0';
1090 two[HALF_LEN - 1] = '\0';
1092 /* destination string is longer than MAX_PATH, but not the constituent parts */
1093 SetLastError(0xdeadbeef);
1094 lstrcpyA(dest, "control");
1095 str = PathCombineA(dest, one, two);
1096 todo_wine
1098 ok(str == NULL, "Expected str == NULL, got %p\n", str);
1099 ok(lstrlenA(dest) == 0, "Expected 0 length, got %i\n", lstrlenA(dest));
1101 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
1104 static void test_PathAddBackslash(void)
1106 LPSTR str;
1107 char path[MAX_PATH];
1108 char too_long[LONG_LEN];
1110 /* try a NULL path */
1111 SetLastError(0xdeadbeef);
1112 str = PathAddBackslashA(NULL);
1113 ok(str == NULL, "Expected str == NULL, got %p\n", str);
1114 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
1116 /* try an empty path */
1117 path[0] = '\0';
1118 SetLastError(0xdeadbeef);
1119 str = PathAddBackslashA(path);
1120 ok(str == (path + lstrlenA(path)), "Expected str to point to end of path, got %p\n", str);
1121 ok(lstrlenA(path) == 0, "Expected empty string, got %i\n", lstrlenA(path));
1122 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
1124 /* try a relative path */
1125 lstrcpyA(path, "one\\two");
1126 SetLastError(0xdeadbeef);
1127 str = PathAddBackslashA(path);
1128 ok(str == (path + lstrlenA(path)), "Expected str to point to end of path, got %p\n", str);
1129 ok(!lstrcmp(path, "one\\two\\"), "Expected one\\two\\, got %s\n", path);
1130 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
1132 /* try periods */
1133 lstrcpyA(path, "one\\..\\two");
1134 SetLastError(0xdeadbeef);
1135 str = PathAddBackslashA(path);
1136 ok(str == (path + lstrlenA(path)), "Expected str to point to end of path, got %p\n", str);
1137 ok(!lstrcmp(path, "one\\..\\two\\"), "Expected one\\..\\two\\, got %s\n", path);
1138 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
1140 /* try just a space */
1141 lstrcpyA(path, " ");
1142 SetLastError(0xdeadbeef);
1143 str = PathAddBackslashA(path);
1144 ok(str == (path + lstrlenA(path)), "Expected str to point to end of path, got %p\n", str);
1145 ok(!lstrcmp(path, " \\"), "Expected \\, got %s\n", path);
1146 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
1148 /* path already has backslash */
1149 lstrcpyA(path, "C:\\one\\");
1150 SetLastError(0xdeadbeef);
1151 str = PathAddBackslashA(path);
1152 ok(str == (path + lstrlenA(path)), "Expected str to point to end of path, got %p\n", str);
1153 ok(!lstrcmp(path, "C:\\one\\"), "Expected C:\\one\\, got %s\n", path);
1154 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
1156 memset(too_long, 'a', LONG_LEN);
1157 too_long[LONG_LEN - 1] = '\0';
1159 /* path is longer than MAX_PATH */
1160 SetLastError(0xdeadbeef);
1161 str = PathAddBackslashA(too_long);
1162 ok(str == NULL, "Expected str == NULL, got %p\n", str);
1163 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
1166 static void test_PathAppendA(void)
1168 char path[MAX_PATH];
1169 char too_long[LONG_LEN];
1170 char one[HALF_LEN], two[HALF_LEN];
1171 BOOL res;
1173 lstrcpy(path, "C:\\one");
1175 /* try NULL pszMore */
1176 SetLastError(0xdeadbeef);
1177 res = PathAppendA(path, NULL);
1178 ok(!res, "Expected failure\n");
1179 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
1180 ok(!lstrcmp(path, "C:\\one"), "Expected C:\\one, got %s\n", path);
1182 /* try empty pszMore */
1183 SetLastError(0xdeadbeef);
1184 res = PathAppendA(path, "");
1185 ok(res, "Expected success\n");
1186 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
1187 ok(!lstrcmp(path, "C:\\one"), "Expected C:\\one, got %s\n", path);
1189 /* try NULL pszPath */
1190 SetLastError(0xdeadbeef);
1191 res = PathAppendA(NULL, "two\\three");
1192 ok(!res, "Expected failure\n");
1193 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
1195 /* try empty pszPath */
1196 path[0] = '\0';
1197 SetLastError(0xdeadbeef);
1198 res = PathAppendA(path, "two\\three");
1199 ok(res, "Expected success\n");
1200 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
1201 ok(!lstrcmp(path, "two\\three"), "Expected \\two\\three, got %s\n", path);
1203 /* try empty pszPath and empty pszMore */
1204 path[0] = '\0';
1205 SetLastError(0xdeadbeef);
1206 res = PathAppendA(path, "");
1207 ok(res, "Expected success\n");
1208 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
1209 ok(!lstrcmp(path, "\\"), "Expected \\, got %s\n", path);
1211 /* try legit params */
1212 lstrcpy(path, "C:\\one");
1213 SetLastError(0xdeadbeef);
1214 res = PathAppendA(path, "two\\three");
1215 ok(res, "Expected success\n");
1216 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
1217 ok(!lstrcmp(path, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", path);
1219 /* try pszPath with backslash after it */
1220 lstrcpy(path, "C:\\one\\");
1221 SetLastError(0xdeadbeef);
1222 res = PathAppendA(path, "two\\three");
1223 ok(res, "Expected success\n");
1224 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
1225 ok(!lstrcmp(path, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", path);
1227 /* try pszMore with backslash before it */
1228 lstrcpy(path, "C:\\one");
1229 SetLastError(0xdeadbeef);
1230 res = PathAppendA(path, "\\two\\three");
1231 ok(res, "Expected success\n");
1232 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
1233 ok(!lstrcmp(path, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", path);
1235 /* try pszMore with backslash after it */
1236 lstrcpy(path, "C:\\one");
1237 SetLastError(0xdeadbeef);
1238 res = PathAppendA(path, "two\\three\\");
1239 ok(res, "Expected success\n");
1240 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
1241 ok(!lstrcmp(path, "C:\\one\\two\\three\\"), "Expected C:\\one\\two\\three\\, got %s\n", path);
1243 /* try spaces in pszPath */
1244 lstrcpy(path, "C: \\ one ");
1245 SetLastError(0xdeadbeef);
1246 res = PathAppendA(path, "two\\three");
1247 ok(res, "Expected success\n");
1248 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
1249 ok(!lstrcmp(path, "C: \\ one \\two\\three"), "Expected C: \\ one \\two\\three, got %s\n", path);
1251 /* try spaces in pszMore */
1252 lstrcpy(path, "C:\\one");
1253 SetLastError(0xdeadbeef);
1254 res = PathAppendA(path, " two \\ three ");
1255 ok(res, "Expected success\n");
1256 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
1257 ok(!lstrcmp(path, "C:\\one\\ two \\ three "), "Expected 'C:\\one\\ two \\ three ', got %s\n", path);
1259 /* pszPath is too long */
1260 memset(too_long, 'a', LONG_LEN);
1261 too_long[LONG_LEN - 1] = '\0';
1262 SetLastError(0xdeadbeef);
1263 res = PathAppendA(too_long, "two\\three");
1264 todo_wine
1266 ok(!res, "Expected failure\n");
1267 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
1268 ok(lstrlen(too_long) == 0, "Expected length of too_long to be zero, got %i\n", lstrlen(too_long));
1271 /* pszMore is too long */
1272 lstrcpy(path, "C:\\one");
1273 memset(too_long, 'a', LONG_LEN);
1274 too_long[LONG_LEN - 1] = '\0';
1275 SetLastError(0xdeadbeef);
1276 res = PathAppendA(path, too_long);
1277 todo_wine
1279 ok(!res, "Expected failure\n");
1280 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
1281 ok(lstrlen(path) == 0, "Expected length of path to be zero, got %i\n", lstrlen(path));
1284 /* both params combined are too long */
1285 memset(one, 'a', HALF_LEN);
1286 one[HALF_LEN - 1] = '\0';
1287 memset(two, 'b', HALF_LEN);
1288 two[HALF_LEN - 1] = '\0';
1289 SetLastError(0xdeadbeef);
1290 res = PathAppendA(one, two);
1291 todo_wine
1293 ok(!res, "Expected failure\n");
1294 ok(lstrlen(one) == 0, "Expected length of one to be zero, got %i\n", lstrlen(one));
1296 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
1299 static void test_PathCanonicalizeA(void)
1301 char dest[MAX_PATH];
1302 char too_long[LONG_LEN];
1303 BOOL res;
1305 /* try a NULL source */
1306 lstrcpy(dest, "test");
1307 SetLastError(0xdeadbeef);
1308 res = PathCanonicalizeA(dest, NULL);
1309 ok(!res, "Expected failure\n");
1310 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1311 "Expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
1312 todo_wine
1314 ok(!lstrcmp(dest, "test"), "Expected test, got %s\n", dest);
1317 /* try an empty source */
1318 lstrcpy(dest, "test");
1319 SetLastError(0xdeadbeef);
1320 res = PathCanonicalizeA(dest, "");
1321 ok(res, "Expected success\n");
1322 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
1323 ok(!lstrcmp(dest, "\\"), "Expected \\, got %s\n", dest);
1325 /* try a NULL dest */
1326 SetLastError(0xdeadbeef);
1327 res = PathCanonicalizeA(NULL, "C:\\");
1328 ok(!res, "Expected failure\n");
1329 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1330 "Expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
1332 /* try empty dest */
1333 dest[0] = '\0';
1334 SetLastError(0xdeadbeef);
1335 res = PathCanonicalizeA(dest, "C:\\");
1336 ok(res, "Expected success\n");
1337 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
1338 ok(!lstrcmp(dest, "C:\\"), "Expected C:\\, got %s\n", dest);
1340 /* try non-empty dest */
1341 lstrcpy(dest, "test");
1342 SetLastError(0xdeadbeef);
1343 res = PathCanonicalizeA(dest, "C:\\");
1344 ok(res, "Expected success\n");
1345 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
1346 ok(!lstrcmp(dest, "C:\\"), "Expected C:\\, got %s\n", dest);
1348 /* try a space for source */
1349 lstrcpy(dest, "test");
1350 SetLastError(0xdeadbeef);
1351 res = PathCanonicalizeA(dest, " ");
1352 ok(res, "Expected success\n");
1353 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
1354 ok(!lstrcmp(dest, " "), "Expected ' ', got %s\n", dest);
1356 /* try a relative path */
1357 lstrcpy(dest, "test");
1358 SetLastError(0xdeadbeef);
1359 res = PathCanonicalizeA(dest, "one\\two");
1360 ok(res, "Expected success\n");
1361 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
1362 ok(!lstrcmp(dest, "one\\two"), "Expected one\\two, got %s\n", dest);
1364 /* try current dir and previous dir */
1365 lstrcpy(dest, "test");
1366 SetLastError(0xdeadbeef);
1367 res = PathCanonicalizeA(dest, "C:\\one\\.\\..\\two\\three\\..");
1368 ok(res, "Expected success\n");
1369 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
1370 ok(!lstrcmp(dest, "C:\\two"), "Expected C:\\two, got %s\n", dest);
1372 /* try simple forward slashes */
1373 lstrcpy(dest, "test");
1374 SetLastError(0xdeadbeef);
1375 res = PathCanonicalizeA(dest, "C:\\one/two/three\\four/five\\six");
1376 ok(res, "Expected success\n");
1377 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
1378 ok(!lstrcmp(dest, "C:\\one/two/three\\four/five\\six"),
1379 "Expected C:\\one/two/three\\four/five\\six, got %s\n", dest);
1381 /* try simple forward slashes with same dir */
1382 lstrcpy(dest, "test");
1383 SetLastError(0xdeadbeef);
1384 res = PathCanonicalizeA(dest, "C:\\one/.\\two");
1385 ok(res, "Expected success\n");
1386 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
1387 ok(!lstrcmp(dest, "C:\\one/.\\two"), "Expected C:\\one/.\\two, got %s\n", dest);
1389 /* try simple forward slashes with change dir */
1390 lstrcpy(dest, "test");
1391 SetLastError(0xdeadbeef);
1392 res = PathCanonicalizeA(dest, "C:\\one/.\\two\\..");
1393 ok(res, "Expected success\n");
1394 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
1395 ok(!lstrcmp(dest, "C:\\one/."), "Expected C:\\one/., got %s\n", dest);
1397 /* try forward slashes with change dirs
1398 * NOTE: if there is a forward slash in between two backslashes,
1399 * everything in between the two backslashes is considered on dir
1401 lstrcpy(dest, "test");
1402 SetLastError(0xdeadbeef);
1403 res = PathCanonicalizeA(dest, "C:\\one/.\\..\\two/three\\..\\four/.five");
1404 ok(res, "Expected success\n");
1405 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
1406 ok(!lstrcmp(dest, "C:\\four/.five"), "Expected C:\\four/.five, got %s\n", dest);
1408 /* try src is too long */
1409 memset(too_long, 'a', LONG_LEN);
1410 too_long[LONG_LEN - 1] = '\0';
1411 lstrcpy(dest, "test");
1412 SetLastError(0xdeadbeef);
1413 res = PathCanonicalizeA(dest, too_long);
1414 todo_wine
1416 ok(!res, "Expected failure\n");
1417 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
1419 ok(lstrlen(too_long) == LONG_LEN - 1, "Expected length LONG_LEN - 1, got %i\n", lstrlen(too_long));
1422 static void test_PathFindExtensionA(void)
1424 LPSTR ext;
1425 char path[MAX_PATH];
1426 char too_long[LONG_LEN];
1428 /* try a NULL path */
1429 SetLastError(0xdeadbeef);
1430 ext = PathFindExtensionA(NULL);
1431 ok(ext == NULL, "Expected NULL, got %p\n", ext);
1432 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
1434 /* try an empty path */
1435 path[0] = '\0';
1436 SetLastError(0xdeadbeef);
1437 ext = PathFindExtensionA(path);
1438 ok(ext == path, "Expected ext == path, got %p\n", ext);
1439 ok(lstrlen(ext) == 0, "Expected length 0, got %i\n", lstrlen(ext));
1440 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
1442 /* try a path without an extension */
1443 lstrcpy(path, "file");
1444 SetLastError(0xdeadbeef);
1445 ext = PathFindExtensionA(path);
1446 ok(ext == path + lstrlen(path), "Expected ext == path, got %p\n", ext);
1447 ok(lstrlen(ext) == 0, "Expected length 0, got %i\n", lstrlen(ext));
1448 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
1450 /* try a path with an extension */
1451 lstrcpy(path, "file.txt");
1452 SetLastError(0xdeadbeef);
1453 ext = PathFindExtensionA(path);
1454 ok(ext == path + lstrlen("file"),
1455 "Expected ext == path + lstrlen(\"file\"), got %p\n", ext);
1456 ok(!lstrcmp(ext, ".txt"), "Expected .txt, got %s\n", ext);
1457 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
1459 /* try a path with two extensions */
1460 lstrcpy(path, "file.txt.doc");
1461 SetLastError(0xdeadbeef);
1462 ext = PathFindExtensionA(path);
1463 ok(ext == path + lstrlen("file.txt"),
1464 "Expected ext == path + lstrlen(\"file.txt\"), got %p\n", ext);
1465 ok(!lstrcmp(ext, ".doc"), "Expected .txt, got %s\n", ext);
1466 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
1468 /* try a path longer than MAX_PATH without an extension*/
1469 memset(too_long, 'a', LONG_LEN);
1470 too_long[LONG_LEN - 1] = '\0';
1471 SetLastError(0xdeadbeef);
1472 ext = PathFindExtensionA(too_long);
1473 ok(ext == too_long + LONG_LEN - 1, "Expected ext == too_long + LONG_LEN - 1, got %p\n", ext);
1474 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
1476 /* try a path longer than MAX_PATH with an extension*/
1477 memset(too_long, 'a', LONG_LEN);
1478 too_long[LONG_LEN - 1] = '\0';
1479 lstrcpy(too_long + 300, ".abcde");
1480 too_long[lstrlen(too_long)] = 'a';
1481 SetLastError(0xdeadbeef);
1482 ext = PathFindExtensionA(too_long);
1483 ok(ext == too_long + 300, "Expected ext == too_long + 300, got %p\n", ext);
1484 ok(lstrlen(ext) == LONG_LEN - 301, "Expected LONG_LEN - 301, got %i\n", lstrlen(ext));
1485 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
1488 START_TEST(path)
1490 hShlwapi = LoadLibraryA("shlwapi.dll");
1491 if (!hShlwapi) return;
1493 test_UrlHash();
1494 test_UrlGetPart();
1495 test_UrlCanonicalize();
1496 test_UrlEscape();
1497 test_UrlCombine();
1498 test_UrlCreateFromPath();
1499 test_UrlIs();
1500 test_UrlUnescape();
1502 test_PathSearchAndQualify();
1503 test_PathCreateFromUrl();
1504 test_PathIsUrl();
1506 test_PathAddBackslash();
1507 test_PathMakePretty();
1508 test_PathMatchSpec();
1510 /* For whatever reason, PathIsValidCharA and PathAppendA share the same
1511 * ordinal number in some native versions. Check this to prevent a crash.
1513 pPathIsValidCharA = (void*)GetProcAddress(hShlwapi, (LPSTR)455);
1514 if (pPathIsValidCharA && pPathIsValidCharA != (void*)GetProcAddress(hShlwapi, "PathAppendA"))
1516 test_PathIsValidCharA();
1518 pPathIsValidCharW = (void*)GetProcAddress(hShlwapi, (LPSTR)456);
1519 if (pPathIsValidCharW) test_PathIsValidCharW();
1522 pPathCombineW = (void*)GetProcAddress(hShlwapi, "PathCombineW");
1523 if (pPathCombineW)
1524 test_PathCombineW();
1526 test_PathCombineA();
1527 test_PathAppendA();
1528 test_PathCanonicalizeA();
1529 test_PathFindExtensionA();