8ef71c98ec46ea0bb51f386f3a919b0dfb6bb6ff
[reactos.git] / rostests / winetests / shlwapi / path.c
1 /* Unit test suite for Path functions
2 *
3 * Copyright 2002 Matthew Mastracci
4 *
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.
9 *
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.
14 *
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
18 */
19
20 #define WIN32_NO_STATUS
21 #define _INC_WINDOWS
22 #define COM_NO_WINDOWS_H
23
24 //#include <stdarg.h>
25 #include <stdio.h>
26
27 #include <wine/test.h>
28 //#include "windef.h"
29 //#include "winbase.h"
30 #include <winreg.h>
31 #include <winnls.h>
32 #include <shlwapi.h>
33 #include <wininet.h>
34
35 static HRESULT (WINAPI *pPathIsValidCharA)(char,DWORD);
36 static HRESULT (WINAPI *pPathIsValidCharW)(WCHAR,DWORD);
37 static LPWSTR (WINAPI *pPathCombineW)(LPWSTR, LPCWSTR, LPCWSTR);
38 static HRESULT (WINAPI *pPathCreateFromUrlA)(LPCSTR, LPSTR, LPDWORD, DWORD);
39 static HRESULT (WINAPI *pPathCreateFromUrlW)(LPCWSTR, LPWSTR, LPDWORD, DWORD);
40 static HRESULT (WINAPI *pPathCreateFromUrlAlloc)(LPCWSTR, LPWSTR*, DWORD);
41 static BOOL (WINAPI *pPathAppendA)(LPSTR, LPCSTR);
42
43 /* ################ */
44
45 static const struct {
46 const char *url;
47 const char *path;
48 DWORD ret, todo;
49 } TEST_PATHFROMURL[] = {
50 /* 0 leading slash */
51 {"file:c:/foo/bar", "c:\\foo\\bar", S_OK, 0},
52 {"file:c|/foo/bar", "c:\\foo\\bar", S_OK, 0},
53 {"file:cx|/foo/bar", "cx|\\foo\\bar", S_OK, 0},
54 {"file:c:foo/bar", "c:foo\\bar", S_OK, 0},
55 {"file:c|foo/bar", "c:foo\\bar", S_OK, 0},
56 {"file:c:/foo%20ba%2fr", "c:\\foo ba/r", S_OK, 0},
57 {"file:foo%20ba%2fr", "foo ba/r", S_OK, 0},
58 {"file:foo/bar/", "foo\\bar\\", S_OK, 0},
59
60 /* 1 leading (back)slash */
61 {"file:/c:/foo/bar", "c:\\foo\\bar", S_OK, 0},
62 {"file:\\c:/foo/bar", "c:\\foo\\bar", S_OK, 0},
63 {"file:/c|/foo/bar", "c:\\foo\\bar", S_OK, 0},
64 {"file:/cx|/foo/bar", "\\cx|\\foo\\bar", S_OK, 0},
65 {"file:/c:foo/bar", "c:foo\\bar", S_OK, 0},
66 {"file:/c|foo/bar", "c:foo\\bar", S_OK, 0},
67 {"file:/c:/foo%20ba%2fr", "c:\\foo ba/r", S_OK, 0},
68 {"file:/foo%20ba%2fr", "\\foo ba/r", S_OK, 0},
69 {"file:/foo/bar/", "\\foo\\bar\\", S_OK, 0},
70
71 /* 2 leading (back)slashes */
72 {"file://c:/foo/bar", "c:\\foo\\bar", S_OK, 0},
73 {"file://c:/d:/foo/bar", "c:\\d:\\foo\\bar", S_OK, 0},
74 {"file://c|/d|/foo/bar", "c:\\d|\\foo\\bar", S_OK, 0},
75 {"file://cx|/foo/bar", "\\\\cx|\\foo\\bar", S_OK, 0},
76 {"file://c:foo/bar", "c:foo\\bar", S_OK, 0},
77 {"file://c|foo/bar", "c:foo\\bar", S_OK, 0},
78 {"file://c:/foo%20ba%2fr", "c:\\foo%20ba%2fr", S_OK, 0},
79 {"file://c%3a/foo/../bar", "\\\\c:\\foo\\..\\bar", S_OK, 0},
80 {"file://c%7c/foo/../bar", "\\\\c|\\foo\\..\\bar", S_OK, 0},
81 {"file://foo%20ba%2fr", "\\\\foo ba/r", S_OK, 0},
82 {"file://localhost/c:/foo/bar", "c:\\foo\\bar", S_OK, 0},
83 {"file://localhost/c:/foo%20ba%5Cr", "c:\\foo ba\\r", S_OK, 0},
84 {"file://LocalHost/c:/foo/bar", "c:\\foo\\bar", S_OK, 0},
85 {"file:\\\\localhost\\c:\\foo\\bar", "c:\\foo\\bar", S_OK, 0},
86 {"file://incomplete", "\\\\incomplete", S_OK, 0},
87
88 /* 3 leading (back)slashes (omitting hostname) */
89 {"file:///c:/foo/bar", "c:\\foo\\bar", S_OK, 0},
90 {"File:///c:/foo/bar", "c:\\foo\\bar", S_OK, 0},
91 {"file:///c:/foo%20ba%2fr", "c:\\foo ba/r", S_OK, 0},
92 {"file:///foo%20ba%2fr", "\\foo ba/r", S_OK, 0},
93 {"file:///foo/bar/", "\\foo\\bar\\", S_OK, 0},
94 {"file:///localhost/c:/foo/bar", "\\localhost\\c:\\foo\\bar", S_OK, 0},
95
96 /* 4 leading (back)slashes */
97 {"file:////c:/foo/bar", "c:\\foo\\bar", S_OK, 0},
98 {"file:////c:/foo%20ba%2fr", "c:\\foo%20ba%2fr", S_OK, 0},
99 {"file:////foo%20ba%2fr", "\\\\foo%20ba%2fr", S_OK, 0},
100
101 /* 5 and more leading (back)slashes */
102 {"file://///c:/foo/bar", "\\\\c:\\foo\\bar", S_OK, 0},
103 {"file://///c:/foo%20ba%2fr", "\\\\c:\\foo ba/r", S_OK, 0},
104 {"file://///foo%20ba%2fr", "\\\\foo ba/r", S_OK, 0},
105 {"file://////c:/foo/bar", "\\\\c:\\foo\\bar", S_OK, 0},
106
107 /* Leading (back)slashes cannot be escaped */
108 {"file:%2f%2flocalhost%2fc:/foo/bar", "//localhost/c:\\foo\\bar", S_OK, 0},
109 {"file:%5C%5Clocalhost%5Cc:/foo/bar", "\\\\localhost\\c:\\foo\\bar", S_OK, 0},
110
111 /* Hostname handling */
112 {"file://l%6fcalhost/c:/foo/bar", "\\\\localhostc:\\foo\\bar", S_OK, 0},
113 {"file://localhost:80/c:/foo/bar", "\\\\localhost:80c:\\foo\\bar", S_OK, 0},
114 {"file://host/c:/foo/bar", "\\\\hostc:\\foo\\bar", S_OK, 0},
115 {"file://host//c:/foo/bar", "\\\\host\\\\c:\\foo\\bar", S_OK, 0},
116 {"file://host/\\c:/foo/bar", "\\\\host\\\\c:\\foo\\bar", S_OK, 0},
117 {"file://host/c:foo/bar", "\\\\hostc:foo\\bar", S_OK, 0},
118 {"file://host/foo/bar", "\\\\host\\foo\\bar", S_OK, 0},
119 {"file:\\\\host\\c:\\foo\\bar", "\\\\hostc:\\foo\\bar", S_OK, 0},
120 {"file:\\\\host\\ca\\foo\\bar", "\\\\host\\ca\\foo\\bar", S_OK, 0},
121 {"file:\\\\host\\c|\\foo\\bar", "\\\\hostc|\\foo\\bar", S_OK, 0},
122 {"file:\\%5Chost\\c:\\foo\\bar", "\\\\host\\c:\\foo\\bar", S_OK, 0},
123 {"file:\\\\host\\cx:\\foo\\bar", "\\\\host\\cx:\\foo\\bar", S_OK, 0},
124 {"file:///host/c:/foo/bar", "\\host\\c:\\foo\\bar", S_OK, 0},
125
126 /* Not file URLs */
127 {"c:\\foo\\bar", NULL, E_INVALIDARG, 0},
128 {"foo/bar", NULL, E_INVALIDARG, 0},
129 {"http://foo/bar", NULL, E_INVALIDARG, 0},
130
131 };
132
133
134 static struct {
135 const char *path;
136 BOOL expect;
137 } TEST_PATH_IS_URL[] = {
138 {"http://foo/bar", TRUE},
139 {"c:\\foo\\bar", FALSE},
140 {"c:/foo/bar", FALSE},
141 {"foo://foo/bar", TRUE},
142 {"foo\\bar", FALSE},
143 {"foo.bar", FALSE},
144 {"bogusscheme:", TRUE},
145 {"http:partial", TRUE},
146 {"www.winehq.org", FALSE},
147 /* More examples that the user might enter as the browser start page */
148 {"winehq.org", FALSE},
149 {"ftp.winehq.org", FALSE},
150 {"http://winehq.org", TRUE},
151 {"http://www.winehq.org", TRUE},
152 {"https://winehq.org", TRUE},
153 {"https://www.winehq.org", TRUE},
154 {"ftp://winehq.org", TRUE},
155 {"ftp://ftp.winehq.org", TRUE},
156 {"file://does_not_exist.txt", TRUE},
157 {"about:blank", TRUE},
158 {"about:home", TRUE},
159 {"about:mozilla", TRUE},
160 /* scheme is case independent */
161 {"HTTP://www.winehq.org", TRUE},
162 /* a space at the start is not allowed */
163 {" http://www.winehq.org", FALSE},
164 {"", FALSE},
165 {NULL, FALSE}
166 };
167
168 static const struct {
169 const char *path;
170 const char *result;
171 } TEST_PATH_UNQUOTE_SPACES[] = {
172 { "abcdef", "abcdef" },
173 { "\"abcdef\"", "abcdef" },
174 { "\"abcdef", "\"abcdef" },
175 { "abcdef\"", "abcdef\"" },
176 { "\"\"abcdef\"\"", "\"abcdef\"" },
177 { "abc\"def", "abc\"def" },
178 { "\"abc\"def", "\"abc\"def" },
179 { "\"abc\"def\"", "abc\"def" },
180 { "\'abcdef\'", "\'abcdef\'" },
181 { "\"\"", "" },
182 { "\"", "" }
183 };
184
185 /* ################ */
186
187 static LPWSTR GetWideString(const char* szString)
188 {
189 LPWSTR wszString = HeapAlloc(GetProcessHeap(), 0, (2*INTERNET_MAX_URL_LENGTH) * sizeof(WCHAR));
190
191 MultiByteToWideChar(CP_ACP, 0, szString, -1, wszString, INTERNET_MAX_URL_LENGTH);
192
193 return wszString;
194 }
195
196 static void FreeWideString(LPWSTR wszString)
197 {
198 HeapFree(GetProcessHeap(), 0, wszString);
199 }
200
201 static LPSTR strdupA(LPCSTR p)
202 {
203 LPSTR ret;
204 DWORD len = (strlen(p) + 1);
205 ret = HeapAlloc(GetProcessHeap(), 0, len);
206 memcpy(ret, p, len);
207 return ret;
208 }
209
210 /* ################ */
211
212 static void test_PathSearchAndQualify(void)
213 {
214 WCHAR path1[] = {'c',':','\\','f','o','o',0};
215 WCHAR expect1[] = {'c',':','\\','f','o','o',0};
216 WCHAR path2[] = {'c',':','f','o','o',0};
217 WCHAR c_drive[] = {'c',':',0};
218 WCHAR foo[] = {'f','o','o',0};
219 WCHAR path3[] = {'\\','f','o','o',0};
220 WCHAR winini[] = {'w','i','n','.','i','n','i',0};
221 WCHAR out[MAX_PATH];
222 WCHAR cur_dir[MAX_PATH];
223 WCHAR dot[] = {'.',0};
224
225 /* c:\foo */
226 ok(PathSearchAndQualifyW(path1, out, MAX_PATH) != 0,
227 "PathSearchAndQualify rets 0\n");
228 ok(!lstrcmpiW(out, expect1), "strings don't match\n");
229
230 /* c:foo */
231 ok(PathSearchAndQualifyW(path2, out, MAX_PATH) != 0,
232 "PathSearchAndQualify rets 0\n");
233 GetFullPathNameW(c_drive, MAX_PATH, cur_dir, NULL);
234 PathAddBackslashW(cur_dir);
235 lstrcatW(cur_dir, foo);
236 ok(!lstrcmpiW(out, cur_dir), "strings don't match\n");
237
238 /* foo */
239 ok(PathSearchAndQualifyW(foo, out, MAX_PATH) != 0,
240 "PathSearchAndQualify rets 0\n");
241 GetFullPathNameW(dot, MAX_PATH, cur_dir, NULL);
242 PathAddBackslashW(cur_dir);
243 lstrcatW(cur_dir, foo);
244 ok(!lstrcmpiW(out, cur_dir), "strings don't match\n");
245
246 /* \foo */
247 ok(PathSearchAndQualifyW(path3, out, MAX_PATH) != 0,
248 "PathSearchAndQualify rets 0\n");
249 GetFullPathNameW(dot, MAX_PATH, cur_dir, NULL);
250 lstrcpyW(cur_dir + 2, path3);
251 ok(!lstrcmpiW(out, cur_dir), "strings don't match\n");
252
253 /* win.ini */
254 ok(PathSearchAndQualifyW(winini, out, MAX_PATH) != 0,
255 "PathSearchAndQualify rets 0\n");
256 if(!SearchPathW(NULL, winini, NULL, MAX_PATH, cur_dir, NULL))
257 GetFullPathNameW(winini, MAX_PATH, cur_dir, NULL);
258 ok(!lstrcmpiW(out, cur_dir), "strings don't match\n");
259
260 }
261
262 static void test_PathCreateFromUrl(void)
263 {
264 size_t i;
265 char ret_path[INTERNET_MAX_URL_LENGTH];
266 DWORD len, len2, ret;
267 WCHAR ret_pathW[INTERNET_MAX_URL_LENGTH];
268 WCHAR *pathW, *urlW;
269
270 if (!pPathCreateFromUrlA) {
271 win_skip("PathCreateFromUrlA not found\n");
272 return;
273 }
274
275 /* Won't say how much is needed without a buffer */
276 len = 0xdeca;
277 ret = pPathCreateFromUrlA("file://foo", NULL, &len, 0);
278 ok(ret == E_INVALIDARG, "got 0x%08x expected E_INVALIDARG\n", ret);
279 ok(len == 0xdeca, "got %x expected 0xdeca\n", len);
280
281 /* Test the decoding itself */
282 for(i = 0; i < sizeof(TEST_PATHFROMURL) / sizeof(TEST_PATHFROMURL[0]); i++) {
283 len = INTERNET_MAX_URL_LENGTH;
284 ret = pPathCreateFromUrlA(TEST_PATHFROMURL[i].url, ret_path, &len, 0);
285 if (!(TEST_PATHFROMURL[i].todo & 0x1))
286 ok(ret == TEST_PATHFROMURL[i].ret, "ret %08x from url %s\n", ret, TEST_PATHFROMURL[i].url);
287 else todo_wine
288 ok(ret == TEST_PATHFROMURL[i].ret, "ret %08x from url %s\n", ret, TEST_PATHFROMURL[i].url);
289 if(SUCCEEDED(ret) && TEST_PATHFROMURL[i].path) {
290 if(!(TEST_PATHFROMURL[i].todo & 0x2)) {
291 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);
292 ok(len == strlen(ret_path), "ret len %d from url %s\n", len, TEST_PATHFROMURL[i].url);
293 } else todo_wine
294 /* Wrong string, don't bother checking the length */
295 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);
296 }
297
298 if (pPathCreateFromUrlW) {
299 len = INTERNET_MAX_URL_LENGTH;
300 pathW = GetWideString(TEST_PATHFROMURL[i].path);
301 urlW = GetWideString(TEST_PATHFROMURL[i].url);
302 ret = pPathCreateFromUrlW(urlW, ret_pathW, &len, 0);
303 WideCharToMultiByte(CP_ACP, 0, ret_pathW, -1, ret_path, sizeof(ret_path),NULL,NULL);
304 if (!(TEST_PATHFROMURL[i].todo & 0x1))
305 ok(ret == TEST_PATHFROMURL[i].ret, "ret %08x from url L\"%s\"\n", ret, TEST_PATHFROMURL[i].url);
306 else todo_wine
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);
317 }
318
319 if (SUCCEEDED(ret))
320 {
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 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);
327 else todo_wine
328 ok(len2 == len + 1, "got len = %d expected %d from url %s\n", len2, len + 1, TEST_PATHFROMURL[i].url);
329 }
330
331 FreeWideString(urlW);
332 FreeWideString(pathW);
333 }
334 }
335
336 if (pPathCreateFromUrlAlloc)
337 {
338 static const WCHAR fileW[] = {'f','i','l','e',':','/','/','f','o','o',0};
339 static const WCHAR fooW[] = {'\\','\\','f','o','o',0};
340
341 pathW = NULL;
342 ret = pPathCreateFromUrlAlloc(fileW, &pathW, 0);
343 ok(ret == S_OK, "got 0x%08x expected S_OK\n", ret);
344 ok(lstrcmpiW(pathW, fooW) == 0, "got %s expected %s\n", wine_dbgstr_w(pathW), wine_dbgstr_w(fooW));
345 HeapFree(GetProcessHeap(), 0, pathW);
346 }
347 }
348
349
350 static void test_PathIsUrl(void)
351 {
352 size_t i;
353 BOOL ret;
354
355 for(i = 0; i < sizeof(TEST_PATH_IS_URL)/sizeof(TEST_PATH_IS_URL[0]); i++) {
356 ret = PathIsURLA(TEST_PATH_IS_URL[i].path);
357 ok(ret == TEST_PATH_IS_URL[i].expect,
358 "returned %d from path %s, expected %d\n", ret, TEST_PATH_IS_URL[i].path,
359 TEST_PATH_IS_URL[i].expect);
360 }
361 }
362
363 static const DWORD SHELL_charclass[] =
364 {
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 0x00000000, 0x00000000, 0x00000000, 0x00000000,
372 0x00000000, 0x00000000, 0x00000000, 0x00000000,
373 0x00000080, 0x00000100, 0x00000200, 0x00000100,
374 0x00000100, 0x00000100, 0x00000100, 0x00000100,
375 0x00000100, 0x00000100, 0x00000002, 0x00000100,
376 0x00000040, 0x00000100, 0x00000004, 0x00000000,
377 0x00000100, 0x00000100, 0x00000100, 0x00000100,
378 0x00000100, 0x00000100, 0x00000100, 0x00000100,
379 0x00000100, 0x00000100, 0x00000010, 0x00000020,
380 0x00000000, 0x00000100, 0x00000000, 0x00000001,
381 0x00000100, 0xffffffff, 0xffffffff, 0xffffffff,
382 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
383 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
384 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
385 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
386 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
387 0xffffffff, 0xffffffff, 0xffffffff, 0x00000100,
388 0x00000008, 0x00000100, 0x00000100, 0x00000100,
389 0x00000100, 0xffffffff, 0xffffffff, 0xffffffff,
390 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
391 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
392 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
393 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
394 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
395 0xffffffff, 0xffffffff, 0xffffffff, 0x00000100,
396 0x00000000, 0x00000100, 0x00000100
397 };
398
399 static void test_PathIsValidCharA(void)
400 {
401 BOOL ret;
402 unsigned int c;
403
404 /* For whatever reason, PathIsValidCharA and PathAppendA share the same
405 * ordinal number in some native versions. Check this to prevent a crash.
406 */
407 if (!pPathIsValidCharA || pPathIsValidCharA == (void*)pPathAppendA)
408 {
409 win_skip("PathIsValidCharA isn't available\n");
410 return;
411 }
412
413 for (c = 0; c < 0x7f; c++)
414 {
415 ret = pPathIsValidCharA( c, ~0U );
416 ok ( ret || !SHELL_charclass[c], "PathIsValidCharA failed: 0x%02x got 0x%08x\n", c, ret );
417 }
418
419 for (c = 0x7f; c <= 0xff; c++)
420 {
421 ret = pPathIsValidCharA( c, ~0U );
422 ok ( ret, "PathIsValidCharA failed: 0x%02x got 0x%08x\n", c, ret );
423 }
424 }
425
426 static void test_PathIsValidCharW(void)
427 {
428 BOOL ret;
429 unsigned int c;
430
431 if (!pPathIsValidCharW)
432 {
433 win_skip("PathIsValidCharW isn't available\n");
434 return;
435 }
436
437 for (c = 0; c < 0x7f; c++)
438 {
439 ret = pPathIsValidCharW( c, ~0U );
440 ok ( ret || !SHELL_charclass[c], "PathIsValidCharW failed: 0x%02x got 0x%08x\n", c, ret );
441 }
442
443 for (c = 0x007f; c <= 0xffff; c++)
444 {
445 ret = pPathIsValidCharW( c, ~0U );
446 ok ( ret, "PathIsValidCharW failed: 0x%02x got 0x%08x\n", c, ret );
447 }
448 }
449
450 static void test_PathMakePretty(void)
451 {
452 char buff[MAX_PATH];
453
454 ok (PathMakePrettyA(NULL) == FALSE, "PathMakePretty: NULL path succeeded\n");
455 buff[0] = '\0';
456 ok (PathMakePrettyA(buff) == TRUE, "PathMakePretty: Empty path failed\n");
457
458 strcpy(buff, "C:\\A LONG FILE NAME WITH \\SPACES.TXT");
459 ok (PathMakePrettyA(buff) == TRUE, "PathMakePretty: Long UC name failed\n");
460 ok (strcmp(buff, "C:\\a long file name with \\spaces.txt") == 0,
461 "PathMakePretty: Long UC name not changed\n");
462
463 strcpy(buff, "C:\\A LONG FILE NAME WITH \\MixedCase.TXT");
464 ok (PathMakePrettyA(buff) == FALSE, "PathMakePretty: Long MC name succeeded\n");
465 ok (strcmp(buff, "C:\\A LONG FILE NAME WITH \\MixedCase.TXT") == 0,
466 "PathMakePretty: Failed but modified path\n");
467
468 strcpy(buff, "TEST");
469 ok (PathMakePrettyA(buff) == TRUE, "PathMakePretty: Short name failed\n");
470 ok (strcmp(buff, "Test") == 0, "PathMakePretty: 1st char lowercased %s\n", buff);
471 }
472
473 static void test_PathMatchSpec(void)
474 {
475 static const char file[] = "c:\\foo\\bar\\filename.ext";
476 static const char spec1[] = ".ext";
477 static const char spec2[] = "*.ext";
478 static const char spec3[] = "*.ext ";
479 static const char spec4[] = " *.ext";
480 static const char spec5[] = "* .ext";
481 static const char spec6[] = "*. ext";
482 static const char spec7[] = "* . ext";
483 static const char spec8[] = "*.e?t";
484 static const char spec9[] = "filename.ext";
485 static const char spec10[] = "*bar\\filename.ext";
486 static const char spec11[] = " foo; *.ext";
487 static const char spec12[] = "*.ext;*.bar";
488 static const char spec13[] = "*bar*";
489
490 ok (PathMatchSpecA(file, spec1) == FALSE, "PathMatchSpec: Spec1 failed\n");
491 ok (PathMatchSpecA(file, spec2) == TRUE, "PathMatchSpec: Spec2 failed\n");
492 ok (PathMatchSpecA(file, spec3) == FALSE, "PathMatchSpec: Spec3 failed\n");
493 ok (PathMatchSpecA(file, spec4) == TRUE, "PathMatchSpec: Spec4 failed\n");
494 todo_wine ok (PathMatchSpecA(file, spec5) == TRUE, "PathMatchSpec: Spec5 failed\n");
495 todo_wine ok (PathMatchSpecA(file, spec6) == TRUE, "PathMatchSpec: Spec6 failed\n");
496 ok (PathMatchSpecA(file, spec7) == FALSE, "PathMatchSpec: Spec7 failed\n");
497 ok (PathMatchSpecA(file, spec8) == TRUE, "PathMatchSpec: Spec8 failed\n");
498 ok (PathMatchSpecA(file, spec9) == FALSE, "PathMatchSpec: Spec9 failed\n");
499 ok (PathMatchSpecA(file, spec10) == TRUE, "PathMatchSpec: Spec10 failed\n");
500 ok (PathMatchSpecA(file, spec11) == TRUE, "PathMatchSpec: Spec11 failed\n");
501 ok (PathMatchSpecA(file, spec12) == TRUE, "PathMatchSpec: Spec12 failed\n");
502 ok (PathMatchSpecA(file, spec13) == TRUE, "PathMatchSpec: Spec13 failed\n");
503 }
504
505 static void test_PathCombineW(void)
506 {
507 LPWSTR wszString, wszString2;
508 WCHAR wbuf[MAX_PATH+1], wstr1[MAX_PATH] = {'C',':','\\',0}, wstr2[MAX_PATH];
509 static const WCHAR expout[] = {'C',':','\\','A','A',0};
510 int i;
511
512 if (!pPathCombineW)
513 {
514 win_skip("PathCombineW isn't available\n");
515 return;
516 }
517
518 wszString2 = HeapAlloc(GetProcessHeap(), 0, MAX_PATH * sizeof(WCHAR));
519
520 /* NULL test */
521 wszString = pPathCombineW(NULL, NULL, NULL);
522 ok (wszString == NULL, "Expected a NULL return\n");
523
524 /* Some NULL */
525 wszString2[0] = 'a';
526 wszString = pPathCombineW(wszString2, NULL, NULL);
527 ok (wszString == NULL ||
528 broken(wszString[0] == 'a'), /* Win95 and some W2K */
529 "Expected a NULL return\n");
530 ok (wszString2[0] == 0 ||
531 broken(wszString2[0] == 'a'), /* Win95 and some W2K */
532 "Destination string not empty\n");
533
534 HeapFree(GetProcessHeap(), 0, wszString2);
535
536 /* overflow test */
537 wstr2[0] = wstr2[1] = wstr2[2] = 'A';
538 for (i=3; i<MAX_PATH/2; i++)
539 wstr1[i] = wstr2[i] = 'A';
540 wstr1[(MAX_PATH/2) - 1] = wstr2[MAX_PATH/2] = 0;
541 memset(wbuf, 0xbf, sizeof(wbuf));
542
543 wszString = pPathCombineW(wbuf, wstr1, wstr2);
544 ok(wszString == NULL, "Expected a NULL return\n");
545 ok(wbuf[0] == 0 ||
546 broken(wbuf[0] == 0xbfbf), /* Win95 and some W2K */
547 "Buffer contains data\n");
548
549 /* PathCombineW can be used in place */
550 wstr1[3] = 0;
551 wstr2[2] = 0;
552 ok(PathCombineW(wstr1, wstr1, wstr2) == wstr1, "Expected a wstr1 return\n");
553 ok(StrCmpW(wstr1, expout) == 0, "Unexpected PathCombine output\n");
554 }
555
556
557 #define LONG_LEN (MAX_PATH * 2)
558 #define HALF_LEN (MAX_PATH / 2 + 1)
559
560 static void test_PathCombineA(void)
561 {
562 LPSTR str;
563 char dest[MAX_PATH];
564 char too_long[LONG_LEN];
565 char one[HALF_LEN], two[HALF_LEN];
566
567 /* try NULL dest */
568 SetLastError(0xdeadbeef);
569 str = PathCombineA(NULL, "C:\\", "one\\two\\three");
570 ok(str == NULL, "Expected NULL, got %p\n", str);
571 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
572
573 /* try NULL dest and NULL directory */
574 SetLastError(0xdeadbeef);
575 str = PathCombineA(NULL, NULL, "one\\two\\three");
576 ok(str == NULL, "Expected NULL, got %p\n", str);
577 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
578
579 /* try all NULL*/
580 SetLastError(0xdeadbeef);
581 str = PathCombineA(NULL, NULL, NULL);
582 ok(str == NULL, "Expected NULL, got %p\n", str);
583 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
584
585 /* try NULL file part */
586 SetLastError(0xdeadbeef);
587 lstrcpyA(dest, "control");
588 str = PathCombineA(dest, "C:\\", NULL);
589 ok(str == dest, "Expected str == dest, got %p\n", str);
590 ok(!lstrcmp(str, "C:\\"), "Expected C:\\, got %s\n", str);
591 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
592
593 /* try empty file part */
594 SetLastError(0xdeadbeef);
595 lstrcpyA(dest, "control");
596 str = PathCombineA(dest, "C:\\", "");
597 ok(str == dest, "Expected str == dest, got %p\n", str);
598 ok(!lstrcmp(str, "C:\\"), "Expected C:\\, got %s\n", str);
599 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
600
601 /* try empty directory and file part */
602 SetLastError(0xdeadbeef);
603 lstrcpyA(dest, "control");
604 str = PathCombineA(dest, "", "");
605 ok(str == dest, "Expected str == dest, got %p\n", str);
606 ok(!lstrcmp(str, "\\") ||
607 broken(!lstrcmp(str, "control")), /* Win95 and some W2K */
608 "Expected \\, got %s\n", str);
609 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
610
611 /* try NULL directory */
612 SetLastError(0xdeadbeef);
613 lstrcpyA(dest, "control");
614 str = PathCombineA(dest, NULL, "one\\two\\three");
615 ok(str == dest, "Expected str == dest, got %p\n", str);
616 ok(!lstrcmp(str, "one\\two\\three"), "Expected one\\two\\three, got %s\n", str);
617 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
618
619 /* try NULL directory and empty file part */
620 SetLastError(0xdeadbeef);
621 lstrcpyA(dest, "control");
622 str = PathCombineA(dest, NULL, "");
623 ok(str == dest, "Expected str == dest, got %p\n", str);
624 ok(!lstrcmp(str, "\\") ||
625 broken(!lstrcmp(str, "one\\two\\three")), /* Win95 and some W2K */
626 "Expected \\, got %s\n", str);
627 ok(GetLastError() == 0xdeadbeef ||
628 broken(GetLastError() == ERROR_INVALID_PARAMETER), /* Win95 */
629 "Expected 0xdeadbeef, got %d\n", GetLastError());
630
631 /* try NULL directory and file part */
632 SetLastError(0xdeadbeef);
633 lstrcpyA(dest, "control");
634 str = PathCombineA(dest, NULL, NULL);
635 ok(str == NULL ||
636 broken(str != NULL), /* Win95 and some W2K */
637 "Expected str == NULL, got %p\n", str);
638 ok(lstrlenA(dest) == 0 ||
639 broken(!lstrcmp(dest, "control")), /* Win95 and some W2K */
640 "Expected 0 length, got %i\n", lstrlenA(dest));
641 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
642
643 /* try directory without backslash */
644 SetLastError(0xdeadbeef);
645 lstrcpyA(dest, "control");
646 str = PathCombineA(dest, "C:", "one\\two\\three");
647 ok(str == dest, "Expected str == dest, got %p\n", str);
648 ok(!lstrcmp(str, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", str);
649 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
650
651 /* try directory with backslash */
652 SetLastError(0xdeadbeef);
653 lstrcpyA(dest, "control");
654 str = PathCombineA(dest, "C:\\", "one\\two\\three");
655 ok(str == dest, "Expected str == dest, got %p\n", str);
656 ok(!lstrcmp(str, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", str);
657 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
658
659 /* try directory with backslash and file with prepended backslash */
660 SetLastError(0xdeadbeef);
661 lstrcpyA(dest, "control");
662 str = PathCombineA(dest, "C:\\", "\\one\\two\\three");
663 ok(str == dest, "Expected str == dest, got %p\n", str);
664 ok(!lstrcmp(str, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", str);
665 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
666
667 /* try previous test, with backslash appended as well */
668 SetLastError(0xdeadbeef);
669 lstrcpyA(dest, "control");
670 str = PathCombineA(dest, "C:\\", "\\one\\two\\three\\");
671 ok(str == dest, "Expected str == dest, got %p\n", str);
672 ok(!lstrcmp(str, "C:\\one\\two\\three\\"), "Expected C:\\one\\two\\three\\, got %s\n", str);
673 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
674
675 /* try a relative directory */
676 SetLastError(0xdeadbeef);
677 lstrcpyA(dest, "control");
678 str = PathCombineA(dest, "relative\\dir", "\\one\\two\\three\\");
679 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
680 /* Vista fails which probably makes sense as PathCombineA expects an absolute dir */
681 if (str)
682 {
683 ok(str == dest, "Expected str == dest, got %p\n", str);
684 ok(!lstrcmp(str, "one\\two\\three\\"), "Expected one\\two\\three\\, got %s\n", str);
685 }
686
687 /* try forward slashes */
688 SetLastError(0xdeadbeef);
689 lstrcpyA(dest, "control");
690 str = PathCombineA(dest, "C:\\", "one/two/three\\");
691 ok(str == dest, "Expected str == dest, got %p\n", str);
692 ok(!lstrcmp(str, "C:\\one/two/three\\"), "Expected one/two/three\\, got %s\n", str);
693 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
694
695 /* try a really weird directory */
696 SetLastError(0xdeadbeef);
697 lstrcpyA(dest, "control");
698 str = PathCombineA(dest, "C:\\/\\/", "\\one\\two\\three\\");
699 ok(str == dest, "Expected str == dest, got %p\n", str);
700 ok(!lstrcmp(str, "C:\\one\\two\\three\\"), "Expected C:\\one\\two\\three\\, got %s\n", str);
701 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
702
703 /* try periods */
704 SetLastError(0xdeadbeef);
705 lstrcpyA(dest, "control");
706 str = PathCombineA(dest, "C:\\", "one\\..\\two\\.\\three");
707 ok(str == dest, "Expected str == dest, got %p\n", str);
708 ok(!lstrcmp(str, "C:\\two\\three"), "Expected C:\\two\\three, got %s\n", str);
709 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
710
711 /* try .. as file */
712 /* try forward slashes */
713 SetLastError(0xdeadbeef);
714 lstrcpyA(dest, "control");
715 str = PathCombineA(dest, "C:\\", "..");
716 ok(str == dest, "Expected str == dest, got %p\n", str);
717 ok(!lstrcmp(str, "C:\\"), "Expected C:\\, got %s\n", str);
718 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
719
720 memset(too_long, 'a', LONG_LEN);
721 too_long[LONG_LEN - 1] = '\0';
722
723 /* try a file longer than MAX_PATH */
724 SetLastError(0xdeadbeef);
725 lstrcpyA(dest, "control");
726 str = PathCombineA(dest, "C:\\", too_long);
727 ok(str == NULL, "Expected str == NULL, got %p\n", str);
728 ok(lstrlenA(dest) == 0 ||
729 broken(!lstrcmp(dest, "control")), /* Win95 and some W2K */
730 "Expected 0 length, got %i\n", lstrlenA(dest));
731 todo_wine ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
732
733 /* try a directory longer than MAX_PATH */
734 SetLastError(0xdeadbeef);
735 lstrcpyA(dest, "control");
736 str = PathCombineA(dest, too_long, "one\\two\\three");
737 ok(str == NULL, "Expected str == NULL, got %p\n", str);
738 ok(lstrlenA(dest) == 0 ||
739 broken(!lstrcmp(dest, "control")), /* Win95 and some W2K */
740 "Expected 0 length, got %i\n", lstrlenA(dest));
741 todo_wine ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
742
743 memset(one, 'b', HALF_LEN);
744 memset(two, 'c', HALF_LEN);
745 one[HALF_LEN - 1] = '\0';
746 two[HALF_LEN - 1] = '\0';
747
748 /* destination string is longer than MAX_PATH, but not the constituent parts */
749 SetLastError(0xdeadbeef);
750 lstrcpyA(dest, "control");
751 str = PathCombineA(dest, one, two);
752 ok(str == NULL, "Expected str == NULL, got %p\n", str);
753 ok(lstrlenA(dest) == 0 ||
754 broken(!lstrcmp(dest, "control")), /* Win95 and some W2K */
755 "Expected 0 length, got %i\n", lstrlenA(dest));
756 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
757 }
758
759 static void test_PathAddBackslash(void)
760 {
761 LPSTR str;
762 char path[MAX_PATH];
763 char too_long[LONG_LEN];
764
765 /* try a NULL path */
766 SetLastError(0xdeadbeef);
767 str = PathAddBackslashA(NULL);
768 ok(str == NULL, "Expected str == NULL, got %p\n", str);
769 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
770
771 /* try an empty path */
772 path[0] = '\0';
773 SetLastError(0xdeadbeef);
774 str = PathAddBackslashA(path);
775 ok(str == (path + lstrlenA(path)), "Expected str to point to end of path, got %p\n", str);
776 ok(lstrlenA(path) == 0, "Expected empty string, got %i\n", lstrlenA(path));
777 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
778
779 /* try a relative path */
780 lstrcpyA(path, "one\\two");
781 SetLastError(0xdeadbeef);
782 str = PathAddBackslashA(path);
783 ok(str == (path + lstrlenA(path)), "Expected str to point to end of path, got %p\n", str);
784 ok(!lstrcmp(path, "one\\two\\"), "Expected one\\two\\, got %s\n", path);
785 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
786
787 /* try periods */
788 lstrcpyA(path, "one\\..\\two");
789 SetLastError(0xdeadbeef);
790 str = PathAddBackslashA(path);
791 ok(str == (path + lstrlenA(path)), "Expected str to point to end of path, got %p\n", str);
792 ok(!lstrcmp(path, "one\\..\\two\\"), "Expected one\\..\\two\\, got %s\n", path);
793 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
794
795 /* try just a space */
796 lstrcpyA(path, " ");
797 SetLastError(0xdeadbeef);
798 str = PathAddBackslashA(path);
799 ok(str == (path + lstrlenA(path)), "Expected str to point to end of path, got %p\n", str);
800 ok(!lstrcmp(path, " \\"), "Expected \\, got %s\n", path);
801 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
802
803 /* path already has backslash */
804 lstrcpyA(path, "C:\\one\\");
805 SetLastError(0xdeadbeef);
806 str = PathAddBackslashA(path);
807 ok(str == (path + lstrlenA(path)), "Expected str to point to end of path, got %p\n", str);
808 ok(!lstrcmp(path, "C:\\one\\"), "Expected C:\\one\\, got %s\n", path);
809 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
810
811 memset(too_long, 'a', LONG_LEN);
812 too_long[LONG_LEN - 1] = '\0';
813
814 /* path is longer than MAX_PATH */
815 SetLastError(0xdeadbeef);
816 str = PathAddBackslashA(too_long);
817 ok(str == NULL, "Expected str == NULL, got %p\n", str);
818 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
819 }
820
821 static void test_PathAppendA(void)
822 {
823 char path[MAX_PATH];
824 char too_long[LONG_LEN];
825 char half[HALF_LEN];
826 BOOL res;
827
828 lstrcpy(path, "C:\\one");
829
830 /* try NULL pszMore */
831 SetLastError(0xdeadbeef);
832 res = PathAppendA(path, NULL);
833 ok(!res, "Expected failure\n");
834 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
835 ok(!lstrcmp(path, "C:\\one"), "Expected C:\\one, got %s\n", path);
836
837 /* try empty pszMore */
838 SetLastError(0xdeadbeef);
839 res = PathAppendA(path, "");
840 ok(res, "Expected success\n");
841 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
842 ok(!lstrcmp(path, "C:\\one"), "Expected C:\\one, got %s\n", path);
843
844 /* try NULL pszPath */
845 SetLastError(0xdeadbeef);
846 res = PathAppendA(NULL, "two\\three");
847 ok(!res, "Expected failure\n");
848 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
849
850 /* try empty pszPath */
851 path[0] = '\0';
852 SetLastError(0xdeadbeef);
853 res = PathAppendA(path, "two\\three");
854 ok(res, "Expected success\n");
855 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
856 ok(!lstrcmp(path, "two\\three"), "Expected \\two\\three, got %s\n", path);
857
858 /* try empty pszPath and empty pszMore */
859 path[0] = '\0';
860 SetLastError(0xdeadbeef);
861 res = PathAppendA(path, "");
862 ok(res, "Expected success\n");
863 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
864 ok(!lstrcmp(path, "\\"), "Expected \\, got %s\n", path);
865
866 /* try legit params */
867 lstrcpy(path, "C:\\one");
868 SetLastError(0xdeadbeef);
869 res = PathAppendA(path, "two\\three");
870 ok(res, "Expected success\n");
871 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
872 ok(!lstrcmp(path, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", path);
873
874 /* try pszPath with backslash after it */
875 lstrcpy(path, "C:\\one\\");
876 SetLastError(0xdeadbeef);
877 res = PathAppendA(path, "two\\three");
878 ok(res, "Expected success\n");
879 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
880 ok(!lstrcmp(path, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", path);
881
882 /* try pszMore with backslash before it */
883 lstrcpy(path, "C:\\one");
884 SetLastError(0xdeadbeef);
885 res = PathAppendA(path, "\\two\\three");
886 ok(res, "Expected success\n");
887 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
888 ok(!lstrcmp(path, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", path);
889
890 /* try pszMore with backslash after it */
891 lstrcpy(path, "C:\\one");
892 SetLastError(0xdeadbeef);
893 res = PathAppendA(path, "two\\three\\");
894 ok(res, "Expected success\n");
895 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
896 ok(!lstrcmp(path, "C:\\one\\two\\three\\"), "Expected C:\\one\\two\\three\\, got %s\n", path);
897
898 /* try spaces in pszPath */
899 lstrcpy(path, "C: \\ one ");
900 SetLastError(0xdeadbeef);
901 res = PathAppendA(path, "two\\three");
902 ok(res, "Expected success\n");
903 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
904 ok(!lstrcmp(path, "C: \\ one \\two\\three"), "Expected C: \\ one \\two\\three, got %s\n", path);
905
906 /* try spaces in pszMore */
907 lstrcpy(path, "C:\\one");
908 SetLastError(0xdeadbeef);
909 res = PathAppendA(path, " two \\ three ");
910 ok(res, "Expected success\n");
911 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
912 ok(!lstrcmp(path, "C:\\one\\ two \\ three "), "Expected 'C:\\one\\ two \\ three ', got %s\n", path);
913
914 /* pszPath is too long */
915 memset(too_long, 'a', LONG_LEN);
916 too_long[LONG_LEN - 1] = '\0';
917 SetLastError(0xdeadbeef);
918 res = PathAppendA(too_long, "two\\three");
919 ok(!res, "Expected failure\n");
920 todo_wine ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
921 ok(lstrlen(too_long) == 0 ||
922 broken(lstrlen(too_long) == (LONG_LEN - 1)), /* Win95 and some W2K */
923 "Expected length of too_long to be zero, got %i\n", lstrlen(too_long));
924
925 /* pszMore is too long */
926 lstrcpy(path, "C:\\one");
927 memset(too_long, 'a', LONG_LEN);
928 too_long[LONG_LEN - 1] = '\0';
929 SetLastError(0xdeadbeef);
930 res = PathAppendA(path, too_long);
931 ok(!res, "Expected failure\n");
932 todo_wine ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
933 ok(lstrlen(path) == 0 ||
934 broken(!lstrcmp(path, "C:\\one")), /* Win95 and some W2K */
935 "Expected length of path to be zero, got %i\n", lstrlen(path));
936
937 /* both params combined are too long */
938 memset(path, 'a', HALF_LEN);
939 path[HALF_LEN - 1] = '\0';
940 memset(half, 'b', HALF_LEN);
941 half[HALF_LEN - 1] = '\0';
942 SetLastError(0xdeadbeef);
943 res = PathAppendA(path, half);
944 ok(!res, "Expected failure\n");
945 ok(lstrlen(path) == 0 ||
946 broken(lstrlen(path) == (HALF_LEN - 1)), /* Win95 and some W2K */
947 "Expected length of path to be zero, got %i\n", lstrlen(path));
948 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
949 }
950
951 static void test_PathCanonicalizeA(void)
952 {
953 char dest[LONG_LEN + MAX_PATH];
954 char too_long[LONG_LEN];
955 BOOL res;
956
957 /* try a NULL source */
958 lstrcpy(dest, "test");
959 SetLastError(0xdeadbeef);
960 res = PathCanonicalizeA(dest, NULL);
961 ok(!res, "Expected failure\n");
962 ok(GetLastError() == ERROR_INVALID_PARAMETER,
963 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
964 ok(dest[0] == 0 || !lstrcmp(dest, "test"),
965 "Expected either an empty string (Vista) or test, got %s\n", dest);
966
967 /* try an empty source */
968 lstrcpy(dest, "test");
969 SetLastError(0xdeadbeef);
970 res = PathCanonicalizeA(dest, "");
971 ok(res, "Expected success\n");
972 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
973 ok(!lstrcmp(dest, "\\") ||
974 broken(!lstrcmp(dest, "test")), /* Win95 and some W2K */
975 "Expected \\, got %s\n", dest);
976
977 /* try a NULL dest */
978 SetLastError(0xdeadbeef);
979 res = PathCanonicalizeA(NULL, "C:\\");
980 ok(!res, "Expected failure\n");
981 ok(GetLastError() == ERROR_INVALID_PARAMETER,
982 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
983
984 /* try empty dest */
985 dest[0] = '\0';
986 SetLastError(0xdeadbeef);
987 res = PathCanonicalizeA(dest, "C:\\");
988 ok(res, "Expected success\n");
989 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
990 ok(!lstrcmp(dest, "C:\\"), "Expected C:\\, got %s\n", dest);
991
992 /* try non-empty dest */
993 lstrcpy(dest, "test");
994 SetLastError(0xdeadbeef);
995 res = PathCanonicalizeA(dest, "C:\\");
996 ok(res, "Expected success\n");
997 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
998 ok(!lstrcmp(dest, "C:\\"), "Expected C:\\, got %s\n", dest);
999
1000 /* try a space for source */
1001 lstrcpy(dest, "test");
1002 SetLastError(0xdeadbeef);
1003 res = PathCanonicalizeA(dest, " ");
1004 ok(res, "Expected success\n");
1005 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1006 ok(!lstrcmp(dest, " "), "Expected ' ', got %s\n", dest);
1007
1008 /* try a relative path */
1009 lstrcpy(dest, "test");
1010 SetLastError(0xdeadbeef);
1011 res = PathCanonicalizeA(dest, "one\\two");
1012 ok(res, "Expected success\n");
1013 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1014 ok(!lstrcmp(dest, "one\\two"), "Expected one\\two, got %s\n", dest);
1015
1016 /* try current dir and previous dir */
1017 lstrcpy(dest, "test");
1018 SetLastError(0xdeadbeef);
1019 res = PathCanonicalizeA(dest, "C:\\one\\.\\..\\two\\three\\..");
1020 ok(res, "Expected success\n");
1021 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1022 ok(!lstrcmp(dest, "C:\\two"), "Expected C:\\two, got %s\n", dest);
1023
1024 /* try simple forward slashes */
1025 lstrcpy(dest, "test");
1026 SetLastError(0xdeadbeef);
1027 res = PathCanonicalizeA(dest, "C:\\one/two/three\\four/five\\six");
1028 ok(res, "Expected success\n");
1029 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1030 ok(!lstrcmp(dest, "C:\\one/two/three\\four/five\\six"),
1031 "Expected C:\\one/two/three\\four/five\\six, got %s\n", dest);
1032
1033 /* try simple forward slashes with same dir */
1034 lstrcpy(dest, "test");
1035 SetLastError(0xdeadbeef);
1036 res = PathCanonicalizeA(dest, "C:\\one/.\\two");
1037 ok(res, "Expected success\n");
1038 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1039 ok(!lstrcmp(dest, "C:\\one/.\\two"), "Expected C:\\one/.\\two, got %s\n", dest);
1040
1041 /* try simple forward slashes with change dir */
1042 lstrcpy(dest, "test");
1043 SetLastError(0xdeadbeef);
1044 res = PathCanonicalizeA(dest, "C:\\one/.\\two\\..");
1045 ok(res, "Expected success\n");
1046 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1047 ok(!lstrcmp(dest, "C:\\one/.") ||
1048 !lstrcmp(dest, "C:\\one/"), /* Vista */
1049 "Expected \"C:\\one/.\" or \"C:\\one/\", got \"%s\"\n", dest);
1050
1051 /* try forward slashes with change dirs
1052 * NOTE: if there is a forward slash in between two backslashes,
1053 * everything in between the two backslashes is considered on dir
1054 */
1055 lstrcpy(dest, "test");
1056 SetLastError(0xdeadbeef);
1057 res = PathCanonicalizeA(dest, "C:\\one/.\\..\\two/three\\..\\four/.five");
1058 ok(res, "Expected success\n");
1059 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1060 ok(!lstrcmp(dest, "C:\\four/.five"), "Expected C:\\four/.five, got %s\n", dest);
1061
1062 /* try src is too long */
1063 memset(too_long, 'a', LONG_LEN);
1064 too_long[LONG_LEN - 1] = '\0';
1065 lstrcpy(dest, "test");
1066 SetLastError(0xdeadbeef);
1067 res = PathCanonicalizeA(dest, too_long);
1068 ok(!res ||
1069 broken(res), /* Win95, some W2K and XP-SP1 */
1070 "Expected failure\n");
1071 todo_wine
1072 {
1073 ok(GetLastError() == 0xdeadbeef || GetLastError() == ERROR_FILENAME_EXCED_RANGE /* Vista */,
1074 "Expected 0xdeadbeef or ERROR_FILENAME_EXCED_RANGE, got %d\n", GetLastError());
1075 }
1076 ok(lstrlen(too_long) == LONG_LEN - 1, "Expected length LONG_LEN - 1, got %i\n", lstrlen(too_long));
1077 }
1078
1079 static void test_PathFindExtensionA(void)
1080 {
1081 LPSTR ext;
1082 char path[MAX_PATH];
1083 char too_long[LONG_LEN];
1084
1085 /* try a NULL path */
1086 SetLastError(0xdeadbeef);
1087 ext = PathFindExtensionA(NULL);
1088 ok(ext == NULL, "Expected NULL, got %p\n", ext);
1089 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1090
1091 /* try an empty path */
1092 path[0] = '\0';
1093 SetLastError(0xdeadbeef);
1094 ext = PathFindExtensionA(path);
1095 ok(ext == path, "Expected ext == path, got %p\n", ext);
1096 ok(lstrlen(ext) == 0, "Expected length 0, got %i\n", lstrlen(ext));
1097 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1098
1099 /* try a path without an extension */
1100 lstrcpy(path, "file");
1101 SetLastError(0xdeadbeef);
1102 ext = PathFindExtensionA(path);
1103 ok(ext == path + lstrlen(path), "Expected ext == path, got %p\n", ext);
1104 ok(lstrlen(ext) == 0, "Expected length 0, got %i\n", lstrlen(ext));
1105 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1106
1107 /* try a path with an extension */
1108 lstrcpy(path, "file.txt");
1109 SetLastError(0xdeadbeef);
1110 ext = PathFindExtensionA(path);
1111 ok(ext == path + lstrlen("file"),
1112 "Expected ext == path + lstrlen(\"file\"), got %p\n", ext);
1113 ok(!lstrcmp(ext, ".txt"), "Expected .txt, got %s\n", ext);
1114 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1115
1116 /* try a path with two extensions */
1117 lstrcpy(path, "file.txt.doc");
1118 SetLastError(0xdeadbeef);
1119 ext = PathFindExtensionA(path);
1120 ok(ext == path + lstrlen("file.txt"),
1121 "Expected ext == path + lstrlen(\"file.txt\"), got %p\n", ext);
1122 ok(!lstrcmp(ext, ".doc"), "Expected .txt, got %s\n", ext);
1123 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1124
1125 /* try a path longer than MAX_PATH without an extension*/
1126 memset(too_long, 'a', LONG_LEN);
1127 too_long[LONG_LEN - 1] = '\0';
1128 SetLastError(0xdeadbeef);
1129 ext = PathFindExtensionA(too_long);
1130 ok(ext == too_long + LONG_LEN - 1, "Expected ext == too_long + LONG_LEN - 1, got %p\n", ext);
1131 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1132
1133 /* try a path longer than MAX_PATH with an extension*/
1134 memset(too_long, 'a', LONG_LEN);
1135 too_long[LONG_LEN - 1] = '\0';
1136 lstrcpy(too_long + 300, ".abcde");
1137 too_long[lstrlen(too_long)] = 'a';
1138 SetLastError(0xdeadbeef);
1139 ext = PathFindExtensionA(too_long);
1140 ok(ext == too_long + 300, "Expected ext == too_long + 300, got %p\n", ext);
1141 ok(lstrlen(ext) == LONG_LEN - 301, "Expected LONG_LEN - 301, got %i\n", lstrlen(ext));
1142 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1143 }
1144
1145 static void test_PathBuildRootA(void)
1146 {
1147 LPSTR root;
1148 char path[10];
1149 char root_expected[26][4];
1150 char drive;
1151 int j;
1152
1153 /* set up the expected paths */
1154 for (drive = 'A'; drive <= 'Z'; drive++)
1155 sprintf(root_expected[drive - 'A'], "%c:\\", drive);
1156
1157 /* test the expected values */
1158 for (j = 0; j < 26; j++)
1159 {
1160 SetLastError(0xdeadbeef);
1161 lstrcpy(path, "aaaaaaaaa");
1162 root = PathBuildRootA(path, j);
1163 ok(root == path, "Expected root == path, got %p\n", root);
1164 ok(!lstrcmp(root, root_expected[j]), "Expected %s, got %s\n", root_expected[j], root);
1165 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1166 }
1167
1168 /* test a negative drive number */
1169 SetLastError(0xdeadbeef);
1170 lstrcpy(path, "aaaaaaaaa");
1171 root = PathBuildRootA(path, -1);
1172 ok(root == path, "Expected root == path, got %p\n", root);
1173 ok(!lstrcmp(path, "aaaaaaaaa") ||
1174 lstrlenA(path) == 0, /* Vista */
1175 "Expected aaaaaaaaa or empty string, got %s\n", path);
1176 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1177
1178 /* test a drive number greater than 25 */
1179 SetLastError(0xdeadbeef);
1180 lstrcpy(path, "aaaaaaaaa");
1181 root = PathBuildRootA(path, 26);
1182 ok(root == path, "Expected root == path, got %p\n", root);
1183 ok(!lstrcmp(path, "aaaaaaaaa") ||
1184 lstrlenA(path) == 0, /* Vista */
1185 "Expected aaaaaaaaa or empty string, got %s\n", path);
1186 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1187
1188 /* length of path is less than 4 */
1189 SetLastError(0xdeadbeef);
1190 lstrcpy(path, "aa");
1191 root = PathBuildRootA(path, 0);
1192 ok(root == path, "Expected root == path, got %p\n", root);
1193 ok(!lstrcmp(path, "A:\\"), "Expected A:\\, got %s\n", path);
1194 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1195
1196 /* path is NULL */
1197 SetLastError(0xdeadbeef);
1198 root = PathBuildRootA(NULL, 0);
1199 ok(root == NULL, "Expected root == NULL, got %p\n", root);
1200 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1201 }
1202
1203 static void test_PathCommonPrefixA(void)
1204 {
1205 char path1[MAX_PATH], path2[MAX_PATH];
1206 char out[MAX_PATH];
1207 int count;
1208
1209 /* test NULL path1 */
1210 SetLastError(0xdeadbeef);
1211 lstrcpy(path2, "C:\\");
1212 lstrcpy(out, "aaa");
1213 count = PathCommonPrefixA(NULL, path2, out);
1214 ok(count == 0, "Expected 0, got %i\n", count);
1215 todo_wine
1216 {
1217 ok(!lstrcmp(out, "aaa"), "Expected aaa, got %s\n", out);
1218 }
1219 ok(!lstrcmp(path2, "C:\\"), "Expected C:\\, got %s\n", path2);
1220 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1221
1222 /* test NULL path2 */
1223 SetLastError(0xdeadbeef);
1224 lstrcpy(path1, "C:\\");
1225 lstrcpy(out, "aaa");
1226 count = PathCommonPrefixA(path1, NULL, out);
1227 ok(count == 0, "Expected 0, got %i\n", count);
1228 todo_wine
1229 {
1230 ok(!lstrcmp(out, "aaa"), "Expected aaa, got %s\n", out);
1231 }
1232 ok(!lstrcmp(path1, "C:\\"), "Expected C:\\, got %s\n", path1);
1233 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1234
1235 /* test empty path1 */
1236 SetLastError(0xdeadbeef);
1237 path1[0] = '\0';
1238 lstrcpy(path2, "C:\\");
1239 lstrcpy(out, "aaa");
1240 count = PathCommonPrefixA(path1, path2, out);
1241 ok(count == 0, "Expected 0, got %i\n", count);
1242 ok(lstrlen(out) == 0, "Expected 0 length out, got %i\n", lstrlen(out));
1243 ok(lstrlen(path1) == 0, "Expected 0 length path1, got %i\n", lstrlen(path1));
1244 ok(!lstrcmp(path2, "C:\\"), "Expected C:\\, got %s\n", path2);
1245 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1246
1247 /* test empty path1 */
1248 SetLastError(0xdeadbeef);
1249 path2[0] = '\0';
1250 lstrcpy(path1, "C:\\");
1251 lstrcpy(out, "aaa");
1252 count = PathCommonPrefixA(path1, path2, out);
1253 ok(count == 0, "Expected 0, got %i\n", count);
1254 ok(lstrlen(out) == 0, "Expected 0 length out, got %i\n", lstrlen(out));
1255 ok(lstrlen(path2) == 0, "Expected 0 length path2, got %i\n", lstrlen(path2));
1256 ok(!lstrcmp(path1, "C:\\"), "Expected C:\\, got %s\n", path1);
1257 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1258
1259 /* paths are legit, out is NULL */
1260 SetLastError(0xdeadbeef);
1261 lstrcpy(path1, "C:\\");
1262 lstrcpy(path2, "C:\\");
1263 count = PathCommonPrefixA(path1, path2, NULL);
1264 ok(count == 3, "Expected 3, got %i\n", count);
1265 ok(!lstrcmp(path1, "C:\\"), "Expected C:\\, got %s\n", path1);
1266 ok(!lstrcmp(path2, "C:\\"), "Expected C:\\, got %s\n", path2);
1267 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1268
1269 /* all parameters legit */
1270 SetLastError(0xdeadbeef);
1271 lstrcpy(path1, "C:\\");
1272 lstrcpy(path2, "C:\\");
1273 lstrcpy(out, "aaa");
1274 count = PathCommonPrefixA(path1, path2, out);
1275 ok(count == 3, "Expected 3, got %i\n", count);
1276 ok(!lstrcmp(path1, "C:\\"), "Expected C:\\, got %s\n", path1);
1277 ok(!lstrcmp(path2, "C:\\"), "Expected C:\\, got %s\n", path2);
1278 ok(!lstrcmp(out, "C:\\"), "Expected C:\\, got %s\n", out);
1279 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1280
1281 /* path1 and path2 not the same, but common prefix */
1282 SetLastError(0xdeadbeef);
1283 lstrcpy(path1, "C:\\one\\two");
1284 lstrcpy(path2, "C:\\one\\three");
1285 lstrcpy(out, "aaa");
1286 count = PathCommonPrefixA(path1, path2, out);
1287 ok(count == 6, "Expected 6, got %i\n", count);
1288 ok(!lstrcmp(path1, "C:\\one\\two"), "Expected C:\\one\\two, got %s\n", path1);
1289 ok(!lstrcmp(path2, "C:\\one\\three"), "Expected C:\\one\\three, got %s\n", path2);
1290 ok(!lstrcmp(out, "C:\\one"), "Expected C:\\one, got %s\n", out);
1291 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1292
1293 /* try . prefix */
1294 SetLastError(0xdeadbeef);
1295 lstrcpy(path1, "one\\.two");
1296 lstrcpy(path2, "one\\.three");
1297 lstrcpy(out, "aaa");
1298 count = PathCommonPrefixA(path1, path2, out);
1299 ok(count == 3, "Expected 3, got %i\n", count);
1300 ok(!lstrcmp(path1, "one\\.two"), "Expected one\\.two, got %s\n", path1);
1301 ok(!lstrcmp(path2, "one\\.three"), "Expected one\\.three, got %s\n", path2);
1302 ok(!lstrcmp(out, "one"), "Expected one, got %s\n", out);
1303 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1304
1305 /* try .. prefix */
1306 SetLastError(0xdeadbeef);
1307 lstrcpy(path1, "one\\..two");
1308 lstrcpy(path2, "one\\..three");
1309 lstrcpy(out, "aaa");
1310 count = PathCommonPrefixA(path1, path2, out);
1311 ok(count == 3, "Expected 3, got %i\n", count);
1312 ok(!lstrcmp(path1, "one\\..two"), "Expected one\\..two, got %s\n", path1);
1313 ok(!lstrcmp(path2, "one\\..three"), "Expected one\\..three, got %s\n", path2);
1314 ok(!lstrcmp(out, "one"), "Expected one, got %s\n", out);
1315 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1316
1317 /* try ... prefix */
1318 SetLastError(0xdeadbeef);
1319 lstrcpy(path1, "one\\...two");
1320 lstrcpy(path2, "one\\...three");
1321 lstrcpy(out, "aaa");
1322 count = PathCommonPrefixA(path1, path2, out);
1323 ok(count == 3, "Expected 3, got %i\n", count);
1324 ok(!lstrcmp(path1, "one\\...two"), "Expected one\\...two, got %s\n", path1);
1325 ok(!lstrcmp(path2, "one\\...three"), "Expected one\\...three, got %s\n", path2);
1326 ok(!lstrcmp(out, "one"), "Expected one, got %s\n", out);
1327 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1328
1329 /* try .\ prefix */
1330 SetLastError(0xdeadbeef);
1331 lstrcpy(path1, "one\\.\\two");
1332 lstrcpy(path2, "one\\.\\three");
1333 lstrcpy(out, "aaa");
1334 count = PathCommonPrefixA(path1, path2, out);
1335 ok(count == 5, "Expected 5, got %i\n", count);
1336 ok(!lstrcmp(path1, "one\\.\\two"), "Expected one\\.\\two, got %s\n", path1);
1337 ok(!lstrcmp(path2, "one\\.\\three"), "Expected one\\.\\three, got %s\n", path2);
1338 ok(!lstrcmp(out, "one\\."), "Expected one\\., got %s\n", out);
1339 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1340
1341 /* try ..\ prefix */
1342 SetLastError(0xdeadbeef);
1343 lstrcpy(path1, "one\\..\\two");
1344 lstrcpy(path2, "one\\..\\three");
1345 lstrcpy(out, "aaa");
1346 count = PathCommonPrefixA(path1, path2, out);
1347 ok(count == 6, "Expected 6, got %i\n", count);
1348 ok(!lstrcmp(path1, "one\\..\\two"), "Expected one\\..\\two, got %s\n", path1);
1349 ok(!lstrcmp(path2, "one\\..\\three"), "Expected one\\..\\three, got %s\n", path2);
1350 ok(!lstrcmp(out, "one\\.."), "Expected one\\.., got %s\n", out);
1351 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1352
1353 /* try ...\\ prefix */
1354 SetLastError(0xdeadbeef);
1355 lstrcpy(path1, "one\\...\\two");
1356 lstrcpy(path2, "one\\...\\three");
1357 lstrcpy(out, "aaa");
1358 count = PathCommonPrefixA(path1, path2, out);
1359 ok(count == 7, "Expected 7, got %i\n", count);
1360 ok(!lstrcmp(path1, "one\\...\\two"), "Expected one\\...\\two, got %s\n", path1);
1361 ok(!lstrcmp(path2, "one\\...\\three"), "Expected one\\...\\three, got %s\n", path2);
1362 ok(!lstrcmp(out, "one\\..."), "Expected one\\..., got %s\n", out);
1363 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1364
1365 /* try prefix that is not an msdn labeled prefix type */
1366 SetLastError(0xdeadbeef);
1367 lstrcpy(path1, "same");
1368 lstrcpy(path2, "same");
1369 lstrcpy(out, "aaa");
1370 count = PathCommonPrefixA(path1, path2, out);
1371 ok(count == 4, "Expected 4, got %i\n", count);
1372 ok(!lstrcmp(path1, "same"), "Expected same, got %s\n", path1);
1373 ok(!lstrcmp(path2, "same"), "Expected same, got %s\n", path2);
1374 ok(!lstrcmp(out, "same"), "Expected same, got %s\n", out);
1375 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1376
1377 /* try . after directory */
1378 SetLastError(0xdeadbeef);
1379 lstrcpy(path1, "one\\mid.\\two");
1380 lstrcpy(path2, "one\\mid.\\three");
1381 lstrcpy(out, "aaa");
1382 count = PathCommonPrefixA(path1, path2, out);
1383 ok(count == 8, "Expected 8, got %i\n", count);
1384 ok(!lstrcmp(path1, "one\\mid.\\two"), "Expected one\\mid.\\two, got %s\n", path1);
1385 ok(!lstrcmp(path2, "one\\mid.\\three"), "Expected one\\mid.\\three, got %s\n", path2);
1386 ok(!lstrcmp(out, "one\\mid."), "Expected one\\mid., got %s\n", out);
1387 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1388
1389 /* try . in the middle of a directory */
1390 SetLastError(0xdeadbeef);
1391 lstrcpy(path1, "one\\mid.end\\two");
1392 lstrcpy(path2, "one\\mid.end\\three");
1393 lstrcpy(out, "aaa");
1394 count = PathCommonPrefixA(path1, path2, out);
1395 ok(count == 11, "Expected 11, got %i\n", count);
1396 ok(!lstrcmp(path1, "one\\mid.end\\two"), "Expected one\\mid.end\\two, got %s\n", path1);
1397 ok(!lstrcmp(path2, "one\\mid.end\\three"), "Expected one\\mid.end\\three, got %s\n", path2);
1398 ok(!lstrcmp(out, "one\\mid.end"), "Expected one\\mid.end, got %s\n", out);
1399 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1400
1401 /* try comparing a .. with the expanded path */
1402 SetLastError(0xdeadbeef);
1403 lstrcpy(path1, "one\\..\\two");
1404 lstrcpy(path2, "two");
1405 lstrcpy(out, "aaa");
1406 count = PathCommonPrefixA(path1, path2, out);
1407 ok(count == 0, "Expected 0, got %i\n", count);
1408 ok(!lstrcmp(path1, "one\\..\\two"), "Expected one\\..\\two, got %s\n", path1);
1409 ok(!lstrcmp(path2, "two"), "Expected two, got %s\n", path2);
1410 ok(lstrlen(out) == 0, "Expected 0 length out, got %i\n", lstrlen(out));
1411 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1412 }
1413
1414 static void test_PathUnquoteSpaces(void)
1415 {
1416 int i;
1417 for(i = 0; i < sizeof(TEST_PATH_UNQUOTE_SPACES) / sizeof(TEST_PATH_UNQUOTE_SPACES[0]); i++)
1418 {
1419 char *path = strdupA(TEST_PATH_UNQUOTE_SPACES[i].path);
1420 WCHAR *pathW = GetWideString(TEST_PATH_UNQUOTE_SPACES[i].path);
1421 WCHAR *resultW = GetWideString(TEST_PATH_UNQUOTE_SPACES[i].result);
1422
1423 PathUnquoteSpacesA(path);
1424 ok(!strcmp(path, TEST_PATH_UNQUOTE_SPACES[i].result), "%s (A): got %s expected %s\n",
1425 TEST_PATH_UNQUOTE_SPACES[i].path, path,
1426 TEST_PATH_UNQUOTE_SPACES[i].result);
1427
1428 PathUnquoteSpacesW(pathW);
1429 ok(!lstrcmpW(pathW, resultW), "%s (W): strings differ\n",
1430 TEST_PATH_UNQUOTE_SPACES[i].path);
1431 FreeWideString(pathW);
1432 FreeWideString(resultW);
1433 HeapFree(GetProcessHeap(), 0, path);
1434 }
1435 }
1436
1437 static void test_PathGetDriveNumber(void)
1438 {
1439 static const CHAR test1A[] = "a:\\test.file";
1440 static const CHAR test2A[] = "file:////b:\\test.file";
1441 static const CHAR test3A[] = "file:///c:\\test.file";
1442 static const CHAR test4A[] = "file:\\\\c:\\test.file";
1443 int ret;
1444
1445 SetLastError(0xdeadbeef);
1446 ret = PathGetDriveNumberA(NULL);
1447 ok(ret == -1, "got %d\n", ret);
1448 ok(GetLastError() == 0xdeadbeef, "got %d\n", GetLastError());
1449
1450 ret = PathGetDriveNumberA(test1A);
1451 ok(ret == 0, "got %d\n", ret);
1452 ret = PathGetDriveNumberA(test2A);
1453 ok(ret == -1, "got %d\n", ret);
1454 ret = PathGetDriveNumberA(test3A);
1455 ok(ret == -1, "got %d\n", ret);
1456 ret = PathGetDriveNumberA(test4A);
1457 ok(ret == -1, "got %d\n", ret);
1458 }
1459
1460 /* ################ */
1461
1462 START_TEST(path)
1463 {
1464 HMODULE hShlwapi = GetModuleHandleA("shlwapi.dll");
1465
1466 /* SHCreateStreamOnFileEx was introduced in shlwapi v6.0 */
1467 if(!GetProcAddress(hShlwapi, "SHCreateStreamOnFileEx")){
1468 win_skip("Too old shlwapi version\n");
1469 return;
1470 }
1471
1472 pPathCreateFromUrlA = (void*)GetProcAddress(hShlwapi, "PathCreateFromUrlA");
1473 pPathCreateFromUrlW = (void*)GetProcAddress(hShlwapi, "PathCreateFromUrlW");
1474 pPathCreateFromUrlAlloc = (void*)GetProcAddress(hShlwapi, "PathCreateFromUrlAlloc");
1475 pPathCombineW = (void*)GetProcAddress(hShlwapi, "PathCombineW");
1476 pPathIsValidCharA = (void*)GetProcAddress(hShlwapi, (LPSTR)455);
1477 pPathIsValidCharW = (void*)GetProcAddress(hShlwapi, (LPSTR)456);
1478 pPathAppendA = (void*)GetProcAddress(hShlwapi, "PathAppendA");
1479
1480 test_PathSearchAndQualify();
1481 test_PathCreateFromUrl();
1482 test_PathIsUrl();
1483
1484 test_PathAddBackslash();
1485 test_PathMakePretty();
1486 test_PathMatchSpec();
1487
1488 test_PathIsValidCharA();
1489 test_PathIsValidCharW();
1490
1491 test_PathCombineW();
1492 test_PathCombineA();
1493 test_PathAppendA();
1494 test_PathCanonicalizeA();
1495 test_PathFindExtensionA();
1496 test_PathBuildRootA();
1497 test_PathCommonPrefixA();
1498 test_PathUnquoteSpaces();
1499 test_PathGetDriveNumber();
1500 }