push 16813bf814fcb5d03ddef80ecfd11fc0f25812b5
[wine/hacks.git] / dlls / shlwapi / tests / path.c
blob0fc092d486bbed83c77b40595f51bdf2d94fe00d
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}
88 struct {
89 const char *path;
90 const char *result;
91 } TEST_PATH_UNQUOTE_SPACES[] = {
92 { "abcdef", "abcdef" },
93 { "\"abcdef\"", "abcdef" },
94 { "\"abcdef", "\"abcdef" },
95 { "abcdef\"", "abcdef\"" },
96 { "\"\"abcdef\"\"", "\"abcdef\"" },
97 { "abc\"def", "abc\"def" },
98 { "\"abc\"def", "\"abc\"def" },
99 { "\"abc\"def\"", "abc\"def" },
100 { "\'abcdef\'", "\'abcdef\'" },
101 { "\"\"", "" },
102 { "\"", "" }
105 /* ################ */
107 static LPWSTR GetWideString(const char* szString)
109 LPWSTR wszString = HeapAlloc(GetProcessHeap(), 0, (2*INTERNET_MAX_URL_LENGTH) * sizeof(WCHAR));
111 MultiByteToWideChar(0, 0, szString, -1, wszString, INTERNET_MAX_URL_LENGTH);
113 return wszString;
116 static void FreeWideString(LPWSTR wszString)
118 HeapFree(GetProcessHeap(), 0, wszString);
121 static LPSTR strdupA(LPCSTR p)
123 LPSTR ret;
124 DWORD len = (strlen(p) + 1);
125 ret = HeapAlloc(GetProcessHeap(), 0, len);
126 memcpy(ret, p, len);
127 return ret;
130 /* ################ */
132 static void test_PathSearchAndQualify(void)
134 WCHAR path1[] = {'c',':','\\','f','o','o',0};
135 WCHAR expect1[] = {'c',':','\\','f','o','o',0};
136 WCHAR path2[] = {'c',':','f','o','o',0};
137 WCHAR c_drive[] = {'c',':',0};
138 WCHAR foo[] = {'f','o','o',0};
139 WCHAR path3[] = {'\\','f','o','o',0};
140 WCHAR winini[] = {'w','i','n','.','i','n','i',0};
141 WCHAR out[MAX_PATH];
142 WCHAR cur_dir[MAX_PATH];
143 WCHAR dot[] = {'.',0};
145 /* c:\foo */
146 ok(PathSearchAndQualifyW(path1, out, MAX_PATH) != 0,
147 "PathSearchAndQualify rets 0\n");
148 ok(!lstrcmpiW(out, expect1), "strings don't match\n");
150 /* c:foo */
151 ok(PathSearchAndQualifyW(path2, out, MAX_PATH) != 0,
152 "PathSearchAndQualify rets 0\n");
153 GetFullPathNameW(c_drive, MAX_PATH, cur_dir, NULL);
154 PathAddBackslashW(cur_dir);
155 lstrcatW(cur_dir, foo);
156 ok(!lstrcmpiW(out, cur_dir), "strings don't match\n");
158 /* foo */
159 ok(PathSearchAndQualifyW(foo, out, MAX_PATH) != 0,
160 "PathSearchAndQualify rets 0\n");
161 GetFullPathNameW(dot, MAX_PATH, cur_dir, NULL);
162 PathAddBackslashW(cur_dir);
163 lstrcatW(cur_dir, foo);
164 ok(!lstrcmpiW(out, cur_dir), "strings don't match\n");
166 /* \foo */
167 ok(PathSearchAndQualifyW(path3, out, MAX_PATH) != 0,
168 "PathSearchAndQualify rets 0\n");
169 GetFullPathNameW(dot, MAX_PATH, cur_dir, NULL);
170 lstrcpyW(cur_dir + 2, path3);
171 ok(!lstrcmpiW(out, cur_dir), "strings don't match\n");
173 /* win.ini */
174 ok(PathSearchAndQualifyW(winini, out, MAX_PATH) != 0,
175 "PathSearchAndQualify rets 0\n");
176 if(!SearchPathW(NULL, winini, NULL, MAX_PATH, cur_dir, NULL))
177 GetFullPathNameW(winini, MAX_PATH, cur_dir, NULL);
178 ok(!lstrcmpiW(out, cur_dir), "strings don't match\n");
182 static void test_PathCreateFromUrl(void)
184 size_t i;
185 char ret_path[INTERNET_MAX_URL_LENGTH];
186 DWORD len, ret;
187 WCHAR ret_pathW[INTERNET_MAX_URL_LENGTH];
188 WCHAR *pathW, *urlW;
189 static const char url[] = "http://www.winehq.org";
191 /* Check ret_path = NULL */
192 len = sizeof(url);
193 ret = PathCreateFromUrlA(url, NULL, &len, 0);
194 ok ( ret == E_INVALIDARG, "got 0x%08x expected E_INVALIDARG\n", ret);
196 for(i = 0; i < sizeof(TEST_PATHFROMURL) / sizeof(TEST_PATHFROMURL[0]); i++) {
197 len = INTERNET_MAX_URL_LENGTH;
198 ret = PathCreateFromUrlA(TEST_PATHFROMURL[i].url, ret_path, &len, 0);
199 ok(ret == TEST_PATHFROMURL[i].ret, "ret %08x from url %s\n", ret, TEST_PATHFROMURL[i].url);
200 if(TEST_PATHFROMURL[i].path) {
201 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);
202 ok(len == strlen(ret_path), "ret len %d from url %s\n", len, TEST_PATHFROMURL[i].url);
204 len = INTERNET_MAX_URL_LENGTH;
205 pathW = GetWideString(TEST_PATHFROMURL[i].path);
206 urlW = GetWideString(TEST_PATHFROMURL[i].url);
207 ret = PathCreateFromUrlW(urlW, ret_pathW, &len, 0);
208 WideCharToMultiByte(CP_ACP, 0, ret_pathW, -1, ret_path, sizeof(ret_path),0,0);
209 ok(ret == TEST_PATHFROMURL[i].ret, "ret %08x from url L\"%s\"\n", ret, TEST_PATHFROMURL[i].url);
210 if(TEST_PATHFROMURL[i].path) {
211 ok(!lstrcmpiW(ret_pathW, pathW), "got %s expected %s from url L\"%s\"\n", ret_path, TEST_PATHFROMURL[i].path, TEST_PATHFROMURL[i].url);
212 ok(len == lstrlenW(ret_pathW), "ret len %d from url L\"%s\"\n", len, TEST_PATHFROMURL[i].url);
214 FreeWideString(urlW);
215 FreeWideString(pathW);
220 static void test_PathIsUrl(void)
222 size_t i;
223 BOOL ret;
225 for(i = 0; i < sizeof(TEST_PATH_IS_URL)/sizeof(TEST_PATH_IS_URL[0]); i++) {
226 ret = PathIsURLA(TEST_PATH_IS_URL[i].path);
227 ok(ret == TEST_PATH_IS_URL[i].expect,
228 "returned %d from path %s, expected %d\n", ret, TEST_PATH_IS_URL[i].path,
229 TEST_PATH_IS_URL[i].expect);
233 static const DWORD SHELL_charclass[] =
235 0x00000000, 0x00000000, 0x00000000, 0x00000000,
236 0x00000000, 0x00000000, 0x00000000, 0x00000000,
237 0x00000000, 0x00000000, 0x00000000, 0x00000000,
238 0x00000000, 0x00000000, 0x00000000, 0x00000000,
239 0x00000000, 0x00000000, 0x00000000, 0x00000000,
240 0x00000000, 0x00000000, 0x00000000, 0x00000000,
241 0x00000000, 0x00000000, 0x00000000, 0x00000000,
242 0x00000000, 0x00000000, 0x00000000, 0x00000000,
243 0x00000080, 0x00000100, 0x00000200, 0x00000100,
244 0x00000100, 0x00000100, 0x00000100, 0x00000100,
245 0x00000100, 0x00000100, 0x00000002, 0x00000100,
246 0x00000040, 0x00000100, 0x00000004, 0x00000000,
247 0x00000100, 0x00000100, 0x00000100, 0x00000100,
248 0x00000100, 0x00000100, 0x00000100, 0x00000100,
249 0x00000100, 0x00000100, 0x00000010, 0x00000020,
250 0x00000000, 0x00000100, 0x00000000, 0x00000001,
251 0x00000100, 0xffffffff, 0xffffffff, 0xffffffff,
252 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
253 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
254 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
255 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
256 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
257 0xffffffff, 0xffffffff, 0xffffffff, 0x00000100,
258 0x00000008, 0x00000100, 0x00000100, 0x00000100,
259 0x00000100, 0xffffffff, 0xffffffff, 0xffffffff,
260 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
261 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
262 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
263 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
264 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
265 0xffffffff, 0xffffffff, 0xffffffff, 0x00000100,
266 0x00000000, 0x00000100, 0x00000100
269 static void test_PathIsValidCharA(void)
271 BOOL ret;
272 unsigned int c;
274 ret = pPathIsValidCharA( 0x7f, 0 );
275 ok ( !ret, "PathIsValidCharA succeeded: 0x%08x\n", (DWORD)ret );
277 ret = pPathIsValidCharA( 0x7f, 1 );
278 ok ( !ret, "PathIsValidCharA succeeded: 0x%08x\n", (DWORD)ret );
280 for (c = 0; c < 0x7f; c++)
282 ret = pPathIsValidCharA( c, ~0U );
283 ok ( ret == SHELL_charclass[c] || (ret == 1 && SHELL_charclass[c] == 0xffffffff),
284 "PathIsValidCharA failed: 0x%02x got 0x%08x expected 0x%08x\n",
285 c, (DWORD)ret, SHELL_charclass[c] );
288 for (c = 0x7f; c <= 0xff; c++)
290 ret = pPathIsValidCharA( c, ~0U );
291 ok ( ret == 0x00000100,
292 "PathIsValidCharA failed: 0x%02x got 0x%08x expected 0x00000100\n",
293 c, (DWORD)ret );
297 static void test_PathIsValidCharW(void)
299 BOOL ret;
300 unsigned int c, err_count = 0;
302 ret = pPathIsValidCharW( 0x7f, 0 );
303 ok ( !ret, "PathIsValidCharW succeeded: 0x%08x\n", (DWORD)ret );
305 ret = pPathIsValidCharW( 0x7f, 1 );
306 ok ( !ret, "PathIsValidCharW succeeded: 0x%08x\n", (DWORD)ret );
308 for (c = 0; c < 0x7f; c++)
310 ret = pPathIsValidCharW( c, ~0U );
311 ok ( ret == SHELL_charclass[c] || (ret == 1 && SHELL_charclass[c] == 0xffffffff),
312 "PathIsValidCharW failed: 0x%02x got 0x%08x expected 0x%08x\n",
313 c, (DWORD)ret, SHELL_charclass[c] );
316 for (c = 0x007f; c <= 0xffff; c++)
318 ret = pPathIsValidCharW( c, ~0U );
319 ok ( ret == 0x00000100,
320 "PathIsValidCharW failed: 0x%02x got 0x%08x expected 0x00000100\n",
321 c, (DWORD)ret );
322 if (ret != 0x00000100)
324 if(++err_count > 100 ) {
325 trace("skipping rest of PathIsValidCharW tests "
326 "because of the current number of errors\n");
327 break;
333 static void test_PathMakePretty(void)
335 char buff[MAX_PATH];
337 ok (PathMakePrettyA(NULL) == FALSE, "PathMakePretty: NULL path succeeded\n");
338 buff[0] = '\0';
339 ok (PathMakePrettyA(buff) == TRUE, "PathMakePretty: Empty path failed\n");
341 strcpy(buff, "C:\\A LONG FILE NAME WITH \\SPACES.TXT");
342 ok (PathMakePrettyA(buff) == TRUE, "PathMakePretty: Long UC name failed\n");
343 ok (strcmp(buff, "C:\\a long file name with \\spaces.txt") == 0,
344 "PathMakePretty: Long UC name not changed\n");
346 strcpy(buff, "C:\\A LONG FILE NAME WITH \\MixedCase.TXT");
347 ok (PathMakePrettyA(buff) == FALSE, "PathMakePretty: Long MC name succeeded\n");
348 ok (strcmp(buff, "C:\\A LONG FILE NAME WITH \\MixedCase.TXT") == 0,
349 "PathMakePretty: Failed but modified path\n");
351 strcpy(buff, "TEST");
352 ok (PathMakePrettyA(buff) == TRUE, "PathMakePretty: Short name failed\n");
353 ok (strcmp(buff, "Test") == 0, "PathMakePretty: 1st char lowercased %s\n", buff);
356 static void test_PathMatchSpec(void)
358 static const char file[] = "c:\\foo\\bar\\filename.ext";
359 static const char spec1[] = ".ext";
360 static const char spec2[] = "*.ext";
361 static const char spec3[] = "*.ext ";
362 static const char spec4[] = " *.ext";
363 static const char spec5[] = "* .ext";
364 static const char spec6[] = "*. ext";
365 static const char spec7[] = "* . ext";
366 static const char spec8[] = "*.e?t";
367 static const char spec9[] = "filename.ext";
368 static const char spec10[] = "*bar\\filename.ext";
369 static const char spec11[] = " foo; *.ext";
370 static const char spec12[] = "*.ext;*.bar";
371 static const char spec13[] = "*bar*";
373 ok (PathMatchSpecA(file, spec1) == FALSE, "PathMatchSpec: Spec1 failed\n");
374 ok (PathMatchSpecA(file, spec2) == TRUE, "PathMatchSpec: Spec2 failed\n");
375 ok (PathMatchSpecA(file, spec3) == FALSE, "PathMatchSpec: Spec3 failed\n");
376 ok (PathMatchSpecA(file, spec4) == TRUE, "PathMatchSpec: Spec4 failed\n");
377 todo_wine ok (PathMatchSpecA(file, spec5) == TRUE, "PathMatchSpec: Spec5 failed\n");
378 todo_wine ok (PathMatchSpecA(file, spec6) == TRUE, "PathMatchSpec: Spec6 failed\n");
379 ok (PathMatchSpecA(file, spec7) == FALSE, "PathMatchSpec: Spec7 failed\n");
380 ok (PathMatchSpecA(file, spec8) == TRUE, "PathMatchSpec: Spec8 failed\n");
381 ok (PathMatchSpecA(file, spec9) == FALSE, "PathMatchSpec: Spec9 failed\n");
382 ok (PathMatchSpecA(file, spec10) == TRUE, "PathMatchSpec: Spec10 failed\n");
383 ok (PathMatchSpecA(file, spec11) == TRUE, "PathMatchSpec: Spec11 failed\n");
384 ok (PathMatchSpecA(file, spec12) == TRUE, "PathMatchSpec: Spec12 failed\n");
385 ok (PathMatchSpecA(file, spec13) == TRUE, "PathMatchSpec: Spec13 failed\n");
388 static void test_PathCombineW(void)
390 LPWSTR wszString, wszString2;
391 WCHAR wbuf[MAX_PATH+1], wstr1[MAX_PATH] = {'C',':','\\',0}, wstr2[MAX_PATH];
392 static const WCHAR expout[] = {'C',':','\\','A','A',0};
393 int i;
395 wszString2 = HeapAlloc(GetProcessHeap(), 0, MAX_PATH * sizeof(WCHAR));
397 /* NULL test */
398 wszString = pPathCombineW(NULL, NULL, NULL);
399 ok (wszString == NULL, "Expected a NULL return\n");
401 /* Some NULL */
402 wszString2[0] = 'a';
403 wszString = pPathCombineW(wszString2, NULL, NULL);
404 ok (wszString == NULL, "Expected a NULL return\n");
405 ok (wszString2[0] == 0, "Destination string not empty\n");
407 HeapFree(GetProcessHeap(), 0, wszString2);
409 /* overflow test */
410 wstr2[0] = wstr2[1] = wstr2[2] = 'A';
411 for (i=3; i<MAX_PATH/2; i++)
412 wstr1[i] = wstr2[i] = 'A';
413 wstr1[(MAX_PATH/2) - 1] = wstr2[MAX_PATH/2] = 0;
414 memset(wbuf, 0xbf, sizeof(wbuf));
416 wszString = pPathCombineW(wbuf, wstr1, wstr2);
417 ok(wszString == NULL, "Expected a NULL return\n");
418 ok(wbuf[0] == 0, "Buffer contains data\n");
420 /* PathCombineW can be used in place */
421 wstr1[3] = 0;
422 wstr2[2] = 0;
423 ok(PathCombineW(wstr1, wstr1, wstr2) == wstr1, "Expected a wstr1 return\n");
424 ok(StrCmpW(wstr1, expout) == 0, "Unexpected PathCombine output\n");
428 #define LONG_LEN (MAX_PATH * 2)
429 #define HALF_LEN (MAX_PATH / 2 + 1)
431 static void test_PathCombineA(void)
433 LPSTR str;
434 char dest[MAX_PATH];
435 char too_long[LONG_LEN];
436 char one[HALF_LEN], two[HALF_LEN];
438 /* try NULL dest */
439 SetLastError(0xdeadbeef);
440 str = PathCombineA(NULL, "C:\\", "one\\two\\three");
441 ok(str == NULL, "Expected NULL, got %p\n", str);
442 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
444 /* try NULL dest and NULL directory */
445 SetLastError(0xdeadbeef);
446 str = PathCombineA(NULL, NULL, "one\\two\\three");
447 ok(str == NULL, "Expected NULL, got %p\n", str);
448 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
450 /* try all NULL*/
451 SetLastError(0xdeadbeef);
452 str = PathCombineA(NULL, NULL, NULL);
453 ok(str == NULL, "Expected NULL, got %p\n", str);
454 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
456 /* try NULL file part */
457 SetLastError(0xdeadbeef);
458 lstrcpyA(dest, "control");
459 str = PathCombineA(dest, "C:\\", NULL);
460 ok(str == dest, "Expected str == dest, got %p\n", str);
461 ok(!lstrcmp(str, "C:\\"), "Expected C:\\, got %s\n", str);
462 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
464 /* try empty file part */
465 SetLastError(0xdeadbeef);
466 lstrcpyA(dest, "control");
467 str = PathCombineA(dest, "C:\\", "");
468 ok(str == dest, "Expected str == dest, got %p\n", str);
469 ok(!lstrcmp(str, "C:\\"), "Expected C:\\, got %s\n", str);
470 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
472 /* try empty directory and file part */
473 SetLastError(0xdeadbeef);
474 lstrcpyA(dest, "control");
475 str = PathCombineA(dest, "", "");
476 ok(str == dest, "Expected str == dest, got %p\n", str);
477 ok(!lstrcmp(str, "\\"), "Expected \\, got %s\n", str);
478 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
480 /* try NULL directory */
481 SetLastError(0xdeadbeef);
482 lstrcpyA(dest, "control");
483 str = PathCombineA(dest, NULL, "one\\two\\three");
484 ok(str == dest, "Expected str == dest, got %p\n", str);
485 ok(!lstrcmp(str, "one\\two\\three"), "Expected one\\two\\three, got %s\n", str);
486 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
488 /* try NULL directory and empty file part */
489 SetLastError(0xdeadbeef);
490 lstrcpyA(dest, "control");
491 str = PathCombineA(dest, NULL, "");
492 ok(str == dest, "Expected str == dest, got %p\n", str);
493 ok(!lstrcmp(str, "\\"), "Expected \\, got %s\n", str);
494 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
496 /* try NULL directory and file part */
497 SetLastError(0xdeadbeef);
498 lstrcpyA(dest, "control");
499 str = PathCombineA(dest, NULL, NULL);
500 ok(str == NULL, "Expected str == NULL, got %p\n", str);
501 ok(lstrlenA(dest) == 0, "Expected 0 length, got %i\n", lstrlenA(dest));
502 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
504 /* try directory without backslash */
505 SetLastError(0xdeadbeef);
506 lstrcpyA(dest, "control");
507 str = PathCombineA(dest, "C:", "one\\two\\three");
508 ok(str == dest, "Expected str == dest, got %p\n", str);
509 ok(!lstrcmp(str, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", str);
510 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
512 /* try directory with backslash */
513 SetLastError(0xdeadbeef);
514 lstrcpyA(dest, "control");
515 str = PathCombineA(dest, "C:\\", "one\\two\\three");
516 ok(str == dest, "Expected str == dest, got %p\n", str);
517 ok(!lstrcmp(str, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", str);
518 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
520 /* try directory with backslash and file with prepended backslash */
521 SetLastError(0xdeadbeef);
522 lstrcpyA(dest, "control");
523 str = PathCombineA(dest, "C:\\", "\\one\\two\\three");
524 ok(str == dest, "Expected str == dest, got %p\n", str);
525 ok(!lstrcmp(str, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", str);
526 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
528 /* try previous test, with backslash appended as well */
529 SetLastError(0xdeadbeef);
530 lstrcpyA(dest, "control");
531 str = PathCombineA(dest, "C:\\", "\\one\\two\\three\\");
532 ok(str == dest, "Expected str == dest, got %p\n", str);
533 ok(!lstrcmp(str, "C:\\one\\two\\three\\"), "Expected C:\\one\\two\\three\\, got %s\n", str);
534 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
536 /* try a relative directory */
537 SetLastError(0xdeadbeef);
538 lstrcpyA(dest, "control");
539 str = PathCombineA(dest, "relative\\dir", "\\one\\two\\three\\");
540 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
541 /* Vista fails which probably makes sense as PathCombineA expects an absolute dir */
542 if (str)
544 ok(str == dest, "Expected str == dest, got %p\n", str);
545 ok(!lstrcmp(str, "one\\two\\three\\"), "Expected one\\two\\three\\, got %s\n", str);
548 /* try forward slashes */
549 SetLastError(0xdeadbeef);
550 lstrcpyA(dest, "control");
551 str = PathCombineA(dest, "C:\\", "one/two/three\\");
552 ok(str == dest, "Expected str == dest, got %p\n", str);
553 ok(!lstrcmp(str, "C:\\one/two/three\\"), "Expected one/two/three\\, got %s\n", str);
554 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
556 /* try a really weird directory */
557 SetLastError(0xdeadbeef);
558 lstrcpyA(dest, "control");
559 str = PathCombineA(dest, "C:\\/\\/", "\\one\\two\\three\\");
560 ok(str == dest, "Expected str == dest, got %p\n", str);
561 ok(!lstrcmp(str, "C:\\one\\two\\three\\"), "Expected C:\\one\\two\\three\\, got %s\n", str);
562 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
564 /* try periods */
565 SetLastError(0xdeadbeef);
566 lstrcpyA(dest, "control");
567 str = PathCombineA(dest, "C:\\", "one\\..\\two\\.\\three");
568 ok(str == dest, "Expected str == dest, got %p\n", str);
569 ok(!lstrcmp(str, "C:\\two\\three"), "Expected C:\\two\\three, got %s\n", str);
570 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
572 /* try .. as file */
573 /* try forward slashes */
574 SetLastError(0xdeadbeef);
575 lstrcpyA(dest, "control");
576 str = PathCombineA(dest, "C:\\", "..");
577 ok(str == dest, "Expected str == dest, got %p\n", str);
578 ok(!lstrcmp(str, "C:\\"), "Expected C:\\, got %s\n", str);
579 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
581 memset(too_long, 'a', LONG_LEN);
582 too_long[LONG_LEN - 1] = '\0';
584 /* try a file longer than MAX_PATH */
585 SetLastError(0xdeadbeef);
586 lstrcpyA(dest, "control");
587 str = PathCombineA(dest, "C:\\", too_long);
588 ok(str == NULL, "Expected str == NULL, got %p\n", str);
589 ok(lstrlenA(dest) == 0, "Expected 0 length, got %i\n", lstrlenA(dest));
590 todo_wine ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
592 /* try a directory longer than MAX_PATH */
593 SetLastError(0xdeadbeef);
594 lstrcpyA(dest, "control");
595 str = PathCombineA(dest, too_long, "one\\two\\three");
596 ok(str == NULL, "Expected str == NULL, got %p\n", str);
597 ok(lstrlenA(dest) == 0, "Expected 0 length, got %i\n", lstrlenA(dest));
598 todo_wine ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
600 memset(one, 'b', HALF_LEN);
601 memset(two, 'c', HALF_LEN);
602 one[HALF_LEN - 1] = '\0';
603 two[HALF_LEN - 1] = '\0';
605 /* destination string is longer than MAX_PATH, but not the constituent parts */
606 SetLastError(0xdeadbeef);
607 lstrcpyA(dest, "control");
608 str = PathCombineA(dest, one, two);
609 ok(str == NULL, "Expected str == NULL, got %p\n", str);
610 ok(lstrlenA(dest) == 0, "Expected 0 length, got %i\n", lstrlenA(dest));
611 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
614 static void test_PathAddBackslash(void)
616 LPSTR str;
617 char path[MAX_PATH];
618 char too_long[LONG_LEN];
620 /* try a NULL path */
621 SetLastError(0xdeadbeef);
622 str = PathAddBackslashA(NULL);
623 ok(str == NULL, "Expected str == NULL, got %p\n", str);
624 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
626 /* try an empty path */
627 path[0] = '\0';
628 SetLastError(0xdeadbeef);
629 str = PathAddBackslashA(path);
630 ok(str == (path + lstrlenA(path)), "Expected str to point to end of path, got %p\n", str);
631 ok(lstrlenA(path) == 0, "Expected empty string, got %i\n", lstrlenA(path));
632 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
634 /* try a relative path */
635 lstrcpyA(path, "one\\two");
636 SetLastError(0xdeadbeef);
637 str = PathAddBackslashA(path);
638 ok(str == (path + lstrlenA(path)), "Expected str to point to end of path, got %p\n", str);
639 ok(!lstrcmp(path, "one\\two\\"), "Expected one\\two\\, got %s\n", path);
640 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
642 /* try periods */
643 lstrcpyA(path, "one\\..\\two");
644 SetLastError(0xdeadbeef);
645 str = PathAddBackslashA(path);
646 ok(str == (path + lstrlenA(path)), "Expected str to point to end of path, got %p\n", str);
647 ok(!lstrcmp(path, "one\\..\\two\\"), "Expected one\\..\\two\\, got %s\n", path);
648 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
650 /* try just a space */
651 lstrcpyA(path, " ");
652 SetLastError(0xdeadbeef);
653 str = PathAddBackslashA(path);
654 ok(str == (path + lstrlenA(path)), "Expected str to point to end of path, got %p\n", str);
655 ok(!lstrcmp(path, " \\"), "Expected \\, got %s\n", path);
656 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
658 /* path already has backslash */
659 lstrcpyA(path, "C:\\one\\");
660 SetLastError(0xdeadbeef);
661 str = PathAddBackslashA(path);
662 ok(str == (path + lstrlenA(path)), "Expected str to point to end of path, got %p\n", str);
663 ok(!lstrcmp(path, "C:\\one\\"), "Expected C:\\one\\, got %s\n", path);
664 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
666 memset(too_long, 'a', LONG_LEN);
667 too_long[LONG_LEN - 1] = '\0';
669 /* path is longer than MAX_PATH */
670 SetLastError(0xdeadbeef);
671 str = PathAddBackslashA(too_long);
672 ok(str == NULL, "Expected str == NULL, got %p\n", str);
673 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
676 static void test_PathAppendA(void)
678 char path[MAX_PATH];
679 char too_long[LONG_LEN];
680 char one[HALF_LEN], two[HALF_LEN];
681 BOOL res;
683 lstrcpy(path, "C:\\one");
685 /* try NULL pszMore */
686 SetLastError(0xdeadbeef);
687 res = PathAppendA(path, NULL);
688 ok(!res, "Expected failure\n");
689 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
690 ok(!lstrcmp(path, "C:\\one"), "Expected C:\\one, got %s\n", path);
692 /* try empty pszMore */
693 SetLastError(0xdeadbeef);
694 res = PathAppendA(path, "");
695 ok(res, "Expected success\n");
696 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
697 ok(!lstrcmp(path, "C:\\one"), "Expected C:\\one, got %s\n", path);
699 /* try NULL pszPath */
700 SetLastError(0xdeadbeef);
701 res = PathAppendA(NULL, "two\\three");
702 ok(!res, "Expected failure\n");
703 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
705 /* try empty pszPath */
706 path[0] = '\0';
707 SetLastError(0xdeadbeef);
708 res = PathAppendA(path, "two\\three");
709 ok(res, "Expected success\n");
710 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
711 ok(!lstrcmp(path, "two\\three"), "Expected \\two\\three, got %s\n", path);
713 /* try empty pszPath and empty pszMore */
714 path[0] = '\0';
715 SetLastError(0xdeadbeef);
716 res = PathAppendA(path, "");
717 ok(res, "Expected success\n");
718 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
719 ok(!lstrcmp(path, "\\"), "Expected \\, got %s\n", path);
721 /* try legit params */
722 lstrcpy(path, "C:\\one");
723 SetLastError(0xdeadbeef);
724 res = PathAppendA(path, "two\\three");
725 ok(res, "Expected success\n");
726 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
727 ok(!lstrcmp(path, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", path);
729 /* try pszPath with backslash after it */
730 lstrcpy(path, "C:\\one\\");
731 SetLastError(0xdeadbeef);
732 res = PathAppendA(path, "two\\three");
733 ok(res, "Expected success\n");
734 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
735 ok(!lstrcmp(path, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", path);
737 /* try pszMore with backslash before it */
738 lstrcpy(path, "C:\\one");
739 SetLastError(0xdeadbeef);
740 res = PathAppendA(path, "\\two\\three");
741 ok(res, "Expected success\n");
742 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
743 ok(!lstrcmp(path, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", path);
745 /* try pszMore with backslash after it */
746 lstrcpy(path, "C:\\one");
747 SetLastError(0xdeadbeef);
748 res = PathAppendA(path, "two\\three\\");
749 ok(res, "Expected success\n");
750 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
751 ok(!lstrcmp(path, "C:\\one\\two\\three\\"), "Expected C:\\one\\two\\three\\, got %s\n", path);
753 /* try spaces in pszPath */
754 lstrcpy(path, "C: \\ one ");
755 SetLastError(0xdeadbeef);
756 res = PathAppendA(path, "two\\three");
757 ok(res, "Expected success\n");
758 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
759 ok(!lstrcmp(path, "C: \\ one \\two\\three"), "Expected C: \\ one \\two\\three, got %s\n", path);
761 /* try spaces in pszMore */
762 lstrcpy(path, "C:\\one");
763 SetLastError(0xdeadbeef);
764 res = PathAppendA(path, " two \\ three ");
765 ok(res, "Expected success\n");
766 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
767 ok(!lstrcmp(path, "C:\\one\\ two \\ three "), "Expected 'C:\\one\\ two \\ three ', got %s\n", path);
769 /* pszPath is too long */
770 memset(too_long, 'a', LONG_LEN);
771 too_long[LONG_LEN - 1] = '\0';
772 SetLastError(0xdeadbeef);
773 res = PathAppendA(too_long, "two\\three");
774 ok(!res, "Expected failure\n");
775 todo_wine ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
776 ok(lstrlen(too_long) == 0, "Expected length of too_long to be zero, got %i\n", lstrlen(too_long));
778 /* pszMore is too long */
779 lstrcpy(path, "C:\\one");
780 memset(too_long, 'a', LONG_LEN);
781 too_long[LONG_LEN - 1] = '\0';
782 SetLastError(0xdeadbeef);
783 res = PathAppendA(path, too_long);
784 ok(!res, "Expected failure\n");
785 todo_wine ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
786 ok(lstrlen(path) == 0, "Expected length of path to be zero, got %i\n", lstrlen(path));
788 /* both params combined are too long */
789 memset(one, 'a', HALF_LEN);
790 one[HALF_LEN - 1] = '\0';
791 memset(two, 'b', HALF_LEN);
792 two[HALF_LEN - 1] = '\0';
793 SetLastError(0xdeadbeef);
794 res = PathAppendA(one, two);
795 ok(!res, "Expected failure\n");
796 ok(lstrlen(one) == 0, "Expected length of one to be zero, got %i\n", lstrlen(one));
797 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
800 static void test_PathCanonicalizeA(void)
802 char dest[LONG_LEN + MAX_PATH];
803 char too_long[LONG_LEN];
804 BOOL res;
806 /* try a NULL source */
807 lstrcpy(dest, "test");
808 SetLastError(0xdeadbeef);
809 res = PathCanonicalizeA(dest, NULL);
810 ok(!res, "Expected failure\n");
811 ok(GetLastError() == ERROR_INVALID_PARAMETER,
812 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
813 ok(dest[0] == 0 || !lstrcmp(dest, "test"),
814 "Expected either an empty string (Vista) or test, got %s\n", dest);
816 /* try an empty source */
817 lstrcpy(dest, "test");
818 SetLastError(0xdeadbeef);
819 res = PathCanonicalizeA(dest, "");
820 ok(res, "Expected success\n");
821 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
822 ok(!lstrcmp(dest, "\\"), "Expected \\, got %s\n", dest);
824 /* try a NULL dest */
825 SetLastError(0xdeadbeef);
826 res = PathCanonicalizeA(NULL, "C:\\");
827 ok(!res, "Expected failure\n");
828 ok(GetLastError() == ERROR_INVALID_PARAMETER,
829 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
831 /* try empty dest */
832 dest[0] = '\0';
833 SetLastError(0xdeadbeef);
834 res = PathCanonicalizeA(dest, "C:\\");
835 ok(res, "Expected success\n");
836 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
837 ok(!lstrcmp(dest, "C:\\"), "Expected C:\\, got %s\n", dest);
839 /* try non-empty dest */
840 lstrcpy(dest, "test");
841 SetLastError(0xdeadbeef);
842 res = PathCanonicalizeA(dest, "C:\\");
843 ok(res, "Expected success\n");
844 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
845 ok(!lstrcmp(dest, "C:\\"), "Expected C:\\, got %s\n", dest);
847 /* try a space for source */
848 lstrcpy(dest, "test");
849 SetLastError(0xdeadbeef);
850 res = PathCanonicalizeA(dest, " ");
851 ok(res, "Expected success\n");
852 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
853 ok(!lstrcmp(dest, " "), "Expected ' ', got %s\n", dest);
855 /* try a relative path */
856 lstrcpy(dest, "test");
857 SetLastError(0xdeadbeef);
858 res = PathCanonicalizeA(dest, "one\\two");
859 ok(res, "Expected success\n");
860 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
861 ok(!lstrcmp(dest, "one\\two"), "Expected one\\two, got %s\n", dest);
863 /* try current dir and previous dir */
864 lstrcpy(dest, "test");
865 SetLastError(0xdeadbeef);
866 res = PathCanonicalizeA(dest, "C:\\one\\.\\..\\two\\three\\..");
867 ok(res, "Expected success\n");
868 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
869 ok(!lstrcmp(dest, "C:\\two"), "Expected C:\\two, got %s\n", dest);
871 /* try simple forward slashes */
872 lstrcpy(dest, "test");
873 SetLastError(0xdeadbeef);
874 res = PathCanonicalizeA(dest, "C:\\one/two/three\\four/five\\six");
875 ok(res, "Expected success\n");
876 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
877 ok(!lstrcmp(dest, "C:\\one/two/three\\four/five\\six"),
878 "Expected C:\\one/two/three\\four/five\\six, got %s\n", dest);
880 /* try simple forward slashes with same dir */
881 lstrcpy(dest, "test");
882 SetLastError(0xdeadbeef);
883 res = PathCanonicalizeA(dest, "C:\\one/.\\two");
884 ok(res, "Expected success\n");
885 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
886 ok(!lstrcmp(dest, "C:\\one/.\\two"), "Expected C:\\one/.\\two, got %s\n", dest);
888 /* try simple forward slashes with change dir */
889 lstrcpy(dest, "test");
890 SetLastError(0xdeadbeef);
891 res = PathCanonicalizeA(dest, "C:\\one/.\\two\\..");
892 ok(res, "Expected success\n");
893 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
894 ok(!lstrcmp(dest, "C:\\one/.") ||
895 !lstrcmp(dest, "C:\\one/"), /* Vista */
896 "Expected \"C:\\one/.\" or \"C:\\one/\", got \"%s\"\n", dest);
898 /* try forward slashes with change dirs
899 * NOTE: if there is a forward slash in between two backslashes,
900 * everything in between the two backslashes is considered on dir
902 lstrcpy(dest, "test");
903 SetLastError(0xdeadbeef);
904 res = PathCanonicalizeA(dest, "C:\\one/.\\..\\two/three\\..\\four/.five");
905 ok(res, "Expected success\n");
906 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
907 ok(!lstrcmp(dest, "C:\\four/.five"), "Expected C:\\four/.five, got %s\n", dest);
909 /* try src is too long */
910 memset(too_long, 'a', LONG_LEN);
911 too_long[LONG_LEN - 1] = '\0';
912 lstrcpy(dest, "test");
913 SetLastError(0xdeadbeef);
914 res = PathCanonicalizeA(dest, too_long);
915 ok(!res, "Expected failure\n");
916 todo_wine
918 ok(GetLastError() == 0xdeadbeef || GetLastError() == ERROR_FILENAME_EXCED_RANGE /* Vista */,
919 "Expected 0xdeadbeef or ERROR_FILENAME_EXCED_RANGE, got %d\n", GetLastError());
921 ok(lstrlen(too_long) == LONG_LEN - 1, "Expected length LONG_LEN - 1, got %i\n", lstrlen(too_long));
924 static void test_PathFindExtensionA(void)
926 LPSTR ext;
927 char path[MAX_PATH];
928 char too_long[LONG_LEN];
930 /* try a NULL path */
931 SetLastError(0xdeadbeef);
932 ext = PathFindExtensionA(NULL);
933 ok(ext == NULL, "Expected NULL, got %p\n", ext);
934 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
936 /* try an empty path */
937 path[0] = '\0';
938 SetLastError(0xdeadbeef);
939 ext = PathFindExtensionA(path);
940 ok(ext == path, "Expected ext == path, got %p\n", ext);
941 ok(lstrlen(ext) == 0, "Expected length 0, got %i\n", lstrlen(ext));
942 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
944 /* try a path without an extension */
945 lstrcpy(path, "file");
946 SetLastError(0xdeadbeef);
947 ext = PathFindExtensionA(path);
948 ok(ext == path + lstrlen(path), "Expected ext == path, got %p\n", ext);
949 ok(lstrlen(ext) == 0, "Expected length 0, got %i\n", lstrlen(ext));
950 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
952 /* try a path with an extension */
953 lstrcpy(path, "file.txt");
954 SetLastError(0xdeadbeef);
955 ext = PathFindExtensionA(path);
956 ok(ext == path + lstrlen("file"),
957 "Expected ext == path + lstrlen(\"file\"), got %p\n", ext);
958 ok(!lstrcmp(ext, ".txt"), "Expected .txt, got %s\n", ext);
959 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
961 /* try a path with two extensions */
962 lstrcpy(path, "file.txt.doc");
963 SetLastError(0xdeadbeef);
964 ext = PathFindExtensionA(path);
965 ok(ext == path + lstrlen("file.txt"),
966 "Expected ext == path + lstrlen(\"file.txt\"), got %p\n", ext);
967 ok(!lstrcmp(ext, ".doc"), "Expected .txt, got %s\n", ext);
968 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
970 /* try a path longer than MAX_PATH without an extension*/
971 memset(too_long, 'a', LONG_LEN);
972 too_long[LONG_LEN - 1] = '\0';
973 SetLastError(0xdeadbeef);
974 ext = PathFindExtensionA(too_long);
975 ok(ext == too_long + LONG_LEN - 1, "Expected ext == too_long + LONG_LEN - 1, got %p\n", ext);
976 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
978 /* try a path longer than MAX_PATH with an extension*/
979 memset(too_long, 'a', LONG_LEN);
980 too_long[LONG_LEN - 1] = '\0';
981 lstrcpy(too_long + 300, ".abcde");
982 too_long[lstrlen(too_long)] = 'a';
983 SetLastError(0xdeadbeef);
984 ext = PathFindExtensionA(too_long);
985 ok(ext == too_long + 300, "Expected ext == too_long + 300, got %p\n", ext);
986 ok(lstrlen(ext) == LONG_LEN - 301, "Expected LONG_LEN - 301, got %i\n", lstrlen(ext));
987 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
990 static void test_PathBuildRootA(void)
992 LPSTR root;
993 char path[10];
994 char root_expected[26][4];
995 char drive;
996 int j;
998 /* set up the expected paths */
999 for (drive = 'A'; drive <= 'Z'; drive++)
1000 sprintf(root_expected[drive - 'A'], "%c:\\", drive);
1002 /* test the expected values */
1003 for (j = 0; j < 26; j++)
1005 SetLastError(0xdeadbeef);
1006 lstrcpy(path, "aaaaaaaaa");
1007 root = PathBuildRootA(path, j);
1008 ok(root == path, "Expected root == path, got %p\n", root);
1009 ok(!lstrcmp(root, root_expected[j]), "Expected %s, got %s\n", root_expected[j], root);
1010 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1013 /* test a negative drive number */
1014 SetLastError(0xdeadbeef);
1015 lstrcpy(path, "aaaaaaaaa");
1016 root = PathBuildRootA(path, -1);
1017 ok(root == path, "Expected root == path, got %p\n", root);
1018 ok(!lstrcmp(path, "aaaaaaaaa") ||
1019 lstrlenA(path) == 0, /* Vista */
1020 "Expected aaaaaaaaa or empty string, got %s\n", path);
1021 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1023 /* test a drive number greater than 25 */
1024 SetLastError(0xdeadbeef);
1025 lstrcpy(path, "aaaaaaaaa");
1026 root = PathBuildRootA(path, 26);
1027 ok(root == path, "Expected root == path, got %p\n", root);
1028 ok(!lstrcmp(path, "aaaaaaaaa") ||
1029 lstrlenA(path) == 0, /* Vista */
1030 "Expected aaaaaaaaa or empty string, got %s\n", path);
1031 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1033 /* length of path is less than 4 */
1034 SetLastError(0xdeadbeef);
1035 lstrcpy(path, "aa");
1036 root = PathBuildRootA(path, 0);
1037 ok(root == path, "Expected root == path, got %p\n", root);
1038 ok(!lstrcmp(path, "A:\\"), "Expected A:\\, got %s\n", path);
1039 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1041 /* path is NULL */
1042 SetLastError(0xdeadbeef);
1043 root = PathBuildRootA(NULL, 0);
1044 ok(root == NULL, "Expected root == NULL, got %p\n", root);
1045 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1048 static void test_PathCommonPrefixA(void)
1050 char path1[MAX_PATH], path2[MAX_PATH];
1051 char out[MAX_PATH];
1052 int count;
1054 /* test NULL path1 */
1055 SetLastError(0xdeadbeef);
1056 lstrcpy(path2, "C:\\");
1057 lstrcpy(out, "aaa");
1058 count = PathCommonPrefixA(NULL, path2, out);
1059 ok(count == 0, "Expected 0, got %i\n", count);
1060 todo_wine
1062 ok(!lstrcmp(out, "aaa"), "Expected aaa, got %s\n", out);
1064 ok(!lstrcmp(path2, "C:\\"), "Expected C:\\, got %s\n", path2);
1065 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1067 /* test NULL path2 */
1068 SetLastError(0xdeadbeef);
1069 lstrcpy(path1, "C:\\");
1070 lstrcpy(out, "aaa");
1071 count = PathCommonPrefixA(path1, NULL, out);
1072 ok(count == 0, "Expected 0, got %i\n", count);
1073 todo_wine
1075 ok(!lstrcmp(out, "aaa"), "Expected aaa, got %s\n", out);
1077 ok(!lstrcmp(path1, "C:\\"), "Expected C:\\, got %s\n", path1);
1078 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1080 /* test empty path1 */
1081 SetLastError(0xdeadbeef);
1082 path1[0] = '\0';
1083 lstrcpy(path2, "C:\\");
1084 lstrcpy(out, "aaa");
1085 count = PathCommonPrefixA(path1, path2, out);
1086 ok(count == 0, "Expected 0, got %i\n", count);
1087 ok(lstrlen(out) == 0, "Expected 0 length out, got %i\n", lstrlen(out));
1088 ok(lstrlen(path1) == 0, "Expected 0 length path1, got %i\n", lstrlen(path1));
1089 ok(!lstrcmp(path2, "C:\\"), "Expected C:\\, got %s\n", path2);
1090 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1092 /* test empty path1 */
1093 SetLastError(0xdeadbeef);
1094 path2[0] = '\0';
1095 lstrcpy(path1, "C:\\");
1096 lstrcpy(out, "aaa");
1097 count = PathCommonPrefixA(path1, path2, out);
1098 ok(count == 0, "Expected 0, got %i\n", count);
1099 ok(lstrlen(out) == 0, "Expected 0 length out, got %i\n", lstrlen(out));
1100 ok(lstrlen(path2) == 0, "Expected 0 length path2, got %i\n", lstrlen(path2));
1101 ok(!lstrcmp(path1, "C:\\"), "Expected C:\\, got %s\n", path1);
1102 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1104 /* paths are legit, out is NULL */
1105 SetLastError(0xdeadbeef);
1106 lstrcpy(path1, "C:\\");
1107 lstrcpy(path2, "C:\\");
1108 count = PathCommonPrefixA(path1, path2, NULL);
1109 ok(count == 3, "Expected 3, got %i\n", count);
1110 ok(!lstrcmp(path1, "C:\\"), "Expected C:\\, got %s\n", path1);
1111 ok(!lstrcmp(path2, "C:\\"), "Expected C:\\, got %s\n", path2);
1112 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1114 /* all parameters legit */
1115 SetLastError(0xdeadbeef);
1116 lstrcpy(path1, "C:\\");
1117 lstrcpy(path2, "C:\\");
1118 lstrcpy(out, "aaa");
1119 count = PathCommonPrefixA(path1, path2, out);
1120 ok(count == 3, "Expected 3, got %i\n", count);
1121 ok(!lstrcmp(path1, "C:\\"), "Expected C:\\, got %s\n", path1);
1122 ok(!lstrcmp(path2, "C:\\"), "Expected C:\\, got %s\n", path2);
1123 ok(!lstrcmp(out, "C:\\"), "Expected C:\\, got %s\n", out);
1124 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1126 /* path1 and path2 not the same, but common prefix */
1127 SetLastError(0xdeadbeef);
1128 lstrcpy(path1, "C:\\one\\two");
1129 lstrcpy(path2, "C:\\one\\three");
1130 lstrcpy(out, "aaa");
1131 count = PathCommonPrefixA(path1, path2, out);
1132 ok(count == 6, "Expected 6, got %i\n", count);
1133 ok(!lstrcmp(path1, "C:\\one\\two"), "Expected C:\\one\\two, got %s\n", path1);
1134 ok(!lstrcmp(path2, "C:\\one\\three"), "Expected C:\\one\\three, got %s\n", path2);
1135 ok(!lstrcmp(out, "C:\\one"), "Expected C:\\one, got %s\n", out);
1136 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1138 /* try . prefix */
1139 SetLastError(0xdeadbeef);
1140 lstrcpy(path1, "one\\.two");
1141 lstrcpy(path2, "one\\.three");
1142 lstrcpy(out, "aaa");
1143 count = PathCommonPrefixA(path1, path2, out);
1144 ok(count == 3, "Expected 3, got %i\n", count);
1145 ok(!lstrcmp(path1, "one\\.two"), "Expected one\\.two, got %s\n", path1);
1146 ok(!lstrcmp(path2, "one\\.three"), "Expected one\\.three, got %s\n", path2);
1147 ok(!lstrcmp(out, "one"), "Expected one, got %s\n", out);
1148 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1150 /* try .. prefix */
1151 SetLastError(0xdeadbeef);
1152 lstrcpy(path1, "one\\..two");
1153 lstrcpy(path2, "one\\..three");
1154 lstrcpy(out, "aaa");
1155 count = PathCommonPrefixA(path1, path2, out);
1156 ok(count == 3, "Expected 3, got %i\n", count);
1157 ok(!lstrcmp(path1, "one\\..two"), "Expected one\\..two, got %s\n", path1);
1158 ok(!lstrcmp(path2, "one\\..three"), "Expected one\\..three, got %s\n", path2);
1159 ok(!lstrcmp(out, "one"), "Expected one, got %s\n", out);
1160 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1162 /* try ... prefix */
1163 SetLastError(0xdeadbeef);
1164 lstrcpy(path1, "one\\...two");
1165 lstrcpy(path2, "one\\...three");
1166 lstrcpy(out, "aaa");
1167 count = PathCommonPrefixA(path1, path2, out);
1168 ok(count == 3, "Expected 3, got %i\n", count);
1169 ok(!lstrcmp(path1, "one\\...two"), "Expected one\\...two, got %s\n", path1);
1170 ok(!lstrcmp(path2, "one\\...three"), "Expected one\\...three, got %s\n", path2);
1171 ok(!lstrcmp(out, "one"), "Expected one, got %s\n", out);
1172 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1174 /* try .\ prefix */
1175 SetLastError(0xdeadbeef);
1176 lstrcpy(path1, "one\\.\\two");
1177 lstrcpy(path2, "one\\.\\three");
1178 lstrcpy(out, "aaa");
1179 count = PathCommonPrefixA(path1, path2, out);
1180 ok(count == 5, "Expected 5, got %i\n", count);
1181 ok(!lstrcmp(path1, "one\\.\\two"), "Expected one\\.\\two, got %s\n", path1);
1182 ok(!lstrcmp(path2, "one\\.\\three"), "Expected one\\.\\three, got %s\n", path2);
1183 ok(!lstrcmp(out, "one\\."), "Expected one\\., got %s\n", out);
1184 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1186 /* try ..\ prefix */
1187 SetLastError(0xdeadbeef);
1188 lstrcpy(path1, "one\\..\\two");
1189 lstrcpy(path2, "one\\..\\three");
1190 lstrcpy(out, "aaa");
1191 count = PathCommonPrefixA(path1, path2, out);
1192 ok(count == 6, "Expected 6, got %i\n", count);
1193 ok(!lstrcmp(path1, "one\\..\\two"), "Expected one\\..\\two, got %s\n", path1);
1194 ok(!lstrcmp(path2, "one\\..\\three"), "Expected one\\..\\three, got %s\n", path2);
1195 ok(!lstrcmp(out, "one\\.."), "Expected one\\.., got %s\n", out);
1196 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1198 /* try ...\\ prefix */
1199 SetLastError(0xdeadbeef);
1200 lstrcpy(path1, "one\\...\\two");
1201 lstrcpy(path2, "one\\...\\three");
1202 lstrcpy(out, "aaa");
1203 count = PathCommonPrefixA(path1, path2, out);
1204 ok(count == 7, "Expected 7, got %i\n", count);
1205 ok(!lstrcmp(path1, "one\\...\\two"), "Expected one\\...\\two, got %s\n", path1);
1206 ok(!lstrcmp(path2, "one\\...\\three"), "Expected one\\...\\three, got %s\n", path2);
1207 ok(!lstrcmp(out, "one\\..."), "Expected one\\..., got %s\n", out);
1208 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1210 /* try prefix that is not an msdn labeled prefix type */
1211 SetLastError(0xdeadbeef);
1212 lstrcpy(path1, "same");
1213 lstrcpy(path2, "same");
1214 lstrcpy(out, "aaa");
1215 count = PathCommonPrefixA(path1, path2, out);
1216 ok(count == 4, "Expected 4, got %i\n", count);
1217 ok(!lstrcmp(path1, "same"), "Expected same, got %s\n", path1);
1218 ok(!lstrcmp(path2, "same"), "Expected same, got %s\n", path2);
1219 ok(!lstrcmp(out, "same"), "Expected same, got %s\n", out);
1220 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1222 /* try . after directory */
1223 SetLastError(0xdeadbeef);
1224 lstrcpy(path1, "one\\mid.\\two");
1225 lstrcpy(path2, "one\\mid.\\three");
1226 lstrcpy(out, "aaa");
1227 count = PathCommonPrefixA(path1, path2, out);
1228 ok(count == 8, "Expected 8, got %i\n", count);
1229 ok(!lstrcmp(path1, "one\\mid.\\two"), "Expected one\\mid.\\two, got %s\n", path1);
1230 ok(!lstrcmp(path2, "one\\mid.\\three"), "Expected one\\mid.\\three, got %s\n", path2);
1231 ok(!lstrcmp(out, "one\\mid."), "Expected one\\mid., got %s\n", out);
1232 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1234 /* try . in the middle of a directory */
1235 SetLastError(0xdeadbeef);
1236 lstrcpy(path1, "one\\mid.end\\two");
1237 lstrcpy(path2, "one\\mid.end\\three");
1238 lstrcpy(out, "aaa");
1239 count = PathCommonPrefixA(path1, path2, out);
1240 ok(count == 11, "Expected 11, got %i\n", count);
1241 ok(!lstrcmp(path1, "one\\mid.end\\two"), "Expected one\\mid.end\\two, got %s\n", path1);
1242 ok(!lstrcmp(path2, "one\\mid.end\\three"), "Expected one\\mid.end\\three, got %s\n", path2);
1243 ok(!lstrcmp(out, "one\\mid.end"), "Expected one\\mid.end, got %s\n", out);
1244 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1246 /* try comparing a .. with the expanded path */
1247 SetLastError(0xdeadbeef);
1248 lstrcpy(path1, "one\\..\\two");
1249 lstrcpy(path2, "two");
1250 lstrcpy(out, "aaa");
1251 count = PathCommonPrefixA(path1, path2, out);
1252 ok(count == 0, "Expected 0, got %i\n", count);
1253 ok(!lstrcmp(path1, "one\\..\\two"), "Expected one\\..\\two, got %s\n", path1);
1254 ok(!lstrcmp(path2, "two"), "Expected two, got %s\n", path2);
1255 ok(lstrlen(out) == 0, "Expected 0 length out, got %i\n", lstrlen(out));
1256 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1259 static void test_PathUnquoteSpaces(void)
1261 int i;
1262 for(i = 0; i < sizeof(TEST_PATH_UNQUOTE_SPACES) / sizeof(TEST_PATH_UNQUOTE_SPACES[0]); i++)
1264 char *path = strdupA(TEST_PATH_UNQUOTE_SPACES[i].path);
1265 WCHAR *pathW = GetWideString(TEST_PATH_UNQUOTE_SPACES[i].path);
1266 WCHAR *resultW = GetWideString(TEST_PATH_UNQUOTE_SPACES[i].result);
1268 PathUnquoteSpacesA(path);
1269 ok(!strcmp(path, TEST_PATH_UNQUOTE_SPACES[i].result), "%s (A): got %s expected %s\n",
1270 TEST_PATH_UNQUOTE_SPACES[i].path, path,
1271 TEST_PATH_UNQUOTE_SPACES[i].result);
1273 PathUnquoteSpacesW(pathW);
1274 ok(!lstrcmpW(pathW, resultW), "%s (W): strings differ\n",
1275 TEST_PATH_UNQUOTE_SPACES[i].path);
1276 FreeWideString(pathW);
1277 FreeWideString(resultW);
1278 HeapFree(GetProcessHeap(), 0, path);
1282 /* ################ */
1284 START_TEST(path)
1286 hShlwapi = GetModuleHandleA("shlwapi.dll");
1288 test_PathSearchAndQualify();
1289 test_PathCreateFromUrl();
1290 test_PathIsUrl();
1292 test_PathAddBackslash();
1293 test_PathMakePretty();
1294 test_PathMatchSpec();
1296 /* For whatever reason, PathIsValidCharA and PathAppendA share the same
1297 * ordinal number in some native versions. Check this to prevent a crash.
1299 pPathIsValidCharA = (void*)GetProcAddress(hShlwapi, (LPSTR)455);
1300 if (pPathIsValidCharA && pPathIsValidCharA != (void*)GetProcAddress(hShlwapi, "PathAppendA"))
1302 test_PathIsValidCharA();
1304 pPathIsValidCharW = (void*)GetProcAddress(hShlwapi, (LPSTR)456);
1305 if (pPathIsValidCharW) test_PathIsValidCharW();
1308 pPathCombineW = (void*)GetProcAddress(hShlwapi, "PathCombineW");
1309 if (pPathCombineW)
1310 test_PathCombineW();
1312 test_PathCombineA();
1313 test_PathAppendA();
1314 test_PathCanonicalizeA();
1315 test_PathFindExtensionA();
1316 test_PathBuildRootA();
1317 test_PathCommonPrefixA();
1318 test_PathUnquoteSpaces();