midimap: Perform stricter error-checking.
[wine] / dlls / shlwapi / tests / 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 }