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, "Expected a NULL return\n");
396 ok (wszString2[0] == 0, "Destination string not empty\n");
398 HeapFree(GetProcessHeap(), 0, wszString2);
401 wstr2[0] = wstr2[1] = wstr2[2] = 'A';
402 for (i=3; i<MAX_PATH/2; i++)
403 wstr1[i] = wstr2[i] = 'A';
404 wstr1[(MAX_PATH/2) - 1] = wstr2[MAX_PATH/2] = 0;
405 memset(wbuf, 0xbf, sizeof(wbuf));
407 wszString = pPathCombineW(wbuf, wstr1, wstr2);
408 ok(wszString == NULL, "Expected a NULL return\n");
409 ok(wbuf[0] == 0, "Buffer contains data\n");
411 /* PathCombineW can be used in place */
414 ok(PathCombineW(wstr1, wstr1, wstr2) == wstr1, "Expected a wstr1 return\n");
415 ok(StrCmpW(wstr1, expout) == 0, "Unexpected PathCombine output\n");
419 #define LONG_LEN (MAX_PATH * 2)
420 #define HALF_LEN (MAX_PATH / 2 + 1)
422 static void test_PathCombineA(void)
426 char too_long[LONG_LEN];
427 char one[HALF_LEN], two[HALF_LEN];
430 SetLastError(0xdeadbeef);
431 str = PathCombineA(NULL, "C:\\", "one\\two\\three");
432 ok(str == NULL, "Expected NULL, got %p\n", str);
433 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
435 /* try NULL dest and NULL directory */
436 SetLastError(0xdeadbeef);
437 str = PathCombineA(NULL, NULL, "one\\two\\three");
438 ok(str == NULL, "Expected NULL, got %p\n", str);
439 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
442 SetLastError(0xdeadbeef);
443 str = PathCombineA(NULL, NULL, NULL);
444 ok(str == NULL, "Expected NULL, got %p\n", str);
445 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
447 /* try NULL file part */
448 SetLastError(0xdeadbeef);
449 lstrcpyA(dest, "control");
450 str = PathCombineA(dest, "C:\\", NULL);
451 ok(str == dest, "Expected str == dest, got %p\n", str);
452 ok(!lstrcmp(str, "C:\\"), "Expected C:\\, got %s\n", str);
453 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
455 /* try empty file part */
456 SetLastError(0xdeadbeef);
457 lstrcpyA(dest, "control");
458 str = PathCombineA(dest, "C:\\", "");
459 ok(str == dest, "Expected str == dest, got %p\n", str);
460 ok(!lstrcmp(str, "C:\\"), "Expected C:\\, got %s\n", str);
461 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
463 /* try empty directory and file part */
464 SetLastError(0xdeadbeef);
465 lstrcpyA(dest, "control");
466 str = PathCombineA(dest, "", "");
467 ok(str == dest, "Expected str == dest, got %p\n", str);
468 ok(!lstrcmp(str, "\\"), "Expected \\, got %s\n", str);
469 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
471 /* try NULL directory */
472 SetLastError(0xdeadbeef);
473 lstrcpyA(dest, "control");
474 str = PathCombineA(dest, NULL, "one\\two\\three");
475 ok(str == dest, "Expected str == dest, got %p\n", str);
476 ok(!lstrcmp(str, "one\\two\\three"), "Expected one\\two\\three, got %s\n", str);
477 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
479 /* try NULL directory and empty file part */
480 SetLastError(0xdeadbeef);
481 lstrcpyA(dest, "control");
482 str = PathCombineA(dest, NULL, "");
483 ok(str == dest, "Expected str == dest, got %p\n", str);
484 ok(!lstrcmp(str, "\\"), "Expected \\, got %s\n", str);
485 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
487 /* try NULL directory and file part */
488 SetLastError(0xdeadbeef);
489 lstrcpyA(dest, "control");
490 str = PathCombineA(dest, NULL, NULL);
491 ok(str == NULL, "Expected str == NULL, got %p\n", str);
492 ok(lstrlenA(dest) == 0, "Expected 0 length, got %i\n", lstrlenA(dest));
493 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
495 /* try directory without backslash */
496 SetLastError(0xdeadbeef);
497 lstrcpyA(dest, "control");
498 str = PathCombineA(dest, "C:", "one\\two\\three");
499 ok(str == dest, "Expected str == dest, got %p\n", str);
500 ok(!lstrcmp(str, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", str);
501 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
503 /* try directory with backslash */
504 SetLastError(0xdeadbeef);
505 lstrcpyA(dest, "control");
506 str = PathCombineA(dest, "C:\\", "one\\two\\three");
507 ok(str == dest, "Expected str == dest, got %p\n", str);
508 ok(!lstrcmp(str, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", str);
509 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
511 /* try directory with backslash and file with prepended 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 previous test, with backslash appended as well */
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 a relative directory */
528 SetLastError(0xdeadbeef);
529 lstrcpyA(dest, "control");
530 str = PathCombineA(dest, "relative\\dir", "\\one\\two\\three\\");
531 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
532 /* Vista fails which probably makes sense as PathCombineA expects an absolute dir */
535 ok(str == dest, "Expected str == dest, got %p\n", str);
536 ok(!lstrcmp(str, "one\\two\\three\\"), "Expected one\\two\\three\\, got %s\n", str);
539 /* try forward slashes */
540 SetLastError(0xdeadbeef);
541 lstrcpyA(dest, "control");
542 str = PathCombineA(dest, "C:\\", "one/two/three\\");
543 ok(str == dest, "Expected str == dest, got %p\n", str);
544 ok(!lstrcmp(str, "C:\\one/two/three\\"), "Expected one/two/three\\, got %s\n", str);
545 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
547 /* try a really weird directory */
548 SetLastError(0xdeadbeef);
549 lstrcpyA(dest, "control");
550 str = PathCombineA(dest, "C:\\/\\/", "\\one\\two\\three\\");
551 ok(str == dest, "Expected str == dest, got %p\n", str);
552 ok(!lstrcmp(str, "C:\\one\\two\\three\\"), "Expected C:\\one\\two\\three\\, got %s\n", str);
553 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
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:\\two\\three"), "Expected C:\\two\\three, got %s\n", str);
561 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
564 /* try forward slashes */
565 SetLastError(0xdeadbeef);
566 lstrcpyA(dest, "control");
567 str = PathCombineA(dest, "C:\\", "..");
568 ok(str == dest, "Expected str == dest, got %p\n", str);
569 ok(!lstrcmp(str, "C:\\"), "Expected C:\\, got %s\n", str);
570 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
572 memset(too_long, 'a', LONG_LEN);
573 too_long[LONG_LEN - 1] = '\0';
575 /* try a file longer than MAX_PATH */
576 SetLastError(0xdeadbeef);
577 lstrcpyA(dest, "control");
578 str = PathCombineA(dest, "C:\\", too_long);
579 ok(str == NULL, "Expected str == NULL, got %p\n", str);
580 ok(lstrlenA(dest) == 0, "Expected 0 length, got %i\n", lstrlenA(dest));
581 todo_wine ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
583 /* try a directory longer than MAX_PATH */
584 SetLastError(0xdeadbeef);
585 lstrcpyA(dest, "control");
586 str = PathCombineA(dest, too_long, "one\\two\\three");
587 ok(str == NULL, "Expected str == NULL, got %p\n", str);
588 ok(lstrlenA(dest) == 0, "Expected 0 length, got %i\n", lstrlenA(dest));
589 todo_wine ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
591 memset(one, 'b', HALF_LEN);
592 memset(two, 'c', HALF_LEN);
593 one[HALF_LEN - 1] = '\0';
594 two[HALF_LEN - 1] = '\0';
596 /* destination string is longer than MAX_PATH, but not the constituent parts */
597 SetLastError(0xdeadbeef);
598 lstrcpyA(dest, "control");
599 str = PathCombineA(dest, one, two);
600 ok(str == NULL, "Expected str == NULL, got %p\n", str);
601 ok(lstrlenA(dest) == 0, "Expected 0 length, got %i\n", lstrlenA(dest));
602 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
605 static void test_PathAddBackslash(void)
609 char too_long[LONG_LEN];
611 /* try a NULL path */
612 SetLastError(0xdeadbeef);
613 str = PathAddBackslashA(NULL);
614 ok(str == NULL, "Expected str == NULL, got %p\n", str);
615 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
617 /* try an empty path */
619 SetLastError(0xdeadbeef);
620 str = PathAddBackslashA(path);
621 ok(str == (path + lstrlenA(path)), "Expected str to point to end of path, got %p\n", str);
622 ok(lstrlenA(path) == 0, "Expected empty string, got %i\n", lstrlenA(path));
623 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
625 /* try a relative path */
626 lstrcpyA(path, "one\\two");
627 SetLastError(0xdeadbeef);
628 str = PathAddBackslashA(path);
629 ok(str == (path + lstrlenA(path)), "Expected str to point to end of path, got %p\n", str);
630 ok(!lstrcmp(path, "one\\two\\"), "Expected one\\two\\, got %s\n", path);
631 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
634 lstrcpyA(path, "one\\..\\two");
635 SetLastError(0xdeadbeef);
636 str = PathAddBackslashA(path);
637 ok(str == (path + lstrlenA(path)), "Expected str to point to end of path, got %p\n", str);
638 ok(!lstrcmp(path, "one\\..\\two\\"), "Expected one\\..\\two\\, got %s\n", path);
639 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
641 /* try just a space */
643 SetLastError(0xdeadbeef);
644 str = PathAddBackslashA(path);
645 ok(str == (path + lstrlenA(path)), "Expected str to point to end of path, got %p\n", str);
646 ok(!lstrcmp(path, " \\"), "Expected \\, got %s\n", path);
647 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
649 /* path already has backslash */
650 lstrcpyA(path, "C:\\one\\");
651 SetLastError(0xdeadbeef);
652 str = PathAddBackslashA(path);
653 ok(str == (path + lstrlenA(path)), "Expected str to point to end of path, got %p\n", str);
654 ok(!lstrcmp(path, "C:\\one\\"), "Expected C:\\one\\, got %s\n", path);
655 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
657 memset(too_long, 'a', LONG_LEN);
658 too_long[LONG_LEN - 1] = '\0';
660 /* path is longer than MAX_PATH */
661 SetLastError(0xdeadbeef);
662 str = PathAddBackslashA(too_long);
663 ok(str == NULL, "Expected str == NULL, got %p\n", str);
664 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
667 static void test_PathAppendA(void)
670 char too_long[LONG_LEN];
671 char one[HALF_LEN], two[HALF_LEN];
674 lstrcpy(path, "C:\\one");
676 /* try NULL pszMore */
677 SetLastError(0xdeadbeef);
678 res = PathAppendA(path, NULL);
679 ok(!res, "Expected failure\n");
680 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
681 ok(!lstrcmp(path, "C:\\one"), "Expected C:\\one, got %s\n", path);
683 /* try empty pszMore */
684 SetLastError(0xdeadbeef);
685 res = PathAppendA(path, "");
686 ok(res, "Expected success\n");
687 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
688 ok(!lstrcmp(path, "C:\\one"), "Expected C:\\one, got %s\n", path);
690 /* try NULL pszPath */
691 SetLastError(0xdeadbeef);
692 res = PathAppendA(NULL, "two\\three");
693 ok(!res, "Expected failure\n");
694 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
696 /* try empty pszPath */
698 SetLastError(0xdeadbeef);
699 res = PathAppendA(path, "two\\three");
700 ok(res, "Expected success\n");
701 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
702 ok(!lstrcmp(path, "two\\three"), "Expected \\two\\three, got %s\n", path);
704 /* try empty pszPath and 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, "\\"), "Expected \\, got %s\n", path);
712 /* try legit params */
713 lstrcpy(path, "C:\\one");
714 SetLastError(0xdeadbeef);
715 res = PathAppendA(path, "two\\three");
716 ok(res, "Expected success\n");
717 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
718 ok(!lstrcmp(path, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", path);
720 /* try pszPath with backslash after it */
721 lstrcpy(path, "C:\\one\\");
722 SetLastError(0xdeadbeef);
723 res = PathAppendA(path, "two\\three");
724 ok(res, "Expected success\n");
725 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
726 ok(!lstrcmp(path, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", path);
728 /* try pszMore with backslash before it */
729 lstrcpy(path, "C:\\one");
730 SetLastError(0xdeadbeef);
731 res = PathAppendA(path, "\\two\\three");
732 ok(res, "Expected success\n");
733 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
734 ok(!lstrcmp(path, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", path);
736 /* try pszMore with backslash after it */
737 lstrcpy(path, "C:\\one");
738 SetLastError(0xdeadbeef);
739 res = PathAppendA(path, "two\\three\\");
740 ok(res, "Expected success\n");
741 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
742 ok(!lstrcmp(path, "C:\\one\\two\\three\\"), "Expected C:\\one\\two\\three\\, got %s\n", path);
744 /* try spaces in pszPath */
745 lstrcpy(path, "C: \\ one ");
746 SetLastError(0xdeadbeef);
747 res = PathAppendA(path, "two\\three");
748 ok(res, "Expected success\n");
749 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
750 ok(!lstrcmp(path, "C: \\ one \\two\\three"), "Expected C: \\ one \\two\\three, got %s\n", path);
752 /* try spaces in pszMore */
753 lstrcpy(path, "C:\\one");
754 SetLastError(0xdeadbeef);
755 res = PathAppendA(path, " two \\ three ");
756 ok(res, "Expected success\n");
757 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
758 ok(!lstrcmp(path, "C:\\one\\ two \\ three "), "Expected 'C:\\one\\ two \\ three ', got %s\n", path);
760 /* pszPath is too long */
761 memset(too_long, 'a', LONG_LEN);
762 too_long[LONG_LEN - 1] = '\0';
763 SetLastError(0xdeadbeef);
764 res = PathAppendA(too_long, "two\\three");
765 ok(!res, "Expected failure\n");
766 todo_wine ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
767 ok(lstrlen(too_long) == 0, "Expected length of too_long to be zero, got %i\n", lstrlen(too_long));
769 /* pszMore is too long */
770 lstrcpy(path, "C:\\one");
771 memset(too_long, 'a', LONG_LEN);
772 too_long[LONG_LEN - 1] = '\0';
773 SetLastError(0xdeadbeef);
774 res = PathAppendA(path, too_long);
775 ok(!res, "Expected failure\n");
776 todo_wine ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
777 ok(lstrlen(path) == 0, "Expected length of path to be zero, got %i\n", lstrlen(path));
779 /* both params combined are too long */
780 memset(one, 'a', HALF_LEN);
781 one[HALF_LEN - 1] = '\0';
782 memset(two, 'b', HALF_LEN);
783 two[HALF_LEN - 1] = '\0';
784 SetLastError(0xdeadbeef);
785 res = PathAppendA(one, two);
786 ok(!res, "Expected failure\n");
787 ok(lstrlen(one) == 0, "Expected length of one to be zero, got %i\n", lstrlen(one));
788 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
791 static void test_PathCanonicalizeA(void)
793 char dest[LONG_LEN + MAX_PATH];
794 char too_long[LONG_LEN];
797 /* try a NULL source */
798 lstrcpy(dest, "test");
799 SetLastError(0xdeadbeef);
800 res = PathCanonicalizeA(dest, NULL);
801 ok(!res, "Expected failure\n");
802 ok(GetLastError() == ERROR_INVALID_PARAMETER,
803 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
804 ok(dest[0] == 0 || !lstrcmp(dest, "test"),
805 "Expected either an empty string (Vista) or test, got %s\n", dest);
807 /* try an empty source */
808 lstrcpy(dest, "test");
809 SetLastError(0xdeadbeef);
810 res = PathCanonicalizeA(dest, "");
811 ok(res, "Expected success\n");
812 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
813 ok(!lstrcmp(dest, "\\"), "Expected \\, got %s\n", dest);
815 /* try a NULL dest */
816 SetLastError(0xdeadbeef);
817 res = PathCanonicalizeA(NULL, "C:\\");
818 ok(!res, "Expected failure\n");
819 ok(GetLastError() == ERROR_INVALID_PARAMETER,
820 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
824 SetLastError(0xdeadbeef);
825 res = PathCanonicalizeA(dest, "C:\\");
826 ok(res, "Expected success\n");
827 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
828 ok(!lstrcmp(dest, "C:\\"), "Expected C:\\, got %s\n", dest);
830 /* try non-empty dest */
831 lstrcpy(dest, "test");
832 SetLastError(0xdeadbeef);
833 res = PathCanonicalizeA(dest, "C:\\");
834 ok(res, "Expected success\n");
835 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
836 ok(!lstrcmp(dest, "C:\\"), "Expected C:\\, got %s\n", dest);
838 /* try a space for source */
839 lstrcpy(dest, "test");
840 SetLastError(0xdeadbeef);
841 res = PathCanonicalizeA(dest, " ");
842 ok(res, "Expected success\n");
843 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
844 ok(!lstrcmp(dest, " "), "Expected ' ', got %s\n", dest);
846 /* try a relative path */
847 lstrcpy(dest, "test");
848 SetLastError(0xdeadbeef);
849 res = PathCanonicalizeA(dest, "one\\two");
850 ok(res, "Expected success\n");
851 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
852 ok(!lstrcmp(dest, "one\\two"), "Expected one\\two, got %s\n", dest);
854 /* try current dir and previous dir */
855 lstrcpy(dest, "test");
856 SetLastError(0xdeadbeef);
857 res = PathCanonicalizeA(dest, "C:\\one\\.\\..\\two\\three\\..");
858 ok(res, "Expected success\n");
859 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
860 ok(!lstrcmp(dest, "C:\\two"), "Expected C:\\two, got %s\n", dest);
862 /* try simple forward slashes */
863 lstrcpy(dest, "test");
864 SetLastError(0xdeadbeef);
865 res = PathCanonicalizeA(dest, "C:\\one/two/three\\four/five\\six");
866 ok(res, "Expected success\n");
867 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
868 ok(!lstrcmp(dest, "C:\\one/two/three\\four/five\\six"),
869 "Expected C:\\one/two/three\\four/five\\six, got %s\n", dest);
871 /* try simple forward slashes with same dir */
872 lstrcpy(dest, "test");
873 SetLastError(0xdeadbeef);
874 res = PathCanonicalizeA(dest, "C:\\one/.\\two");
875 ok(res, "Expected success\n");
876 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
877 ok(!lstrcmp(dest, "C:\\one/.\\two"), "Expected C:\\one/.\\two, got %s\n", dest);
879 /* try simple forward slashes with change dir */
880 lstrcpy(dest, "test");
881 SetLastError(0xdeadbeef);
882 res = PathCanonicalizeA(dest, "C:\\one/.\\two\\..");
883 ok(res, "Expected success\n");
884 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
885 ok(!lstrcmp(dest, "C:\\one/.") ||
886 !lstrcmp(dest, "C:\\one/"), /* Vista */
887 "Expected \"C:\\one/.\" or \"C:\\one/\", got \"%s\"\n", dest);
889 /* try forward slashes with change dirs
890 * NOTE: if there is a forward slash in between two backslashes,
891 * everything in between the two backslashes is considered on dir
893 lstrcpy(dest, "test");
894 SetLastError(0xdeadbeef);
895 res = PathCanonicalizeA(dest, "C:\\one/.\\..\\two/three\\..\\four/.five");
896 ok(res, "Expected success\n");
897 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
898 ok(!lstrcmp(dest, "C:\\four/.five"), "Expected C:\\four/.five, got %s\n", dest);
900 /* try src is too long */
901 memset(too_long, 'a', LONG_LEN);
902 too_long[LONG_LEN - 1] = '\0';
903 lstrcpy(dest, "test");
904 SetLastError(0xdeadbeef);
905 res = PathCanonicalizeA(dest, too_long);
906 ok(!res, "Expected failure\n");
909 ok(GetLastError() == 0xdeadbeef || GetLastError() == ERROR_FILENAME_EXCED_RANGE /* Vista */,
910 "Expected 0xdeadbeef or ERROR_FILENAME_EXCED_RANGE, got %d\n", GetLastError());
912 ok(lstrlen(too_long) == LONG_LEN - 1, "Expected length LONG_LEN - 1, got %i\n", lstrlen(too_long));
915 static void test_PathFindExtensionA(void)
919 char too_long[LONG_LEN];
921 /* try a NULL path */
922 SetLastError(0xdeadbeef);
923 ext = PathFindExtensionA(NULL);
924 ok(ext == NULL, "Expected NULL, got %p\n", ext);
925 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
927 /* try an empty path */
929 SetLastError(0xdeadbeef);
930 ext = PathFindExtensionA(path);
931 ok(ext == path, "Expected ext == path, got %p\n", ext);
932 ok(lstrlen(ext) == 0, "Expected length 0, got %i\n", lstrlen(ext));
933 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
935 /* try a path without an extension */
936 lstrcpy(path, "file");
937 SetLastError(0xdeadbeef);
938 ext = PathFindExtensionA(path);
939 ok(ext == path + lstrlen(path), "Expected ext == path, got %p\n", ext);
940 ok(lstrlen(ext) == 0, "Expected length 0, got %i\n", lstrlen(ext));
941 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
943 /* try a path with an extension */
944 lstrcpy(path, "file.txt");
945 SetLastError(0xdeadbeef);
946 ext = PathFindExtensionA(path);
947 ok(ext == path + lstrlen("file"),
948 "Expected ext == path + lstrlen(\"file\"), got %p\n", ext);
949 ok(!lstrcmp(ext, ".txt"), "Expected .txt, got %s\n", ext);
950 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
952 /* try a path with two extensions */
953 lstrcpy(path, "file.txt.doc");
954 SetLastError(0xdeadbeef);
955 ext = PathFindExtensionA(path);
956 ok(ext == path + lstrlen("file.txt"),
957 "Expected ext == path + lstrlen(\"file.txt\"), got %p\n", ext);
958 ok(!lstrcmp(ext, ".doc"), "Expected .txt, got %s\n", ext);
959 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
961 /* try a path longer than MAX_PATH without an extension*/
962 memset(too_long, 'a', LONG_LEN);
963 too_long[LONG_LEN - 1] = '\0';
964 SetLastError(0xdeadbeef);
965 ext = PathFindExtensionA(too_long);
966 ok(ext == too_long + LONG_LEN - 1, "Expected ext == too_long + LONG_LEN - 1, got %p\n", ext);
967 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
969 /* try a path longer than MAX_PATH with an extension*/
970 memset(too_long, 'a', LONG_LEN);
971 too_long[LONG_LEN - 1] = '\0';
972 lstrcpy(too_long + 300, ".abcde");
973 too_long[lstrlen(too_long)] = 'a';
974 SetLastError(0xdeadbeef);
975 ext = PathFindExtensionA(too_long);
976 ok(ext == too_long + 300, "Expected ext == too_long + 300, got %p\n", ext);
977 ok(lstrlen(ext) == LONG_LEN - 301, "Expected LONG_LEN - 301, got %i\n", lstrlen(ext));
978 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
981 static void test_PathBuildRootA(void)
985 char root_expected[26][4];
989 /* set up the expected paths */
990 for (drive = 'A'; drive <= 'Z'; drive++)
991 sprintf(root_expected[drive - 'A'], "%c:\\", drive);
993 /* test the expected values */
994 for (j = 0; j < 26; j++)
996 SetLastError(0xdeadbeef);
997 lstrcpy(path, "aaaaaaaaa");
998 root = PathBuildRootA(path, j);
999 ok(root == path, "Expected root == path, got %p\n", root);
1000 ok(!lstrcmp(root, root_expected[j]), "Expected %s, got %s\n", root_expected[j], root);
1001 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1004 /* test a negative drive number */
1005 SetLastError(0xdeadbeef);
1006 lstrcpy(path, "aaaaaaaaa");
1007 root = PathBuildRootA(path, -1);
1008 ok(root == path, "Expected root == path, got %p\n", root);
1009 ok(!lstrcmp(path, "aaaaaaaaa") ||
1010 lstrlenA(path) == 0, /* Vista */
1011 "Expected aaaaaaaaa or empty string, got %s\n", path);
1012 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1014 /* test a drive number greater than 25 */
1015 SetLastError(0xdeadbeef);
1016 lstrcpy(path, "aaaaaaaaa");
1017 root = PathBuildRootA(path, 26);
1018 ok(root == path, "Expected root == path, got %p\n", root);
1019 ok(!lstrcmp(path, "aaaaaaaaa") ||
1020 lstrlenA(path) == 0, /* Vista */
1021 "Expected aaaaaaaaa or empty string, got %s\n", path);
1022 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1024 /* length of path is less than 4 */
1025 SetLastError(0xdeadbeef);
1026 lstrcpy(path, "aa");
1027 root = PathBuildRootA(path, 0);
1028 ok(root == path, "Expected root == path, got %p\n", root);
1029 ok(!lstrcmp(path, "A:\\"), "Expected A:\\, got %s\n", path);
1030 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1033 SetLastError(0xdeadbeef);
1034 root = PathBuildRootA(NULL, 0);
1035 ok(root == NULL, "Expected root == NULL, got %p\n", root);
1036 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1039 static void test_PathCommonPrefixA(void)
1041 char path1[MAX_PATH], path2[MAX_PATH];
1045 /* test NULL path1 */
1046 SetLastError(0xdeadbeef);
1047 lstrcpy(path2, "C:\\");
1048 lstrcpy(out, "aaa");
1049 count = PathCommonPrefixA(NULL, path2, out);
1050 ok(count == 0, "Expected 0, got %i\n", count);
1053 ok(!lstrcmp(out, "aaa"), "Expected aaa, got %s\n", out);
1055 ok(!lstrcmp(path2, "C:\\"), "Expected C:\\, got %s\n", path2);
1056 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1058 /* test NULL path2 */
1059 SetLastError(0xdeadbeef);
1060 lstrcpy(path1, "C:\\");
1061 lstrcpy(out, "aaa");
1062 count = PathCommonPrefixA(path1, NULL, out);
1063 ok(count == 0, "Expected 0, got %i\n", count);
1066 ok(!lstrcmp(out, "aaa"), "Expected aaa, got %s\n", out);
1068 ok(!lstrcmp(path1, "C:\\"), "Expected C:\\, got %s\n", path1);
1069 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1071 /* test empty path1 */
1072 SetLastError(0xdeadbeef);
1074 lstrcpy(path2, "C:\\");
1075 lstrcpy(out, "aaa");
1076 count = PathCommonPrefixA(path1, path2, out);
1077 ok(count == 0, "Expected 0, got %i\n", count);
1078 ok(lstrlen(out) == 0, "Expected 0 length out, got %i\n", lstrlen(out));
1079 ok(lstrlen(path1) == 0, "Expected 0 length path1, got %i\n", lstrlen(path1));
1080 ok(!lstrcmp(path2, "C:\\"), "Expected C:\\, got %s\n", path2);
1081 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1083 /* test empty path1 */
1084 SetLastError(0xdeadbeef);
1086 lstrcpy(path1, "C:\\");
1087 lstrcpy(out, "aaa");
1088 count = PathCommonPrefixA(path1, path2, out);
1089 ok(count == 0, "Expected 0, got %i\n", count);
1090 ok(lstrlen(out) == 0, "Expected 0 length out, got %i\n", lstrlen(out));
1091 ok(lstrlen(path2) == 0, "Expected 0 length path2, got %i\n", lstrlen(path2));
1092 ok(!lstrcmp(path1, "C:\\"), "Expected C:\\, got %s\n", path1);
1093 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1095 /* paths are legit, out is NULL */
1096 SetLastError(0xdeadbeef);
1097 lstrcpy(path1, "C:\\");
1098 lstrcpy(path2, "C:\\");
1099 count = PathCommonPrefixA(path1, path2, NULL);
1100 ok(count == 3, "Expected 3, got %i\n", count);
1101 ok(!lstrcmp(path1, "C:\\"), "Expected C:\\, got %s\n", path1);
1102 ok(!lstrcmp(path2, "C:\\"), "Expected C:\\, got %s\n", path2);
1103 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1105 /* all parameters legit */
1106 SetLastError(0xdeadbeef);
1107 lstrcpy(path1, "C:\\");
1108 lstrcpy(path2, "C:\\");
1109 lstrcpy(out, "aaa");
1110 count = PathCommonPrefixA(path1, path2, out);
1111 ok(count == 3, "Expected 3, got %i\n", count);
1112 ok(!lstrcmp(path1, "C:\\"), "Expected C:\\, got %s\n", path1);
1113 ok(!lstrcmp(path2, "C:\\"), "Expected C:\\, got %s\n", path2);
1114 ok(!lstrcmp(out, "C:\\"), "Expected C:\\, got %s\n", out);
1115 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1117 /* path1 and path2 not the same, but common prefix */
1118 SetLastError(0xdeadbeef);
1119 lstrcpy(path1, "C:\\one\\two");
1120 lstrcpy(path2, "C:\\one\\three");
1121 lstrcpy(out, "aaa");
1122 count = PathCommonPrefixA(path1, path2, out);
1123 ok(count == 6, "Expected 6, got %i\n", count);
1124 ok(!lstrcmp(path1, "C:\\one\\two"), "Expected C:\\one\\two, got %s\n", path1);
1125 ok(!lstrcmp(path2, "C:\\one\\three"), "Expected C:\\one\\three, got %s\n", path2);
1126 ok(!lstrcmp(out, "C:\\one"), "Expected C:\\one, got %s\n", out);
1127 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1130 SetLastError(0xdeadbeef);
1131 lstrcpy(path1, "one\\.two");
1132 lstrcpy(path2, "one\\.three");
1133 lstrcpy(out, "aaa");
1134 count = PathCommonPrefixA(path1, path2, out);
1135 ok(count == 3, "Expected 3, got %i\n", count);
1136 ok(!lstrcmp(path1, "one\\.two"), "Expected one\\.two, got %s\n", path1);
1137 ok(!lstrcmp(path2, "one\\.three"), "Expected one\\.three, got %s\n", path2);
1138 ok(!lstrcmp(out, "one"), "Expected one, got %s\n", out);
1139 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1142 SetLastError(0xdeadbeef);
1143 lstrcpy(path1, "one\\..two");
1144 lstrcpy(path2, "one\\..three");
1145 lstrcpy(out, "aaa");
1146 count = PathCommonPrefixA(path1, path2, out);
1147 ok(count == 3, "Expected 3, got %i\n", count);
1148 ok(!lstrcmp(path1, "one\\..two"), "Expected one\\..two, got %s\n", path1);
1149 ok(!lstrcmp(path2, "one\\..three"), "Expected one\\..three, got %s\n", path2);
1150 ok(!lstrcmp(out, "one"), "Expected one, got %s\n", out);
1151 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1153 /* try ... prefix */
1154 SetLastError(0xdeadbeef);
1155 lstrcpy(path1, "one\\...two");
1156 lstrcpy(path2, "one\\...three");
1157 lstrcpy(out, "aaa");
1158 count = PathCommonPrefixA(path1, path2, out);
1159 ok(count == 3, "Expected 3, got %i\n", count);
1160 ok(!lstrcmp(path1, "one\\...two"), "Expected one\\...two, got %s\n", path1);
1161 ok(!lstrcmp(path2, "one\\...three"), "Expected one\\...three, got %s\n", path2);
1162 ok(!lstrcmp(out, "one"), "Expected one, got %s\n", out);
1163 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1166 SetLastError(0xdeadbeef);
1167 lstrcpy(path1, "one\\.\\two");
1168 lstrcpy(path2, "one\\.\\three");
1169 lstrcpy(out, "aaa");
1170 count = PathCommonPrefixA(path1, path2, out);
1171 ok(count == 5, "Expected 5, got %i\n", count);
1172 ok(!lstrcmp(path1, "one\\.\\two"), "Expected one\\.\\two, got %s\n", path1);
1173 ok(!lstrcmp(path2, "one\\.\\three"), "Expected one\\.\\three, got %s\n", path2);
1174 ok(!lstrcmp(out, "one\\."), "Expected one\\., got %s\n", out);
1175 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1177 /* try ..\ prefix */
1178 SetLastError(0xdeadbeef);
1179 lstrcpy(path1, "one\\..\\two");
1180 lstrcpy(path2, "one\\..\\three");
1181 lstrcpy(out, "aaa");
1182 count = PathCommonPrefixA(path1, path2, out);
1183 ok(count == 6, "Expected 6, got %i\n", count);
1184 ok(!lstrcmp(path1, "one\\..\\two"), "Expected one\\..\\two, got %s\n", path1);
1185 ok(!lstrcmp(path2, "one\\..\\three"), "Expected one\\..\\three, got %s\n", path2);
1186 ok(!lstrcmp(out, "one\\.."), "Expected one\\.., got %s\n", out);
1187 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1189 /* try ...\\ prefix */
1190 SetLastError(0xdeadbeef);
1191 lstrcpy(path1, "one\\...\\two");
1192 lstrcpy(path2, "one\\...\\three");
1193 lstrcpy(out, "aaa");
1194 count = PathCommonPrefixA(path1, path2, out);
1195 ok(count == 7, "Expected 7, got %i\n", count);
1196 ok(!lstrcmp(path1, "one\\...\\two"), "Expected one\\...\\two, got %s\n", path1);
1197 ok(!lstrcmp(path2, "one\\...\\three"), "Expected one\\...\\three, got %s\n", path2);
1198 ok(!lstrcmp(out, "one\\..."), "Expected one\\..., got %s\n", out);
1199 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1201 /* try prefix that is not an msdn labeled prefix type */
1202 SetLastError(0xdeadbeef);
1203 lstrcpy(path1, "same");
1204 lstrcpy(path2, "same");
1205 lstrcpy(out, "aaa");
1206 count = PathCommonPrefixA(path1, path2, out);
1207 ok(count == 4, "Expected 4, got %i\n", count);
1208 ok(!lstrcmp(path1, "same"), "Expected same, got %s\n", path1);
1209 ok(!lstrcmp(path2, "same"), "Expected same, got %s\n", path2);
1210 ok(!lstrcmp(out, "same"), "Expected same, got %s\n", out);
1211 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1213 /* try . after directory */
1214 SetLastError(0xdeadbeef);
1215 lstrcpy(path1, "one\\mid.\\two");
1216 lstrcpy(path2, "one\\mid.\\three");
1217 lstrcpy(out, "aaa");
1218 count = PathCommonPrefixA(path1, path2, out);
1219 ok(count == 8, "Expected 8, got %i\n", count);
1220 ok(!lstrcmp(path1, "one\\mid.\\two"), "Expected one\\mid.\\two, got %s\n", path1);
1221 ok(!lstrcmp(path2, "one\\mid.\\three"), "Expected one\\mid.\\three, got %s\n", path2);
1222 ok(!lstrcmp(out, "one\\mid."), "Expected one\\mid., got %s\n", out);
1223 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1225 /* try . in the middle of a directory */
1226 SetLastError(0xdeadbeef);
1227 lstrcpy(path1, "one\\mid.end\\two");
1228 lstrcpy(path2, "one\\mid.end\\three");
1229 lstrcpy(out, "aaa");
1230 count = PathCommonPrefixA(path1, path2, out);
1231 ok(count == 11, "Expected 11, got %i\n", count);
1232 ok(!lstrcmp(path1, "one\\mid.end\\two"), "Expected one\\mid.end\\two, got %s\n", path1);
1233 ok(!lstrcmp(path2, "one\\mid.end\\three"), "Expected one\\mid.end\\three, got %s\n", path2);
1234 ok(!lstrcmp(out, "one\\mid.end"), "Expected one\\mid.end, got %s\n", out);
1235 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1237 /* try comparing a .. with the expanded path */
1238 SetLastError(0xdeadbeef);
1239 lstrcpy(path1, "one\\..\\two");
1240 lstrcpy(path2, "two");
1241 lstrcpy(out, "aaa");
1242 count = PathCommonPrefixA(path1, path2, out);
1243 ok(count == 0, "Expected 0, got %i\n", count);
1244 ok(!lstrcmp(path1, "one\\..\\two"), "Expected one\\..\\two, got %s\n", path1);
1245 ok(!lstrcmp(path2, "two"), "Expected two, got %s\n", path2);
1246 ok(lstrlen(out) == 0, "Expected 0 length out, got %i\n", lstrlen(out));
1247 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1250 static void test_PathUnquoteSpaces(void)
1253 for(i = 0; i < sizeof(TEST_PATH_UNQUOTE_SPACES) / sizeof(TEST_PATH_UNQUOTE_SPACES[0]); i++)
1255 char *path = strdupA(TEST_PATH_UNQUOTE_SPACES[i].path);
1256 WCHAR *pathW = GetWideString(TEST_PATH_UNQUOTE_SPACES[i].path);
1257 WCHAR *resultW = GetWideString(TEST_PATH_UNQUOTE_SPACES[i].result);
1259 PathUnquoteSpacesA(path);
1260 ok(!strcmp(path, TEST_PATH_UNQUOTE_SPACES[i].result), "%s (A): got %s expected %s\n",
1261 TEST_PATH_UNQUOTE_SPACES[i].path, path,
1262 TEST_PATH_UNQUOTE_SPACES[i].result);
1264 PathUnquoteSpacesW(pathW);
1265 ok(!lstrcmpW(pathW, resultW), "%s (W): strings differ\n",
1266 TEST_PATH_UNQUOTE_SPACES[i].path);
1267 FreeWideString(pathW);
1268 FreeWideString(resultW);
1269 HeapFree(GetProcessHeap(), 0, path);
1273 /* ################ */
1277 hShlwapi = GetModuleHandleA("shlwapi.dll");
1279 test_PathSearchAndQualify();
1280 test_PathCreateFromUrl();
1283 test_PathAddBackslash();
1284 test_PathMakePretty();
1285 test_PathMatchSpec();
1287 /* For whatever reason, PathIsValidCharA and PathAppendA share the same
1288 * ordinal number in some native versions. Check this to prevent a crash.
1290 pPathIsValidCharA = (void*)GetProcAddress(hShlwapi, (LPSTR)455);
1291 if (pPathIsValidCharA && pPathIsValidCharA != (void*)GetProcAddress(hShlwapi, "PathAppendA"))
1293 test_PathIsValidCharA();
1295 pPathIsValidCharW = (void*)GetProcAddress(hShlwapi, (LPSTR)456);
1296 if (pPathIsValidCharW) test_PathIsValidCharW();
1299 pPathCombineW = (void*)GetProcAddress(hShlwapi, "PathCombineW");
1301 test_PathCombineW();
1303 test_PathCombineA();
1305 test_PathCanonicalizeA();
1306 test_PathFindExtensionA();
1307 test_PathBuildRootA();
1308 test_PathCommonPrefixA();
1309 test_PathUnquoteSpaces();