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
24 #include "wine/test.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 /* ################ */
42 } TEST_PATHFROMURL[] = {
43 {"file:///c:/foo/ba%5Cr", "c:\\foo\\ba\\r", S_OK},
44 {"file:///c:/foo/../ba%5Cr", "c:\\foo\\..\\ba\\r", S_OK},
45 {"file:///host/c:/foo/bar", "\\host\\c:\\foo\\bar", S_OK},
46 {"file://host/c:/foo/bar", "\\\\hostc:\\foo\\bar", S_OK},
47 {"file://host/c:/foo/bar", "\\\\hostc:\\foo\\bar", S_OK},
48 {"file:\\\\host\\c:\\foo\\bar", "\\\\hostc:\\foo\\bar", S_OK},
49 {"file:\\\\host\\ca\\foo\\bar", "\\\\host\\ca\\foo\\bar", S_OK},
50 {"file:\\\\host\\c|\\foo\\bar", "\\\\hostc|\\foo\\bar", S_OK},
51 {"file:\\%5Chost\\c:\\foo\\bar", "\\\\host\\c:\\foo\\bar", S_OK},
52 {"file:\\\\host\\cx:\\foo\\bar", "\\\\host\\cx:\\foo\\bar", S_OK},
53 {"file://c:/foo/bar", "c:\\foo\\bar", S_OK},
54 {"file://c:/d:/foo/bar", "c:\\d:\\foo\\bar", S_OK},
55 {"file://c|/d|/foo/bar", "c:\\d|\\foo\\bar", S_OK},
56 {"file://host/foo/bar", "\\\\host\\foo\\bar", S_OK},
57 {"file:/foo/bar", "\\foo\\bar", S_OK},
58 {"file:/foo/bar/", "\\foo\\bar\\", S_OK},
59 {"file:foo/bar", "foo\\bar", S_OK},
60 {"file:c:/foo/bar", "c:\\foo\\bar", S_OK},
61 {"file:c|/foo/bar", "c:\\foo\\bar", S_OK},
62 {"file:cx|/foo/bar", "cx|\\foo\\bar", S_OK},
63 {"file:////c:/foo/bar", "c:\\foo\\bar", S_OK},
64 /* {"file:////c:/foo/foo%20bar", "c:\\foo\\foo%20bar", S_OK},*/
66 {"c:\\foo\\bar", NULL, E_INVALIDARG},
67 {"foo/bar", NULL, E_INVALIDARG},
68 {"http://foo/bar", NULL, E_INVALIDARG},
76 } TEST_PATH_IS_URL[] = {
77 {"http://foo/bar", TRUE},
78 {"c:\\foo\\bar", FALSE},
79 {"c:/foo/bar", FALSE},
80 {"foo://foo/bar", TRUE},
83 {"bogusscheme:", TRUE},
84 {"http:partial", TRUE},
85 {"www.winehq.org", FALSE},
86 /* More examples that the user might enter as the browser start page */
87 {"winehq.org", FALSE},
88 {"ftp.winehq.org", FALSE},
89 {"http://winehq.org", TRUE},
90 {"http://www.winehq.org", TRUE},
91 {"https://winehq.org", TRUE},
92 {"https://www.winehq.org", TRUE},
93 {"ftp://winehq.org", TRUE},
94 {"ftp://ftp.winehq.org", TRUE},
95 {"file://does_not_exist.txt", TRUE},
96 {"about:blank", TRUE},
98 {"about:mozilla", TRUE},
99 /* scheme is case independent */
100 {"HTTP://www.winehq.org", TRUE},
101 /* a space at the start is not allowed */
102 {" http://www.winehq.org", FALSE},
110 } TEST_PATH_UNQUOTE_SPACES[] = {
111 { "abcdef", "abcdef" },
112 { "\"abcdef\"", "abcdef" },
113 { "\"abcdef", "\"abcdef" },
114 { "abcdef\"", "abcdef\"" },
115 { "\"\"abcdef\"\"", "\"abcdef\"" },
116 { "abc\"def", "abc\"def" },
117 { "\"abc\"def", "\"abc\"def" },
118 { "\"abc\"def\"", "abc\"def" },
119 { "\'abcdef\'", "\'abcdef\'" },
124 /* ################ */
126 static LPWSTR GetWideString(const char* szString)
128 LPWSTR wszString = HeapAlloc(GetProcessHeap(), 0, (2*INTERNET_MAX_URL_LENGTH) * sizeof(WCHAR));
130 MultiByteToWideChar(0, 0, szString, -1, wszString, INTERNET_MAX_URL_LENGTH);
135 static void FreeWideString(LPWSTR wszString)
137 HeapFree(GetProcessHeap(), 0, wszString);
140 static LPSTR strdupA(LPCSTR p)
143 DWORD len = (strlen(p) + 1);
144 ret = HeapAlloc(GetProcessHeap(), 0, len);
149 /* ################ */
151 static void test_PathSearchAndQualify(void)
153 WCHAR path1[] = {'c',':','\\','f','o','o',0};
154 WCHAR expect1[] = {'c',':','\\','f','o','o',0};
155 WCHAR path2[] = {'c',':','f','o','o',0};
156 WCHAR c_drive[] = {'c',':',0};
157 WCHAR foo[] = {'f','o','o',0};
158 WCHAR path3[] = {'\\','f','o','o',0};
159 WCHAR winini[] = {'w','i','n','.','i','n','i',0};
161 WCHAR cur_dir[MAX_PATH];
162 WCHAR dot[] = {'.',0};
165 ok(PathSearchAndQualifyW(path1, out, MAX_PATH) != 0,
166 "PathSearchAndQualify rets 0\n");
167 ok(!lstrcmpiW(out, expect1), "strings don't match\n");
170 ok(PathSearchAndQualifyW(path2, out, MAX_PATH) != 0,
171 "PathSearchAndQualify rets 0\n");
172 GetFullPathNameW(c_drive, MAX_PATH, cur_dir, NULL);
173 PathAddBackslashW(cur_dir);
174 lstrcatW(cur_dir, foo);
175 ok(!lstrcmpiW(out, cur_dir), "strings don't match\n");
178 ok(PathSearchAndQualifyW(foo, out, MAX_PATH) != 0,
179 "PathSearchAndQualify rets 0\n");
180 GetFullPathNameW(dot, MAX_PATH, cur_dir, NULL);
181 PathAddBackslashW(cur_dir);
182 lstrcatW(cur_dir, foo);
183 ok(!lstrcmpiW(out, cur_dir), "strings don't match\n");
186 ok(PathSearchAndQualifyW(path3, out, MAX_PATH) != 0,
187 "PathSearchAndQualify rets 0\n");
188 GetFullPathNameW(dot, MAX_PATH, cur_dir, NULL);
189 lstrcpyW(cur_dir + 2, path3);
190 ok(!lstrcmpiW(out, cur_dir), "strings don't match\n");
193 ok(PathSearchAndQualifyW(winini, out, MAX_PATH) != 0,
194 "PathSearchAndQualify rets 0\n");
195 if(!SearchPathW(NULL, winini, NULL, MAX_PATH, cur_dir, NULL))
196 GetFullPathNameW(winini, MAX_PATH, cur_dir, NULL);
197 ok(!lstrcmpiW(out, cur_dir), "strings don't match\n");
201 static void test_PathCreateFromUrl(void)
204 char ret_path[INTERNET_MAX_URL_LENGTH];
206 WCHAR ret_pathW[INTERNET_MAX_URL_LENGTH];
208 static const char url[] = "http://www.winehq.org";
210 /* Check ret_path = NULL */
212 ret = PathCreateFromUrlA(url, NULL, &len, 0);
213 ok ( ret == E_INVALIDARG, "got 0x%08x expected E_INVALIDARG\n", ret);
215 for(i = 0; i < sizeof(TEST_PATHFROMURL) / sizeof(TEST_PATHFROMURL[0]); i++) {
216 len = INTERNET_MAX_URL_LENGTH;
217 ret = PathCreateFromUrlA(TEST_PATHFROMURL[i].url, ret_path, &len, 0);
218 ok(ret == TEST_PATHFROMURL[i].ret, "ret %08x from url %s\n", ret, TEST_PATHFROMURL[i].url);
219 if(TEST_PATHFROMURL[i].path) {
220 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);
221 ok(len == strlen(ret_path), "ret len %d from url %s\n", len, TEST_PATHFROMURL[i].url);
223 len = INTERNET_MAX_URL_LENGTH;
224 pathW = GetWideString(TEST_PATHFROMURL[i].path);
225 urlW = GetWideString(TEST_PATHFROMURL[i].url);
226 ret = PathCreateFromUrlW(urlW, ret_pathW, &len, 0);
227 WideCharToMultiByte(CP_ACP, 0, ret_pathW, -1, ret_path, sizeof(ret_path),0,0);
228 ok(ret == TEST_PATHFROMURL[i].ret, "ret %08x from url L\"%s\"\n", ret, TEST_PATHFROMURL[i].url);
229 if(TEST_PATHFROMURL[i].path) {
230 ok(!lstrcmpiW(ret_pathW, pathW), "got %s expected %s from url L\"%s\"\n", ret_path, TEST_PATHFROMURL[i].path, TEST_PATHFROMURL[i].url);
231 ok(len == lstrlenW(ret_pathW), "ret len %d from url L\"%s\"\n", len, TEST_PATHFROMURL[i].url);
233 FreeWideString(urlW);
234 FreeWideString(pathW);
239 static void test_PathIsUrl(void)
244 for(i = 0; i < sizeof(TEST_PATH_IS_URL)/sizeof(TEST_PATH_IS_URL[0]); i++) {
245 ret = PathIsURLA(TEST_PATH_IS_URL[i].path);
246 ok(ret == TEST_PATH_IS_URL[i].expect,
247 "returned %d from path %s, expected %d\n", ret, TEST_PATH_IS_URL[i].path,
248 TEST_PATH_IS_URL[i].expect);
252 static const DWORD SHELL_charclass[] =
254 0x00000000, 0x00000000, 0x00000000, 0x00000000,
255 0x00000000, 0x00000000, 0x00000000, 0x00000000,
256 0x00000000, 0x00000000, 0x00000000, 0x00000000,
257 0x00000000, 0x00000000, 0x00000000, 0x00000000,
258 0x00000000, 0x00000000, 0x00000000, 0x00000000,
259 0x00000000, 0x00000000, 0x00000000, 0x00000000,
260 0x00000000, 0x00000000, 0x00000000, 0x00000000,
261 0x00000000, 0x00000000, 0x00000000, 0x00000000,
262 0x00000080, 0x00000100, 0x00000200, 0x00000100,
263 0x00000100, 0x00000100, 0x00000100, 0x00000100,
264 0x00000100, 0x00000100, 0x00000002, 0x00000100,
265 0x00000040, 0x00000100, 0x00000004, 0x00000000,
266 0x00000100, 0x00000100, 0x00000100, 0x00000100,
267 0x00000100, 0x00000100, 0x00000100, 0x00000100,
268 0x00000100, 0x00000100, 0x00000010, 0x00000020,
269 0x00000000, 0x00000100, 0x00000000, 0x00000001,
270 0x00000100, 0xffffffff, 0xffffffff, 0xffffffff,
271 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
272 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
273 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
274 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
275 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
276 0xffffffff, 0xffffffff, 0xffffffff, 0x00000100,
277 0x00000008, 0x00000100, 0x00000100, 0x00000100,
278 0x00000100, 0xffffffff, 0xffffffff, 0xffffffff,
279 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
280 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
281 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
282 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
283 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
284 0xffffffff, 0xffffffff, 0xffffffff, 0x00000100,
285 0x00000000, 0x00000100, 0x00000100
288 static void test_PathIsValidCharA(void)
293 for (c = 0; c < 0x7f; c++)
295 ret = pPathIsValidCharA( c, ~0U );
296 ok ( ret || !SHELL_charclass[c], "PathIsValidCharA failed: 0x%02x got 0x%08x\n", c, ret );
299 for (c = 0x7f; c <= 0xff; c++)
301 ret = pPathIsValidCharA( c, ~0U );
302 ok ( ret, "PathIsValidCharA failed: 0x%02x got 0x%08x\n", c, ret );
306 static void test_PathIsValidCharW(void)
311 for (c = 0; c < 0x7f; c++)
313 ret = pPathIsValidCharW( c, ~0U );
314 ok ( ret || !SHELL_charclass[c], "PathIsValidCharW failed: 0x%02x got 0x%08x\n", c, ret );
317 for (c = 0x007f; c <= 0xffff; c++)
319 ret = pPathIsValidCharW( c, ~0U );
320 ok ( ret, "PathIsValidCharW failed: 0x%02x got 0x%08x\n", c, ret );
324 static void test_PathMakePretty(void)
328 ok (PathMakePrettyA(NULL) == FALSE, "PathMakePretty: NULL path succeeded\n");
330 ok (PathMakePrettyA(buff) == TRUE, "PathMakePretty: Empty path failed\n");
332 strcpy(buff, "C:\\A LONG FILE NAME WITH \\SPACES.TXT");
333 ok (PathMakePrettyA(buff) == TRUE, "PathMakePretty: Long UC name failed\n");
334 ok (strcmp(buff, "C:\\a long file name with \\spaces.txt") == 0,
335 "PathMakePretty: Long UC name not changed\n");
337 strcpy(buff, "C:\\A LONG FILE NAME WITH \\MixedCase.TXT");
338 ok (PathMakePrettyA(buff) == FALSE, "PathMakePretty: Long MC name succeeded\n");
339 ok (strcmp(buff, "C:\\A LONG FILE NAME WITH \\MixedCase.TXT") == 0,
340 "PathMakePretty: Failed but modified path\n");
342 strcpy(buff, "TEST");
343 ok (PathMakePrettyA(buff) == TRUE, "PathMakePretty: Short name failed\n");
344 ok (strcmp(buff, "Test") == 0, "PathMakePretty: 1st char lowercased %s\n", buff);
347 static void test_PathMatchSpec(void)
349 static const char file[] = "c:\\foo\\bar\\filename.ext";
350 static const char spec1[] = ".ext";
351 static const char spec2[] = "*.ext";
352 static const char spec3[] = "*.ext ";
353 static const char spec4[] = " *.ext";
354 static const char spec5[] = "* .ext";
355 static const char spec6[] = "*. ext";
356 static const char spec7[] = "* . ext";
357 static const char spec8[] = "*.e?t";
358 static const char spec9[] = "filename.ext";
359 static const char spec10[] = "*bar\\filename.ext";
360 static const char spec11[] = " foo; *.ext";
361 static const char spec12[] = "*.ext;*.bar";
362 static const char spec13[] = "*bar*";
364 ok (PathMatchSpecA(file, spec1) == FALSE, "PathMatchSpec: Spec1 failed\n");
365 ok (PathMatchSpecA(file, spec2) == TRUE, "PathMatchSpec: Spec2 failed\n");
366 ok (PathMatchSpecA(file, spec3) == FALSE, "PathMatchSpec: Spec3 failed\n");
367 ok (PathMatchSpecA(file, spec4) == TRUE, "PathMatchSpec: Spec4 failed\n");
368 todo_wine ok (PathMatchSpecA(file, spec5) == TRUE, "PathMatchSpec: Spec5 failed\n");
369 todo_wine ok (PathMatchSpecA(file, spec6) == TRUE, "PathMatchSpec: Spec6 failed\n");
370 ok (PathMatchSpecA(file, spec7) == FALSE, "PathMatchSpec: Spec7 failed\n");
371 ok (PathMatchSpecA(file, spec8) == TRUE, "PathMatchSpec: Spec8 failed\n");
372 ok (PathMatchSpecA(file, spec9) == FALSE, "PathMatchSpec: Spec9 failed\n");
373 ok (PathMatchSpecA(file, spec10) == TRUE, "PathMatchSpec: Spec10 failed\n");
374 ok (PathMatchSpecA(file, spec11) == TRUE, "PathMatchSpec: Spec11 failed\n");
375 ok (PathMatchSpecA(file, spec12) == TRUE, "PathMatchSpec: Spec12 failed\n");
376 ok (PathMatchSpecA(file, spec13) == TRUE, "PathMatchSpec: Spec13 failed\n");
379 static void test_PathCombineW(void)
381 LPWSTR wszString, wszString2;
382 WCHAR wbuf[MAX_PATH+1], wstr1[MAX_PATH] = {'C',':','\\',0}, wstr2[MAX_PATH];
383 static const WCHAR expout[] = {'C',':','\\','A','A',0};
386 wszString2 = HeapAlloc(GetProcessHeap(), 0, MAX_PATH * sizeof(WCHAR));
389 wszString = pPathCombineW(NULL, NULL, NULL);
390 ok (wszString == NULL, "Expected a NULL return\n");
394 wszString = pPathCombineW(wszString2, NULL, NULL);
395 ok (wszString == NULL ||
396 broken(wszString[0] == 'a'), /* Win95 and some W2K */
397 "Expected a NULL return\n");
398 ok (wszString2[0] == 0 ||
399 broken(wszString2[0] == 'a'), /* Win95 and some W2K */
400 "Destination string not empty\n");
402 HeapFree(GetProcessHeap(), 0, wszString2);
405 wstr2[0] = wstr2[1] = wstr2[2] = 'A';
406 for (i=3; i<MAX_PATH/2; i++)
407 wstr1[i] = wstr2[i] = 'A';
408 wstr1[(MAX_PATH/2) - 1] = wstr2[MAX_PATH/2] = 0;
409 memset(wbuf, 0xbf, sizeof(wbuf));
411 wszString = pPathCombineW(wbuf, wstr1, wstr2);
412 ok(wszString == NULL, "Expected a NULL return\n");
414 broken(wbuf[0] == 0xbfbf), /* Win95 and some W2K */
415 "Buffer contains data\n");
417 /* PathCombineW can be used in place */
420 ok(PathCombineW(wstr1, wstr1, wstr2) == wstr1, "Expected a wstr1 return\n");
421 ok(StrCmpW(wstr1, expout) == 0, "Unexpected PathCombine output\n");
425 #define LONG_LEN (MAX_PATH * 2)
426 #define HALF_LEN (MAX_PATH / 2 + 1)
428 static void test_PathCombineA(void)
432 char too_long[LONG_LEN];
433 char one[HALF_LEN], two[HALF_LEN];
436 SetLastError(0xdeadbeef);
437 str = PathCombineA(NULL, "C:\\", "one\\two\\three");
438 ok(str == NULL, "Expected NULL, got %p\n", str);
439 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
441 /* try NULL dest and NULL directory */
442 SetLastError(0xdeadbeef);
443 str = PathCombineA(NULL, NULL, "one\\two\\three");
444 ok(str == NULL, "Expected NULL, got %p\n", str);
445 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
448 SetLastError(0xdeadbeef);
449 str = PathCombineA(NULL, NULL, NULL);
450 ok(str == NULL, "Expected NULL, got %p\n", str);
451 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
453 /* try NULL file part */
454 SetLastError(0xdeadbeef);
455 lstrcpyA(dest, "control");
456 str = PathCombineA(dest, "C:\\", NULL);
457 ok(str == dest, "Expected str == dest, got %p\n", str);
458 ok(!lstrcmp(str, "C:\\"), "Expected C:\\, got %s\n", str);
459 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
461 /* try empty file part */
462 SetLastError(0xdeadbeef);
463 lstrcpyA(dest, "control");
464 str = PathCombineA(dest, "C:\\", "");
465 ok(str == dest, "Expected str == dest, got %p\n", str);
466 ok(!lstrcmp(str, "C:\\"), "Expected C:\\, got %s\n", str);
467 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
469 /* try empty directory and file part */
470 SetLastError(0xdeadbeef);
471 lstrcpyA(dest, "control");
472 str = PathCombineA(dest, "", "");
473 ok(str == dest, "Expected str == dest, got %p\n", str);
474 ok(!lstrcmp(str, "\\") ||
475 broken(!lstrcmp(str, "control")), /* Win95 and some W2K */
476 "Expected \\, got %s\n", str);
477 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
479 /* try NULL directory */
480 SetLastError(0xdeadbeef);
481 lstrcpyA(dest, "control");
482 str = PathCombineA(dest, NULL, "one\\two\\three");
483 ok(str == dest, "Expected str == dest, got %p\n", str);
484 ok(!lstrcmp(str, "one\\two\\three"), "Expected one\\two\\three, got %s\n", str);
485 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
487 /* try NULL directory and empty file part */
488 SetLastError(0xdeadbeef);
489 lstrcpyA(dest, "control");
490 str = PathCombineA(dest, NULL, "");
491 ok(str == dest, "Expected str == dest, got %p\n", str);
492 ok(!lstrcmp(str, "\\") ||
493 broken(!lstrcmp(str, "one\\two\\three")), /* Win95 and some W2K */
494 "Expected \\, got %s\n", str);
495 ok(GetLastError() == 0xdeadbeef ||
496 broken(GetLastError() == ERROR_INVALID_PARAMETER), /* Win95 */
497 "Expected 0xdeadbeef, got %d\n", GetLastError());
499 /* try NULL directory and file part */
500 SetLastError(0xdeadbeef);
501 lstrcpyA(dest, "control");
502 str = PathCombineA(dest, NULL, NULL);
504 broken(str != NULL), /* Win95 and some W2K */
505 "Expected str == NULL, got %p\n", str);
506 ok(lstrlenA(dest) == 0 ||
507 broken(!lstrcmp(dest, "control")), /* Win95 and some W2K */
508 "Expected 0 length, got %i\n", lstrlenA(dest));
509 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
511 /* try directory without backslash */
512 SetLastError(0xdeadbeef);
513 lstrcpyA(dest, "control");
514 str = PathCombineA(dest, "C:", "one\\two\\three");
515 ok(str == dest, "Expected str == dest, got %p\n", str);
516 ok(!lstrcmp(str, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", str);
517 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
519 /* try directory with backslash */
520 SetLastError(0xdeadbeef);
521 lstrcpyA(dest, "control");
522 str = PathCombineA(dest, "C:\\", "one\\two\\three");
523 ok(str == dest, "Expected str == dest, got %p\n", str);
524 ok(!lstrcmp(str, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", str);
525 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
527 /* try directory with backslash and file with prepended backslash */
528 SetLastError(0xdeadbeef);
529 lstrcpyA(dest, "control");
530 str = PathCombineA(dest, "C:\\", "\\one\\two\\three");
531 ok(str == dest, "Expected str == dest, got %p\n", str);
532 ok(!lstrcmp(str, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", str);
533 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
535 /* try previous test, with backslash appended as well */
536 SetLastError(0xdeadbeef);
537 lstrcpyA(dest, "control");
538 str = PathCombineA(dest, "C:\\", "\\one\\two\\three\\");
539 ok(str == dest, "Expected str == dest, got %p\n", str);
540 ok(!lstrcmp(str, "C:\\one\\two\\three\\"), "Expected C:\\one\\two\\three\\, got %s\n", str);
541 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
543 /* try a relative directory */
544 SetLastError(0xdeadbeef);
545 lstrcpyA(dest, "control");
546 str = PathCombineA(dest, "relative\\dir", "\\one\\two\\three\\");
547 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
548 /* Vista fails which probably makes sense as PathCombineA expects an absolute dir */
551 ok(str == dest, "Expected str == dest, got %p\n", str);
552 ok(!lstrcmp(str, "one\\two\\three\\"), "Expected one\\two\\three\\, got %s\n", str);
555 /* try forward slashes */
556 SetLastError(0xdeadbeef);
557 lstrcpyA(dest, "control");
558 str = PathCombineA(dest, "C:\\", "one/two/three\\");
559 ok(str == dest, "Expected str == dest, got %p\n", str);
560 ok(!lstrcmp(str, "C:\\one/two/three\\"), "Expected one/two/three\\, got %s\n", str);
561 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
563 /* try a really weird directory */
564 SetLastError(0xdeadbeef);
565 lstrcpyA(dest, "control");
566 str = PathCombineA(dest, "C:\\/\\/", "\\one\\two\\three\\");
567 ok(str == dest, "Expected str == dest, got %p\n", str);
568 ok(!lstrcmp(str, "C:\\one\\two\\three\\"), "Expected C:\\one\\two\\three\\, got %s\n", str);
569 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
572 SetLastError(0xdeadbeef);
573 lstrcpyA(dest, "control");
574 str = PathCombineA(dest, "C:\\", "one\\..\\two\\.\\three");
575 ok(str == dest, "Expected str == dest, got %p\n", str);
576 ok(!lstrcmp(str, "C:\\two\\three"), "Expected C:\\two\\three, got %s\n", str);
577 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
580 /* try forward slashes */
581 SetLastError(0xdeadbeef);
582 lstrcpyA(dest, "control");
583 str = PathCombineA(dest, "C:\\", "..");
584 ok(str == dest, "Expected str == dest, got %p\n", str);
585 ok(!lstrcmp(str, "C:\\"), "Expected C:\\, got %s\n", str);
586 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
588 memset(too_long, 'a', LONG_LEN);
589 too_long[LONG_LEN - 1] = '\0';
591 /* try a file longer than MAX_PATH */
592 SetLastError(0xdeadbeef);
593 lstrcpyA(dest, "control");
594 str = PathCombineA(dest, "C:\\", too_long);
595 ok(str == NULL, "Expected str == NULL, got %p\n", str);
596 ok(lstrlenA(dest) == 0 ||
597 broken(!lstrcmp(dest, "control")), /* Win95 and some W2K */
598 "Expected 0 length, got %i\n", lstrlenA(dest));
599 todo_wine ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
601 /* try a directory longer than MAX_PATH */
602 SetLastError(0xdeadbeef);
603 lstrcpyA(dest, "control");
604 str = PathCombineA(dest, too_long, "one\\two\\three");
605 ok(str == NULL, "Expected str == NULL, got %p\n", str);
606 ok(lstrlenA(dest) == 0 ||
607 broken(!lstrcmp(dest, "control")), /* Win95 and some W2K */
608 "Expected 0 length, got %i\n", lstrlenA(dest));
609 todo_wine ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
611 memset(one, 'b', HALF_LEN);
612 memset(two, 'c', HALF_LEN);
613 one[HALF_LEN - 1] = '\0';
614 two[HALF_LEN - 1] = '\0';
616 /* destination string is longer than MAX_PATH, but not the constituent parts */
617 SetLastError(0xdeadbeef);
618 lstrcpyA(dest, "control");
619 str = PathCombineA(dest, one, two);
620 ok(str == NULL, "Expected str == NULL, got %p\n", str);
621 ok(lstrlenA(dest) == 0 ||
622 broken(!lstrcmp(dest, "control")), /* Win95 and some W2K */
623 "Expected 0 length, got %i\n", lstrlenA(dest));
624 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
627 static void test_PathAddBackslash(void)
631 char too_long[LONG_LEN];
633 /* try a NULL path */
634 SetLastError(0xdeadbeef);
635 str = PathAddBackslashA(NULL);
636 ok(str == NULL, "Expected str == NULL, got %p\n", str);
637 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
639 /* try an empty path */
641 SetLastError(0xdeadbeef);
642 str = PathAddBackslashA(path);
643 ok(str == (path + lstrlenA(path)), "Expected str to point to end of path, got %p\n", str);
644 ok(lstrlenA(path) == 0, "Expected empty string, got %i\n", lstrlenA(path));
645 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
647 /* try a relative path */
648 lstrcpyA(path, "one\\two");
649 SetLastError(0xdeadbeef);
650 str = PathAddBackslashA(path);
651 ok(str == (path + lstrlenA(path)), "Expected str to point to end of path, got %p\n", str);
652 ok(!lstrcmp(path, "one\\two\\"), "Expected one\\two\\, got %s\n", path);
653 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
656 lstrcpyA(path, "one\\..\\two");
657 SetLastError(0xdeadbeef);
658 str = PathAddBackslashA(path);
659 ok(str == (path + lstrlenA(path)), "Expected str to point to end of path, got %p\n", str);
660 ok(!lstrcmp(path, "one\\..\\two\\"), "Expected one\\..\\two\\, got %s\n", path);
661 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
663 /* try just a space */
665 SetLastError(0xdeadbeef);
666 str = PathAddBackslashA(path);
667 ok(str == (path + lstrlenA(path)), "Expected str to point to end of path, got %p\n", str);
668 ok(!lstrcmp(path, " \\"), "Expected \\, got %s\n", path);
669 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
671 /* path already has backslash */
672 lstrcpyA(path, "C:\\one\\");
673 SetLastError(0xdeadbeef);
674 str = PathAddBackslashA(path);
675 ok(str == (path + lstrlenA(path)), "Expected str to point to end of path, got %p\n", str);
676 ok(!lstrcmp(path, "C:\\one\\"), "Expected C:\\one\\, got %s\n", path);
677 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
679 memset(too_long, 'a', LONG_LEN);
680 too_long[LONG_LEN - 1] = '\0';
682 /* path is longer than MAX_PATH */
683 SetLastError(0xdeadbeef);
684 str = PathAddBackslashA(too_long);
685 ok(str == NULL, "Expected str == NULL, got %p\n", str);
686 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
689 static void test_PathAppendA(void)
692 char too_long[LONG_LEN];
693 char one[HALF_LEN], two[HALF_LEN];
696 lstrcpy(path, "C:\\one");
698 /* try NULL pszMore */
699 SetLastError(0xdeadbeef);
700 res = PathAppendA(path, NULL);
701 ok(!res, "Expected failure\n");
702 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
703 ok(!lstrcmp(path, "C:\\one"), "Expected C:\\one, got %s\n", path);
705 /* try empty pszMore */
706 SetLastError(0xdeadbeef);
707 res = PathAppendA(path, "");
708 ok(res, "Expected success\n");
709 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
710 ok(!lstrcmp(path, "C:\\one"), "Expected C:\\one, got %s\n", path);
712 /* try NULL pszPath */
713 SetLastError(0xdeadbeef);
714 res = PathAppendA(NULL, "two\\three");
715 ok(!res, "Expected failure\n");
716 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
718 /* try empty pszPath */
720 SetLastError(0xdeadbeef);
721 res = PathAppendA(path, "two\\three");
722 ok(res, "Expected success\n");
723 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
724 ok(!lstrcmp(path, "two\\three"), "Expected \\two\\three, got %s\n", path);
726 /* try empty pszPath and empty pszMore */
728 SetLastError(0xdeadbeef);
729 res = PathAppendA(path, "");
730 ok(res, "Expected success\n");
731 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
732 ok(!lstrcmp(path, "\\"), "Expected \\, got %s\n", path);
734 /* try legit params */
735 lstrcpy(path, "C:\\one");
736 SetLastError(0xdeadbeef);
737 res = PathAppendA(path, "two\\three");
738 ok(res, "Expected success\n");
739 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
740 ok(!lstrcmp(path, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", path);
742 /* try pszPath with backslash after it */
743 lstrcpy(path, "C:\\one\\");
744 SetLastError(0xdeadbeef);
745 res = PathAppendA(path, "two\\three");
746 ok(res, "Expected success\n");
747 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
748 ok(!lstrcmp(path, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", path);
750 /* try pszMore with backslash before it */
751 lstrcpy(path, "C:\\one");
752 SetLastError(0xdeadbeef);
753 res = PathAppendA(path, "\\two\\three");
754 ok(res, "Expected success\n");
755 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
756 ok(!lstrcmp(path, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", path);
758 /* try pszMore with backslash after it */
759 lstrcpy(path, "C:\\one");
760 SetLastError(0xdeadbeef);
761 res = PathAppendA(path, "two\\three\\");
762 ok(res, "Expected success\n");
763 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
764 ok(!lstrcmp(path, "C:\\one\\two\\three\\"), "Expected C:\\one\\two\\three\\, got %s\n", path);
766 /* try spaces in pszPath */
767 lstrcpy(path, "C: \\ one ");
768 SetLastError(0xdeadbeef);
769 res = PathAppendA(path, "two\\three");
770 ok(res, "Expected success\n");
771 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
772 ok(!lstrcmp(path, "C: \\ one \\two\\three"), "Expected C: \\ one \\two\\three, got %s\n", path);
774 /* try spaces in pszMore */
775 lstrcpy(path, "C:\\one");
776 SetLastError(0xdeadbeef);
777 res = PathAppendA(path, " two \\ three ");
778 ok(res, "Expected success\n");
779 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
780 ok(!lstrcmp(path, "C:\\one\\ two \\ three "), "Expected 'C:\\one\\ two \\ three ', got %s\n", path);
782 /* pszPath is too long */
783 memset(too_long, 'a', LONG_LEN);
784 too_long[LONG_LEN - 1] = '\0';
785 SetLastError(0xdeadbeef);
786 res = PathAppendA(too_long, "two\\three");
787 ok(!res, "Expected failure\n");
788 todo_wine ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
789 ok(lstrlen(too_long) == 0 ||
790 broken(lstrlen(too_long) == (LONG_LEN - 1)), /* Win95 and some W2K */
791 "Expected length of too_long to be zero, got %i\n", lstrlen(too_long));
793 /* pszMore is too long */
794 lstrcpy(path, "C:\\one");
795 memset(too_long, 'a', LONG_LEN);
796 too_long[LONG_LEN - 1] = '\0';
797 SetLastError(0xdeadbeef);
798 res = PathAppendA(path, too_long);
799 ok(!res, "Expected failure\n");
800 todo_wine ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
801 ok(lstrlen(path) == 0 ||
802 broken(!lstrcmp(path, "C:\\one")), /* Win95 and some W2K */
803 "Expected length of path to be zero, got %i\n", lstrlen(path));
805 /* both params combined are too long */
806 memset(one, 'a', HALF_LEN);
807 one[HALF_LEN - 1] = '\0';
808 memset(two, 'b', HALF_LEN);
809 two[HALF_LEN - 1] = '\0';
810 SetLastError(0xdeadbeef);
811 res = PathAppendA(one, two);
812 ok(!res, "Expected failure\n");
813 ok(lstrlen(one) == 0 ||
814 broken(lstrlen(one) == (HALF_LEN - 1)), /* Win95 and some W2K */
815 "Expected length of one to be zero, got %i\n", lstrlen(one));
816 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
819 static void test_PathCanonicalizeA(void)
821 char dest[LONG_LEN + MAX_PATH];
822 char too_long[LONG_LEN];
825 /* try a NULL source */
826 lstrcpy(dest, "test");
827 SetLastError(0xdeadbeef);
828 res = PathCanonicalizeA(dest, NULL);
829 ok(!res, "Expected failure\n");
830 ok(GetLastError() == ERROR_INVALID_PARAMETER,
831 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
832 ok(dest[0] == 0 || !lstrcmp(dest, "test"),
833 "Expected either an empty string (Vista) or test, got %s\n", dest);
835 /* try an empty source */
836 lstrcpy(dest, "test");
837 SetLastError(0xdeadbeef);
838 res = PathCanonicalizeA(dest, "");
839 ok(res, "Expected success\n");
840 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
841 ok(!lstrcmp(dest, "\\") ||
842 broken(!lstrcmp(dest, "test")), /* Win95 and some W2K */
843 "Expected \\, got %s\n", dest);
845 /* try a NULL dest */
846 SetLastError(0xdeadbeef);
847 res = PathCanonicalizeA(NULL, "C:\\");
848 ok(!res, "Expected failure\n");
849 ok(GetLastError() == ERROR_INVALID_PARAMETER,
850 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
854 SetLastError(0xdeadbeef);
855 res = PathCanonicalizeA(dest, "C:\\");
856 ok(res, "Expected success\n");
857 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
858 ok(!lstrcmp(dest, "C:\\"), "Expected C:\\, got %s\n", dest);
860 /* try non-empty dest */
861 lstrcpy(dest, "test");
862 SetLastError(0xdeadbeef);
863 res = PathCanonicalizeA(dest, "C:\\");
864 ok(res, "Expected success\n");
865 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
866 ok(!lstrcmp(dest, "C:\\"), "Expected C:\\, got %s\n", dest);
868 /* try a space for source */
869 lstrcpy(dest, "test");
870 SetLastError(0xdeadbeef);
871 res = PathCanonicalizeA(dest, " ");
872 ok(res, "Expected success\n");
873 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
874 ok(!lstrcmp(dest, " "), "Expected ' ', got %s\n", dest);
876 /* try a relative path */
877 lstrcpy(dest, "test");
878 SetLastError(0xdeadbeef);
879 res = PathCanonicalizeA(dest, "one\\two");
880 ok(res, "Expected success\n");
881 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
882 ok(!lstrcmp(dest, "one\\two"), "Expected one\\two, got %s\n", dest);
884 /* try current dir and previous dir */
885 lstrcpy(dest, "test");
886 SetLastError(0xdeadbeef);
887 res = PathCanonicalizeA(dest, "C:\\one\\.\\..\\two\\three\\..");
888 ok(res, "Expected success\n");
889 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
890 ok(!lstrcmp(dest, "C:\\two"), "Expected C:\\two, got %s\n", dest);
892 /* try simple forward slashes */
893 lstrcpy(dest, "test");
894 SetLastError(0xdeadbeef);
895 res = PathCanonicalizeA(dest, "C:\\one/two/three\\four/five\\six");
896 ok(res, "Expected success\n");
897 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
898 ok(!lstrcmp(dest, "C:\\one/two/three\\four/five\\six"),
899 "Expected C:\\one/two/three\\four/five\\six, got %s\n", dest);
901 /* try simple forward slashes with same dir */
902 lstrcpy(dest, "test");
903 SetLastError(0xdeadbeef);
904 res = PathCanonicalizeA(dest, "C:\\one/.\\two");
905 ok(res, "Expected success\n");
906 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
907 ok(!lstrcmp(dest, "C:\\one/.\\two"), "Expected C:\\one/.\\two, got %s\n", dest);
909 /* try simple forward slashes with change dir */
910 lstrcpy(dest, "test");
911 SetLastError(0xdeadbeef);
912 res = PathCanonicalizeA(dest, "C:\\one/.\\two\\..");
913 ok(res, "Expected success\n");
914 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
915 ok(!lstrcmp(dest, "C:\\one/.") ||
916 !lstrcmp(dest, "C:\\one/"), /* Vista */
917 "Expected \"C:\\one/.\" or \"C:\\one/\", got \"%s\"\n", dest);
919 /* try forward slashes with change dirs
920 * NOTE: if there is a forward slash in between two backslashes,
921 * everything in between the two backslashes is considered on dir
923 lstrcpy(dest, "test");
924 SetLastError(0xdeadbeef);
925 res = PathCanonicalizeA(dest, "C:\\one/.\\..\\two/three\\..\\four/.five");
926 ok(res, "Expected success\n");
927 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
928 ok(!lstrcmp(dest, "C:\\four/.five"), "Expected C:\\four/.five, got %s\n", dest);
930 /* try src is too long */
931 memset(too_long, 'a', LONG_LEN);
932 too_long[LONG_LEN - 1] = '\0';
933 lstrcpy(dest, "test");
934 SetLastError(0xdeadbeef);
935 res = PathCanonicalizeA(dest, too_long);
937 broken(res), /* Win95, some W2K and XP-SP1 */
938 "Expected failure\n");
941 ok(GetLastError() == 0xdeadbeef || GetLastError() == ERROR_FILENAME_EXCED_RANGE /* Vista */,
942 "Expected 0xdeadbeef or ERROR_FILENAME_EXCED_RANGE, got %d\n", GetLastError());
944 ok(lstrlen(too_long) == LONG_LEN - 1, "Expected length LONG_LEN - 1, got %i\n", lstrlen(too_long));
947 static void test_PathFindExtensionA(void)
951 char too_long[LONG_LEN];
953 /* try a NULL path */
954 SetLastError(0xdeadbeef);
955 ext = PathFindExtensionA(NULL);
956 ok(ext == NULL, "Expected NULL, got %p\n", ext);
957 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
959 /* try an empty path */
961 SetLastError(0xdeadbeef);
962 ext = PathFindExtensionA(path);
963 ok(ext == path, "Expected ext == path, got %p\n", ext);
964 ok(lstrlen(ext) == 0, "Expected length 0, got %i\n", lstrlen(ext));
965 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
967 /* try a path without an extension */
968 lstrcpy(path, "file");
969 SetLastError(0xdeadbeef);
970 ext = PathFindExtensionA(path);
971 ok(ext == path + lstrlen(path), "Expected ext == path, got %p\n", ext);
972 ok(lstrlen(ext) == 0, "Expected length 0, got %i\n", lstrlen(ext));
973 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
975 /* try a path with an extension */
976 lstrcpy(path, "file.txt");
977 SetLastError(0xdeadbeef);
978 ext = PathFindExtensionA(path);
979 ok(ext == path + lstrlen("file"),
980 "Expected ext == path + lstrlen(\"file\"), got %p\n", ext);
981 ok(!lstrcmp(ext, ".txt"), "Expected .txt, got %s\n", ext);
982 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
984 /* try a path with two extensions */
985 lstrcpy(path, "file.txt.doc");
986 SetLastError(0xdeadbeef);
987 ext = PathFindExtensionA(path);
988 ok(ext == path + lstrlen("file.txt"),
989 "Expected ext == path + lstrlen(\"file.txt\"), got %p\n", ext);
990 ok(!lstrcmp(ext, ".doc"), "Expected .txt, got %s\n", ext);
991 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
993 /* try a path longer than MAX_PATH without an extension*/
994 memset(too_long, 'a', LONG_LEN);
995 too_long[LONG_LEN - 1] = '\0';
996 SetLastError(0xdeadbeef);
997 ext = PathFindExtensionA(too_long);
998 ok(ext == too_long + LONG_LEN - 1, "Expected ext == too_long + LONG_LEN - 1, got %p\n", ext);
999 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1001 /* try a path longer than MAX_PATH with an extension*/
1002 memset(too_long, 'a', LONG_LEN);
1003 too_long[LONG_LEN - 1] = '\0';
1004 lstrcpy(too_long + 300, ".abcde");
1005 too_long[lstrlen(too_long)] = 'a';
1006 SetLastError(0xdeadbeef);
1007 ext = PathFindExtensionA(too_long);
1008 ok(ext == too_long + 300, "Expected ext == too_long + 300, got %p\n", ext);
1009 ok(lstrlen(ext) == LONG_LEN - 301, "Expected LONG_LEN - 301, got %i\n", lstrlen(ext));
1010 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1013 static void test_PathBuildRootA(void)
1017 char root_expected[26][4];
1021 /* set up the expected paths */
1022 for (drive = 'A'; drive <= 'Z'; drive++)
1023 sprintf(root_expected[drive - 'A'], "%c:\\", drive);
1025 /* test the expected values */
1026 for (j = 0; j < 26; j++)
1028 SetLastError(0xdeadbeef);
1029 lstrcpy(path, "aaaaaaaaa");
1030 root = PathBuildRootA(path, j);
1031 ok(root == path, "Expected root == path, got %p\n", root);
1032 ok(!lstrcmp(root, root_expected[j]), "Expected %s, got %s\n", root_expected[j], root);
1033 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1036 /* test a negative drive number */
1037 SetLastError(0xdeadbeef);
1038 lstrcpy(path, "aaaaaaaaa");
1039 root = PathBuildRootA(path, -1);
1040 ok(root == path, "Expected root == path, got %p\n", root);
1041 ok(!lstrcmp(path, "aaaaaaaaa") ||
1042 lstrlenA(path) == 0, /* Vista */
1043 "Expected aaaaaaaaa or empty string, got %s\n", path);
1044 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1046 /* test a drive number greater than 25 */
1047 SetLastError(0xdeadbeef);
1048 lstrcpy(path, "aaaaaaaaa");
1049 root = PathBuildRootA(path, 26);
1050 ok(root == path, "Expected root == path, got %p\n", root);
1051 ok(!lstrcmp(path, "aaaaaaaaa") ||
1052 lstrlenA(path) == 0, /* Vista */
1053 "Expected aaaaaaaaa or empty string, got %s\n", path);
1054 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1056 /* length of path is less than 4 */
1057 SetLastError(0xdeadbeef);
1058 lstrcpy(path, "aa");
1059 root = PathBuildRootA(path, 0);
1060 ok(root == path, "Expected root == path, got %p\n", root);
1061 ok(!lstrcmp(path, "A:\\"), "Expected A:\\, got %s\n", path);
1062 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1065 SetLastError(0xdeadbeef);
1066 root = PathBuildRootA(NULL, 0);
1067 ok(root == NULL, "Expected root == NULL, got %p\n", root);
1068 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1071 static void test_PathCommonPrefixA(void)
1073 char path1[MAX_PATH], path2[MAX_PATH];
1077 /* test NULL path1 */
1078 SetLastError(0xdeadbeef);
1079 lstrcpy(path2, "C:\\");
1080 lstrcpy(out, "aaa");
1081 count = PathCommonPrefixA(NULL, path2, out);
1082 ok(count == 0, "Expected 0, got %i\n", count);
1085 ok(!lstrcmp(out, "aaa"), "Expected aaa, got %s\n", out);
1087 ok(!lstrcmp(path2, "C:\\"), "Expected C:\\, got %s\n", path2);
1088 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1090 /* test NULL path2 */
1091 SetLastError(0xdeadbeef);
1092 lstrcpy(path1, "C:\\");
1093 lstrcpy(out, "aaa");
1094 count = PathCommonPrefixA(path1, NULL, out);
1095 ok(count == 0, "Expected 0, got %i\n", count);
1098 ok(!lstrcmp(out, "aaa"), "Expected aaa, got %s\n", out);
1100 ok(!lstrcmp(path1, "C:\\"), "Expected C:\\, got %s\n", path1);
1101 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1103 /* test empty path1 */
1104 SetLastError(0xdeadbeef);
1106 lstrcpy(path2, "C:\\");
1107 lstrcpy(out, "aaa");
1108 count = PathCommonPrefixA(path1, path2, out);
1109 ok(count == 0, "Expected 0, got %i\n", count);
1110 ok(lstrlen(out) == 0, "Expected 0 length out, got %i\n", lstrlen(out));
1111 ok(lstrlen(path1) == 0, "Expected 0 length path1, got %i\n", lstrlen(path1));
1112 ok(!lstrcmp(path2, "C:\\"), "Expected C:\\, got %s\n", path2);
1113 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1115 /* test empty path1 */
1116 SetLastError(0xdeadbeef);
1118 lstrcpy(path1, "C:\\");
1119 lstrcpy(out, "aaa");
1120 count = PathCommonPrefixA(path1, path2, out);
1121 ok(count == 0, "Expected 0, got %i\n", count);
1122 ok(lstrlen(out) == 0, "Expected 0 length out, got %i\n", lstrlen(out));
1123 ok(lstrlen(path2) == 0, "Expected 0 length path2, got %i\n", lstrlen(path2));
1124 ok(!lstrcmp(path1, "C:\\"), "Expected C:\\, got %s\n", path1);
1125 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1127 /* paths are legit, out is NULL */
1128 SetLastError(0xdeadbeef);
1129 lstrcpy(path1, "C:\\");
1130 lstrcpy(path2, "C:\\");
1131 count = PathCommonPrefixA(path1, path2, NULL);
1132 ok(count == 3, "Expected 3, got %i\n", count);
1133 ok(!lstrcmp(path1, "C:\\"), "Expected C:\\, got %s\n", path1);
1134 ok(!lstrcmp(path2, "C:\\"), "Expected C:\\, got %s\n", path2);
1135 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1137 /* all parameters legit */
1138 SetLastError(0xdeadbeef);
1139 lstrcpy(path1, "C:\\");
1140 lstrcpy(path2, "C:\\");
1141 lstrcpy(out, "aaa");
1142 count = PathCommonPrefixA(path1, path2, out);
1143 ok(count == 3, "Expected 3, got %i\n", count);
1144 ok(!lstrcmp(path1, "C:\\"), "Expected C:\\, got %s\n", path1);
1145 ok(!lstrcmp(path2, "C:\\"), "Expected C:\\, got %s\n", path2);
1146 ok(!lstrcmp(out, "C:\\"), "Expected C:\\, got %s\n", out);
1147 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1149 /* path1 and path2 not the same, but common prefix */
1150 SetLastError(0xdeadbeef);
1151 lstrcpy(path1, "C:\\one\\two");
1152 lstrcpy(path2, "C:\\one\\three");
1153 lstrcpy(out, "aaa");
1154 count = PathCommonPrefixA(path1, path2, out);
1155 ok(count == 6, "Expected 6, got %i\n", count);
1156 ok(!lstrcmp(path1, "C:\\one\\two"), "Expected C:\\one\\two, got %s\n", path1);
1157 ok(!lstrcmp(path2, "C:\\one\\three"), "Expected C:\\one\\three, got %s\n", path2);
1158 ok(!lstrcmp(out, "C:\\one"), "Expected C:\\one, got %s\n", out);
1159 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1162 SetLastError(0xdeadbeef);
1163 lstrcpy(path1, "one\\.two");
1164 lstrcpy(path2, "one\\.three");
1165 lstrcpy(out, "aaa");
1166 count = PathCommonPrefixA(path1, path2, out);
1167 ok(count == 3, "Expected 3, got %i\n", count);
1168 ok(!lstrcmp(path1, "one\\.two"), "Expected one\\.two, got %s\n", path1);
1169 ok(!lstrcmp(path2, "one\\.three"), "Expected one\\.three, got %s\n", path2);
1170 ok(!lstrcmp(out, "one"), "Expected one, got %s\n", out);
1171 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1174 SetLastError(0xdeadbeef);
1175 lstrcpy(path1, "one\\..two");
1176 lstrcpy(path2, "one\\..three");
1177 lstrcpy(out, "aaa");
1178 count = PathCommonPrefixA(path1, path2, out);
1179 ok(count == 3, "Expected 3, got %i\n", count);
1180 ok(!lstrcmp(path1, "one\\..two"), "Expected one\\..two, got %s\n", path1);
1181 ok(!lstrcmp(path2, "one\\..three"), "Expected one\\..three, got %s\n", path2);
1182 ok(!lstrcmp(out, "one"), "Expected one, got %s\n", out);
1183 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1185 /* try ... prefix */
1186 SetLastError(0xdeadbeef);
1187 lstrcpy(path1, "one\\...two");
1188 lstrcpy(path2, "one\\...three");
1189 lstrcpy(out, "aaa");
1190 count = PathCommonPrefixA(path1, path2, out);
1191 ok(count == 3, "Expected 3, got %i\n", count);
1192 ok(!lstrcmp(path1, "one\\...two"), "Expected one\\...two, got %s\n", path1);
1193 ok(!lstrcmp(path2, "one\\...three"), "Expected one\\...three, got %s\n", path2);
1194 ok(!lstrcmp(out, "one"), "Expected one, got %s\n", out);
1195 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1198 SetLastError(0xdeadbeef);
1199 lstrcpy(path1, "one\\.\\two");
1200 lstrcpy(path2, "one\\.\\three");
1201 lstrcpy(out, "aaa");
1202 count = PathCommonPrefixA(path1, path2, out);
1203 ok(count == 5, "Expected 5, got %i\n", count);
1204 ok(!lstrcmp(path1, "one\\.\\two"), "Expected one\\.\\two, got %s\n", path1);
1205 ok(!lstrcmp(path2, "one\\.\\three"), "Expected one\\.\\three, got %s\n", path2);
1206 ok(!lstrcmp(out, "one\\."), "Expected one\\., got %s\n", out);
1207 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1209 /* try ..\ prefix */
1210 SetLastError(0xdeadbeef);
1211 lstrcpy(path1, "one\\..\\two");
1212 lstrcpy(path2, "one\\..\\three");
1213 lstrcpy(out, "aaa");
1214 count = PathCommonPrefixA(path1, path2, out);
1215 ok(count == 6, "Expected 6, got %i\n", count);
1216 ok(!lstrcmp(path1, "one\\..\\two"), "Expected one\\..\\two, got %s\n", path1);
1217 ok(!lstrcmp(path2, "one\\..\\three"), "Expected one\\..\\three, got %s\n", path2);
1218 ok(!lstrcmp(out, "one\\.."), "Expected one\\.., got %s\n", out);
1219 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1221 /* try ...\\ prefix */
1222 SetLastError(0xdeadbeef);
1223 lstrcpy(path1, "one\\...\\two");
1224 lstrcpy(path2, "one\\...\\three");
1225 lstrcpy(out, "aaa");
1226 count = PathCommonPrefixA(path1, path2, out);
1227 ok(count == 7, "Expected 7, got %i\n", count);
1228 ok(!lstrcmp(path1, "one\\...\\two"), "Expected one\\...\\two, got %s\n", path1);
1229 ok(!lstrcmp(path2, "one\\...\\three"), "Expected one\\...\\three, got %s\n", path2);
1230 ok(!lstrcmp(out, "one\\..."), "Expected one\\..., got %s\n", out);
1231 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1233 /* try prefix that is not an msdn labeled prefix type */
1234 SetLastError(0xdeadbeef);
1235 lstrcpy(path1, "same");
1236 lstrcpy(path2, "same");
1237 lstrcpy(out, "aaa");
1238 count = PathCommonPrefixA(path1, path2, out);
1239 ok(count == 4, "Expected 4, got %i\n", count);
1240 ok(!lstrcmp(path1, "same"), "Expected same, got %s\n", path1);
1241 ok(!lstrcmp(path2, "same"), "Expected same, got %s\n", path2);
1242 ok(!lstrcmp(out, "same"), "Expected same, got %s\n", out);
1243 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1245 /* try . after directory */
1246 SetLastError(0xdeadbeef);
1247 lstrcpy(path1, "one\\mid.\\two");
1248 lstrcpy(path2, "one\\mid.\\three");
1249 lstrcpy(out, "aaa");
1250 count = PathCommonPrefixA(path1, path2, out);
1251 ok(count == 8, "Expected 8, got %i\n", count);
1252 ok(!lstrcmp(path1, "one\\mid.\\two"), "Expected one\\mid.\\two, got %s\n", path1);
1253 ok(!lstrcmp(path2, "one\\mid.\\three"), "Expected one\\mid.\\three, got %s\n", path2);
1254 ok(!lstrcmp(out, "one\\mid."), "Expected one\\mid., got %s\n", out);
1255 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1257 /* try . in the middle of a directory */
1258 SetLastError(0xdeadbeef);
1259 lstrcpy(path1, "one\\mid.end\\two");
1260 lstrcpy(path2, "one\\mid.end\\three");
1261 lstrcpy(out, "aaa");
1262 count = PathCommonPrefixA(path1, path2, out);
1263 ok(count == 11, "Expected 11, got %i\n", count);
1264 ok(!lstrcmp(path1, "one\\mid.end\\two"), "Expected one\\mid.end\\two, got %s\n", path1);
1265 ok(!lstrcmp(path2, "one\\mid.end\\three"), "Expected one\\mid.end\\three, got %s\n", path2);
1266 ok(!lstrcmp(out, "one\\mid.end"), "Expected one\\mid.end, got %s\n", out);
1267 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1269 /* try comparing a .. with the expanded path */
1270 SetLastError(0xdeadbeef);
1271 lstrcpy(path1, "one\\..\\two");
1272 lstrcpy(path2, "two");
1273 lstrcpy(out, "aaa");
1274 count = PathCommonPrefixA(path1, path2, out);
1275 ok(count == 0, "Expected 0, got %i\n", count);
1276 ok(!lstrcmp(path1, "one\\..\\two"), "Expected one\\..\\two, got %s\n", path1);
1277 ok(!lstrcmp(path2, "two"), "Expected two, got %s\n", path2);
1278 ok(lstrlen(out) == 0, "Expected 0 length out, got %i\n", lstrlen(out));
1279 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1282 static void test_PathUnquoteSpaces(void)
1285 for(i = 0; i < sizeof(TEST_PATH_UNQUOTE_SPACES) / sizeof(TEST_PATH_UNQUOTE_SPACES[0]); i++)
1287 char *path = strdupA(TEST_PATH_UNQUOTE_SPACES[i].path);
1288 WCHAR *pathW = GetWideString(TEST_PATH_UNQUOTE_SPACES[i].path);
1289 WCHAR *resultW = GetWideString(TEST_PATH_UNQUOTE_SPACES[i].result);
1291 PathUnquoteSpacesA(path);
1292 ok(!strcmp(path, TEST_PATH_UNQUOTE_SPACES[i].result), "%s (A): got %s expected %s\n",
1293 TEST_PATH_UNQUOTE_SPACES[i].path, path,
1294 TEST_PATH_UNQUOTE_SPACES[i].result);
1296 PathUnquoteSpacesW(pathW);
1297 ok(!lstrcmpW(pathW, resultW), "%s (W): strings differ\n",
1298 TEST_PATH_UNQUOTE_SPACES[i].path);
1299 FreeWideString(pathW);
1300 FreeWideString(resultW);
1301 HeapFree(GetProcessHeap(), 0, path);
1305 /* ################ */
1309 hShlwapi = GetModuleHandleA("shlwapi.dll");
1311 test_PathSearchAndQualify();
1312 test_PathCreateFromUrl();
1315 test_PathAddBackslash();
1316 test_PathMakePretty();
1317 test_PathMatchSpec();
1319 /* For whatever reason, PathIsValidCharA and PathAppendA share the same
1320 * ordinal number in some native versions. Check this to prevent a crash.
1322 pPathIsValidCharA = (void*)GetProcAddress(hShlwapi, (LPSTR)455);
1323 if (pPathIsValidCharA && pPathIsValidCharA != (void*)GetProcAddress(hShlwapi, "PathAppendA"))
1325 test_PathIsValidCharA();
1327 pPathIsValidCharW = (void*)GetProcAddress(hShlwapi, (LPSTR)456);
1328 if (pPathIsValidCharW) test_PathIsValidCharW();
1331 pPathCombineW = (void*)GetProcAddress(hShlwapi, "PathCombineW");
1333 test_PathCombineW();
1335 test_PathCombineA();
1337 test_PathCanonicalizeA();
1338 test_PathFindExtensionA();
1339 test_PathBuildRootA();
1340 test_PathCommonPrefixA();
1341 test_PathUnquoteSpaces();