shlwapi/tests: Fix a test on Vista.
[wine/multimedia.git] / dlls / shlwapi / tests / path.c
blob6f55395d4c66c34d95cff2b1dffee9e3b9f17877
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[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 todo_wine
815 ok(!lstrcmp(dest, "test"), "Expected test, got %s\n", dest);
818 /* try an empty source */
819 lstrcpy(dest, "test");
820 SetLastError(0xdeadbeef);
821 res = PathCanonicalizeA(dest, "");
822 ok(res, "Expected success\n");
823 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
824 ok(!lstrcmp(dest, "\\"), "Expected \\, got %s\n", dest);
826 /* try a NULL dest */
827 SetLastError(0xdeadbeef);
828 res = PathCanonicalizeA(NULL, "C:\\");
829 ok(!res, "Expected failure\n");
830 ok(GetLastError() == ERROR_INVALID_PARAMETER,
831 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
833 /* try empty dest */
834 dest[0] = '\0';
835 SetLastError(0xdeadbeef);
836 res = PathCanonicalizeA(dest, "C:\\");
837 ok(res, "Expected success\n");
838 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
839 ok(!lstrcmp(dest, "C:\\"), "Expected C:\\, got %s\n", dest);
841 /* try non-empty dest */
842 lstrcpy(dest, "test");
843 SetLastError(0xdeadbeef);
844 res = PathCanonicalizeA(dest, "C:\\");
845 ok(res, "Expected success\n");
846 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
847 ok(!lstrcmp(dest, "C:\\"), "Expected C:\\, got %s\n", dest);
849 /* try a space for source */
850 lstrcpy(dest, "test");
851 SetLastError(0xdeadbeef);
852 res = PathCanonicalizeA(dest, " ");
853 ok(res, "Expected success\n");
854 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
855 ok(!lstrcmp(dest, " "), "Expected ' ', got %s\n", dest);
857 /* try a relative path */
858 lstrcpy(dest, "test");
859 SetLastError(0xdeadbeef);
860 res = PathCanonicalizeA(dest, "one\\two");
861 ok(res, "Expected success\n");
862 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
863 ok(!lstrcmp(dest, "one\\two"), "Expected one\\two, got %s\n", dest);
865 /* try current dir and previous dir */
866 lstrcpy(dest, "test");
867 SetLastError(0xdeadbeef);
868 res = PathCanonicalizeA(dest, "C:\\one\\.\\..\\two\\three\\..");
869 ok(res, "Expected success\n");
870 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
871 ok(!lstrcmp(dest, "C:\\two"), "Expected C:\\two, got %s\n", dest);
873 /* try simple forward slashes */
874 lstrcpy(dest, "test");
875 SetLastError(0xdeadbeef);
876 res = PathCanonicalizeA(dest, "C:\\one/two/three\\four/five\\six");
877 ok(res, "Expected success\n");
878 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
879 ok(!lstrcmp(dest, "C:\\one/two/three\\four/five\\six"),
880 "Expected C:\\one/two/three\\four/five\\six, got %s\n", dest);
882 /* try simple forward slashes with same dir */
883 lstrcpy(dest, "test");
884 SetLastError(0xdeadbeef);
885 res = PathCanonicalizeA(dest, "C:\\one/.\\two");
886 ok(res, "Expected success\n");
887 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
888 ok(!lstrcmp(dest, "C:\\one/.\\two"), "Expected C:\\one/.\\two, got %s\n", dest);
890 /* try simple forward slashes with change dir */
891 lstrcpy(dest, "test");
892 SetLastError(0xdeadbeef);
893 res = PathCanonicalizeA(dest, "C:\\one/.\\two\\..");
894 ok(res, "Expected success\n");
895 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
896 ok(!lstrcmp(dest, "C:\\one/."), "Expected 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, "Expected 0xdeadbeef, got %d\n", GetLastError());
920 ok(lstrlen(too_long) == LONG_LEN - 1, "Expected length LONG_LEN - 1, got %i\n", lstrlen(too_long));
923 static void test_PathFindExtensionA(void)
925 LPSTR ext;
926 char path[MAX_PATH];
927 char too_long[LONG_LEN];
929 /* try a NULL path */
930 SetLastError(0xdeadbeef);
931 ext = PathFindExtensionA(NULL);
932 ok(ext == NULL, "Expected NULL, got %p\n", ext);
933 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
935 /* try an empty path */
936 path[0] = '\0';
937 SetLastError(0xdeadbeef);
938 ext = PathFindExtensionA(path);
939 ok(ext == path, "Expected ext == path, got %p\n", ext);
940 ok(lstrlen(ext) == 0, "Expected length 0, got %i\n", lstrlen(ext));
941 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
943 /* try a path without an extension */
944 lstrcpy(path, "file");
945 SetLastError(0xdeadbeef);
946 ext = PathFindExtensionA(path);
947 ok(ext == path + lstrlen(path), "Expected ext == path, got %p\n", ext);
948 ok(lstrlen(ext) == 0, "Expected length 0, got %i\n", lstrlen(ext));
949 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
951 /* try a path with an extension */
952 lstrcpy(path, "file.txt");
953 SetLastError(0xdeadbeef);
954 ext = PathFindExtensionA(path);
955 ok(ext == path + lstrlen("file"),
956 "Expected ext == path + lstrlen(\"file\"), got %p\n", ext);
957 ok(!lstrcmp(ext, ".txt"), "Expected .txt, got %s\n", ext);
958 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
960 /* try a path with two extensions */
961 lstrcpy(path, "file.txt.doc");
962 SetLastError(0xdeadbeef);
963 ext = PathFindExtensionA(path);
964 ok(ext == path + lstrlen("file.txt"),
965 "Expected ext == path + lstrlen(\"file.txt\"), got %p\n", ext);
966 ok(!lstrcmp(ext, ".doc"), "Expected .txt, got %s\n", ext);
967 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
969 /* try a path longer than MAX_PATH without an extension*/
970 memset(too_long, 'a', LONG_LEN);
971 too_long[LONG_LEN - 1] = '\0';
972 SetLastError(0xdeadbeef);
973 ext = PathFindExtensionA(too_long);
974 ok(ext == too_long + LONG_LEN - 1, "Expected ext == too_long + LONG_LEN - 1, got %p\n", ext);
975 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
977 /* try a path longer than MAX_PATH with an extension*/
978 memset(too_long, 'a', LONG_LEN);
979 too_long[LONG_LEN - 1] = '\0';
980 lstrcpy(too_long + 300, ".abcde");
981 too_long[lstrlen(too_long)] = 'a';
982 SetLastError(0xdeadbeef);
983 ext = PathFindExtensionA(too_long);
984 ok(ext == too_long + 300, "Expected ext == too_long + 300, got %p\n", ext);
985 ok(lstrlen(ext) == LONG_LEN - 301, "Expected LONG_LEN - 301, got %i\n", lstrlen(ext));
986 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
989 static void test_PathBuildRootA(void)
991 LPSTR root;
992 char path[10];
993 char root_expected[26][4];
994 char drive;
995 int j;
997 /* set up the expected paths */
998 for (drive = 'A'; drive <= 'Z'; drive++)
999 sprintf(root_expected[drive - 'A'], "%c:\\", drive);
1001 /* test the expected values */
1002 for (j = 0; j < 26; j++)
1004 SetLastError(0xdeadbeef);
1005 lstrcpy(path, "aaaaaaaaa");
1006 root = PathBuildRootA(path, j);
1007 ok(root == path, "Expected root == path, got %p\n", root);
1008 ok(!lstrcmp(root, root_expected[j]), "Expected %s, got %s\n", root_expected[j], root);
1009 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1012 /* test a negative drive number */
1013 SetLastError(0xdeadbeef);
1014 lstrcpy(path, "aaaaaaaaa");
1015 root = PathBuildRootA(path, -1);
1016 ok(root == path, "Expected root == path, got %p\n", root);
1017 ok(!lstrcmp(path, "aaaaaaaaa"), "Expected aaaaaaaaa, got %s\n", path);
1018 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1020 /* test a drive number greater than 25 */
1021 SetLastError(0xdeadbeef);
1022 lstrcpy(path, "aaaaaaaaa");
1023 root = PathBuildRootA(path, 26);
1024 ok(root == path, "Expected root == path, got %p\n", root);
1025 ok(!lstrcmp(path, "aaaaaaaaa"), "Expected aaaaaaaaa, got %s\n", path);
1026 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1028 /* length of path is less than 4 */
1029 SetLastError(0xdeadbeef);
1030 lstrcpy(path, "aa");
1031 root = PathBuildRootA(path, 0);
1032 ok(root == path, "Expected root == path, got %p\n", root);
1033 ok(!lstrcmp(path, "A:\\"), "Expected A:\\, got %s\n", path);
1034 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1036 /* path is NULL */
1037 SetLastError(0xdeadbeef);
1038 root = PathBuildRootA(NULL, 0);
1039 ok(root == NULL, "Expected root == NULL, got %p\n", root);
1040 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1043 static void test_PathCommonPrefixA(void)
1045 char path1[MAX_PATH], path2[MAX_PATH];
1046 char out[MAX_PATH];
1047 int count;
1049 /* test NULL path1 */
1050 SetLastError(0xdeadbeef);
1051 lstrcpy(path2, "C:\\");
1052 lstrcpy(out, "aaa");
1053 count = PathCommonPrefixA(NULL, path2, out);
1054 ok(count == 0, "Expected 0, got %i\n", count);
1055 todo_wine
1057 ok(!lstrcmp(out, "aaa"), "Expected aaa, got %s\n", out);
1059 ok(!lstrcmp(path2, "C:\\"), "Expected C:\\, got %s\n", path2);
1060 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1062 /* test NULL path2 */
1063 SetLastError(0xdeadbeef);
1064 lstrcpy(path1, "C:\\");
1065 lstrcpy(out, "aaa");
1066 count = PathCommonPrefixA(path1, NULL, out);
1067 ok(count == 0, "Expected 0, got %i\n", count);
1068 todo_wine
1070 ok(!lstrcmp(out, "aaa"), "Expected aaa, got %s\n", out);
1072 ok(!lstrcmp(path1, "C:\\"), "Expected C:\\, got %s\n", path1);
1073 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1075 /* test empty path1 */
1076 SetLastError(0xdeadbeef);
1077 path1[0] = '\0';
1078 lstrcpy(path2, "C:\\");
1079 lstrcpy(out, "aaa");
1080 count = PathCommonPrefixA(path1, path2, out);
1081 ok(count == 0, "Expected 0, got %i\n", count);
1082 ok(lstrlen(out) == 0, "Expected 0 length out, got %i\n", lstrlen(out));
1083 ok(lstrlen(path1) == 0, "Expected 0 length path1, got %i\n", lstrlen(path1));
1084 ok(!lstrcmp(path2, "C:\\"), "Expected C:\\, got %s\n", path2);
1085 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1087 /* test empty path1 */
1088 SetLastError(0xdeadbeef);
1089 path2[0] = '\0';
1090 lstrcpy(path1, "C:\\");
1091 lstrcpy(out, "aaa");
1092 count = PathCommonPrefixA(path1, path2, out);
1093 ok(count == 0, "Expected 0, got %i\n", count);
1094 ok(lstrlen(out) == 0, "Expected 0 length out, got %i\n", lstrlen(out));
1095 ok(lstrlen(path2) == 0, "Expected 0 length path2, got %i\n", lstrlen(path2));
1096 ok(!lstrcmp(path1, "C:\\"), "Expected C:\\, got %s\n", path1);
1097 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1099 /* paths are legit, out is NULL */
1100 SetLastError(0xdeadbeef);
1101 lstrcpy(path1, "C:\\");
1102 lstrcpy(path2, "C:\\");
1103 count = PathCommonPrefixA(path1, path2, NULL);
1104 ok(count == 3, "Expected 3, got %i\n", count);
1105 ok(!lstrcmp(path1, "C:\\"), "Expected C:\\, got %s\n", path1);
1106 ok(!lstrcmp(path2, "C:\\"), "Expected C:\\, got %s\n", path2);
1107 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1109 /* all parameters legit */
1110 SetLastError(0xdeadbeef);
1111 lstrcpy(path1, "C:\\");
1112 lstrcpy(path2, "C:\\");
1113 lstrcpy(out, "aaa");
1114 count = PathCommonPrefixA(path1, path2, out);
1115 ok(count == 3, "Expected 3, got %i\n", count);
1116 ok(!lstrcmp(path1, "C:\\"), "Expected C:\\, got %s\n", path1);
1117 ok(!lstrcmp(path2, "C:\\"), "Expected C:\\, got %s\n", path2);
1118 ok(!lstrcmp(out, "C:\\"), "Expected C:\\, got %s\n", out);
1119 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1121 /* path1 and path2 not the same, but common prefix */
1122 SetLastError(0xdeadbeef);
1123 lstrcpy(path1, "C:\\one\\two");
1124 lstrcpy(path2, "C:\\one\\three");
1125 lstrcpy(out, "aaa");
1126 count = PathCommonPrefixA(path1, path2, out);
1127 ok(count == 6, "Expected 6, got %i\n", count);
1128 ok(!lstrcmp(path1, "C:\\one\\two"), "Expected C:\\one\\two, got %s\n", path1);
1129 ok(!lstrcmp(path2, "C:\\one\\three"), "Expected C:\\one\\three, got %s\n", path2);
1130 ok(!lstrcmp(out, "C:\\one"), "Expected C:\\one, got %s\n", out);
1131 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1133 /* try . prefix */
1134 SetLastError(0xdeadbeef);
1135 lstrcpy(path1, "one\\.two");
1136 lstrcpy(path2, "one\\.three");
1137 lstrcpy(out, "aaa");
1138 count = PathCommonPrefixA(path1, path2, out);
1139 ok(count == 3, "Expected 3, got %i\n", count);
1140 ok(!lstrcmp(path1, "one\\.two"), "Expected one\\.two, got %s\n", path1);
1141 ok(!lstrcmp(path2, "one\\.three"), "Expected one\\.three, got %s\n", path2);
1142 ok(!lstrcmp(out, "one"), "Expected one, got %s\n", out);
1143 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1145 /* try .. prefix */
1146 SetLastError(0xdeadbeef);
1147 lstrcpy(path1, "one\\..two");
1148 lstrcpy(path2, "one\\..three");
1149 lstrcpy(out, "aaa");
1150 count = PathCommonPrefixA(path1, path2, out);
1151 ok(count == 3, "Expected 3, got %i\n", count);
1152 ok(!lstrcmp(path1, "one\\..two"), "Expected one\\..two, got %s\n", path1);
1153 ok(!lstrcmp(path2, "one\\..three"), "Expected one\\..three, got %s\n", path2);
1154 ok(!lstrcmp(out, "one"), "Expected one, got %s\n", out);
1155 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1157 /* try ... prefix */
1158 SetLastError(0xdeadbeef);
1159 lstrcpy(path1, "one\\...two");
1160 lstrcpy(path2, "one\\...three");
1161 lstrcpy(out, "aaa");
1162 count = PathCommonPrefixA(path1, path2, out);
1163 ok(count == 3, "Expected 3, got %i\n", count);
1164 ok(!lstrcmp(path1, "one\\...two"), "Expected one\\...two, got %s\n", path1);
1165 ok(!lstrcmp(path2, "one\\...three"), "Expected one\\...three, got %s\n", path2);
1166 ok(!lstrcmp(out, "one"), "Expected one, got %s\n", out);
1167 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1169 /* try .\ prefix */
1170 SetLastError(0xdeadbeef);
1171 lstrcpy(path1, "one\\.\\two");
1172 lstrcpy(path2, "one\\.\\three");
1173 lstrcpy(out, "aaa");
1174 count = PathCommonPrefixA(path1, path2, out);
1175 ok(count == 5, "Expected 5, got %i\n", count);
1176 ok(!lstrcmp(path1, "one\\.\\two"), "Expected one\\.\\two, got %s\n", path1);
1177 ok(!lstrcmp(path2, "one\\.\\three"), "Expected one\\.\\three, got %s\n", path2);
1178 ok(!lstrcmp(out, "one\\."), "Expected one\\., got %s\n", out);
1179 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1181 /* try ..\ prefix */
1182 SetLastError(0xdeadbeef);
1183 lstrcpy(path1, "one\\..\\two");
1184 lstrcpy(path2, "one\\..\\three");
1185 lstrcpy(out, "aaa");
1186 count = PathCommonPrefixA(path1, path2, out);
1187 ok(count == 6, "Expected 6, got %i\n", count);
1188 ok(!lstrcmp(path1, "one\\..\\two"), "Expected one\\..\\two, got %s\n", path1);
1189 ok(!lstrcmp(path2, "one\\..\\three"), "Expected one\\..\\three, got %s\n", path2);
1190 ok(!lstrcmp(out, "one\\.."), "Expected one\\.., got %s\n", out);
1191 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1193 /* try ...\\ prefix */
1194 SetLastError(0xdeadbeef);
1195 lstrcpy(path1, "one\\...\\two");
1196 lstrcpy(path2, "one\\...\\three");
1197 lstrcpy(out, "aaa");
1198 count = PathCommonPrefixA(path1, path2, out);
1199 ok(count == 7, "Expected 7, got %i\n", count);
1200 ok(!lstrcmp(path1, "one\\...\\two"), "Expected one\\...\\two, got %s\n", path1);
1201 ok(!lstrcmp(path2, "one\\...\\three"), "Expected one\\...\\three, got %s\n", path2);
1202 ok(!lstrcmp(out, "one\\..."), "Expected one\\..., got %s\n", out);
1203 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1205 /* try prefix that is not an msdn labeled prefix type */
1206 SetLastError(0xdeadbeef);
1207 lstrcpy(path1, "same");
1208 lstrcpy(path2, "same");
1209 lstrcpy(out, "aaa");
1210 count = PathCommonPrefixA(path1, path2, out);
1211 ok(count == 4, "Expected 4, got %i\n", count);
1212 ok(!lstrcmp(path1, "same"), "Expected same, got %s\n", path1);
1213 ok(!lstrcmp(path2, "same"), "Expected same, got %s\n", path2);
1214 ok(!lstrcmp(out, "same"), "Expected same, got %s\n", out);
1215 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1217 /* try . after directory */
1218 SetLastError(0xdeadbeef);
1219 lstrcpy(path1, "one\\mid.\\two");
1220 lstrcpy(path2, "one\\mid.\\three");
1221 lstrcpy(out, "aaa");
1222 count = PathCommonPrefixA(path1, path2, out);
1223 ok(count == 8, "Expected 8, got %i\n", count);
1224 ok(!lstrcmp(path1, "one\\mid.\\two"), "Expected one\\mid.\\two, got %s\n", path1);
1225 ok(!lstrcmp(path2, "one\\mid.\\three"), "Expected one\\mid.\\three, got %s\n", path2);
1226 ok(!lstrcmp(out, "one\\mid."), "Expected one\\mid., got %s\n", out);
1227 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1229 /* try . in the middle of a directory */
1230 SetLastError(0xdeadbeef);
1231 lstrcpy(path1, "one\\mid.end\\two");
1232 lstrcpy(path2, "one\\mid.end\\three");
1233 lstrcpy(out, "aaa");
1234 count = PathCommonPrefixA(path1, path2, out);
1235 ok(count == 11, "Expected 11, got %i\n", count);
1236 ok(!lstrcmp(path1, "one\\mid.end\\two"), "Expected one\\mid.end\\two, got %s\n", path1);
1237 ok(!lstrcmp(path2, "one\\mid.end\\three"), "Expected one\\mid.end\\three, got %s\n", path2);
1238 ok(!lstrcmp(out, "one\\mid.end"), "Expected one\\mid.end, got %s\n", out);
1239 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1241 /* try comparing a .. with the expanded path */
1242 SetLastError(0xdeadbeef);
1243 lstrcpy(path1, "one\\..\\two");
1244 lstrcpy(path2, "two");
1245 lstrcpy(out, "aaa");
1246 count = PathCommonPrefixA(path1, path2, out);
1247 ok(count == 0, "Expected 0, got %i\n", count);
1248 ok(!lstrcmp(path1, "one\\..\\two"), "Expected one\\..\\two, got %s\n", path1);
1249 ok(!lstrcmp(path2, "two"), "Expected two, got %s\n", path2);
1250 ok(lstrlen(out) == 0, "Expected 0 length out, got %i\n", lstrlen(out));
1251 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1254 static void test_PathUnquoteSpaces(void)
1256 int i;
1257 for(i = 0; i < sizeof(TEST_PATH_UNQUOTE_SPACES) / sizeof(TEST_PATH_UNQUOTE_SPACES[0]); i++)
1259 char *path = strdupA(TEST_PATH_UNQUOTE_SPACES[i].path);
1260 WCHAR *pathW = GetWideString(TEST_PATH_UNQUOTE_SPACES[i].path);
1261 WCHAR *resultW = GetWideString(TEST_PATH_UNQUOTE_SPACES[i].result);
1263 PathUnquoteSpacesA(path);
1264 ok(!strcmp(path, TEST_PATH_UNQUOTE_SPACES[i].result), "%s (A): got %s expected %s\n",
1265 TEST_PATH_UNQUOTE_SPACES[i].path, path,
1266 TEST_PATH_UNQUOTE_SPACES[i].result);
1268 PathUnquoteSpacesW(pathW);
1269 ok(!lstrcmpW(pathW, resultW), "%s (W): strings differ\n",
1270 TEST_PATH_UNQUOTE_SPACES[i].path);
1271 FreeWideString(pathW);
1272 FreeWideString(resultW);
1273 HeapFree(GetProcessHeap(), 0, path);
1277 /* ################ */
1279 START_TEST(path)
1281 hShlwapi = GetModuleHandleA("shlwapi.dll");
1283 test_PathSearchAndQualify();
1284 test_PathCreateFromUrl();
1285 test_PathIsUrl();
1287 test_PathAddBackslash();
1288 test_PathMakePretty();
1289 test_PathMatchSpec();
1291 /* For whatever reason, PathIsValidCharA and PathAppendA share the same
1292 * ordinal number in some native versions. Check this to prevent a crash.
1294 pPathIsValidCharA = (void*)GetProcAddress(hShlwapi, (LPSTR)455);
1295 if (pPathIsValidCharA && pPathIsValidCharA != (void*)GetProcAddress(hShlwapi, "PathAppendA"))
1297 test_PathIsValidCharA();
1299 pPathIsValidCharW = (void*)GetProcAddress(hShlwapi, (LPSTR)456);
1300 if (pPathIsValidCharW) test_PathIsValidCharW();
1303 pPathCombineW = (void*)GetProcAddress(hShlwapi, "PathCombineW");
1304 if (pPathCombineW)
1305 test_PathCombineW();
1307 test_PathCombineA();
1308 test_PathAppendA();
1309 test_PathCanonicalizeA();
1310 test_PathFindExtensionA();
1311 test_PathBuildRootA();
1312 test_PathCommonPrefixA();
1313 test_PathUnquoteSpaces();