[SHLWAPI_WINETEST]
[reactos.git] / rostests / winetests / shlwapi / path.c
1 /* Unit test suite for Path functions
2 *
3 * Copyright 2002 Matthew Mastracci
4 *
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.
9 *
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.
14 *
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
18 */
19
20 #include <assert.h>
21 #include <stdarg.h>
22 #include <stdio.h>
23
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"
30
31 static HMODULE hShlwapi;
32 static HRESULT (WINAPI *pPathIsValidCharA)(char,DWORD);
33 static HRESULT (WINAPI *pPathIsValidCharW)(WCHAR,DWORD);
34 static LPWSTR (WINAPI *pPathCombineW)(LPWSTR, LPCWSTR, LPCWSTR);
35 static HRESULT (WINAPI *pPathCreateFromUrlA)(LPCSTR, LPSTR, LPDWORD, DWORD);
36 static HRESULT (WINAPI *pPathCreateFromUrlW)(LPCWSTR, LPWSTR, LPDWORD, DWORD);
37
38 /* ################ */
39
40 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},*/
67
68 {"c:\\foo\\bar", NULL, E_INVALIDARG},
69 {"foo/bar", NULL, E_INVALIDARG},
70 {"http://foo/bar", NULL, E_INVALIDARG},
71
72 };
73
74
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}
107 };
108
109 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 { "\"", "" }
124 };
125
126 /* ################ */
127
128 static LPWSTR GetWideString(const char* szString)
129 {
130 LPWSTR wszString = HeapAlloc(GetProcessHeap(), 0, (2*INTERNET_MAX_URL_LENGTH) * sizeof(WCHAR));
131
132 MultiByteToWideChar(0, 0, szString, -1, wszString, INTERNET_MAX_URL_LENGTH);
133
134 return wszString;
135 }
136
137 static void FreeWideString(LPWSTR wszString)
138 {
139 HeapFree(GetProcessHeap(), 0, wszString);
140 }
141
142 static LPSTR strdupA(LPCSTR p)
143 {
144 LPSTR ret;
145 DWORD len = (strlen(p) + 1);
146 ret = HeapAlloc(GetProcessHeap(), 0, len);
147 memcpy(ret, p, len);
148 return ret;
149 }
150
151 /* ################ */
152
153 static void test_PathSearchAndQualify(void)
154 {
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};
165
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");
170
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");
178
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");
186
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");
193
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");
200
201 }
202
203 static void test_PathCreateFromUrl(void)
204 {
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";
211
212 if (!pPathCreateFromUrlA) {
213 win_skip("PathCreateFromUrlA not found\n");
214 return;
215 }
216
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);
221
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);
229 }
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);
241 }
242 FreeWideString(urlW);
243 FreeWideString(pathW);
244 }
245 }
246 }
247
248
249 static void test_PathIsUrl(void)
250 {
251 size_t i;
252 BOOL ret;
253
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);
259 }
260 }
261
262 static const DWORD SHELL_charclass[] =
263 {
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
296 };
297
298 static void test_PathIsValidCharA(void)
299 {
300 BOOL ret;
301 unsigned int c;
302
303 for (c = 0; c < 0x7f; c++)
304 {
305 ret = pPathIsValidCharA( c, ~0U );
306 ok ( ret || !SHELL_charclass[c], "PathIsValidCharA failed: 0x%02x got 0x%08x\n", c, ret );
307 }
308
309 for (c = 0x7f; c <= 0xff; c++)
310 {
311 ret = pPathIsValidCharA( c, ~0U );
312 ok ( ret, "PathIsValidCharA failed: 0x%02x got 0x%08x\n", c, ret );
313 }
314 }
315
316 static void test_PathIsValidCharW(void)
317 {
318 BOOL ret;
319 unsigned int c;
320
321 for (c = 0; c < 0x7f; c++)
322 {
323 ret = pPathIsValidCharW( c, ~0U );
324 ok ( ret || !SHELL_charclass[c], "PathIsValidCharW failed: 0x%02x got 0x%08x\n", c, ret );
325 }
326
327 for (c = 0x007f; c <= 0xffff; c++)
328 {
329 ret = pPathIsValidCharW( c, ~0U );
330 ok ( ret, "PathIsValidCharW failed: 0x%02x got 0x%08x\n", c, ret );
331 }
332 }
333
334 static void test_PathMakePretty(void)
335 {
336 char buff[MAX_PATH];
337
338 ok (PathMakePrettyA(NULL) == FALSE, "PathMakePretty: NULL path succeeded\n");
339 buff[0] = '\0';
340 ok (PathMakePrettyA(buff) == TRUE, "PathMakePretty: Empty path failed\n");
341
342 strcpy(buff, "C:\\A LONG FILE NAME WITH \\SPACES.TXT");
343 ok (PathMakePrettyA(buff) == TRUE, "PathMakePretty: Long UC name failed\n");
344 ok (strcmp(buff, "C:\\a long file name with \\spaces.txt") == 0,
345 "PathMakePretty: Long UC name not changed\n");
346
347 strcpy(buff, "C:\\A LONG FILE NAME WITH \\MixedCase.TXT");
348 ok (PathMakePrettyA(buff) == FALSE, "PathMakePretty: Long MC name succeeded\n");
349 ok (strcmp(buff, "C:\\A LONG FILE NAME WITH \\MixedCase.TXT") == 0,
350 "PathMakePretty: Failed but modified path\n");
351
352 strcpy(buff, "TEST");
353 ok (PathMakePrettyA(buff) == TRUE, "PathMakePretty: Short name failed\n");
354 ok (strcmp(buff, "Test") == 0, "PathMakePretty: 1st char lowercased %s\n", buff);
355 }
356
357 static void test_PathMatchSpec(void)
358 {
359 static const char file[] = "c:\\foo\\bar\\filename.ext";
360 static const char spec1[] = ".ext";
361 static const char spec2[] = "*.ext";
362 static const char spec3[] = "*.ext ";
363 static const char spec4[] = " *.ext";
364 static const char spec5[] = "* .ext";
365 static const char spec6[] = "*. ext";
366 static const char spec7[] = "* . ext";
367 static const char spec8[] = "*.e?t";
368 static const char spec9[] = "filename.ext";
369 static const char spec10[] = "*bar\\filename.ext";
370 static const char spec11[] = " foo; *.ext";
371 static const char spec12[] = "*.ext;*.bar";
372 static const char spec13[] = "*bar*";
373
374 ok (PathMatchSpecA(file, spec1) == FALSE, "PathMatchSpec: Spec1 failed\n");
375 ok (PathMatchSpecA(file, spec2) == TRUE, "PathMatchSpec: Spec2 failed\n");
376 ok (PathMatchSpecA(file, spec3) == FALSE, "PathMatchSpec: Spec3 failed\n");
377 ok (PathMatchSpecA(file, spec4) == TRUE, "PathMatchSpec: Spec4 failed\n");
378 todo_wine ok (PathMatchSpecA(file, spec5) == TRUE, "PathMatchSpec: Spec5 failed\n");
379 todo_wine ok (PathMatchSpecA(file, spec6) == TRUE, "PathMatchSpec: Spec6 failed\n");
380 ok (PathMatchSpecA(file, spec7) == FALSE, "PathMatchSpec: Spec7 failed\n");
381 ok (PathMatchSpecA(file, spec8) == TRUE, "PathMatchSpec: Spec8 failed\n");
382 ok (PathMatchSpecA(file, spec9) == FALSE, "PathMatchSpec: Spec9 failed\n");
383 ok (PathMatchSpecA(file, spec10) == TRUE, "PathMatchSpec: Spec10 failed\n");
384 ok (PathMatchSpecA(file, spec11) == TRUE, "PathMatchSpec: Spec11 failed\n");
385 ok (PathMatchSpecA(file, spec12) == TRUE, "PathMatchSpec: Spec12 failed\n");
386 ok (PathMatchSpecA(file, spec13) == TRUE, "PathMatchSpec: Spec13 failed\n");
387 }
388
389 static void test_PathCombineW(void)
390 {
391 LPWSTR wszString, wszString2;
392 WCHAR wbuf[MAX_PATH+1], wstr1[MAX_PATH] = {'C',':','\\',0}, wstr2[MAX_PATH];
393 static const WCHAR expout[] = {'C',':','\\','A','A',0};
394 int i;
395
396 wszString2 = HeapAlloc(GetProcessHeap(), 0, MAX_PATH * sizeof(WCHAR));
397
398 /* NULL test */
399 wszString = pPathCombineW(NULL, NULL, NULL);
400 ok (wszString == NULL, "Expected a NULL return\n");
401
402 /* Some NULL */
403 wszString2[0] = 'a';
404 wszString = pPathCombineW(wszString2, NULL, NULL);
405 ok (wszString == NULL ||
406 broken(wszString[0] == 'a'), /* Win95 and some W2K */
407 "Expected a NULL return\n");
408 ok (wszString2[0] == 0 ||
409 broken(wszString2[0] == 'a'), /* Win95 and some W2K */
410 "Destination string not empty\n");
411
412 HeapFree(GetProcessHeap(), 0, wszString2);
413
414 /* overflow test */
415 wstr2[0] = wstr2[1] = wstr2[2] = 'A';
416 for (i=3; i<MAX_PATH/2; i++)
417 wstr1[i] = wstr2[i] = 'A';
418 wstr1[(MAX_PATH/2) - 1] = wstr2[MAX_PATH/2] = 0;
419 memset(wbuf, 0xbf, sizeof(wbuf));
420
421 wszString = pPathCombineW(wbuf, wstr1, wstr2);
422 ok(wszString == NULL, "Expected a NULL return\n");
423 ok(wbuf[0] == 0 ||
424 broken(wbuf[0] == 0xbfbf), /* Win95 and some W2K */
425 "Buffer contains data\n");
426
427 /* PathCombineW can be used in place */
428 wstr1[3] = 0;
429 wstr2[2] = 0;
430 ok(PathCombineW(wstr1, wstr1, wstr2) == wstr1, "Expected a wstr1 return\n");
431 ok(StrCmpW(wstr1, expout) == 0, "Unexpected PathCombine output\n");
432 }
433
434
435 #define LONG_LEN (MAX_PATH * 2)
436 #define HALF_LEN (MAX_PATH / 2 + 1)
437
438 static void test_PathCombineA(void)
439 {
440 LPSTR str;
441 char dest[MAX_PATH];
442 char too_long[LONG_LEN];
443 char one[HALF_LEN], two[HALF_LEN];
444
445 /* try NULL dest */
446 SetLastError(0xdeadbeef);
447 str = PathCombineA(NULL, "C:\\", "one\\two\\three");
448 ok(str == NULL, "Expected NULL, got %p\n", str);
449 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
450
451 /* try NULL dest and NULL directory */
452 SetLastError(0xdeadbeef);
453 str = PathCombineA(NULL, NULL, "one\\two\\three");
454 ok(str == NULL, "Expected NULL, got %p\n", str);
455 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
456
457 /* try all NULL*/
458 SetLastError(0xdeadbeef);
459 str = PathCombineA(NULL, NULL, NULL);
460 ok(str == NULL, "Expected NULL, got %p\n", str);
461 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
462
463 /* try NULL file part */
464 SetLastError(0xdeadbeef);
465 lstrcpyA(dest, "control");
466 str = PathCombineA(dest, "C:\\", NULL);
467 ok(str == dest, "Expected str == dest, got %p\n", str);
468 ok(!lstrcmp(str, "C:\\"), "Expected C:\\, got %s\n", str);
469 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
470
471 /* try empty file part */
472 SetLastError(0xdeadbeef);
473 lstrcpyA(dest, "control");
474 str = PathCombineA(dest, "C:\\", "");
475 ok(str == dest, "Expected str == dest, got %p\n", str);
476 ok(!lstrcmp(str, "C:\\"), "Expected C:\\, got %s\n", str);
477 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
478
479 /* try empty directory and file part */
480 SetLastError(0xdeadbeef);
481 lstrcpyA(dest, "control");
482 str = PathCombineA(dest, "", "");
483 ok(str == dest, "Expected str == dest, got %p\n", str);
484 ok(!lstrcmp(str, "\\") ||
485 broken(!lstrcmp(str, "control")), /* Win95 and some W2K */
486 "Expected \\, got %s\n", str);
487 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
488
489 /* try NULL directory */
490 SetLastError(0xdeadbeef);
491 lstrcpyA(dest, "control");
492 str = PathCombineA(dest, NULL, "one\\two\\three");
493 ok(str == dest, "Expected str == dest, got %p\n", str);
494 ok(!lstrcmp(str, "one\\two\\three"), "Expected one\\two\\three, got %s\n", str);
495 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
496
497 /* try NULL directory and empty file part */
498 SetLastError(0xdeadbeef);
499 lstrcpyA(dest, "control");
500 str = PathCombineA(dest, NULL, "");
501 ok(str == dest, "Expected str == dest, got %p\n", str);
502 ok(!lstrcmp(str, "\\") ||
503 broken(!lstrcmp(str, "one\\two\\three")), /* Win95 and some W2K */
504 "Expected \\, got %s\n", str);
505 ok(GetLastError() == 0xdeadbeef ||
506 broken(GetLastError() == ERROR_INVALID_PARAMETER), /* Win95 */
507 "Expected 0xdeadbeef, got %d\n", GetLastError());
508
509 /* try NULL directory and file part */
510 SetLastError(0xdeadbeef);
511 lstrcpyA(dest, "control");
512 str = PathCombineA(dest, NULL, NULL);
513 ok(str == NULL ||
514 broken(str != NULL), /* Win95 and some W2K */
515 "Expected str == NULL, got %p\n", str);
516 ok(lstrlenA(dest) == 0 ||
517 broken(!lstrcmp(dest, "control")), /* Win95 and some W2K */
518 "Expected 0 length, got %i\n", lstrlenA(dest));
519 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
520
521 /* try directory without backslash */
522 SetLastError(0xdeadbeef);
523 lstrcpyA(dest, "control");
524 str = PathCombineA(dest, "C:", "one\\two\\three");
525 ok(str == dest, "Expected str == dest, got %p\n", str);
526 ok(!lstrcmp(str, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", str);
527 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
528
529 /* try directory with backslash */
530 SetLastError(0xdeadbeef);
531 lstrcpyA(dest, "control");
532 str = PathCombineA(dest, "C:\\", "one\\two\\three");
533 ok(str == dest, "Expected str == dest, got %p\n", str);
534 ok(!lstrcmp(str, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", str);
535 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
536
537 /* try directory with backslash and file with prepended backslash */
538 SetLastError(0xdeadbeef);
539 lstrcpyA(dest, "control");
540 str = PathCombineA(dest, "C:\\", "\\one\\two\\three");
541 ok(str == dest, "Expected str == dest, got %p\n", str);
542 ok(!lstrcmp(str, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", str);
543 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
544
545 /* try previous test, with backslash appended as well */
546 SetLastError(0xdeadbeef);
547 lstrcpyA(dest, "control");
548 str = PathCombineA(dest, "C:\\", "\\one\\two\\three\\");
549 ok(str == dest, "Expected str == dest, got %p\n", str);
550 ok(!lstrcmp(str, "C:\\one\\two\\three\\"), "Expected C:\\one\\two\\three\\, got %s\n", str);
551 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
552
553 /* try a relative directory */
554 SetLastError(0xdeadbeef);
555 lstrcpyA(dest, "control");
556 str = PathCombineA(dest, "relative\\dir", "\\one\\two\\three\\");
557 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
558 /* Vista fails which probably makes sense as PathCombineA expects an absolute dir */
559 if (str)
560 {
561 ok(str == dest, "Expected str == dest, got %p\n", str);
562 ok(!lstrcmp(str, "one\\two\\three\\"), "Expected one\\two\\three\\, got %s\n", str);
563 }
564
565 /* try forward slashes */
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 one/two/three\\, got %s\n", str);
571 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
572
573 /* try a really weird directory */
574 SetLastError(0xdeadbeef);
575 lstrcpyA(dest, "control");
576 str = PathCombineA(dest, "C:\\/\\/", "\\one\\two\\three\\");
577 ok(str == dest, "Expected str == dest, got %p\n", str);
578 ok(!lstrcmp(str, "C:\\one\\two\\three\\"), "Expected C:\\one\\two\\three\\, got %s\n", str);
579 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
580
581 /* try periods */
582 SetLastError(0xdeadbeef);
583 lstrcpyA(dest, "control");
584 str = PathCombineA(dest, "C:\\", "one\\..\\two\\.\\three");
585 ok(str == dest, "Expected str == dest, got %p\n", str);
586 ok(!lstrcmp(str, "C:\\two\\three"), "Expected C:\\two\\three, got %s\n", str);
587 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
588
589 /* try .. as file */
590 /* try forward slashes */
591 SetLastError(0xdeadbeef);
592 lstrcpyA(dest, "control");
593 str = PathCombineA(dest, "C:\\", "..");
594 ok(str == dest, "Expected str == dest, got %p\n", str);
595 ok(!lstrcmp(str, "C:\\"), "Expected C:\\, got %s\n", str);
596 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
597
598 memset(too_long, 'a', LONG_LEN);
599 too_long[LONG_LEN - 1] = '\0';
600
601 /* try a file longer than MAX_PATH */
602 SetLastError(0xdeadbeef);
603 lstrcpyA(dest, "control");
604 str = PathCombineA(dest, "C:\\", too_long);
605 ok(str == NULL, "Expected str == NULL, got %p\n", str);
606 ok(lstrlenA(dest) == 0 ||
607 broken(!lstrcmp(dest, "control")), /* Win95 and some W2K */
608 "Expected 0 length, got %i\n", lstrlenA(dest));
609 todo_wine ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
610
611 /* try a directory longer than MAX_PATH */
612 SetLastError(0xdeadbeef);
613 lstrcpyA(dest, "control");
614 str = PathCombineA(dest, too_long, "one\\two\\three");
615 ok(str == NULL, "Expected str == NULL, got %p\n", str);
616 ok(lstrlenA(dest) == 0 ||
617 broken(!lstrcmp(dest, "control")), /* Win95 and some W2K */
618 "Expected 0 length, got %i\n", lstrlenA(dest));
619 todo_wine ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
620
621 memset(one, 'b', HALF_LEN);
622 memset(two, 'c', HALF_LEN);
623 one[HALF_LEN - 1] = '\0';
624 two[HALF_LEN - 1] = '\0';
625
626 /* destination string is longer than MAX_PATH, but not the constituent parts */
627 SetLastError(0xdeadbeef);
628 lstrcpyA(dest, "control");
629 str = PathCombineA(dest, one, two);
630 ok(str == NULL, "Expected str == NULL, got %p\n", str);
631 ok(lstrlenA(dest) == 0 ||
632 broken(!lstrcmp(dest, "control")), /* Win95 and some W2K */
633 "Expected 0 length, got %i\n", lstrlenA(dest));
634 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
635 }
636
637 static void test_PathAddBackslash(void)
638 {
639 LPSTR str;
640 char path[MAX_PATH];
641 char too_long[LONG_LEN];
642
643 /* try a NULL path */
644 SetLastError(0xdeadbeef);
645 str = PathAddBackslashA(NULL);
646 ok(str == NULL, "Expected str == NULL, got %p\n", str);
647 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
648
649 /* try an empty path */
650 path[0] = '\0';
651 SetLastError(0xdeadbeef);
652 str = PathAddBackslashA(path);
653 ok(str == (path + lstrlenA(path)), "Expected str to point to end of path, got %p\n", str);
654 ok(lstrlenA(path) == 0, "Expected empty string, got %i\n", lstrlenA(path));
655 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
656
657 /* try a relative path */
658 lstrcpyA(path, "one\\two");
659 SetLastError(0xdeadbeef);
660 str = PathAddBackslashA(path);
661 ok(str == (path + lstrlenA(path)), "Expected str to point to end of path, got %p\n", str);
662 ok(!lstrcmp(path, "one\\two\\"), "Expected one\\two\\, got %s\n", path);
663 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
664
665 /* try periods */
666 lstrcpyA(path, "one\\..\\two");
667 SetLastError(0xdeadbeef);
668 str = PathAddBackslashA(path);
669 ok(str == (path + lstrlenA(path)), "Expected str to point to end of path, got %p\n", str);
670 ok(!lstrcmp(path, "one\\..\\two\\"), "Expected one\\..\\two\\, got %s\n", path);
671 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
672
673 /* try just a space */
674 lstrcpyA(path, " ");
675 SetLastError(0xdeadbeef);
676 str = PathAddBackslashA(path);
677 ok(str == (path + lstrlenA(path)), "Expected str to point to end of path, got %p\n", str);
678 ok(!lstrcmp(path, " \\"), "Expected \\, got %s\n", path);
679 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
680
681 /* path already has backslash */
682 lstrcpyA(path, "C:\\one\\");
683 SetLastError(0xdeadbeef);
684 str = PathAddBackslashA(path);
685 ok(str == (path + lstrlenA(path)), "Expected str to point to end of path, got %p\n", str);
686 ok(!lstrcmp(path, "C:\\one\\"), "Expected C:\\one\\, got %s\n", path);
687 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
688
689 memset(too_long, 'a', LONG_LEN);
690 too_long[LONG_LEN - 1] = '\0';
691
692 /* path is longer than MAX_PATH */
693 SetLastError(0xdeadbeef);
694 str = PathAddBackslashA(too_long);
695 ok(str == NULL, "Expected str == NULL, got %p\n", str);
696 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
697 }
698
699 static void test_PathAppendA(void)
700 {
701 char path[MAX_PATH];
702 char too_long[LONG_LEN];
703 char half[HALF_LEN];
704 BOOL res;
705
706 lstrcpy(path, "C:\\one");
707
708 /* try NULL pszMore */
709 SetLastError(0xdeadbeef);
710 res = PathAppendA(path, NULL);
711 ok(!res, "Expected failure\n");
712 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
713 ok(!lstrcmp(path, "C:\\one"), "Expected C:\\one, got %s\n", path);
714
715 /* try empty pszMore */
716 SetLastError(0xdeadbeef);
717 res = PathAppendA(path, "");
718 ok(res, "Expected success\n");
719 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
720 ok(!lstrcmp(path, "C:\\one"), "Expected C:\\one, got %s\n", path);
721
722 /* try NULL pszPath */
723 SetLastError(0xdeadbeef);
724 res = PathAppendA(NULL, "two\\three");
725 ok(!res, "Expected failure\n");
726 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
727
728 /* try empty pszPath */
729 path[0] = '\0';
730 SetLastError(0xdeadbeef);
731 res = PathAppendA(path, "two\\three");
732 ok(res, "Expected success\n");
733 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
734 ok(!lstrcmp(path, "two\\three"), "Expected \\two\\three, got %s\n", path);
735
736 /* try empty pszPath and empty pszMore */
737 path[0] = '\0';
738 SetLastError(0xdeadbeef);
739 res = PathAppendA(path, "");
740 ok(res, "Expected success\n");
741 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
742 ok(!lstrcmp(path, "\\"), "Expected \\, got %s\n", path);
743
744 /* try legit params */
745 lstrcpy(path, "C:\\one");
746 SetLastError(0xdeadbeef);
747 res = PathAppendA(path, "two\\three");
748 ok(res, "Expected success\n");
749 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
750 ok(!lstrcmp(path, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", path);
751
752 /* try pszPath with backslash after it */
753 lstrcpy(path, "C:\\one\\");
754 SetLastError(0xdeadbeef);
755 res = PathAppendA(path, "two\\three");
756 ok(res, "Expected success\n");
757 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
758 ok(!lstrcmp(path, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", path);
759
760 /* try pszMore with backslash before it */
761 lstrcpy(path, "C:\\one");
762 SetLastError(0xdeadbeef);
763 res = PathAppendA(path, "\\two\\three");
764 ok(res, "Expected success\n");
765 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
766 ok(!lstrcmp(path, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", path);
767
768 /* try pszMore with backslash after it */
769 lstrcpy(path, "C:\\one");
770 SetLastError(0xdeadbeef);
771 res = PathAppendA(path, "two\\three\\");
772 ok(res, "Expected success\n");
773 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
774 ok(!lstrcmp(path, "C:\\one\\two\\three\\"), "Expected C:\\one\\two\\three\\, got %s\n", path);
775
776 /* try spaces in pszPath */
777 lstrcpy(path, "C: \\ one ");
778 SetLastError(0xdeadbeef);
779 res = PathAppendA(path, "two\\three");
780 ok(res, "Expected success\n");
781 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
782 ok(!lstrcmp(path, "C: \\ one \\two\\three"), "Expected C: \\ one \\two\\three, got %s\n", path);
783
784 /* try spaces in pszMore */
785 lstrcpy(path, "C:\\one");
786 SetLastError(0xdeadbeef);
787 res = PathAppendA(path, " two \\ three ");
788 ok(res, "Expected success\n");
789 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
790 ok(!lstrcmp(path, "C:\\one\\ two \\ three "), "Expected 'C:\\one\\ two \\ three ', got %s\n", path);
791
792 /* pszPath is too long */
793 memset(too_long, 'a', LONG_LEN);
794 too_long[LONG_LEN - 1] = '\0';
795 SetLastError(0xdeadbeef);
796 res = PathAppendA(too_long, "two\\three");
797 ok(!res, "Expected failure\n");
798 todo_wine ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
799 ok(lstrlen(too_long) == 0 ||
800 broken(lstrlen(too_long) == (LONG_LEN - 1)), /* Win95 and some W2K */
801 "Expected length of too_long to be zero, got %i\n", lstrlen(too_long));
802
803 /* pszMore is too long */
804 lstrcpy(path, "C:\\one");
805 memset(too_long, 'a', LONG_LEN);
806 too_long[LONG_LEN - 1] = '\0';
807 SetLastError(0xdeadbeef);
808 res = PathAppendA(path, too_long);
809 ok(!res, "Expected failure\n");
810 todo_wine ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
811 ok(lstrlen(path) == 0 ||
812 broken(!lstrcmp(path, "C:\\one")), /* Win95 and some W2K */
813 "Expected length of path to be zero, got %i\n", lstrlen(path));
814
815 /* both params combined are too long */
816 memset(path, 'a', HALF_LEN);
817 path[HALF_LEN - 1] = '\0';
818 memset(half, 'b', HALF_LEN);
819 half[HALF_LEN - 1] = '\0';
820 SetLastError(0xdeadbeef);
821 res = PathAppendA(path, half);
822 ok(!res, "Expected failure\n");
823 ok(lstrlen(path) == 0 ||
824 broken(lstrlen(path) == (HALF_LEN - 1)), /* Win95 and some W2K */
825 "Expected length of path to be zero, got %i\n", lstrlen(path));
826 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
827 }
828
829 static void test_PathCanonicalizeA(void)
830 {
831 char dest[LONG_LEN + MAX_PATH];
832 char too_long[LONG_LEN];
833 BOOL res;
834
835 /* try a NULL source */
836 lstrcpy(dest, "test");
837 SetLastError(0xdeadbeef);
838 res = PathCanonicalizeA(dest, NULL);
839 ok(!res, "Expected failure\n");
840 ok(GetLastError() == ERROR_INVALID_PARAMETER,
841 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
842 ok(dest[0] == 0 || !lstrcmp(dest, "test"),
843 "Expected either an empty string (Vista) or test, got %s\n", dest);
844
845 /* try an empty source */
846 lstrcpy(dest, "test");
847 SetLastError(0xdeadbeef);
848 res = PathCanonicalizeA(dest, "");
849 ok(res, "Expected success\n");
850 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
851 ok(!lstrcmp(dest, "\\") ||
852 broken(!lstrcmp(dest, "test")), /* Win95 and some W2K */
853 "Expected \\, got %s\n", dest);
854
855 /* try a NULL dest */
856 SetLastError(0xdeadbeef);
857 res = PathCanonicalizeA(NULL, "C:\\");
858 ok(!res, "Expected failure\n");
859 ok(GetLastError() == ERROR_INVALID_PARAMETER,
860 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
861
862 /* try empty dest */
863 dest[0] = '\0';
864 SetLastError(0xdeadbeef);
865 res = PathCanonicalizeA(dest, "C:\\");
866 ok(res, "Expected success\n");
867 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
868 ok(!lstrcmp(dest, "C:\\"), "Expected C:\\, got %s\n", dest);
869
870 /* try non-empty dest */
871 lstrcpy(dest, "test");
872 SetLastError(0xdeadbeef);
873 res = PathCanonicalizeA(dest, "C:\\");
874 ok(res, "Expected success\n");
875 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
876 ok(!lstrcmp(dest, "C:\\"), "Expected C:\\, got %s\n", dest);
877
878 /* try a space for source */
879 lstrcpy(dest, "test");
880 SetLastError(0xdeadbeef);
881 res = PathCanonicalizeA(dest, " ");
882 ok(res, "Expected success\n");
883 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
884 ok(!lstrcmp(dest, " "), "Expected ' ', got %s\n", dest);
885
886 /* try a relative path */
887 lstrcpy(dest, "test");
888 SetLastError(0xdeadbeef);
889 res = PathCanonicalizeA(dest, "one\\two");
890 ok(res, "Expected success\n");
891 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
892 ok(!lstrcmp(dest, "one\\two"), "Expected one\\two, got %s\n", dest);
893
894 /* try current dir and previous dir */
895 lstrcpy(dest, "test");
896 SetLastError(0xdeadbeef);
897 res = PathCanonicalizeA(dest, "C:\\one\\.\\..\\two\\three\\..");
898 ok(res, "Expected success\n");
899 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
900 ok(!lstrcmp(dest, "C:\\two"), "Expected C:\\two, got %s\n", dest);
901
902 /* try simple forward slashes */
903 lstrcpy(dest, "test");
904 SetLastError(0xdeadbeef);
905 res = PathCanonicalizeA(dest, "C:\\one/two/three\\four/five\\six");
906 ok(res, "Expected success\n");
907 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
908 ok(!lstrcmp(dest, "C:\\one/two/three\\four/five\\six"),
909 "Expected C:\\one/two/three\\four/five\\six, got %s\n", dest);
910
911 /* try simple forward slashes with same dir */
912 lstrcpy(dest, "test");
913 SetLastError(0xdeadbeef);
914 res = PathCanonicalizeA(dest, "C:\\one/.\\two");
915 ok(res, "Expected success\n");
916 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
917 ok(!lstrcmp(dest, "C:\\one/.\\two"), "Expected C:\\one/.\\two, got %s\n", dest);
918
919 /* try simple forward slashes with change dir */
920 lstrcpy(dest, "test");
921 SetLastError(0xdeadbeef);
922 res = PathCanonicalizeA(dest, "C:\\one/.\\two\\..");
923 ok(res, "Expected success\n");
924 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
925 ok(!lstrcmp(dest, "C:\\one/.") ||
926 !lstrcmp(dest, "C:\\one/"), /* Vista */
927 "Expected \"C:\\one/.\" or \"C:\\one/\", got \"%s\"\n", dest);
928
929 /* try forward slashes with change dirs
930 * NOTE: if there is a forward slash in between two backslashes,
931 * everything in between the two backslashes is considered on dir
932 */
933 lstrcpy(dest, "test");
934 SetLastError(0xdeadbeef);
935 res = PathCanonicalizeA(dest, "C:\\one/.\\..\\two/three\\..\\four/.five");
936 ok(res, "Expected success\n");
937 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
938 ok(!lstrcmp(dest, "C:\\four/.five"), "Expected C:\\four/.five, got %s\n", dest);
939
940 /* try src is too long */
941 memset(too_long, 'a', LONG_LEN);
942 too_long[LONG_LEN - 1] = '\0';
943 lstrcpy(dest, "test");
944 SetLastError(0xdeadbeef);
945 res = PathCanonicalizeA(dest, too_long);
946 ok(!res ||
947 broken(res), /* Win95, some W2K and XP-SP1 */
948 "Expected failure\n");
949 todo_wine
950 {
951 ok(GetLastError() == 0xdeadbeef || GetLastError() == ERROR_FILENAME_EXCED_RANGE /* Vista */,
952 "Expected 0xdeadbeef or ERROR_FILENAME_EXCED_RANGE, got %d\n", GetLastError());
953 }
954 ok(lstrlen(too_long) == LONG_LEN - 1, "Expected length LONG_LEN - 1, got %i\n", lstrlen(too_long));
955 }
956
957 static void test_PathFindExtensionA(void)
958 {
959 LPSTR ext;
960 char path[MAX_PATH];
961 char too_long[LONG_LEN];
962
963 /* try a NULL path */
964 SetLastError(0xdeadbeef);
965 ext = PathFindExtensionA(NULL);
966 ok(ext == NULL, "Expected NULL, got %p\n", ext);
967 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
968
969 /* try an empty path */
970 path[0] = '\0';
971 SetLastError(0xdeadbeef);
972 ext = PathFindExtensionA(path);
973 ok(ext == path, "Expected ext == path, got %p\n", ext);
974 ok(lstrlen(ext) == 0, "Expected length 0, got %i\n", lstrlen(ext));
975 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
976
977 /* try a path without an extension */
978 lstrcpy(path, "file");
979 SetLastError(0xdeadbeef);
980 ext = PathFindExtensionA(path);
981 ok(ext == path + lstrlen(path), "Expected ext == path, got %p\n", ext);
982 ok(lstrlen(ext) == 0, "Expected length 0, got %i\n", lstrlen(ext));
983 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
984
985 /* try a path with an extension */
986 lstrcpy(path, "file.txt");
987 SetLastError(0xdeadbeef);
988 ext = PathFindExtensionA(path);
989 ok(ext == path + lstrlen("file"),
990 "Expected ext == path + lstrlen(\"file\"), got %p\n", ext);
991 ok(!lstrcmp(ext, ".txt"), "Expected .txt, got %s\n", ext);
992 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
993
994 /* try a path with two extensions */
995 lstrcpy(path, "file.txt.doc");
996 SetLastError(0xdeadbeef);
997 ext = PathFindExtensionA(path);
998 ok(ext == path + lstrlen("file.txt"),
999 "Expected ext == path + lstrlen(\"file.txt\"), got %p\n", ext);
1000 ok(!lstrcmp(ext, ".doc"), "Expected .txt, got %s\n", ext);
1001 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1002
1003 /* try a path longer than MAX_PATH without an extension*/
1004 memset(too_long, 'a', LONG_LEN);
1005 too_long[LONG_LEN - 1] = '\0';
1006 SetLastError(0xdeadbeef);
1007 ext = PathFindExtensionA(too_long);
1008 ok(ext == too_long + LONG_LEN - 1, "Expected ext == too_long + LONG_LEN - 1, got %p\n", ext);
1009 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1010
1011 /* try a path longer than MAX_PATH with an extension*/
1012 memset(too_long, 'a', LONG_LEN);
1013 too_long[LONG_LEN - 1] = '\0';
1014 lstrcpy(too_long + 300, ".abcde");
1015 too_long[lstrlen(too_long)] = 'a';
1016 SetLastError(0xdeadbeef);
1017 ext = PathFindExtensionA(too_long);
1018 ok(ext == too_long + 300, "Expected ext == too_long + 300, got %p\n", ext);
1019 ok(lstrlen(ext) == LONG_LEN - 301, "Expected LONG_LEN - 301, got %i\n", lstrlen(ext));
1020 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1021 }
1022
1023 static void test_PathBuildRootA(void)
1024 {
1025 LPSTR root;
1026 char path[10];
1027 char root_expected[26][4];
1028 char drive;
1029 int j;
1030
1031 /* set up the expected paths */
1032 for (drive = 'A'; drive <= 'Z'; drive++)
1033 sprintf(root_expected[drive - 'A'], "%c:\\", drive);
1034
1035 /* test the expected values */
1036 for (j = 0; j < 26; j++)
1037 {
1038 SetLastError(0xdeadbeef);
1039 lstrcpy(path, "aaaaaaaaa");
1040 root = PathBuildRootA(path, j);
1041 ok(root == path, "Expected root == path, got %p\n", root);
1042 ok(!lstrcmp(root, root_expected[j]), "Expected %s, got %s\n", root_expected[j], root);
1043 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1044 }
1045
1046 /* test a negative drive number */
1047 SetLastError(0xdeadbeef);
1048 lstrcpy(path, "aaaaaaaaa");
1049 root = PathBuildRootA(path, -1);
1050 ok(root == path, "Expected root == path, got %p\n", root);
1051 ok(!lstrcmp(path, "aaaaaaaaa") ||
1052 lstrlenA(path) == 0, /* Vista */
1053 "Expected aaaaaaaaa or empty string, got %s\n", path);
1054 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1055
1056 /* test a drive number greater than 25 */
1057 SetLastError(0xdeadbeef);
1058 lstrcpy(path, "aaaaaaaaa");
1059 root = PathBuildRootA(path, 26);
1060 ok(root == path, "Expected root == path, got %p\n", root);
1061 ok(!lstrcmp(path, "aaaaaaaaa") ||
1062 lstrlenA(path) == 0, /* Vista */
1063 "Expected aaaaaaaaa or empty string, got %s\n", path);
1064 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1065
1066 /* length of path is less than 4 */
1067 SetLastError(0xdeadbeef);
1068 lstrcpy(path, "aa");
1069 root = PathBuildRootA(path, 0);
1070 ok(root == path, "Expected root == path, got %p\n", root);
1071 ok(!lstrcmp(path, "A:\\"), "Expected A:\\, got %s\n", path);
1072 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1073
1074 /* path is NULL */
1075 SetLastError(0xdeadbeef);
1076 root = PathBuildRootA(NULL, 0);
1077 ok(root == NULL, "Expected root == NULL, got %p\n", root);
1078 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1079 }
1080
1081 static void test_PathCommonPrefixA(void)
1082 {
1083 char path1[MAX_PATH], path2[MAX_PATH];
1084 char out[MAX_PATH];
1085 int count;
1086
1087 /* test NULL path1 */
1088 SetLastError(0xdeadbeef);
1089 lstrcpy(path2, "C:\\");
1090 lstrcpy(out, "aaa");
1091 count = PathCommonPrefixA(NULL, path2, out);
1092 ok(count == 0, "Expected 0, got %i\n", count);
1093 todo_wine
1094 {
1095 ok(!lstrcmp(out, "aaa"), "Expected aaa, got %s\n", out);
1096 }
1097 ok(!lstrcmp(path2, "C:\\"), "Expected C:\\, got %s\n", path2);
1098 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1099
1100 /* test NULL path2 */
1101 SetLastError(0xdeadbeef);
1102 lstrcpy(path1, "C:\\");
1103 lstrcpy(out, "aaa");
1104 count = PathCommonPrefixA(path1, NULL, out);
1105 ok(count == 0, "Expected 0, got %i\n", count);
1106 todo_wine
1107 {
1108 ok(!lstrcmp(out, "aaa"), "Expected aaa, got %s\n", out);
1109 }
1110 ok(!lstrcmp(path1, "C:\\"), "Expected C:\\, got %s\n", path1);
1111 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1112
1113 /* test empty path1 */
1114 SetLastError(0xdeadbeef);
1115 path1[0] = '\0';
1116 lstrcpy(path2, "C:\\");
1117 lstrcpy(out, "aaa");
1118 count = PathCommonPrefixA(path1, path2, out);
1119 ok(count == 0, "Expected 0, got %i\n", count);
1120 ok(lstrlen(out) == 0, "Expected 0 length out, got %i\n", lstrlen(out));
1121 ok(lstrlen(path1) == 0, "Expected 0 length path1, got %i\n", lstrlen(path1));
1122 ok(!lstrcmp(path2, "C:\\"), "Expected C:\\, got %s\n", path2);
1123 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1124
1125 /* test empty path1 */
1126 SetLastError(0xdeadbeef);
1127 path2[0] = '\0';
1128 lstrcpy(path1, "C:\\");
1129 lstrcpy(out, "aaa");
1130 count = PathCommonPrefixA(path1, path2, out);
1131 ok(count == 0, "Expected 0, got %i\n", count);
1132 ok(lstrlen(out) == 0, "Expected 0 length out, got %i\n", lstrlen(out));
1133 ok(lstrlen(path2) == 0, "Expected 0 length path2, got %i\n", lstrlen(path2));
1134 ok(!lstrcmp(path1, "C:\\"), "Expected C:\\, got %s\n", path1);
1135 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1136
1137 /* paths are legit, out is NULL */
1138 SetLastError(0xdeadbeef);
1139 lstrcpy(path1, "C:\\");
1140 lstrcpy(path2, "C:\\");
1141 count = PathCommonPrefixA(path1, path2, NULL);
1142 ok(count == 3, "Expected 3, got %i\n", count);
1143 ok(!lstrcmp(path1, "C:\\"), "Expected C:\\, got %s\n", path1);
1144 ok(!lstrcmp(path2, "C:\\"), "Expected C:\\, got %s\n", path2);
1145 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1146
1147 /* all parameters legit */
1148 SetLastError(0xdeadbeef);
1149 lstrcpy(path1, "C:\\");
1150 lstrcpy(path2, "C:\\");
1151 lstrcpy(out, "aaa");
1152 count = PathCommonPrefixA(path1, path2, out);
1153 ok(count == 3, "Expected 3, got %i\n", count);
1154 ok(!lstrcmp(path1, "C:\\"), "Expected C:\\, got %s\n", path1);
1155 ok(!lstrcmp(path2, "C:\\"), "Expected C:\\, got %s\n", path2);
1156 ok(!lstrcmp(out, "C:\\"), "Expected C:\\, got %s\n", out);
1157 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1158
1159 /* path1 and path2 not the same, but common prefix */
1160 SetLastError(0xdeadbeef);
1161 lstrcpy(path1, "C:\\one\\two");
1162 lstrcpy(path2, "C:\\one\\three");
1163 lstrcpy(out, "aaa");
1164 count = PathCommonPrefixA(path1, path2, out);
1165 ok(count == 6, "Expected 6, got %i\n", count);
1166 ok(!lstrcmp(path1, "C:\\one\\two"), "Expected C:\\one\\two, got %s\n", path1);
1167 ok(!lstrcmp(path2, "C:\\one\\three"), "Expected C:\\one\\three, got %s\n", path2);
1168 ok(!lstrcmp(out, "C:\\one"), "Expected C:\\one, got %s\n", out);
1169 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1170
1171 /* try . prefix */
1172 SetLastError(0xdeadbeef);
1173 lstrcpy(path1, "one\\.two");
1174 lstrcpy(path2, "one\\.three");
1175 lstrcpy(out, "aaa");
1176 count = PathCommonPrefixA(path1, path2, out);
1177 ok(count == 3, "Expected 3, got %i\n", count);
1178 ok(!lstrcmp(path1, "one\\.two"), "Expected one\\.two, got %s\n", path1);
1179 ok(!lstrcmp(path2, "one\\.three"), "Expected one\\.three, got %s\n", path2);
1180 ok(!lstrcmp(out, "one"), "Expected one, got %s\n", out);
1181 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1182
1183 /* try .. prefix */
1184 SetLastError(0xdeadbeef);
1185 lstrcpy(path1, "one\\..two");
1186 lstrcpy(path2, "one\\..three");
1187 lstrcpy(out, "aaa");
1188 count = PathCommonPrefixA(path1, path2, out);
1189 ok(count == 3, "Expected 3, got %i\n", count);
1190 ok(!lstrcmp(path1, "one\\..two"), "Expected one\\..two, got %s\n", path1);
1191 ok(!lstrcmp(path2, "one\\..three"), "Expected one\\..three, got %s\n", path2);
1192 ok(!lstrcmp(out, "one"), "Expected one, got %s\n", out);
1193 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1194
1195 /* try ... prefix */
1196 SetLastError(0xdeadbeef);
1197 lstrcpy(path1, "one\\...two");
1198 lstrcpy(path2, "one\\...three");
1199 lstrcpy(out, "aaa");
1200 count = PathCommonPrefixA(path1, path2, out);
1201 ok(count == 3, "Expected 3, got %i\n", count);
1202 ok(!lstrcmp(path1, "one\\...two"), "Expected one\\...two, got %s\n", path1);
1203 ok(!lstrcmp(path2, "one\\...three"), "Expected one\\...three, got %s\n", path2);
1204 ok(!lstrcmp(out, "one"), "Expected one, got %s\n", out);
1205 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1206
1207 /* try .\ prefix */
1208 SetLastError(0xdeadbeef);
1209 lstrcpy(path1, "one\\.\\two");
1210 lstrcpy(path2, "one\\.\\three");
1211 lstrcpy(out, "aaa");
1212 count = PathCommonPrefixA(path1, path2, out);
1213 ok(count == 5, "Expected 5, got %i\n", count);
1214 ok(!lstrcmp(path1, "one\\.\\two"), "Expected one\\.\\two, got %s\n", path1);
1215 ok(!lstrcmp(path2, "one\\.\\three"), "Expected one\\.\\three, got %s\n", path2);
1216 ok(!lstrcmp(out, "one\\."), "Expected one\\., got %s\n", out);
1217 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1218
1219 /* try ..\ prefix */
1220 SetLastError(0xdeadbeef);
1221 lstrcpy(path1, "one\\..\\two");
1222 lstrcpy(path2, "one\\..\\three");
1223 lstrcpy(out, "aaa");
1224 count = PathCommonPrefixA(path1, path2, out);
1225 ok(count == 6, "Expected 6, got %i\n", count);
1226 ok(!lstrcmp(path1, "one\\..\\two"), "Expected one\\..\\two, got %s\n", path1);
1227 ok(!lstrcmp(path2, "one\\..\\three"), "Expected one\\..\\three, got %s\n", path2);
1228 ok(!lstrcmp(out, "one\\.."), "Expected one\\.., got %s\n", out);
1229 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1230
1231 /* try ...\\ prefix */
1232 SetLastError(0xdeadbeef);
1233 lstrcpy(path1, "one\\...\\two");
1234 lstrcpy(path2, "one\\...\\three");
1235 lstrcpy(out, "aaa");
1236 count = PathCommonPrefixA(path1, path2, out);
1237 ok(count == 7, "Expected 7, got %i\n", count);
1238 ok(!lstrcmp(path1, "one\\...\\two"), "Expected one\\...\\two, got %s\n", path1);
1239 ok(!lstrcmp(path2, "one\\...\\three"), "Expected one\\...\\three, got %s\n", path2);
1240 ok(!lstrcmp(out, "one\\..."), "Expected one\\..., got %s\n", out);
1241 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1242
1243 /* try prefix that is not an msdn labeled prefix type */
1244 SetLastError(0xdeadbeef);
1245 lstrcpy(path1, "same");
1246 lstrcpy(path2, "same");
1247 lstrcpy(out, "aaa");
1248 count = PathCommonPrefixA(path1, path2, out);
1249 ok(count == 4, "Expected 4, got %i\n", count);
1250 ok(!lstrcmp(path1, "same"), "Expected same, got %s\n", path1);
1251 ok(!lstrcmp(path2, "same"), "Expected same, got %s\n", path2);
1252 ok(!lstrcmp(out, "same"), "Expected same, got %s\n", out);
1253 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1254
1255 /* try . after directory */
1256 SetLastError(0xdeadbeef);
1257 lstrcpy(path1, "one\\mid.\\two");
1258 lstrcpy(path2, "one\\mid.\\three");
1259 lstrcpy(out, "aaa");
1260 count = PathCommonPrefixA(path1, path2, out);
1261 ok(count == 8, "Expected 8, got %i\n", count);
1262 ok(!lstrcmp(path1, "one\\mid.\\two"), "Expected one\\mid.\\two, got %s\n", path1);
1263 ok(!lstrcmp(path2, "one\\mid.\\three"), "Expected one\\mid.\\three, got %s\n", path2);
1264 ok(!lstrcmp(out, "one\\mid."), "Expected one\\mid., got %s\n", out);
1265 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1266
1267 /* try . in the middle of a directory */
1268 SetLastError(0xdeadbeef);
1269 lstrcpy(path1, "one\\mid.end\\two");
1270 lstrcpy(path2, "one\\mid.end\\three");
1271 lstrcpy(out, "aaa");
1272 count = PathCommonPrefixA(path1, path2, out);
1273 ok(count == 11, "Expected 11, got %i\n", count);
1274 ok(!lstrcmp(path1, "one\\mid.end\\two"), "Expected one\\mid.end\\two, got %s\n", path1);
1275 ok(!lstrcmp(path2, "one\\mid.end\\three"), "Expected one\\mid.end\\three, got %s\n", path2);
1276 ok(!lstrcmp(out, "one\\mid.end"), "Expected one\\mid.end, got %s\n", out);
1277 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1278
1279 /* try comparing a .. with the expanded path */
1280 SetLastError(0xdeadbeef);
1281 lstrcpy(path1, "one\\..\\two");
1282 lstrcpy(path2, "two");
1283 lstrcpy(out, "aaa");
1284 count = PathCommonPrefixA(path1, path2, out);
1285 ok(count == 0, "Expected 0, got %i\n", count);
1286 ok(!lstrcmp(path1, "one\\..\\two"), "Expected one\\..\\two, got %s\n", path1);
1287 ok(!lstrcmp(path2, "two"), "Expected two, got %s\n", path2);
1288 ok(lstrlen(out) == 0, "Expected 0 length out, got %i\n", lstrlen(out));
1289 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1290 }
1291
1292 static void test_PathUnquoteSpaces(void)
1293 {
1294 int i;
1295 for(i = 0; i < sizeof(TEST_PATH_UNQUOTE_SPACES) / sizeof(TEST_PATH_UNQUOTE_SPACES[0]); i++)
1296 {
1297 char *path = strdupA(TEST_PATH_UNQUOTE_SPACES[i].path);
1298 WCHAR *pathW = GetWideString(TEST_PATH_UNQUOTE_SPACES[i].path);
1299 WCHAR *resultW = GetWideString(TEST_PATH_UNQUOTE_SPACES[i].result);
1300
1301 PathUnquoteSpacesA(path);
1302 ok(!strcmp(path, TEST_PATH_UNQUOTE_SPACES[i].result), "%s (A): got %s expected %s\n",
1303 TEST_PATH_UNQUOTE_SPACES[i].path, path,
1304 TEST_PATH_UNQUOTE_SPACES[i].result);
1305
1306 PathUnquoteSpacesW(pathW);
1307 ok(!lstrcmpW(pathW, resultW), "%s (W): strings differ\n",
1308 TEST_PATH_UNQUOTE_SPACES[i].path);
1309 FreeWideString(pathW);
1310 FreeWideString(resultW);
1311 HeapFree(GetProcessHeap(), 0, path);
1312 }
1313 }
1314
1315 /* ################ */
1316
1317 START_TEST(path)
1318 {
1319 hShlwapi = GetModuleHandleA("shlwapi.dll");
1320 pPathCreateFromUrlA = (void*)GetProcAddress(hShlwapi, "PathCreateFromUrlA");
1321 pPathCreateFromUrlW = (void*)GetProcAddress(hShlwapi, "PathCreateFromUrlW");
1322
1323 test_PathSearchAndQualify();
1324 test_PathCreateFromUrl();
1325 test_PathIsUrl();
1326
1327 test_PathAddBackslash();
1328 test_PathMakePretty();
1329 test_PathMatchSpec();
1330
1331 /* For whatever reason, PathIsValidCharA and PathAppendA share the same
1332 * ordinal number in some native versions. Check this to prevent a crash.
1333 */
1334 pPathIsValidCharA = (void*)GetProcAddress(hShlwapi, (LPSTR)455);
1335 if (pPathIsValidCharA && pPathIsValidCharA != (void*)GetProcAddress(hShlwapi, "PathAppendA"))
1336 {
1337 test_PathIsValidCharA();
1338
1339 pPathIsValidCharW = (void*)GetProcAddress(hShlwapi, (LPSTR)456);
1340 if (pPathIsValidCharW) test_PathIsValidCharW();
1341 }
1342
1343 pPathCombineW = (void*)GetProcAddress(hShlwapi, "PathCombineW");
1344 if (pPathCombineW)
1345 test_PathCombineW();
1346
1347 test_PathCombineA();
1348 test_PathAppendA();
1349 test_PathCanonicalizeA();
1350 test_PathFindExtensionA();
1351 test_PathBuildRootA();
1352 test_PathCommonPrefixA();
1353 test_PathUnquoteSpaces();
1354 }