shlwapi: Support NT prefix paths in PathGetDriveNumberW.
[wine.git] / dlls / shlwapi / tests / path.c
blob57fdfdd6c2bd89b5e1b8ab964f0b5d4223538efa
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 <stdarg.h>
21 #include <stdio.h>
23 #include "wine/test.h"
24 #include "windef.h"
25 #include "winbase.h"
26 #include "winreg.h"
27 #include "shlwapi.h"
28 #include "wininet.h"
30 static BOOL (WINAPI *pPathIsValidCharA)(char,DWORD);
31 static BOOL (WINAPI *pPathIsValidCharW)(WCHAR,DWORD);
32 static LPWSTR (WINAPI *pPathCombineW)(LPWSTR, LPCWSTR, LPCWSTR);
33 static HRESULT (WINAPI *pPathCreateFromUrlA)(LPCSTR, LPSTR, LPDWORD, DWORD);
34 static HRESULT (WINAPI *pPathCreateFromUrlW)(LPCWSTR, LPWSTR, LPDWORD, DWORD);
35 static HRESULT (WINAPI *pPathCreateFromUrlAlloc)(LPCWSTR, LPWSTR*, DWORD);
36 static BOOL (WINAPI *pPathAppendA)(LPSTR, LPCSTR);
37 static BOOL (WINAPI *pPathUnExpandEnvStringsA)(LPCSTR, LPSTR, UINT);
38 static BOOL (WINAPI *pPathUnExpandEnvStringsW)(LPCWSTR, LPWSTR, UINT);
39 static BOOL (WINAPI *pPathIsRelativeA)(LPCSTR);
40 static BOOL (WINAPI *pPathIsRelativeW)(LPCWSTR);
42 /* ################ */
44 static const struct {
45 const char *url;
46 const char *path;
47 DWORD ret, todo;
48 } TEST_PATHFROMURL[] = {
49 /* 0 leading slash */
50 {"file:c:/foo/bar", "c:\\foo\\bar", S_OK, 0},
51 {"file:c|/foo/bar", "c:\\foo\\bar", S_OK, 0},
52 {"file:cx|/foo/bar", "cx|\\foo\\bar", S_OK, 0},
53 {"file:c:foo/bar", "c:foo\\bar", S_OK, 0},
54 {"file:c|foo/bar", "c:foo\\bar", S_OK, 0},
55 {"file:c:/foo%20ba%2fr", "c:\\foo ba/r", S_OK, 0},
56 {"file:foo%20ba%2fr", "foo ba/r", S_OK, 0},
57 {"file:foo/bar/", "foo\\bar\\", S_OK, 0},
59 /* 1 leading (back)slash */
60 {"file:/c:/foo/bar", "c:\\foo\\bar", S_OK, 0},
61 {"file:\\c:/foo/bar", "c:\\foo\\bar", S_OK, 0},
62 {"file:/c|/foo/bar", "c:\\foo\\bar", S_OK, 0},
63 {"file:/cx|/foo/bar", "\\cx|\\foo\\bar", S_OK, 0},
64 {"file:/c:foo/bar", "c:foo\\bar", S_OK, 0},
65 {"file:/c|foo/bar", "c:foo\\bar", S_OK, 0},
66 {"file:/c:/foo%20ba%2fr", "c:\\foo ba/r", S_OK, 0},
67 {"file:/foo%20ba%2fr", "\\foo ba/r", S_OK, 0},
68 {"file:/foo/bar/", "\\foo\\bar\\", S_OK, 0},
70 /* 2 leading (back)slashes */
71 {"file://c:/foo/bar", "c:\\foo\\bar", S_OK, 0},
72 {"file://c:/d:/foo/bar", "c:\\d:\\foo\\bar", S_OK, 0},
73 {"file://c|/d|/foo/bar", "c:\\d|\\foo\\bar", S_OK, 0},
74 {"file://cx|/foo/bar", "\\\\cx|\\foo\\bar", S_OK, 0},
75 {"file://c:foo/bar", "c:foo\\bar", S_OK, 0},
76 {"file://c|foo/bar", "c:foo\\bar", S_OK, 0},
77 {"file://c:/foo%20ba%2fr", "c:\\foo%20ba%2fr", S_OK, 0},
78 {"file://c%3a/foo/../bar", "\\\\c:\\foo\\..\\bar", S_OK, 0},
79 {"file://c%7c/foo/../bar", "\\\\c|\\foo\\..\\bar", S_OK, 0},
80 {"file://foo%20ba%2fr", "\\\\foo ba/r", S_OK, 0},
81 {"file://localhost/c:/foo/bar", "c:\\foo\\bar", S_OK, 0},
82 {"file://localhost/c:/foo%20ba%5Cr", "c:\\foo ba\\r", S_OK, 0},
83 {"file://LocalHost/c:/foo/bar", "c:\\foo\\bar", S_OK, 0},
84 {"file:\\\\localhost\\c:\\foo\\bar", "c:\\foo\\bar", S_OK, 0},
85 {"file://incomplete", "\\\\incomplete", S_OK, 0},
87 /* 3 leading (back)slashes (omitting hostname) */
88 {"file:///c:/foo/bar", "c:\\foo\\bar", S_OK, 0},
89 {"File:///c:/foo/bar", "c:\\foo\\bar", S_OK, 0},
90 {"file:///c:/foo%20ba%2fr", "c:\\foo ba/r", S_OK, 0},
91 {"file:///foo%20ba%2fr", "\\foo ba/r", S_OK, 0},
92 {"file:///foo/bar/", "\\foo\\bar\\", S_OK, 0},
93 {"file:///localhost/c:/foo/bar", "\\localhost\\c:\\foo\\bar", S_OK, 0},
95 /* 4 leading (back)slashes */
96 {"file:////c:/foo/bar", "c:\\foo\\bar", S_OK, 0},
97 {"file:////c:/foo%20ba%2fr", "c:\\foo%20ba%2fr", S_OK, 0},
98 {"file:////foo%20ba%2fr", "\\\\foo%20ba%2fr", S_OK, 0},
100 /* 5 and more leading (back)slashes */
101 {"file://///c:/foo/bar", "\\\\c:\\foo\\bar", S_OK, 0},
102 {"file://///c:/foo%20ba%2fr", "\\\\c:\\foo ba/r", S_OK, 0},
103 {"file://///foo%20ba%2fr", "\\\\foo ba/r", S_OK, 0},
104 {"file://////c:/foo/bar", "\\\\c:\\foo\\bar", S_OK, 0},
106 /* Leading (back)slashes cannot be escaped */
107 {"file:%2f%2flocalhost%2fc:/foo/bar", "//localhost/c:\\foo\\bar", S_OK, 0},
108 {"file:%5C%5Clocalhost%5Cc:/foo/bar", "\\\\localhost\\c:\\foo\\bar", S_OK, 0},
110 /* Hostname handling */
111 {"file://l%6fcalhost/c:/foo/bar", "\\\\localhostc:\\foo\\bar", S_OK, 0},
112 {"file://localhost:80/c:/foo/bar", "\\\\localhost:80c:\\foo\\bar", S_OK, 0},
113 {"file://host/c:/foo/bar", "\\\\hostc:\\foo\\bar", S_OK, 0},
114 {"file://host//c:/foo/bar", "\\\\host\\\\c:\\foo\\bar", S_OK, 0},
115 {"file://host/\\c:/foo/bar", "\\\\host\\\\c:\\foo\\bar", S_OK, 0},
116 {"file://host/c:foo/bar", "\\\\hostc:foo\\bar", S_OK, 0},
117 {"file://host/foo/bar", "\\\\host\\foo\\bar", S_OK, 0},
118 {"file:\\\\host\\c:\\foo\\bar", "\\\\hostc:\\foo\\bar", S_OK, 0},
119 {"file:\\\\host\\ca\\foo\\bar", "\\\\host\\ca\\foo\\bar", S_OK, 0},
120 {"file:\\\\host\\c|\\foo\\bar", "\\\\hostc|\\foo\\bar", S_OK, 0},
121 {"file:\\%5Chost\\c:\\foo\\bar", "\\\\host\\c:\\foo\\bar", S_OK, 0},
122 {"file:\\\\host\\cx:\\foo\\bar", "\\\\host\\cx:\\foo\\bar", S_OK, 0},
123 {"file:///host/c:/foo/bar", "\\host\\c:\\foo\\bar", S_OK, 0},
125 /* Not file URLs */
126 {"c:\\foo\\bar", NULL, E_INVALIDARG, 0},
127 {"foo/bar", NULL, E_INVALIDARG, 0},
128 {"http://foo/bar", NULL, E_INVALIDARG, 0},
133 static struct {
134 const char *path;
135 BOOL expect;
136 } TEST_PATH_IS_URL[] = {
137 {"http://foo/bar", TRUE},
138 {"c:\\foo\\bar", FALSE},
139 {"c:/foo/bar", FALSE},
140 {"foo://foo/bar", TRUE},
141 {"foo\\bar", FALSE},
142 {"foo.bar", FALSE},
143 {"bogusscheme:", TRUE},
144 {"http:partial", TRUE},
145 {"www.winehq.org", FALSE},
146 /* More examples that the user might enter as the browser start page */
147 {"winehq.org", FALSE},
148 {"ftp.winehq.org", FALSE},
149 {"http://winehq.org", TRUE},
150 {"http://www.winehq.org", TRUE},
151 {"https://winehq.org", TRUE},
152 {"https://www.winehq.org", TRUE},
153 {"ftp://winehq.org", TRUE},
154 {"ftp://ftp.winehq.org", TRUE},
155 {"file://does_not_exist.txt", TRUE},
156 {"about:blank", TRUE},
157 {"about:home", TRUE},
158 {"about:mozilla", TRUE},
159 /* scheme is case independent */
160 {"HTTP://www.winehq.org", TRUE},
161 /* a space at the start is not allowed */
162 {" http://www.winehq.org", FALSE},
163 {"", FALSE},
164 {NULL, FALSE}
167 static const struct {
168 const char *path;
169 const char *result;
170 } TEST_PATH_UNQUOTE_SPACES[] = {
171 { "abcdef", "abcdef" },
172 { "\"abcdef\"", "abcdef" },
173 { "\"abcdef", "\"abcdef" },
174 { "abcdef\"", "abcdef\"" },
175 { "\"\"abcdef\"\"", "\"abcdef\"" },
176 { "abc\"def", "abc\"def" },
177 { "\"abc\"def", "\"abc\"def" },
178 { "\"abc\"def\"", "abc\"def" },
179 { "\'abcdef\'", "\'abcdef\'" },
180 { "\"\"", "" },
181 { "\"", "" }
184 /* ################ */
186 static LPWSTR GetWideString(const char *src)
188 WCHAR *ret;
190 if (!src)
191 return NULL;
193 ret = HeapAlloc(GetProcessHeap(), 0, (2*INTERNET_MAX_URL_LENGTH) * sizeof(WCHAR));
195 MultiByteToWideChar(CP_ACP, 0, src, -1, ret, INTERNET_MAX_URL_LENGTH);
197 return ret;
200 static void FreeWideString(LPWSTR wszString)
202 HeapFree(GetProcessHeap(), 0, wszString);
205 static LPSTR strdupA(LPCSTR p)
207 LPSTR ret;
208 DWORD len = (strlen(p) + 1);
209 ret = HeapAlloc(GetProcessHeap(), 0, len);
210 memcpy(ret, p, len);
211 return ret;
214 /* ################ */
216 static void test_PathSearchAndQualify(void)
218 WCHAR path1[] = {'c',':','\\','f','o','o',0};
219 WCHAR expect1[] = {'c',':','\\','f','o','o',0};
220 WCHAR path2[] = {'c',':','f','o','o',0};
221 WCHAR c_drive[] = {'c',':',0};
222 WCHAR foo[] = {'f','o','o',0};
223 WCHAR path3[] = {'\\','f','o','o',0};
224 WCHAR winini[] = {'w','i','n','.','i','n','i',0};
225 WCHAR out[MAX_PATH];
226 WCHAR cur_dir[MAX_PATH];
227 WCHAR dot[] = {'.',0};
229 /* c:\foo */
230 ok(PathSearchAndQualifyW(path1, out, MAX_PATH) != 0,
231 "PathSearchAndQualify rets 0\n");
232 ok(!lstrcmpiW(out, expect1), "strings don't match\n");
234 /* c:foo */
235 ok(PathSearchAndQualifyW(path2, out, MAX_PATH) != 0,
236 "PathSearchAndQualify rets 0\n");
237 GetFullPathNameW(c_drive, MAX_PATH, cur_dir, NULL);
238 PathAddBackslashW(cur_dir);
239 lstrcatW(cur_dir, foo);
240 ok(!lstrcmpiW(out, cur_dir), "strings don't match\n");
242 /* foo */
243 ok(PathSearchAndQualifyW(foo, out, MAX_PATH) != 0,
244 "PathSearchAndQualify rets 0\n");
245 GetFullPathNameW(dot, MAX_PATH, cur_dir, NULL);
246 PathAddBackslashW(cur_dir);
247 lstrcatW(cur_dir, foo);
248 ok(!lstrcmpiW(out, cur_dir), "strings don't match\n");
250 /* \foo */
251 ok(PathSearchAndQualifyW(path3, out, MAX_PATH) != 0,
252 "PathSearchAndQualify rets 0\n");
253 GetFullPathNameW(dot, MAX_PATH, cur_dir, NULL);
254 lstrcpyW(cur_dir + 2, path3);
255 ok(!lstrcmpiW(out, cur_dir), "strings don't match\n");
257 /* win.ini */
258 ok(PathSearchAndQualifyW(winini, out, MAX_PATH) != 0,
259 "PathSearchAndQualify rets 0\n");
260 if(!SearchPathW(NULL, winini, NULL, MAX_PATH, cur_dir, NULL))
261 GetFullPathNameW(winini, MAX_PATH, cur_dir, NULL);
262 ok(!lstrcmpiW(out, cur_dir), "strings don't match\n");
266 static void test_PathCreateFromUrl(void)
268 size_t i;
269 char ret_path[INTERNET_MAX_URL_LENGTH];
270 DWORD len, len2, ret;
271 WCHAR ret_pathW[INTERNET_MAX_URL_LENGTH];
272 WCHAR *pathW, *urlW;
274 if (!pPathCreateFromUrlA) {
275 win_skip("PathCreateFromUrlA not found\n");
276 return;
279 /* Won't say how much is needed without a buffer */
280 len = 0xdeca;
281 ret = pPathCreateFromUrlA("file://foo", NULL, &len, 0);
282 ok(ret == E_INVALIDARG, "got 0x%08x expected E_INVALIDARG\n", ret);
283 ok(len == 0xdeca, "got %x expected 0xdeca\n", len);
285 /* Test the decoding itself */
286 for(i = 0; i < sizeof(TEST_PATHFROMURL) / sizeof(TEST_PATHFROMURL[0]); i++) {
287 len = INTERNET_MAX_URL_LENGTH;
288 ret = pPathCreateFromUrlA(TEST_PATHFROMURL[i].url, ret_path, &len, 0);
289 todo_wine_if (TEST_PATHFROMURL[i].todo & 0x1)
290 ok(ret == TEST_PATHFROMURL[i].ret, "ret %08x from url %s\n", ret, TEST_PATHFROMURL[i].url);
291 if(SUCCEEDED(ret) && TEST_PATHFROMURL[i].path) {
292 if(!(TEST_PATHFROMURL[i].todo & 0x2)) {
293 ok(!lstrcmpiA(ret_path, TEST_PATHFROMURL[i].path), "got %s expected %s from url %s\n", ret_path, TEST_PATHFROMURL[i].path, TEST_PATHFROMURL[i].url);
294 ok(len == strlen(ret_path), "ret len %d from url %s\n", len, TEST_PATHFROMURL[i].url);
295 } else todo_wine
296 /* Wrong string, don't bother checking the length */
297 ok(!lstrcmpiA(ret_path, TEST_PATHFROMURL[i].path), "got %s expected %s from url %s\n", ret_path, TEST_PATHFROMURL[i].path, TEST_PATHFROMURL[i].url);
300 if (pPathCreateFromUrlW) {
301 len = INTERNET_MAX_URL_LENGTH;
302 pathW = GetWideString(TEST_PATHFROMURL[i].path);
303 urlW = GetWideString(TEST_PATHFROMURL[i].url);
304 ret = pPathCreateFromUrlW(urlW, ret_pathW, &len, 0);
305 WideCharToMultiByte(CP_ACP, 0, ret_pathW, -1, ret_path, sizeof(ret_path),NULL,NULL);
306 todo_wine_if (TEST_PATHFROMURL[i].todo & 0x1)
307 ok(ret == TEST_PATHFROMURL[i].ret, "ret %08x from url L\"%s\"\n", ret, TEST_PATHFROMURL[i].url);
308 if(SUCCEEDED(ret) && TEST_PATHFROMURL[i].path) {
309 if(!(TEST_PATHFROMURL[i].todo & 0x2)) {
310 ok(!lstrcmpiW(ret_pathW, pathW), "got %s expected %s from url L\"%s\"\n",
311 ret_path, TEST_PATHFROMURL[i].path, TEST_PATHFROMURL[i].url);
312 ok(len == lstrlenW(ret_pathW), "ret len %d from url L\"%s\"\n", len, TEST_PATHFROMURL[i].url);
313 } else todo_wine
314 /* Wrong string, don't bother checking the length */
315 ok(!lstrcmpiW(ret_pathW, pathW), "got %s expected %s from url L\"%s\"\n",
316 ret_path, TEST_PATHFROMURL[i].path, TEST_PATHFROMURL[i].url);
319 if (SUCCEEDED(ret))
321 /* Check what happens if the buffer is too small */
322 len2 = 2;
323 ret = pPathCreateFromUrlW(urlW, ret_pathW, &len2, 0);
324 ok(ret == E_POINTER, "ret %08x, expected E_POINTER from url %s\n", ret, TEST_PATHFROMURL[i].url);
325 todo_wine_if (TEST_PATHFROMURL[i].todo & 0x4)
326 ok(len2 == len + 1, "got len = %d expected %d from url %s\n", len2, len + 1, TEST_PATHFROMURL[i].url);
329 FreeWideString(urlW);
330 FreeWideString(pathW);
334 if (pPathCreateFromUrlAlloc)
336 static const WCHAR fileW[] = {'f','i','l','e',':','/','/','f','o','o',0};
337 static const WCHAR fooW[] = {'\\','\\','f','o','o',0};
339 pathW = NULL;
340 ret = pPathCreateFromUrlAlloc(fileW, &pathW, 0);
341 ok(ret == S_OK, "got 0x%08x expected S_OK\n", ret);
342 ok(lstrcmpiW(pathW, fooW) == 0, "got %s expected %s\n", wine_dbgstr_w(pathW), wine_dbgstr_w(fooW));
343 HeapFree(GetProcessHeap(), 0, pathW);
348 static void test_PathIsUrl(void)
350 size_t i;
351 BOOL ret;
353 for(i = 0; i < sizeof(TEST_PATH_IS_URL)/sizeof(TEST_PATH_IS_URL[0]); i++) {
354 ret = PathIsURLA(TEST_PATH_IS_URL[i].path);
355 ok(ret == TEST_PATH_IS_URL[i].expect,
356 "returned %d from path %s, expected %d\n", ret, TEST_PATH_IS_URL[i].path,
357 TEST_PATH_IS_URL[i].expect);
361 static const DWORD SHELL_charclass[] =
363 0x00000000, 0x00000000, 0x00000000, 0x00000000,
364 0x00000000, 0x00000000, 0x00000000, 0x00000000,
365 0x00000000, 0x00000000, 0x00000000, 0x00000000,
366 0x00000000, 0x00000000, 0x00000000, 0x00000000,
367 0x00000000, 0x00000000, 0x00000000, 0x00000000,
368 0x00000000, 0x00000000, 0x00000000, 0x00000000,
369 0x00000000, 0x00000000, 0x00000000, 0x00000000,
370 0x00000000, 0x00000000, 0x00000000, 0x00000000,
371 0x00000080, 0x00000100, 0x00000200, 0x00000100,
372 0x00000100, 0x00000100, 0x00000100, 0x00000100,
373 0x00000100, 0x00000100, 0x00000002, 0x00000100,
374 0x00000040, 0x00000100, 0x00000004, 0x00000000,
375 0x00000100, 0x00000100, 0x00000100, 0x00000100,
376 0x00000100, 0x00000100, 0x00000100, 0x00000100,
377 0x00000100, 0x00000100, 0x00000010, 0x00000020,
378 0x00000000, 0x00000100, 0x00000000, 0x00000001,
379 0x00000100, 0xffffffff, 0xffffffff, 0xffffffff,
380 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
381 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
382 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
383 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
384 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
385 0xffffffff, 0xffffffff, 0xffffffff, 0x00000100,
386 0x00000008, 0x00000100, 0x00000100, 0x00000100,
387 0x00000100, 0xffffffff, 0xffffffff, 0xffffffff,
388 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
389 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
390 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
391 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
392 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
393 0xffffffff, 0xffffffff, 0xffffffff, 0x00000100,
394 0x00000000, 0x00000100, 0x00000100
397 static void test_PathIsValidCharA(void)
399 BOOL ret;
400 unsigned int c;
402 /* For whatever reason, PathIsValidCharA and PathAppendA share the same
403 * ordinal number in some native versions. Check this to prevent a crash.
405 if (!pPathIsValidCharA || pPathIsValidCharA == (void*)pPathAppendA)
407 win_skip("PathIsValidCharA isn't available\n");
408 return;
411 for (c = 0; c < 0x7f; c++)
413 ret = pPathIsValidCharA( c, ~0U );
414 ok ( ret || !SHELL_charclass[c], "PathIsValidCharA failed: 0x%02x got 0x%08x\n", c, ret );
417 for (c = 0x7f; c <= 0xff; c++)
419 ret = pPathIsValidCharA( c, ~0U );
420 ok ( ret, "PathIsValidCharA failed: 0x%02x got 0x%08x\n", c, ret );
424 static void test_PathIsValidCharW(void)
426 BOOL ret;
427 unsigned int c;
429 if (!pPathIsValidCharW)
431 win_skip("PathIsValidCharW isn't available\n");
432 return;
435 for (c = 0; c < 0x7f; c++)
437 ret = pPathIsValidCharW( c, ~0U );
438 ok ( ret || !SHELL_charclass[c], "PathIsValidCharW failed: 0x%02x got 0x%08x\n", c, ret );
441 for (c = 0x007f; c <= 0xffff; c++)
443 ret = pPathIsValidCharW( c, ~0U );
444 ok ( ret, "PathIsValidCharW failed: 0x%02x got 0x%08x\n", c, ret );
448 static void test_PathMakePretty(void)
450 char buff[MAX_PATH];
452 ok (PathMakePrettyA(NULL) == FALSE, "PathMakePretty: NULL path succeeded\n");
453 buff[0] = '\0';
454 ok (PathMakePrettyA(buff) == TRUE, "PathMakePretty: Empty path failed\n");
456 strcpy(buff, "C:\\A LONG FILE NAME WITH \\SPACES.TXT");
457 ok (PathMakePrettyA(buff) == TRUE, "PathMakePretty: Long UC name failed\n");
458 ok (strcmp(buff, "C:\\a long file name with \\spaces.txt") == 0,
459 "PathMakePretty: Long UC name not changed\n");
461 strcpy(buff, "C:\\A LONG FILE NAME WITH \\MixedCase.TXT");
462 ok (PathMakePrettyA(buff) == FALSE, "PathMakePretty: Long MC name succeeded\n");
463 ok (strcmp(buff, "C:\\A LONG FILE NAME WITH \\MixedCase.TXT") == 0,
464 "PathMakePretty: Failed but modified path\n");
466 strcpy(buff, "TEST");
467 ok (PathMakePrettyA(buff) == TRUE, "PathMakePretty: Short name failed\n");
468 ok (strcmp(buff, "Test") == 0, "PathMakePretty: 1st char lowercased %s\n", buff);
471 static void test_PathMatchSpec(void)
473 static const char file[] = "c:\\foo\\bar\\filename.ext";
474 static const char spec1[] = ".ext";
475 static const char spec2[] = "*.ext";
476 static const char spec3[] = "*.ext ";
477 static const char spec4[] = " *.ext";
478 static const char spec5[] = "* .ext";
479 static const char spec6[] = "*. ext";
480 static const char spec7[] = "* . ext";
481 static const char spec8[] = "*.e?t";
482 static const char spec9[] = "filename.ext";
483 static const char spec10[] = "*bar\\filename.ext";
484 static const char spec11[] = " foo; *.ext";
485 static const char spec12[] = "*.ext;*.bar";
486 static const char spec13[] = "*bar*";
488 ok (PathMatchSpecA(file, spec1) == FALSE, "PathMatchSpec: Spec1 failed\n");
489 ok (PathMatchSpecA(file, spec2) == TRUE, "PathMatchSpec: Spec2 failed\n");
490 ok (PathMatchSpecA(file, spec3) == FALSE, "PathMatchSpec: Spec3 failed\n");
491 ok (PathMatchSpecA(file, spec4) == TRUE, "PathMatchSpec: Spec4 failed\n");
492 todo_wine ok (PathMatchSpecA(file, spec5) == TRUE, "PathMatchSpec: Spec5 failed\n");
493 todo_wine ok (PathMatchSpecA(file, spec6) == TRUE, "PathMatchSpec: Spec6 failed\n");
494 ok (PathMatchSpecA(file, spec7) == FALSE, "PathMatchSpec: Spec7 failed\n");
495 ok (PathMatchSpecA(file, spec8) == TRUE, "PathMatchSpec: Spec8 failed\n");
496 ok (PathMatchSpecA(file, spec9) == FALSE, "PathMatchSpec: Spec9 failed\n");
497 ok (PathMatchSpecA(file, spec10) == TRUE, "PathMatchSpec: Spec10 failed\n");
498 ok (PathMatchSpecA(file, spec11) == TRUE, "PathMatchSpec: Spec11 failed\n");
499 ok (PathMatchSpecA(file, spec12) == TRUE, "PathMatchSpec: Spec12 failed\n");
500 ok (PathMatchSpecA(file, spec13) == TRUE, "PathMatchSpec: Spec13 failed\n");
503 static void test_PathCombineW(void)
505 LPWSTR wszString, wszString2;
506 WCHAR wbuf[MAX_PATH+1], wstr1[MAX_PATH] = {'C',':','\\',0}, wstr2[MAX_PATH];
507 static const WCHAR expout[] = {'C',':','\\','A','A',0};
508 int i;
510 if (!pPathCombineW)
512 win_skip("PathCombineW isn't available\n");
513 return;
516 wszString2 = HeapAlloc(GetProcessHeap(), 0, MAX_PATH * sizeof(WCHAR));
518 /* NULL test */
519 wszString = pPathCombineW(NULL, NULL, NULL);
520 ok (wszString == NULL, "Expected a NULL return\n");
522 /* Some NULL */
523 wszString2[0] = 'a';
524 wszString = pPathCombineW(wszString2, NULL, NULL);
525 ok (wszString == NULL ||
526 broken(wszString[0] == 'a'), /* Win95 and some W2K */
527 "Expected a NULL return\n");
528 ok (wszString2[0] == 0 ||
529 broken(wszString2[0] == 'a'), /* Win95 and some W2K */
530 "Destination string not empty\n");
532 HeapFree(GetProcessHeap(), 0, wszString2);
534 /* overflow test */
535 wstr2[0] = wstr2[1] = wstr2[2] = 'A';
536 for (i=3; i<MAX_PATH/2; i++)
537 wstr1[i] = wstr2[i] = 'A';
538 wstr1[(MAX_PATH/2) - 1] = wstr2[MAX_PATH/2] = 0;
539 memset(wbuf, 0xbf, sizeof(wbuf));
541 wszString = pPathCombineW(wbuf, wstr1, wstr2);
542 ok(wszString == NULL, "Expected a NULL return\n");
543 ok(wbuf[0] == 0 ||
544 broken(wbuf[0] == 0xbfbf), /* Win95 and some W2K */
545 "Buffer contains data\n");
547 /* PathCombineW can be used in place */
548 wstr1[3] = 0;
549 wstr2[2] = 0;
550 ok(PathCombineW(wstr1, wstr1, wstr2) == wstr1, "Expected a wstr1 return\n");
551 ok(StrCmpW(wstr1, expout) == 0, "Unexpected PathCombine output\n");
555 #define LONG_LEN (MAX_PATH * 2)
556 #define HALF_LEN (MAX_PATH / 2 + 1)
558 static void test_PathCombineA(void)
560 LPSTR str;
561 char dest[MAX_PATH];
562 char too_long[LONG_LEN];
563 char one[HALF_LEN], two[HALF_LEN];
565 /* try NULL dest */
566 SetLastError(0xdeadbeef);
567 str = PathCombineA(NULL, "C:\\", "one\\two\\three");
568 ok(str == NULL, "Expected NULL, got %p\n", str);
569 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
571 /* try NULL dest and NULL directory */
572 SetLastError(0xdeadbeef);
573 str = PathCombineA(NULL, NULL, "one\\two\\three");
574 ok(str == NULL, "Expected NULL, got %p\n", str);
575 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
577 /* try all NULL*/
578 SetLastError(0xdeadbeef);
579 str = PathCombineA(NULL, NULL, NULL);
580 ok(str == NULL, "Expected NULL, got %p\n", str);
581 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
583 /* try NULL file part */
584 SetLastError(0xdeadbeef);
585 lstrcpyA(dest, "control");
586 str = PathCombineA(dest, "C:\\", NULL);
587 ok(str == dest, "Expected str == dest, got %p\n", str);
588 ok(!lstrcmpA(str, "C:\\"), "Expected C:\\, got %s\n", str);
589 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
591 /* try empty file part */
592 SetLastError(0xdeadbeef);
593 lstrcpyA(dest, "control");
594 str = PathCombineA(dest, "C:\\", "");
595 ok(str == dest, "Expected str == dest, got %p\n", str);
596 ok(!lstrcmpA(str, "C:\\"), "Expected C:\\, got %s\n", str);
597 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
599 /* try empty directory and file part */
600 SetLastError(0xdeadbeef);
601 lstrcpyA(dest, "control");
602 str = PathCombineA(dest, "", "");
603 ok(str == dest, "Expected str == dest, got %p\n", str);
604 ok(!lstrcmpA(str, "\\") ||
605 broken(!lstrcmpA(str, "control")), /* Win95 and some W2K */
606 "Expected \\, got %s\n", str);
607 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
609 /* try NULL directory */
610 SetLastError(0xdeadbeef);
611 lstrcpyA(dest, "control");
612 str = PathCombineA(dest, NULL, "one\\two\\three");
613 ok(str == dest, "Expected str == dest, got %p\n", str);
614 ok(!lstrcmpA(str, "one\\two\\three"), "Expected one\\two\\three, got %s\n", str);
615 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
617 /* try NULL directory and empty file part */
618 SetLastError(0xdeadbeef);
619 lstrcpyA(dest, "control");
620 str = PathCombineA(dest, NULL, "");
621 ok(str == dest, "Expected str == dest, got %p\n", str);
622 ok(!lstrcmpA(str, "\\") ||
623 broken(!lstrcmpA(str, "one\\two\\three")), /* Win95 and some W2K */
624 "Expected \\, got %s\n", str);
625 ok(GetLastError() == 0xdeadbeef ||
626 broken(GetLastError() == ERROR_INVALID_PARAMETER), /* Win95 */
627 "Expected 0xdeadbeef, got %d\n", GetLastError());
629 /* try NULL directory and file part */
630 SetLastError(0xdeadbeef);
631 lstrcpyA(dest, "control");
632 str = PathCombineA(dest, NULL, NULL);
633 ok(str == NULL ||
634 broken(str != NULL), /* Win95 and some W2K */
635 "Expected str == NULL, got %p\n", str);
636 ok(!dest[0] || broken(!lstrcmpA(dest, "control")), /* Win95 and some W2K */
637 "Expected 0 length, got %i\n", lstrlenA(dest));
638 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
640 /* try directory without backslash */
641 SetLastError(0xdeadbeef);
642 lstrcpyA(dest, "control");
643 str = PathCombineA(dest, "C:", "one\\two\\three");
644 ok(str == dest, "Expected str == dest, got %p\n", str);
645 ok(!lstrcmpA(str, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", str);
646 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
648 /* try directory with backslash */
649 SetLastError(0xdeadbeef);
650 lstrcpyA(dest, "control");
651 str = PathCombineA(dest, "C:\\", "one\\two\\three");
652 ok(str == dest, "Expected str == dest, got %p\n", str);
653 ok(!lstrcmpA(str, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", str);
654 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
656 /* try directory with backslash and file with prepended backslash */
657 SetLastError(0xdeadbeef);
658 lstrcpyA(dest, "control");
659 str = PathCombineA(dest, "C:\\", "\\one\\two\\three");
660 ok(str == dest, "Expected str == dest, got %p\n", str);
661 ok(!lstrcmpA(str, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", str);
662 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
664 /* try previous test, with backslash appended as well */
665 SetLastError(0xdeadbeef);
666 lstrcpyA(dest, "control");
667 str = PathCombineA(dest, "C:\\", "\\one\\two\\three\\");
668 ok(str == dest, "Expected str == dest, got %p\n", str);
669 ok(!lstrcmpA(str, "C:\\one\\two\\three\\"), "Expected C:\\one\\two\\three\\, got %s\n", str);
670 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
672 /* try a relative directory */
673 SetLastError(0xdeadbeef);
674 lstrcpyA(dest, "control");
675 str = PathCombineA(dest, "relative\\dir", "\\one\\two\\three\\");
676 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
677 /* Vista fails which probably makes sense as PathCombineA expects an absolute dir */
678 if (str)
680 ok(str == dest, "Expected str == dest, got %p\n", str);
681 ok(!lstrcmpA(str, "one\\two\\three\\"), "Expected one\\two\\three\\, got %s\n", str);
684 /* try forward slashes */
685 SetLastError(0xdeadbeef);
686 lstrcpyA(dest, "control");
687 str = PathCombineA(dest, "C:\\", "one/two/three\\");
688 ok(str == dest, "Expected str == dest, got %p\n", str);
689 ok(!lstrcmpA(str, "C:\\one/two/three\\"), "Expected one/two/three\\, got %s\n", str);
690 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
692 /* try a really weird directory */
693 SetLastError(0xdeadbeef);
694 lstrcpyA(dest, "control");
695 str = PathCombineA(dest, "C:\\/\\/", "\\one\\two\\three\\");
696 ok(str == dest, "Expected str == dest, got %p\n", str);
697 ok(!lstrcmpA(str, "C:\\one\\two\\three\\"), "Expected C:\\one\\two\\three\\, got %s\n", str);
698 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
700 /* try periods */
701 SetLastError(0xdeadbeef);
702 lstrcpyA(dest, "control");
703 str = PathCombineA(dest, "C:\\", "one\\..\\two\\.\\three");
704 ok(str == dest, "Expected str == dest, got %p\n", str);
705 ok(!lstrcmpA(str, "C:\\two\\three"), "Expected C:\\two\\three, got %s\n", str);
706 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
708 /* try .. as file */
709 /* try forward slashes */
710 SetLastError(0xdeadbeef);
711 lstrcpyA(dest, "control");
712 str = PathCombineA(dest, "C:\\", "..");
713 ok(str == dest, "Expected str == dest, got %p\n", str);
714 ok(!lstrcmpA(str, "C:\\"), "Expected C:\\, got %s\n", str);
715 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
717 memset(too_long, 'a', LONG_LEN);
718 too_long[LONG_LEN - 1] = '\0';
720 /* try a file longer than MAX_PATH */
721 SetLastError(0xdeadbeef);
722 lstrcpyA(dest, "control");
723 str = PathCombineA(dest, "C:\\", too_long);
724 ok(str == NULL, "Expected str == NULL, got %p\n", str);
725 ok(!dest[0] || broken(!lstrcmpA(dest, "control")), /* Win95 and some W2K */
726 "Expected 0 length, got %i\n", lstrlenA(dest));
727 todo_wine ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
729 /* try a directory longer than MAX_PATH */
730 SetLastError(0xdeadbeef);
731 lstrcpyA(dest, "control");
732 str = PathCombineA(dest, too_long, "one\\two\\three");
733 ok(str == NULL, "Expected str == NULL, got %p\n", str);
734 ok(!dest[0] || broken(!lstrcmpA(dest, "control")), /* Win95 and some W2K */
735 "Expected 0 length, got %i\n", lstrlenA(dest));
736 todo_wine ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
738 memset(one, 'b', HALF_LEN);
739 memset(two, 'c', HALF_LEN);
740 one[HALF_LEN - 1] = '\0';
741 two[HALF_LEN - 1] = '\0';
743 /* destination string is longer than MAX_PATH, but not the constituent parts */
744 SetLastError(0xdeadbeef);
745 lstrcpyA(dest, "control");
746 str = PathCombineA(dest, one, two);
747 ok(str == NULL, "Expected str == NULL, got %p\n", str);
748 ok(!dest[0] || broken(!lstrcmpA(dest, "control")), /* Win95 and some W2K */
749 "Expected 0 length, got %i\n", lstrlenA(dest));
750 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
753 static void test_PathAddBackslash(void)
755 LPSTR str;
756 char path[MAX_PATH];
757 char too_long[LONG_LEN];
759 /* try a NULL path */
760 SetLastError(0xdeadbeef);
761 str = PathAddBackslashA(NULL);
762 ok(str == NULL, "Expected str == NULL, got %p\n", str);
763 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
765 /* try an empty path */
766 path[0] = '\0';
767 SetLastError(0xdeadbeef);
768 str = PathAddBackslashA(path);
769 ok(str == (path + lstrlenA(path)), "Expected str to point to end of path, got %p\n", str);
770 ok(!path[0], "Expected empty string, got %i\n", lstrlenA(path));
771 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
773 /* try a relative path */
774 lstrcpyA(path, "one\\two");
775 SetLastError(0xdeadbeef);
776 str = PathAddBackslashA(path);
777 ok(str == (path + lstrlenA(path)), "Expected str to point to end of path, got %p\n", str);
778 ok(!lstrcmpA(path, "one\\two\\"), "Expected one\\two\\, got %s\n", path);
779 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
781 /* try periods */
782 lstrcpyA(path, "one\\..\\two");
783 SetLastError(0xdeadbeef);
784 str = PathAddBackslashA(path);
785 ok(str == (path + lstrlenA(path)), "Expected str to point to end of path, got %p\n", str);
786 ok(!lstrcmpA(path, "one\\..\\two\\"), "Expected one\\..\\two\\, got %s\n", path);
787 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
789 /* try just a space */
790 lstrcpyA(path, " ");
791 SetLastError(0xdeadbeef);
792 str = PathAddBackslashA(path);
793 ok(str == (path + lstrlenA(path)), "Expected str to point to end of path, got %p\n", str);
794 ok(!lstrcmpA(path, " \\"), "Expected \\, got %s\n", path);
795 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
797 /* path already has backslash */
798 lstrcpyA(path, "C:\\one\\");
799 SetLastError(0xdeadbeef);
800 str = PathAddBackslashA(path);
801 ok(str == (path + lstrlenA(path)), "Expected str to point to end of path, got %p\n", str);
802 ok(!lstrcmpA(path, "C:\\one\\"), "Expected C:\\one\\, got %s\n", path);
803 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
805 memset(too_long, 'a', LONG_LEN);
806 too_long[LONG_LEN - 1] = '\0';
808 /* path is longer than MAX_PATH */
809 SetLastError(0xdeadbeef);
810 str = PathAddBackslashA(too_long);
811 ok(str == NULL, "Expected str == NULL, got %p\n", str);
812 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
815 static void test_PathAppendA(void)
817 char path[MAX_PATH];
818 char too_long[LONG_LEN];
819 char half[HALF_LEN];
820 BOOL res;
822 lstrcpyA(path, "C:\\one");
824 /* try NULL pszMore */
825 SetLastError(0xdeadbeef);
826 res = PathAppendA(path, NULL);
827 ok(!res, "Expected failure\n");
828 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
829 ok(!lstrcmpA(path, "C:\\one"), "Expected C:\\one, got %s\n", path);
831 /* try empty pszMore */
832 SetLastError(0xdeadbeef);
833 res = PathAppendA(path, "");
834 ok(res, "Expected success\n");
835 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
836 ok(!lstrcmpA(path, "C:\\one"), "Expected C:\\one, got %s\n", path);
838 /* try NULL pszPath */
839 SetLastError(0xdeadbeef);
840 res = PathAppendA(NULL, "two\\three");
841 ok(!res, "Expected failure\n");
842 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
844 /* try empty pszPath */
845 path[0] = '\0';
846 SetLastError(0xdeadbeef);
847 res = PathAppendA(path, "two\\three");
848 ok(res, "Expected success\n");
849 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
850 ok(!lstrcmpA(path, "two\\three"), "Expected \\two\\three, got %s\n", path);
852 /* try empty pszPath and empty pszMore */
853 path[0] = '\0';
854 SetLastError(0xdeadbeef);
855 res = PathAppendA(path, "");
856 ok(res, "Expected success\n");
857 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
858 ok(!lstrcmpA(path, "\\"), "Expected \\, got %s\n", path);
860 /* try legit params */
861 lstrcpyA(path, "C:\\one");
862 SetLastError(0xdeadbeef);
863 res = PathAppendA(path, "two\\three");
864 ok(res, "Expected success\n");
865 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
866 ok(!lstrcmpA(path, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", path);
868 /* try pszPath with backslash after it */
869 lstrcpyA(path, "C:\\one\\");
870 SetLastError(0xdeadbeef);
871 res = PathAppendA(path, "two\\three");
872 ok(res, "Expected success\n");
873 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
874 ok(!lstrcmpA(path, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", path);
876 /* try pszMore with backslash before it */
877 lstrcpyA(path, "C:\\one");
878 SetLastError(0xdeadbeef);
879 res = PathAppendA(path, "\\two\\three");
880 ok(res, "Expected success\n");
881 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
882 ok(!lstrcmpA(path, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", path);
884 /* try pszMore with backslash after it */
885 lstrcpyA(path, "C:\\one");
886 SetLastError(0xdeadbeef);
887 res = PathAppendA(path, "two\\three\\");
888 ok(res, "Expected success\n");
889 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
890 ok(!lstrcmpA(path, "C:\\one\\two\\three\\"), "Expected C:\\one\\two\\three\\, got %s\n", path);
892 /* try spaces in pszPath */
893 lstrcpyA(path, "C: \\ one ");
894 SetLastError(0xdeadbeef);
895 res = PathAppendA(path, "two\\three");
896 ok(res, "Expected success\n");
897 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
898 ok(!lstrcmpA(path, "C: \\ one \\two\\three"), "Expected C: \\ one \\two\\three, got %s\n", path);
900 /* try spaces in pszMore */
901 lstrcpyA(path, "C:\\one");
902 SetLastError(0xdeadbeef);
903 res = PathAppendA(path, " two \\ three ");
904 ok(res, "Expected success\n");
905 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
906 ok(!lstrcmpA(path, "C:\\one\\ two \\ three "), "Expected 'C:\\one\\ two \\ three ', got %s\n", path);
908 /* pszPath is too long */
909 memset(too_long, 'a', LONG_LEN);
910 too_long[LONG_LEN - 1] = '\0';
911 SetLastError(0xdeadbeef);
912 res = PathAppendA(too_long, "two\\three");
913 ok(!res, "Expected failure\n");
914 todo_wine ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
915 ok(!too_long[0] || broken(lstrlenA(too_long) == (LONG_LEN - 1)), /* Win95 and some W2K */
916 "Expected length of too_long to be zero, got %i\n", lstrlenA(too_long));
918 /* pszMore is too long */
919 lstrcpyA(path, "C:\\one");
920 memset(too_long, 'a', LONG_LEN);
921 too_long[LONG_LEN - 1] = '\0';
922 SetLastError(0xdeadbeef);
923 res = PathAppendA(path, too_long);
924 ok(!res, "Expected failure\n");
925 todo_wine ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
926 ok(!path[0] || broken(!lstrcmpA(path, "C:\\one")), /* Win95 and some W2K */
927 "Expected length of path to be zero, got %i\n", lstrlenA(path));
929 /* both params combined are too long */
930 memset(path, 'a', HALF_LEN);
931 path[HALF_LEN - 1] = '\0';
932 memset(half, 'b', HALF_LEN);
933 half[HALF_LEN - 1] = '\0';
934 SetLastError(0xdeadbeef);
935 res = PathAppendA(path, half);
936 ok(!res, "Expected failure\n");
937 ok(!path[0] || broken(lstrlenA(path) == (HALF_LEN - 1)), /* Win95 and some W2K */
938 "Expected length of path to be zero, got %i\n", lstrlenA(path));
939 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
942 static void test_PathCanonicalizeA(void)
944 char dest[LONG_LEN + MAX_PATH];
945 char too_long[LONG_LEN];
946 BOOL res;
948 /* try a NULL source */
949 lstrcpyA(dest, "test");
950 SetLastError(0xdeadbeef);
951 res = PathCanonicalizeA(dest, NULL);
952 ok(!res, "Expected failure\n");
953 ok(GetLastError() == ERROR_INVALID_PARAMETER,
954 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
955 ok(dest[0] == 0 || !lstrcmpA(dest, "test"),
956 "Expected either an empty string (Vista) or test, got %s\n", dest);
958 /* try an empty source */
959 lstrcpyA(dest, "test");
960 SetLastError(0xdeadbeef);
961 res = PathCanonicalizeA(dest, "");
962 ok(res, "Expected success\n");
963 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
964 ok(!lstrcmpA(dest, "\\") ||
965 broken(!lstrcmpA(dest, "test")), /* Win95 and some W2K */
966 "Expected \\, got %s\n", dest);
968 /* try a NULL dest */
969 SetLastError(0xdeadbeef);
970 res = PathCanonicalizeA(NULL, "C:\\");
971 ok(!res, "Expected failure\n");
972 ok(GetLastError() == ERROR_INVALID_PARAMETER,
973 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
975 /* try empty dest */
976 dest[0] = '\0';
977 SetLastError(0xdeadbeef);
978 res = PathCanonicalizeA(dest, "C:\\");
979 ok(res, "Expected success\n");
980 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
981 ok(!lstrcmpA(dest, "C:\\"), "Expected C:\\, got %s\n", dest);
983 /* try non-empty dest */
984 lstrcpyA(dest, "test");
985 SetLastError(0xdeadbeef);
986 res = PathCanonicalizeA(dest, "C:\\");
987 ok(res, "Expected success\n");
988 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
989 ok(!lstrcmpA(dest, "C:\\"), "Expected C:\\, got %s\n", dest);
991 /* try a space for source */
992 lstrcpyA(dest, "test");
993 SetLastError(0xdeadbeef);
994 res = PathCanonicalizeA(dest, " ");
995 ok(res, "Expected success\n");
996 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
997 ok(!lstrcmpA(dest, " "), "Expected ' ', got %s\n", dest);
999 /* try a relative path */
1000 lstrcpyA(dest, "test");
1001 SetLastError(0xdeadbeef);
1002 res = PathCanonicalizeA(dest, "one\\two");
1003 ok(res, "Expected success\n");
1004 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1005 ok(!lstrcmpA(dest, "one\\two"), "Expected one\\two, got %s\n", dest);
1007 /* try current dir and previous dir */
1008 lstrcpyA(dest, "test");
1009 SetLastError(0xdeadbeef);
1010 res = PathCanonicalizeA(dest, "C:\\one\\.\\..\\two\\three\\..");
1011 ok(res, "Expected success\n");
1012 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1013 ok(!lstrcmpA(dest, "C:\\two"), "Expected C:\\two, got %s\n", dest);
1015 /* try simple forward slashes */
1016 lstrcpyA(dest, "test");
1017 SetLastError(0xdeadbeef);
1018 res = PathCanonicalizeA(dest, "C:\\one/two/three\\four/five\\six");
1019 ok(res, "Expected success\n");
1020 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1021 ok(!lstrcmpA(dest, "C:\\one/two/three\\four/five\\six"),
1022 "Expected C:\\one/two/three\\four/five\\six, got %s\n", dest);
1024 /* try simple forward slashes with same dir */
1025 lstrcpyA(dest, "test");
1026 SetLastError(0xdeadbeef);
1027 res = PathCanonicalizeA(dest, "C:\\one/.\\two");
1028 ok(res, "Expected success\n");
1029 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1030 ok(!lstrcmpA(dest, "C:\\one/.\\two"), "Expected C:\\one/.\\two, got %s\n", dest);
1032 /* try simple forward slashes with change dir */
1033 lstrcpyA(dest, "test");
1034 SetLastError(0xdeadbeef);
1035 res = PathCanonicalizeA(dest, "C:\\one/.\\two\\..");
1036 ok(res, "Expected success\n");
1037 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1038 ok(!lstrcmpA(dest, "C:\\one/.") ||
1039 !lstrcmpA(dest, "C:\\one/"), /* Vista */
1040 "Expected \"C:\\one/.\" or \"C:\\one/\", got \"%s\"\n", dest);
1042 /* try forward slashes with change dirs
1043 * NOTE: if there is a forward slash in between two backslashes,
1044 * everything in between the two backslashes is considered on dir
1046 lstrcpyA(dest, "test");
1047 SetLastError(0xdeadbeef);
1048 res = PathCanonicalizeA(dest, "C:\\one/.\\..\\two/three\\..\\four/.five");
1049 ok(res, "Expected success\n");
1050 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1051 ok(!lstrcmpA(dest, "C:\\four/.five"), "Expected C:\\four/.five, got %s\n", dest);
1053 /* try src is too long */
1054 memset(too_long, 'a', LONG_LEN);
1055 too_long[LONG_LEN - 1] = '\0';
1056 lstrcpyA(dest, "test");
1057 SetLastError(0xdeadbeef);
1058 res = PathCanonicalizeA(dest, too_long);
1059 ok(!res ||
1060 broken(res), /* Win95, some W2K and XP-SP1 */
1061 "Expected failure\n");
1062 todo_wine
1064 ok(GetLastError() == 0xdeadbeef || GetLastError() == ERROR_FILENAME_EXCED_RANGE /* Vista */,
1065 "Expected 0xdeadbeef or ERROR_FILENAME_EXCED_RANGE, got %d\n", GetLastError());
1067 ok(lstrlenA(too_long) == LONG_LEN - 1, "Expected length LONG_LEN - 1, got %i\n", lstrlenA(too_long));
1070 static void test_PathFindExtensionA(void)
1072 LPSTR ext;
1073 char path[MAX_PATH];
1074 char too_long[LONG_LEN];
1076 /* try a NULL path */
1077 SetLastError(0xdeadbeef);
1078 ext = PathFindExtensionA(NULL);
1079 ok(ext == NULL, "Expected NULL, got %p\n", ext);
1080 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1082 /* try an empty path */
1083 path[0] = '\0';
1084 SetLastError(0xdeadbeef);
1085 ext = PathFindExtensionA(path);
1086 ok(ext == path, "Expected ext == path, got %p\n", ext);
1087 ok(!ext[0], "Expected length 0, got %i\n", lstrlenA(ext));
1088 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1090 /* try a path without an extension */
1091 lstrcpyA(path, "file");
1092 SetLastError(0xdeadbeef);
1093 ext = PathFindExtensionA(path);
1094 ok(ext == path + lstrlenA(path), "Expected ext == path, got %p\n", ext);
1095 ok(!ext[0], "Expected length 0, got %i\n", lstrlenA(ext));
1096 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1098 /* try a path with an extension */
1099 lstrcpyA(path, "file.txt");
1100 SetLastError(0xdeadbeef);
1101 ext = PathFindExtensionA(path);
1102 ok(ext == path + lstrlenA("file"),
1103 "Expected ext == path + lstrlenA(\"file\"), got %p\n", ext);
1104 ok(!lstrcmpA(ext, ".txt"), "Expected .txt, got %s\n", ext);
1105 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1107 /* try a path with two extensions */
1108 lstrcpyA(path, "file.txt.doc");
1109 SetLastError(0xdeadbeef);
1110 ext = PathFindExtensionA(path);
1111 ok(ext == path + lstrlenA("file.txt"),
1112 "Expected ext == path + lstrlenA(\"file.txt\"), got %p\n", ext);
1113 ok(!lstrcmpA(ext, ".doc"), "Expected .txt, got %s\n", ext);
1114 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1116 /* try a path longer than MAX_PATH without an extension*/
1117 memset(too_long, 'a', LONG_LEN);
1118 too_long[LONG_LEN - 1] = '\0';
1119 SetLastError(0xdeadbeef);
1120 ext = PathFindExtensionA(too_long);
1121 ok(ext == too_long + LONG_LEN - 1, "Expected ext == too_long + LONG_LEN - 1, got %p\n", ext);
1122 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1124 /* try a path longer than MAX_PATH with an extension*/
1125 memset(too_long, 'a', LONG_LEN);
1126 too_long[LONG_LEN - 1] = '\0';
1127 lstrcpyA(too_long + 300, ".abcde");
1128 too_long[lstrlenA(too_long)] = 'a';
1129 SetLastError(0xdeadbeef);
1130 ext = PathFindExtensionA(too_long);
1131 ok(ext == too_long + 300, "Expected ext == too_long + 300, got %p\n", ext);
1132 ok(lstrlenA(ext) == LONG_LEN - 301, "Expected LONG_LEN - 301, got %i\n", lstrlenA(ext));
1133 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1136 static void test_PathBuildRootA(void)
1138 LPSTR root;
1139 char path[10];
1140 char root_expected[26][4];
1141 char drive;
1142 int j;
1144 /* set up the expected paths */
1145 for (drive = 'A'; drive <= 'Z'; drive++)
1146 sprintf(root_expected[drive - 'A'], "%c:\\", drive);
1148 /* test the expected values */
1149 for (j = 0; j < 26; j++)
1151 SetLastError(0xdeadbeef);
1152 lstrcpyA(path, "aaaaaaaaa");
1153 root = PathBuildRootA(path, j);
1154 ok(root == path, "Expected root == path, got %p\n", root);
1155 ok(!lstrcmpA(root, root_expected[j]), "Expected %s, got %s\n", root_expected[j], root);
1156 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1159 /* test a negative drive number */
1160 SetLastError(0xdeadbeef);
1161 lstrcpyA(path, "aaaaaaaaa");
1162 root = PathBuildRootA(path, -1);
1163 ok(root == path, "Expected root == path, got %p\n", root);
1164 ok(!lstrcmpA(path, "aaaaaaaaa") || !path[0], /* Vista */
1165 "Expected aaaaaaaaa or empty string, got %s\n", path);
1166 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1168 /* test a drive number greater than 25 */
1169 SetLastError(0xdeadbeef);
1170 lstrcpyA(path, "aaaaaaaaa");
1171 root = PathBuildRootA(path, 26);
1172 ok(root == path, "Expected root == path, got %p\n", root);
1173 ok(!lstrcmpA(path, "aaaaaaaaa") || !path[0], /* Vista */
1174 "Expected aaaaaaaaa or empty string, got %s\n", path);
1175 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1177 /* length of path is less than 4 */
1178 SetLastError(0xdeadbeef);
1179 lstrcpyA(path, "aa");
1180 root = PathBuildRootA(path, 0);
1181 ok(root == path, "Expected root == path, got %p\n", root);
1182 ok(!lstrcmpA(path, "A:\\"), "Expected A:\\, got %s\n", path);
1183 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1185 /* path is NULL */
1186 SetLastError(0xdeadbeef);
1187 root = PathBuildRootA(NULL, 0);
1188 ok(root == NULL, "Expected root == NULL, got %p\n", root);
1189 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1192 static void test_PathCommonPrefixA(void)
1194 char path1[MAX_PATH], path2[MAX_PATH];
1195 char out[MAX_PATH];
1196 int count;
1198 /* test NULL path1 */
1199 SetLastError(0xdeadbeef);
1200 lstrcpyA(path2, "C:\\");
1201 lstrcpyA(out, "aaa");
1202 count = PathCommonPrefixA(NULL, path2, out);
1203 ok(count == 0, "Expected 0, got %i\n", count);
1204 todo_wine
1206 ok(!lstrcmpA(out, "aaa"), "Expected aaa, got %s\n", out);
1208 ok(!lstrcmpA(path2, "C:\\"), "Expected C:\\, got %s\n", path2);
1209 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1211 /* test NULL path2 */
1212 SetLastError(0xdeadbeef);
1213 lstrcpyA(path1, "C:\\");
1214 lstrcpyA(out, "aaa");
1215 count = PathCommonPrefixA(path1, NULL, out);
1216 ok(count == 0, "Expected 0, got %i\n", count);
1217 todo_wine
1219 ok(!lstrcmpA(out, "aaa"), "Expected aaa, got %s\n", out);
1221 ok(!lstrcmpA(path1, "C:\\"), "Expected C:\\, got %s\n", path1);
1222 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1224 /* test empty path1 */
1225 SetLastError(0xdeadbeef);
1226 path1[0] = '\0';
1227 lstrcpyA(path2, "C:\\");
1228 lstrcpyA(out, "aaa");
1229 count = PathCommonPrefixA(path1, path2, out);
1230 ok(count == 0, "Expected 0, got %i\n", count);
1231 ok(!out[0], "Expected 0 length out, got %i\n", lstrlenA(out));
1232 ok(!path1[0], "Expected 0 length path1, got %i\n", lstrlenA(path1));
1233 ok(!lstrcmpA(path2, "C:\\"), "Expected C:\\, got %s\n", path2);
1234 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1236 /* test empty path1 */
1237 SetLastError(0xdeadbeef);
1238 path2[0] = '\0';
1239 lstrcpyA(path1, "C:\\");
1240 lstrcpyA(out, "aaa");
1241 count = PathCommonPrefixA(path1, path2, out);
1242 ok(count == 0, "Expected 0, got %i\n", count);
1243 ok(!out[0], "Expected 0 length out, got %i\n", lstrlenA(out));
1244 ok(!path2[0], "Expected 0 length path2, got %i\n", lstrlenA(path2));
1245 ok(!lstrcmpA(path1, "C:\\"), "Expected C:\\, got %s\n", path1);
1246 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1248 /* paths are legit, out is NULL */
1249 SetLastError(0xdeadbeef);
1250 lstrcpyA(path1, "C:\\");
1251 lstrcpyA(path2, "C:\\");
1252 count = PathCommonPrefixA(path1, path2, NULL);
1253 ok(count == 3, "Expected 3, got %i\n", count);
1254 ok(!lstrcmpA(path1, "C:\\"), "Expected C:\\, got %s\n", path1);
1255 ok(!lstrcmpA(path2, "C:\\"), "Expected C:\\, got %s\n", path2);
1256 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1258 /* all parameters legit */
1259 SetLastError(0xdeadbeef);
1260 lstrcpyA(path1, "C:\\");
1261 lstrcpyA(path2, "C:\\");
1262 lstrcpyA(out, "aaa");
1263 count = PathCommonPrefixA(path1, path2, out);
1264 ok(count == 3, "Expected 3, got %i\n", count);
1265 ok(!lstrcmpA(path1, "C:\\"), "Expected C:\\, got %s\n", path1);
1266 ok(!lstrcmpA(path2, "C:\\"), "Expected C:\\, got %s\n", path2);
1267 ok(!lstrcmpA(out, "C:\\"), "Expected C:\\, got %s\n", out);
1268 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1270 /* path1 and path2 not the same, but common prefix */
1271 SetLastError(0xdeadbeef);
1272 lstrcpyA(path1, "C:\\one\\two");
1273 lstrcpyA(path2, "C:\\one\\three");
1274 lstrcpyA(out, "aaa");
1275 count = PathCommonPrefixA(path1, path2, out);
1276 ok(count == 6, "Expected 6, got %i\n", count);
1277 ok(!lstrcmpA(path1, "C:\\one\\two"), "Expected C:\\one\\two, got %s\n", path1);
1278 ok(!lstrcmpA(path2, "C:\\one\\three"), "Expected C:\\one\\three, got %s\n", path2);
1279 ok(!lstrcmpA(out, "C:\\one"), "Expected C:\\one, got %s\n", out);
1280 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1282 /* try . prefix */
1283 SetLastError(0xdeadbeef);
1284 lstrcpyA(path1, "one\\.two");
1285 lstrcpyA(path2, "one\\.three");
1286 lstrcpyA(out, "aaa");
1287 count = PathCommonPrefixA(path1, path2, out);
1288 ok(count == 3, "Expected 3, got %i\n", count);
1289 ok(!lstrcmpA(path1, "one\\.two"), "Expected one\\.two, got %s\n", path1);
1290 ok(!lstrcmpA(path2, "one\\.three"), "Expected one\\.three, got %s\n", path2);
1291 ok(!lstrcmpA(out, "one"), "Expected one, got %s\n", out);
1292 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1294 /* try .. prefix */
1295 SetLastError(0xdeadbeef);
1296 lstrcpyA(path1, "one\\..two");
1297 lstrcpyA(path2, "one\\..three");
1298 lstrcpyA(out, "aaa");
1299 count = PathCommonPrefixA(path1, path2, out);
1300 ok(count == 3, "Expected 3, got %i\n", count);
1301 ok(!lstrcmpA(path1, "one\\..two"), "Expected one\\..two, got %s\n", path1);
1302 ok(!lstrcmpA(path2, "one\\..three"), "Expected one\\..three, got %s\n", path2);
1303 ok(!lstrcmpA(out, "one"), "Expected one, got %s\n", out);
1304 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1306 /* try ... prefix */
1307 SetLastError(0xdeadbeef);
1308 lstrcpyA(path1, "one\\...two");
1309 lstrcpyA(path2, "one\\...three");
1310 lstrcpyA(out, "aaa");
1311 count = PathCommonPrefixA(path1, path2, out);
1312 ok(count == 3, "Expected 3, got %i\n", count);
1313 ok(!lstrcmpA(path1, "one\\...two"), "Expected one\\...two, got %s\n", path1);
1314 ok(!lstrcmpA(path2, "one\\...three"), "Expected one\\...three, got %s\n", path2);
1315 ok(!lstrcmpA(out, "one"), "Expected one, got %s\n", out);
1316 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1318 /* try .\ prefix */
1319 SetLastError(0xdeadbeef);
1320 lstrcpyA(path1, "one\\.\\two");
1321 lstrcpyA(path2, "one\\.\\three");
1322 lstrcpyA(out, "aaa");
1323 count = PathCommonPrefixA(path1, path2, out);
1324 ok(count == 5, "Expected 5, got %i\n", count);
1325 ok(!lstrcmpA(path1, "one\\.\\two"), "Expected one\\.\\two, got %s\n", path1);
1326 ok(!lstrcmpA(path2, "one\\.\\three"), "Expected one\\.\\three, got %s\n", path2);
1327 ok(!lstrcmpA(out, "one\\."), "Expected one\\., got %s\n", out);
1328 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1330 /* try ..\ prefix */
1331 SetLastError(0xdeadbeef);
1332 lstrcpyA(path1, "one\\..\\two");
1333 lstrcpyA(path2, "one\\..\\three");
1334 lstrcpyA(out, "aaa");
1335 count = PathCommonPrefixA(path1, path2, out);
1336 ok(count == 6, "Expected 6, got %i\n", count);
1337 ok(!lstrcmpA(path1, "one\\..\\two"), "Expected one\\..\\two, got %s\n", path1);
1338 ok(!lstrcmpA(path2, "one\\..\\three"), "Expected one\\..\\three, got %s\n", path2);
1339 ok(!lstrcmpA(out, "one\\.."), "Expected one\\.., got %s\n", out);
1340 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1342 /* try ...\\ prefix */
1343 SetLastError(0xdeadbeef);
1344 lstrcpyA(path1, "one\\...\\two");
1345 lstrcpyA(path2, "one\\...\\three");
1346 lstrcpyA(out, "aaa");
1347 count = PathCommonPrefixA(path1, path2, out);
1348 ok(count == 7, "Expected 7, got %i\n", count);
1349 ok(!lstrcmpA(path1, "one\\...\\two"), "Expected one\\...\\two, got %s\n", path1);
1350 ok(!lstrcmpA(path2, "one\\...\\three"), "Expected one\\...\\three, got %s\n", path2);
1351 ok(!lstrcmpA(out, "one\\..."), "Expected one\\..., got %s\n", out);
1352 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1354 /* try prefix that is not an msdn labeled prefix type */
1355 SetLastError(0xdeadbeef);
1356 lstrcpyA(path1, "same");
1357 lstrcpyA(path2, "same");
1358 lstrcpyA(out, "aaa");
1359 count = PathCommonPrefixA(path1, path2, out);
1360 ok(count == 4, "Expected 4, got %i\n", count);
1361 ok(!lstrcmpA(path1, "same"), "Expected same, got %s\n", path1);
1362 ok(!lstrcmpA(path2, "same"), "Expected same, got %s\n", path2);
1363 ok(!lstrcmpA(out, "same"), "Expected same, got %s\n", out);
1364 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1366 /* try . after directory */
1367 SetLastError(0xdeadbeef);
1368 lstrcpyA(path1, "one\\mid.\\two");
1369 lstrcpyA(path2, "one\\mid.\\three");
1370 lstrcpyA(out, "aaa");
1371 count = PathCommonPrefixA(path1, path2, out);
1372 ok(count == 8, "Expected 8, got %i\n", count);
1373 ok(!lstrcmpA(path1, "one\\mid.\\two"), "Expected one\\mid.\\two, got %s\n", path1);
1374 ok(!lstrcmpA(path2, "one\\mid.\\three"), "Expected one\\mid.\\three, got %s\n", path2);
1375 ok(!lstrcmpA(out, "one\\mid."), "Expected one\\mid., got %s\n", out);
1376 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1378 /* try . in the middle of a directory */
1379 SetLastError(0xdeadbeef);
1380 lstrcpyA(path1, "one\\mid.end\\two");
1381 lstrcpyA(path2, "one\\mid.end\\three");
1382 lstrcpyA(out, "aaa");
1383 count = PathCommonPrefixA(path1, path2, out);
1384 ok(count == 11, "Expected 11, got %i\n", count);
1385 ok(!lstrcmpA(path1, "one\\mid.end\\two"), "Expected one\\mid.end\\two, got %s\n", path1);
1386 ok(!lstrcmpA(path2, "one\\mid.end\\three"), "Expected one\\mid.end\\three, got %s\n", path2);
1387 ok(!lstrcmpA(out, "one\\mid.end"), "Expected one\\mid.end, got %s\n", out);
1388 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1390 /* try comparing a .. with the expanded path */
1391 SetLastError(0xdeadbeef);
1392 lstrcpyA(path1, "one\\..\\two");
1393 lstrcpyA(path2, "two");
1394 lstrcpyA(out, "aaa");
1395 count = PathCommonPrefixA(path1, path2, out);
1396 ok(count == 0, "Expected 0, got %i\n", count);
1397 ok(!lstrcmpA(path1, "one\\..\\two"), "Expected one\\..\\two, got %s\n", path1);
1398 ok(!lstrcmpA(path2, "two"), "Expected two, got %s\n", path2);
1399 ok(!out[0], "Expected 0 length out, got %i\n", lstrlenA(out));
1400 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1403 static void test_PathUnquoteSpaces(void)
1405 int i;
1406 for(i = 0; i < sizeof(TEST_PATH_UNQUOTE_SPACES) / sizeof(TEST_PATH_UNQUOTE_SPACES[0]); i++)
1408 char *path = strdupA(TEST_PATH_UNQUOTE_SPACES[i].path);
1409 WCHAR *pathW = GetWideString(TEST_PATH_UNQUOTE_SPACES[i].path);
1410 WCHAR *resultW = GetWideString(TEST_PATH_UNQUOTE_SPACES[i].result);
1412 PathUnquoteSpacesA(path);
1413 ok(!strcmp(path, TEST_PATH_UNQUOTE_SPACES[i].result), "%s (A): got %s expected %s\n",
1414 TEST_PATH_UNQUOTE_SPACES[i].path, path,
1415 TEST_PATH_UNQUOTE_SPACES[i].result);
1417 PathUnquoteSpacesW(pathW);
1418 ok(!lstrcmpW(pathW, resultW), "%s (W): strings differ\n",
1419 TEST_PATH_UNQUOTE_SPACES[i].path);
1420 FreeWideString(pathW);
1421 FreeWideString(resultW);
1422 HeapFree(GetProcessHeap(), 0, path);
1426 static void test_PathGetDriveNumber(void)
1428 static const CHAR test1A[] = "a:\\test.file";
1429 static const CHAR test2A[] = "file:////b:\\test.file";
1430 static const CHAR test3A[] = "file:///c:\\test.file";
1431 static const CHAR test4A[] = "file:\\\\c:\\test.file";
1432 static const CHAR test5A[] = "\\\\?\\C:\\dir\\file.txt";
1433 static const WCHAR test1W[] =
1434 {'a',':','\\',0};
1435 static const WCHAR test5W[] =
1436 {'\\','\\','?','\\','C',':','\\','d','i','r','\\','f','i','l','e',0};
1437 int ret;
1439 SetLastError(0xdeadbeef);
1440 ret = PathGetDriveNumberA(NULL);
1441 ok(ret == -1, "got %d\n", ret);
1442 ok(GetLastError() == 0xdeadbeef, "got %d\n", GetLastError());
1444 ret = PathGetDriveNumberA(test1A);
1445 ok(ret == 0, "got %d\n", ret);
1446 ret = PathGetDriveNumberW(test1W);
1447 ok(ret == 0, "got %d\n", ret);
1448 ret = PathGetDriveNumberA(test2A);
1449 ok(ret == -1, "got %d\n", ret);
1450 ret = PathGetDriveNumberA(test3A);
1451 ok(ret == -1, "got %d\n", ret);
1452 ret = PathGetDriveNumberA(test4A);
1453 ok(ret == -1, "got %d\n", ret);
1455 ret = PathGetDriveNumberA(test5A);
1456 ok(ret == -1, "got %d\n", ret);
1457 ret = PathGetDriveNumberW(test5W);
1458 ok(ret == 2 || broken(ret == -1) /* winxp */, "got = %d\n", ret);
1461 static void test_PathUnExpandEnvStrings(void)
1463 static const WCHAR sysrootW[] = {'%','S','y','s','t','e','m','R','o','o','t','%',0};
1464 static const WCHAR sysdriveW[] = {'%','S','y','s','t','e','m','D','r','i','v','e','%',0};
1465 static const WCHAR nonpathW[] = {'p','a','t','h',0};
1466 static const char sysrootA[] = "%SystemRoot%";
1467 static const char sysdriveA[] = "%SystemDrive%";
1468 WCHAR pathW[MAX_PATH], buffW[MAX_PATH], sysdrvW[3];
1469 char path[MAX_PATH], buff[MAX_PATH], sysdrvA[3], envvarA[10];
1470 BOOL ret;
1471 UINT len;
1473 if (!pPathUnExpandEnvStringsA || !pPathUnExpandEnvStringsW)
1475 win_skip("PathUnExpandEnvStrings not available\n");
1476 return;
1479 /* something that can't be represented with env var */
1480 strcpy(path, "somepath_name");
1481 strcpy(buff, "xx");
1482 SetLastError(0xdeadbeef);
1483 ret = pPathUnExpandEnvStringsA(path, buff, sizeof(buff));
1484 ok(!ret && GetLastError() == 0xdeadbeef, "got %d, error %d\n", ret, GetLastError());
1485 ok(buff[0] == 'x', "wrong return string %s\n", buff);
1487 len = GetSystemDirectoryA(path, MAX_PATH);
1488 ok(len > 0, "failed to get sysdir\n");
1490 sysdrvA[0] = path[0];
1491 strcpy(&sysdrvA[1], ":");
1493 /* buffer size is not enough */
1494 strcpy(buff, "xx");
1495 SetLastError(0xdeadbeef);
1496 ret = pPathUnExpandEnvStringsA(path, buff, 5);
1497 ok(!ret && GetLastError() == 0xdeadbeef, "got %d\n", ret);
1498 ok(buff[0] == 'x', "wrong return string %s\n", buff);
1500 /* buffer size is enough to hold variable name only */
1501 strcpy(buff, "xx");
1502 SetLastError(0xdeadbeef);
1503 ret = pPathUnExpandEnvStringsA(path, buff, sizeof(sysrootA));
1504 ok(!ret && GetLastError() == 0xdeadbeef, "got %d, error %d\n", ret, GetLastError());
1505 ok(buff[0] == 'x', "wrong return string %s\n", buff);
1507 /* enough size */
1508 buff[0] = 0;
1509 ret = pPathUnExpandEnvStringsA(path, buff, sizeof(buff));
1510 ok(ret, "got %d\n", ret);
1511 ok(!strncmp(buff, sysrootA, sizeof(sysrootA)-1), "wrong return string %s\n", buff);
1513 /* expanded value occurs multiple times */
1514 /* for drive C: it unexpands it like 'C:C:' -> '%SystemDrive%C:' */
1515 buff[0] = 0;
1516 strcpy(path, sysdrvA);
1517 strcat(path, sysdrvA);
1518 ret = pPathUnExpandEnvStringsA(path, buff, sizeof(buff));
1519 ok(ret, "got %d\n", ret);
1520 /* expected string */
1521 strcpy(path, sysdriveA);
1522 strcat(path, sysdrvA);
1523 ok(!strcmp(buff, path), "wrong unexpanded string %s, expected %s\n", buff, path);
1525 /* now with altered variable */
1526 ret = GetEnvironmentVariableA("SystemDrive", envvarA, sizeof(envvarA));
1527 ok(ret, "got %d\n", ret);
1529 ret = SetEnvironmentVariableA("SystemDrive", "WW");
1530 ok(ret, "got %d\n", ret);
1532 /* variables are not cached */
1533 strcpy(path, sysdrvA);
1534 strcat(path, sysdrvA);
1535 SetLastError(0xdeadbeef);
1536 ret = pPathUnExpandEnvStringsA(path, buff, sizeof(buff));
1537 ok(!ret && GetLastError() == 0xdeadbeef, "got %d, error %d\n", ret, GetLastError());
1539 ret = SetEnvironmentVariableA("SystemDrive", envvarA);
1540 ok(ret, "got %d\n", ret);
1542 /* PathUnExpandEnvStringsW */
1544 /* something that can't be represented with env var */
1545 lstrcpyW(pathW, nonpathW);
1546 buffW[0] = 'x'; buffW[1] = 0;
1547 SetLastError(0xdeadbeef);
1548 ret = pPathUnExpandEnvStringsW(pathW, buffW, sizeof(buffW)/sizeof(WCHAR));
1549 ok(!ret && GetLastError() == 0xdeadbeef, "got %d, error %d\n", ret, GetLastError());
1550 ok(buffW[0] == 'x', "wrong return string %s\n", wine_dbgstr_w(buffW));
1552 len = GetSystemDirectoryW(pathW, MAX_PATH);
1553 ok(len > 0, "failed to get sysdir\n");
1555 sysdrvW[0] = pathW[0];
1556 sysdrvW[1] = ':';
1557 sysdrvW[2] = 0;
1559 /* buffer size is not enough */
1560 buffW[0] = 'x'; buffW[1] = 0;
1561 SetLastError(0xdeadbeef);
1562 ret = pPathUnExpandEnvStringsW(pathW, buffW, 5);
1563 ok(!ret && GetLastError() == 0xdeadbeef, "got %d, error %d\n", ret, GetLastError());
1564 ok(buffW[0] == 'x', "wrong return string %s\n", wine_dbgstr_w(buffW));
1566 /* buffer size is enough to hold variable name only */
1567 buffW[0] = 'x'; buffW[1] = 0;
1568 SetLastError(0xdeadbeef);
1569 ret = pPathUnExpandEnvStringsW(pathW, buffW, sizeof(sysrootW)/sizeof(WCHAR));
1570 ok(!ret && GetLastError() == 0xdeadbeef, "got %d, error %d\n", ret, GetLastError());
1571 ok(buffW[0] == 'x', "wrong return string %s\n", wine_dbgstr_w(buffW));
1573 /* enough size */
1574 buffW[0] = 0;
1575 ret = pPathUnExpandEnvStringsW(pathW, buffW, sizeof(buffW)/sizeof(WCHAR));
1576 ok(ret, "got %d\n", ret);
1577 ok(!memcmp(buffW, sysrootW, sizeof(sysrootW) - sizeof(WCHAR)), "wrong return string %s\n", wine_dbgstr_w(buffW));
1579 /* expanded value occurs multiple times */
1580 /* for drive C: it unexpands it like 'C:C:' -> '%SystemDrive%C:' */
1581 buffW[0] = 0;
1582 lstrcpyW(pathW, sysdrvW);
1583 lstrcatW(pathW, sysdrvW);
1584 ret = pPathUnExpandEnvStringsW(pathW, buffW, sizeof(buff)/sizeof(WCHAR));
1585 ok(ret, "got %d\n", ret);
1586 /* expected string */
1587 lstrcpyW(pathW, sysdriveW);
1588 lstrcatW(pathW, sysdrvW);
1589 ok(!lstrcmpW(buffW, pathW), "wrong unexpanded string %s, expected %s\n", wine_dbgstr_w(buffW), wine_dbgstr_w(pathW));
1592 static const struct {
1593 const char *path;
1594 BOOL expect;
1595 } test_path_is_relative[] = {
1596 {NULL, TRUE},
1597 {"\0", TRUE},
1598 {"test.txt", TRUE},
1599 {"\\\\folder\\test.txt", FALSE},
1600 {"file://folder/test.txt", TRUE},
1601 {"C:\\test.txt", FALSE},
1602 {"file:///C:/test.txt", TRUE}
1605 static void test_PathIsRelativeA(void)
1607 BOOL ret;
1608 int i, num;
1610 if (!pPathIsRelativeA) {
1611 win_skip("PathIsRelativeA not available\n");
1612 return;
1615 num = sizeof(test_path_is_relative) / sizeof(test_path_is_relative[0]);
1616 for (i = 0; i < num; i++) {
1617 ret = pPathIsRelativeA(test_path_is_relative[i].path);
1618 ok(ret == test_path_is_relative[i].expect,
1619 "PathIsRelativeA(\"%s\") expects %d, got %d.\n",
1620 test_path_is_relative[i].path, test_path_is_relative[i].expect, ret);
1624 static void test_PathIsRelativeW(void)
1626 BOOL ret;
1627 int i, num;
1628 LPWSTR path;
1630 if (!pPathIsRelativeW) {
1631 win_skip("PathIsRelativeW not available\n");
1632 return;
1635 num = sizeof(test_path_is_relative) / sizeof(test_path_is_relative[0]);
1636 for (i = 0; i < num; i++) {
1637 path = GetWideString(test_path_is_relative[i].path);
1639 ret = pPathIsRelativeW(path);
1640 ok(ret == test_path_is_relative[i].expect,
1641 "PathIsRelativeW(\"%s\") expects %d, got %d.\n",
1642 test_path_is_relative[i].path, test_path_is_relative[i].expect, ret);
1644 FreeWideString(path);
1648 static void test_PathStripPathA(void)
1650 const char const_path[] = "test";
1651 char path[] = "short//path\\file.txt";
1653 PathStripPathA(path);
1654 ok(!strcmp(path, "file.txt"), "path = %s\n", path);
1656 /* following test should not crash */
1657 /* LavView 2013 depends on that behaviour */
1658 PathStripPathA((char*)const_path);
1661 START_TEST(path)
1663 HMODULE hShlwapi = GetModuleHandleA("shlwapi.dll");
1665 /* SHCreateStreamOnFileEx was introduced in shlwapi v6.0 */
1666 if(!GetProcAddress(hShlwapi, "SHCreateStreamOnFileEx")){
1667 win_skip("Too old shlwapi version\n");
1668 return;
1671 pPathCreateFromUrlA = (void*)GetProcAddress(hShlwapi, "PathCreateFromUrlA");
1672 pPathCreateFromUrlW = (void*)GetProcAddress(hShlwapi, "PathCreateFromUrlW");
1673 pPathCreateFromUrlAlloc = (void*)GetProcAddress(hShlwapi, "PathCreateFromUrlAlloc");
1674 pPathCombineW = (void*)GetProcAddress(hShlwapi, "PathCombineW");
1675 pPathIsValidCharA = (void*)GetProcAddress(hShlwapi, (LPSTR)455);
1676 pPathIsValidCharW = (void*)GetProcAddress(hShlwapi, (LPSTR)456);
1677 pPathAppendA = (void*)GetProcAddress(hShlwapi, "PathAppendA");
1678 pPathUnExpandEnvStringsA = (void*)GetProcAddress(hShlwapi, "PathUnExpandEnvStringsA");
1679 pPathUnExpandEnvStringsW = (void*)GetProcAddress(hShlwapi, "PathUnExpandEnvStringsW");
1680 pPathIsRelativeA = (void*)GetProcAddress(hShlwapi, "PathIsRelativeA");
1681 pPathIsRelativeW = (void*)GetProcAddress(hShlwapi, "PathIsRelativeW");
1683 test_PathSearchAndQualify();
1684 test_PathCreateFromUrl();
1685 test_PathIsUrl();
1687 test_PathAddBackslash();
1688 test_PathMakePretty();
1689 test_PathMatchSpec();
1691 test_PathIsValidCharA();
1692 test_PathIsValidCharW();
1694 test_PathCombineW();
1695 test_PathCombineA();
1696 test_PathAppendA();
1697 test_PathCanonicalizeA();
1698 test_PathFindExtensionA();
1699 test_PathBuildRootA();
1700 test_PathCommonPrefixA();
1701 test_PathUnquoteSpaces();
1702 test_PathGetDriveNumber();
1703 test_PathUnExpandEnvStrings();
1704 test_PathIsRelativeA();
1705 test_PathIsRelativeW();
1706 test_PathStripPathA();