Autosyncing with Wine HEAD
[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 #include <assert.h>
21 #include <stdarg.h>
22 #include <stdio.h>
23
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"
30
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);
35
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";
39
40 typedef struct _TEST_URL_CANONICALIZE {
41 const char *url;
42 DWORD flags;
43 HRESULT expectret;
44 const char *expecturl;
45 } TEST_URL_CANONICALIZE;
46
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, ""}
88 };
89
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;
97
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"},
106
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"},
126
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"},
134
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"},
151
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"},
155
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"},
165
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"},
169
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"}
177 };
178
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;
186
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 };
209
210 struct {
211 const char *path;
212 const char *url;
213 DWORD ret;
214 } TEST_URLFROMPATH [] = {
215 {"foo", "file:foo", S_OK},
216 {"foo\\bar", "file:foo/bar", S_OK},
217 {"\\foo\\bar", "file:///foo/bar", S_OK},
218 {"c:\\foo\\bar", "file:///c:/foo/bar", S_OK},
219 {"c:foo\\bar", "file:///c:foo/bar", S_OK},
220 {"c:\\foo/b a%r", "file:///c:/foo/b%20a%25r", S_OK},
221 {"c:\\foo\\foo bar", "file:///c:/foo/foo%20bar", S_OK},
222 #if 0
223 /* The following test fails on native shlwapi as distributed with Win95/98.
224 * Wine matches the behaviour of later versions.
225 */
226 {"xx:c:\\foo\\bar", "xx:c:\\foo\\bar", S_FALSE}
227 #endif
228 };
229
230 struct {
231 const char *url;
232 const char *path;
233 DWORD ret;
234 } TEST_PATHFROMURL[] = {
235 {"file:///c:/foo/ba%5Cr", "c:\\foo\\ba\\r", S_OK},
236 {"file:///c:/foo/../ba%5Cr", "c:\\foo\\..\\ba\\r", S_OK},
237 {"file:///host/c:/foo/bar", "\\host\\c:\\foo\\bar", S_OK},
238 {"file://host/c:/foo/bar", "\\\\hostc:\\foo\\bar", S_OK},
239 {"file://host/c:/foo/bar", "\\\\hostc:\\foo\\bar", S_OK},
240 {"file:\\\\host\\c:\\foo\\bar", "\\\\hostc:\\foo\\bar", S_OK},
241 {"file:\\\\host\\ca\\foo\\bar", "\\\\host\\ca\\foo\\bar", S_OK},
242 {"file:\\\\host\\c|\\foo\\bar", "\\\\hostc|\\foo\\bar", S_OK},
243 {"file:\\%5Chost\\c:\\foo\\bar", "\\\\host\\c:\\foo\\bar", S_OK},
244 {"file:\\\\host\\cx:\\foo\\bar", "\\\\host\\cx:\\foo\\bar", S_OK},
245 {"file://c:/foo/bar", "c:\\foo\\bar", S_OK},
246 {"file://c:/d:/foo/bar", "c:\\d:\\foo\\bar", S_OK},
247 {"file://c|/d|/foo/bar", "c:\\d|\\foo\\bar", S_OK},
248 {"file://host/foo/bar", "\\\\host\\foo\\bar", S_OK},
249 {"file:/foo/bar", "\\foo\\bar", S_OK},
250 {"file:/foo/bar/", "\\foo\\bar\\", S_OK},
251 {"file:foo/bar", "foo\\bar", S_OK},
252 {"file:c:/foo/bar", "c:\\foo\\bar", S_OK},
253 {"file:c|/foo/bar", "c:\\foo\\bar", S_OK},
254 {"file:cx|/foo/bar", "cx|\\foo\\bar", S_OK},
255 {"file:////c:/foo/bar", "c:\\foo\\bar", S_OK},
256 /* {"file:////c:/foo/foo%20bar", "c:\\foo\\foo%20bar", S_OK},*/
257
258 {"c:\\foo\\bar", NULL, E_INVALIDARG},
259 {"foo/bar", NULL, E_INVALIDARG},
260 {"http://foo/bar", NULL, E_INVALIDARG},
261
262 };
263
264 struct {
265 char url[30];
266 const char *expect;
267 } TEST_URL_UNESCAPE[] = {
268 {"file://foo/bar", "file://foo/bar"},
269 {"file://fo%20o%5Ca/bar", "file://fo o\\a/bar"}
270 };
271
272
273 struct {
274 const char *path;
275 BOOL expect;
276 } TEST_PATH_IS_URL[] = {
277 {"http://foo/bar", TRUE},
278 {"c:\\foo\\bar", FALSE},
279 {"foo://foo/bar", TRUE},
280 {"foo\\bar", FALSE},
281 {"foo.bar", FALSE},
282 {"bogusscheme:", TRUE},
283 {"http:partial", TRUE}
284 };
285
286 struct {
287 const char *url;
288 BOOL expectOpaque;
289 BOOL expectFile;
290 } TEST_URLIS_ATTRIBS[] = {
291 { "ftp:", FALSE, FALSE },
292 { "http:", FALSE, FALSE },
293 { "gopher:", FALSE, FALSE },
294 { "mailto:", TRUE, FALSE },
295 { "news:", FALSE, FALSE },
296 { "nntp:", FALSE, FALSE },
297 { "telnet:", FALSE, FALSE },
298 { "wais:", FALSE, FALSE },
299 { "file:", FALSE, TRUE },
300 { "mk:", FALSE, FALSE },
301 { "https:", FALSE, FALSE },
302 { "shell:", TRUE, FALSE },
303 { "https:", FALSE, FALSE },
304 { "snews:", FALSE, FALSE },
305 { "local:", FALSE, FALSE },
306 { "javascript:", TRUE, FALSE },
307 { "vbscript:", TRUE, FALSE },
308 { "about:", TRUE, FALSE },
309 { "res:", FALSE, FALSE },
310 { "bogusscheme:", FALSE, FALSE },
311 { "file:\\\\e:\\b\\c", FALSE, TRUE },
312 { "file://e:/b/c", FALSE, TRUE },
313 { "http:partial", FALSE, FALSE },
314 { "mailto://www.winehq.org/test.html", TRUE, FALSE },
315 { "file:partial", FALSE, TRUE }
316 };
317
318 struct {
319 const char *path;
320 const char *result;
321 } TEST_PATH_UNQUOTE_SPACES[] = {
322 { "abcdef", "abcdef" },
323 { "\"abcdef\"", "abcdef" },
324 { "\"abcdef", "\"abcdef" },
325 { "abcdef\"", "abcdef\"" },
326 { "\"\"abcdef\"\"", "\"abcdef\"" },
327 { "abc\"def", "abc\"def" },
328 { "\"abc\"def", "\"abc\"def" },
329 { "\"abc\"def\"", "abc\"def" },
330 { "\'abcdef\'", "\'abcdef\'" },
331 { "\"\"", "" },
332 { "\"", "" }
333 };
334
335 static LPWSTR GetWideString(const char* szString)
336 {
337 LPWSTR wszString = HeapAlloc(GetProcessHeap(), 0, (2*INTERNET_MAX_URL_LENGTH) * sizeof(WCHAR));
338
339 MultiByteToWideChar(0, 0, szString, -1, wszString, INTERNET_MAX_URL_LENGTH);
340
341 return wszString;
342 }
343
344 static void FreeWideString(LPWSTR wszString)
345 {
346 HeapFree(GetProcessHeap(), 0, wszString);
347 }
348
349 static LPSTR strdupA(LPCSTR p)
350 {
351 LPSTR ret;
352 DWORD len = (strlen(p) + 1);
353 ret = HeapAlloc(GetProcessHeap(), 0, len);
354 memcpy(ret, p, len);
355 return ret;
356 }
357
358 static void hash_url(const char* szUrl)
359 {
360 LPCSTR szTestUrl = szUrl;
361 LPWSTR wszTestUrl = GetWideString(szTestUrl);
362
363 DWORD cbSize = sizeof(DWORD);
364 DWORD dwHash1, dwHash2;
365 ok(UrlHashA(szTestUrl, (LPBYTE)&dwHash1, cbSize) == S_OK, "UrlHashA didn't return S_OK\n");
366 ok(UrlHashW(wszTestUrl, (LPBYTE)&dwHash2, cbSize) == S_OK, "UrlHashW didn't return S_OK\n");
367
368 FreeWideString(wszTestUrl);
369
370 ok(dwHash1 == dwHash2, "Hashes didn't compare\n");
371 }
372
373 static void test_UrlHash(void)
374 {
375 hash_url(TEST_URL_1);
376 hash_url(TEST_URL_2);
377 hash_url(TEST_URL_3);
378 }
379
380 static void test_url_part(const char* szUrl, DWORD dwPart, DWORD dwFlags, const char* szExpected)
381 {
382 CHAR szPart[INTERNET_MAX_URL_LENGTH];
383 WCHAR wszPart[INTERNET_MAX_URL_LENGTH];
384 LPWSTR wszUrl = GetWideString(szUrl);
385 LPWSTR wszConvertedPart;
386
387 DWORD dwSize;
388
389 dwSize = INTERNET_MAX_URL_LENGTH;
390 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);
391 dwSize = INTERNET_MAX_URL_LENGTH;
392 ok( UrlGetPartW(wszUrl, wszPart, &dwSize, dwPart, dwFlags) == S_OK, "UrlGetPartW didn't return S_OK\n" );
393
394 wszConvertedPart = GetWideString(szPart);
395
396 ok(lstrcmpW(wszPart,wszConvertedPart)==0, "Strings didn't match between ascii and unicode UrlGetPart!\n");
397
398 FreeWideString(wszUrl);
399 FreeWideString(wszConvertedPart);
400
401 /* Note that v6.0 and later don't return '?' with the query */
402 ok(strcmp(szPart,szExpected)==0 ||
403 (*szExpected=='?' && !strcmp(szPart,szExpected+1)),
404 "Expected %s, but got %s\n", szExpected, szPart);
405 }
406
407 static void test_UrlGetPart(void)
408 {
409 CHAR szPart[INTERNET_MAX_URL_LENGTH];
410 DWORD dwSize;
411 HRESULT res;
412
413 dwSize = sizeof szPart;
414 szPart[0]='x'; szPart[1]=0;
415 res = UrlGetPartA("hi", szPart, &dwSize, URL_PART_SCHEME, 0);
416 todo_wine {
417 ok (res==S_FALSE, "UrlGetPartA(\"hi\") returned %08X\n", res);
418 ok(szPart[0]==0, "UrlGetPartA(\"hi\") return \"%s\" instead of \"\"\n", szPart);
419 }
420 dwSize = sizeof szPart;
421 szPart[0]='x'; szPart[1]=0;
422 res = UrlGetPartA("hi", szPart, &dwSize, URL_PART_QUERY, 0);
423 todo_wine {
424 ok (res==S_FALSE, "UrlGetPartA(\"hi\") returned %08X\n", res);
425 ok(szPart[0]==0, "UrlGetPartA(\"hi\") return \"%s\" instead of \"\"\n", szPart);
426 }
427
428 test_url_part(TEST_URL_3, URL_PART_HOSTNAME, 0, "localhost");
429 test_url_part(TEST_URL_3, URL_PART_PORT, 0, "21");
430 test_url_part(TEST_URL_3, URL_PART_USERNAME, 0, "foo");
431 test_url_part(TEST_URL_3, URL_PART_PASSWORD, 0, "bar");
432 test_url_part(TEST_URL_3, URL_PART_SCHEME, 0, "http");
433 test_url_part(TEST_URL_3, URL_PART_QUERY, 0, "?query=x&return=y");
434 }
435
436 static void test_url_escape(const char *szUrl, DWORD dwFlags, HRESULT dwExpectReturn, const char *szExpectUrl)
437 {
438 CHAR szReturnUrl[INTERNET_MAX_URL_LENGTH];
439 DWORD dwEscaped;
440 WCHAR ret_urlW[INTERNET_MAX_URL_LENGTH];
441 WCHAR *urlW, *expected_urlW;
442 dwEscaped=INTERNET_MAX_URL_LENGTH;
443
444 ok(UrlEscapeA(szUrl, szReturnUrl, &dwEscaped, dwFlags) == dwExpectReturn, "UrlEscapeA didn't return 0x%08x from \"%s\"\n", dwExpectReturn, szUrl);
445 ok(strcmp(szReturnUrl,szExpectUrl)==0, "Expected \"%s\", but got \"%s\" from \"%s\"\n", szExpectUrl, szReturnUrl, szUrl);
446
447 dwEscaped = INTERNET_MAX_URL_LENGTH;
448 urlW = GetWideString(szUrl);
449 expected_urlW = GetWideString(szExpectUrl);
450 ok(UrlEscapeW(urlW, ret_urlW, &dwEscaped, dwFlags) == dwExpectReturn, "UrlEscapeW didn't return 0x%08x from \"%s\"\n", dwExpectReturn, szUrl);
451 WideCharToMultiByte(CP_ACP,0,ret_urlW,-1,szReturnUrl,INTERNET_MAX_URL_LENGTH,0,0);
452 ok(lstrcmpW(ret_urlW, expected_urlW)==0, "Expected \"%s\", but got \"%s\" from \"%s\" flags %08x\n", szExpectUrl, szReturnUrl, szUrl, dwFlags);
453 FreeWideString(urlW);
454 FreeWideString(expected_urlW);
455
456 }
457
458 static void test_url_canonicalize(const char *szUrl, DWORD dwFlags, HRESULT dwExpectReturn, const char *szExpectUrl)
459 {
460 CHAR szReturnUrl[INTERNET_MAX_URL_LENGTH];
461 WCHAR wszReturnUrl[INTERNET_MAX_URL_LENGTH];
462 LPWSTR wszUrl = GetWideString(szUrl);
463 LPWSTR wszExpectUrl = GetWideString(szExpectUrl);
464 LPWSTR wszConvertedUrl;
465
466 DWORD dwSize;
467
468 dwSize = INTERNET_MAX_URL_LENGTH;
469 ok(UrlCanonicalizeA(szUrl, NULL, &dwSize, dwFlags) != dwExpectReturn, "Unexpected return for NULL buffer\n");
470 ok(UrlCanonicalizeA(szUrl, szReturnUrl, &dwSize, dwFlags) == dwExpectReturn, "UrlCanonicalizeA didn't return 0x%08x\n", dwExpectReturn);
471 ok(strcmp(szReturnUrl,szExpectUrl)==0, "UrlCanonicalizeA dwFlags 0x%08x Expected \"%s\", but got \"%s\"\n", dwFlags, szExpectUrl, szReturnUrl);
472
473 dwSize = INTERNET_MAX_URL_LENGTH;
474 ok(UrlCanonicalizeW(wszUrl, NULL, &dwSize, dwFlags) != dwExpectReturn, "Unexpected return for NULL buffer\n");
475 ok(UrlCanonicalizeW(wszUrl, wszReturnUrl, &dwSize, dwFlags) == dwExpectReturn, "UrlCanonicalizeW didn't return 0x%08x\n", dwExpectReturn);
476 wszConvertedUrl = GetWideString(szReturnUrl);
477 ok(lstrcmpW(wszReturnUrl, wszConvertedUrl)==0, "Strings didn't match between ascii and unicode UrlCanonicalize!\n");
478 FreeWideString(wszConvertedUrl);
479
480
481 FreeWideString(wszUrl);
482 FreeWideString(wszExpectUrl);
483 }
484
485
486 static void test_UrlEscape(void)
487 {
488 DWORD size;
489 HRESULT ret;
490 unsigned int i;
491
492 ret = UrlEscapeA("/woningplan/woonkamer basis.swf", NULL, &size, URL_ESCAPE_SPACES_ONLY);
493 ok(ret == E_INVALIDARG, "got %x, expected %x\n", ret, E_INVALIDARG);
494
495 for(i=0; i<sizeof(TEST_ESCAPE)/sizeof(TEST_ESCAPE[0]); i++) {
496 test_url_escape(TEST_ESCAPE[i].url, TEST_ESCAPE[i].flags,
497 TEST_ESCAPE[i].expectret, TEST_ESCAPE[i].expecturl);
498 }
499 }
500
501 static void test_UrlCanonicalize(void)
502 {
503 unsigned int i;
504 CHAR szReturnUrl[INTERNET_MAX_URL_LENGTH];
505 DWORD dwSize;
506 HRESULT hr;
507
508 for(i=0; i<sizeof(TEST_CANONICALIZE)/sizeof(TEST_CANONICALIZE[0]); i++) {
509 test_url_canonicalize(TEST_CANONICALIZE[i].url, TEST_CANONICALIZE[i].flags,
510 TEST_CANONICALIZE[i].expectret, TEST_CANONICALIZE[i].expecturl);
511 }
512
513 /* move to TEST_CANONICALIZE when fixed */
514 dwSize = sizeof szReturnUrl;
515 /*LimeWire online installer calls this*/
516 hr = UrlCanonicalizeA("/uri-res/N2R?urn:sha1:B3K", szReturnUrl, &dwSize,URL_DONT_ESCAPE_EXTRA_INFO | URL_WININET_COMPATIBILITY /*0x82000000*/);
517 ok(hr==S_OK,"UrlCanonicalizeA returned 0x%08x instead of S_OK\n", hr);
518 todo_wine {
519 ok(strcmp(szReturnUrl,"/uri-res/N2R?urn:sha1:B3K")==0, "UrlCanonicalizeA got \"%s\" instead of \"/uri-res/N2R?urn:sha1:B3K\"\n", szReturnUrl);
520 }
521 }
522
523 static void test_url_combine(const char *szUrl1, const char *szUrl2, DWORD dwFlags, HRESULT dwExpectReturn, const char *szExpectUrl)
524 {
525 HRESULT hr;
526 CHAR szReturnUrl[INTERNET_MAX_URL_LENGTH];
527 WCHAR wszReturnUrl[INTERNET_MAX_URL_LENGTH];
528 LPWSTR wszUrl1 = GetWideString(szUrl1);
529 LPWSTR wszUrl2 = GetWideString(szUrl2);
530 LPWSTR wszExpectUrl = GetWideString(szExpectUrl);
531 LPWSTR wszConvertedUrl;
532
533 DWORD dwSize;
534 DWORD dwExpectLen = lstrlen(szExpectUrl);
535
536 hr = UrlCombineA(szUrl1, szUrl2, NULL, NULL, dwFlags);
537 ok(hr == E_INVALIDARG, "UrlCombineA returned 0x%08x, expected 0x%08x\n", hr, E_INVALIDARG);
538
539 dwSize = 0;
540 hr = UrlCombineA(szUrl1, szUrl2, NULL, &dwSize, dwFlags);
541 ok(hr == E_POINTER, "Checking length of string, return was 0x%08x, expected 0x%08x\n", hr, E_POINTER);
542 ok(dwSize == dwExpectLen+1, "Got length %d, expected %d\n", dwSize, dwExpectLen+1);
543
544 dwSize--;
545 hr = UrlCombineA(szUrl1, szUrl2, szReturnUrl, &dwSize, dwFlags);
546 ok(hr == E_POINTER, "UrlCombineA returned 0x%08x, expected 0x%08x\n", hr, E_POINTER);
547 ok(dwSize == dwExpectLen+1, "Got length %d, expected %d\n", dwSize, dwExpectLen+1);
548
549 hr = UrlCombineA(szUrl1, szUrl2, szReturnUrl, &dwSize, dwFlags);
550 ok(hr == dwExpectReturn, "UrlCombineA returned 0x%08x, expected 0x%08x\n", hr, dwExpectReturn);
551 ok(dwSize == dwExpectLen, "Got length %d, expected %d\n", dwSize, dwExpectLen);
552 if(SUCCEEDED(hr)) {
553 ok(strcmp(szReturnUrl,szExpectUrl)==0, "Expected %s, but got %s\n", szExpectUrl, szReturnUrl);
554 }
555
556 dwSize = 0;
557 hr = UrlCombineW(wszUrl1, wszUrl2, NULL, &dwSize, dwFlags);
558 ok(hr == E_POINTER, "Checking length of string, return was 0x%08x, expected 0x%08x\n", hr, E_POINTER);
559 ok(dwSize == dwExpectLen+1, "Got length %d, expected %d\n", dwSize, dwExpectLen+1);
560
561 dwSize--;
562 hr = UrlCombineW(wszUrl1, wszUrl2, wszReturnUrl, &dwSize, dwFlags);
563 ok(hr == E_POINTER, "UrlCombineA returned 0x%08x, expected 0x%08x\n", hr, E_POINTER);
564 ok(dwSize == dwExpectLen+1, "Got length %d, expected %d\n", dwSize, dwExpectLen+1);
565
566 hr = UrlCombineW(wszUrl1, wszUrl2, wszReturnUrl, &dwSize, dwFlags);
567 ok(hr == dwExpectReturn, "UrlCombineW returned 0x%08x, expected 0x%08x\n", hr, dwExpectReturn);
568 ok(dwSize == dwExpectLen, "Got length %d, expected %d\n", dwSize, dwExpectLen);
569 if(SUCCEEDED(hr)) {
570 wszConvertedUrl = GetWideString(szReturnUrl);
571 ok(lstrcmpW(wszReturnUrl, wszConvertedUrl)==0, "Strings didn't match between ascii and unicode UrlCombine!\n");
572 FreeWideString(wszConvertedUrl);
573 }
574
575 FreeWideString(wszUrl1);
576 FreeWideString(wszUrl2);
577 FreeWideString(wszExpectUrl);
578 }
579
580 static void test_UrlCombine(void)
581 {
582 unsigned int i;
583 for(i=0; i<sizeof(TEST_COMBINE)/sizeof(TEST_COMBINE[0]); i++) {
584 test_url_combine(TEST_COMBINE[i].url1, TEST_COMBINE[i].url2, TEST_COMBINE[i].flags,
585 TEST_COMBINE[i].expectret, TEST_COMBINE[i].expecturl);
586 }
587 }
588
589 static void test_UrlCreateFromPath(void)
590 {
591 size_t i;
592 char ret_url[INTERNET_MAX_URL_LENGTH];
593 DWORD len, ret;
594 WCHAR ret_urlW[INTERNET_MAX_URL_LENGTH];
595 WCHAR *pathW, *urlW;
596
597 for(i = 0; i < sizeof(TEST_URLFROMPATH) / sizeof(TEST_URLFROMPATH[0]); i++) {
598 len = INTERNET_MAX_URL_LENGTH;
599 ret = UrlCreateFromPathA(TEST_URLFROMPATH[i].path, ret_url, &len, 0);
600 ok(ret == TEST_URLFROMPATH[i].ret, "ret %08x from path %s\n", ret, TEST_URLFROMPATH[i].path);
601 ok(!lstrcmpi(ret_url, TEST_URLFROMPATH[i].url), "url %s from path %s\n", ret_url, TEST_URLFROMPATH[i].path);
602 ok(len == strlen(ret_url), "ret len %d from path %s\n", len, TEST_URLFROMPATH[i].path);
603
604 len = INTERNET_MAX_URL_LENGTH;
605 pathW = GetWideString(TEST_URLFROMPATH[i].path);
606 urlW = GetWideString(TEST_URLFROMPATH[i].url);
607 ret = UrlCreateFromPathW(pathW, ret_urlW, &len, 0);
608 WideCharToMultiByte(CP_ACP, 0, ret_urlW, -1, ret_url, sizeof(ret_url),0,0);
609 ok(ret == TEST_URLFROMPATH[i].ret, "ret %08x from path L\"%s\", expected %08x\n",
610 ret, TEST_URLFROMPATH[i].path, TEST_URLFROMPATH[i].ret);
611 ok(!lstrcmpiW(ret_urlW, urlW), "got %s expected %s from path L\"%s\"\n", ret_url, TEST_URLFROMPATH[i].url, TEST_URLFROMPATH[i].path);
612 ok(len == lstrlenW(ret_urlW), "ret len %d from path L\"%s\"\n", len, TEST_URLFROMPATH[i].path);
613 FreeWideString(urlW);
614 FreeWideString(pathW);
615 }
616 }
617
618 static void test_UrlIs(void)
619 {
620 BOOL ret;
621 size_t i;
622 WCHAR wurl[80];
623
624 for(i = 0; i < sizeof(TEST_PATH_IS_URL) / sizeof(TEST_PATH_IS_URL[0]); i++) {
625 MultiByteToWideChar(CP_ACP, 0, TEST_PATH_IS_URL[i].path, -1, wurl, 80);
626
627 ret = UrlIsA( TEST_PATH_IS_URL[i].path, URLIS_URL );
628 ok( ret == TEST_PATH_IS_URL[i].expect,
629 "returned %d from path %s, expected %d\n", ret, TEST_PATH_IS_URL[i].path,
630 TEST_PATH_IS_URL[i].expect );
631
632 ret = UrlIsW( wurl, URLIS_URL );
633 ok( ret == TEST_PATH_IS_URL[i].expect,
634 "returned %d from path (UrlIsW) %s, expected %d\n", ret, TEST_PATH_IS_URL[i].path,
635 TEST_PATH_IS_URL[i].expect );
636 }
637 for(i = 0; i < sizeof(TEST_URLIS_ATTRIBS) / sizeof(TEST_URLIS_ATTRIBS[0]); i++) {
638 MultiByteToWideChar(CP_ACP, 0, TEST_URLIS_ATTRIBS[i].url, -1, wurl, 80);
639
640 ret = UrlIsA( TEST_URLIS_ATTRIBS[i].url, URLIS_OPAQUE);
641 ok( ret == TEST_URLIS_ATTRIBS[i].expectOpaque,
642 "returned %d for URLIS_OPAQUE, url \"%s\", expected %d\n", ret, TEST_URLIS_ATTRIBS[i].url,
643 TEST_URLIS_ATTRIBS[i].expectOpaque );
644 ret = UrlIsA( TEST_URLIS_ATTRIBS[i].url, URLIS_FILEURL);
645 ok( ret == TEST_URLIS_ATTRIBS[i].expectFile,
646 "returned %d for URLIS_FILEURL, url \"%s\", expected %d\n", ret, TEST_URLIS_ATTRIBS[i].url,
647 TEST_URLIS_ATTRIBS[i].expectFile );
648
649 ret = UrlIsW( wurl, URLIS_OPAQUE);
650 ok( ret == TEST_URLIS_ATTRIBS[i].expectOpaque,
651 "returned %d for URLIS_OPAQUE (UrlIsW), url \"%s\", expected %d\n", ret, TEST_URLIS_ATTRIBS[i].url,
652 TEST_URLIS_ATTRIBS[i].expectOpaque );
653 ret = UrlIsW( wurl, URLIS_FILEURL);
654 ok( ret == TEST_URLIS_ATTRIBS[i].expectFile,
655 "returned %d for URLIS_FILEURL (UrlIsW), url \"%s\", expected %d\n", ret, TEST_URLIS_ATTRIBS[i].url,
656 TEST_URLIS_ATTRIBS[i].expectFile );
657 }
658 }
659
660 static void test_UrlUnescape(void)
661 {
662 CHAR szReturnUrl[INTERNET_MAX_URL_LENGTH];
663 WCHAR ret_urlW[INTERNET_MAX_URL_LENGTH];
664 WCHAR *urlW, *expected_urlW;
665 DWORD dwEscaped;
666 size_t i;
667 static char inplace[] = "file:///C:/Program%20Files";
668 static WCHAR inplaceW[] = {'f','i','l','e',':','/','/','/','C',':','/',
669 'P','r','o','g','r','a','m','%','2','0','F','i','l','e','s',0};
670
671 for(i=0; i<sizeof(TEST_URL_UNESCAPE)/sizeof(TEST_URL_UNESCAPE[0]); i++) {
672 dwEscaped=INTERNET_MAX_URL_LENGTH;
673 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);
674 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);
675
676 dwEscaped = INTERNET_MAX_URL_LENGTH;
677 urlW = GetWideString(TEST_URL_UNESCAPE[i].url);
678 expected_urlW = GetWideString(TEST_URL_UNESCAPE[i].expect);
679 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);
680 WideCharToMultiByte(CP_ACP,0,ret_urlW,-1,szReturnUrl,INTERNET_MAX_URL_LENGTH,0,0);
681 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);
682 FreeWideString(urlW);
683 FreeWideString(expected_urlW);
684 }
685
686 dwEscaped = sizeof(inplace);
687 ok(UrlUnescapeA(inplace, NULL, &dwEscaped, URL_UNESCAPE_INPLACE) == S_OK, "UrlUnescapeA failed unexpectedly\n");
688
689 dwEscaped = sizeof(inplaceW);
690 ok(UrlUnescapeW(inplaceW, NULL, &dwEscaped, URL_UNESCAPE_INPLACE) == S_OK, "UrlUnescapeW failed unexpectedly\n");
691 }
692
693 static void test_PathSearchAndQualify(void)
694 {
695 WCHAR path1[] = {'c',':','\\','f','o','o',0};
696 WCHAR expect1[] = {'c',':','\\','f','o','o',0};
697 WCHAR path2[] = {'c',':','f','o','o',0};
698 WCHAR c_drive[] = {'c',':',0};
699 WCHAR foo[] = {'f','o','o',0};
700 WCHAR path3[] = {'\\','f','o','o',0};
701 WCHAR winini[] = {'w','i','n','.','i','n','i',0};
702 WCHAR out[MAX_PATH];
703 WCHAR cur_dir[MAX_PATH];
704 WCHAR dot[] = {'.',0};
705
706 /* c:\foo */
707 ok(PathSearchAndQualifyW(path1, out, MAX_PATH) != 0,
708 "PathSearchAndQualify rets 0\n");
709 ok(!lstrcmpiW(out, expect1), "strings don't match\n");
710
711 /* c:foo */
712 ok(PathSearchAndQualifyW(path2, out, MAX_PATH) != 0,
713 "PathSearchAndQualify rets 0\n");
714 GetFullPathNameW(c_drive, MAX_PATH, cur_dir, NULL);
715 PathAddBackslashW(cur_dir);
716 lstrcatW(cur_dir, foo);
717 ok(!lstrcmpiW(out, cur_dir), "strings don't match\n");
718
719 /* foo */
720 ok(PathSearchAndQualifyW(foo, out, MAX_PATH) != 0,
721 "PathSearchAndQualify rets 0\n");
722 GetFullPathNameW(dot, MAX_PATH, cur_dir, NULL);
723 PathAddBackslashW(cur_dir);
724 lstrcatW(cur_dir, foo);
725 ok(!lstrcmpiW(out, cur_dir), "strings don't match\n");
726
727 /* \foo */
728 ok(PathSearchAndQualifyW(path3, out, MAX_PATH) != 0,
729 "PathSearchAndQualify rets 0\n");
730 GetFullPathNameW(dot, MAX_PATH, cur_dir, NULL);
731 lstrcpyW(cur_dir + 2, path3);
732 ok(!lstrcmpiW(out, cur_dir), "strings don't match\n");
733
734 /* win.ini */
735 ok(PathSearchAndQualifyW(winini, out, MAX_PATH) != 0,
736 "PathSearchAndQualify rets 0\n");
737 if(!SearchPathW(NULL, winini, NULL, MAX_PATH, cur_dir, NULL))
738 GetFullPathNameW(winini, MAX_PATH, cur_dir, NULL);
739 ok(!lstrcmpiW(out, cur_dir), "strings don't match\n");
740
741 }
742
743 static void test_PathCreateFromUrl(void)
744 {
745 size_t i;
746 char ret_path[INTERNET_MAX_URL_LENGTH];
747 DWORD len, ret;
748 WCHAR ret_pathW[INTERNET_MAX_URL_LENGTH];
749 WCHAR *pathW, *urlW;
750 static const char url[] = "http://www.winehq.org";
751
752 /* Check ret_path = NULL */
753 len = sizeof(url);
754 ret = PathCreateFromUrlA(url, NULL, &len, 0);
755 ok ( ret == E_INVALIDARG, "got 0x%08x expected E_INVALIDARG\n", ret);
756
757 for(i = 0; i < sizeof(TEST_PATHFROMURL) / sizeof(TEST_PATHFROMURL[0]); i++) {
758 len = INTERNET_MAX_URL_LENGTH;
759 ret = PathCreateFromUrlA(TEST_PATHFROMURL[i].url, ret_path, &len, 0);
760 ok(ret == TEST_PATHFROMURL[i].ret, "ret %08x from url %s\n", ret, TEST_PATHFROMURL[i].url);
761 if(TEST_PATHFROMURL[i].path) {
762 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);
763 ok(len == strlen(ret_path), "ret len %d from url %s\n", len, TEST_PATHFROMURL[i].url);
764 }
765 len = INTERNET_MAX_URL_LENGTH;
766 pathW = GetWideString(TEST_PATHFROMURL[i].path);
767 urlW = GetWideString(TEST_PATHFROMURL[i].url);
768 ret = PathCreateFromUrlW(urlW, ret_pathW, &len, 0);
769 WideCharToMultiByte(CP_ACP, 0, ret_pathW, -1, ret_path, sizeof(ret_path),0,0);
770 ok(ret == TEST_PATHFROMURL[i].ret, "ret %08x from url L\"%s\"\n", ret, TEST_PATHFROMURL[i].url);
771 if(TEST_PATHFROMURL[i].path) {
772 ok(!lstrcmpiW(ret_pathW, pathW), "got %s expected %s from url L\"%s\"\n", ret_path, TEST_PATHFROMURL[i].path, TEST_PATHFROMURL[i].url);
773 ok(len == lstrlenW(ret_pathW), "ret len %d from url L\"%s\"\n", len, TEST_PATHFROMURL[i].url);
774 }
775 FreeWideString(urlW);
776 FreeWideString(pathW);
777 }
778 }
779
780
781 static void test_PathIsUrl(void)
782 {
783 size_t i;
784 BOOL ret;
785
786 for(i = 0; i < sizeof(TEST_PATH_IS_URL)/sizeof(TEST_PATH_IS_URL[0]); i++) {
787 ret = PathIsURLA(TEST_PATH_IS_URL[i].path);
788 ok(ret == TEST_PATH_IS_URL[i].expect,
789 "returned %d from path %s, expected %d\n", ret, TEST_PATH_IS_URL[i].path,
790 TEST_PATH_IS_URL[i].expect);
791 }
792 }
793
794 static const DWORD SHELL_charclass[] =
795 {
796 0x00000000, 0x00000000, 0x00000000, 0x00000000,
797 0x00000000, 0x00000000, 0x00000000, 0x00000000,
798 0x00000000, 0x00000000, 0x00000000, 0x00000000,
799 0x00000000, 0x00000000, 0x00000000, 0x00000000,
800 0x00000000, 0x00000000, 0x00000000, 0x00000000,
801 0x00000000, 0x00000000, 0x00000000, 0x00000000,
802 0x00000000, 0x00000000, 0x00000000, 0x00000000,
803 0x00000000, 0x00000000, 0x00000000, 0x00000000,
804 0x00000080, 0x00000100, 0x00000200, 0x00000100,
805 0x00000100, 0x00000100, 0x00000100, 0x00000100,
806 0x00000100, 0x00000100, 0x00000002, 0x00000100,
807 0x00000040, 0x00000100, 0x00000004, 0x00000000,
808 0x00000100, 0x00000100, 0x00000100, 0x00000100,
809 0x00000100, 0x00000100, 0x00000100, 0x00000100,
810 0x00000100, 0x00000100, 0x00000010, 0x00000020,
811 0x00000000, 0x00000100, 0x00000000, 0x00000001,
812 0x00000100, 0xffffffff, 0xffffffff, 0xffffffff,
813 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
814 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
815 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
816 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
817 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
818 0xffffffff, 0xffffffff, 0xffffffff, 0x00000100,
819 0x00000008, 0x00000100, 0x00000100, 0x00000100,
820 0x00000100, 0xffffffff, 0xffffffff, 0xffffffff,
821 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
822 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
823 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
824 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
825 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
826 0xffffffff, 0xffffffff, 0xffffffff, 0x00000100,
827 0x00000000, 0x00000100, 0x00000100
828 };
829
830 static void test_PathIsValidCharA(void)
831 {
832 BOOL ret;
833 unsigned int c;
834
835 ret = pPathIsValidCharA( 0x7f, 0 );
836 ok ( !ret, "PathIsValidCharA succeeded: 0x%08x\n", (DWORD)ret );
837
838 ret = pPathIsValidCharA( 0x7f, 1 );
839 ok ( !ret, "PathIsValidCharA succeeded: 0x%08x\n", (DWORD)ret );
840
841 for (c = 0; c < 0x7f; c++)
842 {
843 ret = pPathIsValidCharA( c, ~0U );
844 ok ( ret == SHELL_charclass[c] || (ret == 1 && SHELL_charclass[c] == 0xffffffff),
845 "PathIsValidCharA failed: 0x%02x got 0x%08x expected 0x%08x\n",
846 c, (DWORD)ret, SHELL_charclass[c] );
847 }
848
849 for (c = 0x7f; c <= 0xff; c++)
850 {
851 ret = pPathIsValidCharA( c, ~0U );
852 ok ( ret == 0x00000100,
853 "PathIsValidCharA failed: 0x%02x got 0x%08x expected 0x00000100\n",
854 c, (DWORD)ret );
855 }
856 }
857
858 static void test_PathIsValidCharW(void)
859 {
860 BOOL ret;
861 unsigned int c, err_count = 0;
862
863 ret = pPathIsValidCharW( 0x7f, 0 );
864 ok ( !ret, "PathIsValidCharW succeeded: 0x%08x\n", (DWORD)ret );
865
866 ret = pPathIsValidCharW( 0x7f, 1 );
867 ok ( !ret, "PathIsValidCharW succeeded: 0x%08x\n", (DWORD)ret );
868
869 for (c = 0; c < 0x7f; c++)
870 {
871 ret = pPathIsValidCharW( c, ~0U );
872 ok ( ret == SHELL_charclass[c] || (ret == 1 && SHELL_charclass[c] == 0xffffffff),
873 "PathIsValidCharW failed: 0x%02x got 0x%08x expected 0x%08x\n",
874 c, (DWORD)ret, SHELL_charclass[c] );
875 }
876
877 for (c = 0x007f; c <= 0xffff; c++)
878 {
879 ret = pPathIsValidCharW( c, ~0U );
880 ok ( ret == 0x00000100,
881 "PathIsValidCharW failed: 0x%02x got 0x%08x expected 0x00000100\n",
882 c, (DWORD)ret );
883 if (ret != 0x00000100)
884 {
885 if(++err_count > 100 ) {
886 trace("skipping rest of PathIsValidCharW tests "
887 "because of the current number of errors\n");
888 break;
889 }
890 }
891 }
892 }
893
894 static void test_PathMakePretty(void)
895 {
896 char buff[MAX_PATH];
897
898 ok (PathMakePrettyA(NULL) == FALSE, "PathMakePretty: NULL path succeeded\n");
899 buff[0] = '\0';
900 ok (PathMakePrettyA(buff) == TRUE, "PathMakePretty: Empty path failed\n");
901
902 strcpy(buff, "C:\\A LONG FILE NAME WITH \\SPACES.TXT");
903 ok (PathMakePrettyA(buff) == TRUE, "PathMakePretty: Long UC name failed\n");
904 ok (strcmp(buff, "C:\\a long file name with \\spaces.txt") == 0,
905 "PathMakePretty: Long UC name not changed\n");
906
907 strcpy(buff, "C:\\A LONG FILE NAME WITH \\MixedCase.TXT");
908 ok (PathMakePrettyA(buff) == FALSE, "PathMakePretty: Long MC name succeeded\n");
909 ok (strcmp(buff, "C:\\A LONG FILE NAME WITH \\MixedCase.TXT") == 0,
910 "PathMakePretty: Failed but modified path\n");
911
912 strcpy(buff, "TEST");
913 ok (PathMakePrettyA(buff) == TRUE, "PathMakePretty: Short name failed\n");
914 ok (strcmp(buff, "Test") == 0, "PathMakePretty: 1st char lowercased %s\n", buff);
915 }
916
917 static void test_PathMatchSpec(void)
918 {
919 static const char file[] = "c:\\foo\\bar\\filename.ext";
920 static const char spec1[] = ".ext";
921 static const char spec2[] = "*.ext";
922 static const char spec3[] = "*.ext ";
923 static const char spec4[] = " *.ext";
924 static const char spec5[] = "* .ext";
925 static const char spec6[] = "*. ext";
926 static const char spec7[] = "* . ext";
927 static const char spec8[] = "*.e?t";
928 static const char spec9[] = "filename.ext";
929 static const char spec10[] = "*bar\\filename.ext";
930 static const char spec11[] = " foo; *.ext";
931 static const char spec12[] = "*.ext;*.bar";
932 static const char spec13[] = "*bar*";
933
934 ok (PathMatchSpecA(file, spec1) == FALSE, "PathMatchSpec: Spec1 failed\n");
935 ok (PathMatchSpecA(file, spec2) == TRUE, "PathMatchSpec: Spec2 failed\n");
936 ok (PathMatchSpecA(file, spec3) == FALSE, "PathMatchSpec: Spec3 failed\n");
937 ok (PathMatchSpecA(file, spec4) == TRUE, "PathMatchSpec: Spec4 failed\n");
938 todo_wine ok (PathMatchSpecA(file, spec5) == TRUE, "PathMatchSpec: Spec5 failed\n");
939 todo_wine ok (PathMatchSpecA(file, spec6) == TRUE, "PathMatchSpec: Spec6 failed\n");
940 ok (PathMatchSpecA(file, spec7) == FALSE, "PathMatchSpec: Spec7 failed\n");
941 ok (PathMatchSpecA(file, spec8) == TRUE, "PathMatchSpec: Spec8 failed\n");
942 ok (PathMatchSpecA(file, spec9) == FALSE, "PathMatchSpec: Spec9 failed\n");
943 ok (PathMatchSpecA(file, spec10) == TRUE, "PathMatchSpec: Spec10 failed\n");
944 ok (PathMatchSpecA(file, spec11) == TRUE, "PathMatchSpec: Spec11 failed\n");
945 ok (PathMatchSpecA(file, spec12) == TRUE, "PathMatchSpec: Spec12 failed\n");
946 ok (PathMatchSpecA(file, spec13) == TRUE, "PathMatchSpec: Spec13 failed\n");
947 }
948
949 static void test_PathCombineW(void)
950 {
951 LPWSTR wszString, wszString2;
952 WCHAR wbuf[MAX_PATH+1], wstr1[MAX_PATH] = {'C',':','\\',0}, wstr2[MAX_PATH];
953 static const WCHAR expout[] = {'C',':','\\','A','A',0};
954 int i;
955
956 wszString2 = HeapAlloc(GetProcessHeap(), 0, MAX_PATH * sizeof(WCHAR));
957
958 /* NULL test */
959 wszString = pPathCombineW(NULL, NULL, NULL);
960 ok (wszString == NULL, "Expected a NULL return\n");
961
962 /* Some NULL */
963 wszString2[0] = 'a';
964 wszString = pPathCombineW(wszString2, NULL, NULL);
965 ok (wszString == NULL, "Expected a NULL return\n");
966 ok (wszString2[0] == 0, "Destination string not empty\n");
967
968 HeapFree(GetProcessHeap(), 0, wszString2);
969
970 /* overflow test */
971 wstr2[0] = wstr2[1] = wstr2[2] = 'A';
972 for (i=3; i<MAX_PATH/2; i++)
973 wstr1[i] = wstr2[i] = 'A';
974 wstr1[(MAX_PATH/2) - 1] = wstr2[MAX_PATH/2] = 0;
975 memset(wbuf, 0xbf, sizeof(wbuf));
976
977 wszString = pPathCombineW(wbuf, wstr1, wstr2);
978 ok(wszString == NULL, "Expected a NULL return\n");
979 ok(wbuf[0] == 0, "Buffer contains data\n");
980
981 /* PathCombineW can be used in place */
982 wstr1[3] = 0;
983 wstr2[2] = 0;
984 ok(PathCombineW(wstr1, wstr1, wstr2) == wstr1, "Expected a wstr1 return\n");
985 ok(StrCmpW(wstr1, expout) == 0, "Unexpected PathCombine output\n");
986 }
987
988
989 #define LONG_LEN (MAX_PATH * 2)
990 #define HALF_LEN (MAX_PATH / 2 + 1)
991
992 static void test_PathCombineA(void)
993 {
994 LPSTR str;
995 char dest[MAX_PATH];
996 char too_long[LONG_LEN];
997 char one[HALF_LEN], two[HALF_LEN];
998
999 /* try NULL dest */
1000 SetLastError(0xdeadbeef);
1001 str = PathCombineA(NULL, "C:\\", "one\\two\\three");
1002 ok(str == NULL, "Expected NULL, got %p\n", str);
1003 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1004
1005 /* try NULL dest and NULL directory */
1006 SetLastError(0xdeadbeef);
1007 str = PathCombineA(NULL, NULL, "one\\two\\three");
1008 ok(str == NULL, "Expected NULL, got %p\n", str);
1009 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1010
1011 /* try all NULL*/
1012 SetLastError(0xdeadbeef);
1013 str = PathCombineA(NULL, NULL, NULL);
1014 ok(str == NULL, "Expected NULL, got %p\n", str);
1015 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1016
1017 /* try NULL file part */
1018 SetLastError(0xdeadbeef);
1019 lstrcpyA(dest, "control");
1020 str = PathCombineA(dest, "C:\\", NULL);
1021 ok(str == dest, "Expected str == dest, got %p\n", str);
1022 ok(!lstrcmp(str, "C:\\"), "Expected C:\\, got %s\n", str);
1023 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1024
1025 /* try empty file part */
1026 SetLastError(0xdeadbeef);
1027 lstrcpyA(dest, "control");
1028 str = PathCombineA(dest, "C:\\", "");
1029 ok(str == dest, "Expected str == dest, got %p\n", str);
1030 ok(!lstrcmp(str, "C:\\"), "Expected C:\\, got %s\n", str);
1031 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1032
1033 /* try empty directory and file part */
1034 SetLastError(0xdeadbeef);
1035 lstrcpyA(dest, "control");
1036 str = PathCombineA(dest, "", "");
1037 ok(str == dest, "Expected str == dest, got %p\n", str);
1038 ok(!lstrcmp(str, "\\"), "Expected \\, got %s\n", str);
1039 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1040
1041 /* try NULL directory */
1042 SetLastError(0xdeadbeef);
1043 lstrcpyA(dest, "control");
1044 str = PathCombineA(dest, NULL, "one\\two\\three");
1045 ok(str == dest, "Expected str == dest, got %p\n", str);
1046 ok(!lstrcmp(str, "one\\two\\three"), "Expected one\\two\\three, got %s\n", str);
1047 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1048
1049 /* try NULL directory and empty file part */
1050 SetLastError(0xdeadbeef);
1051 lstrcpyA(dest, "control");
1052 str = PathCombineA(dest, NULL, "");
1053 ok(str == dest, "Expected str == dest, got %p\n", str);
1054 ok(!lstrcmp(str, "\\"), "Expected \\, got %s\n", str);
1055 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1056
1057 /* try NULL directory and file part */
1058 SetLastError(0xdeadbeef);
1059 lstrcpyA(dest, "control");
1060 str = PathCombineA(dest, NULL, NULL);
1061 ok(str == NULL, "Expected str == NULL, got %p\n", str);
1062 ok(lstrlenA(dest) == 0, "Expected 0 length, got %i\n", lstrlenA(dest));
1063 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1064
1065 /* try directory without backslash */
1066 SetLastError(0xdeadbeef);
1067 lstrcpyA(dest, "control");
1068 str = PathCombineA(dest, "C:", "one\\two\\three");
1069 ok(str == dest, "Expected str == dest, got %p\n", str);
1070 ok(!lstrcmp(str, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", str);
1071 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1072
1073 /* try directory with backslash */
1074 SetLastError(0xdeadbeef);
1075 lstrcpyA(dest, "control");
1076 str = PathCombineA(dest, "C:\\", "one\\two\\three");
1077 ok(str == dest, "Expected str == dest, got %p\n", str);
1078 ok(!lstrcmp(str, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", str);
1079 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1080
1081 /* try directory with backslash and file with prepended backslash */
1082 SetLastError(0xdeadbeef);
1083 lstrcpyA(dest, "control");
1084 str = PathCombineA(dest, "C:\\", "\\one\\two\\three");
1085 ok(str == dest, "Expected str == dest, got %p\n", str);
1086 ok(!lstrcmp(str, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", str);
1087 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1088
1089 /* try previous test, with backslash appended as well */
1090 SetLastError(0xdeadbeef);
1091 lstrcpyA(dest, "control");
1092 str = PathCombineA(dest, "C:\\", "\\one\\two\\three\\");
1093 ok(str == dest, "Expected str == dest, got %p\n", str);
1094 ok(!lstrcmp(str, "C:\\one\\two\\three\\"), "Expected C:\\one\\two\\three\\, got %s\n", str);
1095 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1096
1097 /* try a relative directory */
1098 SetLastError(0xdeadbeef);
1099 lstrcpyA(dest, "control");
1100 str = PathCombineA(dest, "relative\\dir", "\\one\\two\\three\\");
1101 ok(str == dest, "Expected str == dest, got %p\n", str);
1102 ok(!lstrcmp(str, "one\\two\\three\\"), "Expected one\\two\\three\\, got %s\n", str);
1103 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1104
1105 /* try forward slashes */
1106 SetLastError(0xdeadbeef);
1107 lstrcpyA(dest, "control");
1108 str = PathCombineA(dest, "C:\\", "one/two/three\\");
1109 ok(str == dest, "Expected str == dest, got %p\n", str);
1110 ok(!lstrcmp(str, "C:\\one/two/three\\"), "Expected one/two/three\\, got %s\n", str);
1111 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1112
1113 /* try a really weird directory */
1114 SetLastError(0xdeadbeef);
1115 lstrcpyA(dest, "control");
1116 str = PathCombineA(dest, "C:\\/\\/", "\\one\\two\\three\\");
1117 ok(str == dest, "Expected str == dest, got %p\n", str);
1118 ok(!lstrcmp(str, "C:\\one\\two\\three\\"), "Expected C:\\one\\two\\three\\, got %s\n", str);
1119 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1120
1121 /* try periods */
1122 SetLastError(0xdeadbeef);
1123 lstrcpyA(dest, "control");
1124 str = PathCombineA(dest, "C:\\", "one\\..\\two\\.\\three");
1125 ok(str == dest, "Expected str == dest, got %p\n", str);
1126 ok(!lstrcmp(str, "C:\\two\\three"), "Expected C:\\two\\three, got %s\n", str);
1127 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1128
1129 /* try .. as file */
1130 /* try forward slashes */
1131 SetLastError(0xdeadbeef);
1132 lstrcpyA(dest, "control");
1133 str = PathCombineA(dest, "C:\\", "..");
1134 ok(str == dest, "Expected str == dest, got %p\n", str);
1135 ok(!lstrcmp(str, "C:\\"), "Expected C:\\, got %s\n", str);
1136 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1137
1138 memset(too_long, 'a', LONG_LEN);
1139 too_long[LONG_LEN - 1] = '\0';
1140
1141 /* try a file longer than MAX_PATH */
1142 SetLastError(0xdeadbeef);
1143 lstrcpyA(dest, "control");
1144 str = PathCombineA(dest, "C:\\", too_long);
1145 ok(str == NULL, "Expected str == NULL, got %p\n", str);
1146 ok(lstrlenA(dest) == 0, "Expected 0 length, got %i\n", lstrlenA(dest));
1147 todo_wine ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1148
1149 /* try a directory longer than MAX_PATH */
1150 SetLastError(0xdeadbeef);
1151 lstrcpyA(dest, "control");
1152 str = PathCombineA(dest, too_long, "one\\two\\three");
1153 ok(str == NULL, "Expected str == NULL, got %p\n", str);
1154 ok(lstrlenA(dest) == 0, "Expected 0 length, got %i\n", lstrlenA(dest));
1155 todo_wine ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1156
1157 memset(one, 'b', HALF_LEN);
1158 memset(two, 'c', HALF_LEN);
1159 one[HALF_LEN - 1] = '\0';
1160 two[HALF_LEN - 1] = '\0';
1161
1162 /* destination string is longer than MAX_PATH, but not the constituent parts */
1163 SetLastError(0xdeadbeef);
1164 lstrcpyA(dest, "control");
1165 str = PathCombineA(dest, one, two);
1166 ok(str == NULL, "Expected str == NULL, got %p\n", str);
1167 ok(lstrlenA(dest) == 0, "Expected 0 length, got %i\n", lstrlenA(dest));
1168 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1169 }
1170
1171 static void test_PathAddBackslash(void)
1172 {
1173 LPSTR str;
1174 char path[MAX_PATH];
1175 char too_long[LONG_LEN];
1176
1177 /* try a NULL path */
1178 SetLastError(0xdeadbeef);
1179 str = PathAddBackslashA(NULL);
1180 ok(str == NULL, "Expected str == NULL, got %p\n", str);
1181 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1182
1183 /* try an empty path */
1184 path[0] = '\0';
1185 SetLastError(0xdeadbeef);
1186 str = PathAddBackslashA(path);
1187 ok(str == (path + lstrlenA(path)), "Expected str to point to end of path, got %p\n", str);
1188 ok(lstrlenA(path) == 0, "Expected empty string, got %i\n", lstrlenA(path));
1189 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1190
1191 /* try a relative path */
1192 lstrcpyA(path, "one\\two");
1193 SetLastError(0xdeadbeef);
1194 str = PathAddBackslashA(path);
1195 ok(str == (path + lstrlenA(path)), "Expected str to point to end of path, got %p\n", str);
1196 ok(!lstrcmp(path, "one\\two\\"), "Expected one\\two\\, got %s\n", path);
1197 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1198
1199 /* try periods */
1200 lstrcpyA(path, "one\\..\\two");
1201 SetLastError(0xdeadbeef);
1202 str = PathAddBackslashA(path);
1203 ok(str == (path + lstrlenA(path)), "Expected str to point to end of path, got %p\n", str);
1204 ok(!lstrcmp(path, "one\\..\\two\\"), "Expected one\\..\\two\\, got %s\n", path);
1205 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1206
1207 /* try just a space */
1208 lstrcpyA(path, " ");
1209 SetLastError(0xdeadbeef);
1210 str = PathAddBackslashA(path);
1211 ok(str == (path + lstrlenA(path)), "Expected str to point to end of path, got %p\n", str);
1212 ok(!lstrcmp(path, " \\"), "Expected \\, got %s\n", path);
1213 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1214
1215 /* path already has backslash */
1216 lstrcpyA(path, "C:\\one\\");
1217 SetLastError(0xdeadbeef);
1218 str = PathAddBackslashA(path);
1219 ok(str == (path + lstrlenA(path)), "Expected str to point to end of path, got %p\n", str);
1220 ok(!lstrcmp(path, "C:\\one\\"), "Expected C:\\one\\, got %s\n", path);
1221 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1222
1223 memset(too_long, 'a', LONG_LEN);
1224 too_long[LONG_LEN - 1] = '\0';
1225
1226 /* path is longer than MAX_PATH */
1227 SetLastError(0xdeadbeef);
1228 str = PathAddBackslashA(too_long);
1229 ok(str == NULL, "Expected str == NULL, got %p\n", str);
1230 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1231 }
1232
1233 static void test_PathAppendA(void)
1234 {
1235 char path[MAX_PATH];
1236 char too_long[LONG_LEN];
1237 char one[HALF_LEN], two[HALF_LEN];
1238 BOOL res;
1239
1240 lstrcpy(path, "C:\\one");
1241
1242 /* try NULL pszMore */
1243 SetLastError(0xdeadbeef);
1244 res = PathAppendA(path, NULL);
1245 ok(!res, "Expected failure\n");
1246 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1247 ok(!lstrcmp(path, "C:\\one"), "Expected C:\\one, got %s\n", path);
1248
1249 /* try empty pszMore */
1250 SetLastError(0xdeadbeef);
1251 res = PathAppendA(path, "");
1252 ok(res, "Expected success\n");
1253 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1254 ok(!lstrcmp(path, "C:\\one"), "Expected C:\\one, got %s\n", path);
1255
1256 /* try NULL pszPath */
1257 SetLastError(0xdeadbeef);
1258 res = PathAppendA(NULL, "two\\three");
1259 ok(!res, "Expected failure\n");
1260 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1261
1262 /* try empty pszPath */
1263 path[0] = '\0';
1264 SetLastError(0xdeadbeef);
1265 res = PathAppendA(path, "two\\three");
1266 ok(res, "Expected success\n");
1267 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1268 ok(!lstrcmp(path, "two\\three"), "Expected \\two\\three, got %s\n", path);
1269
1270 /* try empty pszPath and empty pszMore */
1271 path[0] = '\0';
1272 SetLastError(0xdeadbeef);
1273 res = PathAppendA(path, "");
1274 ok(res, "Expected success\n");
1275 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1276 ok(!lstrcmp(path, "\\"), "Expected \\, got %s\n", path);
1277
1278 /* try legit params */
1279 lstrcpy(path, "C:\\one");
1280 SetLastError(0xdeadbeef);
1281 res = PathAppendA(path, "two\\three");
1282 ok(res, "Expected success\n");
1283 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1284 ok(!lstrcmp(path, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", path);
1285
1286 /* try pszPath with backslash after it */
1287 lstrcpy(path, "C:\\one\\");
1288 SetLastError(0xdeadbeef);
1289 res = PathAppendA(path, "two\\three");
1290 ok(res, "Expected success\n");
1291 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1292 ok(!lstrcmp(path, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", path);
1293
1294 /* try pszMore with backslash before it */
1295 lstrcpy(path, "C:\\one");
1296 SetLastError(0xdeadbeef);
1297 res = PathAppendA(path, "\\two\\three");
1298 ok(res, "Expected success\n");
1299 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1300 ok(!lstrcmp(path, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", path);
1301
1302 /* try pszMore with backslash after it */
1303 lstrcpy(path, "C:\\one");
1304 SetLastError(0xdeadbeef);
1305 res = PathAppendA(path, "two\\three\\");
1306 ok(res, "Expected success\n");
1307 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1308 ok(!lstrcmp(path, "C:\\one\\two\\three\\"), "Expected C:\\one\\two\\three\\, got %s\n", path);
1309
1310 /* try spaces in pszPath */
1311 lstrcpy(path, "C: \\ one ");
1312 SetLastError(0xdeadbeef);
1313 res = PathAppendA(path, "two\\three");
1314 ok(res, "Expected success\n");
1315 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1316 ok(!lstrcmp(path, "C: \\ one \\two\\three"), "Expected C: \\ one \\two\\three, got %s\n", path);
1317
1318 /* try spaces in pszMore */
1319 lstrcpy(path, "C:\\one");
1320 SetLastError(0xdeadbeef);
1321 res = PathAppendA(path, " two \\ three ");
1322 ok(res, "Expected success\n");
1323 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1324 ok(!lstrcmp(path, "C:\\one\\ two \\ three "), "Expected 'C:\\one\\ two \\ three ', got %s\n", path);
1325
1326 /* pszPath is too long */
1327 memset(too_long, 'a', LONG_LEN);
1328 too_long[LONG_LEN - 1] = '\0';
1329 SetLastError(0xdeadbeef);
1330 res = PathAppendA(too_long, "two\\three");
1331 ok(!res, "Expected failure\n");
1332 todo_wine ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1333 ok(lstrlen(too_long) == 0, "Expected length of too_long to be zero, got %i\n", lstrlen(too_long));
1334
1335 /* pszMore is too long */
1336 lstrcpy(path, "C:\\one");
1337 memset(too_long, 'a', LONG_LEN);
1338 too_long[LONG_LEN - 1] = '\0';
1339 SetLastError(0xdeadbeef);
1340 res = PathAppendA(path, too_long);
1341 ok(!res, "Expected failure\n");
1342 todo_wine ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1343 ok(lstrlen(path) == 0, "Expected length of path to be zero, got %i\n", lstrlen(path));
1344
1345 /* both params combined are too long */
1346 memset(one, 'a', HALF_LEN);
1347 one[HALF_LEN - 1] = '\0';
1348 memset(two, 'b', HALF_LEN);
1349 two[HALF_LEN - 1] = '\0';
1350 SetLastError(0xdeadbeef);
1351 res = PathAppendA(one, two);
1352 ok(!res, "Expected failure\n");
1353 ok(lstrlen(one) == 0, "Expected length of one to be zero, got %i\n", lstrlen(one));
1354 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1355 }
1356
1357 static void test_PathCanonicalizeA(void)
1358 {
1359 char dest[MAX_PATH];
1360 char too_long[LONG_LEN];
1361 BOOL res;
1362
1363 /* try a NULL source */
1364 lstrcpy(dest, "test");
1365 SetLastError(0xdeadbeef);
1366 res = PathCanonicalizeA(dest, NULL);
1367 ok(!res, "Expected failure\n");
1368 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1369 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1370 todo_wine
1371 {
1372 ok(!lstrcmp(dest, "test"), "Expected test, got %s\n", dest);
1373 }
1374
1375 /* try an empty source */
1376 lstrcpy(dest, "test");
1377 SetLastError(0xdeadbeef);
1378 res = PathCanonicalizeA(dest, "");
1379 ok(res, "Expected success\n");
1380 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1381 ok(!lstrcmp(dest, "\\"), "Expected \\, got %s\n", dest);
1382
1383 /* try a NULL dest */
1384 SetLastError(0xdeadbeef);
1385 res = PathCanonicalizeA(NULL, "C:\\");
1386 ok(!res, "Expected failure\n");
1387 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1388 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1389
1390 /* try empty dest */
1391 dest[0] = '\0';
1392 SetLastError(0xdeadbeef);
1393 res = PathCanonicalizeA(dest, "C:\\");
1394 ok(res, "Expected success\n");
1395 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1396 ok(!lstrcmp(dest, "C:\\"), "Expected C:\\, got %s\n", dest);
1397
1398 /* try non-empty dest */
1399 lstrcpy(dest, "test");
1400 SetLastError(0xdeadbeef);
1401 res = PathCanonicalizeA(dest, "C:\\");
1402 ok(res, "Expected success\n");
1403 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1404 ok(!lstrcmp(dest, "C:\\"), "Expected C:\\, got %s\n", dest);
1405
1406 /* try a space for source */
1407 lstrcpy(dest, "test");
1408 SetLastError(0xdeadbeef);
1409 res = PathCanonicalizeA(dest, " ");
1410 ok(res, "Expected success\n");
1411 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1412 ok(!lstrcmp(dest, " "), "Expected ' ', got %s\n", dest);
1413
1414 /* try a relative path */
1415 lstrcpy(dest, "test");
1416 SetLastError(0xdeadbeef);
1417 res = PathCanonicalizeA(dest, "one\\two");
1418 ok(res, "Expected success\n");
1419 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1420 ok(!lstrcmp(dest, "one\\two"), "Expected one\\two, got %s\n", dest);
1421
1422 /* try current dir and previous dir */
1423 lstrcpy(dest, "test");
1424 SetLastError(0xdeadbeef);
1425 res = PathCanonicalizeA(dest, "C:\\one\\.\\..\\two\\three\\..");
1426 ok(res, "Expected success\n");
1427 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1428 ok(!lstrcmp(dest, "C:\\two"), "Expected C:\\two, got %s\n", dest);
1429
1430 /* try simple forward slashes */
1431 lstrcpy(dest, "test");
1432 SetLastError(0xdeadbeef);
1433 res = PathCanonicalizeA(dest, "C:\\one/two/three\\four/five\\six");
1434 ok(res, "Expected success\n");
1435 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1436 ok(!lstrcmp(dest, "C:\\one/two/three\\four/five\\six"),
1437 "Expected C:\\one/two/three\\four/five\\six, got %s\n", dest);
1438
1439 /* try simple forward slashes with same dir */
1440 lstrcpy(dest, "test");
1441 SetLastError(0xdeadbeef);
1442 res = PathCanonicalizeA(dest, "C:\\one/.\\two");
1443 ok(res, "Expected success\n");
1444 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1445 ok(!lstrcmp(dest, "C:\\one/.\\two"), "Expected C:\\one/.\\two, got %s\n", dest);
1446
1447 /* try simple forward slashes with change dir */
1448 lstrcpy(dest, "test");
1449 SetLastError(0xdeadbeef);
1450 res = PathCanonicalizeA(dest, "C:\\one/.\\two\\..");
1451 ok(res, "Expected success\n");
1452 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1453 ok(!lstrcmp(dest, "C:\\one/."), "Expected C:\\one/., got %s\n", dest);
1454
1455 /* try forward slashes with change dirs
1456 * NOTE: if there is a forward slash in between two backslashes,
1457 * everything in between the two backslashes is considered on dir
1458 */
1459 lstrcpy(dest, "test");
1460 SetLastError(0xdeadbeef);
1461 res = PathCanonicalizeA(dest, "C:\\one/.\\..\\two/three\\..\\four/.five");
1462 ok(res, "Expected success\n");
1463 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1464 ok(!lstrcmp(dest, "C:\\four/.five"), "Expected C:\\four/.five, got %s\n", dest);
1465
1466 /* try src is too long */
1467 memset(too_long, 'a', LONG_LEN);
1468 too_long[LONG_LEN - 1] = '\0';
1469 lstrcpy(dest, "test");
1470 SetLastError(0xdeadbeef);
1471 res = PathCanonicalizeA(dest, too_long);
1472 todo_wine
1473 {
1474 ok(!res, "Expected failure\n");
1475 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1476 }
1477 ok(lstrlen(too_long) == LONG_LEN - 1, "Expected length LONG_LEN - 1, got %i\n", lstrlen(too_long));
1478 }
1479
1480 static void test_PathFindExtensionA(void)
1481 {
1482 LPSTR ext;
1483 char path[MAX_PATH];
1484 char too_long[LONG_LEN];
1485
1486 /* try a NULL path */
1487 SetLastError(0xdeadbeef);
1488 ext = PathFindExtensionA(NULL);
1489 ok(ext == NULL, "Expected NULL, got %p\n", ext);
1490 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1491
1492 /* try an empty path */
1493 path[0] = '\0';
1494 SetLastError(0xdeadbeef);
1495 ext = PathFindExtensionA(path);
1496 ok(ext == path, "Expected ext == path, got %p\n", ext);
1497 ok(lstrlen(ext) == 0, "Expected length 0, got %i\n", lstrlen(ext));
1498 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1499
1500 /* try a path without an extension */
1501 lstrcpy(path, "file");
1502 SetLastError(0xdeadbeef);
1503 ext = PathFindExtensionA(path);
1504 ok(ext == path + lstrlen(path), "Expected ext == path, got %p\n", ext);
1505 ok(lstrlen(ext) == 0, "Expected length 0, got %i\n", lstrlen(ext));
1506 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1507
1508 /* try a path with an extension */
1509 lstrcpy(path, "file.txt");
1510 SetLastError(0xdeadbeef);
1511 ext = PathFindExtensionA(path);
1512 ok(ext == path + lstrlen("file"),
1513 "Expected ext == path + lstrlen(\"file\"), got %p\n", ext);
1514 ok(!lstrcmp(ext, ".txt"), "Expected .txt, got %s\n", ext);
1515 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1516
1517 /* try a path with two extensions */
1518 lstrcpy(path, "file.txt.doc");
1519 SetLastError(0xdeadbeef);
1520 ext = PathFindExtensionA(path);
1521 ok(ext == path + lstrlen("file.txt"),
1522 "Expected ext == path + lstrlen(\"file.txt\"), got %p\n", ext);
1523 ok(!lstrcmp(ext, ".doc"), "Expected .txt, got %s\n", ext);
1524 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1525
1526 /* try a path longer than MAX_PATH without an extension*/
1527 memset(too_long, 'a', LONG_LEN);
1528 too_long[LONG_LEN - 1] = '\0';
1529 SetLastError(0xdeadbeef);
1530 ext = PathFindExtensionA(too_long);
1531 ok(ext == too_long + LONG_LEN - 1, "Expected ext == too_long + LONG_LEN - 1, got %p\n", ext);
1532 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1533
1534 /* try a path longer than MAX_PATH with an extension*/
1535 memset(too_long, 'a', LONG_LEN);
1536 too_long[LONG_LEN - 1] = '\0';
1537 lstrcpy(too_long + 300, ".abcde");
1538 too_long[lstrlen(too_long)] = 'a';
1539 SetLastError(0xdeadbeef);
1540 ext = PathFindExtensionA(too_long);
1541 ok(ext == too_long + 300, "Expected ext == too_long + 300, got %p\n", ext);
1542 ok(lstrlen(ext) == LONG_LEN - 301, "Expected LONG_LEN - 301, got %i\n", lstrlen(ext));
1543 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1544 }
1545
1546 static void test_PathBuildRootA(void)
1547 {
1548 LPSTR root;
1549 char path[10];
1550 char root_expected[26][4];
1551 char drive;
1552 int j;
1553
1554 /* set up the expected paths */
1555 for (drive = 'A'; drive <= 'Z'; drive++)
1556 sprintf(root_expected[drive - 'A'], "%c:\\", drive);
1557
1558 /* test the expected values */
1559 for (j = 0; j < 26; j++)
1560 {
1561 SetLastError(0xdeadbeef);
1562 lstrcpy(path, "aaaaaaaaa");
1563 root = PathBuildRootA(path, j);
1564 ok(root == path, "Expected root == path, got %p\n", root);
1565 ok(!lstrcmp(root, root_expected[j]), "Expected %s, got %s\n", root_expected[j], root);
1566 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1567 }
1568
1569 /* test a negative drive number */
1570 SetLastError(0xdeadbeef);
1571 lstrcpy(path, "aaaaaaaaa");
1572 root = PathBuildRootA(path, -1);
1573 ok(root == path, "Expected root == path, got %p\n", root);
1574 ok(!lstrcmp(path, "aaaaaaaaa"), "Expected aaaaaaaaa, got %s\n", path);
1575 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1576
1577 /* test a drive number greater than 25 */
1578 SetLastError(0xdeadbeef);
1579 lstrcpy(path, "aaaaaaaaa");
1580 root = PathBuildRootA(path, 26);
1581 ok(root == path, "Expected root == path, got %p\n", root);
1582 ok(!lstrcmp(path, "aaaaaaaaa"), "Expected aaaaaaaaa, got %s\n", path);
1583 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1584
1585 /* length of path is less than 4 */
1586 SetLastError(0xdeadbeef);
1587 lstrcpy(path, "aa");
1588 root = PathBuildRootA(path, 0);
1589 ok(root == path, "Expected root == path, got %p\n", root);
1590 ok(!lstrcmp(path, "A:\\"), "Expected A:\\, got %s\n", path);
1591 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1592
1593 /* path is NULL */
1594 SetLastError(0xdeadbeef);
1595 root = PathBuildRootA(NULL, 0);
1596 ok(root == NULL, "Expected root == NULL, got %p\n", root);
1597 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1598 }
1599
1600 static void test_PathCommonPrefixA(void)
1601 {
1602 char path1[MAX_PATH], path2[MAX_PATH];
1603 char out[MAX_PATH];
1604 int count;
1605
1606 /* test NULL path1 */
1607 SetLastError(0xdeadbeef);
1608 lstrcpy(path2, "C:\\");
1609 lstrcpy(out, "aaa");
1610 count = PathCommonPrefixA(NULL, path2, out);
1611 ok(count == 0, "Expected 0, got %i\n", count);
1612 todo_wine
1613 {
1614 ok(!lstrcmp(out, "aaa"), "Expected aaa, got %s\n", out);
1615 }
1616 ok(!lstrcmp(path2, "C:\\"), "Expected C:\\, got %s\n", path2);
1617 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1618
1619 /* test NULL path2 */
1620 SetLastError(0xdeadbeef);
1621 lstrcpy(path1, "C:\\");
1622 lstrcpy(out, "aaa");
1623 count = PathCommonPrefixA(path1, NULL, out);
1624 ok(count == 0, "Expected 0, got %i\n", count);
1625 todo_wine
1626 {
1627 ok(!lstrcmp(out, "aaa"), "Expected aaa, got %s\n", out);
1628 }
1629 ok(!lstrcmp(path1, "C:\\"), "Expected C:\\, got %s\n", path1);
1630 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1631
1632 /* test empty path1 */
1633 SetLastError(0xdeadbeef);
1634 path1[0] = '\0';
1635 lstrcpy(path2, "C:\\");
1636 lstrcpy(out, "aaa");
1637 count = PathCommonPrefixA(path1, path2, out);
1638 ok(count == 0, "Expected 0, got %i\n", count);
1639 ok(lstrlen(out) == 0, "Expected 0 length out, got %i\n", lstrlen(out));
1640 ok(lstrlen(path1) == 0, "Expected 0 length path1, got %i\n", lstrlen(path1));
1641 ok(!lstrcmp(path2, "C:\\"), "Expected C:\\, got %s\n", path2);
1642 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1643
1644 /* test empty path1 */
1645 SetLastError(0xdeadbeef);
1646 path2[0] = '\0';
1647 lstrcpy(path1, "C:\\");
1648 lstrcpy(out, "aaa");
1649 count = PathCommonPrefixA(path1, path2, out);
1650 ok(count == 0, "Expected 0, got %i\n", count);
1651 ok(lstrlen(out) == 0, "Expected 0 length out, got %i\n", lstrlen(out));
1652 ok(lstrlen(path2) == 0, "Expected 0 length path2, got %i\n", lstrlen(path2));
1653 ok(!lstrcmp(path1, "C:\\"), "Expected C:\\, got %s\n", path1);
1654 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1655
1656 /* paths are legit, out is NULL */
1657 SetLastError(0xdeadbeef);
1658 lstrcpy(path1, "C:\\");
1659 lstrcpy(path2, "C:\\");
1660 count = PathCommonPrefixA(path1, path2, NULL);
1661 ok(count == 3, "Expected 3, got %i\n", count);
1662 ok(!lstrcmp(path1, "C:\\"), "Expected C:\\, got %s\n", path1);
1663 ok(!lstrcmp(path2, "C:\\"), "Expected C:\\, got %s\n", path2);
1664 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1665
1666 /* all parameters legit */
1667 SetLastError(0xdeadbeef);
1668 lstrcpy(path1, "C:\\");
1669 lstrcpy(path2, "C:\\");
1670 lstrcpy(out, "aaa");
1671 count = PathCommonPrefixA(path1, path2, out);
1672 ok(count == 3, "Expected 3, got %i\n", count);
1673 ok(!lstrcmp(path1, "C:\\"), "Expected C:\\, got %s\n", path1);
1674 ok(!lstrcmp(path2, "C:\\"), "Expected C:\\, got %s\n", path2);
1675 ok(!lstrcmp(out, "C:\\"), "Expected C:\\, got %s\n", out);
1676 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1677
1678 /* path1 and path2 not the same, but common prefix */
1679 SetLastError(0xdeadbeef);
1680 lstrcpy(path1, "C:\\one\\two");
1681 lstrcpy(path2, "C:\\one\\three");
1682 lstrcpy(out, "aaa");
1683 count = PathCommonPrefixA(path1, path2, out);
1684 ok(count == 6, "Expected 6, got %i\n", count);
1685 ok(!lstrcmp(path1, "C:\\one\\two"), "Expected C:\\one\\two, got %s\n", path1);
1686 ok(!lstrcmp(path2, "C:\\one\\three"), "Expected C:\\one\\three, got %s\n", path2);
1687 ok(!lstrcmp(out, "C:\\one"), "Expected C:\\one, got %s\n", out);
1688 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1689
1690 /* try . prefix */
1691 SetLastError(0xdeadbeef);
1692 lstrcpy(path1, "one\\.two");
1693 lstrcpy(path2, "one\\.three");
1694 lstrcpy(out, "aaa");
1695 count = PathCommonPrefixA(path1, path2, out);
1696 ok(count == 3, "Expected 3, got %i\n", count);
1697 ok(!lstrcmp(path1, "one\\.two"), "Expected one\\.two, got %s\n", path1);
1698 ok(!lstrcmp(path2, "one\\.three"), "Expected one\\.three, got %s\n", path2);
1699 ok(!lstrcmp(out, "one"), "Expected one, got %s\n", out);
1700 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1701
1702 /* try .. prefix */
1703 SetLastError(0xdeadbeef);
1704 lstrcpy(path1, "one\\..two");
1705 lstrcpy(path2, "one\\..three");
1706 lstrcpy(out, "aaa");
1707 count = PathCommonPrefixA(path1, path2, out);
1708 ok(count == 3, "Expected 3, got %i\n", count);
1709 ok(!lstrcmp(path1, "one\\..two"), "Expected one\\..two, got %s\n", path1);
1710 ok(!lstrcmp(path2, "one\\..three"), "Expected one\\..three, got %s\n", path2);
1711 ok(!lstrcmp(out, "one"), "Expected one, got %s\n", out);
1712 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1713
1714 /* try ... prefix */
1715 SetLastError(0xdeadbeef);
1716 lstrcpy(path1, "one\\...two");
1717 lstrcpy(path2, "one\\...three");
1718 lstrcpy(out, "aaa");
1719 count = PathCommonPrefixA(path1, path2, out);
1720 ok(count == 3, "Expected 3, got %i\n", count);
1721 ok(!lstrcmp(path1, "one\\...two"), "Expected one\\...two, got %s\n", path1);
1722 ok(!lstrcmp(path2, "one\\...three"), "Expected one\\...three, got %s\n", path2);
1723 ok(!lstrcmp(out, "one"), "Expected one, got %s\n", out);
1724 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1725
1726 /* try .\ prefix */
1727 SetLastError(0xdeadbeef);
1728 lstrcpy(path1, "one\\.\\two");
1729 lstrcpy(path2, "one\\.\\three");
1730 lstrcpy(out, "aaa");
1731 count = PathCommonPrefixA(path1, path2, out);
1732 ok(count == 5, "Expected 5, got %i\n", count);
1733 ok(!lstrcmp(path1, "one\\.\\two"), "Expected one\\.\\two, got %s\n", path1);
1734 ok(!lstrcmp(path2, "one\\.\\three"), "Expected one\\.\\three, got %s\n", path2);
1735 ok(!lstrcmp(out, "one\\."), "Expected one\\., got %s\n", out);
1736 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1737
1738 /* try ..\ prefix */
1739 SetLastError(0xdeadbeef);
1740 lstrcpy(path1, "one\\..\\two");
1741 lstrcpy(path2, "one\\..\\three");
1742 lstrcpy(out, "aaa");
1743 count = PathCommonPrefixA(path1, path2, out);
1744 ok(count == 6, "Expected 6, got %i\n", count);
1745 ok(!lstrcmp(path1, "one\\..\\two"), "Expected one\\..\\two, got %s\n", path1);
1746 ok(!lstrcmp(path2, "one\\..\\three"), "Expected one\\..\\three, got %s\n", path2);
1747 ok(!lstrcmp(out, "one\\.."), "Expected one\\.., got %s\n", out);
1748 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1749
1750 /* try ...\\ prefix */
1751 SetLastError(0xdeadbeef);
1752 lstrcpy(path1, "one\\...\\two");
1753 lstrcpy(path2, "one\\...\\three");
1754 lstrcpy(out, "aaa");
1755 count = PathCommonPrefixA(path1, path2, out);
1756 ok(count == 7, "Expected 7, got %i\n", count);
1757 ok(!lstrcmp(path1, "one\\...\\two"), "Expected one\\...\\two, got %s\n", path1);
1758 ok(!lstrcmp(path2, "one\\...\\three"), "Expected one\\...\\three, got %s\n", path2);
1759 ok(!lstrcmp(out, "one\\..."), "Expected one\\..., got %s\n", out);
1760 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1761
1762 /* try prefix that is not an msdn labeled prefix type */
1763 SetLastError(0xdeadbeef);
1764 lstrcpy(path1, "same");
1765 lstrcpy(path2, "same");
1766 lstrcpy(out, "aaa");
1767 count = PathCommonPrefixA(path1, path2, out);
1768 ok(count == 4, "Expected 4, got %i\n", count);
1769 ok(!lstrcmp(path1, "same"), "Expected same, got %s\n", path1);
1770 ok(!lstrcmp(path2, "same"), "Expected same, got %s\n", path2);
1771 ok(!lstrcmp(out, "same"), "Expected same, got %s\n", out);
1772 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1773
1774 /* try . after directory */
1775 SetLastError(0xdeadbeef);
1776 lstrcpy(path1, "one\\mid.\\two");
1777 lstrcpy(path2, "one\\mid.\\three");
1778 lstrcpy(out, "aaa");
1779 count = PathCommonPrefixA(path1, path2, out);
1780 ok(count == 8, "Expected 8, got %i\n", count);
1781 ok(!lstrcmp(path1, "one\\mid.\\two"), "Expected one\\mid.\\two, got %s\n", path1);
1782 ok(!lstrcmp(path2, "one\\mid.\\three"), "Expected one\\mid.\\three, got %s\n", path2);
1783 ok(!lstrcmp(out, "one\\mid."), "Expected one\\mid., got %s\n", out);
1784 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1785
1786 /* try . in the middle of a directory */
1787 SetLastError(0xdeadbeef);
1788 lstrcpy(path1, "one\\mid.end\\two");
1789 lstrcpy(path2, "one\\mid.end\\three");
1790 lstrcpy(out, "aaa");
1791 count = PathCommonPrefixA(path1, path2, out);
1792 ok(count == 11, "Expected 11, got %i\n", count);
1793 ok(!lstrcmp(path1, "one\\mid.end\\two"), "Expected one\\mid.end\\two, got %s\n", path1);
1794 ok(!lstrcmp(path2, "one\\mid.end\\three"), "Expected one\\mid.end\\three, got %s\n", path2);
1795 ok(!lstrcmp(out, "one\\mid.end"), "Expected one\\mid.end, got %s\n", out);
1796 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1797
1798 /* try comparing a .. with the expanded path */
1799 SetLastError(0xdeadbeef);
1800 lstrcpy(path1, "one\\..\\two");
1801 lstrcpy(path2, "two");
1802 lstrcpy(out, "aaa");
1803 count = PathCommonPrefixA(path1, path2, out);
1804 ok(count == 0, "Expected 0, got %i\n", count);
1805 ok(!lstrcmp(path1, "one\\..\\two"), "Expected one\\..\\two, got %s\n", path1);
1806 ok(!lstrcmp(path2, "two"), "Expected two, got %s\n", path2);
1807 ok(lstrlen(out) == 0, "Expected 0 length out, got %i\n", lstrlen(out));
1808 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1809 }
1810
1811 static void test_PathUnquoteSpaces(void)
1812 {
1813 int i;
1814 for(i = 0; i < sizeof(TEST_PATH_UNQUOTE_SPACES) / sizeof(TEST_PATH_UNQUOTE_SPACES[0]); i++)
1815 {
1816 char *path = strdupA(TEST_PATH_UNQUOTE_SPACES[i].path);
1817 WCHAR *pathW = GetWideString(TEST_PATH_UNQUOTE_SPACES[i].path);
1818 WCHAR *resultW = GetWideString(TEST_PATH_UNQUOTE_SPACES[i].result);
1819
1820 PathUnquoteSpacesA(path);
1821 ok(!strcmp(path, TEST_PATH_UNQUOTE_SPACES[i].result), "%s (A): got %s expected %s\n",
1822 TEST_PATH_UNQUOTE_SPACES[i].path, path,
1823 TEST_PATH_UNQUOTE_SPACES[i].result);
1824
1825 PathUnquoteSpacesW(pathW);
1826 ok(!lstrcmpW(pathW, resultW), "%s (W): strings differ\n",
1827 TEST_PATH_UNQUOTE_SPACES[i].path);
1828 FreeWideString(pathW);
1829 FreeWideString(resultW);
1830 HeapFree(GetProcessHeap(), 0, path);
1831 }
1832 }
1833
1834 START_TEST(path)
1835 {
1836 hShlwapi = GetModuleHandleA("shlwapi.dll");
1837
1838 test_UrlHash();
1839 test_UrlGetPart();
1840 test_UrlCanonicalize();
1841 test_UrlEscape();
1842 test_UrlCombine();
1843 test_UrlCreateFromPath();
1844 test_UrlIs();
1845 test_UrlUnescape();
1846
1847 test_PathSearchAndQualify();
1848 test_PathCreateFromUrl();
1849 test_PathIsUrl();
1850
1851 test_PathAddBackslash();
1852 test_PathMakePretty();
1853 test_PathMatchSpec();
1854
1855 /* For whatever reason, PathIsValidCharA and PathAppendA share the same
1856 * ordinal number in some native versions. Check this to prevent a crash.
1857 */
1858 pPathIsValidCharA = (void*)GetProcAddress(hShlwapi, (LPSTR)455);
1859 if (pPathIsValidCharA && pPathIsValidCharA != (void*)GetProcAddress(hShlwapi, "PathAppendA"))
1860 {
1861 test_PathIsValidCharA();
1862
1863 pPathIsValidCharW = (void*)GetProcAddress(hShlwapi, (LPSTR)456);
1864 if (pPathIsValidCharW) test_PathIsValidCharW();
1865 }
1866
1867 pPathCombineW = (void*)GetProcAddress(hShlwapi, "PathCombineW");
1868 if (pPathCombineW)
1869 test_PathCombineW();
1870
1871 test_PathCombineA();
1872 test_PathAppendA();
1873 test_PathCanonicalizeA();
1874 test_PathFindExtensionA();
1875 test_PathBuildRootA();
1876 test_PathCommonPrefixA();
1877 test_PathUnquoteSpaces();
1878 }