wininet: Support the Cache-Control max-age directive for setting url cache entry...
[wine/testsucceed.git] / dlls / shlwapi / tests / path.c
blobe5f5c7c60d057a8b5cf71a77e05031cb7b8d3921
1 /* Unit test suite for Path functions
3 * Copyright 2002 Matthew Mastracci
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 #include <assert.h>
21 #include <stdarg.h>
22 #include <stdio.h>
24 #include "wine/test.h"
25 #include "windef.h"
26 #include "winbase.h"
27 #include "winreg.h"
28 #include "shlwapi.h"
29 #include "wininet.h"
31 static HRESULT (WINAPI *pPathIsValidCharA)(char,DWORD);
32 static HRESULT (WINAPI *pPathIsValidCharW)(WCHAR,DWORD);
33 static LPWSTR (WINAPI *pPathCombineW)(LPWSTR, LPCWSTR, LPCWSTR);
34 static HRESULT (WINAPI *pPathCreateFromUrlA)(LPCSTR, LPSTR, LPDWORD, DWORD);
35 static HRESULT (WINAPI *pPathCreateFromUrlW)(LPCWSTR, LPWSTR, LPDWORD, DWORD);
36 static BOOL (WINAPI *pPathAppendA)(LPSTR, LPCSTR);
38 /* ################ */
40 static const struct {
41 const char *url;
42 const char *path;
43 DWORD ret;
44 } TEST_PATHFROMURL[] = {
45 {"file:///c:/foo/ba%5Cr", "c:\\foo\\ba\\r", S_OK},
46 {"file:///c:/foo/../ba%5Cr", "c:\\foo\\..\\ba\\r", S_OK},
47 {"file:///host/c:/foo/bar", "\\host\\c:\\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\\c:\\foo\\bar", "\\\\hostc:\\foo\\bar", S_OK},
51 {"file:\\\\host\\ca\\foo\\bar", "\\\\host\\ca\\foo\\bar", S_OK},
52 {"file:\\\\host\\c|\\foo\\bar", "\\\\hostc|\\foo\\bar", S_OK},
53 {"file:\\%5Chost\\c:\\foo\\bar", "\\\\host\\c:\\foo\\bar", S_OK},
54 {"file:\\\\host\\cx:\\foo\\bar", "\\\\host\\cx:\\foo\\bar", S_OK},
55 {"file://c:/foo/bar", "c:\\foo\\bar", S_OK},
56 {"file://c:/d:/foo/bar", "c:\\d:\\foo\\bar", S_OK},
57 {"file://c|/d|/foo/bar", "c:\\d|\\foo\\bar", S_OK},
58 {"file://host/foo/bar", "\\\\host\\foo\\bar", S_OK},
59 {"file:/foo/bar", "\\foo\\bar", S_OK},
60 {"file:/foo/bar/", "\\foo\\bar\\", S_OK},
61 {"file:foo/bar", "foo\\bar", S_OK},
62 {"file:c:/foo/bar", "c:\\foo\\bar", S_OK},
63 {"file:c|/foo/bar", "c:\\foo\\bar", S_OK},
64 {"file:cx|/foo/bar", "cx|\\foo\\bar", S_OK},
65 {"file:////c:/foo/bar", "c:\\foo\\bar", S_OK},
66 /* {"file:////c:/foo/foo%20bar", "c:\\foo\\foo%20bar", S_OK},*/
68 {"c:\\foo\\bar", NULL, E_INVALIDARG},
69 {"foo/bar", NULL, E_INVALIDARG},
70 {"http://foo/bar", NULL, E_INVALIDARG},
75 static struct {
76 const char *path;
77 BOOL expect;
78 } TEST_PATH_IS_URL[] = {
79 {"http://foo/bar", TRUE},
80 {"c:\\foo\\bar", FALSE},
81 {"c:/foo/bar", FALSE},
82 {"foo://foo/bar", TRUE},
83 {"foo\\bar", FALSE},
84 {"foo.bar", FALSE},
85 {"bogusscheme:", TRUE},
86 {"http:partial", TRUE},
87 {"www.winehq.org", FALSE},
88 /* More examples that the user might enter as the browser start page */
89 {"winehq.org", FALSE},
90 {"ftp.winehq.org", FALSE},
91 {"http://winehq.org", TRUE},
92 {"http://www.winehq.org", TRUE},
93 {"https://winehq.org", TRUE},
94 {"https://www.winehq.org", TRUE},
95 {"ftp://winehq.org", TRUE},
96 {"ftp://ftp.winehq.org", TRUE},
97 {"file://does_not_exist.txt", TRUE},
98 {"about:blank", TRUE},
99 {"about:home", TRUE},
100 {"about:mozilla", TRUE},
101 /* scheme is case independent */
102 {"HTTP://www.winehq.org", TRUE},
103 /* a space at the start is not allowed */
104 {" http://www.winehq.org", FALSE},
105 {"", FALSE},
106 {NULL, FALSE}
109 static const struct {
110 const char *path;
111 const char *result;
112 } TEST_PATH_UNQUOTE_SPACES[] = {
113 { "abcdef", "abcdef" },
114 { "\"abcdef\"", "abcdef" },
115 { "\"abcdef", "\"abcdef" },
116 { "abcdef\"", "abcdef\"" },
117 { "\"\"abcdef\"\"", "\"abcdef\"" },
118 { "abc\"def", "abc\"def" },
119 { "\"abc\"def", "\"abc\"def" },
120 { "\"abc\"def\"", "abc\"def" },
121 { "\'abcdef\'", "\'abcdef\'" },
122 { "\"\"", "" },
123 { "\"", "" }
126 /* ################ */
128 static LPWSTR GetWideString(const char* szString)
130 LPWSTR wszString = HeapAlloc(GetProcessHeap(), 0, (2*INTERNET_MAX_URL_LENGTH) * sizeof(WCHAR));
132 MultiByteToWideChar(0, 0, szString, -1, wszString, INTERNET_MAX_URL_LENGTH);
134 return wszString;
137 static void FreeWideString(LPWSTR wszString)
139 HeapFree(GetProcessHeap(), 0, wszString);
142 static LPSTR strdupA(LPCSTR p)
144 LPSTR ret;
145 DWORD len = (strlen(p) + 1);
146 ret = HeapAlloc(GetProcessHeap(), 0, len);
147 memcpy(ret, p, len);
148 return ret;
151 /* ################ */
153 static void test_PathSearchAndQualify(void)
155 WCHAR path1[] = {'c',':','\\','f','o','o',0};
156 WCHAR expect1[] = {'c',':','\\','f','o','o',0};
157 WCHAR path2[] = {'c',':','f','o','o',0};
158 WCHAR c_drive[] = {'c',':',0};
159 WCHAR foo[] = {'f','o','o',0};
160 WCHAR path3[] = {'\\','f','o','o',0};
161 WCHAR winini[] = {'w','i','n','.','i','n','i',0};
162 WCHAR out[MAX_PATH];
163 WCHAR cur_dir[MAX_PATH];
164 WCHAR dot[] = {'.',0};
166 /* c:\foo */
167 ok(PathSearchAndQualifyW(path1, out, MAX_PATH) != 0,
168 "PathSearchAndQualify rets 0\n");
169 ok(!lstrcmpiW(out, expect1), "strings don't match\n");
171 /* c:foo */
172 ok(PathSearchAndQualifyW(path2, out, MAX_PATH) != 0,
173 "PathSearchAndQualify rets 0\n");
174 GetFullPathNameW(c_drive, MAX_PATH, cur_dir, NULL);
175 PathAddBackslashW(cur_dir);
176 lstrcatW(cur_dir, foo);
177 ok(!lstrcmpiW(out, cur_dir), "strings don't match\n");
179 /* foo */
180 ok(PathSearchAndQualifyW(foo, out, MAX_PATH) != 0,
181 "PathSearchAndQualify rets 0\n");
182 GetFullPathNameW(dot, MAX_PATH, cur_dir, NULL);
183 PathAddBackslashW(cur_dir);
184 lstrcatW(cur_dir, foo);
185 ok(!lstrcmpiW(out, cur_dir), "strings don't match\n");
187 /* \foo */
188 ok(PathSearchAndQualifyW(path3, out, MAX_PATH) != 0,
189 "PathSearchAndQualify rets 0\n");
190 GetFullPathNameW(dot, MAX_PATH, cur_dir, NULL);
191 lstrcpyW(cur_dir + 2, path3);
192 ok(!lstrcmpiW(out, cur_dir), "strings don't match\n");
194 /* win.ini */
195 ok(PathSearchAndQualifyW(winini, out, MAX_PATH) != 0,
196 "PathSearchAndQualify rets 0\n");
197 if(!SearchPathW(NULL, winini, NULL, MAX_PATH, cur_dir, NULL))
198 GetFullPathNameW(winini, MAX_PATH, cur_dir, NULL);
199 ok(!lstrcmpiW(out, cur_dir), "strings don't match\n");
203 static void test_PathCreateFromUrl(void)
205 size_t i;
206 char ret_path[INTERNET_MAX_URL_LENGTH];
207 DWORD len, ret;
208 WCHAR ret_pathW[INTERNET_MAX_URL_LENGTH];
209 WCHAR *pathW, *urlW;
210 static const char url[] = "http://www.winehq.org";
212 if (!pPathCreateFromUrlA) {
213 win_skip("PathCreateFromUrlA not found\n");
214 return;
217 /* Check ret_path = NULL */
218 len = sizeof(url);
219 ret = pPathCreateFromUrlA(url, NULL, &len, 0);
220 ok ( ret == E_INVALIDARG, "got 0x%08x expected E_INVALIDARG\n", ret);
222 for(i = 0; i < sizeof(TEST_PATHFROMURL) / sizeof(TEST_PATHFROMURL[0]); i++) {
223 len = INTERNET_MAX_URL_LENGTH;
224 ret = pPathCreateFromUrlA(TEST_PATHFROMURL[i].url, ret_path, &len, 0);
225 ok(ret == TEST_PATHFROMURL[i].ret, "ret %08x from url %s\n", ret, TEST_PATHFROMURL[i].url);
226 if(TEST_PATHFROMURL[i].path) {
227 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);
228 ok(len == strlen(ret_path), "ret len %d from url %s\n", len, TEST_PATHFROMURL[i].url);
230 if (pPathCreateFromUrlW) {
231 len = INTERNET_MAX_URL_LENGTH;
232 pathW = GetWideString(TEST_PATHFROMURL[i].path);
233 urlW = GetWideString(TEST_PATHFROMURL[i].url);
234 ret = pPathCreateFromUrlW(urlW, ret_pathW, &len, 0);
235 WideCharToMultiByte(CP_ACP, 0, ret_pathW, -1, ret_path, sizeof(ret_path),0,0);
236 ok(ret == TEST_PATHFROMURL[i].ret, "ret %08x from url L\"%s\"\n", ret, TEST_PATHFROMURL[i].url);
237 if(TEST_PATHFROMURL[i].path) {
238 ok(!lstrcmpiW(ret_pathW, pathW), "got %s expected %s from url L\"%s\"\n",
239 ret_path, TEST_PATHFROMURL[i].path, TEST_PATHFROMURL[i].url);
240 ok(len == lstrlenW(ret_pathW), "ret len %d from url L\"%s\"\n", len, TEST_PATHFROMURL[i].url);
242 FreeWideString(urlW);
243 FreeWideString(pathW);
249 static void test_PathIsUrl(void)
251 size_t i;
252 BOOL ret;
254 for(i = 0; i < sizeof(TEST_PATH_IS_URL)/sizeof(TEST_PATH_IS_URL[0]); i++) {
255 ret = PathIsURLA(TEST_PATH_IS_URL[i].path);
256 ok(ret == TEST_PATH_IS_URL[i].expect,
257 "returned %d from path %s, expected %d\n", ret, TEST_PATH_IS_URL[i].path,
258 TEST_PATH_IS_URL[i].expect);
262 static const DWORD SHELL_charclass[] =
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 0x00000000, 0x00000000, 0x00000000, 0x00000000,
272 0x00000080, 0x00000100, 0x00000200, 0x00000100,
273 0x00000100, 0x00000100, 0x00000100, 0x00000100,
274 0x00000100, 0x00000100, 0x00000002, 0x00000100,
275 0x00000040, 0x00000100, 0x00000004, 0x00000000,
276 0x00000100, 0x00000100, 0x00000100, 0x00000100,
277 0x00000100, 0x00000100, 0x00000100, 0x00000100,
278 0x00000100, 0x00000100, 0x00000010, 0x00000020,
279 0x00000000, 0x00000100, 0x00000000, 0x00000001,
280 0x00000100, 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, 0xffffffff,
286 0xffffffff, 0xffffffff, 0xffffffff, 0x00000100,
287 0x00000008, 0x00000100, 0x00000100, 0x00000100,
288 0x00000100, 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, 0xffffffff,
294 0xffffffff, 0xffffffff, 0xffffffff, 0x00000100,
295 0x00000000, 0x00000100, 0x00000100
298 static void test_PathIsValidCharA(void)
300 BOOL ret;
301 unsigned int c;
303 /* For whatever reason, PathIsValidCharA and PathAppendA share the same
304 * ordinal number in some native versions. Check this to prevent a crash.
306 if (!pPathIsValidCharA || pPathIsValidCharA == (void*)pPathAppendA)
308 win_skip("PathIsValidCharA isn't available\n");
309 return;
312 for (c = 0; c < 0x7f; c++)
314 ret = pPathIsValidCharA( c, ~0U );
315 ok ( ret || !SHELL_charclass[c], "PathIsValidCharA failed: 0x%02x got 0x%08x\n", c, ret );
318 for (c = 0x7f; c <= 0xff; c++)
320 ret = pPathIsValidCharA( c, ~0U );
321 ok ( ret, "PathIsValidCharA failed: 0x%02x got 0x%08x\n", c, ret );
325 static void test_PathIsValidCharW(void)
327 BOOL ret;
328 unsigned int c;
330 if (!pPathIsValidCharW)
332 win_skip("PathIsValidCharW isn't available\n");
333 return;
336 for (c = 0; c < 0x7f; c++)
338 ret = pPathIsValidCharW( c, ~0U );
339 ok ( ret || !SHELL_charclass[c], "PathIsValidCharW failed: 0x%02x got 0x%08x\n", c, ret );
342 for (c = 0x007f; c <= 0xffff; c++)
344 ret = pPathIsValidCharW( c, ~0U );
345 ok ( ret, "PathIsValidCharW failed: 0x%02x got 0x%08x\n", c, ret );
349 static void test_PathMakePretty(void)
351 char buff[MAX_PATH];
353 ok (PathMakePrettyA(NULL) == FALSE, "PathMakePretty: NULL path succeeded\n");
354 buff[0] = '\0';
355 ok (PathMakePrettyA(buff) == TRUE, "PathMakePretty: Empty path failed\n");
357 strcpy(buff, "C:\\A LONG FILE NAME WITH \\SPACES.TXT");
358 ok (PathMakePrettyA(buff) == TRUE, "PathMakePretty: Long UC name failed\n");
359 ok (strcmp(buff, "C:\\a long file name with \\spaces.txt") == 0,
360 "PathMakePretty: Long UC name not changed\n");
362 strcpy(buff, "C:\\A LONG FILE NAME WITH \\MixedCase.TXT");
363 ok (PathMakePrettyA(buff) == FALSE, "PathMakePretty: Long MC name succeeded\n");
364 ok (strcmp(buff, "C:\\A LONG FILE NAME WITH \\MixedCase.TXT") == 0,
365 "PathMakePretty: Failed but modified path\n");
367 strcpy(buff, "TEST");
368 ok (PathMakePrettyA(buff) == TRUE, "PathMakePretty: Short name failed\n");
369 ok (strcmp(buff, "Test") == 0, "PathMakePretty: 1st char lowercased %s\n", buff);
372 static void test_PathMatchSpec(void)
374 static const char file[] = "c:\\foo\\bar\\filename.ext";
375 static const char spec1[] = ".ext";
376 static const char spec2[] = "*.ext";
377 static const char spec3[] = "*.ext ";
378 static const char spec4[] = " *.ext";
379 static const char spec5[] = "* .ext";
380 static const char spec6[] = "*. ext";
381 static const char spec7[] = "* . ext";
382 static const char spec8[] = "*.e?t";
383 static const char spec9[] = "filename.ext";
384 static const char spec10[] = "*bar\\filename.ext";
385 static const char spec11[] = " foo; *.ext";
386 static const char spec12[] = "*.ext;*.bar";
387 static const char spec13[] = "*bar*";
389 ok (PathMatchSpecA(file, spec1) == FALSE, "PathMatchSpec: Spec1 failed\n");
390 ok (PathMatchSpecA(file, spec2) == TRUE, "PathMatchSpec: Spec2 failed\n");
391 ok (PathMatchSpecA(file, spec3) == FALSE, "PathMatchSpec: Spec3 failed\n");
392 ok (PathMatchSpecA(file, spec4) == TRUE, "PathMatchSpec: Spec4 failed\n");
393 todo_wine ok (PathMatchSpecA(file, spec5) == TRUE, "PathMatchSpec: Spec5 failed\n");
394 todo_wine ok (PathMatchSpecA(file, spec6) == TRUE, "PathMatchSpec: Spec6 failed\n");
395 ok (PathMatchSpecA(file, spec7) == FALSE, "PathMatchSpec: Spec7 failed\n");
396 ok (PathMatchSpecA(file, spec8) == TRUE, "PathMatchSpec: Spec8 failed\n");
397 ok (PathMatchSpecA(file, spec9) == FALSE, "PathMatchSpec: Spec9 failed\n");
398 ok (PathMatchSpecA(file, spec10) == TRUE, "PathMatchSpec: Spec10 failed\n");
399 ok (PathMatchSpecA(file, spec11) == TRUE, "PathMatchSpec: Spec11 failed\n");
400 ok (PathMatchSpecA(file, spec12) == TRUE, "PathMatchSpec: Spec12 failed\n");
401 ok (PathMatchSpecA(file, spec13) == TRUE, "PathMatchSpec: Spec13 failed\n");
404 static void test_PathCombineW(void)
406 LPWSTR wszString, wszString2;
407 WCHAR wbuf[MAX_PATH+1], wstr1[MAX_PATH] = {'C',':','\\',0}, wstr2[MAX_PATH];
408 static const WCHAR expout[] = {'C',':','\\','A','A',0};
409 int i;
411 if (!pPathCombineW)
413 win_skip("PathCombineW isn't available\n");
414 return;
417 wszString2 = HeapAlloc(GetProcessHeap(), 0, MAX_PATH * sizeof(WCHAR));
419 /* NULL test */
420 wszString = pPathCombineW(NULL, NULL, NULL);
421 ok (wszString == NULL, "Expected a NULL return\n");
423 /* Some NULL */
424 wszString2[0] = 'a';
425 wszString = pPathCombineW(wszString2, NULL, NULL);
426 ok (wszString == NULL ||
427 broken(wszString[0] == 'a'), /* Win95 and some W2K */
428 "Expected a NULL return\n");
429 ok (wszString2[0] == 0 ||
430 broken(wszString2[0] == 'a'), /* Win95 and some W2K */
431 "Destination string not empty\n");
433 HeapFree(GetProcessHeap(), 0, wszString2);
435 /* overflow test */
436 wstr2[0] = wstr2[1] = wstr2[2] = 'A';
437 for (i=3; i<MAX_PATH/2; i++)
438 wstr1[i] = wstr2[i] = 'A';
439 wstr1[(MAX_PATH/2) - 1] = wstr2[MAX_PATH/2] = 0;
440 memset(wbuf, 0xbf, sizeof(wbuf));
442 wszString = pPathCombineW(wbuf, wstr1, wstr2);
443 ok(wszString == NULL, "Expected a NULL return\n");
444 ok(wbuf[0] == 0 ||
445 broken(wbuf[0] == 0xbfbf), /* Win95 and some W2K */
446 "Buffer contains data\n");
448 /* PathCombineW can be used in place */
449 wstr1[3] = 0;
450 wstr2[2] = 0;
451 ok(PathCombineW(wstr1, wstr1, wstr2) == wstr1, "Expected a wstr1 return\n");
452 ok(StrCmpW(wstr1, expout) == 0, "Unexpected PathCombine output\n");
456 #define LONG_LEN (MAX_PATH * 2)
457 #define HALF_LEN (MAX_PATH / 2 + 1)
459 static void test_PathCombineA(void)
461 LPSTR str;
462 char dest[MAX_PATH];
463 char too_long[LONG_LEN];
464 char one[HALF_LEN], two[HALF_LEN];
466 /* try NULL dest */
467 SetLastError(0xdeadbeef);
468 str = PathCombineA(NULL, "C:\\", "one\\two\\three");
469 ok(str == NULL, "Expected NULL, got %p\n", str);
470 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
472 /* try NULL dest and NULL directory */
473 SetLastError(0xdeadbeef);
474 str = PathCombineA(NULL, NULL, "one\\two\\three");
475 ok(str == NULL, "Expected NULL, got %p\n", str);
476 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
478 /* try all NULL*/
479 SetLastError(0xdeadbeef);
480 str = PathCombineA(NULL, NULL, NULL);
481 ok(str == NULL, "Expected NULL, got %p\n", str);
482 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
484 /* try NULL file part */
485 SetLastError(0xdeadbeef);
486 lstrcpyA(dest, "control");
487 str = PathCombineA(dest, "C:\\", NULL);
488 ok(str == dest, "Expected str == dest, got %p\n", str);
489 ok(!lstrcmp(str, "C:\\"), "Expected C:\\, got %s\n", str);
490 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
492 /* try empty file part */
493 SetLastError(0xdeadbeef);
494 lstrcpyA(dest, "control");
495 str = PathCombineA(dest, "C:\\", "");
496 ok(str == dest, "Expected str == dest, got %p\n", str);
497 ok(!lstrcmp(str, "C:\\"), "Expected C:\\, got %s\n", str);
498 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
500 /* try empty directory and file part */
501 SetLastError(0xdeadbeef);
502 lstrcpyA(dest, "control");
503 str = PathCombineA(dest, "", "");
504 ok(str == dest, "Expected str == dest, got %p\n", str);
505 ok(!lstrcmp(str, "\\") ||
506 broken(!lstrcmp(str, "control")), /* Win95 and some W2K */
507 "Expected \\, got %s\n", str);
508 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
510 /* try NULL directory */
511 SetLastError(0xdeadbeef);
512 lstrcpyA(dest, "control");
513 str = PathCombineA(dest, NULL, "one\\two\\three");
514 ok(str == dest, "Expected str == dest, got %p\n", str);
515 ok(!lstrcmp(str, "one\\two\\three"), "Expected one\\two\\three, got %s\n", str);
516 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
518 /* try NULL directory and empty file part */
519 SetLastError(0xdeadbeef);
520 lstrcpyA(dest, "control");
521 str = PathCombineA(dest, NULL, "");
522 ok(str == dest, "Expected str == dest, got %p\n", str);
523 ok(!lstrcmp(str, "\\") ||
524 broken(!lstrcmp(str, "one\\two\\three")), /* Win95 and some W2K */
525 "Expected \\, got %s\n", str);
526 ok(GetLastError() == 0xdeadbeef ||
527 broken(GetLastError() == ERROR_INVALID_PARAMETER), /* Win95 */
528 "Expected 0xdeadbeef, got %d\n", GetLastError());
530 /* try NULL directory and file part */
531 SetLastError(0xdeadbeef);
532 lstrcpyA(dest, "control");
533 str = PathCombineA(dest, NULL, NULL);
534 ok(str == NULL ||
535 broken(str != NULL), /* Win95 and some W2K */
536 "Expected str == NULL, got %p\n", str);
537 ok(lstrlenA(dest) == 0 ||
538 broken(!lstrcmp(dest, "control")), /* Win95 and some W2K */
539 "Expected 0 length, got %i\n", lstrlenA(dest));
540 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
542 /* try directory without backslash */
543 SetLastError(0xdeadbeef);
544 lstrcpyA(dest, "control");
545 str = PathCombineA(dest, "C:", "one\\two\\three");
546 ok(str == dest, "Expected str == dest, got %p\n", str);
547 ok(!lstrcmp(str, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", str);
548 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
550 /* try directory with backslash */
551 SetLastError(0xdeadbeef);
552 lstrcpyA(dest, "control");
553 str = PathCombineA(dest, "C:\\", "one\\two\\three");
554 ok(str == dest, "Expected str == dest, got %p\n", str);
555 ok(!lstrcmp(str, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", str);
556 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
558 /* try directory with backslash and file with prepended backslash */
559 SetLastError(0xdeadbeef);
560 lstrcpyA(dest, "control");
561 str = PathCombineA(dest, "C:\\", "\\one\\two\\three");
562 ok(str == dest, "Expected str == dest, got %p\n", str);
563 ok(!lstrcmp(str, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", str);
564 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
566 /* try previous test, with backslash appended as well */
567 SetLastError(0xdeadbeef);
568 lstrcpyA(dest, "control");
569 str = PathCombineA(dest, "C:\\", "\\one\\two\\three\\");
570 ok(str == dest, "Expected str == dest, got %p\n", str);
571 ok(!lstrcmp(str, "C:\\one\\two\\three\\"), "Expected C:\\one\\two\\three\\, got %s\n", str);
572 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
574 /* try a relative directory */
575 SetLastError(0xdeadbeef);
576 lstrcpyA(dest, "control");
577 str = PathCombineA(dest, "relative\\dir", "\\one\\two\\three\\");
578 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
579 /* Vista fails which probably makes sense as PathCombineA expects an absolute dir */
580 if (str)
582 ok(str == dest, "Expected str == dest, got %p\n", str);
583 ok(!lstrcmp(str, "one\\two\\three\\"), "Expected one\\two\\three\\, got %s\n", str);
586 /* try forward slashes */
587 SetLastError(0xdeadbeef);
588 lstrcpyA(dest, "control");
589 str = PathCombineA(dest, "C:\\", "one/two/three\\");
590 ok(str == dest, "Expected str == dest, got %p\n", str);
591 ok(!lstrcmp(str, "C:\\one/two/three\\"), "Expected one/two/three\\, got %s\n", str);
592 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
594 /* try a really weird directory */
595 SetLastError(0xdeadbeef);
596 lstrcpyA(dest, "control");
597 str = PathCombineA(dest, "C:\\/\\/", "\\one\\two\\three\\");
598 ok(str == dest, "Expected str == dest, got %p\n", str);
599 ok(!lstrcmp(str, "C:\\one\\two\\three\\"), "Expected C:\\one\\two\\three\\, got %s\n", str);
600 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
602 /* try periods */
603 SetLastError(0xdeadbeef);
604 lstrcpyA(dest, "control");
605 str = PathCombineA(dest, "C:\\", "one\\..\\two\\.\\three");
606 ok(str == dest, "Expected str == dest, got %p\n", str);
607 ok(!lstrcmp(str, "C:\\two\\three"), "Expected C:\\two\\three, got %s\n", str);
608 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
610 /* try .. as file */
611 /* try forward slashes */
612 SetLastError(0xdeadbeef);
613 lstrcpyA(dest, "control");
614 str = PathCombineA(dest, "C:\\", "..");
615 ok(str == dest, "Expected str == dest, got %p\n", str);
616 ok(!lstrcmp(str, "C:\\"), "Expected C:\\, got %s\n", str);
617 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
619 memset(too_long, 'a', LONG_LEN);
620 too_long[LONG_LEN - 1] = '\0';
622 /* try a file longer than MAX_PATH */
623 SetLastError(0xdeadbeef);
624 lstrcpyA(dest, "control");
625 str = PathCombineA(dest, "C:\\", too_long);
626 ok(str == NULL, "Expected str == NULL, got %p\n", str);
627 ok(lstrlenA(dest) == 0 ||
628 broken(!lstrcmp(dest, "control")), /* Win95 and some W2K */
629 "Expected 0 length, got %i\n", lstrlenA(dest));
630 todo_wine ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
632 /* try a directory longer than MAX_PATH */
633 SetLastError(0xdeadbeef);
634 lstrcpyA(dest, "control");
635 str = PathCombineA(dest, too_long, "one\\two\\three");
636 ok(str == NULL, "Expected str == NULL, got %p\n", str);
637 ok(lstrlenA(dest) == 0 ||
638 broken(!lstrcmp(dest, "control")), /* Win95 and some W2K */
639 "Expected 0 length, got %i\n", lstrlenA(dest));
640 todo_wine ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
642 memset(one, 'b', HALF_LEN);
643 memset(two, 'c', HALF_LEN);
644 one[HALF_LEN - 1] = '\0';
645 two[HALF_LEN - 1] = '\0';
647 /* destination string is longer than MAX_PATH, but not the constituent parts */
648 SetLastError(0xdeadbeef);
649 lstrcpyA(dest, "control");
650 str = PathCombineA(dest, one, two);
651 ok(str == NULL, "Expected str == NULL, got %p\n", str);
652 ok(lstrlenA(dest) == 0 ||
653 broken(!lstrcmp(dest, "control")), /* Win95 and some W2K */
654 "Expected 0 length, got %i\n", lstrlenA(dest));
655 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
658 static void test_PathAddBackslash(void)
660 LPSTR str;
661 char path[MAX_PATH];
662 char too_long[LONG_LEN];
664 /* try a NULL path */
665 SetLastError(0xdeadbeef);
666 str = PathAddBackslashA(NULL);
667 ok(str == NULL, "Expected str == NULL, got %p\n", str);
668 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
670 /* try an empty path */
671 path[0] = '\0';
672 SetLastError(0xdeadbeef);
673 str = PathAddBackslashA(path);
674 ok(str == (path + lstrlenA(path)), "Expected str to point to end of path, got %p\n", str);
675 ok(lstrlenA(path) == 0, "Expected empty string, got %i\n", lstrlenA(path));
676 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
678 /* try a relative path */
679 lstrcpyA(path, "one\\two");
680 SetLastError(0xdeadbeef);
681 str = PathAddBackslashA(path);
682 ok(str == (path + lstrlenA(path)), "Expected str to point to end of path, got %p\n", str);
683 ok(!lstrcmp(path, "one\\two\\"), "Expected one\\two\\, got %s\n", path);
684 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
686 /* try periods */
687 lstrcpyA(path, "one\\..\\two");
688 SetLastError(0xdeadbeef);
689 str = PathAddBackslashA(path);
690 ok(str == (path + lstrlenA(path)), "Expected str to point to end of path, got %p\n", str);
691 ok(!lstrcmp(path, "one\\..\\two\\"), "Expected one\\..\\two\\, got %s\n", path);
692 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
694 /* try just a space */
695 lstrcpyA(path, " ");
696 SetLastError(0xdeadbeef);
697 str = PathAddBackslashA(path);
698 ok(str == (path + lstrlenA(path)), "Expected str to point to end of path, got %p\n", str);
699 ok(!lstrcmp(path, " \\"), "Expected \\, got %s\n", path);
700 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
702 /* path already has backslash */
703 lstrcpyA(path, "C:\\one\\");
704 SetLastError(0xdeadbeef);
705 str = PathAddBackslashA(path);
706 ok(str == (path + lstrlenA(path)), "Expected str to point to end of path, got %p\n", str);
707 ok(!lstrcmp(path, "C:\\one\\"), "Expected C:\\one\\, got %s\n", path);
708 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
710 memset(too_long, 'a', LONG_LEN);
711 too_long[LONG_LEN - 1] = '\0';
713 /* path is longer than MAX_PATH */
714 SetLastError(0xdeadbeef);
715 str = PathAddBackslashA(too_long);
716 ok(str == NULL, "Expected str == NULL, got %p\n", str);
717 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
720 static void test_PathAppendA(void)
722 char path[MAX_PATH];
723 char too_long[LONG_LEN];
724 char half[HALF_LEN];
725 BOOL res;
727 lstrcpy(path, "C:\\one");
729 /* try NULL pszMore */
730 SetLastError(0xdeadbeef);
731 res = PathAppendA(path, NULL);
732 ok(!res, "Expected failure\n");
733 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
734 ok(!lstrcmp(path, "C:\\one"), "Expected C:\\one, got %s\n", path);
736 /* try empty pszMore */
737 SetLastError(0xdeadbeef);
738 res = PathAppendA(path, "");
739 ok(res, "Expected success\n");
740 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
741 ok(!lstrcmp(path, "C:\\one"), "Expected C:\\one, got %s\n", path);
743 /* try NULL pszPath */
744 SetLastError(0xdeadbeef);
745 res = PathAppendA(NULL, "two\\three");
746 ok(!res, "Expected failure\n");
747 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
749 /* try empty pszPath */
750 path[0] = '\0';
751 SetLastError(0xdeadbeef);
752 res = PathAppendA(path, "two\\three");
753 ok(res, "Expected success\n");
754 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
755 ok(!lstrcmp(path, "two\\three"), "Expected \\two\\three, got %s\n", path);
757 /* try empty pszPath and empty pszMore */
758 path[0] = '\0';
759 SetLastError(0xdeadbeef);
760 res = PathAppendA(path, "");
761 ok(res, "Expected success\n");
762 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
763 ok(!lstrcmp(path, "\\"), "Expected \\, got %s\n", path);
765 /* try legit params */
766 lstrcpy(path, "C:\\one");
767 SetLastError(0xdeadbeef);
768 res = PathAppendA(path, "two\\three");
769 ok(res, "Expected success\n");
770 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
771 ok(!lstrcmp(path, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", path);
773 /* try pszPath with backslash after it */
774 lstrcpy(path, "C:\\one\\");
775 SetLastError(0xdeadbeef);
776 res = PathAppendA(path, "two\\three");
777 ok(res, "Expected success\n");
778 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
779 ok(!lstrcmp(path, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", path);
781 /* try pszMore with backslash before it */
782 lstrcpy(path, "C:\\one");
783 SetLastError(0xdeadbeef);
784 res = PathAppendA(path, "\\two\\three");
785 ok(res, "Expected success\n");
786 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
787 ok(!lstrcmp(path, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", path);
789 /* try pszMore with backslash after it */
790 lstrcpy(path, "C:\\one");
791 SetLastError(0xdeadbeef);
792 res = PathAppendA(path, "two\\three\\");
793 ok(res, "Expected success\n");
794 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
795 ok(!lstrcmp(path, "C:\\one\\two\\three\\"), "Expected C:\\one\\two\\three\\, got %s\n", path);
797 /* try spaces in pszPath */
798 lstrcpy(path, "C: \\ one ");
799 SetLastError(0xdeadbeef);
800 res = PathAppendA(path, "two\\three");
801 ok(res, "Expected success\n");
802 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
803 ok(!lstrcmp(path, "C: \\ one \\two\\three"), "Expected C: \\ one \\two\\three, got %s\n", path);
805 /* try spaces in pszMore */
806 lstrcpy(path, "C:\\one");
807 SetLastError(0xdeadbeef);
808 res = PathAppendA(path, " two \\ three ");
809 ok(res, "Expected success\n");
810 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
811 ok(!lstrcmp(path, "C:\\one\\ two \\ three "), "Expected 'C:\\one\\ two \\ three ', got %s\n", path);
813 /* pszPath is too long */
814 memset(too_long, 'a', LONG_LEN);
815 too_long[LONG_LEN - 1] = '\0';
816 SetLastError(0xdeadbeef);
817 res = PathAppendA(too_long, "two\\three");
818 ok(!res, "Expected failure\n");
819 todo_wine ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
820 ok(lstrlen(too_long) == 0 ||
821 broken(lstrlen(too_long) == (LONG_LEN - 1)), /* Win95 and some W2K */
822 "Expected length of too_long to be zero, got %i\n", lstrlen(too_long));
824 /* pszMore is too long */
825 lstrcpy(path, "C:\\one");
826 memset(too_long, 'a', LONG_LEN);
827 too_long[LONG_LEN - 1] = '\0';
828 SetLastError(0xdeadbeef);
829 res = PathAppendA(path, too_long);
830 ok(!res, "Expected failure\n");
831 todo_wine ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
832 ok(lstrlen(path) == 0 ||
833 broken(!lstrcmp(path, "C:\\one")), /* Win95 and some W2K */
834 "Expected length of path to be zero, got %i\n", lstrlen(path));
836 /* both params combined are too long */
837 memset(path, 'a', HALF_LEN);
838 path[HALF_LEN - 1] = '\0';
839 memset(half, 'b', HALF_LEN);
840 half[HALF_LEN - 1] = '\0';
841 SetLastError(0xdeadbeef);
842 res = PathAppendA(path, half);
843 ok(!res, "Expected failure\n");
844 ok(lstrlen(path) == 0 ||
845 broken(lstrlen(path) == (HALF_LEN - 1)), /* Win95 and some W2K */
846 "Expected length of path to be zero, got %i\n", lstrlen(path));
847 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
850 static void test_PathCanonicalizeA(void)
852 char dest[LONG_LEN + MAX_PATH];
853 char too_long[LONG_LEN];
854 BOOL res;
856 /* try a NULL source */
857 lstrcpy(dest, "test");
858 SetLastError(0xdeadbeef);
859 res = PathCanonicalizeA(dest, NULL);
860 ok(!res, "Expected failure\n");
861 ok(GetLastError() == ERROR_INVALID_PARAMETER,
862 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
863 ok(dest[0] == 0 || !lstrcmp(dest, "test"),
864 "Expected either an empty string (Vista) or test, got %s\n", dest);
866 /* try an empty source */
867 lstrcpy(dest, "test");
868 SetLastError(0xdeadbeef);
869 res = PathCanonicalizeA(dest, "");
870 ok(res, "Expected success\n");
871 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
872 ok(!lstrcmp(dest, "\\") ||
873 broken(!lstrcmp(dest, "test")), /* Win95 and some W2K */
874 "Expected \\, got %s\n", dest);
876 /* try a NULL dest */
877 SetLastError(0xdeadbeef);
878 res = PathCanonicalizeA(NULL, "C:\\");
879 ok(!res, "Expected failure\n");
880 ok(GetLastError() == ERROR_INVALID_PARAMETER,
881 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
883 /* try empty dest */
884 dest[0] = '\0';
885 SetLastError(0xdeadbeef);
886 res = PathCanonicalizeA(dest, "C:\\");
887 ok(res, "Expected success\n");
888 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
889 ok(!lstrcmp(dest, "C:\\"), "Expected C:\\, got %s\n", dest);
891 /* try non-empty dest */
892 lstrcpy(dest, "test");
893 SetLastError(0xdeadbeef);
894 res = PathCanonicalizeA(dest, "C:\\");
895 ok(res, "Expected success\n");
896 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
897 ok(!lstrcmp(dest, "C:\\"), "Expected C:\\, got %s\n", dest);
899 /* try a space for source */
900 lstrcpy(dest, "test");
901 SetLastError(0xdeadbeef);
902 res = PathCanonicalizeA(dest, " ");
903 ok(res, "Expected success\n");
904 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
905 ok(!lstrcmp(dest, " "), "Expected ' ', got %s\n", dest);
907 /* try a relative path */
908 lstrcpy(dest, "test");
909 SetLastError(0xdeadbeef);
910 res = PathCanonicalizeA(dest, "one\\two");
911 ok(res, "Expected success\n");
912 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
913 ok(!lstrcmp(dest, "one\\two"), "Expected one\\two, got %s\n", dest);
915 /* try current dir and previous dir */
916 lstrcpy(dest, "test");
917 SetLastError(0xdeadbeef);
918 res = PathCanonicalizeA(dest, "C:\\one\\.\\..\\two\\three\\..");
919 ok(res, "Expected success\n");
920 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
921 ok(!lstrcmp(dest, "C:\\two"), "Expected C:\\two, got %s\n", dest);
923 /* try simple forward slashes */
924 lstrcpy(dest, "test");
925 SetLastError(0xdeadbeef);
926 res = PathCanonicalizeA(dest, "C:\\one/two/three\\four/five\\six");
927 ok(res, "Expected success\n");
928 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
929 ok(!lstrcmp(dest, "C:\\one/two/three\\four/five\\six"),
930 "Expected C:\\one/two/three\\four/five\\six, got %s\n", dest);
932 /* try simple forward slashes with same dir */
933 lstrcpy(dest, "test");
934 SetLastError(0xdeadbeef);
935 res = PathCanonicalizeA(dest, "C:\\one/.\\two");
936 ok(res, "Expected success\n");
937 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
938 ok(!lstrcmp(dest, "C:\\one/.\\two"), "Expected C:\\one/.\\two, got %s\n", dest);
940 /* try simple forward slashes with change dir */
941 lstrcpy(dest, "test");
942 SetLastError(0xdeadbeef);
943 res = PathCanonicalizeA(dest, "C:\\one/.\\two\\..");
944 ok(res, "Expected success\n");
945 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
946 ok(!lstrcmp(dest, "C:\\one/.") ||
947 !lstrcmp(dest, "C:\\one/"), /* Vista */
948 "Expected \"C:\\one/.\" or \"C:\\one/\", got \"%s\"\n", dest);
950 /* try forward slashes with change dirs
951 * NOTE: if there is a forward slash in between two backslashes,
952 * everything in between the two backslashes is considered on dir
954 lstrcpy(dest, "test");
955 SetLastError(0xdeadbeef);
956 res = PathCanonicalizeA(dest, "C:\\one/.\\..\\two/three\\..\\four/.five");
957 ok(res, "Expected success\n");
958 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
959 ok(!lstrcmp(dest, "C:\\four/.five"), "Expected C:\\four/.five, got %s\n", dest);
961 /* try src is too long */
962 memset(too_long, 'a', LONG_LEN);
963 too_long[LONG_LEN - 1] = '\0';
964 lstrcpy(dest, "test");
965 SetLastError(0xdeadbeef);
966 res = PathCanonicalizeA(dest, too_long);
967 ok(!res ||
968 broken(res), /* Win95, some W2K and XP-SP1 */
969 "Expected failure\n");
970 todo_wine
972 ok(GetLastError() == 0xdeadbeef || GetLastError() == ERROR_FILENAME_EXCED_RANGE /* Vista */,
973 "Expected 0xdeadbeef or ERROR_FILENAME_EXCED_RANGE, got %d\n", GetLastError());
975 ok(lstrlen(too_long) == LONG_LEN - 1, "Expected length LONG_LEN - 1, got %i\n", lstrlen(too_long));
978 static void test_PathFindExtensionA(void)
980 LPSTR ext;
981 char path[MAX_PATH];
982 char too_long[LONG_LEN];
984 /* try a NULL path */
985 SetLastError(0xdeadbeef);
986 ext = PathFindExtensionA(NULL);
987 ok(ext == NULL, "Expected NULL, got %p\n", ext);
988 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
990 /* try an empty path */
991 path[0] = '\0';
992 SetLastError(0xdeadbeef);
993 ext = PathFindExtensionA(path);
994 ok(ext == path, "Expected ext == path, got %p\n", ext);
995 ok(lstrlen(ext) == 0, "Expected length 0, got %i\n", lstrlen(ext));
996 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
998 /* try a path without an extension */
999 lstrcpy(path, "file");
1000 SetLastError(0xdeadbeef);
1001 ext = PathFindExtensionA(path);
1002 ok(ext == path + lstrlen(path), "Expected ext == path, got %p\n", ext);
1003 ok(lstrlen(ext) == 0, "Expected length 0, got %i\n", lstrlen(ext));
1004 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1006 /* try a path with an extension */
1007 lstrcpy(path, "file.txt");
1008 SetLastError(0xdeadbeef);
1009 ext = PathFindExtensionA(path);
1010 ok(ext == path + lstrlen("file"),
1011 "Expected ext == path + lstrlen(\"file\"), got %p\n", ext);
1012 ok(!lstrcmp(ext, ".txt"), "Expected .txt, got %s\n", ext);
1013 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1015 /* try a path with two extensions */
1016 lstrcpy(path, "file.txt.doc");
1017 SetLastError(0xdeadbeef);
1018 ext = PathFindExtensionA(path);
1019 ok(ext == path + lstrlen("file.txt"),
1020 "Expected ext == path + lstrlen(\"file.txt\"), got %p\n", ext);
1021 ok(!lstrcmp(ext, ".doc"), "Expected .txt, got %s\n", ext);
1022 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1024 /* try a path longer than MAX_PATH without an extension*/
1025 memset(too_long, 'a', LONG_LEN);
1026 too_long[LONG_LEN - 1] = '\0';
1027 SetLastError(0xdeadbeef);
1028 ext = PathFindExtensionA(too_long);
1029 ok(ext == too_long + LONG_LEN - 1, "Expected ext == too_long + LONG_LEN - 1, got %p\n", ext);
1030 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1032 /* try a path longer than MAX_PATH with an extension*/
1033 memset(too_long, 'a', LONG_LEN);
1034 too_long[LONG_LEN - 1] = '\0';
1035 lstrcpy(too_long + 300, ".abcde");
1036 too_long[lstrlen(too_long)] = 'a';
1037 SetLastError(0xdeadbeef);
1038 ext = PathFindExtensionA(too_long);
1039 ok(ext == too_long + 300, "Expected ext == too_long + 300, got %p\n", ext);
1040 ok(lstrlen(ext) == LONG_LEN - 301, "Expected LONG_LEN - 301, got %i\n", lstrlen(ext));
1041 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1044 static void test_PathBuildRootA(void)
1046 LPSTR root;
1047 char path[10];
1048 char root_expected[26][4];
1049 char drive;
1050 int j;
1052 /* set up the expected paths */
1053 for (drive = 'A'; drive <= 'Z'; drive++)
1054 sprintf(root_expected[drive - 'A'], "%c:\\", drive);
1056 /* test the expected values */
1057 for (j = 0; j < 26; j++)
1059 SetLastError(0xdeadbeef);
1060 lstrcpy(path, "aaaaaaaaa");
1061 root = PathBuildRootA(path, j);
1062 ok(root == path, "Expected root == path, got %p\n", root);
1063 ok(!lstrcmp(root, root_expected[j]), "Expected %s, got %s\n", root_expected[j], root);
1064 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1067 /* test a negative drive number */
1068 SetLastError(0xdeadbeef);
1069 lstrcpy(path, "aaaaaaaaa");
1070 root = PathBuildRootA(path, -1);
1071 ok(root == path, "Expected root == path, got %p\n", root);
1072 ok(!lstrcmp(path, "aaaaaaaaa") ||
1073 lstrlenA(path) == 0, /* Vista */
1074 "Expected aaaaaaaaa or empty string, got %s\n", path);
1075 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1077 /* test a drive number greater than 25 */
1078 SetLastError(0xdeadbeef);
1079 lstrcpy(path, "aaaaaaaaa");
1080 root = PathBuildRootA(path, 26);
1081 ok(root == path, "Expected root == path, got %p\n", root);
1082 ok(!lstrcmp(path, "aaaaaaaaa") ||
1083 lstrlenA(path) == 0, /* Vista */
1084 "Expected aaaaaaaaa or empty string, got %s\n", path);
1085 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1087 /* length of path is less than 4 */
1088 SetLastError(0xdeadbeef);
1089 lstrcpy(path, "aa");
1090 root = PathBuildRootA(path, 0);
1091 ok(root == path, "Expected root == path, got %p\n", root);
1092 ok(!lstrcmp(path, "A:\\"), "Expected A:\\, got %s\n", path);
1093 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1095 /* path is NULL */
1096 SetLastError(0xdeadbeef);
1097 root = PathBuildRootA(NULL, 0);
1098 ok(root == NULL, "Expected root == NULL, got %p\n", root);
1099 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1102 static void test_PathCommonPrefixA(void)
1104 char path1[MAX_PATH], path2[MAX_PATH];
1105 char out[MAX_PATH];
1106 int count;
1108 /* test NULL path1 */
1109 SetLastError(0xdeadbeef);
1110 lstrcpy(path2, "C:\\");
1111 lstrcpy(out, "aaa");
1112 count = PathCommonPrefixA(NULL, path2, out);
1113 ok(count == 0, "Expected 0, got %i\n", count);
1114 todo_wine
1116 ok(!lstrcmp(out, "aaa"), "Expected aaa, got %s\n", out);
1118 ok(!lstrcmp(path2, "C:\\"), "Expected C:\\, got %s\n", path2);
1119 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1121 /* test NULL path2 */
1122 SetLastError(0xdeadbeef);
1123 lstrcpy(path1, "C:\\");
1124 lstrcpy(out, "aaa");
1125 count = PathCommonPrefixA(path1, NULL, out);
1126 ok(count == 0, "Expected 0, got %i\n", count);
1127 todo_wine
1129 ok(!lstrcmp(out, "aaa"), "Expected aaa, got %s\n", out);
1131 ok(!lstrcmp(path1, "C:\\"), "Expected C:\\, got %s\n", path1);
1132 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1134 /* test empty path1 */
1135 SetLastError(0xdeadbeef);
1136 path1[0] = '\0';
1137 lstrcpy(path2, "C:\\");
1138 lstrcpy(out, "aaa");
1139 count = PathCommonPrefixA(path1, path2, out);
1140 ok(count == 0, "Expected 0, got %i\n", count);
1141 ok(lstrlen(out) == 0, "Expected 0 length out, got %i\n", lstrlen(out));
1142 ok(lstrlen(path1) == 0, "Expected 0 length path1, got %i\n", lstrlen(path1));
1143 ok(!lstrcmp(path2, "C:\\"), "Expected C:\\, got %s\n", path2);
1144 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1146 /* test empty path1 */
1147 SetLastError(0xdeadbeef);
1148 path2[0] = '\0';
1149 lstrcpy(path1, "C:\\");
1150 lstrcpy(out, "aaa");
1151 count = PathCommonPrefixA(path1, path2, out);
1152 ok(count == 0, "Expected 0, got %i\n", count);
1153 ok(lstrlen(out) == 0, "Expected 0 length out, got %i\n", lstrlen(out));
1154 ok(lstrlen(path2) == 0, "Expected 0 length path2, got %i\n", lstrlen(path2));
1155 ok(!lstrcmp(path1, "C:\\"), "Expected C:\\, got %s\n", path1);
1156 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1158 /* paths are legit, out is NULL */
1159 SetLastError(0xdeadbeef);
1160 lstrcpy(path1, "C:\\");
1161 lstrcpy(path2, "C:\\");
1162 count = PathCommonPrefixA(path1, path2, NULL);
1163 ok(count == 3, "Expected 3, got %i\n", count);
1164 ok(!lstrcmp(path1, "C:\\"), "Expected C:\\, got %s\n", path1);
1165 ok(!lstrcmp(path2, "C:\\"), "Expected C:\\, got %s\n", path2);
1166 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1168 /* all parameters legit */
1169 SetLastError(0xdeadbeef);
1170 lstrcpy(path1, "C:\\");
1171 lstrcpy(path2, "C:\\");
1172 lstrcpy(out, "aaa");
1173 count = PathCommonPrefixA(path1, path2, out);
1174 ok(count == 3, "Expected 3, got %i\n", count);
1175 ok(!lstrcmp(path1, "C:\\"), "Expected C:\\, got %s\n", path1);
1176 ok(!lstrcmp(path2, "C:\\"), "Expected C:\\, got %s\n", path2);
1177 ok(!lstrcmp(out, "C:\\"), "Expected C:\\, got %s\n", out);
1178 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1180 /* path1 and path2 not the same, but common prefix */
1181 SetLastError(0xdeadbeef);
1182 lstrcpy(path1, "C:\\one\\two");
1183 lstrcpy(path2, "C:\\one\\three");
1184 lstrcpy(out, "aaa");
1185 count = PathCommonPrefixA(path1, path2, out);
1186 ok(count == 6, "Expected 6, got %i\n", count);
1187 ok(!lstrcmp(path1, "C:\\one\\two"), "Expected C:\\one\\two, got %s\n", path1);
1188 ok(!lstrcmp(path2, "C:\\one\\three"), "Expected C:\\one\\three, got %s\n", path2);
1189 ok(!lstrcmp(out, "C:\\one"), "Expected C:\\one, got %s\n", out);
1190 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1192 /* try . prefix */
1193 SetLastError(0xdeadbeef);
1194 lstrcpy(path1, "one\\.two");
1195 lstrcpy(path2, "one\\.three");
1196 lstrcpy(out, "aaa");
1197 count = PathCommonPrefixA(path1, path2, out);
1198 ok(count == 3, "Expected 3, got %i\n", count);
1199 ok(!lstrcmp(path1, "one\\.two"), "Expected one\\.two, got %s\n", path1);
1200 ok(!lstrcmp(path2, "one\\.three"), "Expected one\\.three, got %s\n", path2);
1201 ok(!lstrcmp(out, "one"), "Expected one, got %s\n", out);
1202 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1204 /* try .. prefix */
1205 SetLastError(0xdeadbeef);
1206 lstrcpy(path1, "one\\..two");
1207 lstrcpy(path2, "one\\..three");
1208 lstrcpy(out, "aaa");
1209 count = PathCommonPrefixA(path1, path2, out);
1210 ok(count == 3, "Expected 3, got %i\n", count);
1211 ok(!lstrcmp(path1, "one\\..two"), "Expected one\\..two, got %s\n", path1);
1212 ok(!lstrcmp(path2, "one\\..three"), "Expected one\\..three, got %s\n", path2);
1213 ok(!lstrcmp(out, "one"), "Expected one, got %s\n", out);
1214 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1216 /* try ... prefix */
1217 SetLastError(0xdeadbeef);
1218 lstrcpy(path1, "one\\...two");
1219 lstrcpy(path2, "one\\...three");
1220 lstrcpy(out, "aaa");
1221 count = PathCommonPrefixA(path1, path2, out);
1222 ok(count == 3, "Expected 3, got %i\n", count);
1223 ok(!lstrcmp(path1, "one\\...two"), "Expected one\\...two, got %s\n", path1);
1224 ok(!lstrcmp(path2, "one\\...three"), "Expected one\\...three, got %s\n", path2);
1225 ok(!lstrcmp(out, "one"), "Expected one, got %s\n", out);
1226 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1228 /* try .\ prefix */
1229 SetLastError(0xdeadbeef);
1230 lstrcpy(path1, "one\\.\\two");
1231 lstrcpy(path2, "one\\.\\three");
1232 lstrcpy(out, "aaa");
1233 count = PathCommonPrefixA(path1, path2, out);
1234 ok(count == 5, "Expected 5, got %i\n", count);
1235 ok(!lstrcmp(path1, "one\\.\\two"), "Expected one\\.\\two, got %s\n", path1);
1236 ok(!lstrcmp(path2, "one\\.\\three"), "Expected one\\.\\three, got %s\n", path2);
1237 ok(!lstrcmp(out, "one\\."), "Expected one\\., got %s\n", out);
1238 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1240 /* try ..\ prefix */
1241 SetLastError(0xdeadbeef);
1242 lstrcpy(path1, "one\\..\\two");
1243 lstrcpy(path2, "one\\..\\three");
1244 lstrcpy(out, "aaa");
1245 count = PathCommonPrefixA(path1, path2, out);
1246 ok(count == 6, "Expected 6, got %i\n", count);
1247 ok(!lstrcmp(path1, "one\\..\\two"), "Expected one\\..\\two, got %s\n", path1);
1248 ok(!lstrcmp(path2, "one\\..\\three"), "Expected one\\..\\three, got %s\n", path2);
1249 ok(!lstrcmp(out, "one\\.."), "Expected one\\.., got %s\n", out);
1250 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1252 /* try ...\\ prefix */
1253 SetLastError(0xdeadbeef);
1254 lstrcpy(path1, "one\\...\\two");
1255 lstrcpy(path2, "one\\...\\three");
1256 lstrcpy(out, "aaa");
1257 count = PathCommonPrefixA(path1, path2, out);
1258 ok(count == 7, "Expected 7, got %i\n", count);
1259 ok(!lstrcmp(path1, "one\\...\\two"), "Expected one\\...\\two, got %s\n", path1);
1260 ok(!lstrcmp(path2, "one\\...\\three"), "Expected one\\...\\three, got %s\n", path2);
1261 ok(!lstrcmp(out, "one\\..."), "Expected one\\..., got %s\n", out);
1262 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1264 /* try prefix that is not an msdn labeled prefix type */
1265 SetLastError(0xdeadbeef);
1266 lstrcpy(path1, "same");
1267 lstrcpy(path2, "same");
1268 lstrcpy(out, "aaa");
1269 count = PathCommonPrefixA(path1, path2, out);
1270 ok(count == 4, "Expected 4, got %i\n", count);
1271 ok(!lstrcmp(path1, "same"), "Expected same, got %s\n", path1);
1272 ok(!lstrcmp(path2, "same"), "Expected same, got %s\n", path2);
1273 ok(!lstrcmp(out, "same"), "Expected same, got %s\n", out);
1274 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1276 /* try . after directory */
1277 SetLastError(0xdeadbeef);
1278 lstrcpy(path1, "one\\mid.\\two");
1279 lstrcpy(path2, "one\\mid.\\three");
1280 lstrcpy(out, "aaa");
1281 count = PathCommonPrefixA(path1, path2, out);
1282 ok(count == 8, "Expected 8, got %i\n", count);
1283 ok(!lstrcmp(path1, "one\\mid.\\two"), "Expected one\\mid.\\two, got %s\n", path1);
1284 ok(!lstrcmp(path2, "one\\mid.\\three"), "Expected one\\mid.\\three, got %s\n", path2);
1285 ok(!lstrcmp(out, "one\\mid."), "Expected one\\mid., got %s\n", out);
1286 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1288 /* try . in the middle of a directory */
1289 SetLastError(0xdeadbeef);
1290 lstrcpy(path1, "one\\mid.end\\two");
1291 lstrcpy(path2, "one\\mid.end\\three");
1292 lstrcpy(out, "aaa");
1293 count = PathCommonPrefixA(path1, path2, out);
1294 ok(count == 11, "Expected 11, got %i\n", count);
1295 ok(!lstrcmp(path1, "one\\mid.end\\two"), "Expected one\\mid.end\\two, got %s\n", path1);
1296 ok(!lstrcmp(path2, "one\\mid.end\\three"), "Expected one\\mid.end\\three, got %s\n", path2);
1297 ok(!lstrcmp(out, "one\\mid.end"), "Expected one\\mid.end, got %s\n", out);
1298 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1300 /* try comparing a .. with the expanded path */
1301 SetLastError(0xdeadbeef);
1302 lstrcpy(path1, "one\\..\\two");
1303 lstrcpy(path2, "two");
1304 lstrcpy(out, "aaa");
1305 count = PathCommonPrefixA(path1, path2, out);
1306 ok(count == 0, "Expected 0, got %i\n", count);
1307 ok(!lstrcmp(path1, "one\\..\\two"), "Expected one\\..\\two, got %s\n", path1);
1308 ok(!lstrcmp(path2, "two"), "Expected two, got %s\n", path2);
1309 ok(lstrlen(out) == 0, "Expected 0 length out, got %i\n", lstrlen(out));
1310 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1313 static void test_PathUnquoteSpaces(void)
1315 int i;
1316 for(i = 0; i < sizeof(TEST_PATH_UNQUOTE_SPACES) / sizeof(TEST_PATH_UNQUOTE_SPACES[0]); i++)
1318 char *path = strdupA(TEST_PATH_UNQUOTE_SPACES[i].path);
1319 WCHAR *pathW = GetWideString(TEST_PATH_UNQUOTE_SPACES[i].path);
1320 WCHAR *resultW = GetWideString(TEST_PATH_UNQUOTE_SPACES[i].result);
1322 PathUnquoteSpacesA(path);
1323 ok(!strcmp(path, TEST_PATH_UNQUOTE_SPACES[i].result), "%s (A): got %s expected %s\n",
1324 TEST_PATH_UNQUOTE_SPACES[i].path, path,
1325 TEST_PATH_UNQUOTE_SPACES[i].result);
1327 PathUnquoteSpacesW(pathW);
1328 ok(!lstrcmpW(pathW, resultW), "%s (W): strings differ\n",
1329 TEST_PATH_UNQUOTE_SPACES[i].path);
1330 FreeWideString(pathW);
1331 FreeWideString(resultW);
1332 HeapFree(GetProcessHeap(), 0, path);
1336 static void test_PathGetDriveNumber(void)
1338 static const CHAR test1A[] = "a:\\test.file";
1339 static const CHAR test2A[] = "file:////b:\\test.file";
1340 static const CHAR test3A[] = "file:///c:\\test.file";
1341 static const CHAR test4A[] = "file:\\\\c:\\test.file";
1342 int ret;
1344 SetLastError(0xdeadbeef);
1345 ret = PathGetDriveNumberA(NULL);
1346 ok(ret == -1, "got %d\n", ret);
1347 ok(GetLastError() == 0xdeadbeef, "got %d\n", GetLastError());
1349 ret = PathGetDriveNumberA(test1A);
1350 ok(ret == 0, "got %d\n", ret);
1351 ret = PathGetDriveNumberA(test2A);
1352 ok(ret == -1, "got %d\n", ret);
1353 ret = PathGetDriveNumberA(test3A);
1354 ok(ret == -1, "got %d\n", ret);
1355 ret = PathGetDriveNumberA(test4A);
1356 ok(ret == -1, "got %d\n", ret);
1359 /* ################ */
1361 START_TEST(path)
1363 HMODULE hShlwapi = GetModuleHandleA("shlwapi.dll");
1365 /* SHCreateStreamOnFileEx was introduced in shlwapi v6.0 */
1366 if(!GetProcAddress(hShlwapi, "SHCreateStreamOnFileEx")){
1367 win_skip("Too old shlwapi version\n");
1368 return;
1371 pPathCreateFromUrlA = (void*)GetProcAddress(hShlwapi, "PathCreateFromUrlA");
1372 pPathCreateFromUrlW = (void*)GetProcAddress(hShlwapi, "PathCreateFromUrlW");
1373 pPathCombineW = (void*)GetProcAddress(hShlwapi, "PathCombineW");
1374 pPathIsValidCharA = (void*)GetProcAddress(hShlwapi, (LPSTR)455);
1375 pPathIsValidCharW = (void*)GetProcAddress(hShlwapi, (LPSTR)456);
1376 pPathAppendA = (void*)GetProcAddress(hShlwapi, "PathAppendA");
1378 test_PathSearchAndQualify();
1379 test_PathCreateFromUrl();
1380 test_PathIsUrl();
1382 test_PathAddBackslash();
1383 test_PathMakePretty();
1384 test_PathMatchSpec();
1386 test_PathIsValidCharA();
1387 test_PathIsValidCharW();
1389 test_PathCombineW();
1390 test_PathCombineA();
1391 test_PathAppendA();
1392 test_PathCanonicalizeA();
1393 test_PathFindExtensionA();
1394 test_PathBuildRootA();
1395 test_PathCommonPrefixA();
1396 test_PathUnquoteSpaces();
1397 test_PathGetDriveNumber();