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
22 static BOOL (WINAPI
*pPathIsValidCharA
)(char,DWORD
);
23 static BOOL (WINAPI
*pPathIsValidCharW
)(WCHAR
,DWORD
);
24 static LPWSTR (WINAPI
*pPathCombineW
)(LPWSTR
, LPCWSTR
, LPCWSTR
);
25 static HRESULT (WINAPI
*pPathCreateFromUrlA
)(LPCSTR
, LPSTR
, LPDWORD
, DWORD
);
26 static HRESULT (WINAPI
*pPathCreateFromUrlW
)(LPCWSTR
, LPWSTR
, LPDWORD
, DWORD
);
27 static HRESULT (WINAPI
*pPathCreateFromUrlAlloc
)(LPCWSTR
, LPWSTR
*, DWORD
);
28 static BOOL (WINAPI
*pPathAppendA
)(LPSTR
, LPCSTR
);
29 static BOOL (WINAPI
*pPathUnExpandEnvStringsA
)(LPCSTR
, LPSTR
, UINT
);
30 static BOOL (WINAPI
*pPathUnExpandEnvStringsW
)(LPCWSTR
, LPWSTR
, UINT
);
31 static BOOL (WINAPI
*pPathIsRelativeA
)(LPCSTR
);
32 static BOOL (WINAPI
*pPathIsRelativeW
)(LPCWSTR
);
34 /* ################ */
40 } TEST_PATHFROMURL
[] = {
42 {"file:c:/foo/bar", "c:\\foo\\bar", S_OK
, 0},
43 {"file:c|/foo/bar", "c:\\foo\\bar", S_OK
, 0},
44 {"file:cx|/foo/bar", "cx|\\foo\\bar", S_OK
, 0},
45 {"file:c:foo/bar", "c:foo\\bar", S_OK
, 0},
46 {"file:c|foo/bar", "c:foo\\bar", S_OK
, 0},
47 {"file:c:/foo%20ba%2fr", "c:\\foo ba/r", S_OK
, 0},
48 {"file:foo%20ba%2fr", "foo ba/r", S_OK
, 0},
49 {"file:foo/bar/", "foo\\bar\\", S_OK
, 0},
51 /* 1 leading (back)slash */
52 {"file:/c:/foo/bar", "c:\\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:/cx|/foo/bar", "\\cx|\\foo\\bar", S_OK
, 0},
56 {"file:/c:foo/bar", "c:foo\\bar", S_OK
, 0},
57 {"file:/c|foo/bar", "c:foo\\bar", S_OK
, 0},
58 {"file:/c:/foo%20ba%2fr", "c:\\foo ba/r", S_OK
, 0},
59 {"file:/foo%20ba%2fr", "\\foo ba/r", S_OK
, 0},
60 {"file:/foo/bar/", "\\foo\\bar\\", S_OK
, 0},
62 /* 2 leading (back)slashes */
63 {"file://c:/foo/bar", "c:\\foo\\bar", S_OK
, 0},
64 {"file://c:/d:/foo/bar", "c:\\d:\\foo\\bar", S_OK
, 0},
65 {"file://c|/d|/foo/bar", "c:\\d|\\foo\\bar", S_OK
, 0},
66 {"file://cx|/foo/bar", "\\\\cx|\\foo\\bar", S_OK
, 0},
67 {"file://c:foo/bar", "c:foo\\bar", S_OK
, 0},
68 {"file://c|foo/bar", "c:foo\\bar", S_OK
, 0},
69 {"file://c:/foo%20ba%2fr", "c:\\foo%20ba%2fr", S_OK
, 0},
70 {"file://c%3a/foo/../bar", "\\\\c:\\foo\\..\\bar", S_OK
, 0},
71 {"file://c%7c/foo/../bar", "\\\\c|\\foo\\..\\bar", S_OK
, 0},
72 {"file://foo%20ba%2fr", "\\\\foo ba/r", S_OK
, 0},
73 {"file://localhost/c:/foo/bar", "c:\\foo\\bar", S_OK
, 0},
74 {"file://localhost/c:/foo%20ba%5Cr", "c:\\foo ba\\r", S_OK
, 0},
75 {"file://LocalHost/c:/foo/bar", "c:\\foo\\bar", S_OK
, 0},
76 {"file:\\\\localhost\\c:\\foo\\bar", "c:\\foo\\bar", S_OK
, 0},
77 {"file://incomplete", "\\\\incomplete", S_OK
, 0},
79 /* 3 leading (back)slashes (omitting hostname) */
80 {"file:///c:/foo/bar", "c:\\foo\\bar", S_OK
, 0},
81 {"File:///c:/foo/bar", "c:\\foo\\bar", S_OK
, 0},
82 {"file:///c:/foo%20ba%2fr", "c:\\foo ba/r", S_OK
, 0},
83 {"file:///foo%20ba%2fr", "\\foo ba/r", S_OK
, 0},
84 {"file:///foo/bar/", "\\foo\\bar\\", S_OK
, 0},
85 {"file:///localhost/c:/foo/bar", "\\localhost\\c:\\foo\\bar", S_OK
, 0},
87 /* 4 leading (back)slashes */
88 {"file:////c:/foo/bar", "c:\\foo\\bar", S_OK
, 0},
89 {"file:////c:/foo%20ba%2fr", "c:\\foo%20ba%2fr", S_OK
, 0},
90 {"file:////foo%20ba%2fr", "\\\\foo%20ba%2fr", S_OK
, 0},
92 /* 5 and more leading (back)slashes */
93 {"file://///c:/foo/bar", "\\\\c:\\foo\\bar", S_OK
, 0},
94 {"file://///c:/foo%20ba%2fr", "\\\\c:\\foo ba/r", S_OK
, 0},
95 {"file://///foo%20ba%2fr", "\\\\foo ba/r", S_OK
, 0},
96 {"file://////c:/foo/bar", "\\\\c:\\foo\\bar", S_OK
, 0},
98 /* Leading (back)slashes cannot be escaped */
99 {"file:%2f%2flocalhost%2fc:/foo/bar", "//localhost/c:\\foo\\bar", S_OK
, 0},
100 {"file:%5C%5Clocalhost%5Cc:/foo/bar", "\\\\localhost\\c:\\foo\\bar", S_OK
, 0},
102 /* Hostname handling */
103 {"file://l%6fcalhost/c:/foo/bar", "\\\\localhostc:\\foo\\bar", S_OK
, 0},
104 {"file://localhost:80/c:/foo/bar", "\\\\localhost:80c:\\foo\\bar", S_OK
, 0},
105 {"file://host/c:/foo/bar", "\\\\hostc:\\foo\\bar", S_OK
, 0},
106 {"file://host//c:/foo/bar", "\\\\host\\\\c:\\foo\\bar", S_OK
, 0},
107 {"file://host/\\c:/foo/bar", "\\\\host\\\\c:\\foo\\bar", S_OK
, 0},
108 {"file://host/c:foo/bar", "\\\\hostc:foo\\bar", S_OK
, 0},
109 {"file://host/foo/bar", "\\\\host\\foo\\bar", S_OK
, 0},
110 {"file:\\\\host\\c:\\foo\\bar", "\\\\hostc:\\foo\\bar", S_OK
, 0},
111 {"file:\\\\host\\ca\\foo\\bar", "\\\\host\\ca\\foo\\bar", S_OK
, 0},
112 {"file:\\\\host\\c|\\foo\\bar", "\\\\hostc|\\foo\\bar", S_OK
, 0},
113 {"file:\\%5Chost\\c:\\foo\\bar", "\\\\host\\c:\\foo\\bar", S_OK
, 0},
114 {"file:\\\\host\\cx:\\foo\\bar", "\\\\host\\cx:\\foo\\bar", S_OK
, 0},
115 {"file:///host/c:/foo/bar", "\\host\\c:\\foo\\bar", S_OK
, 0},
118 {"c:\\foo\\bar", NULL
, E_INVALIDARG
, 0},
119 {"foo/bar", NULL
, E_INVALIDARG
, 0},
120 {"http://foo/bar", NULL
, E_INVALIDARG
, 0},
128 } TEST_PATH_IS_URL
[] = {
129 {"http://foo/bar", TRUE
},
130 {"c:\\foo\\bar", FALSE
},
131 {"c:/foo/bar", FALSE
},
132 {"foo://foo/bar", TRUE
},
135 {"bogusscheme:", TRUE
},
136 {"http:partial", TRUE
},
137 {"www.winehq.org", FALSE
},
138 /* More examples that the user might enter as the browser start page */
139 {"winehq.org", FALSE
},
140 {"ftp.winehq.org", FALSE
},
141 {"http://winehq.org", TRUE
},
142 {"http://www.winehq.org", TRUE
},
143 {"https://winehq.org", TRUE
},
144 {"https://www.winehq.org", TRUE
},
145 {"ftp://winehq.org", TRUE
},
146 {"ftp://ftp.winehq.org", TRUE
},
147 {"file://does_not_exist.txt", TRUE
},
148 {"about:blank", TRUE
},
149 {"about:home", TRUE
},
150 {"about:mozilla", TRUE
},
151 /* scheme is case independent */
152 {"HTTP://www.winehq.org", TRUE
},
153 /* a space at the start is not allowed */
154 {" http://www.winehq.org", FALSE
},
159 static const struct {
162 } TEST_PATH_UNQUOTE_SPACES
[] = {
163 { "abcdef", "abcdef" },
164 { "\"abcdef\"", "abcdef" },
165 { "\"abcdef", "\"abcdef" },
166 { "abcdef\"", "abcdef\"" },
167 { "\"\"abcdef\"\"", "\"abcdef\"" },
168 { "abc\"def", "abc\"def" },
169 { "\"abc\"def", "\"abc\"def" },
170 { "\"abc\"def\"", "abc\"def" },
171 { "\'abcdef\'", "\'abcdef\'" },
176 /* ################ */
178 static LPWSTR
GetWideString(const char *src
)
185 ret
= HeapAlloc(GetProcessHeap(), 0, (2*INTERNET_MAX_URL_LENGTH
) * sizeof(WCHAR
));
187 MultiByteToWideChar(CP_ACP
, 0, src
, -1, ret
, INTERNET_MAX_URL_LENGTH
);
192 static void FreeWideString(LPWSTR wszString
)
194 HeapFree(GetProcessHeap(), 0, wszString
);
197 static LPSTR
strdupA(LPCSTR p
)
200 DWORD len
= (strlen(p
) + 1);
201 ret
= HeapAlloc(GetProcessHeap(), 0, len
);
206 /* ################ */
208 static void test_PathSearchAndQualify(void)
210 WCHAR path1
[] = {'c',':','\\','f','o','o',0};
211 WCHAR expect1
[] = {'c',':','\\','f','o','o',0};
212 WCHAR path2
[] = {'c',':','f','o','o',0};
213 WCHAR c_drive
[] = {'c',':',0};
214 WCHAR foo
[] = {'f','o','o',0};
215 WCHAR path3
[] = {'\\','f','o','o',0};
216 WCHAR winini
[] = {'w','i','n','.','i','n','i',0};
218 WCHAR cur_dir
[MAX_PATH
];
219 WCHAR dot
[] = {'.',0};
222 ok(PathSearchAndQualifyW(path1
, out
, MAX_PATH
) != 0,
223 "PathSearchAndQualify rets 0\n");
224 ok(!lstrcmpiW(out
, expect1
), "strings don't match\n");
227 ok(PathSearchAndQualifyW(path2
, out
, MAX_PATH
) != 0,
228 "PathSearchAndQualify rets 0\n");
229 GetFullPathNameW(c_drive
, MAX_PATH
, cur_dir
, NULL
);
230 PathAddBackslashW(cur_dir
);
231 lstrcatW(cur_dir
, foo
);
232 ok(!lstrcmpiW(out
, cur_dir
), "strings don't match\n");
235 ok(PathSearchAndQualifyW(foo
, out
, MAX_PATH
) != 0,
236 "PathSearchAndQualify rets 0\n");
237 GetFullPathNameW(dot
, 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(path3
, out
, MAX_PATH
) != 0,
244 "PathSearchAndQualify rets 0\n");
245 GetFullPathNameW(dot
, MAX_PATH
, cur_dir
, NULL
);
246 lstrcpyW(cur_dir
+ 2, path3
);
247 ok(!lstrcmpiW(out
, cur_dir
), "strings don't match\n");
250 ok(PathSearchAndQualifyW(winini
, out
, MAX_PATH
) != 0,
251 "PathSearchAndQualify rets 0\n");
252 if(!SearchPathW(NULL
, winini
, NULL
, MAX_PATH
, cur_dir
, NULL
))
253 GetFullPathNameW(winini
, MAX_PATH
, cur_dir
, NULL
);
254 ok(!lstrcmpiW(out
, cur_dir
), "strings don't match\n");
258 static void test_PathCreateFromUrl(void)
261 char ret_path
[INTERNET_MAX_URL_LENGTH
];
262 DWORD len
, len2
, ret
;
263 WCHAR ret_pathW
[INTERNET_MAX_URL_LENGTH
];
266 if (!pPathCreateFromUrlA
) {
267 win_skip("PathCreateFromUrlA not found\n");
271 /* Won't say how much is needed without a buffer */
273 ret
= pPathCreateFromUrlA("file://foo", NULL
, &len
, 0);
274 ok(ret
== E_INVALIDARG
, "got 0x%08x expected E_INVALIDARG\n", ret
);
275 ok(len
== 0xdeca, "got %x expected 0xdeca\n", len
);
277 /* Test the decoding itself */
278 for(i
= 0; i
< sizeof(TEST_PATHFROMURL
) / sizeof(TEST_PATHFROMURL
[0]); i
++) {
279 len
= INTERNET_MAX_URL_LENGTH
;
280 ret
= pPathCreateFromUrlA(TEST_PATHFROMURL
[i
].url
, ret_path
, &len
, 0);
281 todo_wine_if (TEST_PATHFROMURL
[i
].todo
& 0x1)
282 ok(ret
== TEST_PATHFROMURL
[i
].ret
, "ret %08x from url %s\n", ret
, TEST_PATHFROMURL
[i
].url
);
283 if(SUCCEEDED(ret
) && TEST_PATHFROMURL
[i
].path
) {
284 if(!(TEST_PATHFROMURL
[i
].todo
& 0x2)) {
285 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
);
286 ok(len
== strlen(ret_path
), "ret len %d from url %s\n", len
, TEST_PATHFROMURL
[i
].url
);
288 /* Wrong string, don't bother checking the length */
289 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
);
292 if (pPathCreateFromUrlW
) {
293 len
= INTERNET_MAX_URL_LENGTH
;
294 pathW
= GetWideString(TEST_PATHFROMURL
[i
].path
);
295 urlW
= GetWideString(TEST_PATHFROMURL
[i
].url
);
296 ret
= pPathCreateFromUrlW(urlW
, ret_pathW
, &len
, 0);
297 WideCharToMultiByte(CP_ACP
, 0, ret_pathW
, -1, ret_path
, sizeof(ret_path
),NULL
,NULL
);
298 todo_wine_if (TEST_PATHFROMURL
[i
].todo
& 0x1)
299 ok(ret
== TEST_PATHFROMURL
[i
].ret
, "ret %08x from url L\"%s\"\n", ret
, TEST_PATHFROMURL
[i
].url
);
300 if(SUCCEEDED(ret
) && TEST_PATHFROMURL
[i
].path
) {
301 if(!(TEST_PATHFROMURL
[i
].todo
& 0x2)) {
302 ok(!lstrcmpiW(ret_pathW
, pathW
), "got %s expected %s from url L\"%s\"\n",
303 ret_path
, TEST_PATHFROMURL
[i
].path
, TEST_PATHFROMURL
[i
].url
);
304 ok(len
== lstrlenW(ret_pathW
), "ret len %d from url L\"%s\"\n", len
, TEST_PATHFROMURL
[i
].url
);
306 /* Wrong string, don't bother checking the length */
307 ok(!lstrcmpiW(ret_pathW
, pathW
), "got %s expected %s from url L\"%s\"\n",
308 ret_path
, TEST_PATHFROMURL
[i
].path
, TEST_PATHFROMURL
[i
].url
);
313 /* Check what happens if the buffer is too small */
315 ret
= pPathCreateFromUrlW(urlW
, ret_pathW
, &len2
, 0);
316 ok(ret
== E_POINTER
, "ret %08x, expected E_POINTER from url %s\n", ret
, TEST_PATHFROMURL
[i
].url
);
317 todo_wine_if (TEST_PATHFROMURL
[i
].todo
& 0x4)
318 ok(len2
== len
+ 1, "got len = %d expected %d from url %s\n", len2
, len
+ 1, TEST_PATHFROMURL
[i
].url
);
321 FreeWideString(urlW
);
322 FreeWideString(pathW
);
326 if (pPathCreateFromUrlAlloc
)
328 static const WCHAR fileW
[] = {'f','i','l','e',':','/','/','f','o','o',0};
329 static const WCHAR fooW
[] = {'\\','\\','f','o','o',0};
332 ret
= pPathCreateFromUrlAlloc(fileW
, &pathW
, 0);
333 ok(ret
== S_OK
, "got 0x%08x expected S_OK\n", ret
);
334 ok(lstrcmpiW(pathW
, fooW
) == 0, "got %s expected %s\n", wine_dbgstr_w(pathW
), wine_dbgstr_w(fooW
));
335 HeapFree(GetProcessHeap(), 0, pathW
);
340 static void test_PathIsUrl(void)
345 for(i
= 0; i
< sizeof(TEST_PATH_IS_URL
)/sizeof(TEST_PATH_IS_URL
[0]); i
++) {
346 ret
= PathIsURLA(TEST_PATH_IS_URL
[i
].path
);
347 ok(ret
== TEST_PATH_IS_URL
[i
].expect
,
348 "returned %d from path %s, expected %d\n", ret
, TEST_PATH_IS_URL
[i
].path
,
349 TEST_PATH_IS_URL
[i
].expect
);
353 static const DWORD SHELL_charclass
[] =
355 0x00000000, 0x00000000, 0x00000000, 0x00000000,
356 0x00000000, 0x00000000, 0x00000000, 0x00000000,
357 0x00000000, 0x00000000, 0x00000000, 0x00000000,
358 0x00000000, 0x00000000, 0x00000000, 0x00000000,
359 0x00000000, 0x00000000, 0x00000000, 0x00000000,
360 0x00000000, 0x00000000, 0x00000000, 0x00000000,
361 0x00000000, 0x00000000, 0x00000000, 0x00000000,
362 0x00000000, 0x00000000, 0x00000000, 0x00000000,
363 0x00000080, 0x00000100, 0x00000200, 0x00000100,
364 0x00000100, 0x00000100, 0x00000100, 0x00000100,
365 0x00000100, 0x00000100, 0x00000002, 0x00000100,
366 0x00000040, 0x00000100, 0x00000004, 0x00000000,
367 0x00000100, 0x00000100, 0x00000100, 0x00000100,
368 0x00000100, 0x00000100, 0x00000100, 0x00000100,
369 0x00000100, 0x00000100, 0x00000010, 0x00000020,
370 0x00000000, 0x00000100, 0x00000000, 0x00000001,
371 0x00000100, 0xffffffff, 0xffffffff, 0xffffffff,
372 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
373 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
374 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
375 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
376 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
377 0xffffffff, 0xffffffff, 0xffffffff, 0x00000100,
378 0x00000008, 0x00000100, 0x00000100, 0x00000100,
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 0x00000000, 0x00000100, 0x00000100
389 static void test_PathIsValidCharA(void)
394 /* For whatever reason, PathIsValidCharA and PathAppendA share the same
395 * ordinal number in some native versions. Check this to prevent a crash.
397 if (!pPathIsValidCharA
|| pPathIsValidCharA
== (void*)pPathAppendA
)
399 win_skip("PathIsValidCharA isn't available\n");
403 for (c
= 0; c
< 0x7f; c
++)
405 ret
= pPathIsValidCharA( c
, ~0U );
406 ok ( ret
|| !SHELL_charclass
[c
], "PathIsValidCharA failed: 0x%02x got 0x%08x\n", c
, ret
);
409 for (c
= 0x7f; c
<= 0xff; c
++)
411 ret
= pPathIsValidCharA( c
, ~0U );
412 ok ( ret
, "PathIsValidCharA failed: 0x%02x got 0x%08x\n", c
, ret
);
416 static void test_PathIsValidCharW(void)
421 if (!pPathIsValidCharW
)
423 win_skip("PathIsValidCharW isn't available\n");
427 for (c
= 0; c
< 0x7f; c
++)
429 ret
= pPathIsValidCharW( c
, ~0U );
430 ok ( ret
|| !SHELL_charclass
[c
], "PathIsValidCharW failed: 0x%02x got 0x%08x\n", c
, ret
);
433 for (c
= 0x007f; c
<= 0xffff; c
++)
435 ret
= pPathIsValidCharW( c
, ~0U );
436 ok ( ret
, "PathIsValidCharW failed: 0x%02x got 0x%08x\n", c
, ret
);
440 static void test_PathMakePretty(void)
444 ok (PathMakePrettyA(NULL
) == FALSE
, "PathMakePretty: NULL path succeeded\n");
446 ok (PathMakePrettyA(buff
) == TRUE
, "PathMakePretty: Empty path failed\n");
448 strcpy(buff
, "C:\\A LONG FILE NAME WITH \\SPACES.TXT");
449 ok (PathMakePrettyA(buff
) == TRUE
, "PathMakePretty: Long UC name failed\n");
450 ok (strcmp(buff
, "C:\\a long file name with \\spaces.txt") == 0,
451 "PathMakePretty: Long UC name not changed\n");
453 strcpy(buff
, "C:\\A LONG FILE NAME WITH \\MixedCase.TXT");
454 ok (PathMakePrettyA(buff
) == FALSE
, "PathMakePretty: Long MC name succeeded\n");
455 ok (strcmp(buff
, "C:\\A LONG FILE NAME WITH \\MixedCase.TXT") == 0,
456 "PathMakePretty: Failed but modified path\n");
458 strcpy(buff
, "TEST");
459 ok (PathMakePrettyA(buff
) == TRUE
, "PathMakePretty: Short name failed\n");
460 ok (strcmp(buff
, "Test") == 0, "PathMakePretty: 1st char lowercased %s\n", buff
);
463 static void test_PathMatchSpec(void)
465 static const char file
[] = "c:\\foo\\bar\\filename.ext";
466 static const char spec1
[] = ".ext";
467 static const char spec2
[] = "*.ext";
468 static const char spec3
[] = "*.ext ";
469 static const char spec4
[] = " *.ext";
470 static const char spec5
[] = "* .ext";
471 static const char spec6
[] = "*. ext";
472 static const char spec7
[] = "* . ext";
473 static const char spec8
[] = "*.e?t";
474 static const char spec9
[] = "filename.ext";
475 static const char spec10
[] = "*bar\\filename.ext";
476 static const char spec11
[] = " foo; *.ext";
477 static const char spec12
[] = "*.ext;*.bar";
478 static const char spec13
[] = "*bar*";
480 ok (PathMatchSpecA(file
, spec1
) == FALSE
, "PathMatchSpec: Spec1 failed\n");
481 ok (PathMatchSpecA(file
, spec2
) == TRUE
, "PathMatchSpec: Spec2 failed\n");
482 ok (PathMatchSpecA(file
, spec3
) == FALSE
, "PathMatchSpec: Spec3 failed\n");
483 ok (PathMatchSpecA(file
, spec4
) == TRUE
, "PathMatchSpec: Spec4 failed\n");
484 todo_wine
ok (PathMatchSpecA(file
, spec5
) == TRUE
, "PathMatchSpec: Spec5 failed\n");
485 todo_wine
ok (PathMatchSpecA(file
, spec6
) == TRUE
, "PathMatchSpec: Spec6 failed\n");
486 ok (PathMatchSpecA(file
, spec7
) == FALSE
, "PathMatchSpec: Spec7 failed\n");
487 ok (PathMatchSpecA(file
, spec8
) == TRUE
, "PathMatchSpec: Spec8 failed\n");
488 ok (PathMatchSpecA(file
, spec9
) == FALSE
, "PathMatchSpec: Spec9 failed\n");
489 ok (PathMatchSpecA(file
, spec10
) == TRUE
, "PathMatchSpec: Spec10 failed\n");
490 ok (PathMatchSpecA(file
, spec11
) == TRUE
, "PathMatchSpec: Spec11 failed\n");
491 ok (PathMatchSpecA(file
, spec12
) == TRUE
, "PathMatchSpec: Spec12 failed\n");
492 ok (PathMatchSpecA(file
, spec13
) == TRUE
, "PathMatchSpec: Spec13 failed\n");
495 static void test_PathCombineW(void)
497 LPWSTR wszString
, wszString2
;
498 WCHAR wbuf
[MAX_PATH
+1], wstr1
[MAX_PATH
] = {'C',':','\\',0}, wstr2
[MAX_PATH
];
499 static const WCHAR expout
[] = {'C',':','\\','A','A',0};
504 win_skip("PathCombineW isn't available\n");
508 wszString2
= HeapAlloc(GetProcessHeap(), 0, MAX_PATH
* sizeof(WCHAR
));
511 wszString
= pPathCombineW(NULL
, NULL
, NULL
);
512 ok (wszString
== NULL
, "Expected a NULL return\n");
516 wszString
= pPathCombineW(wszString2
, NULL
, NULL
);
517 ok (wszString
== NULL
||
518 broken(wszString
[0] == 'a'), /* Win95 and some W2K */
519 "Expected a NULL return\n");
520 ok (wszString2
[0] == 0 ||
521 broken(wszString2
[0] == 'a'), /* Win95 and some W2K */
522 "Destination string not empty\n");
524 HeapFree(GetProcessHeap(), 0, wszString2
);
527 wstr2
[0] = wstr2
[1] = wstr2
[2] = 'A';
528 for (i
=3; i
<MAX_PATH
/2; i
++)
529 wstr1
[i
] = wstr2
[i
] = 'A';
530 wstr1
[(MAX_PATH
/2) - 1] = wstr2
[MAX_PATH
/2] = 0;
531 memset(wbuf
, 0xbf, sizeof(wbuf
));
533 wszString
= pPathCombineW(wbuf
, wstr1
, wstr2
);
534 ok(wszString
== NULL
, "Expected a NULL return\n");
536 broken(wbuf
[0] == 0xbfbf), /* Win95 and some W2K */
537 "Buffer contains data\n");
539 /* PathCombineW can be used in place */
542 ok(PathCombineW(wstr1
, wstr1
, wstr2
) == wstr1
, "Expected a wstr1 return\n");
543 ok(StrCmpW(wstr1
, expout
) == 0, "Unexpected PathCombine output\n");
547 #define LONG_LEN (MAX_PATH * 2)
548 #define HALF_LEN (MAX_PATH / 2 + 1)
550 static void test_PathCombineA(void)
554 char too_long
[LONG_LEN
];
555 char one
[HALF_LEN
], two
[HALF_LEN
];
558 SetLastError(0xdeadbeef);
559 str
= PathCombineA(NULL
, "C:\\", "one\\two\\three");
560 ok(str
== NULL
, "Expected NULL, got %p\n", str
);
561 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
563 /* try NULL dest and NULL directory */
564 SetLastError(0xdeadbeef);
565 str
= PathCombineA(NULL
, NULL
, "one\\two\\three");
566 ok(str
== NULL
, "Expected NULL, got %p\n", str
);
567 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
570 SetLastError(0xdeadbeef);
571 str
= PathCombineA(NULL
, NULL
, NULL
);
572 ok(str
== NULL
, "Expected NULL, got %p\n", str
);
573 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
575 /* try NULL file part */
576 SetLastError(0xdeadbeef);
577 lstrcpyA(dest
, "control");
578 str
= PathCombineA(dest
, "C:\\", NULL
);
579 ok(str
== dest
, "Expected str == dest, got %p\n", str
);
580 ok(!lstrcmpA(str
, "C:\\"), "Expected C:\\, got %s\n", str
);
581 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
583 /* try empty file part */
584 SetLastError(0xdeadbeef);
585 lstrcpyA(dest
, "control");
586 str
= PathCombineA(dest
, "C:\\", "");
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 directory and file part */
592 SetLastError(0xdeadbeef);
593 lstrcpyA(dest
, "control");
594 str
= PathCombineA(dest
, "", "");
595 ok(str
== dest
, "Expected str == dest, got %p\n", str
);
596 ok(!lstrcmpA(str
, "\\") ||
597 broken(!lstrcmpA(str
, "control")), /* Win95 and some W2K */
598 "Expected \\, got %s\n", str
);
599 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
601 /* try NULL directory */
602 SetLastError(0xdeadbeef);
603 lstrcpyA(dest
, "control");
604 str
= PathCombineA(dest
, NULL
, "one\\two\\three");
605 ok(str
== dest
, "Expected str == dest, got %p\n", str
);
606 ok(!lstrcmpA(str
, "one\\two\\three"), "Expected one\\two\\three, got %s\n", str
);
607 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
609 /* try NULL directory and empty file part */
610 SetLastError(0xdeadbeef);
611 lstrcpyA(dest
, "control");
612 str
= PathCombineA(dest
, NULL
, "");
613 ok(str
== dest
, "Expected str == dest, got %p\n", str
);
614 ok(!lstrcmpA(str
, "\\") ||
615 broken(!lstrcmpA(str
, "one\\two\\three")), /* Win95 and some W2K */
616 "Expected \\, got %s\n", str
);
617 ok(GetLastError() == 0xdeadbeef ||
618 broken(GetLastError() == ERROR_INVALID_PARAMETER
), /* Win95 */
619 "Expected 0xdeadbeef, got %d\n", GetLastError());
621 /* try NULL directory and file part */
622 SetLastError(0xdeadbeef);
623 lstrcpyA(dest
, "control");
624 str
= PathCombineA(dest
, NULL
, NULL
);
626 broken(str
!= NULL
), /* Win95 and some W2K */
627 "Expected str == NULL, got %p\n", str
);
628 ok(!dest
[0] || broken(!lstrcmpA(dest
, "control")), /* Win95 and some W2K */
629 "Expected 0 length, got %i\n", lstrlenA(dest
));
630 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
632 /* try directory without backslash */
633 SetLastError(0xdeadbeef);
634 lstrcpyA(dest
, "control");
635 str
= PathCombineA(dest
, "C:", "one\\two\\three");
636 ok(str
== dest
, "Expected str == dest, got %p\n", str
);
637 ok(!lstrcmpA(str
, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", str
);
638 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
640 /* try directory with 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 and file with prepended 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 previous test, with backslash appended as well */
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 a relative directory */
665 SetLastError(0xdeadbeef);
666 lstrcpyA(dest
, "control");
667 str
= PathCombineA(dest
, "relative\\dir", "\\one\\two\\three\\");
668 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
669 /* Vista fails which probably makes sense as PathCombineA expects an absolute dir */
672 ok(str
== dest
, "Expected str == dest, got %p\n", str
);
673 ok(!lstrcmpA(str
, "one\\two\\three\\"), "Expected one\\two\\three\\, got %s\n", str
);
676 /* try forward slashes */
677 SetLastError(0xdeadbeef);
678 lstrcpyA(dest
, "control");
679 str
= PathCombineA(dest
, "C:\\", "one/two/three\\");
680 ok(str
== dest
, "Expected str == dest, got %p\n", str
);
681 ok(!lstrcmpA(str
, "C:\\one/two/three\\"), "Expected one/two/three\\, got %s\n", str
);
682 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
684 /* try a really weird directory */
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 C:\\one\\two\\three\\, got %s\n", str
);
690 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
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:\\two\\three"), "Expected C:\\two\\three, got %s\n", str
);
698 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
701 /* try forward slashes */
702 SetLastError(0xdeadbeef);
703 lstrcpyA(dest
, "control");
704 str
= PathCombineA(dest
, "C:\\", "..");
705 ok(str
== dest
, "Expected str == dest, got %p\n", str
);
706 ok(!lstrcmpA(str
, "C:\\"), "Expected C:\\, got %s\n", str
);
707 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
709 memset(too_long
, 'a', LONG_LEN
);
710 too_long
[LONG_LEN
- 1] = '\0';
712 /* try a file longer than MAX_PATH */
713 SetLastError(0xdeadbeef);
714 lstrcpyA(dest
, "control");
715 str
= PathCombineA(dest
, "C:\\", too_long
);
716 ok(str
== NULL
, "Expected str == NULL, got %p\n", str
);
717 ok(!dest
[0] || broken(!lstrcmpA(dest
, "control")), /* Win95 and some W2K */
718 "Expected 0 length, got %i\n", lstrlenA(dest
));
719 todo_wine
ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
721 /* try a directory longer than MAX_PATH */
722 SetLastError(0xdeadbeef);
723 lstrcpyA(dest
, "control");
724 str
= PathCombineA(dest
, too_long
, "one\\two\\three");
725 ok(str
== NULL
, "Expected str == NULL, got %p\n", str
);
726 ok(!dest
[0] || broken(!lstrcmpA(dest
, "control")), /* Win95 and some W2K */
727 "Expected 0 length, got %i\n", lstrlenA(dest
));
728 todo_wine
ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
730 memset(one
, 'b', HALF_LEN
);
731 memset(two
, 'c', HALF_LEN
);
732 one
[HALF_LEN
- 1] = '\0';
733 two
[HALF_LEN
- 1] = '\0';
735 /* destination string is longer than MAX_PATH, but not the constituent parts */
736 SetLastError(0xdeadbeef);
737 lstrcpyA(dest
, "control");
738 str
= PathCombineA(dest
, one
, two
);
739 ok(str
== NULL
, "Expected str == NULL, got %p\n", str
);
740 ok(!dest
[0] || broken(!lstrcmpA(dest
, "control")), /* Win95 and some W2K */
741 "Expected 0 length, got %i\n", lstrlenA(dest
));
742 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
745 static void test_PathAddBackslash(void)
749 char too_long
[LONG_LEN
];
751 /* try a NULL path */
752 SetLastError(0xdeadbeef);
753 str
= PathAddBackslashA(NULL
);
754 ok(str
== NULL
, "Expected str == NULL, got %p\n", str
);
755 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
757 /* try an empty path */
759 SetLastError(0xdeadbeef);
760 str
= PathAddBackslashA(path
);
761 ok(str
== (path
+ lstrlenA(path
)), "Expected str to point to end of path, got %p\n", str
);
762 ok(!path
[0], "Expected empty string, got %i\n", lstrlenA(path
));
763 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
765 /* try a relative path */
766 lstrcpyA(path
, "one\\two");
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(!lstrcmpA(path
, "one\\two\\"), "Expected one\\two\\, got %s\n", path
);
771 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
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());
781 /* try just a space */
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
, " \\"), "Expected \\, got %s\n", path
);
787 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
789 /* path already has backslash */
790 lstrcpyA(path
, "C:\\one\\");
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
, "C:\\one\\"), "Expected C:\\one\\, got %s\n", path
);
795 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
797 memset(too_long
, 'a', LONG_LEN
);
798 too_long
[LONG_LEN
- 1] = '\0';
800 /* path is longer than MAX_PATH */
801 SetLastError(0xdeadbeef);
802 str
= PathAddBackslashA(too_long
);
803 ok(str
== NULL
, "Expected str == NULL, got %p\n", str
);
804 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
807 static void test_PathAppendA(void)
810 char too_long
[LONG_LEN
];
814 lstrcpyA(path
, "C:\\one");
816 /* try NULL pszMore */
817 SetLastError(0xdeadbeef);
818 res
= PathAppendA(path
, NULL
);
819 ok(!res
, "Expected failure\n");
820 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
821 ok(!lstrcmpA(path
, "C:\\one"), "Expected C:\\one, got %s\n", path
);
823 /* try empty pszMore */
824 SetLastError(0xdeadbeef);
825 res
= PathAppendA(path
, "");
826 ok(res
, "Expected success\n");
827 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
828 ok(!lstrcmpA(path
, "C:\\one"), "Expected C:\\one, got %s\n", path
);
830 /* try NULL pszPath */
831 SetLastError(0xdeadbeef);
832 res
= PathAppendA(NULL
, "two\\three");
833 ok(!res
, "Expected failure\n");
834 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
836 /* try empty pszPath */
838 SetLastError(0xdeadbeef);
839 res
= PathAppendA(path
, "two\\three");
840 ok(res
, "Expected success\n");
841 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
842 ok(!lstrcmpA(path
, "two\\three"), "Expected \\two\\three, got %s\n", path
);
844 /* try empty pszPath and empty pszMore */
846 SetLastError(0xdeadbeef);
847 res
= PathAppendA(path
, "");
848 ok(res
, "Expected success\n");
849 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
850 ok(!lstrcmpA(path
, "\\"), "Expected \\, got %s\n", path
);
852 /* try legit params */
853 lstrcpyA(path
, "C:\\one");
854 SetLastError(0xdeadbeef);
855 res
= PathAppendA(path
, "two\\three");
856 ok(res
, "Expected success\n");
857 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
858 ok(!lstrcmpA(path
, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", path
);
860 /* try pszPath with backslash after it */
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 pszMore with backslash before 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 after 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 spaces in pszPath */
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 pszMore */
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 /* pszPath is too long */
901 memset(too_long
, 'a', LONG_LEN
);
902 too_long
[LONG_LEN
- 1] = '\0';
903 SetLastError(0xdeadbeef);
904 res
= PathAppendA(too_long
, "two\\three");
905 ok(!res
, "Expected failure\n");
906 todo_wine
ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
907 ok(!too_long
[0] || broken(lstrlenA(too_long
) == (LONG_LEN
- 1)), /* Win95 and some W2K */
908 "Expected length of too_long to be zero, got %i\n", lstrlenA(too_long
));
910 /* pszMore is too long */
911 lstrcpyA(path
, "C:\\one");
912 memset(too_long
, 'a', LONG_LEN
);
913 too_long
[LONG_LEN
- 1] = '\0';
914 SetLastError(0xdeadbeef);
915 res
= PathAppendA(path
, too_long
);
916 ok(!res
, "Expected failure\n");
917 todo_wine
ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
918 ok(!path
[0] || broken(!lstrcmpA(path
, "C:\\one")), /* Win95 and some W2K */
919 "Expected length of path to be zero, got %i\n", lstrlenA(path
));
921 /* both params combined are too long */
922 memset(path
, 'a', HALF_LEN
);
923 path
[HALF_LEN
- 1] = '\0';
924 memset(half
, 'b', HALF_LEN
);
925 half
[HALF_LEN
- 1] = '\0';
926 SetLastError(0xdeadbeef);
927 res
= PathAppendA(path
, half
);
928 ok(!res
, "Expected failure\n");
929 ok(!path
[0] || broken(lstrlenA(path
) == (HALF_LEN
- 1)), /* Win95 and some W2K */
930 "Expected length of path to be zero, got %i\n", lstrlenA(path
));
931 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
934 static void test_PathCanonicalizeA(void)
936 char dest
[LONG_LEN
+ MAX_PATH
];
937 char too_long
[LONG_LEN
];
940 /* try a NULL source */
941 lstrcpyA(dest
, "test");
942 SetLastError(0xdeadbeef);
943 res
= PathCanonicalizeA(dest
, NULL
);
944 ok(!res
, "Expected failure\n");
945 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
946 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
947 ok(dest
[0] == 0 || !lstrcmpA(dest
, "test"),
948 "Expected either an empty string (Vista) or test, got %s\n", dest
);
950 /* try an empty source */
951 lstrcpyA(dest
, "test");
952 SetLastError(0xdeadbeef);
953 res
= PathCanonicalizeA(dest
, "");
954 ok(res
, "Expected success\n");
955 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
956 ok(!lstrcmpA(dest
, "\\") ||
957 broken(!lstrcmpA(dest
, "test")), /* Win95 and some W2K */
958 "Expected \\, got %s\n", dest
);
960 /* try a NULL dest */
961 SetLastError(0xdeadbeef);
962 res
= PathCanonicalizeA(NULL
, "C:\\");
963 ok(!res
, "Expected failure\n");
964 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
965 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
969 SetLastError(0xdeadbeef);
970 res
= PathCanonicalizeA(dest
, "C:\\");
971 ok(res
, "Expected success\n");
972 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
973 ok(!lstrcmpA(dest
, "C:\\"), "Expected C:\\, got %s\n", dest
);
975 /* try non-empty dest */
976 lstrcpyA(dest
, "test");
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 a space for source */
984 lstrcpyA(dest
, "test");
985 SetLastError(0xdeadbeef);
986 res
= PathCanonicalizeA(dest
, " ");
987 ok(res
, "Expected success\n");
988 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
989 ok(!lstrcmpA(dest
, " "), "Expected ' ', got %s\n", dest
);
991 /* try a relative path */
992 lstrcpyA(dest
, "test");
993 SetLastError(0xdeadbeef);
994 res
= PathCanonicalizeA(dest
, "one\\two");
995 ok(res
, "Expected success\n");
996 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
997 ok(!lstrcmpA(dest
, "one\\two"), "Expected one\\two, got %s\n", dest
);
999 /* try current dir and previous dir */
1000 lstrcpyA(dest
, "test");
1001 SetLastError(0xdeadbeef);
1002 res
= PathCanonicalizeA(dest
, "C:\\one\\.\\..\\two\\three\\..");
1003 ok(res
, "Expected success\n");
1004 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1005 ok(!lstrcmpA(dest
, "C:\\two"), "Expected C:\\two, got %s\n", dest
);
1007 /* try simple forward slashes */
1008 lstrcpyA(dest
, "test");
1009 SetLastError(0xdeadbeef);
1010 res
= PathCanonicalizeA(dest
, "C:\\one/two/three\\four/five\\six");
1011 ok(res
, "Expected success\n");
1012 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1013 ok(!lstrcmpA(dest
, "C:\\one/two/three\\four/five\\six"),
1014 "Expected C:\\one/two/three\\four/five\\six, got %s\n", dest
);
1016 /* try simple forward slashes with same dir */
1017 lstrcpyA(dest
, "test");
1018 SetLastError(0xdeadbeef);
1019 res
= PathCanonicalizeA(dest
, "C:\\one/.\\two");
1020 ok(res
, "Expected success\n");
1021 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1022 ok(!lstrcmpA(dest
, "C:\\one/.\\two"), "Expected C:\\one/.\\two, got %s\n", dest
);
1024 /* try simple forward slashes with change 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/.") ||
1031 !lstrcmpA(dest
, "C:\\one/"), /* Vista */
1032 "Expected \"C:\\one/.\" or \"C:\\one/\", got \"%s\"\n", dest
);
1034 /* try forward slashes with change dirs
1035 * NOTE: if there is a forward slash in between two backslashes,
1036 * everything in between the two backslashes is considered on dir
1038 lstrcpyA(dest
, "test");
1039 SetLastError(0xdeadbeef);
1040 res
= PathCanonicalizeA(dest
, "C:\\one/.\\..\\two/three\\..\\four/.five");
1041 ok(res
, "Expected success\n");
1042 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1043 ok(!lstrcmpA(dest
, "C:\\four/.five"), "Expected C:\\four/.five, got %s\n", dest
);
1045 /* try src is too long */
1046 memset(too_long
, 'a', LONG_LEN
);
1047 too_long
[LONG_LEN
- 1] = '\0';
1048 lstrcpyA(dest
, "test");
1049 SetLastError(0xdeadbeef);
1050 res
= PathCanonicalizeA(dest
, too_long
);
1052 broken(res
), /* Win95, some W2K and XP-SP1 */
1053 "Expected failure\n");
1056 ok(GetLastError() == 0xdeadbeef || GetLastError() == ERROR_FILENAME_EXCED_RANGE
/* Vista */,
1057 "Expected 0xdeadbeef or ERROR_FILENAME_EXCED_RANGE, got %d\n", GetLastError());
1059 ok(lstrlenA(too_long
) == LONG_LEN
- 1, "Expected length LONG_LEN - 1, got %i\n", lstrlenA(too_long
));
1062 static void test_PathFindExtensionA(void)
1065 char path
[MAX_PATH
];
1066 char too_long
[LONG_LEN
];
1068 /* try a NULL path */
1069 SetLastError(0xdeadbeef);
1070 ext
= PathFindExtensionA(NULL
);
1071 ok(ext
== NULL
, "Expected NULL, got %p\n", ext
);
1072 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1074 /* try an empty path */
1076 SetLastError(0xdeadbeef);
1077 ext
= PathFindExtensionA(path
);
1078 ok(ext
== path
, "Expected ext == path, got %p\n", ext
);
1079 ok(!ext
[0], "Expected length 0, got %i\n", lstrlenA(ext
));
1080 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1082 /* try a path without an extension */
1083 lstrcpyA(path
, "file");
1084 SetLastError(0xdeadbeef);
1085 ext
= PathFindExtensionA(path
);
1086 ok(ext
== path
+ lstrlenA(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 with an extension */
1091 lstrcpyA(path
, "file.txt");
1092 SetLastError(0xdeadbeef);
1093 ext
= PathFindExtensionA(path
);
1094 ok(ext
== path
+ lstrlenA("file"),
1095 "Expected ext == path + lstrlenA(\"file\"), got %p\n", ext
);
1096 ok(!lstrcmpA(ext
, ".txt"), "Expected .txt, got %s\n", ext
);
1097 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1099 /* try a path with two extensions */
1100 lstrcpyA(path
, "file.txt.doc");
1101 SetLastError(0xdeadbeef);
1102 ext
= PathFindExtensionA(path
);
1103 ok(ext
== path
+ lstrlenA("file.txt"),
1104 "Expected ext == path + lstrlenA(\"file.txt\"), got %p\n", ext
);
1105 ok(!lstrcmpA(ext
, ".doc"), "Expected .txt, got %s\n", ext
);
1106 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1108 /* try a path longer than MAX_PATH without an extension*/
1109 memset(too_long
, 'a', LONG_LEN
);
1110 too_long
[LONG_LEN
- 1] = '\0';
1111 SetLastError(0xdeadbeef);
1112 ext
= PathFindExtensionA(too_long
);
1113 ok(ext
== too_long
+ LONG_LEN
- 1, "Expected ext == too_long + LONG_LEN - 1, got %p\n", ext
);
1114 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1116 /* try a path longer than MAX_PATH with an extension*/
1117 memset(too_long
, 'a', LONG_LEN
);
1118 too_long
[LONG_LEN
- 1] = '\0';
1119 lstrcpyA(too_long
+ 300, ".abcde");
1120 too_long
[lstrlenA(too_long
)] = 'a';
1121 SetLastError(0xdeadbeef);
1122 ext
= PathFindExtensionA(too_long
);
1123 ok(ext
== too_long
+ 300, "Expected ext == too_long + 300, got %p\n", ext
);
1124 ok(lstrlenA(ext
) == LONG_LEN
- 301, "Expected LONG_LEN - 301, got %i\n", lstrlenA(ext
));
1125 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1128 static void test_PathBuildRootA(void)
1132 char root_expected
[26][4];
1136 /* set up the expected paths */
1137 for (drive
= 'A'; drive
<= 'Z'; drive
++)
1138 sprintf(root_expected
[drive
- 'A'], "%c:\\", drive
);
1140 /* test the expected values */
1141 for (j
= 0; j
< 26; j
++)
1143 SetLastError(0xdeadbeef);
1144 lstrcpyA(path
, "aaaaaaaaa");
1145 root
= PathBuildRootA(path
, j
);
1146 ok(root
== path
, "Expected root == path, got %p\n", root
);
1147 ok(!lstrcmpA(root
, root_expected
[j
]), "Expected %s, got %s\n", root_expected
[j
], root
);
1148 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1151 /* test a negative drive number */
1152 SetLastError(0xdeadbeef);
1153 lstrcpyA(path
, "aaaaaaaaa");
1154 root
= PathBuildRootA(path
, -1);
1155 ok(root
== path
, "Expected root == path, got %p\n", root
);
1156 ok(!lstrcmpA(path
, "aaaaaaaaa") || !path
[0], /* Vista */
1157 "Expected aaaaaaaaa or empty string, got %s\n", path
);
1158 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1160 /* test a drive number greater than 25 */
1161 SetLastError(0xdeadbeef);
1162 lstrcpyA(path
, "aaaaaaaaa");
1163 root
= PathBuildRootA(path
, 26);
1164 ok(root
== path
, "Expected root == path, got %p\n", root
);
1165 ok(!lstrcmpA(path
, "aaaaaaaaa") || !path
[0], /* Vista */
1166 "Expected aaaaaaaaa or empty string, got %s\n", path
);
1167 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1169 /* length of path is less than 4 */
1170 SetLastError(0xdeadbeef);
1171 lstrcpyA(path
, "aa");
1172 root
= PathBuildRootA(path
, 0);
1173 ok(root
== path
, "Expected root == path, got %p\n", root
);
1174 ok(!lstrcmpA(path
, "A:\\"), "Expected A:\\, got %s\n", path
);
1175 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1178 SetLastError(0xdeadbeef);
1179 root
= PathBuildRootA(NULL
, 0);
1180 ok(root
== NULL
, "Expected root == NULL, got %p\n", root
);
1181 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1184 static void test_PathCommonPrefixA(void)
1186 char path1
[MAX_PATH
], path2
[MAX_PATH
];
1190 /* test NULL path1 */
1191 SetLastError(0xdeadbeef);
1192 lstrcpyA(path2
, "C:\\");
1193 lstrcpyA(out
, "aaa");
1194 count
= PathCommonPrefixA(NULL
, path2
, out
);
1195 ok(count
== 0, "Expected 0, got %i\n", count
);
1198 ok(!lstrcmpA(out
, "aaa"), "Expected aaa, got %s\n", out
);
1200 ok(!lstrcmpA(path2
, "C:\\"), "Expected C:\\, got %s\n", path2
);
1201 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1203 /* test NULL path2 */
1204 SetLastError(0xdeadbeef);
1205 lstrcpyA(path1
, "C:\\");
1206 lstrcpyA(out
, "aaa");
1207 count
= PathCommonPrefixA(path1
, NULL
, out
);
1208 ok(count
== 0, "Expected 0, got %i\n", count
);
1211 ok(!lstrcmpA(out
, "aaa"), "Expected aaa, got %s\n", out
);
1213 ok(!lstrcmpA(path1
, "C:\\"), "Expected C:\\, got %s\n", path1
);
1214 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1216 /* test empty path1 */
1217 SetLastError(0xdeadbeef);
1219 lstrcpyA(path2
, "C:\\");
1220 lstrcpyA(out
, "aaa");
1221 count
= PathCommonPrefixA(path1
, path2
, out
);
1222 ok(count
== 0, "Expected 0, got %i\n", count
);
1223 ok(!out
[0], "Expected 0 length out, got %i\n", lstrlenA(out
));
1224 ok(!path1
[0], "Expected 0 length path1, got %i\n", lstrlenA(path1
));
1225 ok(!lstrcmpA(path2
, "C:\\"), "Expected C:\\, got %s\n", path2
);
1226 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1228 /* test empty path1 */
1229 SetLastError(0xdeadbeef);
1231 lstrcpyA(path1
, "C:\\");
1232 lstrcpyA(out
, "aaa");
1233 count
= PathCommonPrefixA(path1
, path2
, out
);
1234 ok(count
== 0, "Expected 0, got %i\n", count
);
1235 ok(!out
[0], "Expected 0 length out, got %i\n", lstrlenA(out
));
1236 ok(!path2
[0], "Expected 0 length path2, got %i\n", lstrlenA(path2
));
1237 ok(!lstrcmpA(path1
, "C:\\"), "Expected C:\\, got %s\n", path1
);
1238 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1240 /* paths are legit, out is NULL */
1241 SetLastError(0xdeadbeef);
1242 lstrcpyA(path1
, "C:\\");
1243 lstrcpyA(path2
, "C:\\");
1244 count
= PathCommonPrefixA(path1
, path2
, NULL
);
1245 ok(count
== 3, "Expected 3, got %i\n", count
);
1246 ok(!lstrcmpA(path1
, "C:\\"), "Expected C:\\, got %s\n", path1
);
1247 ok(!lstrcmpA(path2
, "C:\\"), "Expected C:\\, got %s\n", path2
);
1248 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1250 /* all parameters legit */
1251 SetLastError(0xdeadbeef);
1252 lstrcpyA(path1
, "C:\\");
1253 lstrcpyA(path2
, "C:\\");
1254 lstrcpyA(out
, "aaa");
1255 count
= PathCommonPrefixA(path1
, path2
, out
);
1256 ok(count
== 3, "Expected 3, got %i\n", count
);
1257 ok(!lstrcmpA(path1
, "C:\\"), "Expected C:\\, got %s\n", path1
);
1258 ok(!lstrcmpA(path2
, "C:\\"), "Expected C:\\, got %s\n", path2
);
1259 ok(!lstrcmpA(out
, "C:\\"), "Expected C:\\, got %s\n", out
);
1260 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1262 /* path1 and path2 not the same, but common prefix */
1263 SetLastError(0xdeadbeef);
1264 lstrcpyA(path1
, "C:\\one\\two");
1265 lstrcpyA(path2
, "C:\\one\\three");
1266 lstrcpyA(out
, "aaa");
1267 count
= PathCommonPrefixA(path1
, path2
, out
);
1268 ok(count
== 6, "Expected 6, got %i\n", count
);
1269 ok(!lstrcmpA(path1
, "C:\\one\\two"), "Expected C:\\one\\two, got %s\n", path1
);
1270 ok(!lstrcmpA(path2
, "C:\\one\\three"), "Expected C:\\one\\three, got %s\n", path2
);
1271 ok(!lstrcmpA(out
, "C:\\one"), "Expected C:\\one, got %s\n", out
);
1272 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1275 SetLastError(0xdeadbeef);
1276 lstrcpyA(path1
, "one\\.two");
1277 lstrcpyA(path2
, "one\\.three");
1278 lstrcpyA(out
, "aaa");
1279 count
= PathCommonPrefixA(path1
, path2
, out
);
1280 ok(count
== 3, "Expected 3, got %i\n", count
);
1281 ok(!lstrcmpA(path1
, "one\\.two"), "Expected one\\.two, got %s\n", path1
);
1282 ok(!lstrcmpA(path2
, "one\\.three"), "Expected one\\.three, got %s\n", path2
);
1283 ok(!lstrcmpA(out
, "one"), "Expected one, got %s\n", out
);
1284 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1287 SetLastError(0xdeadbeef);
1288 lstrcpyA(path1
, "one\\..two");
1289 lstrcpyA(path2
, "one\\..three");
1290 lstrcpyA(out
, "aaa");
1291 count
= PathCommonPrefixA(path1
, path2
, out
);
1292 ok(count
== 3, "Expected 3, got %i\n", count
);
1293 ok(!lstrcmpA(path1
, "one\\..two"), "Expected one\\..two, got %s\n", path1
);
1294 ok(!lstrcmpA(path2
, "one\\..three"), "Expected one\\..three, got %s\n", path2
);
1295 ok(!lstrcmpA(out
, "one"), "Expected one, got %s\n", out
);
1296 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1298 /* try ... prefix */
1299 SetLastError(0xdeadbeef);
1300 lstrcpyA(path1
, "one\\...two");
1301 lstrcpyA(path2
, "one\\...three");
1302 lstrcpyA(out
, "aaa");
1303 count
= PathCommonPrefixA(path1
, path2
, out
);
1304 ok(count
== 3, "Expected 3, got %i\n", count
);
1305 ok(!lstrcmpA(path1
, "one\\...two"), "Expected one\\...two, got %s\n", path1
);
1306 ok(!lstrcmpA(path2
, "one\\...three"), "Expected one\\...three, got %s\n", path2
);
1307 ok(!lstrcmpA(out
, "one"), "Expected one, got %s\n", out
);
1308 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1311 SetLastError(0xdeadbeef);
1312 lstrcpyA(path1
, "one\\.\\two");
1313 lstrcpyA(path2
, "one\\.\\three");
1314 lstrcpyA(out
, "aaa");
1315 count
= PathCommonPrefixA(path1
, path2
, out
);
1316 ok(count
== 5, "Expected 5, got %i\n", count
);
1317 ok(!lstrcmpA(path1
, "one\\.\\two"), "Expected one\\.\\two, got %s\n", path1
);
1318 ok(!lstrcmpA(path2
, "one\\.\\three"), "Expected one\\.\\three, got %s\n", path2
);
1319 ok(!lstrcmpA(out
, "one\\."), "Expected one\\., got %s\n", out
);
1320 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1322 /* try ..\ prefix */
1323 SetLastError(0xdeadbeef);
1324 lstrcpyA(path1
, "one\\..\\two");
1325 lstrcpyA(path2
, "one\\..\\three");
1326 lstrcpyA(out
, "aaa");
1327 count
= PathCommonPrefixA(path1
, path2
, out
);
1328 ok(count
== 6, "Expected 6, got %i\n", count
);
1329 ok(!lstrcmpA(path1
, "one\\..\\two"), "Expected one\\..\\two, got %s\n", path1
);
1330 ok(!lstrcmpA(path2
, "one\\..\\three"), "Expected one\\..\\three, got %s\n", path2
);
1331 ok(!lstrcmpA(out
, "one\\.."), "Expected one\\.., got %s\n", out
);
1332 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1334 /* try ...\\ prefix */
1335 SetLastError(0xdeadbeef);
1336 lstrcpyA(path1
, "one\\...\\two");
1337 lstrcpyA(path2
, "one\\...\\three");
1338 lstrcpyA(out
, "aaa");
1339 count
= PathCommonPrefixA(path1
, path2
, out
);
1340 ok(count
== 7, "Expected 7, got %i\n", count
);
1341 ok(!lstrcmpA(path1
, "one\\...\\two"), "Expected one\\...\\two, got %s\n", path1
);
1342 ok(!lstrcmpA(path2
, "one\\...\\three"), "Expected one\\...\\three, got %s\n", path2
);
1343 ok(!lstrcmpA(out
, "one\\..."), "Expected one\\..., got %s\n", out
);
1344 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1346 /* try prefix that is not an msdn labeled prefix type */
1347 SetLastError(0xdeadbeef);
1348 lstrcpyA(path1
, "same");
1349 lstrcpyA(path2
, "same");
1350 lstrcpyA(out
, "aaa");
1351 count
= PathCommonPrefixA(path1
, path2
, out
);
1352 ok(count
== 4, "Expected 4, got %i\n", count
);
1353 ok(!lstrcmpA(path1
, "same"), "Expected same, got %s\n", path1
);
1354 ok(!lstrcmpA(path2
, "same"), "Expected same, got %s\n", path2
);
1355 ok(!lstrcmpA(out
, "same"), "Expected same, got %s\n", out
);
1356 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1358 /* try . after directory */
1359 SetLastError(0xdeadbeef);
1360 lstrcpyA(path1
, "one\\mid.\\two");
1361 lstrcpyA(path2
, "one\\mid.\\three");
1362 lstrcpyA(out
, "aaa");
1363 count
= PathCommonPrefixA(path1
, path2
, out
);
1364 ok(count
== 8, "Expected 8, got %i\n", count
);
1365 ok(!lstrcmpA(path1
, "one\\mid.\\two"), "Expected one\\mid.\\two, got %s\n", path1
);
1366 ok(!lstrcmpA(path2
, "one\\mid.\\three"), "Expected one\\mid.\\three, got %s\n", path2
);
1367 ok(!lstrcmpA(out
, "one\\mid."), "Expected one\\mid., got %s\n", out
);
1368 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1370 /* try . in the middle of a directory */
1371 SetLastError(0xdeadbeef);
1372 lstrcpyA(path1
, "one\\mid.end\\two");
1373 lstrcpyA(path2
, "one\\mid.end\\three");
1374 lstrcpyA(out
, "aaa");
1375 count
= PathCommonPrefixA(path1
, path2
, out
);
1376 ok(count
== 11, "Expected 11, got %i\n", count
);
1377 ok(!lstrcmpA(path1
, "one\\mid.end\\two"), "Expected one\\mid.end\\two, got %s\n", path1
);
1378 ok(!lstrcmpA(path2
, "one\\mid.end\\three"), "Expected one\\mid.end\\three, got %s\n", path2
);
1379 ok(!lstrcmpA(out
, "one\\mid.end"), "Expected one\\mid.end, got %s\n", out
);
1380 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1382 /* try comparing a .. with the expanded path */
1383 SetLastError(0xdeadbeef);
1384 lstrcpyA(path1
, "one\\..\\two");
1385 lstrcpyA(path2
, "two");
1386 lstrcpyA(out
, "aaa");
1387 count
= PathCommonPrefixA(path1
, path2
, out
);
1388 ok(count
== 0, "Expected 0, got %i\n", count
);
1389 ok(!lstrcmpA(path1
, "one\\..\\two"), "Expected one\\..\\two, got %s\n", path1
);
1390 ok(!lstrcmpA(path2
, "two"), "Expected two, got %s\n", path2
);
1391 ok(!out
[0], "Expected 0 length out, got %i\n", lstrlenA(out
));
1392 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1395 static void test_PathUnquoteSpaces(void)
1398 for(i
= 0; i
< sizeof(TEST_PATH_UNQUOTE_SPACES
) / sizeof(TEST_PATH_UNQUOTE_SPACES
[0]); i
++)
1400 char *path
= strdupA(TEST_PATH_UNQUOTE_SPACES
[i
].path
);
1401 WCHAR
*pathW
= GetWideString(TEST_PATH_UNQUOTE_SPACES
[i
].path
);
1402 WCHAR
*resultW
= GetWideString(TEST_PATH_UNQUOTE_SPACES
[i
].result
);
1404 PathUnquoteSpacesA(path
);
1405 ok(!strcmp(path
, TEST_PATH_UNQUOTE_SPACES
[i
].result
), "%s (A): got %s expected %s\n",
1406 TEST_PATH_UNQUOTE_SPACES
[i
].path
, path
,
1407 TEST_PATH_UNQUOTE_SPACES
[i
].result
);
1409 PathUnquoteSpacesW(pathW
);
1410 ok(!lstrcmpW(pathW
, resultW
), "%s (W): strings differ\n",
1411 TEST_PATH_UNQUOTE_SPACES
[i
].path
);
1412 FreeWideString(pathW
);
1413 FreeWideString(resultW
);
1414 HeapFree(GetProcessHeap(), 0, path
);
1418 static void test_PathGetDriveNumber(void)
1420 static const CHAR test1A
[] = "a:\\test.file";
1421 static const CHAR test2A
[] = "file:////b:\\test.file";
1422 static const CHAR test3A
[] = "file:///c:\\test.file";
1423 static const CHAR test4A
[] = "file:\\\\c:\\test.file";
1424 static const CHAR test5A
[] = "\\\\?\\C:\\dir\\file.txt";
1425 static const WCHAR test1W
[] =
1427 static const WCHAR test5W
[] =
1428 {'\\','\\','?','\\','C',':','\\','d','i','r','\\','f','i','l','e',0};
1431 SetLastError(0xdeadbeef);
1432 ret
= PathGetDriveNumberA(NULL
);
1433 ok(ret
== -1, "got %d\n", ret
);
1434 ok(GetLastError() == 0xdeadbeef, "got %d\n", GetLastError());
1436 ret
= PathGetDriveNumberA(test1A
);
1437 ok(ret
== 0, "got %d\n", ret
);
1438 ret
= PathGetDriveNumberW(test1W
);
1439 ok(ret
== 0, "got %d\n", ret
);
1440 ret
= PathGetDriveNumberA(test2A
);
1441 ok(ret
== -1, "got %d\n", ret
);
1442 ret
= PathGetDriveNumberA(test3A
);
1443 ok(ret
== -1, "got %d\n", ret
);
1444 ret
= PathGetDriveNumberA(test4A
);
1445 ok(ret
== -1, "got %d\n", ret
);
1447 ret
= PathGetDriveNumberA(test5A
);
1448 ok(ret
== -1, "got %d\n", ret
);
1449 ret
= PathGetDriveNumberW(test5W
);
1450 ok(ret
== 2 || broken(ret
== -1) /* winxp */, "got = %d\n", ret
);
1453 static void test_PathUnExpandEnvStrings(void)
1455 static const WCHAR sysrootW
[] = {'%','S','y','s','t','e','m','R','o','o','t','%',0};
1456 static const WCHAR sysdriveW
[] = {'%','S','y','s','t','e','m','D','r','i','v','e','%',0};
1457 static const WCHAR nonpathW
[] = {'p','a','t','h',0};
1458 static const WCHAR computernameW
[] = {'C','O','M','P','U','T','E','R','N','A','M','E',0};
1459 static const char sysrootA
[] = "%SystemRoot%";
1460 static const char sysdriveA
[] = "%SystemDrive%";
1461 WCHAR pathW
[MAX_PATH
], buffW
[MAX_PATH
], sysdrvW
[3], envvarW
[30];
1462 char path
[MAX_PATH
], buff
[MAX_PATH
], sysdrvA
[3], envvarA
[30];
1466 if (!pPathUnExpandEnvStringsA
|| !pPathUnExpandEnvStringsW
)
1468 win_skip("PathUnExpandEnvStrings not available\n");
1472 /* The value of ComputerName is not a path */
1473 ret
= GetEnvironmentVariableA("COMPUTERNAME", envvarA
, sizeof(envvarA
));
1474 ok(ret
, "got %d\n", ret
);
1475 SetLastError(0xdeadbeef);
1476 ret
= pPathUnExpandEnvStringsA(envvarA
, buff
, sizeof(buff
));
1477 ok(!ret
&& GetLastError() == 0xdeadbeef, "got %d, error %d\n", ret
, GetLastError());
1479 ret
= GetEnvironmentVariableW(computernameW
, envvarW
, sizeof(envvarW
)/sizeof(WCHAR
));
1480 ok(ret
, "got %d\n", ret
);
1481 SetLastError(0xdeadbeef);
1482 ret
= pPathUnExpandEnvStringsW(envvarW
, buffW
, sizeof(buffW
)/sizeof(WCHAR
));
1483 ok(!ret
&& GetLastError() == 0xdeadbeef, "got %d, error %d\n", ret
, GetLastError());
1485 /* something that can't be represented with env var */
1486 strcpy(path
, "somepath_name");
1488 SetLastError(0xdeadbeef);
1489 ret
= pPathUnExpandEnvStringsA(path
, buff
, sizeof(buff
));
1490 ok(!ret
&& GetLastError() == 0xdeadbeef, "got %d, error %d\n", ret
, GetLastError());
1491 ok(buff
[0] == 'x', "wrong return string %s\n", buff
);
1493 len
= GetSystemDirectoryA(path
, MAX_PATH
);
1494 ok(len
> 0, "failed to get sysdir\n");
1496 sysdrvA
[0] = path
[0];
1497 strcpy(&sysdrvA
[1], ":");
1499 /* buffer size is not enough */
1501 SetLastError(0xdeadbeef);
1502 ret
= pPathUnExpandEnvStringsA(path
, buff
, 5);
1503 ok(!ret
&& GetLastError() == 0xdeadbeef, "got %d\n", ret
);
1504 ok(buff
[0] == 'x', "wrong return string %s\n", buff
);
1506 /* buffer size is enough to hold variable name only */
1508 SetLastError(0xdeadbeef);
1509 ret
= pPathUnExpandEnvStringsA(path
, buff
, sizeof(sysrootA
));
1510 ok(!ret
&& GetLastError() == 0xdeadbeef, "got %d, error %d\n", ret
, GetLastError());
1511 ok(buff
[0] == 'x', "wrong return string %s\n", buff
);
1515 ret
= pPathUnExpandEnvStringsA(path
, buff
, sizeof(buff
));
1516 ok(ret
, "got %d\n", ret
);
1517 ok(!strncmp(buff
, sysrootA
, sizeof(sysrootA
)-1), "wrong return string %s\n", buff
);
1519 /* expanded value occurs multiple times */
1520 /* for drive C: it unexpands it like 'C:C:' -> '%SystemDrive%C:' */
1522 strcpy(path
, sysdrvA
);
1523 strcat(path
, sysdrvA
);
1524 ret
= pPathUnExpandEnvStringsA(path
, buff
, sizeof(buff
));
1525 ok(ret
, "got %d\n", ret
);
1526 /* expected string */
1527 strcpy(path
, sysdriveA
);
1528 strcat(path
, sysdrvA
);
1529 ok(!strcmp(buff
, path
), "wrong unexpanded string %s, expected %s\n", buff
, path
);
1531 /* now with altered variable */
1532 ret
= GetEnvironmentVariableA("SystemDrive", envvarA
, sizeof(envvarA
));
1533 ok(ret
, "got %d\n", ret
);
1535 ret
= SetEnvironmentVariableA("SystemDrive", "WW");
1536 ok(ret
, "got %d\n", ret
);
1538 /* variables are not cached */
1539 strcpy(path
, sysdrvA
);
1540 strcat(path
, sysdrvA
);
1541 SetLastError(0xdeadbeef);
1542 ret
= pPathUnExpandEnvStringsA(path
, buff
, sizeof(buff
));
1543 ok(!ret
&& GetLastError() == 0xdeadbeef, "got %d, error %d\n", ret
, GetLastError());
1545 ret
= SetEnvironmentVariableA("SystemDrive", envvarA
);
1546 ok(ret
, "got %d\n", ret
);
1548 /* PathUnExpandEnvStringsW */
1550 /* something that can't be represented with env var */
1551 lstrcpyW(pathW
, nonpathW
);
1552 buffW
[0] = 'x'; buffW
[1] = 0;
1553 SetLastError(0xdeadbeef);
1554 ret
= pPathUnExpandEnvStringsW(pathW
, buffW
, sizeof(buffW
)/sizeof(WCHAR
));
1555 ok(!ret
&& GetLastError() == 0xdeadbeef, "got %d, error %d\n", ret
, GetLastError());
1556 ok(buffW
[0] == 'x', "wrong return string %s\n", wine_dbgstr_w(buffW
));
1558 len
= GetSystemDirectoryW(pathW
, MAX_PATH
);
1559 ok(len
> 0, "failed to get sysdir\n");
1561 sysdrvW
[0] = pathW
[0];
1565 /* buffer size is not enough */
1566 buffW
[0] = 'x'; buffW
[1] = 0;
1567 SetLastError(0xdeadbeef);
1568 ret
= pPathUnExpandEnvStringsW(pathW
, buffW
, 5);
1569 ok(!ret
&& GetLastError() == 0xdeadbeef, "got %d, error %d\n", ret
, GetLastError());
1570 ok(buffW
[0] == 'x', "wrong return string %s\n", wine_dbgstr_w(buffW
));
1572 /* buffer size is enough to hold variable name only */
1573 buffW
[0] = 'x'; buffW
[1] = 0;
1574 SetLastError(0xdeadbeef);
1575 ret
= pPathUnExpandEnvStringsW(pathW
, buffW
, sizeof(sysrootW
)/sizeof(WCHAR
));
1576 ok(!ret
&& GetLastError() == 0xdeadbeef, "got %d, error %d\n", ret
, GetLastError());
1577 ok(buffW
[0] == 'x', "wrong return string %s\n", wine_dbgstr_w(buffW
));
1581 ret
= pPathUnExpandEnvStringsW(pathW
, buffW
, sizeof(buffW
)/sizeof(WCHAR
));
1582 ok(ret
, "got %d\n", ret
);
1583 ok(!memcmp(buffW
, sysrootW
, sizeof(sysrootW
) - sizeof(WCHAR
)), "wrong return string %s\n", wine_dbgstr_w(buffW
));
1585 /* expanded value occurs multiple times */
1586 /* for drive C: it unexpands it like 'C:C:' -> '%SystemDrive%C:' */
1588 lstrcpyW(pathW
, sysdrvW
);
1589 lstrcatW(pathW
, sysdrvW
);
1590 ret
= pPathUnExpandEnvStringsW(pathW
, buffW
, sizeof(buff
)/sizeof(WCHAR
));
1591 ok(ret
, "got %d\n", ret
);
1592 /* expected string */
1593 lstrcpyW(pathW
, sysdriveW
);
1594 lstrcatW(pathW
, sysdrvW
);
1595 ok(!lstrcmpW(buffW
, pathW
), "wrong unexpanded string %s, expected %s\n", wine_dbgstr_w(buffW
), wine_dbgstr_w(pathW
));
1598 static const struct {
1601 } test_path_is_relative
[] = {
1605 {"\\\\folder\\test.txt", FALSE
},
1606 {"file://folder/test.txt", TRUE
},
1607 {"C:\\test.txt", FALSE
},
1608 {"file:///C:/test.txt", TRUE
}
1611 static void test_PathIsRelativeA(void)
1616 if (!pPathIsRelativeA
) {
1617 win_skip("PathIsRelativeA not available\n");
1621 num
= sizeof(test_path_is_relative
) / sizeof(test_path_is_relative
[0]);
1622 for (i
= 0; i
< num
; i
++) {
1623 ret
= pPathIsRelativeA(test_path_is_relative
[i
].path
);
1624 ok(ret
== test_path_is_relative
[i
].expect
,
1625 "PathIsRelativeA(\"%s\") expects %d, got %d.\n",
1626 test_path_is_relative
[i
].path
, test_path_is_relative
[i
].expect
, ret
);
1630 static void test_PathIsRelativeW(void)
1636 if (!pPathIsRelativeW
) {
1637 win_skip("PathIsRelativeW not available\n");
1641 num
= sizeof(test_path_is_relative
) / sizeof(test_path_is_relative
[0]);
1642 for (i
= 0; i
< num
; i
++) {
1643 path
= GetWideString(test_path_is_relative
[i
].path
);
1645 ret
= pPathIsRelativeW(path
);
1646 ok(ret
== test_path_is_relative
[i
].expect
,
1647 "PathIsRelativeW(\"%s\") expects %d, got %d.\n",
1648 test_path_is_relative
[i
].path
, test_path_is_relative
[i
].expect
, ret
);
1650 FreeWideString(path
);
1654 static void test_PathStripPathA(void)
1656 const char const_path
[] = "test";
1657 char path
[] = "short//path\\file.txt";
1659 PathStripPathA(path
);
1660 ok(!strcmp(path
, "file.txt"), "path = %s\n", path
);
1662 /* following test should not crash */
1663 /* LavView 2013 depends on that behaviour */
1664 PathStripPathA((char*)const_path
);
1669 HMODULE hShlwapi
= GetModuleHandleA("shlwapi.dll");
1671 /* SHCreateStreamOnFileEx was introduced in shlwapi v6.0 */
1672 if(!GetProcAddress(hShlwapi
, "SHCreateStreamOnFileEx")){
1673 win_skip("Too old shlwapi version\n");
1677 pPathCreateFromUrlA
= (void*)GetProcAddress(hShlwapi
, "PathCreateFromUrlA");
1678 pPathCreateFromUrlW
= (void*)GetProcAddress(hShlwapi
, "PathCreateFromUrlW");
1679 pPathCreateFromUrlAlloc
= (void*)GetProcAddress(hShlwapi
, "PathCreateFromUrlAlloc");
1680 pPathCombineW
= (void*)GetProcAddress(hShlwapi
, "PathCombineW");
1681 pPathIsValidCharA
= (void*)GetProcAddress(hShlwapi
, (LPSTR
)455);
1682 pPathIsValidCharW
= (void*)GetProcAddress(hShlwapi
, (LPSTR
)456);
1683 pPathAppendA
= (void*)GetProcAddress(hShlwapi
, "PathAppendA");
1684 pPathUnExpandEnvStringsA
= (void*)GetProcAddress(hShlwapi
, "PathUnExpandEnvStringsA");
1685 pPathUnExpandEnvStringsW
= (void*)GetProcAddress(hShlwapi
, "PathUnExpandEnvStringsW");
1686 pPathIsRelativeA
= (void*)GetProcAddress(hShlwapi
, "PathIsRelativeA");
1687 pPathIsRelativeW
= (void*)GetProcAddress(hShlwapi
, "PathIsRelativeW");
1689 test_PathSearchAndQualify();
1690 test_PathCreateFromUrl();
1693 test_PathAddBackslash();
1694 test_PathMakePretty();
1695 test_PathMatchSpec();
1697 test_PathIsValidCharA();
1698 test_PathIsValidCharW();
1700 test_PathCombineW();
1701 test_PathCombineA();
1703 test_PathCanonicalizeA();
1704 test_PathFindExtensionA();
1705 test_PathBuildRootA();
1706 test_PathCommonPrefixA();
1707 test_PathUnquoteSpaces();
1708 test_PathGetDriveNumber();
1709 test_PathUnExpandEnvStrings();
1710 test_PathIsRelativeA();
1711 test_PathIsRelativeW();
1712 test_PathStripPathA();