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