push 92ef5b88da02911741c0a2f56030fd2e20189321
[wine/hacks.git] / dlls / shlwapi / tests / path.c
blob7eb02b2c42fa56a4d9a6ed123efc91f2cd966dfd
1 /* Unit test suite for Path functions
3 * Copyright 2002 Matthew Mastracci
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 #include <assert.h>
21 #include <stdarg.h>
22 #include <stdio.h>
24 #include "wine/test.h"
25 #include "windef.h"
26 #include "winbase.h"
27 #include "winreg.h"
28 #include "shlwapi.h"
29 #include "wininet.h"
31 static HMODULE hShlwapi;
32 static HRESULT (WINAPI *pPathIsValidCharA)(char,DWORD);
33 static HRESULT (WINAPI *pPathIsValidCharW)(WCHAR,DWORD);
34 static LPWSTR (WINAPI *pPathCombineW)(LPWSTR, LPCWSTR, LPCWSTR);
36 const char* TEST_URL_1 = "http://www.winehq.org/tests?date=10/10/1923";
37 const char* TEST_URL_2 = "http://localhost:8080/tests%2e.html?date=Mon%2010/10/1923";
38 const char* TEST_URL_3 = "http://foo:bar@localhost:21/internal.php?query=x&return=y";
40 typedef struct _TEST_URL_CANONICALIZE {
41 const char *url;
42 DWORD flags;
43 HRESULT expectret;
44 const char *expecturl;
45 } TEST_URL_CANONICALIZE;
47 const TEST_URL_CANONICALIZE TEST_CANONICALIZE[] = {
48 /*FIXME {"http://www.winehq.org/tests/../tests/../..", 0, S_OK, "http://www.winehq.org/"},*/
49 {"http://www.winehq.org/tests/../tests", 0, S_OK, "http://www.winehq.org/tests"},
50 {"http://www.winehq.org/tests\n", URL_WININET_COMPATIBILITY|URL_ESCAPE_SPACES_ONLY|URL_ESCAPE_UNSAFE, S_OK, "http://www.winehq.org/tests"},
51 {"http://www.winehq.org/tests\r", URL_WININET_COMPATIBILITY|URL_ESCAPE_SPACES_ONLY|URL_ESCAPE_UNSAFE, S_OK, "http://www.winehq.org/tests"},
52 {"http://www.winehq.org/tests\r", 0, S_OK, "http://www.winehq.org/tests"},
53 {"http://www.winehq.org/tests\r", URL_DONT_SIMPLIFY, S_OK, "http://www.winehq.org/tests"},
54 {"http://www.winehq.org/tests/../tests/", 0, S_OK, "http://www.winehq.org/tests/"},
55 {"http://www.winehq.org/tests/../tests/..", 0, S_OK, "http://www.winehq.org/"},
56 {"http://www.winehq.org/tests/../tests/../", 0, S_OK, "http://www.winehq.org/"},
57 {"http://www.winehq.org/tests/..", 0, S_OK, "http://www.winehq.org/"},
58 {"http://www.winehq.org/tests/../", 0, S_OK, "http://www.winehq.org/"},
59 {"http://www.winehq.org/tests/..?query=x&return=y", 0, S_OK, "http://www.winehq.org/?query=x&return=y"},
60 {"http://www.winehq.org/tests/../?query=x&return=y", 0, S_OK, "http://www.winehq.org/?query=x&return=y"},
61 {"http://www.winehq.org/tests/..#example", 0, S_OK, "http://www.winehq.org/#example"},
62 {"http://www.winehq.org/tests/../#example", 0, S_OK, "http://www.winehq.org/#example"},
63 {"http://www.winehq.org/tests\\../#example", 0, S_OK, "http://www.winehq.org/#example"},
64 {"http://www.winehq.org/tests/..\\#example", 0, S_OK, "http://www.winehq.org/#example"},
65 {"http://www.winehq.org\\tests/../#example", 0, S_OK, "http://www.winehq.org/#example"},
66 {"http://www.winehq.org/tests/../#example", URL_DONT_SIMPLIFY, S_OK, "http://www.winehq.org/tests/../#example"},
67 {"http://www.winehq.org/tests/foo bar", URL_ESCAPE_SPACES_ONLY| URL_DONT_ESCAPE_EXTRA_INFO , S_OK, "http://www.winehq.org/tests/foo%20bar"},
68 {"http://www.winehq.org/tests/foo%20bar", URL_UNESCAPE , S_OK, "http://www.winehq.org/tests/foo bar"},
69 {"file:///c:/tests/foo%20bar", URL_UNESCAPE , S_OK, "file:///c:/tests/foo bar"},
70 {"file:///c:/tests\\foo%20bar", URL_UNESCAPE , S_OK, "file:///c:/tests/foo bar"},
71 {"file:///c:/tests/foo%20bar", 0, S_OK, "file:///c:/tests/foo%20bar"},
72 {"file:///c:/tests/foo%20bar", URL_FILE_USE_PATHURL, S_OK, "file://c:\\tests\\foo bar"},
73 {"file://c:/tests/../tests/foo%20bar", URL_FILE_USE_PATHURL, S_OK, "file://c:\\tests\\foo bar"},
74 {"file://c:/tests\\../tests/foo%20bar", URL_FILE_USE_PATHURL, S_OK, "file://c:\\tests\\foo bar"},
75 {"file://c:/tests/foo%20bar", URL_FILE_USE_PATHURL, S_OK, "file://c:\\tests\\foo bar"},
76 {"file:///c://tests/foo%20bar", URL_FILE_USE_PATHURL, S_OK, "file://c:\\\\tests\\foo bar"},
77 {"file:///c:\\tests\\foo bar", 0, S_OK, "file:///c:/tests/foo bar"},
78 {"file:///c:\\tests\\foo bar", URL_DONT_SIMPLIFY, S_OK, "file:///c:/tests/foo bar"},
79 {"http://www.winehq.org/site/about", URL_FILE_USE_PATHURL, S_OK, "http://www.winehq.org/site/about"},
80 {"file_://www.winehq.org/site/about", URL_FILE_USE_PATHURL, S_OK, "file_://www.winehq.org/site/about"},
81 {"c:\\dir\\file", 0, S_OK, "file:///c:/dir/file"},
82 {"file:///c:\\dir\\file", 0, S_OK, "file:///c:/dir/file"},
83 {"c:dir\\file", 0, S_OK, "file:///c:dir/file"},
84 {"c:\\tests\\foo bar", URL_FILE_USE_PATHURL, S_OK, "file://c:\\tests\\foo bar"},
85 {"c:\\tests\\foo bar", 0, S_OK, "file:///c:/tests/foo%20bar"},
86 {"A", 0, S_OK, "A"},
87 {"", 0, S_OK, ""}
90 typedef struct _TEST_URL_ESCAPE {
91 const char *url;
92 DWORD flags;
93 DWORD expectescaped;
94 HRESULT expectret;
95 const char *expecturl;
96 } TEST_URL_ESCAPE;
98 const TEST_URL_ESCAPE TEST_ESCAPE[] = {
99 {"http://www.winehq.org/tests0", 0, 0, S_OK, "http://www.winehq.org/tests0"},
100 {"http://www.winehq.org/tests1\n", 0, 0, S_OK, "http://www.winehq.org/tests1%0A"},
101 {"http://www.winehq.org/tests2\r", 0, 0, S_OK, "http://www.winehq.org/tests2%0D"},
102 {"http://www.winehq.org/tests3\r", URL_ESCAPE_SPACES_ONLY|URL_ESCAPE_UNSAFE, 0, S_OK, "http://www.winehq.org/tests3\r"},
103 {"http://www.winehq.org/tests4\r", URL_ESCAPE_SPACES_ONLY, 0, S_OK, "http://www.winehq.org/tests4\r"},
104 {"http://www.winehq.org/tests5\r", URL_WININET_COMPATIBILITY|URL_ESCAPE_SPACES_ONLY, 0, S_OK, "http://www.winehq.org/tests5\r"},
105 {"/direct/swhelp/series6/6.2i_latestservicepack.dat\r", URL_ESCAPE_SPACES_ONLY, 0, S_OK, "/direct/swhelp/series6/6.2i_latestservicepack.dat\r"},
107 {"file://////foo/bar\\baz", 0, 0, S_OK, "file://foo/bar/baz"},
108 {"file://///foo/bar\\baz", 0, 0, S_OK, "file://foo/bar/baz"},
109 {"file:////foo/bar\\baz", 0, 0, S_OK, "file://foo/bar/baz"},
110 {"file:///localhost/foo/bar\\baz", 0, 0, S_OK, "file:///localhost/foo/bar/baz"},
111 {"file:///foo/bar\\baz", 0, 0, S_OK, "file:///foo/bar/baz"},
112 {"file://loCalHost/foo/bar\\baz", 0, 0, S_OK, "file:///foo/bar/baz"},
113 {"file://foo/bar\\baz", 0, 0, S_OK, "file://foo/bar/baz"},
114 {"file:/localhost/foo/bar\\baz", 0, 0, S_OK, "file:///localhost/foo/bar/baz"},
115 {"file:/foo/bar\\baz", 0, 0, S_OK, "file:///foo/bar/baz"},
116 {"file:foo/bar\\baz", 0, 0, S_OK, "file:foo/bar/baz"},
117 {"file:\\foo/bar\\baz", 0, 0, S_OK, "file:///foo/bar/baz"},
118 {"file:\\\\foo/bar\\baz", 0, 0, S_OK, "file://foo/bar/baz"},
119 {"file:\\\\\\foo/bar\\baz", 0, 0, S_OK, "file:///foo/bar/baz"},
120 {"file:\\\\localhost\\foo/bar\\baz", 0, 0, S_OK, "file:///foo/bar/baz"},
121 {"file:///f oo/b?a r\\baz", 0, 0, S_OK, "file:///f%20oo/b?a r\\baz"},
122 {"file:///foo/b#a r\\baz", 0, 0, S_OK, "file:///foo/b%23a%20r/baz"},
123 {"file:///f o^&`{}|][\"<>\\%o/b#a r\\baz", 0, 0, S_OK, "file:///f%20o%5E%26%60%7B%7D%7C%5D%5B%22%3C%3E/%o/b%23a%20r/baz"},
124 {"file:///f o%o/b?a r\\b%az", URL_ESCAPE_PERCENT, 0, S_OK, "file:///f%20o%25o/b?a r\\b%az"},
125 {"file:/foo/bar\\baz", URL_ESCAPE_SEGMENT_ONLY, 0, S_OK, "file:%2Ffoo%2Fbar%5Cbaz"},
127 {"foo/b%ar\\ba?z\\", URL_ESCAPE_SEGMENT_ONLY, 0, S_OK, "foo%2Fb%ar%5Cba%3Fz%5C"},
128 {"foo/b%ar\\ba?z\\", URL_ESCAPE_PERCENT | URL_ESCAPE_SEGMENT_ONLY, 0, S_OK, "foo%2Fb%25ar%5Cba%3Fz%5C"},
129 {"foo/bar\\ba?z\\", 0, 0, S_OK, "foo/bar%5Cba?z\\"},
130 {"/foo/bar\\ba?z\\", 0, 0, S_OK, "/foo/bar%5Cba?z\\"},
131 {"/foo/bar\\ba#z\\", 0, 0, S_OK, "/foo/bar%5Cba#z\\"},
132 {"/foo/%5C", 0, 0, S_OK, "/foo/%5C"},
133 {"/foo/%5C", URL_ESCAPE_PERCENT, 0, S_OK, "/foo/%255C"},
135 {"http://////foo/bar\\baz", 0, 0, S_OK, "http://////foo/bar/baz"},
136 {"http://///foo/bar\\baz", 0, 0, S_OK, "http://///foo/bar/baz"},
137 {"http:////foo/bar\\baz", 0, 0, S_OK, "http:////foo/bar/baz"},
138 {"http:///foo/bar\\baz", 0, 0, S_OK, "http:///foo/bar/baz"},
139 {"http://localhost/foo/bar\\baz", 0, 0, S_OK, "http://localhost/foo/bar/baz"},
140 {"http://foo/bar\\baz", 0, 0, S_OK, "http://foo/bar/baz"},
141 {"http:/foo/bar\\baz", 0, 0, S_OK, "http:/foo/bar/baz"},
142 {"http:foo/bar\\ba?z\\", 0, 0, S_OK, "http:foo%2Fbar%2Fba?z\\"},
143 {"http:foo/bar\\ba#z\\", 0, 0, S_OK, "http:foo%2Fbar%2Fba#z\\"},
144 {"http:\\foo/bar\\baz", 0, 0, S_OK, "http:/foo/bar/baz"},
145 {"http:\\\\foo/bar\\baz", 0, 0, S_OK, "http://foo/bar/baz"},
146 {"http:\\\\\\foo/bar\\baz", 0, 0, S_OK, "http:///foo/bar/baz"},
147 {"http:\\\\\\\\foo/bar\\baz", 0, 0, S_OK, "http:////foo/bar/baz"},
148 {"http:/fo ?o/b ar\\baz", 0, 0, S_OK, "http:/fo%20?o/b ar\\baz"},
149 {"http:fo ?o/b ar\\baz", 0, 0, S_OK, "http:fo%20?o/b ar\\baz"},
150 {"http:/foo/bar\\baz", URL_ESCAPE_SEGMENT_ONLY, 0, S_OK, "http:%2Ffoo%2Fbar%5Cbaz"},
152 {"https://foo/bar\\baz", 0, 0, S_OK, "https://foo/bar/baz"},
153 {"https:/foo/bar\\baz", 0, 0, S_OK, "https:/foo/bar/baz"},
154 {"https:\\foo/bar\\baz", 0, 0, S_OK, "https:/foo/bar/baz"},
156 {"foo:////foo/bar\\baz", 0, 0, S_OK, "foo:////foo/bar%5Cbaz"},
157 {"foo:///foo/bar\\baz", 0, 0, S_OK, "foo:///foo/bar%5Cbaz"},
158 {"foo://localhost/foo/bar\\baz", 0, 0, S_OK, "foo://localhost/foo/bar%5Cbaz"},
159 {"foo://foo/bar\\baz", 0, 0, S_OK, "foo://foo/bar%5Cbaz"},
160 {"foo:/foo/bar\\baz", 0, 0, S_OK, "foo:/foo/bar%5Cbaz"},
161 {"foo:foo/bar\\baz", 0, 0, S_OK, "foo:foo%2Fbar%5Cbaz"},
162 {"foo:\\foo/bar\\baz", 0, 0, S_OK, "foo:%5Cfoo%2Fbar%5Cbaz"},
163 {"foo:/foo/bar\\ba?\\z", 0, 0, S_OK, "foo:/foo/bar%5Cba?\\z"},
164 {"foo:/foo/bar\\ba#\\z", 0, 0, S_OK, "foo:/foo/bar%5Cba#\\z"},
166 {"mailto:/fo/o@b\\%a?\\r.b#\\az", 0, 0, S_OK, "mailto:%2Ffo%2Fo@b%5C%a%3F%5Cr.b%23%5Caz"},
167 {"mailto:fo/o@b\\%a?\\r.b#\\az", 0, 0, S_OK, "mailto:fo%2Fo@b%5C%a%3F%5Cr.b%23%5Caz"},
168 {"mailto:fo/o@b\\%a?\\r.b#\\az", URL_ESCAPE_PERCENT, 0, S_OK, "mailto:fo%2Fo@b%5C%25a%3F%5Cr.b%23%5Caz"},
170 {"ftp:fo/o@bar.baz/foo/bar", 0, 0, S_OK, "ftp:fo%2Fo@bar.baz%2Ffoo%2Fbar"},
171 {"ftp:/fo/o@bar.baz/foo/bar", 0, 0, S_OK, "ftp:/fo/o@bar.baz/foo/bar"},
172 {"ftp://fo/o@bar.baz/fo?o\\bar", 0, 0, S_OK, "ftp://fo/o@bar.baz/fo?o\\bar"},
173 {"ftp://fo/o@bar.baz/fo#o\\bar", 0, 0, S_OK, "ftp://fo/o@bar.baz/fo#o\\bar"},
174 {"ftp://localhost/o@bar.baz/fo#o\\bar", 0, 0, S_OK, "ftp://localhost/o@bar.baz/fo#o\\bar"},
175 {"ftp:///fo/o@bar.baz/foo/bar", 0, 0, S_OK, "ftp:///fo/o@bar.baz/foo/bar"},
176 {"ftp:////fo/o@bar.baz/foo/bar", 0, 0, S_OK, "ftp:////fo/o@bar.baz/foo/bar"}
179 typedef struct _TEST_URL_COMBINE {
180 const char *url1;
181 const char *url2;
182 DWORD flags;
183 HRESULT expectret;
184 const char *expecturl;
185 } TEST_URL_COMBINE;
187 const TEST_URL_COMBINE TEST_COMBINE[] = {
188 {"http://www.winehq.org/tests", "tests1", 0, S_OK, "http://www.winehq.org/tests1"},
189 {"http://www.%77inehq.org/tests", "tests1", 0, S_OK, "http://www.%77inehq.org/tests1"},
190 /*FIXME {"http://www.winehq.org/tests", "../tests2", 0, S_OK, "http://www.winehq.org/tests2"},*/
191 {"http://www.winehq.org/tests/", "../tests3", 0, S_OK, "http://www.winehq.org/tests3"},
192 {"http://www.winehq.org/tests/test1", "test2", 0, S_OK, "http://www.winehq.org/tests/test2"},
193 {"http://www.winehq.org/tests/../tests", "tests4", 0, S_OK, "http://www.winehq.org/tests4"},
194 {"http://www.winehq.org/tests/../tests/", "tests5", 0, S_OK, "http://www.winehq.org/tests/tests5"},
195 {"http://www.winehq.org/tests/../tests/", "/tests6/..", 0, S_OK, "http://www.winehq.org/"},
196 {"http://www.winehq.org/tests/../tests/..", "tests7/..", 0, S_OK, "http://www.winehq.org/"},
197 {"http://www.winehq.org/tests/?query=x&return=y", "tests8", 0, S_OK, "http://www.winehq.org/tests/tests8"},
198 {"http://www.winehq.org/tests/#example", "tests9", 0, S_OK, "http://www.winehq.org/tests/tests9"},
199 {"http://www.winehq.org/tests/../tests/", "/tests10/..", URL_DONT_SIMPLIFY, S_OK, "http://www.winehq.org/tests10/.."},
200 {"http://www.winehq.org/tests/../", "tests11", URL_DONT_SIMPLIFY, S_OK, "http://www.winehq.org/tests/../tests11"},
201 {"file:///C:\\dir\\file.txt", "test.txt", 0, S_OK, "file:///C:/dir/test.txt"},
202 {"http://www.winehq.org/test/", "test%20file.txt", 0, S_OK, "http://www.winehq.org/test/test%20file.txt"},
203 {"http://www.winehq.org/test/", "test%20file.txt", URL_FILE_USE_PATHURL, S_OK, "http://www.winehq.org/test/test%20file.txt"},
204 {"http://www.winehq.org%2ftest/", "test%20file.txt", URL_FILE_USE_PATHURL, S_OK, "http://www.winehq.org%2ftest/test%20file.txt"},
205 {"xxx:@MSITStore:file.chm/file.html", "dir/file", 0, S_OK, "xxx:dir/file"},
206 {"mk:@MSITStore:file.chm::/file.html", "/dir/file", 0, S_OK, "mk:@MSITStore:file.chm::/dir/file"},
207 {"mk:@MSITStore:file.chm::/file.html", "mk:@MSITStore:file.chm::/dir/file", 0, S_OK, "mk:@MSITStore:file.chm::/dir/file"},
208 {"foo:today", "foo:calendar", 0, S_OK, "foo:calendar"},
209 {"foo:today", "bar:calendar", 0, S_OK, "bar:calendar"},
210 {"foo:/today", "foo:calendar", 0, S_OK, "foo:/calendar"},
211 {"foo:/today/", "foo:calendar", 0, S_OK, "foo:/today/calendar"},
214 struct {
215 const char *path;
216 const char *url;
217 DWORD ret;
218 } TEST_URLFROMPATH [] = {
219 {"foo", "file:foo", S_OK},
220 {"foo\\bar", "file:foo/bar", S_OK},
221 {"\\foo\\bar", "file:///foo/bar", S_OK},
222 {"c:\\foo\\bar", "file:///c:/foo/bar", S_OK},
223 {"c:foo\\bar", "file:///c:foo/bar", S_OK},
224 {"c:\\foo/b a%r", "file:///c:/foo/b%20a%25r", S_OK},
225 {"c:\\foo\\foo bar", "file:///c:/foo/foo%20bar", S_OK},
226 #if 0
227 /* The following test fails on native shlwapi as distributed with Win95/98.
228 * Wine matches the behaviour of later versions.
230 {"xx:c:\\foo\\bar", "xx:c:\\foo\\bar", S_FALSE}
231 #endif
234 struct {
235 const char *url;
236 const char *path;
237 DWORD ret;
238 } TEST_PATHFROMURL[] = {
239 {"file:///c:/foo/ba%5Cr", "c:\\foo\\ba\\r", S_OK},
240 {"file:///c:/foo/../ba%5Cr", "c:\\foo\\..\\ba\\r", S_OK},
241 {"file:///host/c:/foo/bar", "\\host\\c:\\foo\\bar", S_OK},
242 {"file://host/c:/foo/bar", "\\\\hostc:\\foo\\bar", S_OK},
243 {"file://host/c:/foo/bar", "\\\\hostc:\\foo\\bar", S_OK},
244 {"file:\\\\host\\c:\\foo\\bar", "\\\\hostc:\\foo\\bar", S_OK},
245 {"file:\\\\host\\ca\\foo\\bar", "\\\\host\\ca\\foo\\bar", S_OK},
246 {"file:\\\\host\\c|\\foo\\bar", "\\\\hostc|\\foo\\bar", S_OK},
247 {"file:\\%5Chost\\c:\\foo\\bar", "\\\\host\\c:\\foo\\bar", S_OK},
248 {"file:\\\\host\\cx:\\foo\\bar", "\\\\host\\cx:\\foo\\bar", S_OK},
249 {"file://c:/foo/bar", "c:\\foo\\bar", S_OK},
250 {"file://c:/d:/foo/bar", "c:\\d:\\foo\\bar", S_OK},
251 {"file://c|/d|/foo/bar", "c:\\d|\\foo\\bar", S_OK},
252 {"file://host/foo/bar", "\\\\host\\foo\\bar", S_OK},
253 {"file:/foo/bar", "\\foo\\bar", S_OK},
254 {"file:/foo/bar/", "\\foo\\bar\\", S_OK},
255 {"file:foo/bar", "foo\\bar", S_OK},
256 {"file:c:/foo/bar", "c:\\foo\\bar", S_OK},
257 {"file:c|/foo/bar", "c:\\foo\\bar", S_OK},
258 {"file:cx|/foo/bar", "cx|\\foo\\bar", S_OK},
259 {"file:////c:/foo/bar", "c:\\foo\\bar", S_OK},
260 /* {"file:////c:/foo/foo%20bar", "c:\\foo\\foo%20bar", S_OK},*/
262 {"c:\\foo\\bar", NULL, E_INVALIDARG},
263 {"foo/bar", NULL, E_INVALIDARG},
264 {"http://foo/bar", NULL, E_INVALIDARG},
268 struct {
269 char url[30];
270 const char *expect;
271 } TEST_URL_UNESCAPE[] = {
272 {"file://foo/bar", "file://foo/bar"},
273 {"file://fo%20o%5Ca/bar", "file://fo o\\a/bar"}
277 struct {
278 const char *path;
279 BOOL expect;
280 } TEST_PATH_IS_URL[] = {
281 {"http://foo/bar", TRUE},
282 {"c:\\foo\\bar", FALSE},
283 {"foo://foo/bar", TRUE},
284 {"foo\\bar", FALSE},
285 {"foo.bar", FALSE},
286 {"bogusscheme:", TRUE},
287 {"http:partial", TRUE}
290 struct {
291 const char *url;
292 BOOL expectOpaque;
293 BOOL expectFile;
294 } TEST_URLIS_ATTRIBS[] = {
295 { "ftp:", FALSE, FALSE },
296 { "http:", FALSE, FALSE },
297 { "gopher:", FALSE, FALSE },
298 { "mailto:", TRUE, FALSE },
299 { "news:", FALSE, FALSE },
300 { "nntp:", FALSE, FALSE },
301 { "telnet:", FALSE, FALSE },
302 { "wais:", FALSE, FALSE },
303 { "file:", FALSE, TRUE },
304 { "mk:", FALSE, FALSE },
305 { "https:", FALSE, FALSE },
306 { "shell:", TRUE, FALSE },
307 { "https:", FALSE, FALSE },
308 { "snews:", FALSE, FALSE },
309 { "local:", FALSE, FALSE },
310 { "javascript:", TRUE, FALSE },
311 { "vbscript:", TRUE, FALSE },
312 { "about:", TRUE, FALSE },
313 { "res:", FALSE, FALSE },
314 { "bogusscheme:", FALSE, FALSE },
315 { "file:\\\\e:\\b\\c", FALSE, TRUE },
316 { "file://e:/b/c", FALSE, TRUE },
317 { "http:partial", FALSE, FALSE },
318 { "mailto://www.winehq.org/test.html", TRUE, FALSE },
319 { "file:partial", FALSE, TRUE }
322 struct {
323 const char *path;
324 const char *result;
325 } TEST_PATH_UNQUOTE_SPACES[] = {
326 { "abcdef", "abcdef" },
327 { "\"abcdef\"", "abcdef" },
328 { "\"abcdef", "\"abcdef" },
329 { "abcdef\"", "abcdef\"" },
330 { "\"\"abcdef\"\"", "\"abcdef\"" },
331 { "abc\"def", "abc\"def" },
332 { "\"abc\"def", "\"abc\"def" },
333 { "\"abc\"def\"", "abc\"def" },
334 { "\'abcdef\'", "\'abcdef\'" },
335 { "\"\"", "" },
336 { "\"", "" }
339 static LPWSTR GetWideString(const char* szString)
341 LPWSTR wszString = HeapAlloc(GetProcessHeap(), 0, (2*INTERNET_MAX_URL_LENGTH) * sizeof(WCHAR));
343 MultiByteToWideChar(0, 0, szString, -1, wszString, INTERNET_MAX_URL_LENGTH);
345 return wszString;
348 static void FreeWideString(LPWSTR wszString)
350 HeapFree(GetProcessHeap(), 0, wszString);
353 static LPSTR strdupA(LPCSTR p)
355 LPSTR ret;
356 DWORD len = (strlen(p) + 1);
357 ret = HeapAlloc(GetProcessHeap(), 0, len);
358 memcpy(ret, p, len);
359 return ret;
362 static void hash_url(const char* szUrl)
364 LPCSTR szTestUrl = szUrl;
365 LPWSTR wszTestUrl = GetWideString(szTestUrl);
367 DWORD cbSize = sizeof(DWORD);
368 DWORD dwHash1, dwHash2;
369 ok(UrlHashA(szTestUrl, (LPBYTE)&dwHash1, cbSize) == S_OK, "UrlHashA didn't return S_OK\n");
370 ok(UrlHashW(wszTestUrl, (LPBYTE)&dwHash2, cbSize) == S_OK, "UrlHashW didn't return S_OK\n");
372 FreeWideString(wszTestUrl);
374 ok(dwHash1 == dwHash2, "Hashes didn't compare\n");
377 static void test_UrlHash(void)
379 hash_url(TEST_URL_1);
380 hash_url(TEST_URL_2);
381 hash_url(TEST_URL_3);
384 static void test_url_part(const char* szUrl, DWORD dwPart, DWORD dwFlags, const char* szExpected)
386 CHAR szPart[INTERNET_MAX_URL_LENGTH];
387 WCHAR wszPart[INTERNET_MAX_URL_LENGTH];
388 LPWSTR wszUrl = GetWideString(szUrl);
389 LPWSTR wszConvertedPart;
391 DWORD dwSize;
393 dwSize = INTERNET_MAX_URL_LENGTH;
394 ok( UrlGetPartA(szUrl, szPart, &dwSize, dwPart, dwFlags) == S_OK, "UrlGetPartA for \"%s\" part 0x%08x didn't return S_OK but \"%s\"\n", szUrl, dwPart, szPart);
395 dwSize = INTERNET_MAX_URL_LENGTH;
396 ok( UrlGetPartW(wszUrl, wszPart, &dwSize, dwPart, dwFlags) == S_OK, "UrlGetPartW didn't return S_OK\n" );
398 wszConvertedPart = GetWideString(szPart);
400 ok(lstrcmpW(wszPart,wszConvertedPart)==0, "Strings didn't match between ascii and unicode UrlGetPart!\n");
402 FreeWideString(wszUrl);
403 FreeWideString(wszConvertedPart);
405 /* Note that v6.0 and later don't return '?' with the query */
406 ok(strcmp(szPart,szExpected)==0 ||
407 (*szExpected=='?' && !strcmp(szPart,szExpected+1)),
408 "Expected %s, but got %s\n", szExpected, szPart);
411 static void test_UrlGetPart(void)
413 CHAR szPart[INTERNET_MAX_URL_LENGTH];
414 DWORD dwSize;
415 HRESULT res;
417 dwSize = sizeof szPart;
418 szPart[0]='x'; szPart[1]=0;
419 res = UrlGetPartA("hi", szPart, &dwSize, URL_PART_SCHEME, 0);
420 todo_wine {
421 ok (res==S_FALSE, "UrlGetPartA(\"hi\") returned %08X\n", res);
422 ok(szPart[0]==0, "UrlGetPartA(\"hi\") return \"%s\" instead of \"\"\n", szPart);
424 dwSize = sizeof szPart;
425 szPart[0]='x'; szPart[1]=0;
426 res = UrlGetPartA("hi", szPart, &dwSize, URL_PART_QUERY, 0);
427 todo_wine {
428 ok (res==S_FALSE, "UrlGetPartA(\"hi\") returned %08X\n", res);
429 ok(szPart[0]==0, "UrlGetPartA(\"hi\") return \"%s\" instead of \"\"\n", szPart);
432 test_url_part(TEST_URL_3, URL_PART_HOSTNAME, 0, "localhost");
433 test_url_part(TEST_URL_3, URL_PART_PORT, 0, "21");
434 test_url_part(TEST_URL_3, URL_PART_USERNAME, 0, "foo");
435 test_url_part(TEST_URL_3, URL_PART_PASSWORD, 0, "bar");
436 test_url_part(TEST_URL_3, URL_PART_SCHEME, 0, "http");
437 test_url_part(TEST_URL_3, URL_PART_QUERY, 0, "?query=x&return=y");
440 static void test_url_escape(const char *szUrl, DWORD dwFlags, HRESULT dwExpectReturn, const char *szExpectUrl)
442 CHAR szReturnUrl[INTERNET_MAX_URL_LENGTH];
443 DWORD dwEscaped;
444 WCHAR ret_urlW[INTERNET_MAX_URL_LENGTH];
445 WCHAR *urlW, *expected_urlW;
446 dwEscaped=INTERNET_MAX_URL_LENGTH;
448 ok(UrlEscapeA(szUrl, szReturnUrl, &dwEscaped, dwFlags) == dwExpectReturn, "UrlEscapeA didn't return 0x%08x from \"%s\"\n", dwExpectReturn, szUrl);
449 ok(strcmp(szReturnUrl,szExpectUrl)==0, "Expected \"%s\", but got \"%s\" from \"%s\"\n", szExpectUrl, szReturnUrl, szUrl);
451 dwEscaped = INTERNET_MAX_URL_LENGTH;
452 urlW = GetWideString(szUrl);
453 expected_urlW = GetWideString(szExpectUrl);
454 ok(UrlEscapeW(urlW, ret_urlW, &dwEscaped, dwFlags) == dwExpectReturn, "UrlEscapeW didn't return 0x%08x from \"%s\"\n", dwExpectReturn, szUrl);
455 WideCharToMultiByte(CP_ACP,0,ret_urlW,-1,szReturnUrl,INTERNET_MAX_URL_LENGTH,0,0);
456 ok(lstrcmpW(ret_urlW, expected_urlW)==0, "Expected \"%s\", but got \"%s\" from \"%s\" flags %08x\n", szExpectUrl, szReturnUrl, szUrl, dwFlags);
457 FreeWideString(urlW);
458 FreeWideString(expected_urlW);
462 static void test_url_canonicalize(const char *szUrl, DWORD dwFlags, HRESULT dwExpectReturn, const char *szExpectUrl)
464 CHAR szReturnUrl[INTERNET_MAX_URL_LENGTH];
465 WCHAR wszReturnUrl[INTERNET_MAX_URL_LENGTH];
466 LPWSTR wszUrl = GetWideString(szUrl);
467 LPWSTR wszExpectUrl = GetWideString(szExpectUrl);
468 LPWSTR wszConvertedUrl;
470 DWORD dwSize;
472 dwSize = INTERNET_MAX_URL_LENGTH;
473 ok(UrlCanonicalizeA(szUrl, NULL, &dwSize, dwFlags) != dwExpectReturn, "Unexpected return for NULL buffer\n");
474 ok(UrlCanonicalizeA(szUrl, szReturnUrl, &dwSize, dwFlags) == dwExpectReturn, "UrlCanonicalizeA didn't return 0x%08x\n", dwExpectReturn);
475 ok(strcmp(szReturnUrl,szExpectUrl)==0, "UrlCanonicalizeA dwFlags 0x%08x Expected \"%s\", but got \"%s\"\n", dwFlags, szExpectUrl, szReturnUrl);
477 dwSize = INTERNET_MAX_URL_LENGTH;
478 ok(UrlCanonicalizeW(wszUrl, NULL, &dwSize, dwFlags) != dwExpectReturn, "Unexpected return for NULL buffer\n");
479 ok(UrlCanonicalizeW(wszUrl, wszReturnUrl, &dwSize, dwFlags) == dwExpectReturn, "UrlCanonicalizeW didn't return 0x%08x\n", dwExpectReturn);
480 wszConvertedUrl = GetWideString(szReturnUrl);
481 ok(lstrcmpW(wszReturnUrl, wszConvertedUrl)==0, "Strings didn't match between ascii and unicode UrlCanonicalize!\n");
482 FreeWideString(wszConvertedUrl);
485 FreeWideString(wszUrl);
486 FreeWideString(wszExpectUrl);
490 static void test_UrlEscape(void)
492 DWORD size;
493 HRESULT ret;
494 unsigned int i;
496 ret = UrlEscapeA("/woningplan/woonkamer basis.swf", NULL, &size, URL_ESCAPE_SPACES_ONLY);
497 ok(ret == E_INVALIDARG, "got %x, expected %x\n", ret, E_INVALIDARG);
499 for(i=0; i<sizeof(TEST_ESCAPE)/sizeof(TEST_ESCAPE[0]); i++) {
500 test_url_escape(TEST_ESCAPE[i].url, TEST_ESCAPE[i].flags,
501 TEST_ESCAPE[i].expectret, TEST_ESCAPE[i].expecturl);
505 static void test_UrlCanonicalize(void)
507 unsigned int i;
508 CHAR szReturnUrl[INTERNET_MAX_URL_LENGTH];
509 DWORD dwSize;
510 HRESULT hr;
512 for(i=0; i<sizeof(TEST_CANONICALIZE)/sizeof(TEST_CANONICALIZE[0]); i++) {
513 test_url_canonicalize(TEST_CANONICALIZE[i].url, TEST_CANONICALIZE[i].flags,
514 TEST_CANONICALIZE[i].expectret, TEST_CANONICALIZE[i].expecturl);
517 /* move to TEST_CANONICALIZE when fixed */
518 dwSize = sizeof szReturnUrl;
519 /*LimeWire online installer calls this*/
520 hr = UrlCanonicalizeA("/uri-res/N2R?urn:sha1:B3K", szReturnUrl, &dwSize,URL_DONT_ESCAPE_EXTRA_INFO | URL_WININET_COMPATIBILITY /*0x82000000*/);
521 ok(hr==S_OK,"UrlCanonicalizeA returned 0x%08x instead of S_OK\n", hr);
522 todo_wine {
523 ok(strcmp(szReturnUrl,"/uri-res/N2R?urn:sha1:B3K")==0, "UrlCanonicalizeA got \"%s\" instead of \"/uri-res/N2R?urn:sha1:B3K\"\n", szReturnUrl);
527 static void test_url_combine(const char *szUrl1, const char *szUrl2, DWORD dwFlags, HRESULT dwExpectReturn, const char *szExpectUrl)
529 HRESULT hr;
530 CHAR szReturnUrl[INTERNET_MAX_URL_LENGTH];
531 WCHAR wszReturnUrl[INTERNET_MAX_URL_LENGTH];
532 LPWSTR wszUrl1 = GetWideString(szUrl1);
533 LPWSTR wszUrl2 = GetWideString(szUrl2);
534 LPWSTR wszExpectUrl = GetWideString(szExpectUrl);
535 LPWSTR wszConvertedUrl;
537 DWORD dwSize;
538 DWORD dwExpectLen = lstrlen(szExpectUrl);
540 hr = UrlCombineA(szUrl1, szUrl2, NULL, NULL, dwFlags);
541 ok(hr == E_INVALIDARG, "UrlCombineA returned 0x%08x, expected 0x%08x\n", hr, E_INVALIDARG);
543 dwSize = 0;
544 hr = UrlCombineA(szUrl1, szUrl2, NULL, &dwSize, dwFlags);
545 ok(hr == E_POINTER, "Checking length of string, return was 0x%08x, expected 0x%08x\n", hr, E_POINTER);
546 ok(dwSize == dwExpectLen+1, "Got length %d, expected %d\n", dwSize, dwExpectLen+1);
548 dwSize--;
549 hr = UrlCombineA(szUrl1, szUrl2, szReturnUrl, &dwSize, dwFlags);
550 ok(hr == E_POINTER, "UrlCombineA returned 0x%08x, expected 0x%08x\n", hr, E_POINTER);
551 ok(dwSize == dwExpectLen+1, "Got length %d, expected %d\n", dwSize, dwExpectLen+1);
553 hr = UrlCombineA(szUrl1, szUrl2, szReturnUrl, &dwSize, dwFlags);
554 ok(hr == dwExpectReturn, "UrlCombineA returned 0x%08x, expected 0x%08x\n", hr, dwExpectReturn);
555 ok(dwSize == dwExpectLen, "Got length %d, expected %d\n", dwSize, dwExpectLen);
556 if(SUCCEEDED(hr)) {
557 ok(strcmp(szReturnUrl,szExpectUrl)==0, "Expected %s, but got %s\n", szExpectUrl, szReturnUrl);
560 dwSize = 0;
561 hr = UrlCombineW(wszUrl1, wszUrl2, NULL, &dwSize, dwFlags);
562 ok(hr == E_POINTER, "Checking length of string, return was 0x%08x, expected 0x%08x\n", hr, E_POINTER);
563 ok(dwSize == dwExpectLen+1, "Got length %d, expected %d\n", dwSize, dwExpectLen+1);
565 dwSize--;
566 hr = UrlCombineW(wszUrl1, wszUrl2, wszReturnUrl, &dwSize, dwFlags);
567 ok(hr == E_POINTER, "UrlCombineA returned 0x%08x, expected 0x%08x\n", hr, E_POINTER);
568 ok(dwSize == dwExpectLen+1, "Got length %d, expected %d\n", dwSize, dwExpectLen+1);
570 hr = UrlCombineW(wszUrl1, wszUrl2, wszReturnUrl, &dwSize, dwFlags);
571 ok(hr == dwExpectReturn, "UrlCombineW returned 0x%08x, expected 0x%08x\n", hr, dwExpectReturn);
572 ok(dwSize == dwExpectLen, "Got length %d, expected %d\n", dwSize, dwExpectLen);
573 if(SUCCEEDED(hr)) {
574 wszConvertedUrl = GetWideString(szReturnUrl);
575 ok(lstrcmpW(wszReturnUrl, wszConvertedUrl)==0, "Strings didn't match between ascii and unicode UrlCombine!\n");
576 FreeWideString(wszConvertedUrl);
579 FreeWideString(wszUrl1);
580 FreeWideString(wszUrl2);
581 FreeWideString(wszExpectUrl);
584 static void test_UrlCombine(void)
586 unsigned int i;
587 for(i=0; i<sizeof(TEST_COMBINE)/sizeof(TEST_COMBINE[0]); i++) {
588 test_url_combine(TEST_COMBINE[i].url1, TEST_COMBINE[i].url2, TEST_COMBINE[i].flags,
589 TEST_COMBINE[i].expectret, TEST_COMBINE[i].expecturl);
593 static void test_UrlCreateFromPath(void)
595 size_t i;
596 char ret_url[INTERNET_MAX_URL_LENGTH];
597 DWORD len, ret;
598 WCHAR ret_urlW[INTERNET_MAX_URL_LENGTH];
599 WCHAR *pathW, *urlW;
601 for(i = 0; i < sizeof(TEST_URLFROMPATH) / sizeof(TEST_URLFROMPATH[0]); i++) {
602 len = INTERNET_MAX_URL_LENGTH;
603 ret = UrlCreateFromPathA(TEST_URLFROMPATH[i].path, ret_url, &len, 0);
604 ok(ret == TEST_URLFROMPATH[i].ret, "ret %08x from path %s\n", ret, TEST_URLFROMPATH[i].path);
605 ok(!lstrcmpi(ret_url, TEST_URLFROMPATH[i].url), "url %s from path %s\n", ret_url, TEST_URLFROMPATH[i].path);
606 ok(len == strlen(ret_url), "ret len %d from path %s\n", len, TEST_URLFROMPATH[i].path);
608 len = INTERNET_MAX_URL_LENGTH;
609 pathW = GetWideString(TEST_URLFROMPATH[i].path);
610 urlW = GetWideString(TEST_URLFROMPATH[i].url);
611 ret = UrlCreateFromPathW(pathW, ret_urlW, &len, 0);
612 WideCharToMultiByte(CP_ACP, 0, ret_urlW, -1, ret_url, sizeof(ret_url),0,0);
613 ok(ret == TEST_URLFROMPATH[i].ret, "ret %08x from path L\"%s\", expected %08x\n",
614 ret, TEST_URLFROMPATH[i].path, TEST_URLFROMPATH[i].ret);
615 ok(!lstrcmpiW(ret_urlW, urlW), "got %s expected %s from path L\"%s\"\n", ret_url, TEST_URLFROMPATH[i].url, TEST_URLFROMPATH[i].path);
616 ok(len == lstrlenW(ret_urlW), "ret len %d from path L\"%s\"\n", len, TEST_URLFROMPATH[i].path);
617 FreeWideString(urlW);
618 FreeWideString(pathW);
622 static void test_UrlIs(void)
624 BOOL ret;
625 size_t i;
626 WCHAR wurl[80];
628 for(i = 0; i < sizeof(TEST_PATH_IS_URL) / sizeof(TEST_PATH_IS_URL[0]); i++) {
629 MultiByteToWideChar(CP_ACP, 0, TEST_PATH_IS_URL[i].path, -1, wurl, 80);
631 ret = UrlIsA( TEST_PATH_IS_URL[i].path, URLIS_URL );
632 ok( ret == TEST_PATH_IS_URL[i].expect,
633 "returned %d from path %s, expected %d\n", ret, TEST_PATH_IS_URL[i].path,
634 TEST_PATH_IS_URL[i].expect );
636 ret = UrlIsW( wurl, URLIS_URL );
637 ok( ret == TEST_PATH_IS_URL[i].expect,
638 "returned %d from path (UrlIsW) %s, expected %d\n", ret, TEST_PATH_IS_URL[i].path,
639 TEST_PATH_IS_URL[i].expect );
641 for(i = 0; i < sizeof(TEST_URLIS_ATTRIBS) / sizeof(TEST_URLIS_ATTRIBS[0]); i++) {
642 MultiByteToWideChar(CP_ACP, 0, TEST_URLIS_ATTRIBS[i].url, -1, wurl, 80);
644 ret = UrlIsA( TEST_URLIS_ATTRIBS[i].url, URLIS_OPAQUE);
645 ok( ret == TEST_URLIS_ATTRIBS[i].expectOpaque,
646 "returned %d for URLIS_OPAQUE, url \"%s\", expected %d\n", ret, TEST_URLIS_ATTRIBS[i].url,
647 TEST_URLIS_ATTRIBS[i].expectOpaque );
648 ret = UrlIsA( TEST_URLIS_ATTRIBS[i].url, URLIS_FILEURL);
649 ok( ret == TEST_URLIS_ATTRIBS[i].expectFile,
650 "returned %d for URLIS_FILEURL, url \"%s\", expected %d\n", ret, TEST_URLIS_ATTRIBS[i].url,
651 TEST_URLIS_ATTRIBS[i].expectFile );
653 ret = UrlIsW( wurl, URLIS_OPAQUE);
654 ok( ret == TEST_URLIS_ATTRIBS[i].expectOpaque,
655 "returned %d for URLIS_OPAQUE (UrlIsW), url \"%s\", expected %d\n", ret, TEST_URLIS_ATTRIBS[i].url,
656 TEST_URLIS_ATTRIBS[i].expectOpaque );
657 ret = UrlIsW( wurl, URLIS_FILEURL);
658 ok( ret == TEST_URLIS_ATTRIBS[i].expectFile,
659 "returned %d for URLIS_FILEURL (UrlIsW), url \"%s\", expected %d\n", ret, TEST_URLIS_ATTRIBS[i].url,
660 TEST_URLIS_ATTRIBS[i].expectFile );
664 static void test_UrlUnescape(void)
666 CHAR szReturnUrl[INTERNET_MAX_URL_LENGTH];
667 WCHAR ret_urlW[INTERNET_MAX_URL_LENGTH];
668 WCHAR *urlW, *expected_urlW;
669 DWORD dwEscaped;
670 size_t i;
671 static char inplace[] = "file:///C:/Program%20Files";
672 static WCHAR inplaceW[] = {'f','i','l','e',':','/','/','/','C',':','/',
673 'P','r','o','g','r','a','m','%','2','0','F','i','l','e','s',0};
675 for(i=0; i<sizeof(TEST_URL_UNESCAPE)/sizeof(TEST_URL_UNESCAPE[0]); i++) {
676 dwEscaped=INTERNET_MAX_URL_LENGTH;
677 ok(UrlUnescapeA(TEST_URL_UNESCAPE[i].url, szReturnUrl, &dwEscaped, 0) == S_OK, "UrlUnescapeA didn't return 0x%08x from \"%s\"\n", S_OK, TEST_URL_UNESCAPE[i].url);
678 ok(strcmp(szReturnUrl,TEST_URL_UNESCAPE[i].expect)==0, "Expected \"%s\", but got \"%s\" from \"%s\"\n", TEST_URL_UNESCAPE[i].expect, szReturnUrl, TEST_URL_UNESCAPE[i].url);
680 dwEscaped = INTERNET_MAX_URL_LENGTH;
681 urlW = GetWideString(TEST_URL_UNESCAPE[i].url);
682 expected_urlW = GetWideString(TEST_URL_UNESCAPE[i].expect);
683 ok(UrlUnescapeW(urlW, ret_urlW, &dwEscaped, 0) == S_OK, "UrlUnescapeW didn't return 0x%08x from \"%s\"\n", S_OK, TEST_URL_UNESCAPE[i].url);
684 WideCharToMultiByte(CP_ACP,0,ret_urlW,-1,szReturnUrl,INTERNET_MAX_URL_LENGTH,0,0);
685 ok(lstrcmpW(ret_urlW, expected_urlW)==0, "Expected \"%s\", but got \"%s\" from \"%s\" flags %08lx\n", TEST_URL_UNESCAPE[i].expect, szReturnUrl, TEST_URL_UNESCAPE[i].url, 0L);
686 FreeWideString(urlW);
687 FreeWideString(expected_urlW);
690 dwEscaped = sizeof(inplace);
691 ok(UrlUnescapeA(inplace, NULL, &dwEscaped, URL_UNESCAPE_INPLACE) == S_OK, "UrlUnescapeA failed unexpectedly\n");
693 dwEscaped = sizeof(inplaceW);
694 ok(UrlUnescapeW(inplaceW, NULL, &dwEscaped, URL_UNESCAPE_INPLACE) == S_OK, "UrlUnescapeW failed unexpectedly\n");
697 static void test_PathSearchAndQualify(void)
699 WCHAR path1[] = {'c',':','\\','f','o','o',0};
700 WCHAR expect1[] = {'c',':','\\','f','o','o',0};
701 WCHAR path2[] = {'c',':','f','o','o',0};
702 WCHAR c_drive[] = {'c',':',0};
703 WCHAR foo[] = {'f','o','o',0};
704 WCHAR path3[] = {'\\','f','o','o',0};
705 WCHAR winini[] = {'w','i','n','.','i','n','i',0};
706 WCHAR out[MAX_PATH];
707 WCHAR cur_dir[MAX_PATH];
708 WCHAR dot[] = {'.',0};
710 /* c:\foo */
711 ok(PathSearchAndQualifyW(path1, out, MAX_PATH) != 0,
712 "PathSearchAndQualify rets 0\n");
713 ok(!lstrcmpiW(out, expect1), "strings don't match\n");
715 /* c:foo */
716 ok(PathSearchAndQualifyW(path2, out, MAX_PATH) != 0,
717 "PathSearchAndQualify rets 0\n");
718 GetFullPathNameW(c_drive, MAX_PATH, cur_dir, NULL);
719 PathAddBackslashW(cur_dir);
720 lstrcatW(cur_dir, foo);
721 ok(!lstrcmpiW(out, cur_dir), "strings don't match\n");
723 /* foo */
724 ok(PathSearchAndQualifyW(foo, out, MAX_PATH) != 0,
725 "PathSearchAndQualify rets 0\n");
726 GetFullPathNameW(dot, MAX_PATH, cur_dir, NULL);
727 PathAddBackslashW(cur_dir);
728 lstrcatW(cur_dir, foo);
729 ok(!lstrcmpiW(out, cur_dir), "strings don't match\n");
731 /* \foo */
732 ok(PathSearchAndQualifyW(path3, out, MAX_PATH) != 0,
733 "PathSearchAndQualify rets 0\n");
734 GetFullPathNameW(dot, MAX_PATH, cur_dir, NULL);
735 lstrcpyW(cur_dir + 2, path3);
736 ok(!lstrcmpiW(out, cur_dir), "strings don't match\n");
738 /* win.ini */
739 ok(PathSearchAndQualifyW(winini, out, MAX_PATH) != 0,
740 "PathSearchAndQualify rets 0\n");
741 if(!SearchPathW(NULL, winini, NULL, MAX_PATH, cur_dir, NULL))
742 GetFullPathNameW(winini, MAX_PATH, cur_dir, NULL);
743 ok(!lstrcmpiW(out, cur_dir), "strings don't match\n");
747 static void test_PathCreateFromUrl(void)
749 size_t i;
750 char ret_path[INTERNET_MAX_URL_LENGTH];
751 DWORD len, ret;
752 WCHAR ret_pathW[INTERNET_MAX_URL_LENGTH];
753 WCHAR *pathW, *urlW;
754 static const char url[] = "http://www.winehq.org";
756 /* Check ret_path = NULL */
757 len = sizeof(url);
758 ret = PathCreateFromUrlA(url, NULL, &len, 0);
759 ok ( ret == E_INVALIDARG, "got 0x%08x expected E_INVALIDARG\n", ret);
761 for(i = 0; i < sizeof(TEST_PATHFROMURL) / sizeof(TEST_PATHFROMURL[0]); i++) {
762 len = INTERNET_MAX_URL_LENGTH;
763 ret = PathCreateFromUrlA(TEST_PATHFROMURL[i].url, ret_path, &len, 0);
764 ok(ret == TEST_PATHFROMURL[i].ret, "ret %08x from url %s\n", ret, TEST_PATHFROMURL[i].url);
765 if(TEST_PATHFROMURL[i].path) {
766 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);
767 ok(len == strlen(ret_path), "ret len %d from url %s\n", len, TEST_PATHFROMURL[i].url);
769 len = INTERNET_MAX_URL_LENGTH;
770 pathW = GetWideString(TEST_PATHFROMURL[i].path);
771 urlW = GetWideString(TEST_PATHFROMURL[i].url);
772 ret = PathCreateFromUrlW(urlW, ret_pathW, &len, 0);
773 WideCharToMultiByte(CP_ACP, 0, ret_pathW, -1, ret_path, sizeof(ret_path),0,0);
774 ok(ret == TEST_PATHFROMURL[i].ret, "ret %08x from url L\"%s\"\n", ret, TEST_PATHFROMURL[i].url);
775 if(TEST_PATHFROMURL[i].path) {
776 ok(!lstrcmpiW(ret_pathW, pathW), "got %s expected %s from url L\"%s\"\n", ret_path, TEST_PATHFROMURL[i].path, TEST_PATHFROMURL[i].url);
777 ok(len == lstrlenW(ret_pathW), "ret len %d from url L\"%s\"\n", len, TEST_PATHFROMURL[i].url);
779 FreeWideString(urlW);
780 FreeWideString(pathW);
785 static void test_PathIsUrl(void)
787 size_t i;
788 BOOL ret;
790 for(i = 0; i < sizeof(TEST_PATH_IS_URL)/sizeof(TEST_PATH_IS_URL[0]); i++) {
791 ret = PathIsURLA(TEST_PATH_IS_URL[i].path);
792 ok(ret == TEST_PATH_IS_URL[i].expect,
793 "returned %d from path %s, expected %d\n", ret, TEST_PATH_IS_URL[i].path,
794 TEST_PATH_IS_URL[i].expect);
798 static const DWORD SHELL_charclass[] =
800 0x00000000, 0x00000000, 0x00000000, 0x00000000,
801 0x00000000, 0x00000000, 0x00000000, 0x00000000,
802 0x00000000, 0x00000000, 0x00000000, 0x00000000,
803 0x00000000, 0x00000000, 0x00000000, 0x00000000,
804 0x00000000, 0x00000000, 0x00000000, 0x00000000,
805 0x00000000, 0x00000000, 0x00000000, 0x00000000,
806 0x00000000, 0x00000000, 0x00000000, 0x00000000,
807 0x00000000, 0x00000000, 0x00000000, 0x00000000,
808 0x00000080, 0x00000100, 0x00000200, 0x00000100,
809 0x00000100, 0x00000100, 0x00000100, 0x00000100,
810 0x00000100, 0x00000100, 0x00000002, 0x00000100,
811 0x00000040, 0x00000100, 0x00000004, 0x00000000,
812 0x00000100, 0x00000100, 0x00000100, 0x00000100,
813 0x00000100, 0x00000100, 0x00000100, 0x00000100,
814 0x00000100, 0x00000100, 0x00000010, 0x00000020,
815 0x00000000, 0x00000100, 0x00000000, 0x00000001,
816 0x00000100, 0xffffffff, 0xffffffff, 0xffffffff,
817 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
818 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
819 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
820 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
821 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
822 0xffffffff, 0xffffffff, 0xffffffff, 0x00000100,
823 0x00000008, 0x00000100, 0x00000100, 0x00000100,
824 0x00000100, 0xffffffff, 0xffffffff, 0xffffffff,
825 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
826 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
827 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
828 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
829 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
830 0xffffffff, 0xffffffff, 0xffffffff, 0x00000100,
831 0x00000000, 0x00000100, 0x00000100
834 static void test_PathIsValidCharA(void)
836 BOOL ret;
837 unsigned int c;
839 ret = pPathIsValidCharA( 0x7f, 0 );
840 ok ( !ret, "PathIsValidCharA succeeded: 0x%08x\n", (DWORD)ret );
842 ret = pPathIsValidCharA( 0x7f, 1 );
843 ok ( !ret, "PathIsValidCharA succeeded: 0x%08x\n", (DWORD)ret );
845 for (c = 0; c < 0x7f; c++)
847 ret = pPathIsValidCharA( c, ~0U );
848 ok ( ret == SHELL_charclass[c] || (ret == 1 && SHELL_charclass[c] == 0xffffffff),
849 "PathIsValidCharA failed: 0x%02x got 0x%08x expected 0x%08x\n",
850 c, (DWORD)ret, SHELL_charclass[c] );
853 for (c = 0x7f; c <= 0xff; c++)
855 ret = pPathIsValidCharA( c, ~0U );
856 ok ( ret == 0x00000100,
857 "PathIsValidCharA failed: 0x%02x got 0x%08x expected 0x00000100\n",
858 c, (DWORD)ret );
862 static void test_PathIsValidCharW(void)
864 BOOL ret;
865 unsigned int c, err_count = 0;
867 ret = pPathIsValidCharW( 0x7f, 0 );
868 ok ( !ret, "PathIsValidCharW succeeded: 0x%08x\n", (DWORD)ret );
870 ret = pPathIsValidCharW( 0x7f, 1 );
871 ok ( !ret, "PathIsValidCharW succeeded: 0x%08x\n", (DWORD)ret );
873 for (c = 0; c < 0x7f; c++)
875 ret = pPathIsValidCharW( c, ~0U );
876 ok ( ret == SHELL_charclass[c] || (ret == 1 && SHELL_charclass[c] == 0xffffffff),
877 "PathIsValidCharW failed: 0x%02x got 0x%08x expected 0x%08x\n",
878 c, (DWORD)ret, SHELL_charclass[c] );
881 for (c = 0x007f; c <= 0xffff; c++)
883 ret = pPathIsValidCharW( c, ~0U );
884 ok ( ret == 0x00000100,
885 "PathIsValidCharW failed: 0x%02x got 0x%08x expected 0x00000100\n",
886 c, (DWORD)ret );
887 if (ret != 0x00000100)
889 if(++err_count > 100 ) {
890 trace("skipping rest of PathIsValidCharW tests "
891 "because of the current number of errors\n");
892 break;
898 static void test_PathMakePretty(void)
900 char buff[MAX_PATH];
902 ok (PathMakePrettyA(NULL) == FALSE, "PathMakePretty: NULL path succeeded\n");
903 buff[0] = '\0';
904 ok (PathMakePrettyA(buff) == TRUE, "PathMakePretty: Empty path failed\n");
906 strcpy(buff, "C:\\A LONG FILE NAME WITH \\SPACES.TXT");
907 ok (PathMakePrettyA(buff) == TRUE, "PathMakePretty: Long UC name failed\n");
908 ok (strcmp(buff, "C:\\a long file name with \\spaces.txt") == 0,
909 "PathMakePretty: Long UC name not changed\n");
911 strcpy(buff, "C:\\A LONG FILE NAME WITH \\MixedCase.TXT");
912 ok (PathMakePrettyA(buff) == FALSE, "PathMakePretty: Long MC name succeeded\n");
913 ok (strcmp(buff, "C:\\A LONG FILE NAME WITH \\MixedCase.TXT") == 0,
914 "PathMakePretty: Failed but modified path\n");
916 strcpy(buff, "TEST");
917 ok (PathMakePrettyA(buff) == TRUE, "PathMakePretty: Short name failed\n");
918 ok (strcmp(buff, "Test") == 0, "PathMakePretty: 1st char lowercased %s\n", buff);
921 static void test_PathMatchSpec(void)
923 static const char file[] = "c:\\foo\\bar\\filename.ext";
924 static const char spec1[] = ".ext";
925 static const char spec2[] = "*.ext";
926 static const char spec3[] = "*.ext ";
927 static const char spec4[] = " *.ext";
928 static const char spec5[] = "* .ext";
929 static const char spec6[] = "*. ext";
930 static const char spec7[] = "* . ext";
931 static const char spec8[] = "*.e?t";
932 static const char spec9[] = "filename.ext";
933 static const char spec10[] = "*bar\\filename.ext";
934 static const char spec11[] = " foo; *.ext";
935 static const char spec12[] = "*.ext;*.bar";
936 static const char spec13[] = "*bar*";
938 ok (PathMatchSpecA(file, spec1) == FALSE, "PathMatchSpec: Spec1 failed\n");
939 ok (PathMatchSpecA(file, spec2) == TRUE, "PathMatchSpec: Spec2 failed\n");
940 ok (PathMatchSpecA(file, spec3) == FALSE, "PathMatchSpec: Spec3 failed\n");
941 ok (PathMatchSpecA(file, spec4) == TRUE, "PathMatchSpec: Spec4 failed\n");
942 todo_wine ok (PathMatchSpecA(file, spec5) == TRUE, "PathMatchSpec: Spec5 failed\n");
943 todo_wine ok (PathMatchSpecA(file, spec6) == TRUE, "PathMatchSpec: Spec6 failed\n");
944 ok (PathMatchSpecA(file, spec7) == FALSE, "PathMatchSpec: Spec7 failed\n");
945 ok (PathMatchSpecA(file, spec8) == TRUE, "PathMatchSpec: Spec8 failed\n");
946 ok (PathMatchSpecA(file, spec9) == FALSE, "PathMatchSpec: Spec9 failed\n");
947 ok (PathMatchSpecA(file, spec10) == TRUE, "PathMatchSpec: Spec10 failed\n");
948 ok (PathMatchSpecA(file, spec11) == TRUE, "PathMatchSpec: Spec11 failed\n");
949 ok (PathMatchSpecA(file, spec12) == TRUE, "PathMatchSpec: Spec12 failed\n");
950 ok (PathMatchSpecA(file, spec13) == TRUE, "PathMatchSpec: Spec13 failed\n");
953 static void test_PathCombineW(void)
955 LPWSTR wszString, wszString2;
956 WCHAR wbuf[MAX_PATH+1], wstr1[MAX_PATH] = {'C',':','\\',0}, wstr2[MAX_PATH];
957 static const WCHAR expout[] = {'C',':','\\','A','A',0};
958 int i;
960 wszString2 = HeapAlloc(GetProcessHeap(), 0, MAX_PATH * sizeof(WCHAR));
962 /* NULL test */
963 wszString = pPathCombineW(NULL, NULL, NULL);
964 ok (wszString == NULL, "Expected a NULL return\n");
966 /* Some NULL */
967 wszString2[0] = 'a';
968 wszString = pPathCombineW(wszString2, NULL, NULL);
969 ok (wszString == NULL, "Expected a NULL return\n");
970 ok (wszString2[0] == 0, "Destination string not empty\n");
972 HeapFree(GetProcessHeap(), 0, wszString2);
974 /* overflow test */
975 wstr2[0] = wstr2[1] = wstr2[2] = 'A';
976 for (i=3; i<MAX_PATH/2; i++)
977 wstr1[i] = wstr2[i] = 'A';
978 wstr1[(MAX_PATH/2) - 1] = wstr2[MAX_PATH/2] = 0;
979 memset(wbuf, 0xbf, sizeof(wbuf));
981 wszString = pPathCombineW(wbuf, wstr1, wstr2);
982 ok(wszString == NULL, "Expected a NULL return\n");
983 ok(wbuf[0] == 0, "Buffer contains data\n");
985 /* PathCombineW can be used in place */
986 wstr1[3] = 0;
987 wstr2[2] = 0;
988 ok(PathCombineW(wstr1, wstr1, wstr2) == wstr1, "Expected a wstr1 return\n");
989 ok(StrCmpW(wstr1, expout) == 0, "Unexpected PathCombine output\n");
993 #define LONG_LEN (MAX_PATH * 2)
994 #define HALF_LEN (MAX_PATH / 2 + 1)
996 static void test_PathCombineA(void)
998 LPSTR str;
999 char dest[MAX_PATH];
1000 char too_long[LONG_LEN];
1001 char one[HALF_LEN], two[HALF_LEN];
1003 /* try NULL dest */
1004 SetLastError(0xdeadbeef);
1005 str = PathCombineA(NULL, "C:\\", "one\\two\\three");
1006 ok(str == NULL, "Expected NULL, got %p\n", str);
1007 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1009 /* try NULL dest and NULL directory */
1010 SetLastError(0xdeadbeef);
1011 str = PathCombineA(NULL, NULL, "one\\two\\three");
1012 ok(str == NULL, "Expected NULL, got %p\n", str);
1013 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1015 /* try all NULL*/
1016 SetLastError(0xdeadbeef);
1017 str = PathCombineA(NULL, NULL, NULL);
1018 ok(str == NULL, "Expected NULL, got %p\n", str);
1019 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1021 /* try NULL file part */
1022 SetLastError(0xdeadbeef);
1023 lstrcpyA(dest, "control");
1024 str = PathCombineA(dest, "C:\\", NULL);
1025 ok(str == dest, "Expected str == dest, got %p\n", str);
1026 ok(!lstrcmp(str, "C:\\"), "Expected C:\\, got %s\n", str);
1027 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1029 /* try empty file part */
1030 SetLastError(0xdeadbeef);
1031 lstrcpyA(dest, "control");
1032 str = PathCombineA(dest, "C:\\", "");
1033 ok(str == dest, "Expected str == dest, got %p\n", str);
1034 ok(!lstrcmp(str, "C:\\"), "Expected C:\\, got %s\n", str);
1035 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1037 /* try empty directory and file part */
1038 SetLastError(0xdeadbeef);
1039 lstrcpyA(dest, "control");
1040 str = PathCombineA(dest, "", "");
1041 ok(str == dest, "Expected str == dest, got %p\n", str);
1042 ok(!lstrcmp(str, "\\"), "Expected \\, got %s\n", str);
1043 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1045 /* try NULL directory */
1046 SetLastError(0xdeadbeef);
1047 lstrcpyA(dest, "control");
1048 str = PathCombineA(dest, NULL, "one\\two\\three");
1049 ok(str == dest, "Expected str == dest, got %p\n", str);
1050 ok(!lstrcmp(str, "one\\two\\three"), "Expected one\\two\\three, got %s\n", str);
1051 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1053 /* try NULL directory and empty file part */
1054 SetLastError(0xdeadbeef);
1055 lstrcpyA(dest, "control");
1056 str = PathCombineA(dest, NULL, "");
1057 ok(str == dest, "Expected str == dest, got %p\n", str);
1058 ok(!lstrcmp(str, "\\"), "Expected \\, got %s\n", str);
1059 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1061 /* try NULL directory and file part */
1062 SetLastError(0xdeadbeef);
1063 lstrcpyA(dest, "control");
1064 str = PathCombineA(dest, NULL, NULL);
1065 ok(str == NULL, "Expected str == NULL, got %p\n", str);
1066 ok(lstrlenA(dest) == 0, "Expected 0 length, got %i\n", lstrlenA(dest));
1067 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1069 /* try directory without backslash */
1070 SetLastError(0xdeadbeef);
1071 lstrcpyA(dest, "control");
1072 str = PathCombineA(dest, "C:", "one\\two\\three");
1073 ok(str == dest, "Expected str == dest, got %p\n", str);
1074 ok(!lstrcmp(str, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", str);
1075 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1077 /* try directory with backslash */
1078 SetLastError(0xdeadbeef);
1079 lstrcpyA(dest, "control");
1080 str = PathCombineA(dest, "C:\\", "one\\two\\three");
1081 ok(str == dest, "Expected str == dest, got %p\n", str);
1082 ok(!lstrcmp(str, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", str);
1083 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1085 /* try directory with backslash and file with prepended backslash */
1086 SetLastError(0xdeadbeef);
1087 lstrcpyA(dest, "control");
1088 str = PathCombineA(dest, "C:\\", "\\one\\two\\three");
1089 ok(str == dest, "Expected str == dest, got %p\n", str);
1090 ok(!lstrcmp(str, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", str);
1091 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1093 /* try previous test, with backslash appended as well */
1094 SetLastError(0xdeadbeef);
1095 lstrcpyA(dest, "control");
1096 str = PathCombineA(dest, "C:\\", "\\one\\two\\three\\");
1097 ok(str == dest, "Expected str == dest, got %p\n", str);
1098 ok(!lstrcmp(str, "C:\\one\\two\\three\\"), "Expected C:\\one\\two\\three\\, got %s\n", str);
1099 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1101 /* try a relative directory */
1102 SetLastError(0xdeadbeef);
1103 lstrcpyA(dest, "control");
1104 str = PathCombineA(dest, "relative\\dir", "\\one\\two\\three\\");
1105 ok(str == dest, "Expected str == dest, got %p\n", str);
1106 ok(!lstrcmp(str, "one\\two\\three\\"), "Expected one\\two\\three\\, got %s\n", str);
1107 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1109 /* try forward slashes */
1110 SetLastError(0xdeadbeef);
1111 lstrcpyA(dest, "control");
1112 str = PathCombineA(dest, "C:\\", "one/two/three\\");
1113 ok(str == dest, "Expected str == dest, got %p\n", str);
1114 ok(!lstrcmp(str, "C:\\one/two/three\\"), "Expected one/two/three\\, got %s\n", str);
1115 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1117 /* try a really weird directory */
1118 SetLastError(0xdeadbeef);
1119 lstrcpyA(dest, "control");
1120 str = PathCombineA(dest, "C:\\/\\/", "\\one\\two\\three\\");
1121 ok(str == dest, "Expected str == dest, got %p\n", str);
1122 ok(!lstrcmp(str, "C:\\one\\two\\three\\"), "Expected C:\\one\\two\\three\\, got %s\n", str);
1123 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1125 /* try periods */
1126 SetLastError(0xdeadbeef);
1127 lstrcpyA(dest, "control");
1128 str = PathCombineA(dest, "C:\\", "one\\..\\two\\.\\three");
1129 ok(str == dest, "Expected str == dest, got %p\n", str);
1130 ok(!lstrcmp(str, "C:\\two\\three"), "Expected C:\\two\\three, got %s\n", str);
1131 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1133 /* try .. as file */
1134 /* try forward slashes */
1135 SetLastError(0xdeadbeef);
1136 lstrcpyA(dest, "control");
1137 str = PathCombineA(dest, "C:\\", "..");
1138 ok(str == dest, "Expected str == dest, got %p\n", str);
1139 ok(!lstrcmp(str, "C:\\"), "Expected C:\\, got %s\n", str);
1140 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1142 memset(too_long, 'a', LONG_LEN);
1143 too_long[LONG_LEN - 1] = '\0';
1145 /* try a file longer than MAX_PATH */
1146 SetLastError(0xdeadbeef);
1147 lstrcpyA(dest, "control");
1148 str = PathCombineA(dest, "C:\\", too_long);
1149 ok(str == NULL, "Expected str == NULL, got %p\n", str);
1150 ok(lstrlenA(dest) == 0, "Expected 0 length, got %i\n", lstrlenA(dest));
1151 todo_wine ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1153 /* try a directory longer than MAX_PATH */
1154 SetLastError(0xdeadbeef);
1155 lstrcpyA(dest, "control");
1156 str = PathCombineA(dest, too_long, "one\\two\\three");
1157 ok(str == NULL, "Expected str == NULL, got %p\n", str);
1158 ok(lstrlenA(dest) == 0, "Expected 0 length, got %i\n", lstrlenA(dest));
1159 todo_wine ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1161 memset(one, 'b', HALF_LEN);
1162 memset(two, 'c', HALF_LEN);
1163 one[HALF_LEN - 1] = '\0';
1164 two[HALF_LEN - 1] = '\0';
1166 /* destination string is longer than MAX_PATH, but not the constituent parts */
1167 SetLastError(0xdeadbeef);
1168 lstrcpyA(dest, "control");
1169 str = PathCombineA(dest, one, two);
1170 ok(str == NULL, "Expected str == NULL, got %p\n", str);
1171 ok(lstrlenA(dest) == 0, "Expected 0 length, got %i\n", lstrlenA(dest));
1172 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1175 static void test_PathAddBackslash(void)
1177 LPSTR str;
1178 char path[MAX_PATH];
1179 char too_long[LONG_LEN];
1181 /* try a NULL path */
1182 SetLastError(0xdeadbeef);
1183 str = PathAddBackslashA(NULL);
1184 ok(str == NULL, "Expected str == NULL, got %p\n", str);
1185 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1187 /* try an empty path */
1188 path[0] = '\0';
1189 SetLastError(0xdeadbeef);
1190 str = PathAddBackslashA(path);
1191 ok(str == (path + lstrlenA(path)), "Expected str to point to end of path, got %p\n", str);
1192 ok(lstrlenA(path) == 0, "Expected empty string, got %i\n", lstrlenA(path));
1193 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1195 /* try a relative path */
1196 lstrcpyA(path, "one\\two");
1197 SetLastError(0xdeadbeef);
1198 str = PathAddBackslashA(path);
1199 ok(str == (path + lstrlenA(path)), "Expected str to point to end of path, got %p\n", str);
1200 ok(!lstrcmp(path, "one\\two\\"), "Expected one\\two\\, got %s\n", path);
1201 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1203 /* try periods */
1204 lstrcpyA(path, "one\\..\\two");
1205 SetLastError(0xdeadbeef);
1206 str = PathAddBackslashA(path);
1207 ok(str == (path + lstrlenA(path)), "Expected str to point to end of path, got %p\n", str);
1208 ok(!lstrcmp(path, "one\\..\\two\\"), "Expected one\\..\\two\\, got %s\n", path);
1209 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1211 /* try just a space */
1212 lstrcpyA(path, " ");
1213 SetLastError(0xdeadbeef);
1214 str = PathAddBackslashA(path);
1215 ok(str == (path + lstrlenA(path)), "Expected str to point to end of path, got %p\n", str);
1216 ok(!lstrcmp(path, " \\"), "Expected \\, got %s\n", path);
1217 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1219 /* path already has backslash */
1220 lstrcpyA(path, "C:\\one\\");
1221 SetLastError(0xdeadbeef);
1222 str = PathAddBackslashA(path);
1223 ok(str == (path + lstrlenA(path)), "Expected str to point to end of path, got %p\n", str);
1224 ok(!lstrcmp(path, "C:\\one\\"), "Expected C:\\one\\, got %s\n", path);
1225 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1227 memset(too_long, 'a', LONG_LEN);
1228 too_long[LONG_LEN - 1] = '\0';
1230 /* path is longer than MAX_PATH */
1231 SetLastError(0xdeadbeef);
1232 str = PathAddBackslashA(too_long);
1233 ok(str == NULL, "Expected str == NULL, got %p\n", str);
1234 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1237 static void test_PathAppendA(void)
1239 char path[MAX_PATH];
1240 char too_long[LONG_LEN];
1241 char one[HALF_LEN], two[HALF_LEN];
1242 BOOL res;
1244 lstrcpy(path, "C:\\one");
1246 /* try NULL pszMore */
1247 SetLastError(0xdeadbeef);
1248 res = PathAppendA(path, NULL);
1249 ok(!res, "Expected failure\n");
1250 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1251 ok(!lstrcmp(path, "C:\\one"), "Expected C:\\one, got %s\n", path);
1253 /* try empty pszMore */
1254 SetLastError(0xdeadbeef);
1255 res = PathAppendA(path, "");
1256 ok(res, "Expected success\n");
1257 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1258 ok(!lstrcmp(path, "C:\\one"), "Expected C:\\one, got %s\n", path);
1260 /* try NULL pszPath */
1261 SetLastError(0xdeadbeef);
1262 res = PathAppendA(NULL, "two\\three");
1263 ok(!res, "Expected failure\n");
1264 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1266 /* try empty pszPath */
1267 path[0] = '\0';
1268 SetLastError(0xdeadbeef);
1269 res = PathAppendA(path, "two\\three");
1270 ok(res, "Expected success\n");
1271 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1272 ok(!lstrcmp(path, "two\\three"), "Expected \\two\\three, got %s\n", path);
1274 /* try empty pszPath and empty pszMore */
1275 path[0] = '\0';
1276 SetLastError(0xdeadbeef);
1277 res = PathAppendA(path, "");
1278 ok(res, "Expected success\n");
1279 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1280 ok(!lstrcmp(path, "\\"), "Expected \\, got %s\n", path);
1282 /* try legit params */
1283 lstrcpy(path, "C:\\one");
1284 SetLastError(0xdeadbeef);
1285 res = PathAppendA(path, "two\\three");
1286 ok(res, "Expected success\n");
1287 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1288 ok(!lstrcmp(path, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", path);
1290 /* try pszPath with backslash after it */
1291 lstrcpy(path, "C:\\one\\");
1292 SetLastError(0xdeadbeef);
1293 res = PathAppendA(path, "two\\three");
1294 ok(res, "Expected success\n");
1295 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1296 ok(!lstrcmp(path, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", path);
1298 /* try pszMore with backslash before it */
1299 lstrcpy(path, "C:\\one");
1300 SetLastError(0xdeadbeef);
1301 res = PathAppendA(path, "\\two\\three");
1302 ok(res, "Expected success\n");
1303 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1304 ok(!lstrcmp(path, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", path);
1306 /* try pszMore with backslash after it */
1307 lstrcpy(path, "C:\\one");
1308 SetLastError(0xdeadbeef);
1309 res = PathAppendA(path, "two\\three\\");
1310 ok(res, "Expected success\n");
1311 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1312 ok(!lstrcmp(path, "C:\\one\\two\\three\\"), "Expected C:\\one\\two\\three\\, got %s\n", path);
1314 /* try spaces in pszPath */
1315 lstrcpy(path, "C: \\ one ");
1316 SetLastError(0xdeadbeef);
1317 res = PathAppendA(path, "two\\three");
1318 ok(res, "Expected success\n");
1319 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1320 ok(!lstrcmp(path, "C: \\ one \\two\\three"), "Expected C: \\ one \\two\\three, got %s\n", path);
1322 /* try spaces in pszMore */
1323 lstrcpy(path, "C:\\one");
1324 SetLastError(0xdeadbeef);
1325 res = PathAppendA(path, " two \\ three ");
1326 ok(res, "Expected success\n");
1327 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1328 ok(!lstrcmp(path, "C:\\one\\ two \\ three "), "Expected 'C:\\one\\ two \\ three ', got %s\n", path);
1330 /* pszPath is too long */
1331 memset(too_long, 'a', LONG_LEN);
1332 too_long[LONG_LEN - 1] = '\0';
1333 SetLastError(0xdeadbeef);
1334 res = PathAppendA(too_long, "two\\three");
1335 ok(!res, "Expected failure\n");
1336 todo_wine ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1337 ok(lstrlen(too_long) == 0, "Expected length of too_long to be zero, got %i\n", lstrlen(too_long));
1339 /* pszMore is too long */
1340 lstrcpy(path, "C:\\one");
1341 memset(too_long, 'a', LONG_LEN);
1342 too_long[LONG_LEN - 1] = '\0';
1343 SetLastError(0xdeadbeef);
1344 res = PathAppendA(path, too_long);
1345 ok(!res, "Expected failure\n");
1346 todo_wine ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1347 ok(lstrlen(path) == 0, "Expected length of path to be zero, got %i\n", lstrlen(path));
1349 /* both params combined are too long */
1350 memset(one, 'a', HALF_LEN);
1351 one[HALF_LEN - 1] = '\0';
1352 memset(two, 'b', HALF_LEN);
1353 two[HALF_LEN - 1] = '\0';
1354 SetLastError(0xdeadbeef);
1355 res = PathAppendA(one, two);
1356 ok(!res, "Expected failure\n");
1357 ok(lstrlen(one) == 0, "Expected length of one to be zero, got %i\n", lstrlen(one));
1358 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1361 static void test_PathCanonicalizeA(void)
1363 char dest[MAX_PATH];
1364 char too_long[LONG_LEN];
1365 BOOL res;
1367 /* try a NULL source */
1368 lstrcpy(dest, "test");
1369 SetLastError(0xdeadbeef);
1370 res = PathCanonicalizeA(dest, NULL);
1371 ok(!res, "Expected failure\n");
1372 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1373 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1374 todo_wine
1376 ok(!lstrcmp(dest, "test"), "Expected test, got %s\n", dest);
1379 /* try an empty source */
1380 lstrcpy(dest, "test");
1381 SetLastError(0xdeadbeef);
1382 res = PathCanonicalizeA(dest, "");
1383 ok(res, "Expected success\n");
1384 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1385 ok(!lstrcmp(dest, "\\"), "Expected \\, got %s\n", dest);
1387 /* try a NULL dest */
1388 SetLastError(0xdeadbeef);
1389 res = PathCanonicalizeA(NULL, "C:\\");
1390 ok(!res, "Expected failure\n");
1391 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1392 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1394 /* try empty dest */
1395 dest[0] = '\0';
1396 SetLastError(0xdeadbeef);
1397 res = PathCanonicalizeA(dest, "C:\\");
1398 ok(res, "Expected success\n");
1399 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1400 ok(!lstrcmp(dest, "C:\\"), "Expected C:\\, got %s\n", dest);
1402 /* try non-empty dest */
1403 lstrcpy(dest, "test");
1404 SetLastError(0xdeadbeef);
1405 res = PathCanonicalizeA(dest, "C:\\");
1406 ok(res, "Expected success\n");
1407 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1408 ok(!lstrcmp(dest, "C:\\"), "Expected C:\\, got %s\n", dest);
1410 /* try a space for source */
1411 lstrcpy(dest, "test");
1412 SetLastError(0xdeadbeef);
1413 res = PathCanonicalizeA(dest, " ");
1414 ok(res, "Expected success\n");
1415 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1416 ok(!lstrcmp(dest, " "), "Expected ' ', got %s\n", dest);
1418 /* try a relative path */
1419 lstrcpy(dest, "test");
1420 SetLastError(0xdeadbeef);
1421 res = PathCanonicalizeA(dest, "one\\two");
1422 ok(res, "Expected success\n");
1423 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1424 ok(!lstrcmp(dest, "one\\two"), "Expected one\\two, got %s\n", dest);
1426 /* try current dir and previous dir */
1427 lstrcpy(dest, "test");
1428 SetLastError(0xdeadbeef);
1429 res = PathCanonicalizeA(dest, "C:\\one\\.\\..\\two\\three\\..");
1430 ok(res, "Expected success\n");
1431 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1432 ok(!lstrcmp(dest, "C:\\two"), "Expected C:\\two, got %s\n", dest);
1434 /* try simple forward slashes */
1435 lstrcpy(dest, "test");
1436 SetLastError(0xdeadbeef);
1437 res = PathCanonicalizeA(dest, "C:\\one/two/three\\four/five\\six");
1438 ok(res, "Expected success\n");
1439 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1440 ok(!lstrcmp(dest, "C:\\one/two/three\\four/five\\six"),
1441 "Expected C:\\one/two/three\\four/five\\six, got %s\n", dest);
1443 /* try simple forward slashes with same dir */
1444 lstrcpy(dest, "test");
1445 SetLastError(0xdeadbeef);
1446 res = PathCanonicalizeA(dest, "C:\\one/.\\two");
1447 ok(res, "Expected success\n");
1448 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1449 ok(!lstrcmp(dest, "C:\\one/.\\two"), "Expected C:\\one/.\\two, got %s\n", dest);
1451 /* try simple forward slashes with change dir */
1452 lstrcpy(dest, "test");
1453 SetLastError(0xdeadbeef);
1454 res = PathCanonicalizeA(dest, "C:\\one/.\\two\\..");
1455 ok(res, "Expected success\n");
1456 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1457 ok(!lstrcmp(dest, "C:\\one/."), "Expected C:\\one/., got %s\n", dest);
1459 /* try forward slashes with change dirs
1460 * NOTE: if there is a forward slash in between two backslashes,
1461 * everything in between the two backslashes is considered on dir
1463 lstrcpy(dest, "test");
1464 SetLastError(0xdeadbeef);
1465 res = PathCanonicalizeA(dest, "C:\\one/.\\..\\two/three\\..\\four/.five");
1466 ok(res, "Expected success\n");
1467 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1468 ok(!lstrcmp(dest, "C:\\four/.five"), "Expected C:\\four/.five, got %s\n", dest);
1470 /* try src is too long */
1471 memset(too_long, 'a', LONG_LEN);
1472 too_long[LONG_LEN - 1] = '\0';
1473 lstrcpy(dest, "test");
1474 SetLastError(0xdeadbeef);
1475 res = PathCanonicalizeA(dest, too_long);
1476 todo_wine
1478 ok(!res, "Expected failure\n");
1479 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1481 ok(lstrlen(too_long) == LONG_LEN - 1, "Expected length LONG_LEN - 1, got %i\n", lstrlen(too_long));
1484 static void test_PathFindExtensionA(void)
1486 LPSTR ext;
1487 char path[MAX_PATH];
1488 char too_long[LONG_LEN];
1490 /* try a NULL path */
1491 SetLastError(0xdeadbeef);
1492 ext = PathFindExtensionA(NULL);
1493 ok(ext == NULL, "Expected NULL, got %p\n", ext);
1494 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1496 /* try an empty path */
1497 path[0] = '\0';
1498 SetLastError(0xdeadbeef);
1499 ext = PathFindExtensionA(path);
1500 ok(ext == path, "Expected ext == path, got %p\n", ext);
1501 ok(lstrlen(ext) == 0, "Expected length 0, got %i\n", lstrlen(ext));
1502 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1504 /* try a path without an extension */
1505 lstrcpy(path, "file");
1506 SetLastError(0xdeadbeef);
1507 ext = PathFindExtensionA(path);
1508 ok(ext == path + lstrlen(path), "Expected ext == path, got %p\n", ext);
1509 ok(lstrlen(ext) == 0, "Expected length 0, got %i\n", lstrlen(ext));
1510 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1512 /* try a path with an extension */
1513 lstrcpy(path, "file.txt");
1514 SetLastError(0xdeadbeef);
1515 ext = PathFindExtensionA(path);
1516 ok(ext == path + lstrlen("file"),
1517 "Expected ext == path + lstrlen(\"file\"), got %p\n", ext);
1518 ok(!lstrcmp(ext, ".txt"), "Expected .txt, got %s\n", ext);
1519 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1521 /* try a path with two extensions */
1522 lstrcpy(path, "file.txt.doc");
1523 SetLastError(0xdeadbeef);
1524 ext = PathFindExtensionA(path);
1525 ok(ext == path + lstrlen("file.txt"),
1526 "Expected ext == path + lstrlen(\"file.txt\"), got %p\n", ext);
1527 ok(!lstrcmp(ext, ".doc"), "Expected .txt, got %s\n", ext);
1528 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1530 /* try a path longer than MAX_PATH without an extension*/
1531 memset(too_long, 'a', LONG_LEN);
1532 too_long[LONG_LEN - 1] = '\0';
1533 SetLastError(0xdeadbeef);
1534 ext = PathFindExtensionA(too_long);
1535 ok(ext == too_long + LONG_LEN - 1, "Expected ext == too_long + LONG_LEN - 1, got %p\n", ext);
1536 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1538 /* try a path longer than MAX_PATH with an extension*/
1539 memset(too_long, 'a', LONG_LEN);
1540 too_long[LONG_LEN - 1] = '\0';
1541 lstrcpy(too_long + 300, ".abcde");
1542 too_long[lstrlen(too_long)] = 'a';
1543 SetLastError(0xdeadbeef);
1544 ext = PathFindExtensionA(too_long);
1545 ok(ext == too_long + 300, "Expected ext == too_long + 300, got %p\n", ext);
1546 ok(lstrlen(ext) == LONG_LEN - 301, "Expected LONG_LEN - 301, got %i\n", lstrlen(ext));
1547 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1550 static void test_PathBuildRootA(void)
1552 LPSTR root;
1553 char path[10];
1554 char root_expected[26][4];
1555 char drive;
1556 int j;
1558 /* set up the expected paths */
1559 for (drive = 'A'; drive <= 'Z'; drive++)
1560 sprintf(root_expected[drive - 'A'], "%c:\\", drive);
1562 /* test the expected values */
1563 for (j = 0; j < 26; j++)
1565 SetLastError(0xdeadbeef);
1566 lstrcpy(path, "aaaaaaaaa");
1567 root = PathBuildRootA(path, j);
1568 ok(root == path, "Expected root == path, got %p\n", root);
1569 ok(!lstrcmp(root, root_expected[j]), "Expected %s, got %s\n", root_expected[j], root);
1570 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1573 /* test a negative drive number */
1574 SetLastError(0xdeadbeef);
1575 lstrcpy(path, "aaaaaaaaa");
1576 root = PathBuildRootA(path, -1);
1577 ok(root == path, "Expected root == path, got %p\n", root);
1578 ok(!lstrcmp(path, "aaaaaaaaa"), "Expected aaaaaaaaa, got %s\n", path);
1579 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1581 /* test a drive number greater than 25 */
1582 SetLastError(0xdeadbeef);
1583 lstrcpy(path, "aaaaaaaaa");
1584 root = PathBuildRootA(path, 26);
1585 ok(root == path, "Expected root == path, got %p\n", root);
1586 ok(!lstrcmp(path, "aaaaaaaaa"), "Expected aaaaaaaaa, got %s\n", path);
1587 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1589 /* length of path is less than 4 */
1590 SetLastError(0xdeadbeef);
1591 lstrcpy(path, "aa");
1592 root = PathBuildRootA(path, 0);
1593 ok(root == path, "Expected root == path, got %p\n", root);
1594 ok(!lstrcmp(path, "A:\\"), "Expected A:\\, got %s\n", path);
1595 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1597 /* path is NULL */
1598 SetLastError(0xdeadbeef);
1599 root = PathBuildRootA(NULL, 0);
1600 ok(root == NULL, "Expected root == NULL, got %p\n", root);
1601 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1604 static void test_PathCommonPrefixA(void)
1606 char path1[MAX_PATH], path2[MAX_PATH];
1607 char out[MAX_PATH];
1608 int count;
1610 /* test NULL path1 */
1611 SetLastError(0xdeadbeef);
1612 lstrcpy(path2, "C:\\");
1613 lstrcpy(out, "aaa");
1614 count = PathCommonPrefixA(NULL, path2, out);
1615 ok(count == 0, "Expected 0, got %i\n", count);
1616 todo_wine
1618 ok(!lstrcmp(out, "aaa"), "Expected aaa, got %s\n", out);
1620 ok(!lstrcmp(path2, "C:\\"), "Expected C:\\, got %s\n", path2);
1621 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1623 /* test NULL path2 */
1624 SetLastError(0xdeadbeef);
1625 lstrcpy(path1, "C:\\");
1626 lstrcpy(out, "aaa");
1627 count = PathCommonPrefixA(path1, NULL, out);
1628 ok(count == 0, "Expected 0, got %i\n", count);
1629 todo_wine
1631 ok(!lstrcmp(out, "aaa"), "Expected aaa, got %s\n", out);
1633 ok(!lstrcmp(path1, "C:\\"), "Expected C:\\, got %s\n", path1);
1634 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1636 /* test empty path1 */
1637 SetLastError(0xdeadbeef);
1638 path1[0] = '\0';
1639 lstrcpy(path2, "C:\\");
1640 lstrcpy(out, "aaa");
1641 count = PathCommonPrefixA(path1, path2, out);
1642 ok(count == 0, "Expected 0, got %i\n", count);
1643 ok(lstrlen(out) == 0, "Expected 0 length out, got %i\n", lstrlen(out));
1644 ok(lstrlen(path1) == 0, "Expected 0 length path1, got %i\n", lstrlen(path1));
1645 ok(!lstrcmp(path2, "C:\\"), "Expected C:\\, got %s\n", path2);
1646 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1648 /* test empty path1 */
1649 SetLastError(0xdeadbeef);
1650 path2[0] = '\0';
1651 lstrcpy(path1, "C:\\");
1652 lstrcpy(out, "aaa");
1653 count = PathCommonPrefixA(path1, path2, out);
1654 ok(count == 0, "Expected 0, got %i\n", count);
1655 ok(lstrlen(out) == 0, "Expected 0 length out, got %i\n", lstrlen(out));
1656 ok(lstrlen(path2) == 0, "Expected 0 length path2, got %i\n", lstrlen(path2));
1657 ok(!lstrcmp(path1, "C:\\"), "Expected C:\\, got %s\n", path1);
1658 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1660 /* paths are legit, out is NULL */
1661 SetLastError(0xdeadbeef);
1662 lstrcpy(path1, "C:\\");
1663 lstrcpy(path2, "C:\\");
1664 count = PathCommonPrefixA(path1, path2, NULL);
1665 ok(count == 3, "Expected 3, got %i\n", count);
1666 ok(!lstrcmp(path1, "C:\\"), "Expected C:\\, got %s\n", path1);
1667 ok(!lstrcmp(path2, "C:\\"), "Expected C:\\, got %s\n", path2);
1668 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1670 /* all parameters legit */
1671 SetLastError(0xdeadbeef);
1672 lstrcpy(path1, "C:\\");
1673 lstrcpy(path2, "C:\\");
1674 lstrcpy(out, "aaa");
1675 count = PathCommonPrefixA(path1, path2, out);
1676 ok(count == 3, "Expected 3, got %i\n", count);
1677 ok(!lstrcmp(path1, "C:\\"), "Expected C:\\, got %s\n", path1);
1678 ok(!lstrcmp(path2, "C:\\"), "Expected C:\\, got %s\n", path2);
1679 ok(!lstrcmp(out, "C:\\"), "Expected C:\\, got %s\n", out);
1680 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1682 /* path1 and path2 not the same, but common prefix */
1683 SetLastError(0xdeadbeef);
1684 lstrcpy(path1, "C:\\one\\two");
1685 lstrcpy(path2, "C:\\one\\three");
1686 lstrcpy(out, "aaa");
1687 count = PathCommonPrefixA(path1, path2, out);
1688 ok(count == 6, "Expected 6, got %i\n", count);
1689 ok(!lstrcmp(path1, "C:\\one\\two"), "Expected C:\\one\\two, got %s\n", path1);
1690 ok(!lstrcmp(path2, "C:\\one\\three"), "Expected C:\\one\\three, got %s\n", path2);
1691 ok(!lstrcmp(out, "C:\\one"), "Expected C:\\one, got %s\n", out);
1692 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1694 /* try . prefix */
1695 SetLastError(0xdeadbeef);
1696 lstrcpy(path1, "one\\.two");
1697 lstrcpy(path2, "one\\.three");
1698 lstrcpy(out, "aaa");
1699 count = PathCommonPrefixA(path1, path2, out);
1700 ok(count == 3, "Expected 3, got %i\n", count);
1701 ok(!lstrcmp(path1, "one\\.two"), "Expected one\\.two, got %s\n", path1);
1702 ok(!lstrcmp(path2, "one\\.three"), "Expected one\\.three, got %s\n", path2);
1703 ok(!lstrcmp(out, "one"), "Expected one, got %s\n", out);
1704 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1706 /* try .. prefix */
1707 SetLastError(0xdeadbeef);
1708 lstrcpy(path1, "one\\..two");
1709 lstrcpy(path2, "one\\..three");
1710 lstrcpy(out, "aaa");
1711 count = PathCommonPrefixA(path1, path2, out);
1712 ok(count == 3, "Expected 3, got %i\n", count);
1713 ok(!lstrcmp(path1, "one\\..two"), "Expected one\\..two, got %s\n", path1);
1714 ok(!lstrcmp(path2, "one\\..three"), "Expected one\\..three, got %s\n", path2);
1715 ok(!lstrcmp(out, "one"), "Expected one, got %s\n", out);
1716 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1718 /* try ... prefix */
1719 SetLastError(0xdeadbeef);
1720 lstrcpy(path1, "one\\...two");
1721 lstrcpy(path2, "one\\...three");
1722 lstrcpy(out, "aaa");
1723 count = PathCommonPrefixA(path1, path2, out);
1724 ok(count == 3, "Expected 3, got %i\n", count);
1725 ok(!lstrcmp(path1, "one\\...two"), "Expected one\\...two, got %s\n", path1);
1726 ok(!lstrcmp(path2, "one\\...three"), "Expected one\\...three, got %s\n", path2);
1727 ok(!lstrcmp(out, "one"), "Expected one, got %s\n", out);
1728 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1730 /* try .\ prefix */
1731 SetLastError(0xdeadbeef);
1732 lstrcpy(path1, "one\\.\\two");
1733 lstrcpy(path2, "one\\.\\three");
1734 lstrcpy(out, "aaa");
1735 count = PathCommonPrefixA(path1, path2, out);
1736 ok(count == 5, "Expected 5, got %i\n", count);
1737 ok(!lstrcmp(path1, "one\\.\\two"), "Expected one\\.\\two, got %s\n", path1);
1738 ok(!lstrcmp(path2, "one\\.\\three"), "Expected one\\.\\three, got %s\n", path2);
1739 ok(!lstrcmp(out, "one\\."), "Expected one\\., got %s\n", out);
1740 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1742 /* try ..\ prefix */
1743 SetLastError(0xdeadbeef);
1744 lstrcpy(path1, "one\\..\\two");
1745 lstrcpy(path2, "one\\..\\three");
1746 lstrcpy(out, "aaa");
1747 count = PathCommonPrefixA(path1, path2, out);
1748 ok(count == 6, "Expected 6, got %i\n", count);
1749 ok(!lstrcmp(path1, "one\\..\\two"), "Expected one\\..\\two, got %s\n", path1);
1750 ok(!lstrcmp(path2, "one\\..\\three"), "Expected one\\..\\three, got %s\n", path2);
1751 ok(!lstrcmp(out, "one\\.."), "Expected one\\.., got %s\n", out);
1752 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1754 /* try ...\\ prefix */
1755 SetLastError(0xdeadbeef);
1756 lstrcpy(path1, "one\\...\\two");
1757 lstrcpy(path2, "one\\...\\three");
1758 lstrcpy(out, "aaa");
1759 count = PathCommonPrefixA(path1, path2, out);
1760 ok(count == 7, "Expected 7, got %i\n", count);
1761 ok(!lstrcmp(path1, "one\\...\\two"), "Expected one\\...\\two, got %s\n", path1);
1762 ok(!lstrcmp(path2, "one\\...\\three"), "Expected one\\...\\three, got %s\n", path2);
1763 ok(!lstrcmp(out, "one\\..."), "Expected one\\..., got %s\n", out);
1764 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1766 /* try prefix that is not an msdn labeled prefix type */
1767 SetLastError(0xdeadbeef);
1768 lstrcpy(path1, "same");
1769 lstrcpy(path2, "same");
1770 lstrcpy(out, "aaa");
1771 count = PathCommonPrefixA(path1, path2, out);
1772 ok(count == 4, "Expected 4, got %i\n", count);
1773 ok(!lstrcmp(path1, "same"), "Expected same, got %s\n", path1);
1774 ok(!lstrcmp(path2, "same"), "Expected same, got %s\n", path2);
1775 ok(!lstrcmp(out, "same"), "Expected same, got %s\n", out);
1776 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1778 /* try . after directory */
1779 SetLastError(0xdeadbeef);
1780 lstrcpy(path1, "one\\mid.\\two");
1781 lstrcpy(path2, "one\\mid.\\three");
1782 lstrcpy(out, "aaa");
1783 count = PathCommonPrefixA(path1, path2, out);
1784 ok(count == 8, "Expected 8, got %i\n", count);
1785 ok(!lstrcmp(path1, "one\\mid.\\two"), "Expected one\\mid.\\two, got %s\n", path1);
1786 ok(!lstrcmp(path2, "one\\mid.\\three"), "Expected one\\mid.\\three, got %s\n", path2);
1787 ok(!lstrcmp(out, "one\\mid."), "Expected one\\mid., got %s\n", out);
1788 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1790 /* try . in the middle of a directory */
1791 SetLastError(0xdeadbeef);
1792 lstrcpy(path1, "one\\mid.end\\two");
1793 lstrcpy(path2, "one\\mid.end\\three");
1794 lstrcpy(out, "aaa");
1795 count = PathCommonPrefixA(path1, path2, out);
1796 ok(count == 11, "Expected 11, got %i\n", count);
1797 ok(!lstrcmp(path1, "one\\mid.end\\two"), "Expected one\\mid.end\\two, got %s\n", path1);
1798 ok(!lstrcmp(path2, "one\\mid.end\\three"), "Expected one\\mid.end\\three, got %s\n", path2);
1799 ok(!lstrcmp(out, "one\\mid.end"), "Expected one\\mid.end, got %s\n", out);
1800 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1802 /* try comparing a .. with the expanded path */
1803 SetLastError(0xdeadbeef);
1804 lstrcpy(path1, "one\\..\\two");
1805 lstrcpy(path2, "two");
1806 lstrcpy(out, "aaa");
1807 count = PathCommonPrefixA(path1, path2, out);
1808 ok(count == 0, "Expected 0, got %i\n", count);
1809 ok(!lstrcmp(path1, "one\\..\\two"), "Expected one\\..\\two, got %s\n", path1);
1810 ok(!lstrcmp(path2, "two"), "Expected two, got %s\n", path2);
1811 ok(lstrlen(out) == 0, "Expected 0 length out, got %i\n", lstrlen(out));
1812 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1815 static void test_PathUnquoteSpaces(void)
1817 int i;
1818 for(i = 0; i < sizeof(TEST_PATH_UNQUOTE_SPACES) / sizeof(TEST_PATH_UNQUOTE_SPACES[0]); i++)
1820 char *path = strdupA(TEST_PATH_UNQUOTE_SPACES[i].path);
1821 WCHAR *pathW = GetWideString(TEST_PATH_UNQUOTE_SPACES[i].path);
1822 WCHAR *resultW = GetWideString(TEST_PATH_UNQUOTE_SPACES[i].result);
1824 PathUnquoteSpacesA(path);
1825 ok(!strcmp(path, TEST_PATH_UNQUOTE_SPACES[i].result), "%s (A): got %s expected %s\n",
1826 TEST_PATH_UNQUOTE_SPACES[i].path, path,
1827 TEST_PATH_UNQUOTE_SPACES[i].result);
1829 PathUnquoteSpacesW(pathW);
1830 ok(!lstrcmpW(pathW, resultW), "%s (W): strings differ\n",
1831 TEST_PATH_UNQUOTE_SPACES[i].path);
1832 FreeWideString(pathW);
1833 FreeWideString(resultW);
1834 HeapFree(GetProcessHeap(), 0, path);
1838 START_TEST(path)
1840 hShlwapi = GetModuleHandleA("shlwapi.dll");
1842 test_UrlHash();
1843 test_UrlGetPart();
1844 test_UrlCanonicalize();
1845 test_UrlEscape();
1846 test_UrlCombine();
1847 test_UrlCreateFromPath();
1848 test_UrlIs();
1849 test_UrlUnescape();
1851 test_PathSearchAndQualify();
1852 test_PathCreateFromUrl();
1853 test_PathIsUrl();
1855 test_PathAddBackslash();
1856 test_PathMakePretty();
1857 test_PathMatchSpec();
1859 /* For whatever reason, PathIsValidCharA and PathAppendA share the same
1860 * ordinal number in some native versions. Check this to prevent a crash.
1862 pPathIsValidCharA = (void*)GetProcAddress(hShlwapi, (LPSTR)455);
1863 if (pPathIsValidCharA && pPathIsValidCharA != (void*)GetProcAddress(hShlwapi, "PathAppendA"))
1865 test_PathIsValidCharA();
1867 pPathIsValidCharW = (void*)GetProcAddress(hShlwapi, (LPSTR)456);
1868 if (pPathIsValidCharW) test_PathIsValidCharW();
1871 pPathCombineW = (void*)GetProcAddress(hShlwapi, "PathCombineW");
1872 if (pPathCombineW)
1873 test_PathCombineW();
1875 test_PathCombineA();
1876 test_PathAppendA();
1877 test_PathCanonicalizeA();
1878 test_PathFindExtensionA();
1879 test_PathBuildRootA();
1880 test_PathCommonPrefixA();
1881 test_PathUnquoteSpaces();