push 18e7434c914c4b496a7d961dbc3fc7a912612215
[wine/hacks.git] / dlls / shlwapi / tests / path.c
blobd84ca7a8bd77aadd8076ae5a9be978512c1af9cb
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/."), "Expected C:\\one/., got %s\n", dest);
896 /* try forward slashes with change dirs
897 * NOTE: if there is a forward slash in between two backslashes,
898 * everything in between the two backslashes is considered on dir
900 lstrcpy(dest, "test");
901 SetLastError(0xdeadbeef);
902 res = PathCanonicalizeA(dest, "C:\\one/.\\..\\two/three\\..\\four/.five");
903 ok(res, "Expected success\n");
904 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
905 ok(!lstrcmp(dest, "C:\\four/.five"), "Expected C:\\four/.five, got %s\n", dest);
907 /* try src is too long */
908 memset(too_long, 'a', LONG_LEN);
909 too_long[LONG_LEN - 1] = '\0';
910 lstrcpy(dest, "test");
911 SetLastError(0xdeadbeef);
912 res = PathCanonicalizeA(dest, too_long);
913 ok(!res, "Expected failure\n");
914 todo_wine
916 ok(GetLastError() == 0xdeadbeef || GetLastError() == ERROR_FILENAME_EXCED_RANGE /* Vista */,
917 "Expected 0xdeadbeef or ERROR_FILENAME_EXCED_RANGE, got %d\n", GetLastError());
919 ok(lstrlen(too_long) == LONG_LEN - 1, "Expected length LONG_LEN - 1, got %i\n", lstrlen(too_long));
922 static void test_PathFindExtensionA(void)
924 LPSTR ext;
925 char path[MAX_PATH];
926 char too_long[LONG_LEN];
928 /* try a NULL path */
929 SetLastError(0xdeadbeef);
930 ext = PathFindExtensionA(NULL);
931 ok(ext == NULL, "Expected NULL, got %p\n", ext);
932 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
934 /* try an empty path */
935 path[0] = '\0';
936 SetLastError(0xdeadbeef);
937 ext = PathFindExtensionA(path);
938 ok(ext == path, "Expected ext == path, got %p\n", ext);
939 ok(lstrlen(ext) == 0, "Expected length 0, got %i\n", lstrlen(ext));
940 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
942 /* try a path without an extension */
943 lstrcpy(path, "file");
944 SetLastError(0xdeadbeef);
945 ext = PathFindExtensionA(path);
946 ok(ext == path + lstrlen(path), "Expected ext == path, got %p\n", ext);
947 ok(lstrlen(ext) == 0, "Expected length 0, got %i\n", lstrlen(ext));
948 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
950 /* try a path with an extension */
951 lstrcpy(path, "file.txt");
952 SetLastError(0xdeadbeef);
953 ext = PathFindExtensionA(path);
954 ok(ext == path + lstrlen("file"),
955 "Expected ext == path + lstrlen(\"file\"), got %p\n", ext);
956 ok(!lstrcmp(ext, ".txt"), "Expected .txt, got %s\n", ext);
957 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
959 /* try a path with two extensions */
960 lstrcpy(path, "file.txt.doc");
961 SetLastError(0xdeadbeef);
962 ext = PathFindExtensionA(path);
963 ok(ext == path + lstrlen("file.txt"),
964 "Expected ext == path + lstrlen(\"file.txt\"), got %p\n", ext);
965 ok(!lstrcmp(ext, ".doc"), "Expected .txt, got %s\n", ext);
966 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
968 /* try a path longer than MAX_PATH without an extension*/
969 memset(too_long, 'a', LONG_LEN);
970 too_long[LONG_LEN - 1] = '\0';
971 SetLastError(0xdeadbeef);
972 ext = PathFindExtensionA(too_long);
973 ok(ext == too_long + LONG_LEN - 1, "Expected ext == too_long + LONG_LEN - 1, got %p\n", ext);
974 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
976 /* try a path longer than MAX_PATH with an extension*/
977 memset(too_long, 'a', LONG_LEN);
978 too_long[LONG_LEN - 1] = '\0';
979 lstrcpy(too_long + 300, ".abcde");
980 too_long[lstrlen(too_long)] = 'a';
981 SetLastError(0xdeadbeef);
982 ext = PathFindExtensionA(too_long);
983 ok(ext == too_long + 300, "Expected ext == too_long + 300, got %p\n", ext);
984 ok(lstrlen(ext) == LONG_LEN - 301, "Expected LONG_LEN - 301, got %i\n", lstrlen(ext));
985 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
988 static void test_PathBuildRootA(void)
990 LPSTR root;
991 char path[10];
992 char root_expected[26][4];
993 char drive;
994 int j;
996 /* set up the expected paths */
997 for (drive = 'A'; drive <= 'Z'; drive++)
998 sprintf(root_expected[drive - 'A'], "%c:\\", drive);
1000 /* test the expected values */
1001 for (j = 0; j < 26; j++)
1003 SetLastError(0xdeadbeef);
1004 lstrcpy(path, "aaaaaaaaa");
1005 root = PathBuildRootA(path, j);
1006 ok(root == path, "Expected root == path, got %p\n", root);
1007 ok(!lstrcmp(root, root_expected[j]), "Expected %s, got %s\n", root_expected[j], root);
1008 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1011 /* test a negative drive number */
1012 SetLastError(0xdeadbeef);
1013 lstrcpy(path, "aaaaaaaaa");
1014 root = PathBuildRootA(path, -1);
1015 ok(root == path, "Expected root == path, got %p\n", root);
1016 ok(!lstrcmp(path, "aaaaaaaaa"), "Expected aaaaaaaaa, got %s\n", path);
1017 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1019 /* test a drive number greater than 25 */
1020 SetLastError(0xdeadbeef);
1021 lstrcpy(path, "aaaaaaaaa");
1022 root = PathBuildRootA(path, 26);
1023 ok(root == path, "Expected root == path, got %p\n", root);
1024 ok(!lstrcmp(path, "aaaaaaaaa"), "Expected aaaaaaaaa, got %s\n", path);
1025 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1027 /* length of path is less than 4 */
1028 SetLastError(0xdeadbeef);
1029 lstrcpy(path, "aa");
1030 root = PathBuildRootA(path, 0);
1031 ok(root == path, "Expected root == path, got %p\n", root);
1032 ok(!lstrcmp(path, "A:\\"), "Expected A:\\, got %s\n", path);
1033 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1035 /* path is NULL */
1036 SetLastError(0xdeadbeef);
1037 root = PathBuildRootA(NULL, 0);
1038 ok(root == NULL, "Expected root == NULL, got %p\n", root);
1039 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1042 static void test_PathCommonPrefixA(void)
1044 char path1[MAX_PATH], path2[MAX_PATH];
1045 char out[MAX_PATH];
1046 int count;
1048 /* test NULL path1 */
1049 SetLastError(0xdeadbeef);
1050 lstrcpy(path2, "C:\\");
1051 lstrcpy(out, "aaa");
1052 count = PathCommonPrefixA(NULL, path2, out);
1053 ok(count == 0, "Expected 0, got %i\n", count);
1054 todo_wine
1056 ok(!lstrcmp(out, "aaa"), "Expected aaa, got %s\n", out);
1058 ok(!lstrcmp(path2, "C:\\"), "Expected C:\\, got %s\n", path2);
1059 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1061 /* test NULL path2 */
1062 SetLastError(0xdeadbeef);
1063 lstrcpy(path1, "C:\\");
1064 lstrcpy(out, "aaa");
1065 count = PathCommonPrefixA(path1, NULL, out);
1066 ok(count == 0, "Expected 0, got %i\n", count);
1067 todo_wine
1069 ok(!lstrcmp(out, "aaa"), "Expected aaa, got %s\n", out);
1071 ok(!lstrcmp(path1, "C:\\"), "Expected C:\\, got %s\n", path1);
1072 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1074 /* test empty path1 */
1075 SetLastError(0xdeadbeef);
1076 path1[0] = '\0';
1077 lstrcpy(path2, "C:\\");
1078 lstrcpy(out, "aaa");
1079 count = PathCommonPrefixA(path1, path2, out);
1080 ok(count == 0, "Expected 0, got %i\n", count);
1081 ok(lstrlen(out) == 0, "Expected 0 length out, got %i\n", lstrlen(out));
1082 ok(lstrlen(path1) == 0, "Expected 0 length path1, got %i\n", lstrlen(path1));
1083 ok(!lstrcmp(path2, "C:\\"), "Expected C:\\, got %s\n", path2);
1084 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1086 /* test empty path1 */
1087 SetLastError(0xdeadbeef);
1088 path2[0] = '\0';
1089 lstrcpy(path1, "C:\\");
1090 lstrcpy(out, "aaa");
1091 count = PathCommonPrefixA(path1, path2, out);
1092 ok(count == 0, "Expected 0, got %i\n", count);
1093 ok(lstrlen(out) == 0, "Expected 0 length out, got %i\n", lstrlen(out));
1094 ok(lstrlen(path2) == 0, "Expected 0 length path2, got %i\n", lstrlen(path2));
1095 ok(!lstrcmp(path1, "C:\\"), "Expected C:\\, got %s\n", path1);
1096 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1098 /* paths are legit, out is NULL */
1099 SetLastError(0xdeadbeef);
1100 lstrcpy(path1, "C:\\");
1101 lstrcpy(path2, "C:\\");
1102 count = PathCommonPrefixA(path1, path2, NULL);
1103 ok(count == 3, "Expected 3, got %i\n", count);
1104 ok(!lstrcmp(path1, "C:\\"), "Expected C:\\, got %s\n", path1);
1105 ok(!lstrcmp(path2, "C:\\"), "Expected C:\\, got %s\n", path2);
1106 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1108 /* all parameters legit */
1109 SetLastError(0xdeadbeef);
1110 lstrcpy(path1, "C:\\");
1111 lstrcpy(path2, "C:\\");
1112 lstrcpy(out, "aaa");
1113 count = PathCommonPrefixA(path1, path2, out);
1114 ok(count == 3, "Expected 3, got %i\n", count);
1115 ok(!lstrcmp(path1, "C:\\"), "Expected C:\\, got %s\n", path1);
1116 ok(!lstrcmp(path2, "C:\\"), "Expected C:\\, got %s\n", path2);
1117 ok(!lstrcmp(out, "C:\\"), "Expected C:\\, got %s\n", out);
1118 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1120 /* path1 and path2 not the same, but common prefix */
1121 SetLastError(0xdeadbeef);
1122 lstrcpy(path1, "C:\\one\\two");
1123 lstrcpy(path2, "C:\\one\\three");
1124 lstrcpy(out, "aaa");
1125 count = PathCommonPrefixA(path1, path2, out);
1126 ok(count == 6, "Expected 6, got %i\n", count);
1127 ok(!lstrcmp(path1, "C:\\one\\two"), "Expected C:\\one\\two, got %s\n", path1);
1128 ok(!lstrcmp(path2, "C:\\one\\three"), "Expected C:\\one\\three, got %s\n", path2);
1129 ok(!lstrcmp(out, "C:\\one"), "Expected C:\\one, got %s\n", out);
1130 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1132 /* try . prefix */
1133 SetLastError(0xdeadbeef);
1134 lstrcpy(path1, "one\\.two");
1135 lstrcpy(path2, "one\\.three");
1136 lstrcpy(out, "aaa");
1137 count = PathCommonPrefixA(path1, path2, out);
1138 ok(count == 3, "Expected 3, got %i\n", count);
1139 ok(!lstrcmp(path1, "one\\.two"), "Expected one\\.two, got %s\n", path1);
1140 ok(!lstrcmp(path2, "one\\.three"), "Expected one\\.three, got %s\n", path2);
1141 ok(!lstrcmp(out, "one"), "Expected one, got %s\n", out);
1142 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1144 /* try .. prefix */
1145 SetLastError(0xdeadbeef);
1146 lstrcpy(path1, "one\\..two");
1147 lstrcpy(path2, "one\\..three");
1148 lstrcpy(out, "aaa");
1149 count = PathCommonPrefixA(path1, path2, out);
1150 ok(count == 3, "Expected 3, got %i\n", count);
1151 ok(!lstrcmp(path1, "one\\..two"), "Expected one\\..two, got %s\n", path1);
1152 ok(!lstrcmp(path2, "one\\..three"), "Expected one\\..three, got %s\n", path2);
1153 ok(!lstrcmp(out, "one"), "Expected one, got %s\n", out);
1154 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1156 /* try ... prefix */
1157 SetLastError(0xdeadbeef);
1158 lstrcpy(path1, "one\\...two");
1159 lstrcpy(path2, "one\\...three");
1160 lstrcpy(out, "aaa");
1161 count = PathCommonPrefixA(path1, path2, out);
1162 ok(count == 3, "Expected 3, got %i\n", count);
1163 ok(!lstrcmp(path1, "one\\...two"), "Expected one\\...two, got %s\n", path1);
1164 ok(!lstrcmp(path2, "one\\...three"), "Expected one\\...three, got %s\n", path2);
1165 ok(!lstrcmp(out, "one"), "Expected one, got %s\n", out);
1166 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1168 /* try .\ prefix */
1169 SetLastError(0xdeadbeef);
1170 lstrcpy(path1, "one\\.\\two");
1171 lstrcpy(path2, "one\\.\\three");
1172 lstrcpy(out, "aaa");
1173 count = PathCommonPrefixA(path1, path2, out);
1174 ok(count == 5, "Expected 5, got %i\n", count);
1175 ok(!lstrcmp(path1, "one\\.\\two"), "Expected one\\.\\two, got %s\n", path1);
1176 ok(!lstrcmp(path2, "one\\.\\three"), "Expected one\\.\\three, got %s\n", path2);
1177 ok(!lstrcmp(out, "one\\."), "Expected one\\., got %s\n", out);
1178 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1180 /* try ..\ prefix */
1181 SetLastError(0xdeadbeef);
1182 lstrcpy(path1, "one\\..\\two");
1183 lstrcpy(path2, "one\\..\\three");
1184 lstrcpy(out, "aaa");
1185 count = PathCommonPrefixA(path1, path2, out);
1186 ok(count == 6, "Expected 6, got %i\n", count);
1187 ok(!lstrcmp(path1, "one\\..\\two"), "Expected one\\..\\two, got %s\n", path1);
1188 ok(!lstrcmp(path2, "one\\..\\three"), "Expected one\\..\\three, got %s\n", path2);
1189 ok(!lstrcmp(out, "one\\.."), "Expected one\\.., got %s\n", out);
1190 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1192 /* try ...\\ prefix */
1193 SetLastError(0xdeadbeef);
1194 lstrcpy(path1, "one\\...\\two");
1195 lstrcpy(path2, "one\\...\\three");
1196 lstrcpy(out, "aaa");
1197 count = PathCommonPrefixA(path1, path2, out);
1198 ok(count == 7, "Expected 7, got %i\n", count);
1199 ok(!lstrcmp(path1, "one\\...\\two"), "Expected one\\...\\two, got %s\n", path1);
1200 ok(!lstrcmp(path2, "one\\...\\three"), "Expected one\\...\\three, got %s\n", path2);
1201 ok(!lstrcmp(out, "one\\..."), "Expected one\\..., got %s\n", out);
1202 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1204 /* try prefix that is not an msdn labeled prefix type */
1205 SetLastError(0xdeadbeef);
1206 lstrcpy(path1, "same");
1207 lstrcpy(path2, "same");
1208 lstrcpy(out, "aaa");
1209 count = PathCommonPrefixA(path1, path2, out);
1210 ok(count == 4, "Expected 4, got %i\n", count);
1211 ok(!lstrcmp(path1, "same"), "Expected same, got %s\n", path1);
1212 ok(!lstrcmp(path2, "same"), "Expected same, got %s\n", path2);
1213 ok(!lstrcmp(out, "same"), "Expected same, got %s\n", out);
1214 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1216 /* try . after directory */
1217 SetLastError(0xdeadbeef);
1218 lstrcpy(path1, "one\\mid.\\two");
1219 lstrcpy(path2, "one\\mid.\\three");
1220 lstrcpy(out, "aaa");
1221 count = PathCommonPrefixA(path1, path2, out);
1222 ok(count == 8, "Expected 8, got %i\n", count);
1223 ok(!lstrcmp(path1, "one\\mid.\\two"), "Expected one\\mid.\\two, got %s\n", path1);
1224 ok(!lstrcmp(path2, "one\\mid.\\three"), "Expected one\\mid.\\three, got %s\n", path2);
1225 ok(!lstrcmp(out, "one\\mid."), "Expected one\\mid., got %s\n", out);
1226 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1228 /* try . in the middle of a directory */
1229 SetLastError(0xdeadbeef);
1230 lstrcpy(path1, "one\\mid.end\\two");
1231 lstrcpy(path2, "one\\mid.end\\three");
1232 lstrcpy(out, "aaa");
1233 count = PathCommonPrefixA(path1, path2, out);
1234 ok(count == 11, "Expected 11, got %i\n", count);
1235 ok(!lstrcmp(path1, "one\\mid.end\\two"), "Expected one\\mid.end\\two, got %s\n", path1);
1236 ok(!lstrcmp(path2, "one\\mid.end\\three"), "Expected one\\mid.end\\three, got %s\n", path2);
1237 ok(!lstrcmp(out, "one\\mid.end"), "Expected one\\mid.end, got %s\n", out);
1238 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1240 /* try comparing a .. with the expanded path */
1241 SetLastError(0xdeadbeef);
1242 lstrcpy(path1, "one\\..\\two");
1243 lstrcpy(path2, "two");
1244 lstrcpy(out, "aaa");
1245 count = PathCommonPrefixA(path1, path2, out);
1246 ok(count == 0, "Expected 0, got %i\n", count);
1247 ok(!lstrcmp(path1, "one\\..\\two"), "Expected one\\..\\two, got %s\n", path1);
1248 ok(!lstrcmp(path2, "two"), "Expected two, got %s\n", path2);
1249 ok(lstrlen(out) == 0, "Expected 0 length out, got %i\n", lstrlen(out));
1250 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1253 static void test_PathUnquoteSpaces(void)
1255 int i;
1256 for(i = 0; i < sizeof(TEST_PATH_UNQUOTE_SPACES) / sizeof(TEST_PATH_UNQUOTE_SPACES[0]); i++)
1258 char *path = strdupA(TEST_PATH_UNQUOTE_SPACES[i].path);
1259 WCHAR *pathW = GetWideString(TEST_PATH_UNQUOTE_SPACES[i].path);
1260 WCHAR *resultW = GetWideString(TEST_PATH_UNQUOTE_SPACES[i].result);
1262 PathUnquoteSpacesA(path);
1263 ok(!strcmp(path, TEST_PATH_UNQUOTE_SPACES[i].result), "%s (A): got %s expected %s\n",
1264 TEST_PATH_UNQUOTE_SPACES[i].path, path,
1265 TEST_PATH_UNQUOTE_SPACES[i].result);
1267 PathUnquoteSpacesW(pathW);
1268 ok(!lstrcmpW(pathW, resultW), "%s (W): strings differ\n",
1269 TEST_PATH_UNQUOTE_SPACES[i].path);
1270 FreeWideString(pathW);
1271 FreeWideString(resultW);
1272 HeapFree(GetProcessHeap(), 0, path);
1276 /* ################ */
1278 START_TEST(path)
1280 hShlwapi = GetModuleHandleA("shlwapi.dll");
1282 test_PathSearchAndQualify();
1283 test_PathCreateFromUrl();
1284 test_PathIsUrl();
1286 test_PathAddBackslash();
1287 test_PathMakePretty();
1288 test_PathMatchSpec();
1290 /* For whatever reason, PathIsValidCharA and PathAppendA share the same
1291 * ordinal number in some native versions. Check this to prevent a crash.
1293 pPathIsValidCharA = (void*)GetProcAddress(hShlwapi, (LPSTR)455);
1294 if (pPathIsValidCharA && pPathIsValidCharA != (void*)GetProcAddress(hShlwapi, "PathAppendA"))
1296 test_PathIsValidCharA();
1298 pPathIsValidCharW = (void*)GetProcAddress(hShlwapi, (LPSTR)456);
1299 if (pPathIsValidCharW) test_PathIsValidCharW();
1302 pPathCombineW = (void*)GetProcAddress(hShlwapi, "PathCombineW");
1303 if (pPathCombineW)
1304 test_PathCombineW();
1306 test_PathCombineA();
1307 test_PathAppendA();
1308 test_PathCanonicalizeA();
1309 test_PathFindExtensionA();
1310 test_PathBuildRootA();
1311 test_PathCommonPrefixA();
1312 test_PathUnquoteSpaces();