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
23 #include "wine/test.h"
30 static HRESULT (WINAPI *pPathIsValidCharA)(char,DWORD);
31 static HRESULT (WINAPI *pPathIsValidCharW)(WCHAR,DWORD);
32 static LPWSTR (WINAPI *pPathCombineW)(LPWSTR, LPCWSTR, LPCWSTR);
33 static HRESULT (WINAPI *pPathCreateFromUrlA)(LPCSTR, LPSTR, LPDWORD, DWORD);
34 static HRESULT (WINAPI *pPathCreateFromUrlW)(LPCWSTR, LPWSTR, LPDWORD, DWORD);
35 static BOOL (WINAPI *pPathAppendA)(LPSTR, LPCSTR);
37 /* ################ */
43 } TEST_PATHFROMURL[] = {
44 {"file:///c:/foo/ba%5Cr", "c:\\foo\\ba\\r", S_OK},
45 {"file:///c:/foo/../ba%5Cr", "c:\\foo\\..\\ba\\r", S_OK},
46 {"file:///host/c:/foo/bar", "\\host\\c:\\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\\c:\\foo\\bar", "\\\\hostc:\\foo\\bar", S_OK},
50 {"file:\\\\host\\ca\\foo\\bar", "\\\\host\\ca\\foo\\bar", S_OK},
51 {"file:\\\\host\\c|\\foo\\bar", "\\\\hostc|\\foo\\bar", S_OK},
52 {"file:\\%5Chost\\c:\\foo\\bar", "\\\\host\\c:\\foo\\bar", S_OK},
53 {"file:\\\\host\\cx:\\foo\\bar", "\\\\host\\cx:\\foo\\bar", S_OK},
54 {"file://c:/foo/bar", "c:\\foo\\bar", S_OK},
55 {"file://c:/d:/foo/bar", "c:\\d:\\foo\\bar", S_OK},
56 {"file://c|/d|/foo/bar", "c:\\d|\\foo\\bar", S_OK},
57 {"file://host/foo/bar", "\\\\host\\foo\\bar", S_OK},
58 {"file:/foo/bar", "\\foo\\bar", S_OK},
59 {"file:/foo/bar/", "\\foo\\bar\\", S_OK},
60 {"file:foo/bar", "foo\\bar", S_OK},
61 {"file:c:/foo/bar", "c:\\foo\\bar", S_OK},
62 {"file:c|/foo/bar", "c:\\foo\\bar", S_OK},
63 {"file:cx|/foo/bar", "cx|\\foo\\bar", S_OK},
64 {"file:////c:/foo/bar", "c:\\foo\\bar", S_OK},
65 /* {"file:////c:/foo/foo%20bar", "c:\\foo\\foo%20bar", S_OK},*/
67 {"c:\\foo\\bar", NULL, E_INVALIDARG},
68 {"foo/bar", NULL, E_INVALIDARG},
69 {"http://foo/bar", NULL, E_INVALIDARG},
77 } TEST_PATH_IS_URL[] = {
78 {"http://foo/bar", TRUE},
79 {"c:\\foo\\bar", FALSE},
80 {"c:/foo/bar", FALSE},
81 {"foo://foo/bar", TRUE},
84 {"bogusscheme:", TRUE},
85 {"http:partial", TRUE},
86 {"www.winehq.org", FALSE},
87 /* More examples that the user might enter as the browser start page */
88 {"winehq.org", FALSE},
89 {"ftp.winehq.org", FALSE},
90 {"http://winehq.org", TRUE},
91 {"http://www.winehq.org", TRUE},
92 {"https://winehq.org", TRUE},
93 {"https://www.winehq.org", TRUE},
94 {"ftp://winehq.org", TRUE},
95 {"ftp://ftp.winehq.org", TRUE},
96 {"file://does_not_exist.txt", TRUE},
97 {"about:blank", TRUE},
99 {"about:mozilla", TRUE},
100 /* scheme is case independent */
101 {"HTTP://www.winehq.org", TRUE},
102 /* a space at the start is not allowed */
103 {" http://www.winehq.org", FALSE},
108 static const struct {
111 } TEST_PATH_UNQUOTE_SPACES[] = {
112 { "abcdef", "abcdef" },
113 { "\"abcdef\"", "abcdef" },
114 { "\"abcdef", "\"abcdef" },
115 { "abcdef\"", "abcdef\"" },
116 { "\"\"abcdef\"\"", "\"abcdef\"" },
117 { "abc\"def", "abc\"def" },
118 { "\"abc\"def", "\"abc\"def" },
119 { "\"abc\"def\"", "abc\"def" },
120 { "\'abcdef\'", "\'abcdef\'" },
125 /* ################ */
127 static LPWSTR GetWideString(const char* szString)
129 LPWSTR wszString = HeapAlloc(GetProcessHeap(), 0, (2*INTERNET_MAX_URL_LENGTH) * sizeof(WCHAR));
131 MultiByteToWideChar(0, 0, szString, -1, wszString, INTERNET_MAX_URL_LENGTH);
136 static void FreeWideString(LPWSTR wszString)
138 HeapFree(GetProcessHeap(), 0, wszString);
141 static LPSTR strdupA(LPCSTR p)
144 DWORD len = (strlen(p) + 1);
145 ret = HeapAlloc(GetProcessHeap(), 0, len);
150 /* ################ */
152 static void test_PathSearchAndQualify(void)
154 WCHAR path1[] = {'c',':','\\','f','o','o',0};
155 WCHAR expect1[] = {'c',':','\\','f','o','o',0};
156 WCHAR path2[] = {'c',':','f','o','o',0};
157 WCHAR c_drive[] = {'c',':',0};
158 WCHAR foo[] = {'f','o','o',0};
159 WCHAR path3[] = {'\\','f','o','o',0};
160 WCHAR winini[] = {'w','i','n','.','i','n','i',0};
162 WCHAR cur_dir[MAX_PATH];
163 WCHAR dot[] = {'.',0};
166 ok(PathSearchAndQualifyW(path1, out, MAX_PATH) != 0,
167 "PathSearchAndQualify rets 0\n");
168 ok(!lstrcmpiW(out, expect1), "strings don't match\n");
171 ok(PathSearchAndQualifyW(path2, out, MAX_PATH) != 0,
172 "PathSearchAndQualify rets 0\n");
173 GetFullPathNameW(c_drive, MAX_PATH, cur_dir, NULL);
174 PathAddBackslashW(cur_dir);
175 lstrcatW(cur_dir, foo);
176 ok(!lstrcmpiW(out, cur_dir), "strings don't match\n");
179 ok(PathSearchAndQualifyW(foo, out, MAX_PATH) != 0,
180 "PathSearchAndQualify rets 0\n");
181 GetFullPathNameW(dot, MAX_PATH, cur_dir, NULL);
182 PathAddBackslashW(cur_dir);
183 lstrcatW(cur_dir, foo);
184 ok(!lstrcmpiW(out, cur_dir), "strings don't match\n");
187 ok(PathSearchAndQualifyW(path3, out, MAX_PATH) != 0,
188 "PathSearchAndQualify rets 0\n");
189 GetFullPathNameW(dot, MAX_PATH, cur_dir, NULL);
190 lstrcpyW(cur_dir + 2, path3);
191 ok(!lstrcmpiW(out, cur_dir), "strings don't match\n");
194 ok(PathSearchAndQualifyW(winini, out, MAX_PATH) != 0,
195 "PathSearchAndQualify rets 0\n");
196 if(!SearchPathW(NULL, winini, NULL, MAX_PATH, cur_dir, NULL))
197 GetFullPathNameW(winini, MAX_PATH, cur_dir, NULL);
198 ok(!lstrcmpiW(out, cur_dir), "strings don't match\n");
202 static void test_PathCreateFromUrl(void)
205 char ret_path[INTERNET_MAX_URL_LENGTH];
207 WCHAR ret_pathW[INTERNET_MAX_URL_LENGTH];
209 static const char url[] = "http://www.winehq.org";
211 if (!pPathCreateFromUrlA) {
212 win_skip("PathCreateFromUrlA not found\n");
216 /* Check ret_path = NULL */
218 ret = pPathCreateFromUrlA(url, NULL, &len, 0);
219 ok ( ret == E_INVALIDARG, "got 0x%08x expected E_INVALIDARG\n", ret);
221 for(i = 0; i < sizeof(TEST_PATHFROMURL) / sizeof(TEST_PATHFROMURL[0]); i++) {
222 len = INTERNET_MAX_URL_LENGTH;
223 ret = pPathCreateFromUrlA(TEST_PATHFROMURL[i].url, ret_path, &len, 0);
224 ok(ret == TEST_PATHFROMURL[i].ret, "ret %08x from url %s\n", ret, TEST_PATHFROMURL[i].url);
225 if(TEST_PATHFROMURL[i].path) {
226 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);
227 ok(len == strlen(ret_path), "ret len %d from url %s\n", len, TEST_PATHFROMURL[i].url);
229 if (pPathCreateFromUrlW) {
230 len = INTERNET_MAX_URL_LENGTH;
231 pathW = GetWideString(TEST_PATHFROMURL[i].path);
232 urlW = GetWideString(TEST_PATHFROMURL[i].url);
233 ret = pPathCreateFromUrlW(urlW, ret_pathW, &len, 0);
234 WideCharToMultiByte(CP_ACP, 0, ret_pathW, -1, ret_path, sizeof(ret_path),0,0);
235 ok(ret == TEST_PATHFROMURL[i].ret, "ret %08x from url L\"%s\"\n", ret, TEST_PATHFROMURL[i].url);
236 if(TEST_PATHFROMURL[i].path) {
237 ok(!lstrcmpiW(ret_pathW, pathW), "got %s expected %s from url L\"%s\"\n",
238 ret_path, TEST_PATHFROMURL[i].path, TEST_PATHFROMURL[i].url);
239 ok(len == lstrlenW(ret_pathW), "ret len %d from url L\"%s\"\n", len, TEST_PATHFROMURL[i].url);
241 FreeWideString(urlW);
242 FreeWideString(pathW);
248 static void test_PathIsUrl(void)
253 for(i = 0; i < sizeof(TEST_PATH_IS_URL)/sizeof(TEST_PATH_IS_URL[0]); i++) {
254 ret = PathIsURLA(TEST_PATH_IS_URL[i].path);
255 ok(ret == TEST_PATH_IS_URL[i].expect,
256 "returned %d from path %s, expected %d\n", ret, TEST_PATH_IS_URL[i].path,
257 TEST_PATH_IS_URL[i].expect);
261 static const DWORD SHELL_charclass[] =
263 0x00000000, 0x00000000, 0x00000000, 0x00000000,
264 0x00000000, 0x00000000, 0x00000000, 0x00000000,
265 0x00000000, 0x00000000, 0x00000000, 0x00000000,
266 0x00000000, 0x00000000, 0x00000000, 0x00000000,
267 0x00000000, 0x00000000, 0x00000000, 0x00000000,
268 0x00000000, 0x00000000, 0x00000000, 0x00000000,
269 0x00000000, 0x00000000, 0x00000000, 0x00000000,
270 0x00000000, 0x00000000, 0x00000000, 0x00000000,
271 0x00000080, 0x00000100, 0x00000200, 0x00000100,
272 0x00000100, 0x00000100, 0x00000100, 0x00000100,
273 0x00000100, 0x00000100, 0x00000002, 0x00000100,
274 0x00000040, 0x00000100, 0x00000004, 0x00000000,
275 0x00000100, 0x00000100, 0x00000100, 0x00000100,
276 0x00000100, 0x00000100, 0x00000100, 0x00000100,
277 0x00000100, 0x00000100, 0x00000010, 0x00000020,
278 0x00000000, 0x00000100, 0x00000000, 0x00000001,
279 0x00000100, 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, 0xffffffff,
285 0xffffffff, 0xffffffff, 0xffffffff, 0x00000100,
286 0x00000008, 0x00000100, 0x00000100, 0x00000100,
287 0x00000100, 0xffffffff, 0xffffffff, 0xffffffff,
288 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
289 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
290 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
291 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
292 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
293 0xffffffff, 0xffffffff, 0xffffffff, 0x00000100,
294 0x00000000, 0x00000100, 0x00000100
297 static void test_PathIsValidCharA(void)
302 /* For whatever reason, PathIsValidCharA and PathAppendA share the same
303 * ordinal number in some native versions. Check this to prevent a crash.
305 if (!pPathIsValidCharA || pPathIsValidCharA == (void*)pPathAppendA)
307 win_skip("PathIsValidCharA isn't available\n");
311 for (c = 0; c < 0x7f; c++)
313 ret = pPathIsValidCharA( c, ~0U );
314 ok ( ret || !SHELL_charclass[c], "PathIsValidCharA failed: 0x%02x got 0x%08x\n", c, ret );
317 for (c = 0x7f; c <= 0xff; c++)
319 ret = pPathIsValidCharA( c, ~0U );
320 ok ( ret, "PathIsValidCharA failed: 0x%02x got 0x%08x\n", c, ret );
324 static void test_PathIsValidCharW(void)
329 if (!pPathIsValidCharW)
331 win_skip("PathIsValidCharW isn't available\n");
335 for (c = 0; c < 0x7f; c++)
337 ret = pPathIsValidCharW( c, ~0U );
338 ok ( ret || !SHELL_charclass[c], "PathIsValidCharW failed: 0x%02x got 0x%08x\n", c, ret );
341 for (c = 0x007f; c <= 0xffff; c++)
343 ret = pPathIsValidCharW( c, ~0U );
344 ok ( ret, "PathIsValidCharW failed: 0x%02x got 0x%08x\n", c, ret );
348 static void test_PathMakePretty(void)
352 ok (PathMakePrettyA(NULL) == FALSE, "PathMakePretty: NULL path succeeded\n");
354 ok (PathMakePrettyA(buff) == TRUE, "PathMakePretty: Empty path failed\n");
356 strcpy(buff, "C:\\A LONG FILE NAME WITH \\SPACES.TXT");
357 ok (PathMakePrettyA(buff) == TRUE, "PathMakePretty: Long UC name failed\n");
358 ok (strcmp(buff, "C:\\a long file name with \\spaces.txt") == 0,
359 "PathMakePretty: Long UC name not changed\n");
361 strcpy(buff, "C:\\A LONG FILE NAME WITH \\MixedCase.TXT");
362 ok (PathMakePrettyA(buff) == FALSE, "PathMakePretty: Long MC name succeeded\n");
363 ok (strcmp(buff, "C:\\A LONG FILE NAME WITH \\MixedCase.TXT") == 0,
364 "PathMakePretty: Failed but modified path\n");
366 strcpy(buff, "TEST");
367 ok (PathMakePrettyA(buff) == TRUE, "PathMakePretty: Short name failed\n");
368 ok (strcmp(buff, "Test") == 0, "PathMakePretty: 1st char lowercased %s\n", buff);
371 static void test_PathMatchSpec(void)
373 static const char file[] = "c:\\foo\\bar\\filename.ext";
374 static const char spec1[] = ".ext";
375 static const char spec2[] = "*.ext";
376 static const char spec3[] = "*.ext ";
377 static const char spec4[] = " *.ext";
378 static const char spec5[] = "* .ext";
379 static const char spec6[] = "*. ext";
380 static const char spec7[] = "* . ext";
381 static const char spec8[] = "*.e?t";
382 static const char spec9[] = "filename.ext";
383 static const char spec10[] = "*bar\\filename.ext";
384 static const char spec11[] = " foo; *.ext";
385 static const char spec12[] = "*.ext;*.bar";
386 static const char spec13[] = "*bar*";
388 ok (PathMatchSpecA(file, spec1) == FALSE, "PathMatchSpec: Spec1 failed\n");
389 ok (PathMatchSpecA(file, spec2) == TRUE, "PathMatchSpec: Spec2 failed\n");
390 ok (PathMatchSpecA(file, spec3) == FALSE, "PathMatchSpec: Spec3 failed\n");
391 ok (PathMatchSpecA(file, spec4) == TRUE, "PathMatchSpec: Spec4 failed\n");
392 todo_wine ok (PathMatchSpecA(file, spec5) == TRUE, "PathMatchSpec: Spec5 failed\n");
393 todo_wine ok (PathMatchSpecA(file, spec6) == TRUE, "PathMatchSpec: Spec6 failed\n");
394 ok (PathMatchSpecA(file, spec7) == FALSE, "PathMatchSpec: Spec7 failed\n");
395 ok (PathMatchSpecA(file, spec8) == TRUE, "PathMatchSpec: Spec8 failed\n");
396 ok (PathMatchSpecA(file, spec9) == FALSE, "PathMatchSpec: Spec9 failed\n");
397 ok (PathMatchSpecA(file, spec10) == TRUE, "PathMatchSpec: Spec10 failed\n");
398 ok (PathMatchSpecA(file, spec11) == TRUE, "PathMatchSpec: Spec11 failed\n");
399 ok (PathMatchSpecA(file, spec12) == TRUE, "PathMatchSpec: Spec12 failed\n");
400 ok (PathMatchSpecA(file, spec13) == TRUE, "PathMatchSpec: Spec13 failed\n");
403 static void test_PathCombineW(void)
405 LPWSTR wszString, wszString2;
406 WCHAR wbuf[MAX_PATH+1], wstr1[MAX_PATH] = {'C',':','\\',0}, wstr2[MAX_PATH];
407 static const WCHAR expout[] = {'C',':','\\','A','A',0};
412 win_skip("PathCombineW isn't available\n");
416 wszString2 = HeapAlloc(GetProcessHeap(), 0, MAX_PATH * sizeof(WCHAR));
419 wszString = pPathCombineW(NULL, NULL, NULL);
420 ok (wszString == NULL, "Expected a NULL return\n");
424 wszString = pPathCombineW(wszString2, NULL, NULL);
425 ok (wszString == NULL ||
426 broken(wszString[0] == 'a'), /* Win95 and some W2K */
427 "Expected a NULL return\n");
428 ok (wszString2[0] == 0 ||
429 broken(wszString2[0] == 'a'), /* Win95 and some W2K */
430 "Destination string not empty\n");
432 HeapFree(GetProcessHeap(), 0, wszString2);
435 wstr2[0] = wstr2[1] = wstr2[2] = 'A';
436 for (i=3; i<MAX_PATH/2; i++)
437 wstr1[i] = wstr2[i] = 'A';
438 wstr1[(MAX_PATH/2) - 1] = wstr2[MAX_PATH/2] = 0;
439 memset(wbuf, 0xbf, sizeof(wbuf));
441 wszString = pPathCombineW(wbuf, wstr1, wstr2);
442 ok(wszString == NULL, "Expected a NULL return\n");
444 broken(wbuf[0] == 0xbfbf), /* Win95 and some W2K */
445 "Buffer contains data\n");
447 /* PathCombineW can be used in place */
450 ok(PathCombineW(wstr1, wstr1, wstr2) == wstr1, "Expected a wstr1 return\n");
451 ok(StrCmpW(wstr1, expout) == 0, "Unexpected PathCombine output\n");
455 #define LONG_LEN (MAX_PATH * 2)
456 #define HALF_LEN (MAX_PATH / 2 + 1)
458 static void test_PathCombineA(void)
462 char too_long[LONG_LEN];
463 char one[HALF_LEN], two[HALF_LEN];
466 SetLastError(0xdeadbeef);
467 str = PathCombineA(NULL, "C:\\", "one\\two\\three");
468 ok(str == NULL, "Expected NULL, got %p\n", str);
469 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
471 /* try NULL dest and NULL directory */
472 SetLastError(0xdeadbeef);
473 str = PathCombineA(NULL, NULL, "one\\two\\three");
474 ok(str == NULL, "Expected NULL, got %p\n", str);
475 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
478 SetLastError(0xdeadbeef);
479 str = PathCombineA(NULL, NULL, NULL);
480 ok(str == NULL, "Expected NULL, got %p\n", str);
481 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
483 /* try NULL file part */
484 SetLastError(0xdeadbeef);
485 lstrcpyA(dest, "control");
486 str = PathCombineA(dest, "C:\\", NULL);
487 ok(str == dest, "Expected str == dest, got %p\n", str);
488 ok(!lstrcmp(str, "C:\\"), "Expected C:\\, got %s\n", str);
489 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
491 /* try empty file part */
492 SetLastError(0xdeadbeef);
493 lstrcpyA(dest, "control");
494 str = PathCombineA(dest, "C:\\", "");
495 ok(str == dest, "Expected str == dest, got %p\n", str);
496 ok(!lstrcmp(str, "C:\\"), "Expected C:\\, got %s\n", str);
497 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
499 /* try empty directory and file part */
500 SetLastError(0xdeadbeef);
501 lstrcpyA(dest, "control");
502 str = PathCombineA(dest, "", "");
503 ok(str == dest, "Expected str == dest, got %p\n", str);
504 ok(!lstrcmp(str, "\\") ||
505 broken(!lstrcmp(str, "control")), /* Win95 and some W2K */
506 "Expected \\, got %s\n", str);
507 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
509 /* try NULL directory */
510 SetLastError(0xdeadbeef);
511 lstrcpyA(dest, "control");
512 str = PathCombineA(dest, NULL, "one\\two\\three");
513 ok(str == dest, "Expected str == dest, got %p\n", str);
514 ok(!lstrcmp(str, "one\\two\\three"), "Expected one\\two\\three, got %s\n", str);
515 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
517 /* try NULL directory and empty file part */
518 SetLastError(0xdeadbeef);
519 lstrcpyA(dest, "control");
520 str = PathCombineA(dest, NULL, "");
521 ok(str == dest, "Expected str == dest, got %p\n", str);
522 ok(!lstrcmp(str, "\\") ||
523 broken(!lstrcmp(str, "one\\two\\three")), /* Win95 and some W2K */
524 "Expected \\, got %s\n", str);
525 ok(GetLastError() == 0xdeadbeef ||
526 broken(GetLastError() == ERROR_INVALID_PARAMETER), /* Win95 */
527 "Expected 0xdeadbeef, got %d\n", GetLastError());
529 /* try NULL directory and file part */
530 SetLastError(0xdeadbeef);
531 lstrcpyA(dest, "control");
532 str = PathCombineA(dest, NULL, NULL);
534 broken(str != NULL), /* Win95 and some W2K */
535 "Expected str == NULL, got %p\n", str);
536 ok(lstrlenA(dest) == 0 ||
537 broken(!lstrcmp(dest, "control")), /* Win95 and some W2K */
538 "Expected 0 length, got %i\n", lstrlenA(dest));
539 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
541 /* try directory without backslash */
542 SetLastError(0xdeadbeef);
543 lstrcpyA(dest, "control");
544 str = PathCombineA(dest, "C:", "one\\two\\three");
545 ok(str == dest, "Expected str == dest, got %p\n", str);
546 ok(!lstrcmp(str, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", str);
547 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
549 /* try directory with backslash */
550 SetLastError(0xdeadbeef);
551 lstrcpyA(dest, "control");
552 str = PathCombineA(dest, "C:\\", "one\\two\\three");
553 ok(str == dest, "Expected str == dest, got %p\n", str);
554 ok(!lstrcmp(str, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", str);
555 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
557 /* try directory with backslash and file with prepended backslash */
558 SetLastError(0xdeadbeef);
559 lstrcpyA(dest, "control");
560 str = PathCombineA(dest, "C:\\", "\\one\\two\\three");
561 ok(str == dest, "Expected str == dest, got %p\n", str);
562 ok(!lstrcmp(str, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", str);
563 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
565 /* try previous test, with backslash appended as well */
566 SetLastError(0xdeadbeef);
567 lstrcpyA(dest, "control");
568 str = PathCombineA(dest, "C:\\", "\\one\\two\\three\\");
569 ok(str == dest, "Expected str == dest, got %p\n", str);
570 ok(!lstrcmp(str, "C:\\one\\two\\three\\"), "Expected C:\\one\\two\\three\\, got %s\n", str);
571 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
573 /* try a relative directory */
574 SetLastError(0xdeadbeef);
575 lstrcpyA(dest, "control");
576 str = PathCombineA(dest, "relative\\dir", "\\one\\two\\three\\");
577 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
578 /* Vista fails which probably makes sense as PathCombineA expects an absolute dir */
581 ok(str == dest, "Expected str == dest, got %p\n", str);
582 ok(!lstrcmp(str, "one\\two\\three\\"), "Expected one\\two\\three\\, got %s\n", str);
585 /* try forward slashes */
586 SetLastError(0xdeadbeef);
587 lstrcpyA(dest, "control");
588 str = PathCombineA(dest, "C:\\", "one/two/three\\");
589 ok(str == dest, "Expected str == dest, got %p\n", str);
590 ok(!lstrcmp(str, "C:\\one/two/three\\"), "Expected one/two/three\\, got %s\n", str);
591 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
593 /* try a really weird directory */
594 SetLastError(0xdeadbeef);
595 lstrcpyA(dest, "control");
596 str = PathCombineA(dest, "C:\\/\\/", "\\one\\two\\three\\");
597 ok(str == dest, "Expected str == dest, got %p\n", str);
598 ok(!lstrcmp(str, "C:\\one\\two\\three\\"), "Expected C:\\one\\two\\three\\, got %s\n", str);
599 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
602 SetLastError(0xdeadbeef);
603 lstrcpyA(dest, "control");
604 str = PathCombineA(dest, "C:\\", "one\\..\\two\\.\\three");
605 ok(str == dest, "Expected str == dest, got %p\n", str);
606 ok(!lstrcmp(str, "C:\\two\\three"), "Expected C:\\two\\three, got %s\n", str);
607 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
610 /* try forward slashes */
611 SetLastError(0xdeadbeef);
612 lstrcpyA(dest, "control");
613 str = PathCombineA(dest, "C:\\", "..");
614 ok(str == dest, "Expected str == dest, got %p\n", str);
615 ok(!lstrcmp(str, "C:\\"), "Expected C:\\, got %s\n", str);
616 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
618 memset(too_long, 'a', LONG_LEN);
619 too_long[LONG_LEN - 1] = '\0';
621 /* try a file longer than MAX_PATH */
622 SetLastError(0xdeadbeef);
623 lstrcpyA(dest, "control");
624 str = PathCombineA(dest, "C:\\", too_long);
625 ok(str == NULL, "Expected str == NULL, got %p\n", str);
626 ok(lstrlenA(dest) == 0 ||
627 broken(!lstrcmp(dest, "control")), /* Win95 and some W2K */
628 "Expected 0 length, got %i\n", lstrlenA(dest));
629 todo_wine ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
631 /* try a directory longer than MAX_PATH */
632 SetLastError(0xdeadbeef);
633 lstrcpyA(dest, "control");
634 str = PathCombineA(dest, too_long, "one\\two\\three");
635 ok(str == NULL, "Expected str == NULL, got %p\n", str);
636 ok(lstrlenA(dest) == 0 ||
637 broken(!lstrcmp(dest, "control")), /* Win95 and some W2K */
638 "Expected 0 length, got %i\n", lstrlenA(dest));
639 todo_wine ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
641 memset(one, 'b', HALF_LEN);
642 memset(two, 'c', HALF_LEN);
643 one[HALF_LEN - 1] = '\0';
644 two[HALF_LEN - 1] = '\0';
646 /* destination string is longer than MAX_PATH, but not the constituent parts */
647 SetLastError(0xdeadbeef);
648 lstrcpyA(dest, "control");
649 str = PathCombineA(dest, one, two);
650 ok(str == NULL, "Expected str == NULL, got %p\n", str);
651 ok(lstrlenA(dest) == 0 ||
652 broken(!lstrcmp(dest, "control")), /* Win95 and some W2K */
653 "Expected 0 length, got %i\n", lstrlenA(dest));
654 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
657 static void test_PathAddBackslash(void)
661 char too_long[LONG_LEN];
663 /* try a NULL path */
664 SetLastError(0xdeadbeef);
665 str = PathAddBackslashA(NULL);
666 ok(str == NULL, "Expected str == NULL, got %p\n", str);
667 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
669 /* try an empty path */
671 SetLastError(0xdeadbeef);
672 str = PathAddBackslashA(path);
673 ok(str == (path + lstrlenA(path)), "Expected str to point to end of path, got %p\n", str);
674 ok(lstrlenA(path) == 0, "Expected empty string, got %i\n", lstrlenA(path));
675 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
677 /* try a relative path */
678 lstrcpyA(path, "one\\two");
679 SetLastError(0xdeadbeef);
680 str = PathAddBackslashA(path);
681 ok(str == (path + lstrlenA(path)), "Expected str to point to end of path, got %p\n", str);
682 ok(!lstrcmp(path, "one\\two\\"), "Expected one\\two\\, got %s\n", path);
683 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
686 lstrcpyA(path, "one\\..\\two");
687 SetLastError(0xdeadbeef);
688 str = PathAddBackslashA(path);
689 ok(str == (path + lstrlenA(path)), "Expected str to point to end of path, got %p\n", str);
690 ok(!lstrcmp(path, "one\\..\\two\\"), "Expected one\\..\\two\\, got %s\n", path);
691 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
693 /* try just a space */
695 SetLastError(0xdeadbeef);
696 str = PathAddBackslashA(path);
697 ok(str == (path + lstrlenA(path)), "Expected str to point to end of path, got %p\n", str);
698 ok(!lstrcmp(path, " \\"), "Expected \\, got %s\n", path);
699 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
701 /* path already has backslash */
702 lstrcpyA(path, "C:\\one\\");
703 SetLastError(0xdeadbeef);
704 str = PathAddBackslashA(path);
705 ok(str == (path + lstrlenA(path)), "Expected str to point to end of path, got %p\n", str);
706 ok(!lstrcmp(path, "C:\\one\\"), "Expected C:\\one\\, got %s\n", path);
707 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
709 memset(too_long, 'a', LONG_LEN);
710 too_long[LONG_LEN - 1] = '\0';
712 /* path is longer than MAX_PATH */
713 SetLastError(0xdeadbeef);
714 str = PathAddBackslashA(too_long);
715 ok(str == NULL, "Expected str == NULL, got %p\n", str);
716 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
719 static void test_PathAppendA(void)
722 char too_long[LONG_LEN];
726 lstrcpy(path, "C:\\one");
728 /* try NULL pszMore */
729 SetLastError(0xdeadbeef);
730 res = PathAppendA(path, NULL);
731 ok(!res, "Expected failure\n");
732 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
733 ok(!lstrcmp(path, "C:\\one"), "Expected C:\\one, got %s\n", path);
735 /* try empty pszMore */
736 SetLastError(0xdeadbeef);
737 res = PathAppendA(path, "");
738 ok(res, "Expected success\n");
739 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
740 ok(!lstrcmp(path, "C:\\one"), "Expected C:\\one, got %s\n", path);
742 /* try NULL pszPath */
743 SetLastError(0xdeadbeef);
744 res = PathAppendA(NULL, "two\\three");
745 ok(!res, "Expected failure\n");
746 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
748 /* try empty pszPath */
750 SetLastError(0xdeadbeef);
751 res = PathAppendA(path, "two\\three");
752 ok(res, "Expected success\n");
753 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
754 ok(!lstrcmp(path, "two\\three"), "Expected \\two\\three, got %s\n", path);
756 /* try empty pszPath and empty pszMore */
758 SetLastError(0xdeadbeef);
759 res = PathAppendA(path, "");
760 ok(res, "Expected success\n");
761 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
762 ok(!lstrcmp(path, "\\"), "Expected \\, got %s\n", path);
764 /* try legit params */
765 lstrcpy(path, "C:\\one");
766 SetLastError(0xdeadbeef);
767 res = PathAppendA(path, "two\\three");
768 ok(res, "Expected success\n");
769 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
770 ok(!lstrcmp(path, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", path);
772 /* try pszPath with backslash after it */
773 lstrcpy(path, "C:\\one\\");
774 SetLastError(0xdeadbeef);
775 res = PathAppendA(path, "two\\three");
776 ok(res, "Expected success\n");
777 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
778 ok(!lstrcmp(path, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", path);
780 /* try pszMore with backslash before it */
781 lstrcpy(path, "C:\\one");
782 SetLastError(0xdeadbeef);
783 res = PathAppendA(path, "\\two\\three");
784 ok(res, "Expected success\n");
785 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
786 ok(!lstrcmp(path, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", path);
788 /* try pszMore with backslash after it */
789 lstrcpy(path, "C:\\one");
790 SetLastError(0xdeadbeef);
791 res = PathAppendA(path, "two\\three\\");
792 ok(res, "Expected success\n");
793 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
794 ok(!lstrcmp(path, "C:\\one\\two\\three\\"), "Expected C:\\one\\two\\three\\, got %s\n", path);
796 /* try spaces in pszPath */
797 lstrcpy(path, "C: \\ one ");
798 SetLastError(0xdeadbeef);
799 res = PathAppendA(path, "two\\three");
800 ok(res, "Expected success\n");
801 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
802 ok(!lstrcmp(path, "C: \\ one \\two\\three"), "Expected C: \\ one \\two\\three, got %s\n", path);
804 /* try spaces in pszMore */
805 lstrcpy(path, "C:\\one");
806 SetLastError(0xdeadbeef);
807 res = PathAppendA(path, " two \\ three ");
808 ok(res, "Expected success\n");
809 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
810 ok(!lstrcmp(path, "C:\\one\\ two \\ three "), "Expected 'C:\\one\\ two \\ three ', got %s\n", path);
812 /* pszPath is too long */
813 memset(too_long, 'a', LONG_LEN);
814 too_long[LONG_LEN - 1] = '\0';
815 SetLastError(0xdeadbeef);
816 res = PathAppendA(too_long, "two\\three");
817 ok(!res, "Expected failure\n");
818 todo_wine ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
819 ok(lstrlen(too_long) == 0 ||
820 broken(lstrlen(too_long) == (LONG_LEN - 1)), /* Win95 and some W2K */
821 "Expected length of too_long to be zero, got %i\n", lstrlen(too_long));
823 /* pszMore is too long */
824 lstrcpy(path, "C:\\one");
825 memset(too_long, 'a', LONG_LEN);
826 too_long[LONG_LEN - 1] = '\0';
827 SetLastError(0xdeadbeef);
828 res = PathAppendA(path, too_long);
829 ok(!res, "Expected failure\n");
830 todo_wine ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
831 ok(lstrlen(path) == 0 ||
832 broken(!lstrcmp(path, "C:\\one")), /* Win95 and some W2K */
833 "Expected length of path to be zero, got %i\n", lstrlen(path));
835 /* both params combined are too long */
836 memset(path, 'a', HALF_LEN);
837 path[HALF_LEN - 1] = '\0';
838 memset(half, 'b', HALF_LEN);
839 half[HALF_LEN - 1] = '\0';
840 SetLastError(0xdeadbeef);
841 res = PathAppendA(path, half);
842 ok(!res, "Expected failure\n");
843 ok(lstrlen(path) == 0 ||
844 broken(lstrlen(path) == (HALF_LEN - 1)), /* Win95 and some W2K */
845 "Expected length of path to be zero, got %i\n", lstrlen(path));
846 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
849 static void test_PathCanonicalizeA(void)
851 char dest[LONG_LEN + MAX_PATH];
852 char too_long[LONG_LEN];
855 /* try a NULL source */
856 lstrcpy(dest, "test");
857 SetLastError(0xdeadbeef);
858 res = PathCanonicalizeA(dest, NULL);
859 ok(!res, "Expected failure\n");
860 ok(GetLastError() == ERROR_INVALID_PARAMETER,
861 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
862 ok(dest[0] == 0 || !lstrcmp(dest, "test"),
863 "Expected either an empty string (Vista) or test, got %s\n", dest);
865 /* try an empty source */
866 lstrcpy(dest, "test");
867 SetLastError(0xdeadbeef);
868 res = PathCanonicalizeA(dest, "");
869 ok(res, "Expected success\n");
870 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
871 ok(!lstrcmp(dest, "\\") ||
872 broken(!lstrcmp(dest, "test")), /* Win95 and some W2K */
873 "Expected \\, got %s\n", dest);
875 /* try a NULL dest */
876 SetLastError(0xdeadbeef);
877 res = PathCanonicalizeA(NULL, "C:\\");
878 ok(!res, "Expected failure\n");
879 ok(GetLastError() == ERROR_INVALID_PARAMETER,
880 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
884 SetLastError(0xdeadbeef);
885 res = PathCanonicalizeA(dest, "C:\\");
886 ok(res, "Expected success\n");
887 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
888 ok(!lstrcmp(dest, "C:\\"), "Expected C:\\, got %s\n", dest);
890 /* try non-empty dest */
891 lstrcpy(dest, "test");
892 SetLastError(0xdeadbeef);
893 res = PathCanonicalizeA(dest, "C:\\");
894 ok(res, "Expected success\n");
895 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
896 ok(!lstrcmp(dest, "C:\\"), "Expected C:\\, got %s\n", dest);
898 /* try a space for source */
899 lstrcpy(dest, "test");
900 SetLastError(0xdeadbeef);
901 res = PathCanonicalizeA(dest, " ");
902 ok(res, "Expected success\n");
903 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
904 ok(!lstrcmp(dest, " "), "Expected ' ', got %s\n", dest);
906 /* try a relative path */
907 lstrcpy(dest, "test");
908 SetLastError(0xdeadbeef);
909 res = PathCanonicalizeA(dest, "one\\two");
910 ok(res, "Expected success\n");
911 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
912 ok(!lstrcmp(dest, "one\\two"), "Expected one\\two, got %s\n", dest);
914 /* try current dir and previous dir */
915 lstrcpy(dest, "test");
916 SetLastError(0xdeadbeef);
917 res = PathCanonicalizeA(dest, "C:\\one\\.\\..\\two\\three\\..");
918 ok(res, "Expected success\n");
919 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
920 ok(!lstrcmp(dest, "C:\\two"), "Expected C:\\two, got %s\n", dest);
922 /* try simple forward slashes */
923 lstrcpy(dest, "test");
924 SetLastError(0xdeadbeef);
925 res = PathCanonicalizeA(dest, "C:\\one/two/three\\four/five\\six");
926 ok(res, "Expected success\n");
927 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
928 ok(!lstrcmp(dest, "C:\\one/two/three\\four/five\\six"),
929 "Expected C:\\one/two/three\\four/five\\six, got %s\n", dest);
931 /* try simple forward slashes with same dir */
932 lstrcpy(dest, "test");
933 SetLastError(0xdeadbeef);
934 res = PathCanonicalizeA(dest, "C:\\one/.\\two");
935 ok(res, "Expected success\n");
936 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
937 ok(!lstrcmp(dest, "C:\\one/.\\two"), "Expected C:\\one/.\\two, got %s\n", dest);
939 /* try simple forward slashes with change dir */
940 lstrcpy(dest, "test");
941 SetLastError(0xdeadbeef);
942 res = PathCanonicalizeA(dest, "C:\\one/.\\two\\..");
943 ok(res, "Expected success\n");
944 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
945 ok(!lstrcmp(dest, "C:\\one/.") ||
946 !lstrcmp(dest, "C:\\one/"), /* Vista */
947 "Expected \"C:\\one/.\" or \"C:\\one/\", got \"%s\"\n", dest);
949 /* try forward slashes with change dirs
950 * NOTE: if there is a forward slash in between two backslashes,
951 * everything in between the two backslashes is considered on dir
953 lstrcpy(dest, "test");
954 SetLastError(0xdeadbeef);
955 res = PathCanonicalizeA(dest, "C:\\one/.\\..\\two/three\\..\\four/.five");
956 ok(res, "Expected success\n");
957 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
958 ok(!lstrcmp(dest, "C:\\four/.five"), "Expected C:\\four/.five, got %s\n", dest);
960 /* try src is too long */
961 memset(too_long, 'a', LONG_LEN);
962 too_long[LONG_LEN - 1] = '\0';
963 lstrcpy(dest, "test");
964 SetLastError(0xdeadbeef);
965 res = PathCanonicalizeA(dest, too_long);
967 broken(res), /* Win95, some W2K and XP-SP1 */
968 "Expected failure\n");
971 ok(GetLastError() == 0xdeadbeef || GetLastError() == ERROR_FILENAME_EXCED_RANGE /* Vista */,
972 "Expected 0xdeadbeef or ERROR_FILENAME_EXCED_RANGE, got %d\n", GetLastError());
974 ok(lstrlen(too_long) == LONG_LEN - 1, "Expected length LONG_LEN - 1, got %i\n", lstrlen(too_long));
977 static void test_PathFindExtensionA(void)
981 char too_long[LONG_LEN];
983 /* try a NULL path */
984 SetLastError(0xdeadbeef);
985 ext = PathFindExtensionA(NULL);
986 ok(ext == NULL, "Expected NULL, got %p\n", ext);
987 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
989 /* try an empty path */
991 SetLastError(0xdeadbeef);
992 ext = PathFindExtensionA(path);
993 ok(ext == path, "Expected ext == path, got %p\n", ext);
994 ok(lstrlen(ext) == 0, "Expected length 0, got %i\n", lstrlen(ext));
995 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
997 /* try a path without an extension */
998 lstrcpy(path, "file");
999 SetLastError(0xdeadbeef);
1000 ext = PathFindExtensionA(path);
1001 ok(ext == path + lstrlen(path), "Expected ext == path, got %p\n", ext);
1002 ok(lstrlen(ext) == 0, "Expected length 0, got %i\n", lstrlen(ext));
1003 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1005 /* try a path with an extension */
1006 lstrcpy(path, "file.txt");
1007 SetLastError(0xdeadbeef);
1008 ext = PathFindExtensionA(path);
1009 ok(ext == path + lstrlen("file"),
1010 "Expected ext == path + lstrlen(\"file\"), got %p\n", ext);
1011 ok(!lstrcmp(ext, ".txt"), "Expected .txt, got %s\n", ext);
1012 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1014 /* try a path with two extensions */
1015 lstrcpy(path, "file.txt.doc");
1016 SetLastError(0xdeadbeef);
1017 ext = PathFindExtensionA(path);
1018 ok(ext == path + lstrlen("file.txt"),
1019 "Expected ext == path + lstrlen(\"file.txt\"), got %p\n", ext);
1020 ok(!lstrcmp(ext, ".doc"), "Expected .txt, got %s\n", ext);
1021 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1023 /* try a path longer than MAX_PATH without an extension*/
1024 memset(too_long, 'a', LONG_LEN);
1025 too_long[LONG_LEN - 1] = '\0';
1026 SetLastError(0xdeadbeef);
1027 ext = PathFindExtensionA(too_long);
1028 ok(ext == too_long + LONG_LEN - 1, "Expected ext == too_long + LONG_LEN - 1, got %p\n", ext);
1029 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1031 /* try a path longer than MAX_PATH with an extension*/
1032 memset(too_long, 'a', LONG_LEN);
1033 too_long[LONG_LEN - 1] = '\0';
1034 lstrcpy(too_long + 300, ".abcde");
1035 too_long[lstrlen(too_long)] = 'a';
1036 SetLastError(0xdeadbeef);
1037 ext = PathFindExtensionA(too_long);
1038 ok(ext == too_long + 300, "Expected ext == too_long + 300, got %p\n", ext);
1039 ok(lstrlen(ext) == LONG_LEN - 301, "Expected LONG_LEN - 301, got %i\n", lstrlen(ext));
1040 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1043 static void test_PathBuildRootA(void)
1047 char root_expected[26][4];
1051 /* set up the expected paths */
1052 for (drive = 'A'; drive <= 'Z'; drive++)
1053 sprintf(root_expected[drive - 'A'], "%c:\\", drive);
1055 /* test the expected values */
1056 for (j = 0; j < 26; j++)
1058 SetLastError(0xdeadbeef);
1059 lstrcpy(path, "aaaaaaaaa");
1060 root = PathBuildRootA(path, j);
1061 ok(root == path, "Expected root == path, got %p\n", root);
1062 ok(!lstrcmp(root, root_expected[j]), "Expected %s, got %s\n", root_expected[j], root);
1063 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1066 /* test a negative drive number */
1067 SetLastError(0xdeadbeef);
1068 lstrcpy(path, "aaaaaaaaa");
1069 root = PathBuildRootA(path, -1);
1070 ok(root == path, "Expected root == path, got %p\n", root);
1071 ok(!lstrcmp(path, "aaaaaaaaa") ||
1072 lstrlenA(path) == 0, /* Vista */
1073 "Expected aaaaaaaaa or empty string, got %s\n", path);
1074 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1076 /* test a drive number greater than 25 */
1077 SetLastError(0xdeadbeef);
1078 lstrcpy(path, "aaaaaaaaa");
1079 root = PathBuildRootA(path, 26);
1080 ok(root == path, "Expected root == path, got %p\n", root);
1081 ok(!lstrcmp(path, "aaaaaaaaa") ||
1082 lstrlenA(path) == 0, /* Vista */
1083 "Expected aaaaaaaaa or empty string, got %s\n", path);
1084 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1086 /* length of path is less than 4 */
1087 SetLastError(0xdeadbeef);
1088 lstrcpy(path, "aa");
1089 root = PathBuildRootA(path, 0);
1090 ok(root == path, "Expected root == path, got %p\n", root);
1091 ok(!lstrcmp(path, "A:\\"), "Expected A:\\, got %s\n", path);
1092 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1095 SetLastError(0xdeadbeef);
1096 root = PathBuildRootA(NULL, 0);
1097 ok(root == NULL, "Expected root == NULL, got %p\n", root);
1098 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1101 static void test_PathCommonPrefixA(void)
1103 char path1[MAX_PATH], path2[MAX_PATH];
1107 /* test NULL path1 */
1108 SetLastError(0xdeadbeef);
1109 lstrcpy(path2, "C:\\");
1110 lstrcpy(out, "aaa");
1111 count = PathCommonPrefixA(NULL, path2, out);
1112 ok(count == 0, "Expected 0, got %i\n", count);
1115 ok(!lstrcmp(out, "aaa"), "Expected aaa, got %s\n", out);
1117 ok(!lstrcmp(path2, "C:\\"), "Expected C:\\, got %s\n", path2);
1118 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1120 /* test NULL path2 */
1121 SetLastError(0xdeadbeef);
1122 lstrcpy(path1, "C:\\");
1123 lstrcpy(out, "aaa");
1124 count = PathCommonPrefixA(path1, NULL, out);
1125 ok(count == 0, "Expected 0, got %i\n", count);
1128 ok(!lstrcmp(out, "aaa"), "Expected aaa, got %s\n", out);
1130 ok(!lstrcmp(path1, "C:\\"), "Expected C:\\, got %s\n", path1);
1131 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1133 /* test empty path1 */
1134 SetLastError(0xdeadbeef);
1136 lstrcpy(path2, "C:\\");
1137 lstrcpy(out, "aaa");
1138 count = PathCommonPrefixA(path1, path2, out);
1139 ok(count == 0, "Expected 0, got %i\n", count);
1140 ok(lstrlen(out) == 0, "Expected 0 length out, got %i\n", lstrlen(out));
1141 ok(lstrlen(path1) == 0, "Expected 0 length path1, got %i\n", lstrlen(path1));
1142 ok(!lstrcmp(path2, "C:\\"), "Expected C:\\, got %s\n", path2);
1143 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1145 /* test empty path1 */
1146 SetLastError(0xdeadbeef);
1148 lstrcpy(path1, "C:\\");
1149 lstrcpy(out, "aaa");
1150 count = PathCommonPrefixA(path1, path2, out);
1151 ok(count == 0, "Expected 0, got %i\n", count);
1152 ok(lstrlen(out) == 0, "Expected 0 length out, got %i\n", lstrlen(out));
1153 ok(lstrlen(path2) == 0, "Expected 0 length path2, got %i\n", lstrlen(path2));
1154 ok(!lstrcmp(path1, "C:\\"), "Expected C:\\, got %s\n", path1);
1155 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1157 /* paths are legit, out is NULL */
1158 SetLastError(0xdeadbeef);
1159 lstrcpy(path1, "C:\\");
1160 lstrcpy(path2, "C:\\");
1161 count = PathCommonPrefixA(path1, path2, NULL);
1162 ok(count == 3, "Expected 3, got %i\n", count);
1163 ok(!lstrcmp(path1, "C:\\"), "Expected C:\\, got %s\n", path1);
1164 ok(!lstrcmp(path2, "C:\\"), "Expected C:\\, got %s\n", path2);
1165 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1167 /* all parameters legit */
1168 SetLastError(0xdeadbeef);
1169 lstrcpy(path1, "C:\\");
1170 lstrcpy(path2, "C:\\");
1171 lstrcpy(out, "aaa");
1172 count = PathCommonPrefixA(path1, path2, out);
1173 ok(count == 3, "Expected 3, got %i\n", count);
1174 ok(!lstrcmp(path1, "C:\\"), "Expected C:\\, got %s\n", path1);
1175 ok(!lstrcmp(path2, "C:\\"), "Expected C:\\, got %s\n", path2);
1176 ok(!lstrcmp(out, "C:\\"), "Expected C:\\, got %s\n", out);
1177 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1179 /* path1 and path2 not the same, but common prefix */
1180 SetLastError(0xdeadbeef);
1181 lstrcpy(path1, "C:\\one\\two");
1182 lstrcpy(path2, "C:\\one\\three");
1183 lstrcpy(out, "aaa");
1184 count = PathCommonPrefixA(path1, path2, out);
1185 ok(count == 6, "Expected 6, got %i\n", count);
1186 ok(!lstrcmp(path1, "C:\\one\\two"), "Expected C:\\one\\two, got %s\n", path1);
1187 ok(!lstrcmp(path2, "C:\\one\\three"), "Expected C:\\one\\three, got %s\n", path2);
1188 ok(!lstrcmp(out, "C:\\one"), "Expected C:\\one, got %s\n", out);
1189 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1192 SetLastError(0xdeadbeef);
1193 lstrcpy(path1, "one\\.two");
1194 lstrcpy(path2, "one\\.three");
1195 lstrcpy(out, "aaa");
1196 count = PathCommonPrefixA(path1, path2, out);
1197 ok(count == 3, "Expected 3, got %i\n", count);
1198 ok(!lstrcmp(path1, "one\\.two"), "Expected one\\.two, got %s\n", path1);
1199 ok(!lstrcmp(path2, "one\\.three"), "Expected one\\.three, got %s\n", path2);
1200 ok(!lstrcmp(out, "one"), "Expected one, got %s\n", out);
1201 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1204 SetLastError(0xdeadbeef);
1205 lstrcpy(path1, "one\\..two");
1206 lstrcpy(path2, "one\\..three");
1207 lstrcpy(out, "aaa");
1208 count = PathCommonPrefixA(path1, path2, out);
1209 ok(count == 3, "Expected 3, got %i\n", count);
1210 ok(!lstrcmp(path1, "one\\..two"), "Expected one\\..two, got %s\n", path1);
1211 ok(!lstrcmp(path2, "one\\..three"), "Expected one\\..three, got %s\n", path2);
1212 ok(!lstrcmp(out, "one"), "Expected one, got %s\n", out);
1213 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1215 /* try ... prefix */
1216 SetLastError(0xdeadbeef);
1217 lstrcpy(path1, "one\\...two");
1218 lstrcpy(path2, "one\\...three");
1219 lstrcpy(out, "aaa");
1220 count = PathCommonPrefixA(path1, path2, out);
1221 ok(count == 3, "Expected 3, got %i\n", count);
1222 ok(!lstrcmp(path1, "one\\...two"), "Expected one\\...two, got %s\n", path1);
1223 ok(!lstrcmp(path2, "one\\...three"), "Expected one\\...three, got %s\n", path2);
1224 ok(!lstrcmp(out, "one"), "Expected one, got %s\n", out);
1225 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1228 SetLastError(0xdeadbeef);
1229 lstrcpy(path1, "one\\.\\two");
1230 lstrcpy(path2, "one\\.\\three");
1231 lstrcpy(out, "aaa");
1232 count = PathCommonPrefixA(path1, path2, out);
1233 ok(count == 5, "Expected 5, got %i\n", count);
1234 ok(!lstrcmp(path1, "one\\.\\two"), "Expected one\\.\\two, got %s\n", path1);
1235 ok(!lstrcmp(path2, "one\\.\\three"), "Expected one\\.\\three, got %s\n", path2);
1236 ok(!lstrcmp(out, "one\\."), "Expected one\\., got %s\n", out);
1237 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1239 /* try ..\ prefix */
1240 SetLastError(0xdeadbeef);
1241 lstrcpy(path1, "one\\..\\two");
1242 lstrcpy(path2, "one\\..\\three");
1243 lstrcpy(out, "aaa");
1244 count = PathCommonPrefixA(path1, path2, out);
1245 ok(count == 6, "Expected 6, got %i\n", count);
1246 ok(!lstrcmp(path1, "one\\..\\two"), "Expected one\\..\\two, got %s\n", path1);
1247 ok(!lstrcmp(path2, "one\\..\\three"), "Expected one\\..\\three, got %s\n", path2);
1248 ok(!lstrcmp(out, "one\\.."), "Expected one\\.., got %s\n", out);
1249 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1251 /* try ...\\ prefix */
1252 SetLastError(0xdeadbeef);
1253 lstrcpy(path1, "one\\...\\two");
1254 lstrcpy(path2, "one\\...\\three");
1255 lstrcpy(out, "aaa");
1256 count = PathCommonPrefixA(path1, path2, out);
1257 ok(count == 7, "Expected 7, got %i\n", count);
1258 ok(!lstrcmp(path1, "one\\...\\two"), "Expected one\\...\\two, got %s\n", path1);
1259 ok(!lstrcmp(path2, "one\\...\\three"), "Expected one\\...\\three, got %s\n", path2);
1260 ok(!lstrcmp(out, "one\\..."), "Expected one\\..., got %s\n", out);
1261 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1263 /* try prefix that is not an msdn labeled prefix type */
1264 SetLastError(0xdeadbeef);
1265 lstrcpy(path1, "same");
1266 lstrcpy(path2, "same");
1267 lstrcpy(out, "aaa");
1268 count = PathCommonPrefixA(path1, path2, out);
1269 ok(count == 4, "Expected 4, got %i\n", count);
1270 ok(!lstrcmp(path1, "same"), "Expected same, got %s\n", path1);
1271 ok(!lstrcmp(path2, "same"), "Expected same, got %s\n", path2);
1272 ok(!lstrcmp(out, "same"), "Expected same, got %s\n", out);
1273 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1275 /* try . after directory */
1276 SetLastError(0xdeadbeef);
1277 lstrcpy(path1, "one\\mid.\\two");
1278 lstrcpy(path2, "one\\mid.\\three");
1279 lstrcpy(out, "aaa");
1280 count = PathCommonPrefixA(path1, path2, out);
1281 ok(count == 8, "Expected 8, got %i\n", count);
1282 ok(!lstrcmp(path1, "one\\mid.\\two"), "Expected one\\mid.\\two, got %s\n", path1);
1283 ok(!lstrcmp(path2, "one\\mid.\\three"), "Expected one\\mid.\\three, got %s\n", path2);
1284 ok(!lstrcmp(out, "one\\mid."), "Expected one\\mid., got %s\n", out);
1285 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1287 /* try . in the middle of a directory */
1288 SetLastError(0xdeadbeef);
1289 lstrcpy(path1, "one\\mid.end\\two");
1290 lstrcpy(path2, "one\\mid.end\\three");
1291 lstrcpy(out, "aaa");
1292 count = PathCommonPrefixA(path1, path2, out);
1293 ok(count == 11, "Expected 11, got %i\n", count);
1294 ok(!lstrcmp(path1, "one\\mid.end\\two"), "Expected one\\mid.end\\two, got %s\n", path1);
1295 ok(!lstrcmp(path2, "one\\mid.end\\three"), "Expected one\\mid.end\\three, got %s\n", path2);
1296 ok(!lstrcmp(out, "one\\mid.end"), "Expected one\\mid.end, got %s\n", out);
1297 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1299 /* try comparing a .. with the expanded path */
1300 SetLastError(0xdeadbeef);
1301 lstrcpy(path1, "one\\..\\two");
1302 lstrcpy(path2, "two");
1303 lstrcpy(out, "aaa");
1304 count = PathCommonPrefixA(path1, path2, out);
1305 ok(count == 0, "Expected 0, got %i\n", count);
1306 ok(!lstrcmp(path1, "one\\..\\two"), "Expected one\\..\\two, got %s\n", path1);
1307 ok(!lstrcmp(path2, "two"), "Expected two, got %s\n", path2);
1308 ok(lstrlen(out) == 0, "Expected 0 length out, got %i\n", lstrlen(out));
1309 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1312 static void test_PathUnquoteSpaces(void)
1315 for(i = 0; i < sizeof(TEST_PATH_UNQUOTE_SPACES) / sizeof(TEST_PATH_UNQUOTE_SPACES[0]); i++)
1317 char *path = strdupA(TEST_PATH_UNQUOTE_SPACES[i].path);
1318 WCHAR *pathW = GetWideString(TEST_PATH_UNQUOTE_SPACES[i].path);
1319 WCHAR *resultW = GetWideString(TEST_PATH_UNQUOTE_SPACES[i].result);
1321 PathUnquoteSpacesA(path);
1322 ok(!strcmp(path, TEST_PATH_UNQUOTE_SPACES[i].result), "%s (A): got %s expected %s\n",
1323 TEST_PATH_UNQUOTE_SPACES[i].path, path,
1324 TEST_PATH_UNQUOTE_SPACES[i].result);
1326 PathUnquoteSpacesW(pathW);
1327 ok(!lstrcmpW(pathW, resultW), "%s (W): strings differ\n",
1328 TEST_PATH_UNQUOTE_SPACES[i].path);
1329 FreeWideString(pathW);
1330 FreeWideString(resultW);
1331 HeapFree(GetProcessHeap(), 0, path);
1335 static void test_PathGetDriveNumber(void)
1337 static const CHAR test1A[] = "a:\\test.file";
1338 static const CHAR test2A[] = "file:////b:\\test.file";
1339 static const CHAR test3A[] = "file:///c:\\test.file";
1340 static const CHAR test4A[] = "file:\\\\c:\\test.file";
1343 SetLastError(0xdeadbeef);
1344 ret = PathGetDriveNumberA(NULL);
1345 ok(ret == -1, "got %d\n", ret);
1346 ok(GetLastError() == 0xdeadbeef, "got %d\n", GetLastError());
1348 ret = PathGetDriveNumberA(test1A);
1349 ok(ret == 0, "got %d\n", ret);
1350 ret = PathGetDriveNumberA(test2A);
1351 ok(ret == -1, "got %d\n", ret);
1352 ret = PathGetDriveNumberA(test3A);
1353 ok(ret == -1, "got %d\n", ret);
1354 ret = PathGetDriveNumberA(test4A);
1355 ok(ret == -1, "got %d\n", ret);
1358 /* ################ */
1362 HMODULE hShlwapi = GetModuleHandleA("shlwapi.dll");
1364 /* SHCreateStreamOnFileEx was introduced in shlwapi v6.0 */
1365 if(!GetProcAddress(hShlwapi, "SHCreateStreamOnFileEx")){
1366 win_skip("Too old shlwapi version\n");
1370 pPathCreateFromUrlA = (void*)GetProcAddress(hShlwapi, "PathCreateFromUrlA");
1371 pPathCreateFromUrlW = (void*)GetProcAddress(hShlwapi, "PathCreateFromUrlW");
1372 pPathCombineW = (void*)GetProcAddress(hShlwapi, "PathCombineW");
1373 pPathIsValidCharA = (void*)GetProcAddress(hShlwapi, (LPSTR)455);
1374 pPathIsValidCharW = (void*)GetProcAddress(hShlwapi, (LPSTR)456);
1375 pPathAppendA = (void*)GetProcAddress(hShlwapi, "PathAppendA");
1377 test_PathSearchAndQualify();
1378 test_PathCreateFromUrl();
1381 test_PathAddBackslash();
1382 test_PathMakePretty();
1383 test_PathMatchSpec();
1385 test_PathIsValidCharA();
1386 test_PathIsValidCharW();
1388 test_PathCombineW();
1389 test_PathCombineA();
1391 test_PathCanonicalizeA();
1392 test_PathFindExtensionA();
1393 test_PathBuildRootA();
1394 test_PathCommonPrefixA();
1395 test_PathUnquoteSpaces();
1396 test_PathGetDriveNumber();