1 /* Unit test suite for Path functions
3 * Copyright 2002 Matthew Mastracci
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #include "wine/test.h"
30 static BOOL (WINAPI
*pPathIsValidCharA
)(char,DWORD
);
31 static BOOL (WINAPI
*pPathIsValidCharW
)(WCHAR
,DWORD
);
32 static LPWSTR (WINAPI
*pPathCombineW
)(LPWSTR
, LPCWSTR
, LPCWSTR
);
33 static HRESULT (WINAPI
*pPathCreateFromUrlA
)(LPCSTR
, LPSTR
, LPDWORD
, DWORD
);
34 static HRESULT (WINAPI
*pPathCreateFromUrlW
)(LPCWSTR
, LPWSTR
, LPDWORD
, DWORD
);
35 static HRESULT (WINAPI
*pPathCreateFromUrlAlloc
)(LPCWSTR
, LPWSTR
*, DWORD
);
36 static BOOL (WINAPI
*pPathAppendA
)(LPSTR
, LPCSTR
);
37 static BOOL (WINAPI
*pPathUnExpandEnvStringsA
)(LPCSTR
, LPSTR
, UINT
);
38 static BOOL (WINAPI
*pPathUnExpandEnvStringsW
)(LPCWSTR
, LPWSTR
, UINT
);
39 static BOOL (WINAPI
*pPathIsRelativeA
)(LPCSTR
);
40 static BOOL (WINAPI
*pPathIsRelativeW
)(LPCWSTR
);
42 /* ################ */
48 } TEST_PATHFROMURL
[] = {
50 {"file:c:/foo/bar", "c:\\foo\\bar", S_OK
, 0},
51 {"file:c|/foo/bar", "c:\\foo\\bar", S_OK
, 0},
52 {"file:cx|/foo/bar", "cx|\\foo\\bar", S_OK
, 0},
53 {"file:c:foo/bar", "c:foo\\bar", S_OK
, 0},
54 {"file:c|foo/bar", "c:foo\\bar", S_OK
, 0},
55 {"file:c:/foo%20ba%2fr", "c:\\foo ba/r", S_OK
, 0},
56 {"file:foo%20ba%2fr", "foo ba/r", S_OK
, 0},
57 {"file:foo/bar/", "foo\\bar\\", S_OK
, 0},
59 /* 1 leading (back)slash */
60 {"file:/c:/foo/bar", "c:\\foo\\bar", S_OK
, 0},
61 {"file:\\c:/foo/bar", "c:\\foo\\bar", S_OK
, 0},
62 {"file:/c|/foo/bar", "c:\\foo\\bar", S_OK
, 0},
63 {"file:/cx|/foo/bar", "\\cx|\\foo\\bar", S_OK
, 0},
64 {"file:/c:foo/bar", "c:foo\\bar", S_OK
, 0},
65 {"file:/c|foo/bar", "c:foo\\bar", S_OK
, 0},
66 {"file:/c:/foo%20ba%2fr", "c:\\foo ba/r", S_OK
, 0},
67 {"file:/foo%20ba%2fr", "\\foo ba/r", S_OK
, 0},
68 {"file:/foo/bar/", "\\foo\\bar\\", S_OK
, 0},
70 /* 2 leading (back)slashes */
71 {"file://c:/foo/bar", "c:\\foo\\bar", S_OK
, 0},
72 {"file://c:/d:/foo/bar", "c:\\d:\\foo\\bar", S_OK
, 0},
73 {"file://c|/d|/foo/bar", "c:\\d|\\foo\\bar", S_OK
, 0},
74 {"file://cx|/foo/bar", "\\\\cx|\\foo\\bar", S_OK
, 0},
75 {"file://c:foo/bar", "c:foo\\bar", S_OK
, 0},
76 {"file://c|foo/bar", "c:foo\\bar", S_OK
, 0},
77 {"file://c:/foo%20ba%2fr", "c:\\foo%20ba%2fr", S_OK
, 0},
78 {"file://c%3a/foo/../bar", "\\\\c:\\foo\\..\\bar", S_OK
, 0},
79 {"file://c%7c/foo/../bar", "\\\\c|\\foo\\..\\bar", S_OK
, 0},
80 {"file://foo%20ba%2fr", "\\\\foo ba/r", S_OK
, 0},
81 {"file://localhost/c:/foo/bar", "c:\\foo\\bar", S_OK
, 0},
82 {"file://localhost/c:/foo%20ba%5Cr", "c:\\foo ba\\r", S_OK
, 0},
83 {"file://LocalHost/c:/foo/bar", "c:\\foo\\bar", S_OK
, 0},
84 {"file:\\\\localhost\\c:\\foo\\bar", "c:\\foo\\bar", S_OK
, 0},
85 {"file://incomplete", "\\\\incomplete", S_OK
, 0},
87 /* 3 leading (back)slashes (omitting hostname) */
88 {"file:///c:/foo/bar", "c:\\foo\\bar", S_OK
, 0},
89 {"File:///c:/foo/bar", "c:\\foo\\bar", S_OK
, 0},
90 {"file:///c:/foo%20ba%2fr", "c:\\foo ba/r", S_OK
, 0},
91 {"file:///foo%20ba%2fr", "\\foo ba/r", S_OK
, 0},
92 {"file:///foo/bar/", "\\foo\\bar\\", S_OK
, 0},
93 {"file:///localhost/c:/foo/bar", "\\localhost\\c:\\foo\\bar", S_OK
, 0},
95 /* 4 leading (back)slashes */
96 {"file:////c:/foo/bar", "c:\\foo\\bar", S_OK
, 0},
97 {"file:////c:/foo%20ba%2fr", "c:\\foo%20ba%2fr", S_OK
, 0},
98 {"file:////foo%20ba%2fr", "\\\\foo%20ba%2fr", S_OK
, 0},
100 /* 5 and more leading (back)slashes */
101 {"file://///c:/foo/bar", "\\\\c:\\foo\\bar", S_OK
, 0},
102 {"file://///c:/foo%20ba%2fr", "\\\\c:\\foo ba/r", S_OK
, 0},
103 {"file://///foo%20ba%2fr", "\\\\foo ba/r", S_OK
, 0},
104 {"file://////c:/foo/bar", "\\\\c:\\foo\\bar", S_OK
, 0},
106 /* Leading (back)slashes cannot be escaped */
107 {"file:%2f%2flocalhost%2fc:/foo/bar", "//localhost/c:\\foo\\bar", S_OK
, 0},
108 {"file:%5C%5Clocalhost%5Cc:/foo/bar", "\\\\localhost\\c:\\foo\\bar", S_OK
, 0},
110 /* Hostname handling */
111 {"file://l%6fcalhost/c:/foo/bar", "\\\\localhostc:\\foo\\bar", S_OK
, 0},
112 {"file://localhost:80/c:/foo/bar", "\\\\localhost:80c:\\foo\\bar", S_OK
, 0},
113 {"file://host/c:/foo/bar", "\\\\hostc:\\foo\\bar", S_OK
, 0},
114 {"file://host//c:/foo/bar", "\\\\host\\\\c:\\foo\\bar", S_OK
, 0},
115 {"file://host/\\c:/foo/bar", "\\\\host\\\\c:\\foo\\bar", S_OK
, 0},
116 {"file://host/c:foo/bar", "\\\\hostc:foo\\bar", S_OK
, 0},
117 {"file://host/foo/bar", "\\\\host\\foo\\bar", S_OK
, 0},
118 {"file:\\\\host\\c:\\foo\\bar", "\\\\hostc:\\foo\\bar", S_OK
, 0},
119 {"file:\\\\host\\ca\\foo\\bar", "\\\\host\\ca\\foo\\bar", S_OK
, 0},
120 {"file:\\\\host\\c|\\foo\\bar", "\\\\hostc|\\foo\\bar", S_OK
, 0},
121 {"file:\\%5Chost\\c:\\foo\\bar", "\\\\host\\c:\\foo\\bar", S_OK
, 0},
122 {"file:\\\\host\\cx:\\foo\\bar", "\\\\host\\cx:\\foo\\bar", S_OK
, 0},
123 {"file:///host/c:/foo/bar", "\\host\\c:\\foo\\bar", S_OK
, 0},
126 {"c:\\foo\\bar", NULL
, E_INVALIDARG
, 0},
127 {"foo/bar", NULL
, E_INVALIDARG
, 0},
128 {"http://foo/bar", NULL
, E_INVALIDARG
, 0},
136 } TEST_PATH_IS_URL
[] = {
137 {"http://foo/bar", TRUE
},
138 {"c:\\foo\\bar", FALSE
},
139 {"c:/foo/bar", FALSE
},
140 {"foo://foo/bar", TRUE
},
143 {"bogusscheme:", TRUE
},
144 {"http:partial", TRUE
},
145 {"www.winehq.org", FALSE
},
146 /* More examples that the user might enter as the browser start page */
147 {"winehq.org", FALSE
},
148 {"ftp.winehq.org", FALSE
},
149 {"http://winehq.org", TRUE
},
150 {"http://www.winehq.org", TRUE
},
151 {"https://winehq.org", TRUE
},
152 {"https://www.winehq.org", TRUE
},
153 {"ftp://winehq.org", TRUE
},
154 {"ftp://ftp.winehq.org", TRUE
},
155 {"file://does_not_exist.txt", TRUE
},
156 {"about:blank", TRUE
},
157 {"about:home", TRUE
},
158 {"about:mozilla", TRUE
},
159 /* scheme is case independent */
160 {"HTTP://www.winehq.org", TRUE
},
161 /* a space at the start is not allowed */
162 {" http://www.winehq.org", FALSE
},
167 static const struct {
170 } TEST_PATH_UNQUOTE_SPACES
[] = {
171 { "abcdef", "abcdef" },
172 { "\"abcdef\"", "abcdef" },
173 { "\"abcdef", "\"abcdef" },
174 { "abcdef\"", "abcdef\"" },
175 { "\"\"abcdef\"\"", "\"abcdef\"" },
176 { "abc\"def", "abc\"def" },
177 { "\"abc\"def", "\"abc\"def" },
178 { "\"abc\"def\"", "abc\"def" },
179 { "\'abcdef\'", "\'abcdef\'" },
184 /* ################ */
186 static LPWSTR
GetWideString(const char *src
)
193 ret
= HeapAlloc(GetProcessHeap(), 0, (2*INTERNET_MAX_URL_LENGTH
) * sizeof(WCHAR
));
195 MultiByteToWideChar(CP_ACP
, 0, src
, -1, ret
, INTERNET_MAX_URL_LENGTH
);
200 static void FreeWideString(LPWSTR wszString
)
202 HeapFree(GetProcessHeap(), 0, wszString
);
205 static LPSTR
strdupA(LPCSTR p
)
208 DWORD len
= (strlen(p
) + 1);
209 ret
= HeapAlloc(GetProcessHeap(), 0, len
);
214 /* ################ */
216 static void test_PathSearchAndQualify(void)
218 WCHAR path1
[] = {'c',':','\\','f','o','o',0};
219 WCHAR expect1
[] = {'c',':','\\','f','o','o',0};
220 WCHAR path2
[] = {'c',':','f','o','o',0};
221 WCHAR c_drive
[] = {'c',':',0};
222 WCHAR foo
[] = {'f','o','o',0};
223 WCHAR path3
[] = {'\\','f','o','o',0};
224 WCHAR winini
[] = {'w','i','n','.','i','n','i',0};
226 WCHAR cur_dir
[MAX_PATH
];
227 WCHAR dot
[] = {'.',0};
230 ok(PathSearchAndQualifyW(path1
, out
, MAX_PATH
) != 0,
231 "PathSearchAndQualify rets 0\n");
232 ok(!lstrcmpiW(out
, expect1
), "strings don't match\n");
235 ok(PathSearchAndQualifyW(path2
, out
, MAX_PATH
) != 0,
236 "PathSearchAndQualify rets 0\n");
237 GetFullPathNameW(c_drive
, MAX_PATH
, cur_dir
, NULL
);
238 PathAddBackslashW(cur_dir
);
239 lstrcatW(cur_dir
, foo
);
240 ok(!lstrcmpiW(out
, cur_dir
), "strings don't match\n");
243 ok(PathSearchAndQualifyW(foo
, out
, MAX_PATH
) != 0,
244 "PathSearchAndQualify rets 0\n");
245 GetFullPathNameW(dot
, MAX_PATH
, cur_dir
, NULL
);
246 PathAddBackslashW(cur_dir
);
247 lstrcatW(cur_dir
, foo
);
248 ok(!lstrcmpiW(out
, cur_dir
), "strings don't match\n");
251 ok(PathSearchAndQualifyW(path3
, out
, MAX_PATH
) != 0,
252 "PathSearchAndQualify rets 0\n");
253 GetFullPathNameW(dot
, MAX_PATH
, cur_dir
, NULL
);
254 lstrcpyW(cur_dir
+ 2, path3
);
255 ok(!lstrcmpiW(out
, cur_dir
), "strings don't match\n");
258 ok(PathSearchAndQualifyW(winini
, out
, MAX_PATH
) != 0,
259 "PathSearchAndQualify rets 0\n");
260 if(!SearchPathW(NULL
, winini
, NULL
, MAX_PATH
, cur_dir
, NULL
))
261 GetFullPathNameW(winini
, MAX_PATH
, cur_dir
, NULL
);
262 ok(!lstrcmpiW(out
, cur_dir
), "strings don't match\n");
266 static void test_PathCreateFromUrl(void)
269 char ret_path
[INTERNET_MAX_URL_LENGTH
];
270 DWORD len
, len2
, ret
;
271 WCHAR ret_pathW
[INTERNET_MAX_URL_LENGTH
];
274 if (!pPathCreateFromUrlA
) {
275 win_skip("PathCreateFromUrlA not found\n");
279 /* Won't say how much is needed without a buffer */
281 ret
= pPathCreateFromUrlA("file://foo", NULL
, &len
, 0);
282 ok(ret
== E_INVALIDARG
, "got 0x%08x expected E_INVALIDARG\n", ret
);
283 ok(len
== 0xdeca, "got %x expected 0xdeca\n", len
);
285 /* Test the decoding itself */
286 for (i
= 0; i
< ARRAY_SIZE(TEST_PATHFROMURL
); i
++) {
287 len
= INTERNET_MAX_URL_LENGTH
;
288 ret
= pPathCreateFromUrlA(TEST_PATHFROMURL
[i
].url
, ret_path
, &len
, 0);
289 todo_wine_if (TEST_PATHFROMURL
[i
].todo
& 0x1)
290 ok(ret
== TEST_PATHFROMURL
[i
].ret
, "ret %08x from url %s\n", ret
, TEST_PATHFROMURL
[i
].url
);
291 if(SUCCEEDED(ret
) && TEST_PATHFROMURL
[i
].path
) {
292 if(!(TEST_PATHFROMURL
[i
].todo
& 0x2)) {
293 ok(!lstrcmpiA(ret_path
, TEST_PATHFROMURL
[i
].path
), "got %s expected %s from url %s\n", ret_path
, TEST_PATHFROMURL
[i
].path
, TEST_PATHFROMURL
[i
].url
);
294 ok(len
== strlen(ret_path
), "ret len %d from url %s\n", len
, TEST_PATHFROMURL
[i
].url
);
296 /* Wrong string, don't bother checking the length */
297 ok(!lstrcmpiA(ret_path
, TEST_PATHFROMURL
[i
].path
), "got %s expected %s from url %s\n", ret_path
, TEST_PATHFROMURL
[i
].path
, TEST_PATHFROMURL
[i
].url
);
300 if (pPathCreateFromUrlW
) {
301 len
= INTERNET_MAX_URL_LENGTH
;
302 pathW
= GetWideString(TEST_PATHFROMURL
[i
].path
);
303 urlW
= GetWideString(TEST_PATHFROMURL
[i
].url
);
304 ret
= pPathCreateFromUrlW(urlW
, ret_pathW
, &len
, 0);
305 WideCharToMultiByte(CP_ACP
, 0, ret_pathW
, -1, ret_path
, sizeof(ret_path
),NULL
,NULL
);
306 todo_wine_if (TEST_PATHFROMURL
[i
].todo
& 0x1)
307 ok(ret
== TEST_PATHFROMURL
[i
].ret
, "ret %08x from url L\"%s\"\n", ret
, TEST_PATHFROMURL
[i
].url
);
308 if(SUCCEEDED(ret
) && TEST_PATHFROMURL
[i
].path
) {
309 if(!(TEST_PATHFROMURL
[i
].todo
& 0x2)) {
310 ok(!lstrcmpiW(ret_pathW
, pathW
), "got %s expected %s from url L\"%s\"\n",
311 ret_path
, TEST_PATHFROMURL
[i
].path
, TEST_PATHFROMURL
[i
].url
);
312 ok(len
== lstrlenW(ret_pathW
), "ret len %d from url L\"%s\"\n", len
, TEST_PATHFROMURL
[i
].url
);
314 /* Wrong string, don't bother checking the length */
315 ok(!lstrcmpiW(ret_pathW
, pathW
), "got %s expected %s from url L\"%s\"\n",
316 ret_path
, TEST_PATHFROMURL
[i
].path
, TEST_PATHFROMURL
[i
].url
);
321 /* Check what happens if the buffer is too small */
323 ret
= pPathCreateFromUrlW(urlW
, ret_pathW
, &len2
, 0);
324 ok(ret
== E_POINTER
, "ret %08x, expected E_POINTER from url %s\n", ret
, TEST_PATHFROMURL
[i
].url
);
325 todo_wine_if (TEST_PATHFROMURL
[i
].todo
& 0x4)
326 ok(len2
== len
+ 1, "got len = %d expected %d from url %s\n", len2
, len
+ 1, TEST_PATHFROMURL
[i
].url
);
329 FreeWideString(urlW
);
330 FreeWideString(pathW
);
334 if (pPathCreateFromUrlAlloc
)
336 static const WCHAR fileW
[] = {'f','i','l','e',':','/','/','f','o','o',0};
337 static const WCHAR fooW
[] = {'\\','\\','f','o','o',0};
340 ret
= pPathCreateFromUrlAlloc(fileW
, &pathW
, 0);
341 ok(ret
== S_OK
, "got 0x%08x expected S_OK\n", ret
);
342 ok(lstrcmpiW(pathW
, fooW
) == 0, "got %s expected %s\n", wine_dbgstr_w(pathW
), wine_dbgstr_w(fooW
));
343 HeapFree(GetProcessHeap(), 0, pathW
);
348 static void test_PathIsUrl(void)
353 for (i
= 0; i
< ARRAY_SIZE(TEST_PATH_IS_URL
); i
++) {
354 ret
= PathIsURLA(TEST_PATH_IS_URL
[i
].path
);
355 ok(ret
== TEST_PATH_IS_URL
[i
].expect
,
356 "returned %d from path %s, expected %d\n", ret
, TEST_PATH_IS_URL
[i
].path
,
357 TEST_PATH_IS_URL
[i
].expect
);
361 static const DWORD SHELL_charclass
[] =
363 0x00000000, 0x00000000, 0x00000000, 0x00000000,
364 0x00000000, 0x00000000, 0x00000000, 0x00000000,
365 0x00000000, 0x00000000, 0x00000000, 0x00000000,
366 0x00000000, 0x00000000, 0x00000000, 0x00000000,
367 0x00000000, 0x00000000, 0x00000000, 0x00000000,
368 0x00000000, 0x00000000, 0x00000000, 0x00000000,
369 0x00000000, 0x00000000, 0x00000000, 0x00000000,
370 0x00000000, 0x00000000, 0x00000000, 0x00000000,
371 0x00000080, 0x00000100, 0x00000200, 0x00000100,
372 0x00000100, 0x00000100, 0x00000100, 0x00000100,
373 0x00000100, 0x00000100, 0x00000002, 0x00000100,
374 0x00000040, 0x00000100, 0x00000004, 0x00000000,
375 0x00000100, 0x00000100, 0x00000100, 0x00000100,
376 0x00000100, 0x00000100, 0x00000100, 0x00000100,
377 0x00000100, 0x00000100, 0x00000010, 0x00000020,
378 0x00000000, 0x00000100, 0x00000000, 0x00000001,
379 0x00000100, 0xffffffff, 0xffffffff, 0xffffffff,
380 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
381 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
382 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
383 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
384 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
385 0xffffffff, 0xffffffff, 0xffffffff, 0x00000100,
386 0x00000008, 0x00000100, 0x00000100, 0x00000100,
387 0x00000100, 0xffffffff, 0xffffffff, 0xffffffff,
388 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
389 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
390 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
391 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
392 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
393 0xffffffff, 0xffffffff, 0xffffffff, 0x00000100,
394 0x00000000, 0x00000100, 0x00000100
397 static void test_PathIsValidCharA(void)
402 /* For whatever reason, PathIsValidCharA and PathAppendA share the same
403 * ordinal number in some native versions. Check this to prevent a crash.
405 if (!pPathIsValidCharA
|| pPathIsValidCharA
== (void*)pPathAppendA
)
407 win_skip("PathIsValidCharA isn't available\n");
411 for (c
= 0; c
< 0x7f; c
++)
413 ret
= pPathIsValidCharA( c
, ~0U );
414 ok ( ret
|| !SHELL_charclass
[c
], "PathIsValidCharA failed: 0x%02x got 0x%08x\n", c
, ret
);
417 for (c
= 0x7f; c
<= 0xff; c
++)
419 ret
= pPathIsValidCharA( c
, ~0U );
420 ok ( ret
, "PathIsValidCharA failed: 0x%02x got 0x%08x\n", c
, ret
);
424 static void test_PathIsValidCharW(void)
429 if (!pPathIsValidCharW
)
431 win_skip("PathIsValidCharW isn't available\n");
435 for (c
= 0; c
< 0x7f; c
++)
437 ret
= pPathIsValidCharW( c
, ~0U );
438 ok ( ret
|| !SHELL_charclass
[c
], "PathIsValidCharW failed: 0x%02x got 0x%08x\n", c
, ret
);
441 for (c
= 0x007f; c
<= 0xffff; c
++)
443 ret
= pPathIsValidCharW( c
, ~0U );
444 ok ( ret
, "PathIsValidCharW failed: 0x%02x got 0x%08x\n", c
, ret
);
448 static void test_PathMakePretty(void)
452 ok (PathMakePrettyA(NULL
) == FALSE
, "PathMakePretty: NULL path succeeded\n");
454 ok (PathMakePrettyA(buff
) == TRUE
, "PathMakePretty: Empty path failed\n");
456 strcpy(buff
, "C:\\A LONG FILE NAME WITH \\SPACES.TXT");
457 ok (PathMakePrettyA(buff
) == TRUE
, "PathMakePretty: Long UC name failed\n");
458 ok (strcmp(buff
, "C:\\a long file name with \\spaces.txt") == 0,
459 "PathMakePretty: Long UC name not changed\n");
461 strcpy(buff
, "C:\\A LONG FILE NAME WITH \\MixedCase.TXT");
462 ok (PathMakePrettyA(buff
) == FALSE
, "PathMakePretty: Long MC name succeeded\n");
463 ok (strcmp(buff
, "C:\\A LONG FILE NAME WITH \\MixedCase.TXT") == 0,
464 "PathMakePretty: Failed but modified path\n");
466 strcpy(buff
, "TEST");
467 ok (PathMakePrettyA(buff
) == TRUE
, "PathMakePretty: Short name failed\n");
468 ok (strcmp(buff
, "Test") == 0, "PathMakePretty: 1st char lowercased %s\n", buff
);
471 static void test_PathMatchSpec(void)
473 static const char file
[] = "c:\\foo\\bar\\filename.ext";
474 static const char spec1
[] = ".ext";
475 static const char spec2
[] = "*.ext";
476 static const char spec3
[] = "*.ext ";
477 static const char spec4
[] = " *.ext";
478 static const char spec5
[] = "* .ext";
479 static const char spec6
[] = "*. ext";
480 static const char spec7
[] = "* . ext";
481 static const char spec8
[] = "*.e?t";
482 static const char spec9
[] = "filename.ext";
483 static const char spec10
[] = "*bar\\filename.ext";
484 static const char spec11
[] = " foo; *.ext";
485 static const char spec12
[] = "*.ext;*.bar";
486 static const char spec13
[] = "*bar*";
488 ok (PathMatchSpecA(file
, spec1
) == FALSE
, "PathMatchSpec: Spec1 failed\n");
489 ok (PathMatchSpecA(file
, spec2
) == TRUE
, "PathMatchSpec: Spec2 failed\n");
490 ok (PathMatchSpecA(file
, spec3
) == FALSE
, "PathMatchSpec: Spec3 failed\n");
491 ok (PathMatchSpecA(file
, spec4
) == TRUE
, "PathMatchSpec: Spec4 failed\n");
492 todo_wine
ok (PathMatchSpecA(file
, spec5
) == TRUE
, "PathMatchSpec: Spec5 failed\n");
493 todo_wine
ok (PathMatchSpecA(file
, spec6
) == TRUE
, "PathMatchSpec: Spec6 failed\n");
494 ok (PathMatchSpecA(file
, spec7
) == FALSE
, "PathMatchSpec: Spec7 failed\n");
495 ok (PathMatchSpecA(file
, spec8
) == TRUE
, "PathMatchSpec: Spec8 failed\n");
496 ok (PathMatchSpecA(file
, spec9
) == FALSE
, "PathMatchSpec: Spec9 failed\n");
497 ok (PathMatchSpecA(file
, spec10
) == TRUE
, "PathMatchSpec: Spec10 failed\n");
498 ok (PathMatchSpecA(file
, spec11
) == TRUE
, "PathMatchSpec: Spec11 failed\n");
499 ok (PathMatchSpecA(file
, spec12
) == TRUE
, "PathMatchSpec: Spec12 failed\n");
500 ok (PathMatchSpecA(file
, spec13
) == TRUE
, "PathMatchSpec: Spec13 failed\n");
503 static void test_PathCombineW(void)
505 LPWSTR wszString
, wszString2
;
506 WCHAR wbuf
[MAX_PATH
+1], wstr1
[MAX_PATH
] = {'C',':','\\',0}, wstr2
[MAX_PATH
];
507 static const WCHAR expout
[] = {'C',':','\\','A','A',0};
512 win_skip("PathCombineW isn't available\n");
516 wszString2
= HeapAlloc(GetProcessHeap(), 0, MAX_PATH
* sizeof(WCHAR
));
519 wszString
= pPathCombineW(NULL
, NULL
, NULL
);
520 ok (wszString
== NULL
, "Expected a NULL return\n");
524 wszString
= pPathCombineW(wszString2
, NULL
, NULL
);
525 ok (wszString
== NULL
||
526 broken(wszString
[0] == 'a'), /* Win95 and some W2K */
527 "Expected a NULL return\n");
528 ok (wszString2
[0] == 0 ||
529 broken(wszString2
[0] == 'a'), /* Win95 and some W2K */
530 "Destination string not empty\n");
532 HeapFree(GetProcessHeap(), 0, wszString2
);
535 wstr2
[0] = wstr2
[1] = wstr2
[2] = 'A';
536 for (i
=3; i
<MAX_PATH
/2; i
++)
537 wstr1
[i
] = wstr2
[i
] = 'A';
538 wstr1
[(MAX_PATH
/2) - 1] = wstr2
[MAX_PATH
/2] = 0;
539 memset(wbuf
, 0xbf, sizeof(wbuf
));
541 wszString
= pPathCombineW(wbuf
, wstr1
, wstr2
);
542 ok(wszString
== NULL
, "Expected a NULL return\n");
544 broken(wbuf
[0] == 0xbfbf), /* Win95 and some W2K */
545 "Buffer contains data\n");
547 /* PathCombineW can be used in place */
550 ok(PathCombineW(wstr1
, wstr1
, wstr2
) == wstr1
, "Expected a wstr1 return\n");
551 ok(StrCmpW(wstr1
, expout
) == 0, "Unexpected PathCombine output\n");
555 #define LONG_LEN (MAX_PATH * 2)
556 #define HALF_LEN (MAX_PATH / 2 + 1)
558 static void test_PathCombineA(void)
562 char too_long
[LONG_LEN
];
563 char one
[HALF_LEN
], two
[HALF_LEN
];
566 SetLastError(0xdeadbeef);
567 str
= PathCombineA(NULL
, "C:\\", "one\\two\\three");
568 ok(str
== NULL
, "Expected NULL, got %p\n", str
);
569 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
571 /* try NULL dest and NULL directory */
572 SetLastError(0xdeadbeef);
573 str
= PathCombineA(NULL
, NULL
, "one\\two\\three");
574 ok(str
== NULL
, "Expected NULL, got %p\n", str
);
575 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
578 SetLastError(0xdeadbeef);
579 str
= PathCombineA(NULL
, NULL
, NULL
);
580 ok(str
== NULL
, "Expected NULL, got %p\n", str
);
581 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
583 /* try NULL file part */
584 SetLastError(0xdeadbeef);
585 lstrcpyA(dest
, "control");
586 str
= PathCombineA(dest
, "C:\\", NULL
);
587 ok(str
== dest
, "Expected str == dest, got %p\n", str
);
588 ok(!lstrcmpA(str
, "C:\\"), "Expected C:\\, got %s\n", str
);
589 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
591 /* try empty file part */
592 SetLastError(0xdeadbeef);
593 lstrcpyA(dest
, "control");
594 str
= PathCombineA(dest
, "C:\\", "");
595 ok(str
== dest
, "Expected str == dest, got %p\n", str
);
596 ok(!lstrcmpA(str
, "C:\\"), "Expected C:\\, got %s\n", str
);
597 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
599 /* try empty directory and file part */
600 SetLastError(0xdeadbeef);
601 lstrcpyA(dest
, "control");
602 str
= PathCombineA(dest
, "", "");
603 ok(str
== dest
, "Expected str == dest, got %p\n", str
);
604 ok(!lstrcmpA(str
, "\\") ||
605 broken(!lstrcmpA(str
, "control")), /* Win95 and some W2K */
606 "Expected \\, got %s\n", str
);
607 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
609 /* try NULL directory */
610 SetLastError(0xdeadbeef);
611 lstrcpyA(dest
, "control");
612 str
= PathCombineA(dest
, NULL
, "one\\two\\three");
613 ok(str
== dest
, "Expected str == dest, got %p\n", str
);
614 ok(!lstrcmpA(str
, "one\\two\\three"), "Expected one\\two\\three, got %s\n", str
);
615 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
617 /* try NULL directory and empty file part */
618 SetLastError(0xdeadbeef);
619 lstrcpyA(dest
, "control");
620 str
= PathCombineA(dest
, NULL
, "");
621 ok(str
== dest
, "Expected str == dest, got %p\n", str
);
622 ok(!lstrcmpA(str
, "\\") ||
623 broken(!lstrcmpA(str
, "one\\two\\three")), /* Win95 and some W2K */
624 "Expected \\, got %s\n", str
);
625 ok(GetLastError() == 0xdeadbeef ||
626 broken(GetLastError() == ERROR_INVALID_PARAMETER
), /* Win95 */
627 "Expected 0xdeadbeef, got %d\n", GetLastError());
629 /* try NULL directory and file part */
630 SetLastError(0xdeadbeef);
631 lstrcpyA(dest
, "control");
632 str
= PathCombineA(dest
, NULL
, NULL
);
634 broken(str
!= NULL
), /* Win95 and some W2K */
635 "Expected str == NULL, got %p\n", str
);
636 ok(!dest
[0] || broken(!lstrcmpA(dest
, "control")), /* Win95 and some W2K */
637 "Expected 0 length, got %i\n", lstrlenA(dest
));
638 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
640 /* try directory without backslash */
641 SetLastError(0xdeadbeef);
642 lstrcpyA(dest
, "control");
643 str
= PathCombineA(dest
, "C:", "one\\two\\three");
644 ok(str
== dest
, "Expected str == dest, got %p\n", str
);
645 ok(!lstrcmpA(str
, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", str
);
646 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
648 /* try directory with backslash */
649 SetLastError(0xdeadbeef);
650 lstrcpyA(dest
, "control");
651 str
= PathCombineA(dest
, "C:\\", "one\\two\\three");
652 ok(str
== dest
, "Expected str == dest, got %p\n", str
);
653 ok(!lstrcmpA(str
, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", str
);
654 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
656 /* try directory with backslash and file with prepended backslash */
657 SetLastError(0xdeadbeef);
658 lstrcpyA(dest
, "control");
659 str
= PathCombineA(dest
, "C:\\", "\\one\\two\\three");
660 ok(str
== dest
, "Expected str == dest, got %p\n", str
);
661 ok(!lstrcmpA(str
, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", str
);
662 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
664 /* try previous test, with backslash appended as well */
665 SetLastError(0xdeadbeef);
666 lstrcpyA(dest
, "control");
667 str
= PathCombineA(dest
, "C:\\", "\\one\\two\\three\\");
668 ok(str
== dest
, "Expected str == dest, got %p\n", str
);
669 ok(!lstrcmpA(str
, "C:\\one\\two\\three\\"), "Expected C:\\one\\two\\three\\, got %s\n", str
);
670 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
672 /* try a relative directory */
673 SetLastError(0xdeadbeef);
674 lstrcpyA(dest
, "control");
675 str
= PathCombineA(dest
, "relative\\dir", "\\one\\two\\three\\");
676 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
677 /* Vista fails which probably makes sense as PathCombineA expects an absolute dir */
680 ok(str
== dest
, "Expected str == dest, got %p\n", str
);
681 ok(!lstrcmpA(str
, "one\\two\\three\\"), "Expected one\\two\\three\\, got %s\n", str
);
684 /* try forward slashes */
685 SetLastError(0xdeadbeef);
686 lstrcpyA(dest
, "control");
687 str
= PathCombineA(dest
, "C:\\", "one/two/three\\");
688 ok(str
== dest
, "Expected str == dest, got %p\n", str
);
689 ok(!lstrcmpA(str
, "C:\\one/two/three\\"), "Expected one/two/three\\, got %s\n", str
);
690 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
692 /* try a really weird directory */
693 SetLastError(0xdeadbeef);
694 lstrcpyA(dest
, "control");
695 str
= PathCombineA(dest
, "C:\\/\\/", "\\one\\two\\three\\");
696 ok(str
== dest
, "Expected str == dest, got %p\n", str
);
697 ok(!lstrcmpA(str
, "C:\\one\\two\\three\\"), "Expected C:\\one\\two\\three\\, got %s\n", str
);
698 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
701 SetLastError(0xdeadbeef);
702 lstrcpyA(dest
, "control");
703 str
= PathCombineA(dest
, "C:\\", "one\\..\\two\\.\\three");
704 ok(str
== dest
, "Expected str == dest, got %p\n", str
);
705 ok(!lstrcmpA(str
, "C:\\two\\three"), "Expected C:\\two\\three, got %s\n", str
);
706 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
709 /* try forward slashes */
710 SetLastError(0xdeadbeef);
711 lstrcpyA(dest
, "control");
712 str
= PathCombineA(dest
, "C:\\", "..");
713 ok(str
== dest
, "Expected str == dest, got %p\n", str
);
714 ok(!lstrcmpA(str
, "C:\\"), "Expected C:\\, got %s\n", str
);
715 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
717 memset(too_long
, 'a', LONG_LEN
);
718 too_long
[LONG_LEN
- 1] = '\0';
720 /* try a file longer than MAX_PATH */
721 SetLastError(0xdeadbeef);
722 lstrcpyA(dest
, "control");
723 str
= PathCombineA(dest
, "C:\\", too_long
);
724 ok(str
== NULL
, "Expected str == NULL, got %p\n", str
);
725 ok(!dest
[0] || broken(!lstrcmpA(dest
, "control")), /* Win95 and some W2K */
726 "Expected 0 length, got %i\n", lstrlenA(dest
));
727 todo_wine
ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
729 /* try a directory longer than MAX_PATH */
730 SetLastError(0xdeadbeef);
731 lstrcpyA(dest
, "control");
732 str
= PathCombineA(dest
, too_long
, "one\\two\\three");
733 ok(str
== NULL
, "Expected str == NULL, got %p\n", str
);
734 ok(!dest
[0] || broken(!lstrcmpA(dest
, "control")), /* Win95 and some W2K */
735 "Expected 0 length, got %i\n", lstrlenA(dest
));
736 todo_wine
ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
738 memset(one
, 'b', HALF_LEN
);
739 memset(two
, 'c', HALF_LEN
);
740 one
[HALF_LEN
- 1] = '\0';
741 two
[HALF_LEN
- 1] = '\0';
743 /* destination string is longer than MAX_PATH, but not the constituent parts */
744 SetLastError(0xdeadbeef);
745 lstrcpyA(dest
, "control");
746 str
= PathCombineA(dest
, one
, two
);
747 ok(str
== NULL
, "Expected str == NULL, got %p\n", str
);
748 ok(!dest
[0] || broken(!lstrcmpA(dest
, "control")), /* Win95 and some W2K */
749 "Expected 0 length, got %i\n", lstrlenA(dest
));
750 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
753 static void test_PathAddBackslash(void)
757 char too_long
[LONG_LEN
];
759 /* try a NULL path */
760 SetLastError(0xdeadbeef);
761 str
= PathAddBackslashA(NULL
);
762 ok(str
== NULL
, "Expected str == NULL, got %p\n", str
);
763 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
765 /* try an empty path */
767 SetLastError(0xdeadbeef);
768 str
= PathAddBackslashA(path
);
769 ok(str
== (path
+ lstrlenA(path
)), "Expected str to point to end of path, got %p\n", str
);
770 ok(!path
[0], "Expected empty string, got %i\n", lstrlenA(path
));
771 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
773 /* try a relative path */
774 lstrcpyA(path
, "one\\two");
775 SetLastError(0xdeadbeef);
776 str
= PathAddBackslashA(path
);
777 ok(str
== (path
+ lstrlenA(path
)), "Expected str to point to end of path, got %p\n", str
);
778 ok(!lstrcmpA(path
, "one\\two\\"), "Expected one\\two\\, got %s\n", path
);
779 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
782 lstrcpyA(path
, "one\\..\\two");
783 SetLastError(0xdeadbeef);
784 str
= PathAddBackslashA(path
);
785 ok(str
== (path
+ lstrlenA(path
)), "Expected str to point to end of path, got %p\n", str
);
786 ok(!lstrcmpA(path
, "one\\..\\two\\"), "Expected one\\..\\two\\, got %s\n", path
);
787 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
789 /* try just a space */
791 SetLastError(0xdeadbeef);
792 str
= PathAddBackslashA(path
);
793 ok(str
== (path
+ lstrlenA(path
)), "Expected str to point to end of path, got %p\n", str
);
794 ok(!lstrcmpA(path
, " \\"), "Expected \\, got %s\n", path
);
795 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
797 /* path already has backslash */
798 lstrcpyA(path
, "C:\\one\\");
799 SetLastError(0xdeadbeef);
800 str
= PathAddBackslashA(path
);
801 ok(str
== (path
+ lstrlenA(path
)), "Expected str to point to end of path, got %p\n", str
);
802 ok(!lstrcmpA(path
, "C:\\one\\"), "Expected C:\\one\\, got %s\n", path
);
803 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
805 memset(too_long
, 'a', LONG_LEN
);
806 too_long
[LONG_LEN
- 1] = '\0';
808 /* path is longer than MAX_PATH */
809 SetLastError(0xdeadbeef);
810 str
= PathAddBackslashA(too_long
);
811 ok(str
== NULL
, "Expected str == NULL, got %p\n", str
);
812 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
815 static void test_PathAppendA(void)
818 char too_long
[LONG_LEN
];
822 lstrcpyA(path
, "C:\\one");
824 /* try NULL pszMore */
825 SetLastError(0xdeadbeef);
826 res
= PathAppendA(path
, NULL
);
827 ok(!res
, "Expected failure\n");
828 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
829 ok(!lstrcmpA(path
, "C:\\one"), "Expected C:\\one, got %s\n", path
);
831 /* try empty pszMore */
832 SetLastError(0xdeadbeef);
833 res
= PathAppendA(path
, "");
834 ok(res
, "Expected success\n");
835 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
836 ok(!lstrcmpA(path
, "C:\\one"), "Expected C:\\one, got %s\n", path
);
838 /* try NULL pszPath */
839 SetLastError(0xdeadbeef);
840 res
= PathAppendA(NULL
, "two\\three");
841 ok(!res
, "Expected failure\n");
842 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
844 /* try empty pszPath */
846 SetLastError(0xdeadbeef);
847 res
= PathAppendA(path
, "two\\three");
848 ok(res
, "Expected success\n");
849 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
850 ok(!lstrcmpA(path
, "two\\three"), "Expected \\two\\three, got %s\n", path
);
852 /* try empty pszPath and empty pszMore */
854 SetLastError(0xdeadbeef);
855 res
= PathAppendA(path
, "");
856 ok(res
, "Expected success\n");
857 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
858 ok(!lstrcmpA(path
, "\\"), "Expected \\, got %s\n", path
);
860 /* try legit params */
861 lstrcpyA(path
, "C:\\one");
862 SetLastError(0xdeadbeef);
863 res
= PathAppendA(path
, "two\\three");
864 ok(res
, "Expected success\n");
865 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
866 ok(!lstrcmpA(path
, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", path
);
868 /* try pszPath with backslash after it */
869 lstrcpyA(path
, "C:\\one\\");
870 SetLastError(0xdeadbeef);
871 res
= PathAppendA(path
, "two\\three");
872 ok(res
, "Expected success\n");
873 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
874 ok(!lstrcmpA(path
, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", path
);
876 /* try pszMore with backslash before it */
877 lstrcpyA(path
, "C:\\one");
878 SetLastError(0xdeadbeef);
879 res
= PathAppendA(path
, "\\two\\three");
880 ok(res
, "Expected success\n");
881 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
882 ok(!lstrcmpA(path
, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", path
);
884 /* try pszMore with backslash after it */
885 lstrcpyA(path
, "C:\\one");
886 SetLastError(0xdeadbeef);
887 res
= PathAppendA(path
, "two\\three\\");
888 ok(res
, "Expected success\n");
889 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
890 ok(!lstrcmpA(path
, "C:\\one\\two\\three\\"), "Expected C:\\one\\two\\three\\, got %s\n", path
);
892 /* try spaces in pszPath */
893 lstrcpyA(path
, "C: \\ one ");
894 SetLastError(0xdeadbeef);
895 res
= PathAppendA(path
, "two\\three");
896 ok(res
, "Expected success\n");
897 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
898 ok(!lstrcmpA(path
, "C: \\ one \\two\\three"), "Expected C: \\ one \\two\\three, got %s\n", path
);
900 /* try spaces in pszMore */
901 lstrcpyA(path
, "C:\\one");
902 SetLastError(0xdeadbeef);
903 res
= PathAppendA(path
, " two \\ three ");
904 ok(res
, "Expected success\n");
905 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
906 ok(!lstrcmpA(path
, "C:\\one\\ two \\ three "), "Expected 'C:\\one\\ two \\ three ', got %s\n", path
);
908 /* pszPath is too long */
909 memset(too_long
, 'a', LONG_LEN
);
910 too_long
[LONG_LEN
- 1] = '\0';
911 SetLastError(0xdeadbeef);
912 res
= PathAppendA(too_long
, "two\\three");
913 ok(!res
, "Expected failure\n");
914 todo_wine
ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
915 ok(!too_long
[0] || broken(lstrlenA(too_long
) == (LONG_LEN
- 1)), /* Win95 and some W2K */
916 "Expected length of too_long to be zero, got %i\n", lstrlenA(too_long
));
918 /* pszMore is too long */
919 lstrcpyA(path
, "C:\\one");
920 memset(too_long
, 'a', LONG_LEN
);
921 too_long
[LONG_LEN
- 1] = '\0';
922 SetLastError(0xdeadbeef);
923 res
= PathAppendA(path
, too_long
);
924 ok(!res
, "Expected failure\n");
925 todo_wine
ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
926 ok(!path
[0] || broken(!lstrcmpA(path
, "C:\\one")), /* Win95 and some W2K */
927 "Expected length of path to be zero, got %i\n", lstrlenA(path
));
929 /* both params combined are too long */
930 memset(path
, 'a', HALF_LEN
);
931 path
[HALF_LEN
- 1] = '\0';
932 memset(half
, 'b', HALF_LEN
);
933 half
[HALF_LEN
- 1] = '\0';
934 SetLastError(0xdeadbeef);
935 res
= PathAppendA(path
, half
);
936 ok(!res
, "Expected failure\n");
937 ok(!path
[0] || broken(lstrlenA(path
) == (HALF_LEN
- 1)), /* Win95 and some W2K */
938 "Expected length of path to be zero, got %i\n", lstrlenA(path
));
939 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
942 static void test_PathCanonicalizeA(void)
944 char dest
[LONG_LEN
+ MAX_PATH
];
945 char too_long
[LONG_LEN
];
948 /* try a NULL source */
949 lstrcpyA(dest
, "test");
950 SetLastError(0xdeadbeef);
951 res
= PathCanonicalizeA(dest
, NULL
);
952 ok(!res
, "Expected failure\n");
953 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
954 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
955 ok(dest
[0] == 0 || !lstrcmpA(dest
, "test"),
956 "Expected either an empty string (Vista) or test, got %s\n", dest
);
958 /* try an empty source */
959 lstrcpyA(dest
, "test");
960 SetLastError(0xdeadbeef);
961 res
= PathCanonicalizeA(dest
, "");
962 ok(res
, "Expected success\n");
963 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
964 ok(!lstrcmpA(dest
, "\\") ||
965 broken(!lstrcmpA(dest
, "test")), /* Win95 and some W2K */
966 "Expected \\, got %s\n", dest
);
968 /* try a NULL dest */
969 SetLastError(0xdeadbeef);
970 res
= PathCanonicalizeA(NULL
, "C:\\");
971 ok(!res
, "Expected failure\n");
972 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
973 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
977 SetLastError(0xdeadbeef);
978 res
= PathCanonicalizeA(dest
, "C:\\");
979 ok(res
, "Expected success\n");
980 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
981 ok(!lstrcmpA(dest
, "C:\\"), "Expected C:\\, got %s\n", dest
);
983 /* try non-empty dest */
984 lstrcpyA(dest
, "test");
985 SetLastError(0xdeadbeef);
986 res
= PathCanonicalizeA(dest
, "C:\\");
987 ok(res
, "Expected success\n");
988 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
989 ok(!lstrcmpA(dest
, "C:\\"), "Expected C:\\, got %s\n", dest
);
991 /* try a space for source */
992 lstrcpyA(dest
, "test");
993 SetLastError(0xdeadbeef);
994 res
= PathCanonicalizeA(dest
, " ");
995 ok(res
, "Expected success\n");
996 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
997 ok(!lstrcmpA(dest
, " "), "Expected ' ', got %s\n", dest
);
999 /* try a relative path */
1000 lstrcpyA(dest
, "test");
1001 SetLastError(0xdeadbeef);
1002 res
= PathCanonicalizeA(dest
, "one\\two");
1003 ok(res
, "Expected success\n");
1004 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1005 ok(!lstrcmpA(dest
, "one\\two"), "Expected one\\two, got %s\n", dest
);
1007 /* try current dir and previous dir */
1008 lstrcpyA(dest
, "test");
1009 SetLastError(0xdeadbeef);
1010 res
= PathCanonicalizeA(dest
, "C:\\one\\.\\..\\two\\three\\..");
1011 ok(res
, "Expected success\n");
1012 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1013 ok(!lstrcmpA(dest
, "C:\\two"), "Expected C:\\two, got %s\n", dest
);
1015 /* try simple forward slashes */
1016 lstrcpyA(dest
, "test");
1017 SetLastError(0xdeadbeef);
1018 res
= PathCanonicalizeA(dest
, "C:\\one/two/three\\four/five\\six");
1019 ok(res
, "Expected success\n");
1020 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1021 ok(!lstrcmpA(dest
, "C:\\one/two/three\\four/five\\six"),
1022 "Expected C:\\one/two/three\\four/five\\six, got %s\n", dest
);
1024 /* try simple forward slashes with same dir */
1025 lstrcpyA(dest
, "test");
1026 SetLastError(0xdeadbeef);
1027 res
= PathCanonicalizeA(dest
, "C:\\one/.\\two");
1028 ok(res
, "Expected success\n");
1029 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1030 ok(!lstrcmpA(dest
, "C:\\one/.\\two"), "Expected C:\\one/.\\two, got %s\n", dest
);
1032 /* try simple forward slashes with change dir */
1033 lstrcpyA(dest
, "test");
1034 SetLastError(0xdeadbeef);
1035 res
= PathCanonicalizeA(dest
, "C:\\one/.\\two\\..");
1036 ok(res
, "Expected success\n");
1037 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1038 ok(!lstrcmpA(dest
, "C:\\one/.") ||
1039 !lstrcmpA(dest
, "C:\\one/"), /* Vista */
1040 "Expected \"C:\\one/.\" or \"C:\\one/\", got \"%s\"\n", dest
);
1042 /* try forward slashes with change dirs
1043 * NOTE: if there is a forward slash in between two backslashes,
1044 * everything in between the two backslashes is considered on dir
1046 lstrcpyA(dest
, "test");
1047 SetLastError(0xdeadbeef);
1048 res
= PathCanonicalizeA(dest
, "C:\\one/.\\..\\two/three\\..\\four/.five");
1049 ok(res
, "Expected success\n");
1050 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1051 ok(!lstrcmpA(dest
, "C:\\four/.five"), "Expected C:\\four/.five, got %s\n", dest
);
1053 /* try src is too long */
1054 memset(too_long
, 'a', LONG_LEN
);
1055 too_long
[LONG_LEN
- 1] = '\0';
1056 lstrcpyA(dest
, "test");
1057 SetLastError(0xdeadbeef);
1058 res
= PathCanonicalizeA(dest
, too_long
);
1060 broken(res
), /* Win95, some W2K and XP-SP1 */
1061 "Expected failure\n");
1064 ok(GetLastError() == 0xdeadbeef || GetLastError() == ERROR_FILENAME_EXCED_RANGE
/* Vista */,
1065 "Expected 0xdeadbeef or ERROR_FILENAME_EXCED_RANGE, got %d\n", GetLastError());
1067 ok(lstrlenA(too_long
) == LONG_LEN
- 1, "Expected length LONG_LEN - 1, got %i\n", lstrlenA(too_long
));
1070 static void test_PathFindExtensionA(void)
1073 char path
[MAX_PATH
];
1074 char too_long
[LONG_LEN
];
1076 /* try a NULL path */
1077 SetLastError(0xdeadbeef);
1078 ext
= PathFindExtensionA(NULL
);
1079 ok(ext
== NULL
, "Expected NULL, got %p\n", ext
);
1080 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1082 /* try an empty path */
1084 SetLastError(0xdeadbeef);
1085 ext
= PathFindExtensionA(path
);
1086 ok(ext
== path
, "Expected ext == path, got %p\n", ext
);
1087 ok(!ext
[0], "Expected length 0, got %i\n", lstrlenA(ext
));
1088 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1090 /* try a path without an extension */
1091 lstrcpyA(path
, "file");
1092 SetLastError(0xdeadbeef);
1093 ext
= PathFindExtensionA(path
);
1094 ok(ext
== path
+ lstrlenA(path
), "Expected ext == path, got %p\n", ext
);
1095 ok(!ext
[0], "Expected length 0, got %i\n", lstrlenA(ext
));
1096 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1098 /* try a path with an extension */
1099 lstrcpyA(path
, "file.txt");
1100 SetLastError(0xdeadbeef);
1101 ext
= PathFindExtensionA(path
);
1102 ok(ext
== path
+ lstrlenA("file"),
1103 "Expected ext == path + lstrlenA(\"file\"), got %p\n", ext
);
1104 ok(!lstrcmpA(ext
, ".txt"), "Expected .txt, got %s\n", ext
);
1105 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1107 /* try a path with two extensions */
1108 lstrcpyA(path
, "file.txt.doc");
1109 SetLastError(0xdeadbeef);
1110 ext
= PathFindExtensionA(path
);
1111 ok(ext
== path
+ lstrlenA("file.txt"),
1112 "Expected ext == path + lstrlenA(\"file.txt\"), got %p\n", ext
);
1113 ok(!lstrcmpA(ext
, ".doc"), "Expected .txt, got %s\n", ext
);
1114 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1116 /* try a path longer than MAX_PATH without an extension*/
1117 memset(too_long
, 'a', LONG_LEN
);
1118 too_long
[LONG_LEN
- 1] = '\0';
1119 SetLastError(0xdeadbeef);
1120 ext
= PathFindExtensionA(too_long
);
1121 ok(ext
== too_long
+ LONG_LEN
- 1, "Expected ext == too_long + LONG_LEN - 1, got %p\n", ext
);
1122 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1124 /* try a path longer than MAX_PATH with an extension*/
1125 memset(too_long
, 'a', LONG_LEN
);
1126 too_long
[LONG_LEN
- 1] = '\0';
1127 lstrcpyA(too_long
+ 300, ".abcde");
1128 too_long
[lstrlenA(too_long
)] = 'a';
1129 SetLastError(0xdeadbeef);
1130 ext
= PathFindExtensionA(too_long
);
1131 ok(ext
== too_long
+ 300, "Expected ext == too_long + 300, got %p\n", ext
);
1132 ok(lstrlenA(ext
) == LONG_LEN
- 301, "Expected LONG_LEN - 301, got %i\n", lstrlenA(ext
));
1133 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1136 static void test_PathBuildRootA(void)
1140 char root_expected
[26][4];
1144 /* set up the expected paths */
1145 for (drive
= 'A'; drive
<= 'Z'; drive
++)
1146 sprintf(root_expected
[drive
- 'A'], "%c:\\", drive
);
1148 /* test the expected values */
1149 for (j
= 0; j
< 26; j
++)
1151 SetLastError(0xdeadbeef);
1152 lstrcpyA(path
, "aaaaaaaaa");
1153 root
= PathBuildRootA(path
, j
);
1154 ok(root
== path
, "Expected root == path, got %p\n", root
);
1155 ok(!lstrcmpA(root
, root_expected
[j
]), "Expected %s, got %s\n", root_expected
[j
], root
);
1156 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1159 /* test a negative drive number */
1160 SetLastError(0xdeadbeef);
1161 lstrcpyA(path
, "aaaaaaaaa");
1162 root
= PathBuildRootA(path
, -1);
1163 ok(root
== path
, "Expected root == path, got %p\n", root
);
1164 ok(!lstrcmpA(path
, "aaaaaaaaa") || !path
[0], /* Vista */
1165 "Expected aaaaaaaaa or empty string, got %s\n", path
);
1166 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1168 /* test a drive number greater than 25 */
1169 SetLastError(0xdeadbeef);
1170 lstrcpyA(path
, "aaaaaaaaa");
1171 root
= PathBuildRootA(path
, 26);
1172 ok(root
== path
, "Expected root == path, got %p\n", root
);
1173 ok(!lstrcmpA(path
, "aaaaaaaaa") || !path
[0], /* Vista */
1174 "Expected aaaaaaaaa or empty string, got %s\n", path
);
1175 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1177 /* length of path is less than 4 */
1178 SetLastError(0xdeadbeef);
1179 lstrcpyA(path
, "aa");
1180 root
= PathBuildRootA(path
, 0);
1181 ok(root
== path
, "Expected root == path, got %p\n", root
);
1182 ok(!lstrcmpA(path
, "A:\\"), "Expected A:\\, got %s\n", path
);
1183 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1186 SetLastError(0xdeadbeef);
1187 root
= PathBuildRootA(NULL
, 0);
1188 ok(root
== NULL
, "Expected root == NULL, got %p\n", root
);
1189 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1192 static void test_PathCommonPrefixA(void)
1194 char path1
[MAX_PATH
], path2
[MAX_PATH
];
1198 /* test NULL path1 */
1199 SetLastError(0xdeadbeef);
1200 lstrcpyA(path2
, "C:\\");
1201 lstrcpyA(out
, "aaa");
1202 count
= PathCommonPrefixA(NULL
, path2
, out
);
1203 ok(count
== 0, "Expected 0, got %i\n", count
);
1206 ok(!lstrcmpA(out
, "aaa"), "Expected aaa, got %s\n", out
);
1208 ok(!lstrcmpA(path2
, "C:\\"), "Expected C:\\, got %s\n", path2
);
1209 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1211 /* test NULL path2 */
1212 SetLastError(0xdeadbeef);
1213 lstrcpyA(path1
, "C:\\");
1214 lstrcpyA(out
, "aaa");
1215 count
= PathCommonPrefixA(path1
, NULL
, out
);
1216 ok(count
== 0, "Expected 0, got %i\n", count
);
1219 ok(!lstrcmpA(out
, "aaa"), "Expected aaa, got %s\n", out
);
1221 ok(!lstrcmpA(path1
, "C:\\"), "Expected C:\\, got %s\n", path1
);
1222 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1224 /* test empty path1 */
1225 SetLastError(0xdeadbeef);
1227 lstrcpyA(path2
, "C:\\");
1228 lstrcpyA(out
, "aaa");
1229 count
= PathCommonPrefixA(path1
, path2
, out
);
1230 ok(count
== 0, "Expected 0, got %i\n", count
);
1231 ok(!out
[0], "Expected 0 length out, got %i\n", lstrlenA(out
));
1232 ok(!path1
[0], "Expected 0 length path1, got %i\n", lstrlenA(path1
));
1233 ok(!lstrcmpA(path2
, "C:\\"), "Expected C:\\, got %s\n", path2
);
1234 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1236 /* test empty path1 */
1237 SetLastError(0xdeadbeef);
1239 lstrcpyA(path1
, "C:\\");
1240 lstrcpyA(out
, "aaa");
1241 count
= PathCommonPrefixA(path1
, path2
, out
);
1242 ok(count
== 0, "Expected 0, got %i\n", count
);
1243 ok(!out
[0], "Expected 0 length out, got %i\n", lstrlenA(out
));
1244 ok(!path2
[0], "Expected 0 length path2, got %i\n", lstrlenA(path2
));
1245 ok(!lstrcmpA(path1
, "C:\\"), "Expected C:\\, got %s\n", path1
);
1246 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1248 /* paths are legit, out is NULL */
1249 SetLastError(0xdeadbeef);
1250 lstrcpyA(path1
, "C:\\");
1251 lstrcpyA(path2
, "C:\\");
1252 count
= PathCommonPrefixA(path1
, path2
, NULL
);
1253 ok(count
== 3, "Expected 3, got %i\n", count
);
1254 ok(!lstrcmpA(path1
, "C:\\"), "Expected C:\\, got %s\n", path1
);
1255 ok(!lstrcmpA(path2
, "C:\\"), "Expected C:\\, got %s\n", path2
);
1256 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1258 /* all parameters legit */
1259 SetLastError(0xdeadbeef);
1260 lstrcpyA(path1
, "C:\\");
1261 lstrcpyA(path2
, "C:\\");
1262 lstrcpyA(out
, "aaa");
1263 count
= PathCommonPrefixA(path1
, path2
, out
);
1264 ok(count
== 3, "Expected 3, got %i\n", count
);
1265 ok(!lstrcmpA(path1
, "C:\\"), "Expected C:\\, got %s\n", path1
);
1266 ok(!lstrcmpA(path2
, "C:\\"), "Expected C:\\, got %s\n", path2
);
1267 ok(!lstrcmpA(out
, "C:\\"), "Expected C:\\, got %s\n", out
);
1268 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1270 /* path1 and path2 not the same, but common prefix */
1271 SetLastError(0xdeadbeef);
1272 lstrcpyA(path1
, "C:\\one\\two");
1273 lstrcpyA(path2
, "C:\\one\\three");
1274 lstrcpyA(out
, "aaa");
1275 count
= PathCommonPrefixA(path1
, path2
, out
);
1276 ok(count
== 6, "Expected 6, got %i\n", count
);
1277 ok(!lstrcmpA(path1
, "C:\\one\\two"), "Expected C:\\one\\two, got %s\n", path1
);
1278 ok(!lstrcmpA(path2
, "C:\\one\\three"), "Expected C:\\one\\three, got %s\n", path2
);
1279 ok(!lstrcmpA(out
, "C:\\one"), "Expected C:\\one, got %s\n", out
);
1280 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1283 SetLastError(0xdeadbeef);
1284 lstrcpyA(path1
, "one\\.two");
1285 lstrcpyA(path2
, "one\\.three");
1286 lstrcpyA(out
, "aaa");
1287 count
= PathCommonPrefixA(path1
, path2
, out
);
1288 ok(count
== 3, "Expected 3, got %i\n", count
);
1289 ok(!lstrcmpA(path1
, "one\\.two"), "Expected one\\.two, got %s\n", path1
);
1290 ok(!lstrcmpA(path2
, "one\\.three"), "Expected one\\.three, got %s\n", path2
);
1291 ok(!lstrcmpA(out
, "one"), "Expected one, got %s\n", out
);
1292 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1295 SetLastError(0xdeadbeef);
1296 lstrcpyA(path1
, "one\\..two");
1297 lstrcpyA(path2
, "one\\..three");
1298 lstrcpyA(out
, "aaa");
1299 count
= PathCommonPrefixA(path1
, path2
, out
);
1300 ok(count
== 3, "Expected 3, got %i\n", count
);
1301 ok(!lstrcmpA(path1
, "one\\..two"), "Expected one\\..two, got %s\n", path1
);
1302 ok(!lstrcmpA(path2
, "one\\..three"), "Expected one\\..three, got %s\n", path2
);
1303 ok(!lstrcmpA(out
, "one"), "Expected one, got %s\n", out
);
1304 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1306 /* try ... prefix */
1307 SetLastError(0xdeadbeef);
1308 lstrcpyA(path1
, "one\\...two");
1309 lstrcpyA(path2
, "one\\...three");
1310 lstrcpyA(out
, "aaa");
1311 count
= PathCommonPrefixA(path1
, path2
, out
);
1312 ok(count
== 3, "Expected 3, got %i\n", count
);
1313 ok(!lstrcmpA(path1
, "one\\...two"), "Expected one\\...two, got %s\n", path1
);
1314 ok(!lstrcmpA(path2
, "one\\...three"), "Expected one\\...three, got %s\n", path2
);
1315 ok(!lstrcmpA(out
, "one"), "Expected one, got %s\n", out
);
1316 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1319 SetLastError(0xdeadbeef);
1320 lstrcpyA(path1
, "one\\.\\two");
1321 lstrcpyA(path2
, "one\\.\\three");
1322 lstrcpyA(out
, "aaa");
1323 count
= PathCommonPrefixA(path1
, path2
, out
);
1324 ok(count
== 5, "Expected 5, got %i\n", count
);
1325 ok(!lstrcmpA(path1
, "one\\.\\two"), "Expected one\\.\\two, got %s\n", path1
);
1326 ok(!lstrcmpA(path2
, "one\\.\\three"), "Expected one\\.\\three, got %s\n", path2
);
1327 ok(!lstrcmpA(out
, "one\\."), "Expected one\\., got %s\n", out
);
1328 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1330 /* try ..\ prefix */
1331 SetLastError(0xdeadbeef);
1332 lstrcpyA(path1
, "one\\..\\two");
1333 lstrcpyA(path2
, "one\\..\\three");
1334 lstrcpyA(out
, "aaa");
1335 count
= PathCommonPrefixA(path1
, path2
, out
);
1336 ok(count
== 6, "Expected 6, got %i\n", count
);
1337 ok(!lstrcmpA(path1
, "one\\..\\two"), "Expected one\\..\\two, got %s\n", path1
);
1338 ok(!lstrcmpA(path2
, "one\\..\\three"), "Expected one\\..\\three, got %s\n", path2
);
1339 ok(!lstrcmpA(out
, "one\\.."), "Expected one\\.., got %s\n", out
);
1340 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1342 /* try ...\\ prefix */
1343 SetLastError(0xdeadbeef);
1344 lstrcpyA(path1
, "one\\...\\two");
1345 lstrcpyA(path2
, "one\\...\\three");
1346 lstrcpyA(out
, "aaa");
1347 count
= PathCommonPrefixA(path1
, path2
, out
);
1348 ok(count
== 7, "Expected 7, got %i\n", count
);
1349 ok(!lstrcmpA(path1
, "one\\...\\two"), "Expected one\\...\\two, got %s\n", path1
);
1350 ok(!lstrcmpA(path2
, "one\\...\\three"), "Expected one\\...\\three, got %s\n", path2
);
1351 ok(!lstrcmpA(out
, "one\\..."), "Expected one\\..., got %s\n", out
);
1352 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1354 /* try prefix that is not an msdn labeled prefix type */
1355 SetLastError(0xdeadbeef);
1356 lstrcpyA(path1
, "same");
1357 lstrcpyA(path2
, "same");
1358 lstrcpyA(out
, "aaa");
1359 count
= PathCommonPrefixA(path1
, path2
, out
);
1360 ok(count
== 4, "Expected 4, got %i\n", count
);
1361 ok(!lstrcmpA(path1
, "same"), "Expected same, got %s\n", path1
);
1362 ok(!lstrcmpA(path2
, "same"), "Expected same, got %s\n", path2
);
1363 ok(!lstrcmpA(out
, "same"), "Expected same, got %s\n", out
);
1364 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1366 /* try . after directory */
1367 SetLastError(0xdeadbeef);
1368 lstrcpyA(path1
, "one\\mid.\\two");
1369 lstrcpyA(path2
, "one\\mid.\\three");
1370 lstrcpyA(out
, "aaa");
1371 count
= PathCommonPrefixA(path1
, path2
, out
);
1372 ok(count
== 8, "Expected 8, got %i\n", count
);
1373 ok(!lstrcmpA(path1
, "one\\mid.\\two"), "Expected one\\mid.\\two, got %s\n", path1
);
1374 ok(!lstrcmpA(path2
, "one\\mid.\\three"), "Expected one\\mid.\\three, got %s\n", path2
);
1375 ok(!lstrcmpA(out
, "one\\mid."), "Expected one\\mid., got %s\n", out
);
1376 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1378 /* try . in the middle of a directory */
1379 SetLastError(0xdeadbeef);
1380 lstrcpyA(path1
, "one\\mid.end\\two");
1381 lstrcpyA(path2
, "one\\mid.end\\three");
1382 lstrcpyA(out
, "aaa");
1383 count
= PathCommonPrefixA(path1
, path2
, out
);
1384 ok(count
== 11, "Expected 11, got %i\n", count
);
1385 ok(!lstrcmpA(path1
, "one\\mid.end\\two"), "Expected one\\mid.end\\two, got %s\n", path1
);
1386 ok(!lstrcmpA(path2
, "one\\mid.end\\three"), "Expected one\\mid.end\\three, got %s\n", path2
);
1387 ok(!lstrcmpA(out
, "one\\mid.end"), "Expected one\\mid.end, got %s\n", out
);
1388 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1390 /* try comparing a .. with the expanded path */
1391 SetLastError(0xdeadbeef);
1392 lstrcpyA(path1
, "one\\..\\two");
1393 lstrcpyA(path2
, "two");
1394 lstrcpyA(out
, "aaa");
1395 count
= PathCommonPrefixA(path1
, path2
, out
);
1396 ok(count
== 0, "Expected 0, got %i\n", count
);
1397 ok(!lstrcmpA(path1
, "one\\..\\two"), "Expected one\\..\\two, got %s\n", path1
);
1398 ok(!lstrcmpA(path2
, "two"), "Expected two, got %s\n", path2
);
1399 ok(!out
[0], "Expected 0 length out, got %i\n", lstrlenA(out
));
1400 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1403 static void test_PathUnquoteSpaces(void)
1406 for (i
= 0; i
< ARRAY_SIZE(TEST_PATH_UNQUOTE_SPACES
); i
++)
1408 char *path
= strdupA(TEST_PATH_UNQUOTE_SPACES
[i
].path
);
1409 WCHAR
*pathW
= GetWideString(TEST_PATH_UNQUOTE_SPACES
[i
].path
);
1410 WCHAR
*resultW
= GetWideString(TEST_PATH_UNQUOTE_SPACES
[i
].result
);
1412 PathUnquoteSpacesA(path
);
1413 ok(!strcmp(path
, TEST_PATH_UNQUOTE_SPACES
[i
].result
), "%s (A): got %s expected %s\n",
1414 TEST_PATH_UNQUOTE_SPACES
[i
].path
, path
,
1415 TEST_PATH_UNQUOTE_SPACES
[i
].result
);
1417 PathUnquoteSpacesW(pathW
);
1418 ok(!lstrcmpW(pathW
, resultW
), "%s (W): strings differ\n",
1419 TEST_PATH_UNQUOTE_SPACES
[i
].path
);
1420 FreeWideString(pathW
);
1421 FreeWideString(resultW
);
1422 HeapFree(GetProcessHeap(), 0, path
);
1426 static void test_PathGetDriveNumber(void)
1428 static const CHAR test1A
[] = "a:\\test.file";
1429 static const CHAR test2A
[] = "file:////b:\\test.file";
1430 static const CHAR test3A
[] = "file:///c:\\test.file";
1431 static const CHAR test4A
[] = "file:\\\\c:\\test.file";
1432 static const CHAR test5A
[] = "\\\\?\\C:\\dir\\file.txt";
1433 static const WCHAR test1W
[] =
1435 static const WCHAR test5W
[] =
1436 {'\\','\\','?','\\','C',':','\\','d','i','r','\\','f','i','l','e',0};
1439 SetLastError(0xdeadbeef);
1440 ret
= PathGetDriveNumberA(NULL
);
1441 ok(ret
== -1, "got %d\n", ret
);
1442 ok(GetLastError() == 0xdeadbeef, "got %d\n", GetLastError());
1444 ret
= PathGetDriveNumberA(test1A
);
1445 ok(ret
== 0, "got %d\n", ret
);
1446 ret
= PathGetDriveNumberW(test1W
);
1447 ok(ret
== 0, "got %d\n", ret
);
1448 ret
= PathGetDriveNumberA(test2A
);
1449 ok(ret
== -1, "got %d\n", ret
);
1450 ret
= PathGetDriveNumberA(test3A
);
1451 ok(ret
== -1, "got %d\n", ret
);
1452 ret
= PathGetDriveNumberA(test4A
);
1453 ok(ret
== -1, "got %d\n", ret
);
1455 ret
= PathGetDriveNumberA(test5A
);
1456 ok(ret
== -1, "got %d\n", ret
);
1457 ret
= PathGetDriveNumberW(test5W
);
1458 ok(ret
== 2 || broken(ret
== -1) /* winxp */, "got = %d\n", ret
);
1461 static void test_PathUnExpandEnvStrings(void)
1463 static const WCHAR sysrootW
[] = {'%','S','y','s','t','e','m','R','o','o','t','%',0};
1464 static const WCHAR sysdriveW
[] = {'%','S','y','s','t','e','m','D','r','i','v','e','%',0};
1465 static const WCHAR nonpathW
[] = {'p','a','t','h',0};
1466 static const WCHAR computernameW
[] = {'C','O','M','P','U','T','E','R','N','A','M','E',0};
1467 static const char sysrootA
[] = "%SystemRoot%";
1468 static const char sysdriveA
[] = "%SystemDrive%";
1469 WCHAR pathW
[MAX_PATH
], buffW
[MAX_PATH
], sysdrvW
[3], envvarW
[30];
1470 char path
[MAX_PATH
], buff
[MAX_PATH
], sysdrvA
[3], envvarA
[30];
1474 if (!pPathUnExpandEnvStringsA
|| !pPathUnExpandEnvStringsW
)
1476 win_skip("PathUnExpandEnvStrings not available\n");
1480 /* The value of ComputerName is not a path */
1481 ret
= GetEnvironmentVariableA("COMPUTERNAME", envvarA
, sizeof(envvarA
));
1482 ok(ret
, "got %d\n", ret
);
1483 SetLastError(0xdeadbeef);
1484 ret
= pPathUnExpandEnvStringsA(envvarA
, buff
, sizeof(buff
));
1485 ok(!ret
&& GetLastError() == 0xdeadbeef, "got %d, error %d\n", ret
, GetLastError());
1487 ret
= GetEnvironmentVariableW(computernameW
, envvarW
, ARRAY_SIZE(envvarW
));
1488 ok(ret
, "got %d\n", ret
);
1489 SetLastError(0xdeadbeef);
1490 ret
= pPathUnExpandEnvStringsW(envvarW
, buffW
, ARRAY_SIZE(buffW
));
1491 ok(!ret
&& GetLastError() == 0xdeadbeef, "got %d, error %d\n", ret
, GetLastError());
1493 /* something that can't be represented with env var */
1494 strcpy(path
, "somepath_name");
1496 SetLastError(0xdeadbeef);
1497 ret
= pPathUnExpandEnvStringsA(path
, buff
, sizeof(buff
));
1498 ok(!ret
&& GetLastError() == 0xdeadbeef, "got %d, error %d\n", ret
, GetLastError());
1499 ok(buff
[0] == 'x', "wrong return string %s\n", buff
);
1501 len
= GetSystemDirectoryA(path
, MAX_PATH
);
1502 ok(len
> 0, "failed to get sysdir\n");
1504 sysdrvA
[0] = path
[0];
1505 strcpy(&sysdrvA
[1], ":");
1507 /* buffer size is not enough */
1509 SetLastError(0xdeadbeef);
1510 ret
= pPathUnExpandEnvStringsA(path
, buff
, 5);
1511 ok(!ret
&& GetLastError() == 0xdeadbeef, "got %d\n", ret
);
1512 ok(buff
[0] == 'x', "wrong return string %s\n", buff
);
1514 /* buffer size is enough to hold variable name only */
1516 SetLastError(0xdeadbeef);
1517 ret
= pPathUnExpandEnvStringsA(path
, buff
, sizeof(sysrootA
));
1518 ok(!ret
&& GetLastError() == 0xdeadbeef, "got %d, error %d\n", ret
, GetLastError());
1519 ok(buff
[0] == 'x', "wrong return string %s\n", buff
);
1523 ret
= pPathUnExpandEnvStringsA(path
, buff
, sizeof(buff
));
1524 ok(ret
, "got %d\n", ret
);
1525 ok(!strncmp(buff
, sysrootA
, sizeof(sysrootA
)-1), "wrong return string %s\n", buff
);
1527 /* expanded value occurs multiple times */
1528 /* for drive C: it unexpands it like 'C:C:' -> '%SystemDrive%C:' */
1530 strcpy(path
, sysdrvA
);
1531 strcat(path
, sysdrvA
);
1532 ret
= pPathUnExpandEnvStringsA(path
, buff
, sizeof(buff
));
1533 ok(ret
, "got %d\n", ret
);
1534 /* expected string */
1535 strcpy(path
, sysdriveA
);
1536 strcat(path
, sysdrvA
);
1537 ok(!strcmp(buff
, path
), "wrong unexpanded string %s, expected %s\n", buff
, path
);
1539 /* now with altered variable */
1540 ret
= GetEnvironmentVariableA("SystemDrive", envvarA
, sizeof(envvarA
));
1541 ok(ret
, "got %d\n", ret
);
1543 ret
= SetEnvironmentVariableA("SystemDrive", "WW");
1544 ok(ret
, "got %d\n", ret
);
1546 /* variables are not cached */
1547 strcpy(path
, sysdrvA
);
1548 strcat(path
, sysdrvA
);
1549 SetLastError(0xdeadbeef);
1550 ret
= pPathUnExpandEnvStringsA(path
, buff
, sizeof(buff
));
1551 ok(!ret
&& GetLastError() == 0xdeadbeef, "got %d, error %d\n", ret
, GetLastError());
1553 ret
= SetEnvironmentVariableA("SystemDrive", envvarA
);
1554 ok(ret
, "got %d\n", ret
);
1556 /* PathUnExpandEnvStringsW */
1558 /* something that can't be represented with env var */
1559 lstrcpyW(pathW
, nonpathW
);
1560 buffW
[0] = 'x'; buffW
[1] = 0;
1561 SetLastError(0xdeadbeef);
1562 ret
= pPathUnExpandEnvStringsW(pathW
, buffW
, ARRAY_SIZE(buffW
));
1563 ok(!ret
&& GetLastError() == 0xdeadbeef, "got %d, error %d\n", ret
, GetLastError());
1564 ok(buffW
[0] == 'x', "wrong return string %s\n", wine_dbgstr_w(buffW
));
1566 len
= GetSystemDirectoryW(pathW
, MAX_PATH
);
1567 ok(len
> 0, "failed to get sysdir\n");
1569 sysdrvW
[0] = pathW
[0];
1573 /* buffer size is not enough */
1574 buffW
[0] = 'x'; buffW
[1] = 0;
1575 SetLastError(0xdeadbeef);
1576 ret
= pPathUnExpandEnvStringsW(pathW
, buffW
, 5);
1577 ok(!ret
&& GetLastError() == 0xdeadbeef, "got %d, error %d\n", ret
, GetLastError());
1578 ok(buffW
[0] == 'x', "wrong return string %s\n", wine_dbgstr_w(buffW
));
1580 /* buffer size is enough to hold variable name only */
1581 buffW
[0] = 'x'; buffW
[1] = 0;
1582 SetLastError(0xdeadbeef);
1583 ret
= pPathUnExpandEnvStringsW(pathW
, buffW
, ARRAY_SIZE(sysrootW
));
1584 ok(!ret
&& GetLastError() == 0xdeadbeef, "got %d, error %d\n", ret
, GetLastError());
1585 ok(buffW
[0] == 'x', "wrong return string %s\n", wine_dbgstr_w(buffW
));
1589 ret
= pPathUnExpandEnvStringsW(pathW
, buffW
, ARRAY_SIZE(buffW
));
1590 ok(ret
, "got %d\n", ret
);
1591 ok(!memcmp(buffW
, sysrootW
, sizeof(sysrootW
) - sizeof(WCHAR
)), "wrong return string %s\n", wine_dbgstr_w(buffW
));
1593 /* expanded value occurs multiple times */
1594 /* for drive C: it unexpands it like 'C:C:' -> '%SystemDrive%C:' */
1596 lstrcpyW(pathW
, sysdrvW
);
1597 lstrcatW(pathW
, sysdrvW
);
1598 ret
= pPathUnExpandEnvStringsW(pathW
, buffW
, ARRAY_SIZE(buffW
));
1599 ok(ret
, "got %d\n", ret
);
1600 /* expected string */
1601 lstrcpyW(pathW
, sysdriveW
);
1602 lstrcatW(pathW
, sysdrvW
);
1603 ok(!lstrcmpW(buffW
, pathW
), "wrong unexpanded string %s, expected %s\n", wine_dbgstr_w(buffW
), wine_dbgstr_w(pathW
));
1606 static const struct {
1609 } test_path_is_relative
[] = {
1613 {"\\\\folder\\test.txt", FALSE
},
1614 {"file://folder/test.txt", TRUE
},
1615 {"C:\\test.txt", FALSE
},
1616 {"file:///C:/test.txt", TRUE
}
1619 static void test_PathIsRelativeA(void)
1624 if (!pPathIsRelativeA
) {
1625 win_skip("PathIsRelativeA not available\n");
1629 num
= ARRAY_SIZE(test_path_is_relative
);
1630 for (i
= 0; i
< num
; i
++) {
1631 ret
= pPathIsRelativeA(test_path_is_relative
[i
].path
);
1632 ok(ret
== test_path_is_relative
[i
].expect
,
1633 "PathIsRelativeA(\"%s\") expects %d, got %d.\n",
1634 test_path_is_relative
[i
].path
, test_path_is_relative
[i
].expect
, ret
);
1638 static void test_PathIsRelativeW(void)
1644 if (!pPathIsRelativeW
) {
1645 win_skip("PathIsRelativeW not available\n");
1649 num
= ARRAY_SIZE(test_path_is_relative
);
1650 for (i
= 0; i
< num
; i
++) {
1651 path
= GetWideString(test_path_is_relative
[i
].path
);
1653 ret
= pPathIsRelativeW(path
);
1654 ok(ret
== test_path_is_relative
[i
].expect
,
1655 "PathIsRelativeW(\"%s\") expects %d, got %d.\n",
1656 test_path_is_relative
[i
].path
, test_path_is_relative
[i
].expect
, ret
);
1658 FreeWideString(path
);
1662 static void test_PathStripPathA(void)
1664 const char const_path
[] = "test";
1665 char path
[] = "short//path\\file.txt";
1667 PathStripPathA(path
);
1668 ok(!strcmp(path
, "file.txt"), "path = %s\n", path
);
1670 /* following test should not crash */
1671 /* LavView 2013 depends on that behaviour */
1672 PathStripPathA((char*)const_path
);
1675 static void test_PathUndecorate(void)
1677 static const struct {
1679 const WCHAR
*expect
;
1681 { L
"c:\\test\\a[123]", L
"c:\\test\\a" },
1682 { L
"c:\\test\\a[123].txt", L
"c:\\test\\a.txt" },
1683 { L
"c:\\test\\a.txt[123]", L
"c:\\test\\a.txt[123]" },
1684 { L
"c:\\test\\a[123a].txt", L
"c:\\test\\a[123a].txt" },
1685 { L
"c:\\test\\a[a123].txt", L
"c:\\test\\a[a123].txt" },
1686 { L
"c:\\test\\a[12\x0660].txt", L
"c:\\test\\a[12\x0660].txt" },
1687 { L
"c:\\test\\a[12]file", L
"c:\\test\\a[12]file" },
1688 { L
"c:\\test[123]\\a", L
"c:\\test[123]\\a" },
1689 { L
"c:\\test\\[123]", L
"c:\\test\\[123]" },
1690 { L
"a[123]", L
"a" },
1692 { L
"[123]", L
"[123]" }
1694 char bufa
[MAX_PATH
], expect
[MAX_PATH
];
1695 WCHAR buf
[MAX_PATH
];
1698 for (i
= 0; i
< ARRAY_SIZE(tests
); i
++)
1700 wcscpy(buf
, tests
[i
].path
);
1701 PathUndecorateW(buf
);
1702 ok(!wcscmp(buf
, tests
[i
].expect
), "PathUndecorateW returned %s, expected %s\n",
1703 wine_dbgstr_w(buf
), wine_dbgstr_w(tests
[i
].expect
));
1705 WideCharToMultiByte(CP_ACP
, WC_NO_BEST_FIT_CHARS
, tests
[i
].path
, -1, bufa
, ARRAY_SIZE(bufa
), "?", NULL
);
1706 WideCharToMultiByte(CP_ACP
, WC_NO_BEST_FIT_CHARS
, tests
[i
].expect
, -1, expect
, ARRAY_SIZE(expect
), "?", NULL
);
1707 PathUndecorateA(bufa
);
1708 ok(!strcmp(bufa
, expect
), "PathUndecorateA returned %s, expected %s\n", bufa
, expect
);
1711 PathUndecorateA(NULL
);
1712 PathUndecorateW(NULL
);
1717 HMODULE hShlwapi
= GetModuleHandleA("shlwapi.dll");
1719 /* SHCreateStreamOnFileEx was introduced in shlwapi v6.0 */
1720 if(!GetProcAddress(hShlwapi
, "SHCreateStreamOnFileEx")){
1721 win_skip("Too old shlwapi version\n");
1725 pPathCreateFromUrlA
= (void*)GetProcAddress(hShlwapi
, "PathCreateFromUrlA");
1726 pPathCreateFromUrlW
= (void*)GetProcAddress(hShlwapi
, "PathCreateFromUrlW");
1727 pPathCreateFromUrlAlloc
= (void*)GetProcAddress(hShlwapi
, "PathCreateFromUrlAlloc");
1728 pPathCombineW
= (void*)GetProcAddress(hShlwapi
, "PathCombineW");
1729 pPathIsValidCharA
= (void*)GetProcAddress(hShlwapi
, (LPSTR
)455);
1730 pPathIsValidCharW
= (void*)GetProcAddress(hShlwapi
, (LPSTR
)456);
1731 pPathAppendA
= (void*)GetProcAddress(hShlwapi
, "PathAppendA");
1732 pPathUnExpandEnvStringsA
= (void*)GetProcAddress(hShlwapi
, "PathUnExpandEnvStringsA");
1733 pPathUnExpandEnvStringsW
= (void*)GetProcAddress(hShlwapi
, "PathUnExpandEnvStringsW");
1734 pPathIsRelativeA
= (void*)GetProcAddress(hShlwapi
, "PathIsRelativeA");
1735 pPathIsRelativeW
= (void*)GetProcAddress(hShlwapi
, "PathIsRelativeW");
1737 test_PathSearchAndQualify();
1738 test_PathCreateFromUrl();
1741 test_PathAddBackslash();
1742 test_PathMakePretty();
1743 test_PathMatchSpec();
1745 test_PathIsValidCharA();
1746 test_PathIsValidCharW();
1748 test_PathCombineW();
1749 test_PathCombineA();
1751 test_PathCanonicalizeA();
1752 test_PathFindExtensionA();
1753 test_PathBuildRootA();
1754 test_PathCommonPrefixA();
1755 test_PathUnquoteSpaces();
1756 test_PathGetDriveNumber();
1757 test_PathUnExpandEnvStrings();
1758 test_PathIsRelativeA();
1759 test_PathIsRelativeW();
1760 test_PathStripPathA();
1761 test_PathUndecorate();