push 87b6981010d7405c33b14cddcceec21b47729eba
[wine/hacks.git] / dlls / shlwapi / tests / path.c
blobe52502fdf58889492c21edbb03d8344da8fe9429
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
20 #include <assert.h>
21 #include <stdarg.h>
22 #include <stdio.h>
24 #include "wine/test.h"
25 #include "windef.h"
26 #include "winbase.h"
27 #include "winreg.h"
28 #include "shlwapi.h"
29 #include "wininet.h"
31 static HMODULE hShlwapi;
32 static HRESULT (WINAPI *pPathIsValidCharA)(char,DWORD);
33 static HRESULT (WINAPI *pPathIsValidCharW)(WCHAR,DWORD);
34 static LPWSTR (WINAPI *pPathCombineW)(LPWSTR, LPCWSTR, LPCWSTR);
35 static HRESULT (WINAPI *pPathCreateFromUrlA)(LPCSTR, LPSTR, LPDWORD, DWORD);
36 static HRESULT (WINAPI *pPathCreateFromUrlW)(LPCWSTR, LPWSTR, LPDWORD, DWORD);
38 /* ################ */
40 struct {
41 const char *url;
42 const char *path;
43 DWORD ret;
44 } TEST_PATHFROMURL[] = {
45 {"file:///c:/foo/ba%5Cr", "c:\\foo\\ba\\r", S_OK},
46 {"file:///c:/foo/../ba%5Cr", "c:\\foo\\..\\ba\\r", S_OK},
47 {"file:///host/c:/foo/bar", "\\host\\c:\\foo\\bar", S_OK},
48 {"file://host/c:/foo/bar", "\\\\hostc:\\foo\\bar", S_OK},
49 {"file://host/c:/foo/bar", "\\\\hostc:\\foo\\bar", S_OK},
50 {"file:\\\\host\\c:\\foo\\bar", "\\\\hostc:\\foo\\bar", S_OK},
51 {"file:\\\\host\\ca\\foo\\bar", "\\\\host\\ca\\foo\\bar", S_OK},
52 {"file:\\\\host\\c|\\foo\\bar", "\\\\hostc|\\foo\\bar", S_OK},
53 {"file:\\%5Chost\\c:\\foo\\bar", "\\\\host\\c:\\foo\\bar", S_OK},
54 {"file:\\\\host\\cx:\\foo\\bar", "\\\\host\\cx:\\foo\\bar", S_OK},
55 {"file://c:/foo/bar", "c:\\foo\\bar", S_OK},
56 {"file://c:/d:/foo/bar", "c:\\d:\\foo\\bar", S_OK},
57 {"file://c|/d|/foo/bar", "c:\\d|\\foo\\bar", S_OK},
58 {"file://host/foo/bar", "\\\\host\\foo\\bar", S_OK},
59 {"file:/foo/bar", "\\foo\\bar", S_OK},
60 {"file:/foo/bar/", "\\foo\\bar\\", S_OK},
61 {"file:foo/bar", "foo\\bar", S_OK},
62 {"file:c:/foo/bar", "c:\\foo\\bar", S_OK},
63 {"file:c|/foo/bar", "c:\\foo\\bar", S_OK},
64 {"file:cx|/foo/bar", "cx|\\foo\\bar", S_OK},
65 {"file:////c:/foo/bar", "c:\\foo\\bar", S_OK},
66 /* {"file:////c:/foo/foo%20bar", "c:\\foo\\foo%20bar", S_OK},*/
68 {"c:\\foo\\bar", NULL, E_INVALIDARG},
69 {"foo/bar", NULL, E_INVALIDARG},
70 {"http://foo/bar", NULL, E_INVALIDARG},
75 static struct {
76 const char *path;
77 BOOL expect;
78 } TEST_PATH_IS_URL[] = {
79 {"http://foo/bar", TRUE},
80 {"c:\\foo\\bar", FALSE},
81 {"c:/foo/bar", FALSE},
82 {"foo://foo/bar", TRUE},
83 {"foo\\bar", FALSE},
84 {"foo.bar", FALSE},
85 {"bogusscheme:", TRUE},
86 {"http:partial", TRUE},
87 {"www.winehq.org", FALSE},
88 /* More examples that the user might enter as the browser start page */
89 {"winehq.org", FALSE},
90 {"ftp.winehq.org", FALSE},
91 {"http://winehq.org", TRUE},
92 {"http://www.winehq.org", TRUE},
93 {"https://winehq.org", TRUE},
94 {"https://www.winehq.org", TRUE},
95 {"ftp://winehq.org", TRUE},
96 {"ftp://ftp.winehq.org", TRUE},
97 {"file://does_not_exist.txt", TRUE},
98 {"about:blank", TRUE},
99 {"about:home", TRUE},
100 {"about:mozilla", TRUE},
101 /* scheme is case independent */
102 {"HTTP://www.winehq.org", TRUE},
103 /* a space at the start is not allowed */
104 {" http://www.winehq.org", FALSE},
105 {"", FALSE},
106 {NULL, FALSE}
109 struct {
110 const char *path;
111 const char *result;
112 } TEST_PATH_UNQUOTE_SPACES[] = {
113 { "abcdef", "abcdef" },
114 { "\"abcdef\"", "abcdef" },
115 { "\"abcdef", "\"abcdef" },
116 { "abcdef\"", "abcdef\"" },
117 { "\"\"abcdef\"\"", "\"abcdef\"" },
118 { "abc\"def", "abc\"def" },
119 { "\"abc\"def", "\"abc\"def" },
120 { "\"abc\"def\"", "abc\"def" },
121 { "\'abcdef\'", "\'abcdef\'" },
122 { "\"\"", "" },
123 { "\"", "" }
126 /* ################ */
128 static LPWSTR GetWideString(const char* szString)
130 LPWSTR wszString = HeapAlloc(GetProcessHeap(), 0, (2*INTERNET_MAX_URL_LENGTH) * sizeof(WCHAR));
132 MultiByteToWideChar(0, 0, szString, -1, wszString, INTERNET_MAX_URL_LENGTH);
134 return wszString;
137 static void FreeWideString(LPWSTR wszString)
139 HeapFree(GetProcessHeap(), 0, wszString);
142 static LPSTR strdupA(LPCSTR p)
144 LPSTR ret;
145 DWORD len = (strlen(p) + 1);
146 ret = HeapAlloc(GetProcessHeap(), 0, len);
147 memcpy(ret, p, len);
148 return ret;
151 /* ################ */
153 static void test_PathSearchAndQualify(void)
155 WCHAR path1[] = {'c',':','\\','f','o','o',0};
156 WCHAR expect1[] = {'c',':','\\','f','o','o',0};
157 WCHAR path2[] = {'c',':','f','o','o',0};
158 WCHAR c_drive[] = {'c',':',0};
159 WCHAR foo[] = {'f','o','o',0};
160 WCHAR path3[] = {'\\','f','o','o',0};
161 WCHAR winini[] = {'w','i','n','.','i','n','i',0};
162 WCHAR out[MAX_PATH];
163 WCHAR cur_dir[MAX_PATH];
164 WCHAR dot[] = {'.',0};
166 /* c:\foo */
167 ok(PathSearchAndQualifyW(path1, out, MAX_PATH) != 0,
168 "PathSearchAndQualify rets 0\n");
169 ok(!lstrcmpiW(out, expect1), "strings don't match\n");
171 /* c:foo */
172 ok(PathSearchAndQualifyW(path2, out, MAX_PATH) != 0,
173 "PathSearchAndQualify rets 0\n");
174 GetFullPathNameW(c_drive, MAX_PATH, cur_dir, NULL);
175 PathAddBackslashW(cur_dir);
176 lstrcatW(cur_dir, foo);
177 ok(!lstrcmpiW(out, cur_dir), "strings don't match\n");
179 /* foo */
180 ok(PathSearchAndQualifyW(foo, out, MAX_PATH) != 0,
181 "PathSearchAndQualify rets 0\n");
182 GetFullPathNameW(dot, MAX_PATH, cur_dir, NULL);
183 PathAddBackslashW(cur_dir);
184 lstrcatW(cur_dir, foo);
185 ok(!lstrcmpiW(out, cur_dir), "strings don't match\n");
187 /* \foo */
188 ok(PathSearchAndQualifyW(path3, out, MAX_PATH) != 0,
189 "PathSearchAndQualify rets 0\n");
190 GetFullPathNameW(dot, MAX_PATH, cur_dir, NULL);
191 lstrcpyW(cur_dir + 2, path3);
192 ok(!lstrcmpiW(out, cur_dir), "strings don't match\n");
194 /* win.ini */
195 ok(PathSearchAndQualifyW(winini, out, MAX_PATH) != 0,
196 "PathSearchAndQualify rets 0\n");
197 if(!SearchPathW(NULL, winini, NULL, MAX_PATH, cur_dir, NULL))
198 GetFullPathNameW(winini, MAX_PATH, cur_dir, NULL);
199 ok(!lstrcmpiW(out, cur_dir), "strings don't match\n");
203 static void test_PathCreateFromUrl(void)
205 size_t i;
206 char ret_path[INTERNET_MAX_URL_LENGTH];
207 DWORD len, ret;
208 WCHAR ret_pathW[INTERNET_MAX_URL_LENGTH];
209 WCHAR *pathW, *urlW;
210 static const char url[] = "http://www.winehq.org";
212 if (!pPathCreateFromUrlA) {
213 win_skip("PathCreateFromUrlA not found\n");
214 return;
217 /* Check ret_path = NULL */
218 len = sizeof(url);
219 ret = pPathCreateFromUrlA(url, NULL, &len, 0);
220 ok ( ret == E_INVALIDARG, "got 0x%08x expected E_INVALIDARG\n", ret);
222 for(i = 0; i < sizeof(TEST_PATHFROMURL) / sizeof(TEST_PATHFROMURL[0]); i++) {
223 len = INTERNET_MAX_URL_LENGTH;
224 ret = pPathCreateFromUrlA(TEST_PATHFROMURL[i].url, ret_path, &len, 0);
225 ok(ret == TEST_PATHFROMURL[i].ret, "ret %08x from url %s\n", ret, TEST_PATHFROMURL[i].url);
226 if(TEST_PATHFROMURL[i].path) {
227 ok(!lstrcmpi(ret_path, TEST_PATHFROMURL[i].path), "got %s expected %s from url %s\n", ret_path, TEST_PATHFROMURL[i].path, TEST_PATHFROMURL[i].url);
228 ok(len == strlen(ret_path), "ret len %d from url %s\n", len, TEST_PATHFROMURL[i].url);
230 if (pPathCreateFromUrlW) {
231 len = INTERNET_MAX_URL_LENGTH;
232 pathW = GetWideString(TEST_PATHFROMURL[i].path);
233 urlW = GetWideString(TEST_PATHFROMURL[i].url);
234 ret = pPathCreateFromUrlW(urlW, ret_pathW, &len, 0);
235 WideCharToMultiByte(CP_ACP, 0, ret_pathW, -1, ret_path, sizeof(ret_path),0,0);
236 ok(ret == TEST_PATHFROMURL[i].ret, "ret %08x from url L\"%s\"\n", ret, TEST_PATHFROMURL[i].url);
237 if(TEST_PATHFROMURL[i].path) {
238 ok(!lstrcmpiW(ret_pathW, pathW), "got %s expected %s from url L\"%s\"\n",
239 ret_path, TEST_PATHFROMURL[i].path, TEST_PATHFROMURL[i].url);
240 ok(len == lstrlenW(ret_pathW), "ret len %d from url L\"%s\"\n", len, TEST_PATHFROMURL[i].url);
242 FreeWideString(urlW);
243 FreeWideString(pathW);
249 static void test_PathIsUrl(void)
251 size_t i;
252 BOOL ret;
254 for(i = 0; i < sizeof(TEST_PATH_IS_URL)/sizeof(TEST_PATH_IS_URL[0]); i++) {
255 ret = PathIsURLA(TEST_PATH_IS_URL[i].path);
256 ok(ret == TEST_PATH_IS_URL[i].expect,
257 "returned %d from path %s, expected %d\n", ret, TEST_PATH_IS_URL[i].path,
258 TEST_PATH_IS_URL[i].expect);
262 static const DWORD SHELL_charclass[] =
264 0x00000000, 0x00000000, 0x00000000, 0x00000000,
265 0x00000000, 0x00000000, 0x00000000, 0x00000000,
266 0x00000000, 0x00000000, 0x00000000, 0x00000000,
267 0x00000000, 0x00000000, 0x00000000, 0x00000000,
268 0x00000000, 0x00000000, 0x00000000, 0x00000000,
269 0x00000000, 0x00000000, 0x00000000, 0x00000000,
270 0x00000000, 0x00000000, 0x00000000, 0x00000000,
271 0x00000000, 0x00000000, 0x00000000, 0x00000000,
272 0x00000080, 0x00000100, 0x00000200, 0x00000100,
273 0x00000100, 0x00000100, 0x00000100, 0x00000100,
274 0x00000100, 0x00000100, 0x00000002, 0x00000100,
275 0x00000040, 0x00000100, 0x00000004, 0x00000000,
276 0x00000100, 0x00000100, 0x00000100, 0x00000100,
277 0x00000100, 0x00000100, 0x00000100, 0x00000100,
278 0x00000100, 0x00000100, 0x00000010, 0x00000020,
279 0x00000000, 0x00000100, 0x00000000, 0x00000001,
280 0x00000100, 0xffffffff, 0xffffffff, 0xffffffff,
281 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
282 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
283 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
284 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
285 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
286 0xffffffff, 0xffffffff, 0xffffffff, 0x00000100,
287 0x00000008, 0x00000100, 0x00000100, 0x00000100,
288 0x00000100, 0xffffffff, 0xffffffff, 0xffffffff,
289 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
290 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
291 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
292 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
293 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
294 0xffffffff, 0xffffffff, 0xffffffff, 0x00000100,
295 0x00000000, 0x00000100, 0x00000100
298 static void test_PathIsValidCharA(void)
300 BOOL ret;
301 unsigned int c;
303 for (c = 0; c < 0x7f; c++)
305 ret = pPathIsValidCharA( c, ~0U );
306 ok ( ret || !SHELL_charclass[c], "PathIsValidCharA failed: 0x%02x got 0x%08x\n", c, ret );
309 for (c = 0x7f; c <= 0xff; c++)
311 ret = pPathIsValidCharA( c, ~0U );
312 ok ( ret, "PathIsValidCharA failed: 0x%02x got 0x%08x\n", c, ret );
316 static void test_PathIsValidCharW(void)
318 BOOL ret;
319 unsigned int c;
321 for (c = 0; c < 0x7f; c++)
323 ret = pPathIsValidCharW( c, ~0U );
324 ok ( ret || !SHELL_charclass[c], "PathIsValidCharW failed: 0x%02x got 0x%08x\n", c, ret );
327 for (c = 0x007f; c <= 0xffff; c++)
329 ret = pPathIsValidCharW( c, ~0U );
330 ok ( ret, "PathIsValidCharW failed: 0x%02x got 0x%08x\n", c, ret );
334 static void test_PathMakePretty(void)
336 char buff[MAX_PATH];
338 ok (PathMakePrettyA(NULL) == FALSE, "PathMakePretty: NULL path succeeded\n");
339 buff[0] = '\0';
340 ok (PathMakePrettyA(buff) == TRUE, "PathMakePretty: Empty path failed\n");
342 strcpy(buff, "C:\\A LONG FILE NAME WITH \\SPACES.TXT");
343 ok (PathMakePrettyA(buff) == TRUE, "PathMakePretty: Long UC name failed\n");
344 ok (strcmp(buff, "C:\\a long file name with \\spaces.txt") == 0,
345 "PathMakePretty: Long UC name not changed\n");
347 strcpy(buff, "C:\\A LONG FILE NAME WITH \\MixedCase.TXT");
348 ok (PathMakePrettyA(buff) == FALSE, "PathMakePretty: Long MC name succeeded\n");
349 ok (strcmp(buff, "C:\\A LONG FILE NAME WITH \\MixedCase.TXT") == 0,
350 "PathMakePretty: Failed but modified path\n");
352 strcpy(buff, "TEST");
353 ok (PathMakePrettyA(buff) == TRUE, "PathMakePretty: Short name failed\n");
354 ok (strcmp(buff, "Test") == 0, "PathMakePretty: 1st char lowercased %s\n", buff);
357 static void test_PathMatchSpec(void)
359 static const char file[] = "c:\\foo\\bar\\filename.ext";
360 static const char spec1[] = ".ext";
361 static const char spec2[] = "*.ext";
362 static const char spec3[] = "*.ext ";
363 static const char spec4[] = " *.ext";
364 static const char spec5[] = "* .ext";
365 static const char spec6[] = "*. ext";
366 static const char spec7[] = "* . ext";
367 static const char spec8[] = "*.e?t";
368 static const char spec9[] = "filename.ext";
369 static const char spec10[] = "*bar\\filename.ext";
370 static const char spec11[] = " foo; *.ext";
371 static const char spec12[] = "*.ext;*.bar";
372 static const char spec13[] = "*bar*";
374 ok (PathMatchSpecA(file, spec1) == FALSE, "PathMatchSpec: Spec1 failed\n");
375 ok (PathMatchSpecA(file, spec2) == TRUE, "PathMatchSpec: Spec2 failed\n");
376 ok (PathMatchSpecA(file, spec3) == FALSE, "PathMatchSpec: Spec3 failed\n");
377 ok (PathMatchSpecA(file, spec4) == TRUE, "PathMatchSpec: Spec4 failed\n");
378 todo_wine ok (PathMatchSpecA(file, spec5) == TRUE, "PathMatchSpec: Spec5 failed\n");
379 todo_wine ok (PathMatchSpecA(file, spec6) == TRUE, "PathMatchSpec: Spec6 failed\n");
380 ok (PathMatchSpecA(file, spec7) == FALSE, "PathMatchSpec: Spec7 failed\n");
381 ok (PathMatchSpecA(file, spec8) == TRUE, "PathMatchSpec: Spec8 failed\n");
382 ok (PathMatchSpecA(file, spec9) == FALSE, "PathMatchSpec: Spec9 failed\n");
383 ok (PathMatchSpecA(file, spec10) == TRUE, "PathMatchSpec: Spec10 failed\n");
384 ok (PathMatchSpecA(file, spec11) == TRUE, "PathMatchSpec: Spec11 failed\n");
385 ok (PathMatchSpecA(file, spec12) == TRUE, "PathMatchSpec: Spec12 failed\n");
386 ok (PathMatchSpecA(file, spec13) == TRUE, "PathMatchSpec: Spec13 failed\n");
389 static void test_PathCombineW(void)
391 LPWSTR wszString, wszString2;
392 WCHAR wbuf[MAX_PATH+1], wstr1[MAX_PATH] = {'C',':','\\',0}, wstr2[MAX_PATH];
393 static const WCHAR expout[] = {'C',':','\\','A','A',0};
394 int i;
396 wszString2 = HeapAlloc(GetProcessHeap(), 0, MAX_PATH * sizeof(WCHAR));
398 /* NULL test */
399 wszString = pPathCombineW(NULL, NULL, NULL);
400 ok (wszString == NULL, "Expected a NULL return\n");
402 /* Some NULL */
403 wszString2[0] = 'a';
404 wszString = pPathCombineW(wszString2, NULL, NULL);
405 ok (wszString == NULL ||
406 broken(wszString[0] == 'a'), /* Win95 and some W2K */
407 "Expected a NULL return\n");
408 ok (wszString2[0] == 0 ||
409 broken(wszString2[0] == 'a'), /* Win95 and some W2K */
410 "Destination string not empty\n");
412 HeapFree(GetProcessHeap(), 0, wszString2);
414 /* overflow test */
415 wstr2[0] = wstr2[1] = wstr2[2] = 'A';
416 for (i=3; i<MAX_PATH/2; i++)
417 wstr1[i] = wstr2[i] = 'A';
418 wstr1[(MAX_PATH/2) - 1] = wstr2[MAX_PATH/2] = 0;
419 memset(wbuf, 0xbf, sizeof(wbuf));
421 wszString = pPathCombineW(wbuf, wstr1, wstr2);
422 ok(wszString == NULL, "Expected a NULL return\n");
423 ok(wbuf[0] == 0 ||
424 broken(wbuf[0] == 0xbfbf), /* Win95 and some W2K */
425 "Buffer contains data\n");
427 /* PathCombineW can be used in place */
428 wstr1[3] = 0;
429 wstr2[2] = 0;
430 ok(PathCombineW(wstr1, wstr1, wstr2) == wstr1, "Expected a wstr1 return\n");
431 ok(StrCmpW(wstr1, expout) == 0, "Unexpected PathCombine output\n");
435 #define LONG_LEN (MAX_PATH * 2)
436 #define HALF_LEN (MAX_PATH / 2 + 1)
438 static void test_PathCombineA(void)
440 LPSTR str;
441 char dest[MAX_PATH];
442 char too_long[LONG_LEN];
443 char one[HALF_LEN], two[HALF_LEN];
445 /* try NULL dest */
446 SetLastError(0xdeadbeef);
447 str = PathCombineA(NULL, "C:\\", "one\\two\\three");
448 ok(str == NULL, "Expected NULL, got %p\n", str);
449 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
451 /* try NULL dest and NULL directory */
452 SetLastError(0xdeadbeef);
453 str = PathCombineA(NULL, NULL, "one\\two\\three");
454 ok(str == NULL, "Expected NULL, got %p\n", str);
455 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
457 /* try all NULL*/
458 SetLastError(0xdeadbeef);
459 str = PathCombineA(NULL, NULL, NULL);
460 ok(str == NULL, "Expected NULL, got %p\n", str);
461 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
463 /* try NULL file part */
464 SetLastError(0xdeadbeef);
465 lstrcpyA(dest, "control");
466 str = PathCombineA(dest, "C:\\", NULL);
467 ok(str == dest, "Expected str == dest, got %p\n", str);
468 ok(!lstrcmp(str, "C:\\"), "Expected C:\\, got %s\n", str);
469 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
471 /* try empty file part */
472 SetLastError(0xdeadbeef);
473 lstrcpyA(dest, "control");
474 str = PathCombineA(dest, "C:\\", "");
475 ok(str == dest, "Expected str == dest, got %p\n", str);
476 ok(!lstrcmp(str, "C:\\"), "Expected C:\\, got %s\n", str);
477 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
479 /* try empty directory and file part */
480 SetLastError(0xdeadbeef);
481 lstrcpyA(dest, "control");
482 str = PathCombineA(dest, "", "");
483 ok(str == dest, "Expected str == dest, got %p\n", str);
484 ok(!lstrcmp(str, "\\") ||
485 broken(!lstrcmp(str, "control")), /* Win95 and some W2K */
486 "Expected \\, got %s\n", str);
487 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
489 /* try NULL directory */
490 SetLastError(0xdeadbeef);
491 lstrcpyA(dest, "control");
492 str = PathCombineA(dest, NULL, "one\\two\\three");
493 ok(str == dest, "Expected str == dest, got %p\n", str);
494 ok(!lstrcmp(str, "one\\two\\three"), "Expected one\\two\\three, got %s\n", str);
495 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
497 /* try NULL directory and empty file part */
498 SetLastError(0xdeadbeef);
499 lstrcpyA(dest, "control");
500 str = PathCombineA(dest, NULL, "");
501 ok(str == dest, "Expected str == dest, got %p\n", str);
502 ok(!lstrcmp(str, "\\") ||
503 broken(!lstrcmp(str, "one\\two\\three")), /* Win95 and some W2K */
504 "Expected \\, got %s\n", str);
505 ok(GetLastError() == 0xdeadbeef ||
506 broken(GetLastError() == ERROR_INVALID_PARAMETER), /* Win95 */
507 "Expected 0xdeadbeef, got %d\n", GetLastError());
509 /* try NULL directory and file part */
510 SetLastError(0xdeadbeef);
511 lstrcpyA(dest, "control");
512 str = PathCombineA(dest, NULL, NULL);
513 ok(str == NULL ||
514 broken(str != NULL), /* Win95 and some W2K */
515 "Expected str == NULL, got %p\n", str);
516 ok(lstrlenA(dest) == 0 ||
517 broken(!lstrcmp(dest, "control")), /* Win95 and some W2K */
518 "Expected 0 length, got %i\n", lstrlenA(dest));
519 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
521 /* try directory without backslash */
522 SetLastError(0xdeadbeef);
523 lstrcpyA(dest, "control");
524 str = PathCombineA(dest, "C:", "one\\two\\three");
525 ok(str == dest, "Expected str == dest, got %p\n", str);
526 ok(!lstrcmp(str, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", str);
527 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
529 /* try directory with backslash */
530 SetLastError(0xdeadbeef);
531 lstrcpyA(dest, "control");
532 str = PathCombineA(dest, "C:\\", "one\\two\\three");
533 ok(str == dest, "Expected str == dest, got %p\n", str);
534 ok(!lstrcmp(str, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", str);
535 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
537 /* try directory with backslash and file with prepended backslash */
538 SetLastError(0xdeadbeef);
539 lstrcpyA(dest, "control");
540 str = PathCombineA(dest, "C:\\", "\\one\\two\\three");
541 ok(str == dest, "Expected str == dest, got %p\n", str);
542 ok(!lstrcmp(str, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", str);
543 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
545 /* try previous test, with backslash appended as well */
546 SetLastError(0xdeadbeef);
547 lstrcpyA(dest, "control");
548 str = PathCombineA(dest, "C:\\", "\\one\\two\\three\\");
549 ok(str == dest, "Expected str == dest, got %p\n", str);
550 ok(!lstrcmp(str, "C:\\one\\two\\three\\"), "Expected C:\\one\\two\\three\\, got %s\n", str);
551 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
553 /* try a relative directory */
554 SetLastError(0xdeadbeef);
555 lstrcpyA(dest, "control");
556 str = PathCombineA(dest, "relative\\dir", "\\one\\two\\three\\");
557 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
558 /* Vista fails which probably makes sense as PathCombineA expects an absolute dir */
559 if (str)
561 ok(str == dest, "Expected str == dest, got %p\n", str);
562 ok(!lstrcmp(str, "one\\two\\three\\"), "Expected one\\two\\three\\, got %s\n", str);
565 /* try forward slashes */
566 SetLastError(0xdeadbeef);
567 lstrcpyA(dest, "control");
568 str = PathCombineA(dest, "C:\\", "one/two/three\\");
569 ok(str == dest, "Expected str == dest, got %p\n", str);
570 ok(!lstrcmp(str, "C:\\one/two/three\\"), "Expected one/two/three\\, got %s\n", str);
571 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
573 /* try a really weird directory */
574 SetLastError(0xdeadbeef);
575 lstrcpyA(dest, "control");
576 str = PathCombineA(dest, "C:\\/\\/", "\\one\\two\\three\\");
577 ok(str == dest, "Expected str == dest, got %p\n", str);
578 ok(!lstrcmp(str, "C:\\one\\two\\three\\"), "Expected C:\\one\\two\\three\\, got %s\n", str);
579 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
581 /* try periods */
582 SetLastError(0xdeadbeef);
583 lstrcpyA(dest, "control");
584 str = PathCombineA(dest, "C:\\", "one\\..\\two\\.\\three");
585 ok(str == dest, "Expected str == dest, got %p\n", str);
586 ok(!lstrcmp(str, "C:\\two\\three"), "Expected C:\\two\\three, got %s\n", str);
587 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
589 /* try .. as file */
590 /* try forward slashes */
591 SetLastError(0xdeadbeef);
592 lstrcpyA(dest, "control");
593 str = PathCombineA(dest, "C:\\", "..");
594 ok(str == dest, "Expected str == dest, got %p\n", str);
595 ok(!lstrcmp(str, "C:\\"), "Expected C:\\, got %s\n", str);
596 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
598 memset(too_long, 'a', LONG_LEN);
599 too_long[LONG_LEN - 1] = '\0';
601 /* try a file longer than MAX_PATH */
602 SetLastError(0xdeadbeef);
603 lstrcpyA(dest, "control");
604 str = PathCombineA(dest, "C:\\", too_long);
605 ok(str == NULL, "Expected str == NULL, got %p\n", str);
606 ok(lstrlenA(dest) == 0 ||
607 broken(!lstrcmp(dest, "control")), /* Win95 and some W2K */
608 "Expected 0 length, got %i\n", lstrlenA(dest));
609 todo_wine ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
611 /* try a directory longer than MAX_PATH */
612 SetLastError(0xdeadbeef);
613 lstrcpyA(dest, "control");
614 str = PathCombineA(dest, too_long, "one\\two\\three");
615 ok(str == NULL, "Expected str == NULL, got %p\n", str);
616 ok(lstrlenA(dest) == 0 ||
617 broken(!lstrcmp(dest, "control")), /* Win95 and some W2K */
618 "Expected 0 length, got %i\n", lstrlenA(dest));
619 todo_wine ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
621 memset(one, 'b', HALF_LEN);
622 memset(two, 'c', HALF_LEN);
623 one[HALF_LEN - 1] = '\0';
624 two[HALF_LEN - 1] = '\0';
626 /* destination string is longer than MAX_PATH, but not the constituent parts */
627 SetLastError(0xdeadbeef);
628 lstrcpyA(dest, "control");
629 str = PathCombineA(dest, one, two);
630 ok(str == NULL, "Expected str == NULL, got %p\n", str);
631 ok(lstrlenA(dest) == 0 ||
632 broken(!lstrcmp(dest, "control")), /* Win95 and some W2K */
633 "Expected 0 length, got %i\n", lstrlenA(dest));
634 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
637 static void test_PathAddBackslash(void)
639 LPSTR str;
640 char path[MAX_PATH];
641 char too_long[LONG_LEN];
643 /* try a NULL path */
644 SetLastError(0xdeadbeef);
645 str = PathAddBackslashA(NULL);
646 ok(str == NULL, "Expected str == NULL, got %p\n", str);
647 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
649 /* try an empty path */
650 path[0] = '\0';
651 SetLastError(0xdeadbeef);
652 str = PathAddBackslashA(path);
653 ok(str == (path + lstrlenA(path)), "Expected str to point to end of path, got %p\n", str);
654 ok(lstrlenA(path) == 0, "Expected empty string, got %i\n", lstrlenA(path));
655 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
657 /* try a relative path */
658 lstrcpyA(path, "one\\two");
659 SetLastError(0xdeadbeef);
660 str = PathAddBackslashA(path);
661 ok(str == (path + lstrlenA(path)), "Expected str to point to end of path, got %p\n", str);
662 ok(!lstrcmp(path, "one\\two\\"), "Expected one\\two\\, got %s\n", path);
663 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
665 /* try periods */
666 lstrcpyA(path, "one\\..\\two");
667 SetLastError(0xdeadbeef);
668 str = PathAddBackslashA(path);
669 ok(str == (path + lstrlenA(path)), "Expected str to point to end of path, got %p\n", str);
670 ok(!lstrcmp(path, "one\\..\\two\\"), "Expected one\\..\\two\\, got %s\n", path);
671 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
673 /* try just a space */
674 lstrcpyA(path, " ");
675 SetLastError(0xdeadbeef);
676 str = PathAddBackslashA(path);
677 ok(str == (path + lstrlenA(path)), "Expected str to point to end of path, got %p\n", str);
678 ok(!lstrcmp(path, " \\"), "Expected \\, got %s\n", path);
679 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
681 /* path already has backslash */
682 lstrcpyA(path, "C:\\one\\");
683 SetLastError(0xdeadbeef);
684 str = PathAddBackslashA(path);
685 ok(str == (path + lstrlenA(path)), "Expected str to point to end of path, got %p\n", str);
686 ok(!lstrcmp(path, "C:\\one\\"), "Expected C:\\one\\, got %s\n", path);
687 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
689 memset(too_long, 'a', LONG_LEN);
690 too_long[LONG_LEN - 1] = '\0';
692 /* path is longer than MAX_PATH */
693 SetLastError(0xdeadbeef);
694 str = PathAddBackslashA(too_long);
695 ok(str == NULL, "Expected str == NULL, got %p\n", str);
696 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
699 static void test_PathAppendA(void)
701 char path[MAX_PATH];
702 char too_long[LONG_LEN];
703 char half[HALF_LEN];
704 BOOL res;
706 lstrcpy(path, "C:\\one");
708 /* try NULL pszMore */
709 SetLastError(0xdeadbeef);
710 res = PathAppendA(path, NULL);
711 ok(!res, "Expected failure\n");
712 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
713 ok(!lstrcmp(path, "C:\\one"), "Expected C:\\one, got %s\n", path);
715 /* try empty pszMore */
716 SetLastError(0xdeadbeef);
717 res = PathAppendA(path, "");
718 ok(res, "Expected success\n");
719 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
720 ok(!lstrcmp(path, "C:\\one"), "Expected C:\\one, got %s\n", path);
722 /* try NULL pszPath */
723 SetLastError(0xdeadbeef);
724 res = PathAppendA(NULL, "two\\three");
725 ok(!res, "Expected failure\n");
726 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
728 /* try empty pszPath */
729 path[0] = '\0';
730 SetLastError(0xdeadbeef);
731 res = PathAppendA(path, "two\\three");
732 ok(res, "Expected success\n");
733 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
734 ok(!lstrcmp(path, "two\\three"), "Expected \\two\\three, got %s\n", path);
736 /* try empty pszPath and empty pszMore */
737 path[0] = '\0';
738 SetLastError(0xdeadbeef);
739 res = PathAppendA(path, "");
740 ok(res, "Expected success\n");
741 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
742 ok(!lstrcmp(path, "\\"), "Expected \\, got %s\n", path);
744 /* try legit params */
745 lstrcpy(path, "C:\\one");
746 SetLastError(0xdeadbeef);
747 res = PathAppendA(path, "two\\three");
748 ok(res, "Expected success\n");
749 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
750 ok(!lstrcmp(path, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", path);
752 /* try pszPath with backslash after it */
753 lstrcpy(path, "C:\\one\\");
754 SetLastError(0xdeadbeef);
755 res = PathAppendA(path, "two\\three");
756 ok(res, "Expected success\n");
757 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
758 ok(!lstrcmp(path, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", path);
760 /* try pszMore with backslash before it */
761 lstrcpy(path, "C:\\one");
762 SetLastError(0xdeadbeef);
763 res = PathAppendA(path, "\\two\\three");
764 ok(res, "Expected success\n");
765 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
766 ok(!lstrcmp(path, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", path);
768 /* try pszMore with backslash after it */
769 lstrcpy(path, "C:\\one");
770 SetLastError(0xdeadbeef);
771 res = PathAppendA(path, "two\\three\\");
772 ok(res, "Expected success\n");
773 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
774 ok(!lstrcmp(path, "C:\\one\\two\\three\\"), "Expected C:\\one\\two\\three\\, got %s\n", path);
776 /* try spaces in pszPath */
777 lstrcpy(path, "C: \\ one ");
778 SetLastError(0xdeadbeef);
779 res = PathAppendA(path, "two\\three");
780 ok(res, "Expected success\n");
781 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
782 ok(!lstrcmp(path, "C: \\ one \\two\\three"), "Expected C: \\ one \\two\\three, got %s\n", path);
784 /* try spaces in pszMore */
785 lstrcpy(path, "C:\\one");
786 SetLastError(0xdeadbeef);
787 res = PathAppendA(path, " two \\ three ");
788 ok(res, "Expected success\n");
789 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
790 ok(!lstrcmp(path, "C:\\one\\ two \\ three "), "Expected 'C:\\one\\ two \\ three ', got %s\n", path);
792 /* pszPath is too long */
793 memset(too_long, 'a', LONG_LEN);
794 too_long[LONG_LEN - 1] = '\0';
795 SetLastError(0xdeadbeef);
796 res = PathAppendA(too_long, "two\\three");
797 ok(!res, "Expected failure\n");
798 todo_wine ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
799 ok(lstrlen(too_long) == 0 ||
800 broken(lstrlen(too_long) == (LONG_LEN - 1)), /* Win95 and some W2K */
801 "Expected length of too_long to be zero, got %i\n", lstrlen(too_long));
803 /* pszMore is too long */
804 lstrcpy(path, "C:\\one");
805 memset(too_long, 'a', LONG_LEN);
806 too_long[LONG_LEN - 1] = '\0';
807 SetLastError(0xdeadbeef);
808 res = PathAppendA(path, too_long);
809 ok(!res, "Expected failure\n");
810 todo_wine ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
811 ok(lstrlen(path) == 0 ||
812 broken(!lstrcmp(path, "C:\\one")), /* Win95 and some W2K */
813 "Expected length of path to be zero, got %i\n", lstrlen(path));
815 /* both params combined are too long */
816 memset(path, 'a', HALF_LEN);
817 path[HALF_LEN - 1] = '\0';
818 memset(half, 'b', HALF_LEN);
819 half[HALF_LEN - 1] = '\0';
820 SetLastError(0xdeadbeef);
821 res = PathAppendA(path, half);
822 ok(!res, "Expected failure\n");
823 ok(lstrlen(path) == 0 ||
824 broken(lstrlen(path) == (HALF_LEN - 1)), /* Win95 and some W2K */
825 "Expected length of path to be zero, got %i\n", lstrlen(path));
826 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
829 static void test_PathCanonicalizeA(void)
831 char dest[LONG_LEN + MAX_PATH];
832 char too_long[LONG_LEN];
833 BOOL res;
835 /* try a NULL source */
836 lstrcpy(dest, "test");
837 SetLastError(0xdeadbeef);
838 res = PathCanonicalizeA(dest, NULL);
839 ok(!res, "Expected failure\n");
840 ok(GetLastError() == ERROR_INVALID_PARAMETER,
841 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
842 ok(dest[0] == 0 || !lstrcmp(dest, "test"),
843 "Expected either an empty string (Vista) or test, got %s\n", dest);
845 /* try an empty source */
846 lstrcpy(dest, "test");
847 SetLastError(0xdeadbeef);
848 res = PathCanonicalizeA(dest, "");
849 ok(res, "Expected success\n");
850 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
851 ok(!lstrcmp(dest, "\\") ||
852 broken(!lstrcmp(dest, "test")), /* Win95 and some W2K */
853 "Expected \\, got %s\n", dest);
855 /* try a NULL dest */
856 SetLastError(0xdeadbeef);
857 res = PathCanonicalizeA(NULL, "C:\\");
858 ok(!res, "Expected failure\n");
859 ok(GetLastError() == ERROR_INVALID_PARAMETER,
860 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
862 /* try empty dest */
863 dest[0] = '\0';
864 SetLastError(0xdeadbeef);
865 res = PathCanonicalizeA(dest, "C:\\");
866 ok(res, "Expected success\n");
867 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
868 ok(!lstrcmp(dest, "C:\\"), "Expected C:\\, got %s\n", dest);
870 /* try non-empty dest */
871 lstrcpy(dest, "test");
872 SetLastError(0xdeadbeef);
873 res = PathCanonicalizeA(dest, "C:\\");
874 ok(res, "Expected success\n");
875 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
876 ok(!lstrcmp(dest, "C:\\"), "Expected C:\\, got %s\n", dest);
878 /* try a space for source */
879 lstrcpy(dest, "test");
880 SetLastError(0xdeadbeef);
881 res = PathCanonicalizeA(dest, " ");
882 ok(res, "Expected success\n");
883 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
884 ok(!lstrcmp(dest, " "), "Expected ' ', got %s\n", dest);
886 /* try a relative path */
887 lstrcpy(dest, "test");
888 SetLastError(0xdeadbeef);
889 res = PathCanonicalizeA(dest, "one\\two");
890 ok(res, "Expected success\n");
891 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
892 ok(!lstrcmp(dest, "one\\two"), "Expected one\\two, got %s\n", dest);
894 /* try current dir and previous dir */
895 lstrcpy(dest, "test");
896 SetLastError(0xdeadbeef);
897 res = PathCanonicalizeA(dest, "C:\\one\\.\\..\\two\\three\\..");
898 ok(res, "Expected success\n");
899 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
900 ok(!lstrcmp(dest, "C:\\two"), "Expected C:\\two, got %s\n", dest);
902 /* try simple forward slashes */
903 lstrcpy(dest, "test");
904 SetLastError(0xdeadbeef);
905 res = PathCanonicalizeA(dest, "C:\\one/two/three\\four/five\\six");
906 ok(res, "Expected success\n");
907 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
908 ok(!lstrcmp(dest, "C:\\one/two/three\\four/five\\six"),
909 "Expected C:\\one/two/three\\four/five\\six, got %s\n", dest);
911 /* try simple forward slashes with same dir */
912 lstrcpy(dest, "test");
913 SetLastError(0xdeadbeef);
914 res = PathCanonicalizeA(dest, "C:\\one/.\\two");
915 ok(res, "Expected success\n");
916 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
917 ok(!lstrcmp(dest, "C:\\one/.\\two"), "Expected C:\\one/.\\two, got %s\n", dest);
919 /* try simple forward slashes with change dir */
920 lstrcpy(dest, "test");
921 SetLastError(0xdeadbeef);
922 res = PathCanonicalizeA(dest, "C:\\one/.\\two\\..");
923 ok(res, "Expected success\n");
924 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
925 ok(!lstrcmp(dest, "C:\\one/.") ||
926 !lstrcmp(dest, "C:\\one/"), /* Vista */
927 "Expected \"C:\\one/.\" or \"C:\\one/\", got \"%s\"\n", dest);
929 /* try forward slashes with change dirs
930 * NOTE: if there is a forward slash in between two backslashes,
931 * everything in between the two backslashes is considered on dir
933 lstrcpy(dest, "test");
934 SetLastError(0xdeadbeef);
935 res = PathCanonicalizeA(dest, "C:\\one/.\\..\\two/three\\..\\four/.five");
936 ok(res, "Expected success\n");
937 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
938 ok(!lstrcmp(dest, "C:\\four/.five"), "Expected C:\\four/.five, got %s\n", dest);
940 /* try src is too long */
941 memset(too_long, 'a', LONG_LEN);
942 too_long[LONG_LEN - 1] = '\0';
943 lstrcpy(dest, "test");
944 SetLastError(0xdeadbeef);
945 res = PathCanonicalizeA(dest, too_long);
946 ok(!res ||
947 broken(res), /* Win95, some W2K and XP-SP1 */
948 "Expected failure\n");
949 todo_wine
951 ok(GetLastError() == 0xdeadbeef || GetLastError() == ERROR_FILENAME_EXCED_RANGE /* Vista */,
952 "Expected 0xdeadbeef or ERROR_FILENAME_EXCED_RANGE, got %d\n", GetLastError());
954 ok(lstrlen(too_long) == LONG_LEN - 1, "Expected length LONG_LEN - 1, got %i\n", lstrlen(too_long));
957 static void test_PathFindExtensionA(void)
959 LPSTR ext;
960 char path[MAX_PATH];
961 char too_long[LONG_LEN];
963 /* try a NULL path */
964 SetLastError(0xdeadbeef);
965 ext = PathFindExtensionA(NULL);
966 ok(ext == NULL, "Expected NULL, got %p\n", ext);
967 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
969 /* try an empty path */
970 path[0] = '\0';
971 SetLastError(0xdeadbeef);
972 ext = PathFindExtensionA(path);
973 ok(ext == path, "Expected ext == path, got %p\n", ext);
974 ok(lstrlen(ext) == 0, "Expected length 0, got %i\n", lstrlen(ext));
975 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
977 /* try a path without an extension */
978 lstrcpy(path, "file");
979 SetLastError(0xdeadbeef);
980 ext = PathFindExtensionA(path);
981 ok(ext == path + lstrlen(path), "Expected ext == path, got %p\n", ext);
982 ok(lstrlen(ext) == 0, "Expected length 0, got %i\n", lstrlen(ext));
983 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
985 /* try a path with an extension */
986 lstrcpy(path, "file.txt");
987 SetLastError(0xdeadbeef);
988 ext = PathFindExtensionA(path);
989 ok(ext == path + lstrlen("file"),
990 "Expected ext == path + lstrlen(\"file\"), got %p\n", ext);
991 ok(!lstrcmp(ext, ".txt"), "Expected .txt, got %s\n", ext);
992 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
994 /* try a path with two extensions */
995 lstrcpy(path, "file.txt.doc");
996 SetLastError(0xdeadbeef);
997 ext = PathFindExtensionA(path);
998 ok(ext == path + lstrlen("file.txt"),
999 "Expected ext == path + lstrlen(\"file.txt\"), got %p\n", ext);
1000 ok(!lstrcmp(ext, ".doc"), "Expected .txt, got %s\n", ext);
1001 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1003 /* try a path longer than MAX_PATH without an extension*/
1004 memset(too_long, 'a', LONG_LEN);
1005 too_long[LONG_LEN - 1] = '\0';
1006 SetLastError(0xdeadbeef);
1007 ext = PathFindExtensionA(too_long);
1008 ok(ext == too_long + LONG_LEN - 1, "Expected ext == too_long + LONG_LEN - 1, got %p\n", ext);
1009 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1011 /* try a path longer than MAX_PATH with an extension*/
1012 memset(too_long, 'a', LONG_LEN);
1013 too_long[LONG_LEN - 1] = '\0';
1014 lstrcpy(too_long + 300, ".abcde");
1015 too_long[lstrlen(too_long)] = 'a';
1016 SetLastError(0xdeadbeef);
1017 ext = PathFindExtensionA(too_long);
1018 ok(ext == too_long + 300, "Expected ext == too_long + 300, got %p\n", ext);
1019 ok(lstrlen(ext) == LONG_LEN - 301, "Expected LONG_LEN - 301, got %i\n", lstrlen(ext));
1020 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1023 static void test_PathBuildRootA(void)
1025 LPSTR root;
1026 char path[10];
1027 char root_expected[26][4];
1028 char drive;
1029 int j;
1031 /* set up the expected paths */
1032 for (drive = 'A'; drive <= 'Z'; drive++)
1033 sprintf(root_expected[drive - 'A'], "%c:\\", drive);
1035 /* test the expected values */
1036 for (j = 0; j < 26; j++)
1038 SetLastError(0xdeadbeef);
1039 lstrcpy(path, "aaaaaaaaa");
1040 root = PathBuildRootA(path, j);
1041 ok(root == path, "Expected root == path, got %p\n", root);
1042 ok(!lstrcmp(root, root_expected[j]), "Expected %s, got %s\n", root_expected[j], root);
1043 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1046 /* test a negative drive number */
1047 SetLastError(0xdeadbeef);
1048 lstrcpy(path, "aaaaaaaaa");
1049 root = PathBuildRootA(path, -1);
1050 ok(root == path, "Expected root == path, got %p\n", root);
1051 ok(!lstrcmp(path, "aaaaaaaaa") ||
1052 lstrlenA(path) == 0, /* Vista */
1053 "Expected aaaaaaaaa or empty string, got %s\n", path);
1054 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1056 /* test a drive number greater than 25 */
1057 SetLastError(0xdeadbeef);
1058 lstrcpy(path, "aaaaaaaaa");
1059 root = PathBuildRootA(path, 26);
1060 ok(root == path, "Expected root == path, got %p\n", root);
1061 ok(!lstrcmp(path, "aaaaaaaaa") ||
1062 lstrlenA(path) == 0, /* Vista */
1063 "Expected aaaaaaaaa or empty string, got %s\n", path);
1064 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1066 /* length of path is less than 4 */
1067 SetLastError(0xdeadbeef);
1068 lstrcpy(path, "aa");
1069 root = PathBuildRootA(path, 0);
1070 ok(root == path, "Expected root == path, got %p\n", root);
1071 ok(!lstrcmp(path, "A:\\"), "Expected A:\\, got %s\n", path);
1072 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1074 /* path is NULL */
1075 SetLastError(0xdeadbeef);
1076 root = PathBuildRootA(NULL, 0);
1077 ok(root == NULL, "Expected root == NULL, got %p\n", root);
1078 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1081 static void test_PathCommonPrefixA(void)
1083 char path1[MAX_PATH], path2[MAX_PATH];
1084 char out[MAX_PATH];
1085 int count;
1087 /* test NULL path1 */
1088 SetLastError(0xdeadbeef);
1089 lstrcpy(path2, "C:\\");
1090 lstrcpy(out, "aaa");
1091 count = PathCommonPrefixA(NULL, path2, out);
1092 ok(count == 0, "Expected 0, got %i\n", count);
1093 todo_wine
1095 ok(!lstrcmp(out, "aaa"), "Expected aaa, got %s\n", out);
1097 ok(!lstrcmp(path2, "C:\\"), "Expected C:\\, got %s\n", path2);
1098 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1100 /* test NULL path2 */
1101 SetLastError(0xdeadbeef);
1102 lstrcpy(path1, "C:\\");
1103 lstrcpy(out, "aaa");
1104 count = PathCommonPrefixA(path1, NULL, out);
1105 ok(count == 0, "Expected 0, got %i\n", count);
1106 todo_wine
1108 ok(!lstrcmp(out, "aaa"), "Expected aaa, got %s\n", out);
1110 ok(!lstrcmp(path1, "C:\\"), "Expected C:\\, got %s\n", path1);
1111 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1113 /* test empty path1 */
1114 SetLastError(0xdeadbeef);
1115 path1[0] = '\0';
1116 lstrcpy(path2, "C:\\");
1117 lstrcpy(out, "aaa");
1118 count = PathCommonPrefixA(path1, path2, out);
1119 ok(count == 0, "Expected 0, got %i\n", count);
1120 ok(lstrlen(out) == 0, "Expected 0 length out, got %i\n", lstrlen(out));
1121 ok(lstrlen(path1) == 0, "Expected 0 length path1, got %i\n", lstrlen(path1));
1122 ok(!lstrcmp(path2, "C:\\"), "Expected C:\\, got %s\n", path2);
1123 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1125 /* test empty path1 */
1126 SetLastError(0xdeadbeef);
1127 path2[0] = '\0';
1128 lstrcpy(path1, "C:\\");
1129 lstrcpy(out, "aaa");
1130 count = PathCommonPrefixA(path1, path2, out);
1131 ok(count == 0, "Expected 0, got %i\n", count);
1132 ok(lstrlen(out) == 0, "Expected 0 length out, got %i\n", lstrlen(out));
1133 ok(lstrlen(path2) == 0, "Expected 0 length path2, got %i\n", lstrlen(path2));
1134 ok(!lstrcmp(path1, "C:\\"), "Expected C:\\, got %s\n", path1);
1135 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1137 /* paths are legit, out is NULL */
1138 SetLastError(0xdeadbeef);
1139 lstrcpy(path1, "C:\\");
1140 lstrcpy(path2, "C:\\");
1141 count = PathCommonPrefixA(path1, path2, NULL);
1142 ok(count == 3, "Expected 3, got %i\n", count);
1143 ok(!lstrcmp(path1, "C:\\"), "Expected C:\\, got %s\n", path1);
1144 ok(!lstrcmp(path2, "C:\\"), "Expected C:\\, got %s\n", path2);
1145 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1147 /* all parameters legit */
1148 SetLastError(0xdeadbeef);
1149 lstrcpy(path1, "C:\\");
1150 lstrcpy(path2, "C:\\");
1151 lstrcpy(out, "aaa");
1152 count = PathCommonPrefixA(path1, path2, out);
1153 ok(count == 3, "Expected 3, got %i\n", count);
1154 ok(!lstrcmp(path1, "C:\\"), "Expected C:\\, got %s\n", path1);
1155 ok(!lstrcmp(path2, "C:\\"), "Expected C:\\, got %s\n", path2);
1156 ok(!lstrcmp(out, "C:\\"), "Expected C:\\, got %s\n", out);
1157 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1159 /* path1 and path2 not the same, but common prefix */
1160 SetLastError(0xdeadbeef);
1161 lstrcpy(path1, "C:\\one\\two");
1162 lstrcpy(path2, "C:\\one\\three");
1163 lstrcpy(out, "aaa");
1164 count = PathCommonPrefixA(path1, path2, out);
1165 ok(count == 6, "Expected 6, got %i\n", count);
1166 ok(!lstrcmp(path1, "C:\\one\\two"), "Expected C:\\one\\two, got %s\n", path1);
1167 ok(!lstrcmp(path2, "C:\\one\\three"), "Expected C:\\one\\three, got %s\n", path2);
1168 ok(!lstrcmp(out, "C:\\one"), "Expected C:\\one, got %s\n", out);
1169 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1171 /* try . prefix */
1172 SetLastError(0xdeadbeef);
1173 lstrcpy(path1, "one\\.two");
1174 lstrcpy(path2, "one\\.three");
1175 lstrcpy(out, "aaa");
1176 count = PathCommonPrefixA(path1, path2, out);
1177 ok(count == 3, "Expected 3, got %i\n", count);
1178 ok(!lstrcmp(path1, "one\\.two"), "Expected one\\.two, got %s\n", path1);
1179 ok(!lstrcmp(path2, "one\\.three"), "Expected one\\.three, got %s\n", path2);
1180 ok(!lstrcmp(out, "one"), "Expected one, got %s\n", out);
1181 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1183 /* try .. prefix */
1184 SetLastError(0xdeadbeef);
1185 lstrcpy(path1, "one\\..two");
1186 lstrcpy(path2, "one\\..three");
1187 lstrcpy(out, "aaa");
1188 count = PathCommonPrefixA(path1, path2, out);
1189 ok(count == 3, "Expected 3, got %i\n", count);
1190 ok(!lstrcmp(path1, "one\\..two"), "Expected one\\..two, got %s\n", path1);
1191 ok(!lstrcmp(path2, "one\\..three"), "Expected one\\..three, got %s\n", path2);
1192 ok(!lstrcmp(out, "one"), "Expected one, got %s\n", out);
1193 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1195 /* try ... prefix */
1196 SetLastError(0xdeadbeef);
1197 lstrcpy(path1, "one\\...two");
1198 lstrcpy(path2, "one\\...three");
1199 lstrcpy(out, "aaa");
1200 count = PathCommonPrefixA(path1, path2, out);
1201 ok(count == 3, "Expected 3, got %i\n", count);
1202 ok(!lstrcmp(path1, "one\\...two"), "Expected one\\...two, got %s\n", path1);
1203 ok(!lstrcmp(path2, "one\\...three"), "Expected one\\...three, got %s\n", path2);
1204 ok(!lstrcmp(out, "one"), "Expected one, got %s\n", out);
1205 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1207 /* try .\ prefix */
1208 SetLastError(0xdeadbeef);
1209 lstrcpy(path1, "one\\.\\two");
1210 lstrcpy(path2, "one\\.\\three");
1211 lstrcpy(out, "aaa");
1212 count = PathCommonPrefixA(path1, path2, out);
1213 ok(count == 5, "Expected 5, got %i\n", count);
1214 ok(!lstrcmp(path1, "one\\.\\two"), "Expected one\\.\\two, got %s\n", path1);
1215 ok(!lstrcmp(path2, "one\\.\\three"), "Expected one\\.\\three, got %s\n", path2);
1216 ok(!lstrcmp(out, "one\\."), "Expected one\\., got %s\n", out);
1217 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1219 /* try ..\ prefix */
1220 SetLastError(0xdeadbeef);
1221 lstrcpy(path1, "one\\..\\two");
1222 lstrcpy(path2, "one\\..\\three");
1223 lstrcpy(out, "aaa");
1224 count = PathCommonPrefixA(path1, path2, out);
1225 ok(count == 6, "Expected 6, got %i\n", count);
1226 ok(!lstrcmp(path1, "one\\..\\two"), "Expected one\\..\\two, got %s\n", path1);
1227 ok(!lstrcmp(path2, "one\\..\\three"), "Expected one\\..\\three, got %s\n", path2);
1228 ok(!lstrcmp(out, "one\\.."), "Expected one\\.., got %s\n", out);
1229 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1231 /* try ...\\ prefix */
1232 SetLastError(0xdeadbeef);
1233 lstrcpy(path1, "one\\...\\two");
1234 lstrcpy(path2, "one\\...\\three");
1235 lstrcpy(out, "aaa");
1236 count = PathCommonPrefixA(path1, path2, out);
1237 ok(count == 7, "Expected 7, got %i\n", count);
1238 ok(!lstrcmp(path1, "one\\...\\two"), "Expected one\\...\\two, got %s\n", path1);
1239 ok(!lstrcmp(path2, "one\\...\\three"), "Expected one\\...\\three, got %s\n", path2);
1240 ok(!lstrcmp(out, "one\\..."), "Expected one\\..., got %s\n", out);
1241 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1243 /* try prefix that is not an msdn labeled prefix type */
1244 SetLastError(0xdeadbeef);
1245 lstrcpy(path1, "same");
1246 lstrcpy(path2, "same");
1247 lstrcpy(out, "aaa");
1248 count = PathCommonPrefixA(path1, path2, out);
1249 ok(count == 4, "Expected 4, got %i\n", count);
1250 ok(!lstrcmp(path1, "same"), "Expected same, got %s\n", path1);
1251 ok(!lstrcmp(path2, "same"), "Expected same, got %s\n", path2);
1252 ok(!lstrcmp(out, "same"), "Expected same, got %s\n", out);
1253 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1255 /* try . after directory */
1256 SetLastError(0xdeadbeef);
1257 lstrcpy(path1, "one\\mid.\\two");
1258 lstrcpy(path2, "one\\mid.\\three");
1259 lstrcpy(out, "aaa");
1260 count = PathCommonPrefixA(path1, path2, out);
1261 ok(count == 8, "Expected 8, got %i\n", count);
1262 ok(!lstrcmp(path1, "one\\mid.\\two"), "Expected one\\mid.\\two, got %s\n", path1);
1263 ok(!lstrcmp(path2, "one\\mid.\\three"), "Expected one\\mid.\\three, got %s\n", path2);
1264 ok(!lstrcmp(out, "one\\mid."), "Expected one\\mid., got %s\n", out);
1265 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1267 /* try . in the middle of a directory */
1268 SetLastError(0xdeadbeef);
1269 lstrcpy(path1, "one\\mid.end\\two");
1270 lstrcpy(path2, "one\\mid.end\\three");
1271 lstrcpy(out, "aaa");
1272 count = PathCommonPrefixA(path1, path2, out);
1273 ok(count == 11, "Expected 11, got %i\n", count);
1274 ok(!lstrcmp(path1, "one\\mid.end\\two"), "Expected one\\mid.end\\two, got %s\n", path1);
1275 ok(!lstrcmp(path2, "one\\mid.end\\three"), "Expected one\\mid.end\\three, got %s\n", path2);
1276 ok(!lstrcmp(out, "one\\mid.end"), "Expected one\\mid.end, got %s\n", out);
1277 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1279 /* try comparing a .. with the expanded path */
1280 SetLastError(0xdeadbeef);
1281 lstrcpy(path1, "one\\..\\two");
1282 lstrcpy(path2, "two");
1283 lstrcpy(out, "aaa");
1284 count = PathCommonPrefixA(path1, path2, out);
1285 ok(count == 0, "Expected 0, got %i\n", count);
1286 ok(!lstrcmp(path1, "one\\..\\two"), "Expected one\\..\\two, got %s\n", path1);
1287 ok(!lstrcmp(path2, "two"), "Expected two, got %s\n", path2);
1288 ok(lstrlen(out) == 0, "Expected 0 length out, got %i\n", lstrlen(out));
1289 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1292 static void test_PathUnquoteSpaces(void)
1294 int i;
1295 for(i = 0; i < sizeof(TEST_PATH_UNQUOTE_SPACES) / sizeof(TEST_PATH_UNQUOTE_SPACES[0]); i++)
1297 char *path = strdupA(TEST_PATH_UNQUOTE_SPACES[i].path);
1298 WCHAR *pathW = GetWideString(TEST_PATH_UNQUOTE_SPACES[i].path);
1299 WCHAR *resultW = GetWideString(TEST_PATH_UNQUOTE_SPACES[i].result);
1301 PathUnquoteSpacesA(path);
1302 ok(!strcmp(path, TEST_PATH_UNQUOTE_SPACES[i].result), "%s (A): got %s expected %s\n",
1303 TEST_PATH_UNQUOTE_SPACES[i].path, path,
1304 TEST_PATH_UNQUOTE_SPACES[i].result);
1306 PathUnquoteSpacesW(pathW);
1307 ok(!lstrcmpW(pathW, resultW), "%s (W): strings differ\n",
1308 TEST_PATH_UNQUOTE_SPACES[i].path);
1309 FreeWideString(pathW);
1310 FreeWideString(resultW);
1311 HeapFree(GetProcessHeap(), 0, path);
1315 /* ################ */
1317 START_TEST(path)
1319 hShlwapi = GetModuleHandleA("shlwapi.dll");
1320 pPathCreateFromUrlA = (void*)GetProcAddress(hShlwapi, "PathCreateFromUrlA");
1321 pPathCreateFromUrlW = (void*)GetProcAddress(hShlwapi, "PathCreateFromUrlW");
1323 test_PathSearchAndQualify();
1324 test_PathCreateFromUrl();
1325 test_PathIsUrl();
1327 test_PathAddBackslash();
1328 test_PathMakePretty();
1329 test_PathMatchSpec();
1331 /* For whatever reason, PathIsValidCharA and PathAppendA share the same
1332 * ordinal number in some native versions. Check this to prevent a crash.
1334 pPathIsValidCharA = (void*)GetProcAddress(hShlwapi, (LPSTR)455);
1335 if (pPathIsValidCharA && pPathIsValidCharA != (void*)GetProcAddress(hShlwapi, "PathAppendA"))
1337 test_PathIsValidCharA();
1339 pPathIsValidCharW = (void*)GetProcAddress(hShlwapi, (LPSTR)456);
1340 if (pPathIsValidCharW) test_PathIsValidCharW();
1343 pPathCombineW = (void*)GetProcAddress(hShlwapi, "PathCombineW");
1344 if (pPathCombineW)
1345 test_PathCombineW();
1347 test_PathCombineA();
1348 test_PathAppendA();
1349 test_PathCanonicalizeA();
1350 test_PathFindExtensionA();
1351 test_PathBuildRootA();
1352 test_PathCommonPrefixA();
1353 test_PathUnquoteSpaces();