shlwapi/tests: Fix a few test failures on Win95 and some W2K.
[wine/hacks.git] / dlls / shlwapi / tests / path.c
blob2260d884c7fa1034092bd2c6adcfdfc8689e8c84
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);
36 /* ################ */
38 struct {
39 const char *url;
40 const char *path;
41 DWORD ret;
42 } TEST_PATHFROMURL[] = {
43 {"file:///c:/foo/ba%5Cr", "c:\\foo\\ba\\r", S_OK},
44 {"file:///c:/foo/../ba%5Cr", "c:\\foo\\..\\ba\\r", S_OK},
45 {"file:///host/c:/foo/bar", "\\host\\c:\\foo\\bar", S_OK},
46 {"file://host/c:/foo/bar", "\\\\hostc:\\foo\\bar", S_OK},
47 {"file://host/c:/foo/bar", "\\\\hostc:\\foo\\bar", S_OK},
48 {"file:\\\\host\\c:\\foo\\bar", "\\\\hostc:\\foo\\bar", S_OK},
49 {"file:\\\\host\\ca\\foo\\bar", "\\\\host\\ca\\foo\\bar", S_OK},
50 {"file:\\\\host\\c|\\foo\\bar", "\\\\hostc|\\foo\\bar", S_OK},
51 {"file:\\%5Chost\\c:\\foo\\bar", "\\\\host\\c:\\foo\\bar", S_OK},
52 {"file:\\\\host\\cx:\\foo\\bar", "\\\\host\\cx:\\foo\\bar", S_OK},
53 {"file://c:/foo/bar", "c:\\foo\\bar", S_OK},
54 {"file://c:/d:/foo/bar", "c:\\d:\\foo\\bar", S_OK},
55 {"file://c|/d|/foo/bar", "c:\\d|\\foo\\bar", S_OK},
56 {"file://host/foo/bar", "\\\\host\\foo\\bar", S_OK},
57 {"file:/foo/bar", "\\foo\\bar", S_OK},
58 {"file:/foo/bar/", "\\foo\\bar\\", S_OK},
59 {"file:foo/bar", "foo\\bar", S_OK},
60 {"file:c:/foo/bar", "c:\\foo\\bar", S_OK},
61 {"file:c|/foo/bar", "c:\\foo\\bar", S_OK},
62 {"file:cx|/foo/bar", "cx|\\foo\\bar", S_OK},
63 {"file:////c:/foo/bar", "c:\\foo\\bar", S_OK},
64 /* {"file:////c:/foo/foo%20bar", "c:\\foo\\foo%20bar", S_OK},*/
66 {"c:\\foo\\bar", NULL, E_INVALIDARG},
67 {"foo/bar", NULL, E_INVALIDARG},
68 {"http://foo/bar", NULL, E_INVALIDARG},
73 static struct {
74 const char *path;
75 BOOL expect;
76 } TEST_PATH_IS_URL[] = {
77 {"http://foo/bar", TRUE},
78 {"c:\\foo\\bar", FALSE},
79 {"c:/foo/bar", FALSE},
80 {"foo://foo/bar", TRUE},
81 {"foo\\bar", FALSE},
82 {"foo.bar", FALSE},
83 {"bogusscheme:", TRUE},
84 {"http:partial", TRUE},
85 {"www.winehq.org", FALSE},
86 /* More examples that the user might enter as the browser start page */
87 {"winehq.org", FALSE},
88 {"ftp.winehq.org", FALSE},
89 {"http://winehq.org", TRUE},
90 {"http://www.winehq.org", TRUE},
91 {"https://winehq.org", TRUE},
92 {"https://www.winehq.org", TRUE},
93 {"ftp://winehq.org", TRUE},
94 {"ftp://ftp.winehq.org", TRUE},
95 {"file://does_not_exist.txt", TRUE},
96 {"about:blank", TRUE},
97 {"about:home", TRUE},
98 {"about:mozilla", TRUE},
99 /* scheme is case independent */
100 {"HTTP://www.winehq.org", TRUE},
101 /* a space at the start is not allowed */
102 {" http://www.winehq.org", FALSE},
103 {"", FALSE},
104 {NULL, FALSE}
107 struct {
108 const char *path;
109 const char *result;
110 } TEST_PATH_UNQUOTE_SPACES[] = {
111 { "abcdef", "abcdef" },
112 { "\"abcdef\"", "abcdef" },
113 { "\"abcdef", "\"abcdef" },
114 { "abcdef\"", "abcdef\"" },
115 { "\"\"abcdef\"\"", "\"abcdef\"" },
116 { "abc\"def", "abc\"def" },
117 { "\"abc\"def", "\"abc\"def" },
118 { "\"abc\"def\"", "abc\"def" },
119 { "\'abcdef\'", "\'abcdef\'" },
120 { "\"\"", "" },
121 { "\"", "" }
124 /* ################ */
126 static LPWSTR GetWideString(const char* szString)
128 LPWSTR wszString = HeapAlloc(GetProcessHeap(), 0, (2*INTERNET_MAX_URL_LENGTH) * sizeof(WCHAR));
130 MultiByteToWideChar(0, 0, szString, -1, wszString, INTERNET_MAX_URL_LENGTH);
132 return wszString;
135 static void FreeWideString(LPWSTR wszString)
137 HeapFree(GetProcessHeap(), 0, wszString);
140 static LPSTR strdupA(LPCSTR p)
142 LPSTR ret;
143 DWORD len = (strlen(p) + 1);
144 ret = HeapAlloc(GetProcessHeap(), 0, len);
145 memcpy(ret, p, len);
146 return ret;
149 /* ################ */
151 static void test_PathSearchAndQualify(void)
153 WCHAR path1[] = {'c',':','\\','f','o','o',0};
154 WCHAR expect1[] = {'c',':','\\','f','o','o',0};
155 WCHAR path2[] = {'c',':','f','o','o',0};
156 WCHAR c_drive[] = {'c',':',0};
157 WCHAR foo[] = {'f','o','o',0};
158 WCHAR path3[] = {'\\','f','o','o',0};
159 WCHAR winini[] = {'w','i','n','.','i','n','i',0};
160 WCHAR out[MAX_PATH];
161 WCHAR cur_dir[MAX_PATH];
162 WCHAR dot[] = {'.',0};
164 /* c:\foo */
165 ok(PathSearchAndQualifyW(path1, out, MAX_PATH) != 0,
166 "PathSearchAndQualify rets 0\n");
167 ok(!lstrcmpiW(out, expect1), "strings don't match\n");
169 /* c:foo */
170 ok(PathSearchAndQualifyW(path2, out, MAX_PATH) != 0,
171 "PathSearchAndQualify rets 0\n");
172 GetFullPathNameW(c_drive, MAX_PATH, cur_dir, NULL);
173 PathAddBackslashW(cur_dir);
174 lstrcatW(cur_dir, foo);
175 ok(!lstrcmpiW(out, cur_dir), "strings don't match\n");
177 /* foo */
178 ok(PathSearchAndQualifyW(foo, out, MAX_PATH) != 0,
179 "PathSearchAndQualify rets 0\n");
180 GetFullPathNameW(dot, MAX_PATH, cur_dir, NULL);
181 PathAddBackslashW(cur_dir);
182 lstrcatW(cur_dir, foo);
183 ok(!lstrcmpiW(out, cur_dir), "strings don't match\n");
185 /* \foo */
186 ok(PathSearchAndQualifyW(path3, out, MAX_PATH) != 0,
187 "PathSearchAndQualify rets 0\n");
188 GetFullPathNameW(dot, MAX_PATH, cur_dir, NULL);
189 lstrcpyW(cur_dir + 2, path3);
190 ok(!lstrcmpiW(out, cur_dir), "strings don't match\n");
192 /* win.ini */
193 ok(PathSearchAndQualifyW(winini, out, MAX_PATH) != 0,
194 "PathSearchAndQualify rets 0\n");
195 if(!SearchPathW(NULL, winini, NULL, MAX_PATH, cur_dir, NULL))
196 GetFullPathNameW(winini, MAX_PATH, cur_dir, NULL);
197 ok(!lstrcmpiW(out, cur_dir), "strings don't match\n");
201 static void test_PathCreateFromUrl(void)
203 size_t i;
204 char ret_path[INTERNET_MAX_URL_LENGTH];
205 DWORD len, ret;
206 WCHAR ret_pathW[INTERNET_MAX_URL_LENGTH];
207 WCHAR *pathW, *urlW;
208 static const char url[] = "http://www.winehq.org";
210 /* Check ret_path = NULL */
211 len = sizeof(url);
212 ret = PathCreateFromUrlA(url, NULL, &len, 0);
213 ok ( ret == E_INVALIDARG, "got 0x%08x expected E_INVALIDARG\n", ret);
215 for(i = 0; i < sizeof(TEST_PATHFROMURL) / sizeof(TEST_PATHFROMURL[0]); i++) {
216 len = INTERNET_MAX_URL_LENGTH;
217 ret = PathCreateFromUrlA(TEST_PATHFROMURL[i].url, ret_path, &len, 0);
218 ok(ret == TEST_PATHFROMURL[i].ret, "ret %08x from url %s\n", ret, TEST_PATHFROMURL[i].url);
219 if(TEST_PATHFROMURL[i].path) {
220 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);
221 ok(len == strlen(ret_path), "ret len %d from url %s\n", len, TEST_PATHFROMURL[i].url);
223 len = INTERNET_MAX_URL_LENGTH;
224 pathW = GetWideString(TEST_PATHFROMURL[i].path);
225 urlW = GetWideString(TEST_PATHFROMURL[i].url);
226 ret = PathCreateFromUrlW(urlW, ret_pathW, &len, 0);
227 WideCharToMultiByte(CP_ACP, 0, ret_pathW, -1, ret_path, sizeof(ret_path),0,0);
228 ok(ret == TEST_PATHFROMURL[i].ret, "ret %08x from url L\"%s\"\n", ret, TEST_PATHFROMURL[i].url);
229 if(TEST_PATHFROMURL[i].path) {
230 ok(!lstrcmpiW(ret_pathW, pathW), "got %s expected %s from url L\"%s\"\n", ret_path, TEST_PATHFROMURL[i].path, TEST_PATHFROMURL[i].url);
231 ok(len == lstrlenW(ret_pathW), "ret len %d from url L\"%s\"\n", len, TEST_PATHFROMURL[i].url);
233 FreeWideString(urlW);
234 FreeWideString(pathW);
239 static void test_PathIsUrl(void)
241 size_t i;
242 BOOL ret;
244 for(i = 0; i < sizeof(TEST_PATH_IS_URL)/sizeof(TEST_PATH_IS_URL[0]); i++) {
245 ret = PathIsURLA(TEST_PATH_IS_URL[i].path);
246 ok(ret == TEST_PATH_IS_URL[i].expect,
247 "returned %d from path %s, expected %d\n", ret, TEST_PATH_IS_URL[i].path,
248 TEST_PATH_IS_URL[i].expect);
252 static const DWORD SHELL_charclass[] =
254 0x00000000, 0x00000000, 0x00000000, 0x00000000,
255 0x00000000, 0x00000000, 0x00000000, 0x00000000,
256 0x00000000, 0x00000000, 0x00000000, 0x00000000,
257 0x00000000, 0x00000000, 0x00000000, 0x00000000,
258 0x00000000, 0x00000000, 0x00000000, 0x00000000,
259 0x00000000, 0x00000000, 0x00000000, 0x00000000,
260 0x00000000, 0x00000000, 0x00000000, 0x00000000,
261 0x00000000, 0x00000000, 0x00000000, 0x00000000,
262 0x00000080, 0x00000100, 0x00000200, 0x00000100,
263 0x00000100, 0x00000100, 0x00000100, 0x00000100,
264 0x00000100, 0x00000100, 0x00000002, 0x00000100,
265 0x00000040, 0x00000100, 0x00000004, 0x00000000,
266 0x00000100, 0x00000100, 0x00000100, 0x00000100,
267 0x00000100, 0x00000100, 0x00000100, 0x00000100,
268 0x00000100, 0x00000100, 0x00000010, 0x00000020,
269 0x00000000, 0x00000100, 0x00000000, 0x00000001,
270 0x00000100, 0xffffffff, 0xffffffff, 0xffffffff,
271 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
272 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
273 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
274 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
275 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
276 0xffffffff, 0xffffffff, 0xffffffff, 0x00000100,
277 0x00000008, 0x00000100, 0x00000100, 0x00000100,
278 0x00000100, 0xffffffff, 0xffffffff, 0xffffffff,
279 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
280 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
281 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
282 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
283 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
284 0xffffffff, 0xffffffff, 0xffffffff, 0x00000100,
285 0x00000000, 0x00000100, 0x00000100
288 static void test_PathIsValidCharA(void)
290 BOOL ret;
291 unsigned int c;
293 for (c = 0; c < 0x7f; c++)
295 ret = pPathIsValidCharA( c, ~0U );
296 ok ( ret || !SHELL_charclass[c], "PathIsValidCharA failed: 0x%02x got 0x%08x\n", c, ret );
299 for (c = 0x7f; c <= 0xff; c++)
301 ret = pPathIsValidCharA( c, ~0U );
302 ok ( ret, "PathIsValidCharA failed: 0x%02x got 0x%08x\n", c, ret );
306 static void test_PathIsValidCharW(void)
308 BOOL ret;
309 unsigned int c;
311 for (c = 0; c < 0x7f; c++)
313 ret = pPathIsValidCharW( c, ~0U );
314 ok ( ret || !SHELL_charclass[c], "PathIsValidCharW failed: 0x%02x got 0x%08x\n", c, ret );
317 for (c = 0x007f; c <= 0xffff; c++)
319 ret = pPathIsValidCharW( c, ~0U );
320 ok ( ret, "PathIsValidCharW failed: 0x%02x got 0x%08x\n", c, ret );
324 static void test_PathMakePretty(void)
326 char buff[MAX_PATH];
328 ok (PathMakePrettyA(NULL) == FALSE, "PathMakePretty: NULL path succeeded\n");
329 buff[0] = '\0';
330 ok (PathMakePrettyA(buff) == TRUE, "PathMakePretty: Empty path failed\n");
332 strcpy(buff, "C:\\A LONG FILE NAME WITH \\SPACES.TXT");
333 ok (PathMakePrettyA(buff) == TRUE, "PathMakePretty: Long UC name failed\n");
334 ok (strcmp(buff, "C:\\a long file name with \\spaces.txt") == 0,
335 "PathMakePretty: Long UC name not changed\n");
337 strcpy(buff, "C:\\A LONG FILE NAME WITH \\MixedCase.TXT");
338 ok (PathMakePrettyA(buff) == FALSE, "PathMakePretty: Long MC name succeeded\n");
339 ok (strcmp(buff, "C:\\A LONG FILE NAME WITH \\MixedCase.TXT") == 0,
340 "PathMakePretty: Failed but modified path\n");
342 strcpy(buff, "TEST");
343 ok (PathMakePrettyA(buff) == TRUE, "PathMakePretty: Short name failed\n");
344 ok (strcmp(buff, "Test") == 0, "PathMakePretty: 1st char lowercased %s\n", buff);
347 static void test_PathMatchSpec(void)
349 static const char file[] = "c:\\foo\\bar\\filename.ext";
350 static const char spec1[] = ".ext";
351 static const char spec2[] = "*.ext";
352 static const char spec3[] = "*.ext ";
353 static const char spec4[] = " *.ext";
354 static const char spec5[] = "* .ext";
355 static const char spec6[] = "*. ext";
356 static const char spec7[] = "* . ext";
357 static const char spec8[] = "*.e?t";
358 static const char spec9[] = "filename.ext";
359 static const char spec10[] = "*bar\\filename.ext";
360 static const char spec11[] = " foo; *.ext";
361 static const char spec12[] = "*.ext;*.bar";
362 static const char spec13[] = "*bar*";
364 ok (PathMatchSpecA(file, spec1) == FALSE, "PathMatchSpec: Spec1 failed\n");
365 ok (PathMatchSpecA(file, spec2) == TRUE, "PathMatchSpec: Spec2 failed\n");
366 ok (PathMatchSpecA(file, spec3) == FALSE, "PathMatchSpec: Spec3 failed\n");
367 ok (PathMatchSpecA(file, spec4) == TRUE, "PathMatchSpec: Spec4 failed\n");
368 todo_wine ok (PathMatchSpecA(file, spec5) == TRUE, "PathMatchSpec: Spec5 failed\n");
369 todo_wine ok (PathMatchSpecA(file, spec6) == TRUE, "PathMatchSpec: Spec6 failed\n");
370 ok (PathMatchSpecA(file, spec7) == FALSE, "PathMatchSpec: Spec7 failed\n");
371 ok (PathMatchSpecA(file, spec8) == TRUE, "PathMatchSpec: Spec8 failed\n");
372 ok (PathMatchSpecA(file, spec9) == FALSE, "PathMatchSpec: Spec9 failed\n");
373 ok (PathMatchSpecA(file, spec10) == TRUE, "PathMatchSpec: Spec10 failed\n");
374 ok (PathMatchSpecA(file, spec11) == TRUE, "PathMatchSpec: Spec11 failed\n");
375 ok (PathMatchSpecA(file, spec12) == TRUE, "PathMatchSpec: Spec12 failed\n");
376 ok (PathMatchSpecA(file, spec13) == TRUE, "PathMatchSpec: Spec13 failed\n");
379 static void test_PathCombineW(void)
381 LPWSTR wszString, wszString2;
382 WCHAR wbuf[MAX_PATH+1], wstr1[MAX_PATH] = {'C',':','\\',0}, wstr2[MAX_PATH];
383 static const WCHAR expout[] = {'C',':','\\','A','A',0};
384 int i;
386 wszString2 = HeapAlloc(GetProcessHeap(), 0, MAX_PATH * sizeof(WCHAR));
388 /* NULL test */
389 wszString = pPathCombineW(NULL, NULL, NULL);
390 ok (wszString == NULL, "Expected a NULL return\n");
392 /* Some NULL */
393 wszString2[0] = 'a';
394 wszString = pPathCombineW(wszString2, NULL, NULL);
395 ok (wszString == NULL ||
396 broken(wszString[0] = 'a'), /* Win95 and some W2K */
397 "Expected a NULL return\n");
398 ok (wszString2[0] == 0 ||
399 broken(wszString[0] = 'a'), /* Win95 and some W2K */
400 "Destination string not empty\n");
402 HeapFree(GetProcessHeap(), 0, wszString2);
404 /* overflow test */
405 wstr2[0] = wstr2[1] = wstr2[2] = 'A';
406 for (i=3; i<MAX_PATH/2; i++)
407 wstr1[i] = wstr2[i] = 'A';
408 wstr1[(MAX_PATH/2) - 1] = wstr2[MAX_PATH/2] = 0;
409 memset(wbuf, 0xbf, sizeof(wbuf));
411 wszString = pPathCombineW(wbuf, wstr1, wstr2);
412 ok(wszString == NULL, "Expected a NULL return\n");
413 ok(wbuf[0] == 0, "Buffer contains data\n");
415 /* PathCombineW can be used in place */
416 wstr1[3] = 0;
417 wstr2[2] = 0;
418 ok(PathCombineW(wstr1, wstr1, wstr2) == wstr1, "Expected a wstr1 return\n");
419 ok(StrCmpW(wstr1, expout) == 0, "Unexpected PathCombine output\n");
423 #define LONG_LEN (MAX_PATH * 2)
424 #define HALF_LEN (MAX_PATH / 2 + 1)
426 static void test_PathCombineA(void)
428 LPSTR str;
429 char dest[MAX_PATH];
430 char too_long[LONG_LEN];
431 char one[HALF_LEN], two[HALF_LEN];
433 /* try NULL dest */
434 SetLastError(0xdeadbeef);
435 str = PathCombineA(NULL, "C:\\", "one\\two\\three");
436 ok(str == NULL, "Expected NULL, got %p\n", str);
437 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
439 /* try NULL dest and NULL directory */
440 SetLastError(0xdeadbeef);
441 str = PathCombineA(NULL, NULL, "one\\two\\three");
442 ok(str == NULL, "Expected NULL, got %p\n", str);
443 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
445 /* try all NULL*/
446 SetLastError(0xdeadbeef);
447 str = PathCombineA(NULL, NULL, NULL);
448 ok(str == NULL, "Expected NULL, got %p\n", str);
449 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
451 /* try NULL file part */
452 SetLastError(0xdeadbeef);
453 lstrcpyA(dest, "control");
454 str = PathCombineA(dest, "C:\\", NULL);
455 ok(str == dest, "Expected str == dest, got %p\n", str);
456 ok(!lstrcmp(str, "C:\\"), "Expected C:\\, got %s\n", str);
457 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
459 /* try empty file part */
460 SetLastError(0xdeadbeef);
461 lstrcpyA(dest, "control");
462 str = PathCombineA(dest, "C:\\", "");
463 ok(str == dest, "Expected str == dest, got %p\n", str);
464 ok(!lstrcmp(str, "C:\\"), "Expected C:\\, got %s\n", str);
465 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
467 /* try empty directory and file part */
468 SetLastError(0xdeadbeef);
469 lstrcpyA(dest, "control");
470 str = PathCombineA(dest, "", "");
471 ok(str == dest, "Expected str == dest, got %p\n", str);
472 ok(!lstrcmp(str, "\\"), "Expected \\, got %s\n", str);
473 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
475 /* try NULL directory */
476 SetLastError(0xdeadbeef);
477 lstrcpyA(dest, "control");
478 str = PathCombineA(dest, NULL, "one\\two\\three");
479 ok(str == dest, "Expected str == dest, got %p\n", str);
480 ok(!lstrcmp(str, "one\\two\\three"), "Expected one\\two\\three, got %s\n", str);
481 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
483 /* try NULL directory and empty file part */
484 SetLastError(0xdeadbeef);
485 lstrcpyA(dest, "control");
486 str = PathCombineA(dest, NULL, "");
487 ok(str == dest, "Expected str == dest, got %p\n", str);
488 ok(!lstrcmp(str, "\\"), "Expected \\, got %s\n", str);
489 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
491 /* try NULL directory and file part */
492 SetLastError(0xdeadbeef);
493 lstrcpyA(dest, "control");
494 str = PathCombineA(dest, NULL, NULL);
495 ok(str == NULL, "Expected str == NULL, got %p\n", str);
496 ok(lstrlenA(dest) == 0 ||
497 broken(!lstrcmp(dest, "control")), /* Win95 and some W2K */
498 "Expected 0 length, got %i\n", lstrlenA(dest));
499 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
501 /* try directory without backslash */
502 SetLastError(0xdeadbeef);
503 lstrcpyA(dest, "control");
504 str = PathCombineA(dest, "C:", "one\\two\\three");
505 ok(str == dest, "Expected str == dest, got %p\n", str);
506 ok(!lstrcmp(str, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", str);
507 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
509 /* try directory with backslash */
510 SetLastError(0xdeadbeef);
511 lstrcpyA(dest, "control");
512 str = PathCombineA(dest, "C:\\", "one\\two\\three");
513 ok(str == dest, "Expected str == dest, got %p\n", str);
514 ok(!lstrcmp(str, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", str);
515 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
517 /* try directory with backslash and file with prepended backslash */
518 SetLastError(0xdeadbeef);
519 lstrcpyA(dest, "control");
520 str = PathCombineA(dest, "C:\\", "\\one\\two\\three");
521 ok(str == dest, "Expected str == dest, got %p\n", str);
522 ok(!lstrcmp(str, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", str);
523 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
525 /* try previous test, with backslash appended as well */
526 SetLastError(0xdeadbeef);
527 lstrcpyA(dest, "control");
528 str = PathCombineA(dest, "C:\\", "\\one\\two\\three\\");
529 ok(str == dest, "Expected str == dest, got %p\n", str);
530 ok(!lstrcmp(str, "C:\\one\\two\\three\\"), "Expected C:\\one\\two\\three\\, got %s\n", str);
531 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
533 /* try a relative directory */
534 SetLastError(0xdeadbeef);
535 lstrcpyA(dest, "control");
536 str = PathCombineA(dest, "relative\\dir", "\\one\\two\\three\\");
537 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
538 /* Vista fails which probably makes sense as PathCombineA expects an absolute dir */
539 if (str)
541 ok(str == dest, "Expected str == dest, got %p\n", str);
542 ok(!lstrcmp(str, "one\\two\\three\\"), "Expected one\\two\\three\\, got %s\n", str);
545 /* try forward slashes */
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 one/two/three\\, got %s\n", str);
551 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
553 /* try a really weird directory */
554 SetLastError(0xdeadbeef);
555 lstrcpyA(dest, "control");
556 str = PathCombineA(dest, "C:\\/\\/", "\\one\\two\\three\\");
557 ok(str == dest, "Expected str == dest, got %p\n", str);
558 ok(!lstrcmp(str, "C:\\one\\two\\three\\"), "Expected C:\\one\\two\\three\\, got %s\n", str);
559 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
561 /* try periods */
562 SetLastError(0xdeadbeef);
563 lstrcpyA(dest, "control");
564 str = PathCombineA(dest, "C:\\", "one\\..\\two\\.\\three");
565 ok(str == dest, "Expected str == dest, got %p\n", str);
566 ok(!lstrcmp(str, "C:\\two\\three"), "Expected C:\\two\\three, got %s\n", str);
567 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
569 /* try .. as file */
570 /* try forward slashes */
571 SetLastError(0xdeadbeef);
572 lstrcpyA(dest, "control");
573 str = PathCombineA(dest, "C:\\", "..");
574 ok(str == dest, "Expected str == dest, got %p\n", str);
575 ok(!lstrcmp(str, "C:\\"), "Expected C:\\, got %s\n", str);
576 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
578 memset(too_long, 'a', LONG_LEN);
579 too_long[LONG_LEN - 1] = '\0';
581 /* try a file longer than MAX_PATH */
582 SetLastError(0xdeadbeef);
583 lstrcpyA(dest, "control");
584 str = PathCombineA(dest, "C:\\", too_long);
585 ok(str == NULL, "Expected str == NULL, got %p\n", str);
586 ok(lstrlenA(dest) == 0 ||
587 broken(!lstrcmp(dest, "control")), /* Win95 and some W2K */
588 "Expected 0 length, got %i\n", lstrlenA(dest));
589 todo_wine ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
591 /* try a directory longer than MAX_PATH */
592 SetLastError(0xdeadbeef);
593 lstrcpyA(dest, "control");
594 str = PathCombineA(dest, too_long, "one\\two\\three");
595 ok(str == NULL, "Expected str == NULL, got %p\n", str);
596 ok(lstrlenA(dest) == 0 ||
597 broken(!lstrcmp(dest, "control")), /* Win95 and some W2K */
598 "Expected 0 length, got %i\n", lstrlenA(dest));
599 todo_wine ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
601 memset(one, 'b', HALF_LEN);
602 memset(two, 'c', HALF_LEN);
603 one[HALF_LEN - 1] = '\0';
604 two[HALF_LEN - 1] = '\0';
606 /* destination string is longer than MAX_PATH, but not the constituent parts */
607 SetLastError(0xdeadbeef);
608 lstrcpyA(dest, "control");
609 str = PathCombineA(dest, one, two);
610 ok(str == NULL, "Expected str == NULL, got %p\n", str);
611 ok(lstrlenA(dest) == 0 ||
612 broken(!lstrcmp(dest, "control")), /* Win95 and some W2K */
613 "Expected 0 length, got %i\n", lstrlenA(dest));
614 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
617 static void test_PathAddBackslash(void)
619 LPSTR str;
620 char path[MAX_PATH];
621 char too_long[LONG_LEN];
623 /* try a NULL path */
624 SetLastError(0xdeadbeef);
625 str = PathAddBackslashA(NULL);
626 ok(str == NULL, "Expected str == NULL, got %p\n", str);
627 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
629 /* try an empty path */
630 path[0] = '\0';
631 SetLastError(0xdeadbeef);
632 str = PathAddBackslashA(path);
633 ok(str == (path + lstrlenA(path)), "Expected str to point to end of path, got %p\n", str);
634 ok(lstrlenA(path) == 0, "Expected empty string, got %i\n", lstrlenA(path));
635 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
637 /* try a relative path */
638 lstrcpyA(path, "one\\two");
639 SetLastError(0xdeadbeef);
640 str = PathAddBackslashA(path);
641 ok(str == (path + lstrlenA(path)), "Expected str to point to end of path, got %p\n", str);
642 ok(!lstrcmp(path, "one\\two\\"), "Expected one\\two\\, got %s\n", path);
643 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
645 /* try periods */
646 lstrcpyA(path, "one\\..\\two");
647 SetLastError(0xdeadbeef);
648 str = PathAddBackslashA(path);
649 ok(str == (path + lstrlenA(path)), "Expected str to point to end of path, got %p\n", str);
650 ok(!lstrcmp(path, "one\\..\\two\\"), "Expected one\\..\\two\\, got %s\n", path);
651 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
653 /* try just a space */
654 lstrcpyA(path, " ");
655 SetLastError(0xdeadbeef);
656 str = PathAddBackslashA(path);
657 ok(str == (path + lstrlenA(path)), "Expected str to point to end of path, got %p\n", str);
658 ok(!lstrcmp(path, " \\"), "Expected \\, got %s\n", path);
659 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
661 /* path already has backslash */
662 lstrcpyA(path, "C:\\one\\");
663 SetLastError(0xdeadbeef);
664 str = PathAddBackslashA(path);
665 ok(str == (path + lstrlenA(path)), "Expected str to point to end of path, got %p\n", str);
666 ok(!lstrcmp(path, "C:\\one\\"), "Expected C:\\one\\, got %s\n", path);
667 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
669 memset(too_long, 'a', LONG_LEN);
670 too_long[LONG_LEN - 1] = '\0';
672 /* path is longer than MAX_PATH */
673 SetLastError(0xdeadbeef);
674 str = PathAddBackslashA(too_long);
675 ok(str == NULL, "Expected str == NULL, got %p\n", str);
676 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
679 static void test_PathAppendA(void)
681 char path[MAX_PATH];
682 char too_long[LONG_LEN];
683 char one[HALF_LEN], two[HALF_LEN];
684 BOOL res;
686 lstrcpy(path, "C:\\one");
688 /* try NULL pszMore */
689 SetLastError(0xdeadbeef);
690 res = PathAppendA(path, NULL);
691 ok(!res, "Expected failure\n");
692 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
693 ok(!lstrcmp(path, "C:\\one"), "Expected C:\\one, got %s\n", path);
695 /* try empty pszMore */
696 SetLastError(0xdeadbeef);
697 res = PathAppendA(path, "");
698 ok(res, "Expected success\n");
699 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
700 ok(!lstrcmp(path, "C:\\one"), "Expected C:\\one, got %s\n", path);
702 /* try NULL pszPath */
703 SetLastError(0xdeadbeef);
704 res = PathAppendA(NULL, "two\\three");
705 ok(!res, "Expected failure\n");
706 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
708 /* try empty pszPath */
709 path[0] = '\0';
710 SetLastError(0xdeadbeef);
711 res = PathAppendA(path, "two\\three");
712 ok(res, "Expected success\n");
713 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
714 ok(!lstrcmp(path, "two\\three"), "Expected \\two\\three, got %s\n", path);
716 /* try empty pszPath and empty pszMore */
717 path[0] = '\0';
718 SetLastError(0xdeadbeef);
719 res = PathAppendA(path, "");
720 ok(res, "Expected success\n");
721 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
722 ok(!lstrcmp(path, "\\"), "Expected \\, got %s\n", path);
724 /* try legit params */
725 lstrcpy(path, "C:\\one");
726 SetLastError(0xdeadbeef);
727 res = PathAppendA(path, "two\\three");
728 ok(res, "Expected success\n");
729 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
730 ok(!lstrcmp(path, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", path);
732 /* try pszPath with backslash after it */
733 lstrcpy(path, "C:\\one\\");
734 SetLastError(0xdeadbeef);
735 res = PathAppendA(path, "two\\three");
736 ok(res, "Expected success\n");
737 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
738 ok(!lstrcmp(path, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", path);
740 /* try pszMore with backslash before it */
741 lstrcpy(path, "C:\\one");
742 SetLastError(0xdeadbeef);
743 res = PathAppendA(path, "\\two\\three");
744 ok(res, "Expected success\n");
745 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
746 ok(!lstrcmp(path, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", path);
748 /* try pszMore with backslash after it */
749 lstrcpy(path, "C:\\one");
750 SetLastError(0xdeadbeef);
751 res = PathAppendA(path, "two\\three\\");
752 ok(res, "Expected success\n");
753 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
754 ok(!lstrcmp(path, "C:\\one\\two\\three\\"), "Expected C:\\one\\two\\three\\, got %s\n", path);
756 /* try spaces in pszPath */
757 lstrcpy(path, "C: \\ one ");
758 SetLastError(0xdeadbeef);
759 res = PathAppendA(path, "two\\three");
760 ok(res, "Expected success\n");
761 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
762 ok(!lstrcmp(path, "C: \\ one \\two\\three"), "Expected C: \\ one \\two\\three, got %s\n", path);
764 /* try spaces in pszMore */
765 lstrcpy(path, "C:\\one");
766 SetLastError(0xdeadbeef);
767 res = PathAppendA(path, " two \\ three ");
768 ok(res, "Expected success\n");
769 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
770 ok(!lstrcmp(path, "C:\\one\\ two \\ three "), "Expected 'C:\\one\\ two \\ three ', got %s\n", path);
772 /* pszPath is too long */
773 memset(too_long, 'a', LONG_LEN);
774 too_long[LONG_LEN - 1] = '\0';
775 SetLastError(0xdeadbeef);
776 res = PathAppendA(too_long, "two\\three");
777 ok(!res, "Expected failure\n");
778 todo_wine ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
779 ok(lstrlen(too_long) == 0, "Expected length of too_long to be zero, got %i\n", lstrlen(too_long));
781 /* pszMore is too long */
782 lstrcpy(path, "C:\\one");
783 memset(too_long, 'a', LONG_LEN);
784 too_long[LONG_LEN - 1] = '\0';
785 SetLastError(0xdeadbeef);
786 res = PathAppendA(path, too_long);
787 ok(!res, "Expected failure\n");
788 todo_wine ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
789 ok(lstrlen(path) == 0, "Expected length of path to be zero, got %i\n", lstrlen(path));
791 /* both params combined are too long */
792 memset(one, 'a', HALF_LEN);
793 one[HALF_LEN - 1] = '\0';
794 memset(two, 'b', HALF_LEN);
795 two[HALF_LEN - 1] = '\0';
796 SetLastError(0xdeadbeef);
797 res = PathAppendA(one, two);
798 ok(!res, "Expected failure\n");
799 ok(lstrlen(one) == 0, "Expected length of one to be zero, got %i\n", lstrlen(one));
800 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
803 static void test_PathCanonicalizeA(void)
805 char dest[LONG_LEN + MAX_PATH];
806 char too_long[LONG_LEN];
807 BOOL res;
809 /* try a NULL source */
810 lstrcpy(dest, "test");
811 SetLastError(0xdeadbeef);
812 res = PathCanonicalizeA(dest, NULL);
813 ok(!res, "Expected failure\n");
814 ok(GetLastError() == ERROR_INVALID_PARAMETER,
815 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
816 ok(dest[0] == 0 || !lstrcmp(dest, "test"),
817 "Expected either an empty string (Vista) or test, got %s\n", dest);
819 /* try an empty source */
820 lstrcpy(dest, "test");
821 SetLastError(0xdeadbeef);
822 res = PathCanonicalizeA(dest, "");
823 ok(res, "Expected success\n");
824 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
825 ok(!lstrcmp(dest, "\\"), "Expected \\, got %s\n", dest);
827 /* try a NULL dest */
828 SetLastError(0xdeadbeef);
829 res = PathCanonicalizeA(NULL, "C:\\");
830 ok(!res, "Expected failure\n");
831 ok(GetLastError() == ERROR_INVALID_PARAMETER,
832 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
834 /* try empty dest */
835 dest[0] = '\0';
836 SetLastError(0xdeadbeef);
837 res = PathCanonicalizeA(dest, "C:\\");
838 ok(res, "Expected success\n");
839 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
840 ok(!lstrcmp(dest, "C:\\"), "Expected C:\\, got %s\n", dest);
842 /* try non-empty dest */
843 lstrcpy(dest, "test");
844 SetLastError(0xdeadbeef);
845 res = PathCanonicalizeA(dest, "C:\\");
846 ok(res, "Expected success\n");
847 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
848 ok(!lstrcmp(dest, "C:\\"), "Expected C:\\, got %s\n", dest);
850 /* try a space for source */
851 lstrcpy(dest, "test");
852 SetLastError(0xdeadbeef);
853 res = PathCanonicalizeA(dest, " ");
854 ok(res, "Expected success\n");
855 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
856 ok(!lstrcmp(dest, " "), "Expected ' ', got %s\n", dest);
858 /* try a relative path */
859 lstrcpy(dest, "test");
860 SetLastError(0xdeadbeef);
861 res = PathCanonicalizeA(dest, "one\\two");
862 ok(res, "Expected success\n");
863 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
864 ok(!lstrcmp(dest, "one\\two"), "Expected one\\two, got %s\n", dest);
866 /* try current dir and previous dir */
867 lstrcpy(dest, "test");
868 SetLastError(0xdeadbeef);
869 res = PathCanonicalizeA(dest, "C:\\one\\.\\..\\two\\three\\..");
870 ok(res, "Expected success\n");
871 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
872 ok(!lstrcmp(dest, "C:\\two"), "Expected C:\\two, got %s\n", dest);
874 /* try simple forward slashes */
875 lstrcpy(dest, "test");
876 SetLastError(0xdeadbeef);
877 res = PathCanonicalizeA(dest, "C:\\one/two/three\\four/five\\six");
878 ok(res, "Expected success\n");
879 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
880 ok(!lstrcmp(dest, "C:\\one/two/three\\four/five\\six"),
881 "Expected C:\\one/two/three\\four/five\\six, got %s\n", dest);
883 /* try simple forward slashes with same dir */
884 lstrcpy(dest, "test");
885 SetLastError(0xdeadbeef);
886 res = PathCanonicalizeA(dest, "C:\\one/.\\two");
887 ok(res, "Expected success\n");
888 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
889 ok(!lstrcmp(dest, "C:\\one/.\\two"), "Expected C:\\one/.\\two, got %s\n", dest);
891 /* try simple forward slashes with change dir */
892 lstrcpy(dest, "test");
893 SetLastError(0xdeadbeef);
894 res = PathCanonicalizeA(dest, "C:\\one/.\\two\\..");
895 ok(res, "Expected success\n");
896 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
897 ok(!lstrcmp(dest, "C:\\one/.") ||
898 !lstrcmp(dest, "C:\\one/"), /* Vista */
899 "Expected \"C:\\one/.\" or \"C:\\one/\", got \"%s\"\n", dest);
901 /* try forward slashes with change dirs
902 * NOTE: if there is a forward slash in between two backslashes,
903 * everything in between the two backslashes is considered on dir
905 lstrcpy(dest, "test");
906 SetLastError(0xdeadbeef);
907 res = PathCanonicalizeA(dest, "C:\\one/.\\..\\two/three\\..\\four/.five");
908 ok(res, "Expected success\n");
909 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
910 ok(!lstrcmp(dest, "C:\\four/.five"), "Expected C:\\four/.five, got %s\n", dest);
912 /* try src is too long */
913 memset(too_long, 'a', LONG_LEN);
914 too_long[LONG_LEN - 1] = '\0';
915 lstrcpy(dest, "test");
916 SetLastError(0xdeadbeef);
917 res = PathCanonicalizeA(dest, too_long);
918 ok(!res, "Expected failure\n");
919 todo_wine
921 ok(GetLastError() == 0xdeadbeef || GetLastError() == ERROR_FILENAME_EXCED_RANGE /* Vista */,
922 "Expected 0xdeadbeef or ERROR_FILENAME_EXCED_RANGE, got %d\n", GetLastError());
924 ok(lstrlen(too_long) == LONG_LEN - 1, "Expected length LONG_LEN - 1, got %i\n", lstrlen(too_long));
927 static void test_PathFindExtensionA(void)
929 LPSTR ext;
930 char path[MAX_PATH];
931 char too_long[LONG_LEN];
933 /* try a NULL path */
934 SetLastError(0xdeadbeef);
935 ext = PathFindExtensionA(NULL);
936 ok(ext == NULL, "Expected NULL, got %p\n", ext);
937 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
939 /* try an empty path */
940 path[0] = '\0';
941 SetLastError(0xdeadbeef);
942 ext = PathFindExtensionA(path);
943 ok(ext == path, "Expected ext == path, got %p\n", ext);
944 ok(lstrlen(ext) == 0, "Expected length 0, got %i\n", lstrlen(ext));
945 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
947 /* try a path without an extension */
948 lstrcpy(path, "file");
949 SetLastError(0xdeadbeef);
950 ext = PathFindExtensionA(path);
951 ok(ext == path + lstrlen(path), "Expected ext == path, got %p\n", ext);
952 ok(lstrlen(ext) == 0, "Expected length 0, got %i\n", lstrlen(ext));
953 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
955 /* try a path with an extension */
956 lstrcpy(path, "file.txt");
957 SetLastError(0xdeadbeef);
958 ext = PathFindExtensionA(path);
959 ok(ext == path + lstrlen("file"),
960 "Expected ext == path + lstrlen(\"file\"), got %p\n", ext);
961 ok(!lstrcmp(ext, ".txt"), "Expected .txt, got %s\n", ext);
962 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
964 /* try a path with two extensions */
965 lstrcpy(path, "file.txt.doc");
966 SetLastError(0xdeadbeef);
967 ext = PathFindExtensionA(path);
968 ok(ext == path + lstrlen("file.txt"),
969 "Expected ext == path + lstrlen(\"file.txt\"), got %p\n", ext);
970 ok(!lstrcmp(ext, ".doc"), "Expected .txt, got %s\n", ext);
971 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
973 /* try a path longer than MAX_PATH without an extension*/
974 memset(too_long, 'a', LONG_LEN);
975 too_long[LONG_LEN - 1] = '\0';
976 SetLastError(0xdeadbeef);
977 ext = PathFindExtensionA(too_long);
978 ok(ext == too_long + LONG_LEN - 1, "Expected ext == too_long + LONG_LEN - 1, got %p\n", ext);
979 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
981 /* try a path longer than MAX_PATH with an extension*/
982 memset(too_long, 'a', LONG_LEN);
983 too_long[LONG_LEN - 1] = '\0';
984 lstrcpy(too_long + 300, ".abcde");
985 too_long[lstrlen(too_long)] = 'a';
986 SetLastError(0xdeadbeef);
987 ext = PathFindExtensionA(too_long);
988 ok(ext == too_long + 300, "Expected ext == too_long + 300, got %p\n", ext);
989 ok(lstrlen(ext) == LONG_LEN - 301, "Expected LONG_LEN - 301, got %i\n", lstrlen(ext));
990 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
993 static void test_PathBuildRootA(void)
995 LPSTR root;
996 char path[10];
997 char root_expected[26][4];
998 char drive;
999 int j;
1001 /* set up the expected paths */
1002 for (drive = 'A'; drive <= 'Z'; drive++)
1003 sprintf(root_expected[drive - 'A'], "%c:\\", drive);
1005 /* test the expected values */
1006 for (j = 0; j < 26; j++)
1008 SetLastError(0xdeadbeef);
1009 lstrcpy(path, "aaaaaaaaa");
1010 root = PathBuildRootA(path, j);
1011 ok(root == path, "Expected root == path, got %p\n", root);
1012 ok(!lstrcmp(root, root_expected[j]), "Expected %s, got %s\n", root_expected[j], root);
1013 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1016 /* test a negative drive number */
1017 SetLastError(0xdeadbeef);
1018 lstrcpy(path, "aaaaaaaaa");
1019 root = PathBuildRootA(path, -1);
1020 ok(root == path, "Expected root == path, got %p\n", root);
1021 ok(!lstrcmp(path, "aaaaaaaaa") ||
1022 lstrlenA(path) == 0, /* Vista */
1023 "Expected aaaaaaaaa or empty string, got %s\n", path);
1024 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1026 /* test a drive number greater than 25 */
1027 SetLastError(0xdeadbeef);
1028 lstrcpy(path, "aaaaaaaaa");
1029 root = PathBuildRootA(path, 26);
1030 ok(root == path, "Expected root == path, got %p\n", root);
1031 ok(!lstrcmp(path, "aaaaaaaaa") ||
1032 lstrlenA(path) == 0, /* Vista */
1033 "Expected aaaaaaaaa or empty string, got %s\n", path);
1034 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1036 /* length of path is less than 4 */
1037 SetLastError(0xdeadbeef);
1038 lstrcpy(path, "aa");
1039 root = PathBuildRootA(path, 0);
1040 ok(root == path, "Expected root == path, got %p\n", root);
1041 ok(!lstrcmp(path, "A:\\"), "Expected A:\\, got %s\n", path);
1042 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1044 /* path is NULL */
1045 SetLastError(0xdeadbeef);
1046 root = PathBuildRootA(NULL, 0);
1047 ok(root == NULL, "Expected root == NULL, got %p\n", root);
1048 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1051 static void test_PathCommonPrefixA(void)
1053 char path1[MAX_PATH], path2[MAX_PATH];
1054 char out[MAX_PATH];
1055 int count;
1057 /* test NULL path1 */
1058 SetLastError(0xdeadbeef);
1059 lstrcpy(path2, "C:\\");
1060 lstrcpy(out, "aaa");
1061 count = PathCommonPrefixA(NULL, path2, out);
1062 ok(count == 0, "Expected 0, got %i\n", count);
1063 todo_wine
1065 ok(!lstrcmp(out, "aaa"), "Expected aaa, got %s\n", out);
1067 ok(!lstrcmp(path2, "C:\\"), "Expected C:\\, got %s\n", path2);
1068 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1070 /* test NULL path2 */
1071 SetLastError(0xdeadbeef);
1072 lstrcpy(path1, "C:\\");
1073 lstrcpy(out, "aaa");
1074 count = PathCommonPrefixA(path1, NULL, out);
1075 ok(count == 0, "Expected 0, got %i\n", count);
1076 todo_wine
1078 ok(!lstrcmp(out, "aaa"), "Expected aaa, got %s\n", out);
1080 ok(!lstrcmp(path1, "C:\\"), "Expected C:\\, got %s\n", path1);
1081 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1083 /* test empty path1 */
1084 SetLastError(0xdeadbeef);
1085 path1[0] = '\0';
1086 lstrcpy(path2, "C:\\");
1087 lstrcpy(out, "aaa");
1088 count = PathCommonPrefixA(path1, path2, out);
1089 ok(count == 0, "Expected 0, got %i\n", count);
1090 ok(lstrlen(out) == 0, "Expected 0 length out, got %i\n", lstrlen(out));
1091 ok(lstrlen(path1) == 0, "Expected 0 length path1, got %i\n", lstrlen(path1));
1092 ok(!lstrcmp(path2, "C:\\"), "Expected C:\\, got %s\n", path2);
1093 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1095 /* test empty path1 */
1096 SetLastError(0xdeadbeef);
1097 path2[0] = '\0';
1098 lstrcpy(path1, "C:\\");
1099 lstrcpy(out, "aaa");
1100 count = PathCommonPrefixA(path1, path2, out);
1101 ok(count == 0, "Expected 0, got %i\n", count);
1102 ok(lstrlen(out) == 0, "Expected 0 length out, got %i\n", lstrlen(out));
1103 ok(lstrlen(path2) == 0, "Expected 0 length path2, got %i\n", lstrlen(path2));
1104 ok(!lstrcmp(path1, "C:\\"), "Expected C:\\, got %s\n", path1);
1105 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1107 /* paths are legit, out is NULL */
1108 SetLastError(0xdeadbeef);
1109 lstrcpy(path1, "C:\\");
1110 lstrcpy(path2, "C:\\");
1111 count = PathCommonPrefixA(path1, path2, NULL);
1112 ok(count == 3, "Expected 3, got %i\n", count);
1113 ok(!lstrcmp(path1, "C:\\"), "Expected C:\\, got %s\n", path1);
1114 ok(!lstrcmp(path2, "C:\\"), "Expected C:\\, got %s\n", path2);
1115 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1117 /* all parameters legit */
1118 SetLastError(0xdeadbeef);
1119 lstrcpy(path1, "C:\\");
1120 lstrcpy(path2, "C:\\");
1121 lstrcpy(out, "aaa");
1122 count = PathCommonPrefixA(path1, path2, out);
1123 ok(count == 3, "Expected 3, got %i\n", count);
1124 ok(!lstrcmp(path1, "C:\\"), "Expected C:\\, got %s\n", path1);
1125 ok(!lstrcmp(path2, "C:\\"), "Expected C:\\, got %s\n", path2);
1126 ok(!lstrcmp(out, "C:\\"), "Expected C:\\, got %s\n", out);
1127 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1129 /* path1 and path2 not the same, but common prefix */
1130 SetLastError(0xdeadbeef);
1131 lstrcpy(path1, "C:\\one\\two");
1132 lstrcpy(path2, "C:\\one\\three");
1133 lstrcpy(out, "aaa");
1134 count = PathCommonPrefixA(path1, path2, out);
1135 ok(count == 6, "Expected 6, got %i\n", count);
1136 ok(!lstrcmp(path1, "C:\\one\\two"), "Expected C:\\one\\two, got %s\n", path1);
1137 ok(!lstrcmp(path2, "C:\\one\\three"), "Expected C:\\one\\three, got %s\n", path2);
1138 ok(!lstrcmp(out, "C:\\one"), "Expected C:\\one, got %s\n", out);
1139 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1141 /* try . prefix */
1142 SetLastError(0xdeadbeef);
1143 lstrcpy(path1, "one\\.two");
1144 lstrcpy(path2, "one\\.three");
1145 lstrcpy(out, "aaa");
1146 count = PathCommonPrefixA(path1, path2, out);
1147 ok(count == 3, "Expected 3, got %i\n", count);
1148 ok(!lstrcmp(path1, "one\\.two"), "Expected one\\.two, got %s\n", path1);
1149 ok(!lstrcmp(path2, "one\\.three"), "Expected one\\.three, got %s\n", path2);
1150 ok(!lstrcmp(out, "one"), "Expected one, got %s\n", out);
1151 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1153 /* try .. prefix */
1154 SetLastError(0xdeadbeef);
1155 lstrcpy(path1, "one\\..two");
1156 lstrcpy(path2, "one\\..three");
1157 lstrcpy(out, "aaa");
1158 count = PathCommonPrefixA(path1, path2, out);
1159 ok(count == 3, "Expected 3, got %i\n", count);
1160 ok(!lstrcmp(path1, "one\\..two"), "Expected one\\..two, got %s\n", path1);
1161 ok(!lstrcmp(path2, "one\\..three"), "Expected one\\..three, got %s\n", path2);
1162 ok(!lstrcmp(out, "one"), "Expected one, got %s\n", out);
1163 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1165 /* try ... prefix */
1166 SetLastError(0xdeadbeef);
1167 lstrcpy(path1, "one\\...two");
1168 lstrcpy(path2, "one\\...three");
1169 lstrcpy(out, "aaa");
1170 count = PathCommonPrefixA(path1, path2, out);
1171 ok(count == 3, "Expected 3, got %i\n", count);
1172 ok(!lstrcmp(path1, "one\\...two"), "Expected one\\...two, got %s\n", path1);
1173 ok(!lstrcmp(path2, "one\\...three"), "Expected one\\...three, got %s\n", path2);
1174 ok(!lstrcmp(out, "one"), "Expected one, got %s\n", out);
1175 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1177 /* try .\ prefix */
1178 SetLastError(0xdeadbeef);
1179 lstrcpy(path1, "one\\.\\two");
1180 lstrcpy(path2, "one\\.\\three");
1181 lstrcpy(out, "aaa");
1182 count = PathCommonPrefixA(path1, path2, out);
1183 ok(count == 5, "Expected 5, got %i\n", count);
1184 ok(!lstrcmp(path1, "one\\.\\two"), "Expected one\\.\\two, got %s\n", path1);
1185 ok(!lstrcmp(path2, "one\\.\\three"), "Expected one\\.\\three, got %s\n", path2);
1186 ok(!lstrcmp(out, "one\\."), "Expected one\\., got %s\n", out);
1187 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1189 /* try ..\ prefix */
1190 SetLastError(0xdeadbeef);
1191 lstrcpy(path1, "one\\..\\two");
1192 lstrcpy(path2, "one\\..\\three");
1193 lstrcpy(out, "aaa");
1194 count = PathCommonPrefixA(path1, path2, out);
1195 ok(count == 6, "Expected 6, got %i\n", count);
1196 ok(!lstrcmp(path1, "one\\..\\two"), "Expected one\\..\\two, got %s\n", path1);
1197 ok(!lstrcmp(path2, "one\\..\\three"), "Expected one\\..\\three, got %s\n", path2);
1198 ok(!lstrcmp(out, "one\\.."), "Expected one\\.., got %s\n", out);
1199 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1201 /* try ...\\ prefix */
1202 SetLastError(0xdeadbeef);
1203 lstrcpy(path1, "one\\...\\two");
1204 lstrcpy(path2, "one\\...\\three");
1205 lstrcpy(out, "aaa");
1206 count = PathCommonPrefixA(path1, path2, out);
1207 ok(count == 7, "Expected 7, got %i\n", count);
1208 ok(!lstrcmp(path1, "one\\...\\two"), "Expected one\\...\\two, got %s\n", path1);
1209 ok(!lstrcmp(path2, "one\\...\\three"), "Expected one\\...\\three, got %s\n", path2);
1210 ok(!lstrcmp(out, "one\\..."), "Expected one\\..., got %s\n", out);
1211 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1213 /* try prefix that is not an msdn labeled prefix type */
1214 SetLastError(0xdeadbeef);
1215 lstrcpy(path1, "same");
1216 lstrcpy(path2, "same");
1217 lstrcpy(out, "aaa");
1218 count = PathCommonPrefixA(path1, path2, out);
1219 ok(count == 4, "Expected 4, got %i\n", count);
1220 ok(!lstrcmp(path1, "same"), "Expected same, got %s\n", path1);
1221 ok(!lstrcmp(path2, "same"), "Expected same, got %s\n", path2);
1222 ok(!lstrcmp(out, "same"), "Expected same, got %s\n", out);
1223 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1225 /* try . after directory */
1226 SetLastError(0xdeadbeef);
1227 lstrcpy(path1, "one\\mid.\\two");
1228 lstrcpy(path2, "one\\mid.\\three");
1229 lstrcpy(out, "aaa");
1230 count = PathCommonPrefixA(path1, path2, out);
1231 ok(count == 8, "Expected 8, got %i\n", count);
1232 ok(!lstrcmp(path1, "one\\mid.\\two"), "Expected one\\mid.\\two, got %s\n", path1);
1233 ok(!lstrcmp(path2, "one\\mid.\\three"), "Expected one\\mid.\\three, got %s\n", path2);
1234 ok(!lstrcmp(out, "one\\mid."), "Expected one\\mid., got %s\n", out);
1235 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1237 /* try . in the middle of a directory */
1238 SetLastError(0xdeadbeef);
1239 lstrcpy(path1, "one\\mid.end\\two");
1240 lstrcpy(path2, "one\\mid.end\\three");
1241 lstrcpy(out, "aaa");
1242 count = PathCommonPrefixA(path1, path2, out);
1243 ok(count == 11, "Expected 11, got %i\n", count);
1244 ok(!lstrcmp(path1, "one\\mid.end\\two"), "Expected one\\mid.end\\two, got %s\n", path1);
1245 ok(!lstrcmp(path2, "one\\mid.end\\three"), "Expected one\\mid.end\\three, got %s\n", path2);
1246 ok(!lstrcmp(out, "one\\mid.end"), "Expected one\\mid.end, got %s\n", out);
1247 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1249 /* try comparing a .. with the expanded path */
1250 SetLastError(0xdeadbeef);
1251 lstrcpy(path1, "one\\..\\two");
1252 lstrcpy(path2, "two");
1253 lstrcpy(out, "aaa");
1254 count = PathCommonPrefixA(path1, path2, out);
1255 ok(count == 0, "Expected 0, got %i\n", count);
1256 ok(!lstrcmp(path1, "one\\..\\two"), "Expected one\\..\\two, got %s\n", path1);
1257 ok(!lstrcmp(path2, "two"), "Expected two, got %s\n", path2);
1258 ok(lstrlen(out) == 0, "Expected 0 length out, got %i\n", lstrlen(out));
1259 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1262 static void test_PathUnquoteSpaces(void)
1264 int i;
1265 for(i = 0; i < sizeof(TEST_PATH_UNQUOTE_SPACES) / sizeof(TEST_PATH_UNQUOTE_SPACES[0]); i++)
1267 char *path = strdupA(TEST_PATH_UNQUOTE_SPACES[i].path);
1268 WCHAR *pathW = GetWideString(TEST_PATH_UNQUOTE_SPACES[i].path);
1269 WCHAR *resultW = GetWideString(TEST_PATH_UNQUOTE_SPACES[i].result);
1271 PathUnquoteSpacesA(path);
1272 ok(!strcmp(path, TEST_PATH_UNQUOTE_SPACES[i].result), "%s (A): got %s expected %s\n",
1273 TEST_PATH_UNQUOTE_SPACES[i].path, path,
1274 TEST_PATH_UNQUOTE_SPACES[i].result);
1276 PathUnquoteSpacesW(pathW);
1277 ok(!lstrcmpW(pathW, resultW), "%s (W): strings differ\n",
1278 TEST_PATH_UNQUOTE_SPACES[i].path);
1279 FreeWideString(pathW);
1280 FreeWideString(resultW);
1281 HeapFree(GetProcessHeap(), 0, path);
1285 /* ################ */
1287 START_TEST(path)
1289 hShlwapi = GetModuleHandleA("shlwapi.dll");
1291 test_PathSearchAndQualify();
1292 test_PathCreateFromUrl();
1293 test_PathIsUrl();
1295 test_PathAddBackslash();
1296 test_PathMakePretty();
1297 test_PathMatchSpec();
1299 /* For whatever reason, PathIsValidCharA and PathAppendA share the same
1300 * ordinal number in some native versions. Check this to prevent a crash.
1302 pPathIsValidCharA = (void*)GetProcAddress(hShlwapi, (LPSTR)455);
1303 if (pPathIsValidCharA && pPathIsValidCharA != (void*)GetProcAddress(hShlwapi, "PathAppendA"))
1305 test_PathIsValidCharA();
1307 pPathIsValidCharW = (void*)GetProcAddress(hShlwapi, (LPSTR)456);
1308 if (pPathIsValidCharW) test_PathIsValidCharW();
1311 pPathCombineW = (void*)GetProcAddress(hShlwapi, "PathCombineW");
1312 if (pPathCombineW)
1313 test_PathCombineW();
1315 test_PathCombineA();
1316 test_PathAppendA();
1317 test_PathCanonicalizeA();
1318 test_PathFindExtensionA();
1319 test_PathBuildRootA();
1320 test_PathCommonPrefixA();
1321 test_PathUnquoteSpaces();