Fix direct sound capabilities to match hardware.
[wine] / dlls / shlwapi / tests / 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  */
19
20 #include <assert.h>
21 #include <stdlib.h>
22 #include <stdarg.h>
23 #include <stdio.h>
24
25 #include "wine/test.h"
26 #include "windef.h"
27 #include "winbase.h"
28 #include "wine/unicode.h"
29 #include "winreg.h"
30 #include "shlwapi.h"
31 #include "wininet.h"
32
33 static HMODULE hShlwapi;
34 static HRESULT (WINAPI *pPathIsValidCharA)(char,DWORD);
35 static HRESULT (WINAPI *pPathIsValidCharW)(WCHAR,DWORD);
36
37 const char* TEST_URL_1 = "http://www.winehq.org/tests?date=10/10/1923";
38 const char* TEST_URL_2 = "http://localhost:8080/tests%2e.html?date=Mon%2010/10/1923";
39 const char* TEST_URL_3 = "http://foo:bar@localhost:21/internal.php?query=x&return=y";
40
41 typedef struct _TEST_URL_CANONICALIZE {
42     char *url;
43     DWORD flags;
44     HRESULT expectret;
45     char *expecturl;
46 } TEST_URL_CANONICALIZE;
47
48 const TEST_URL_CANONICALIZE TEST_CANONICALIZE[] = {
49     /*FIXME {"http://www.winehq.org/tests/../tests/../..", 0, S_OK, "http://www.winehq.org/"},*/
50     {"http://www.winehq.org/tests/../tests", 0, S_OK, "http://www.winehq.org/tests"},
51     {"http://www.winehq.org/tests\n", URL_WININET_COMPATIBILITY|URL_ESCAPE_SPACES_ONLY|URL_ESCAPE_UNSAFE, S_OK, "http://www.winehq.org/tests"},
52     {"http://www.winehq.org/tests\r", URL_WININET_COMPATIBILITY|URL_ESCAPE_SPACES_ONLY|URL_ESCAPE_UNSAFE, S_OK, "http://www.winehq.org/tests"},
53     {"http://www.winehq.org/tests\r", 0, S_OK, "http://www.winehq.org/tests"},
54     {"http://www.winehq.org/tests\r", URL_DONT_SIMPLIFY, S_OK, "http://www.winehq.org/tests"},
55     {"http://www.winehq.org/tests/../tests/", 0, S_OK, "http://www.winehq.org/tests/"},
56     {"http://www.winehq.org/tests/../tests/..", 0, S_OK, "http://www.winehq.org/"},
57     {"http://www.winehq.org/tests/../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/../", 0, S_OK, "http://www.winehq.org/"},
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/../?query=x&return=y", 0, S_OK, "http://www.winehq.org/?query=x&return=y"},
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", URL_DONT_SIMPLIFY, S_OK, "http://www.winehq.org/tests/../#example"},
65 };
66
67 typedef struct _TEST_URL_ESCAPE {
68     char *url;
69     DWORD flags;
70     DWORD expectescaped;
71     HRESULT expectret;
72     char *expecturl;
73 } TEST_URL_ESCAPE;
74
75 const TEST_URL_ESCAPE TEST_ESCAPE[] = {
76     {"http://www.winehq.org/tests0", 0, 0, S_OK, "http://www.winehq.org/tests0"},
77     {"http://www.winehq.org/tests1\n", 0, 0, S_OK, "http://www.winehq.org/tests1%0A"},
78     {"http://www.winehq.org/tests2\r", 0, 0, S_OK, "http://www.winehq.org/tests2%0D"},
79     {"http://www.winehq.org/tests3\r", URL_ESCAPE_SPACES_ONLY|URL_ESCAPE_UNSAFE, 0, S_OK, "http://www.winehq.org/tests3\r"},
80     {"http://www.winehq.org/tests4\r", URL_ESCAPE_SPACES_ONLY, 0, S_OK, "http://www.winehq.org/tests4\r"},
81     {"http://www.winehq.org/tests5\r", URL_WININET_COMPATIBILITY|URL_ESCAPE_SPACES_ONLY, 0, S_OK, "http://www.winehq.org/tests5\r"},
82     {"/direct/swhelp/series6/6.2i_latestservicepack.dat\r", URL_ESCAPE_SPACES_ONLY, 0, S_OK, "/direct/swhelp/series6/6.2i_latestservicepack.dat\r"},
83
84     {"file://////foo/bar\\baz", 0, 0, S_OK, "file://foo/bar/baz"},
85     {"file://///foo/bar\\baz", 0, 0, S_OK, "file://foo/bar/baz"},
86     {"file:////foo/bar\\baz", 0, 0, S_OK, "file://foo/bar/baz"},
87     {"file:///localhost/foo/bar\\baz", 0, 0, S_OK, "file:///localhost/foo/bar/baz"},
88     {"file:///foo/bar\\baz", 0, 0, S_OK, "file:///foo/bar/baz"},
89     {"file://loCalHost/foo/bar\\baz", 0, 0, S_OK, "file:///foo/bar/baz"},
90     {"file://foo/bar\\baz", 0, 0, S_OK, "file://foo/bar/baz"},
91     {"file:/localhost/foo/bar\\baz", 0, 0, S_OK, "file:///localhost/foo/bar/baz"},
92     {"file:/foo/bar\\baz", 0, 0, S_OK, "file:///foo/bar/baz"},
93     {"file:foo/bar\\baz", 0, 0, S_OK, "file:foo/bar/baz"},
94     {"file:\\foo/bar\\baz", 0, 0, S_OK, "file:///foo/bar/baz"},
95     {"file:\\\\foo/bar\\baz", 0, 0, S_OK, "file://foo/bar/baz"},
96     {"file:\\\\\\foo/bar\\baz", 0, 0, S_OK, "file:///foo/bar/baz"},
97     {"file:\\\\localhost\\foo/bar\\baz", 0, 0, S_OK, "file:///foo/bar/baz"},
98     {"file:///f oo/b?a r\\baz", 0, 0, S_OK, "file:///f%20oo/b?a r\\baz"},
99     {"file:///foo/b#a r\\baz", 0, 0, S_OK, "file:///foo/b%23a%20r/baz"},
100     {"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"},
101     {"file:///f o%o/b?a r\\b%az", URL_ESCAPE_PERCENT, 0, S_OK, "file:///f%20o%25o/b?a r\\b%az"},
102     {"file:/foo/bar\\baz", URL_ESCAPE_SEGMENT_ONLY, 0, S_OK, "file:%2Ffoo%2Fbar%5Cbaz"},
103
104     {"foo/b%ar\\ba?z\\", URL_ESCAPE_SEGMENT_ONLY, 0, S_OK, "foo%2Fb%ar%5Cba%3Fz%5C"},
105     {"foo/b%ar\\ba?z\\", URL_ESCAPE_PERCENT | URL_ESCAPE_SEGMENT_ONLY, 0, S_OK, "foo%2Fb%25ar%5Cba%3Fz%5C"},
106     {"foo/bar\\ba?z\\", 0, 0, S_OK, "foo/bar%5Cba?z\\"},
107     {"/foo/bar\\ba?z\\", 0, 0, S_OK, "/foo/bar%5Cba?z\\"},
108     {"/foo/bar\\ba#z\\", 0, 0, S_OK, "/foo/bar%5Cba#z\\"},
109     {"/foo/%5C", 0, 0, S_OK, "/foo/%5C"},
110     {"/foo/%5C", URL_ESCAPE_PERCENT, 0, S_OK, "/foo/%255C"},
111
112     {"http://////foo/bar\\baz", 0, 0, S_OK, "http://////foo/bar/baz"},
113     {"http://///foo/bar\\baz", 0, 0, S_OK, "http://///foo/bar/baz"},
114     {"http:////foo/bar\\baz", 0, 0, S_OK, "http:////foo/bar/baz"},
115     {"http:///foo/bar\\baz", 0, 0, S_OK, "http:///foo/bar/baz"},
116     {"http://localhost/foo/bar\\baz", 0, 0, S_OK, "http://localhost/foo/bar/baz"},
117     {"http://foo/bar\\baz", 0, 0, S_OK, "http://foo/bar/baz"},
118     {"http:/foo/bar\\baz", 0, 0, S_OK, "http:/foo/bar/baz"},
119     {"http:foo/bar\\ba?z\\", 0, 0, S_OK, "http:foo%2Fbar%2Fba?z\\"},
120     {"http:foo/bar\\ba#z\\", 0, 0, S_OK, "http:foo%2Fbar%2Fba#z\\"},
121     {"http:\\foo/bar\\baz", 0, 0, S_OK, "http:/foo/bar/baz"},
122     {"http:\\\\foo/bar\\baz", 0, 0, S_OK, "http://foo/bar/baz"},
123     {"http:\\\\\\foo/bar\\baz", 0, 0, S_OK, "http:///foo/bar/baz"},
124     {"http:\\\\\\\\foo/bar\\baz", 0, 0, S_OK, "http:////foo/bar/baz"},
125     {"http:/fo ?o/b ar\\baz", 0, 0, S_OK, "http:/fo%20?o/b ar\\baz"},
126     {"http:fo ?o/b ar\\baz", 0, 0, S_OK, "http:fo%20?o/b ar\\baz"},
127     {"http:/foo/bar\\baz", URL_ESCAPE_SEGMENT_ONLY, 0, S_OK, "http:%2Ffoo%2Fbar%5Cbaz"},
128
129     {"https://foo/bar\\baz", 0, 0, S_OK, "https://foo/bar/baz"},
130     {"https:/foo/bar\\baz", 0, 0, S_OK, "https:/foo/bar/baz"},
131     {"https:\\foo/bar\\baz", 0, 0, S_OK, "https:/foo/bar/baz"},
132
133     {"foo:////foo/bar\\baz", 0, 0, S_OK, "foo:////foo/bar%5Cbaz"},
134     {"foo:///foo/bar\\baz", 0, 0, S_OK, "foo:///foo/bar%5Cbaz"},
135     {"foo://localhost/foo/bar\\baz", 0, 0, S_OK, "foo://localhost/foo/bar%5Cbaz"},
136     {"foo://foo/bar\\baz", 0, 0, S_OK, "foo://foo/bar%5Cbaz"},
137     {"foo:/foo/bar\\baz", 0, 0, S_OK, "foo:/foo/bar%5Cbaz"},
138     {"foo:foo/bar\\baz", 0, 0, S_OK, "foo:foo%2Fbar%5Cbaz"},
139     {"foo:\\foo/bar\\baz", 0, 0, S_OK, "foo:%5Cfoo%2Fbar%5Cbaz"},
140     {"foo:/foo/bar\\ba?\\z", 0, 0, S_OK, "foo:/foo/bar%5Cba?\\z"},
141     {"foo:/foo/bar\\ba#\\z", 0, 0, S_OK, "foo:/foo/bar%5Cba#\\z"},
142
143     {"mailto:/fo/o@b\\%a?\\r.b#\\az", 0, 0, S_OK, "mailto:%2Ffo%2Fo@b%5C%a%3F%5Cr.b%23%5Caz"},
144     {"mailto:fo/o@b\\%a?\\r.b#\\az", 0, 0, S_OK, "mailto:fo%2Fo@b%5C%a%3F%5Cr.b%23%5Caz"},
145     {"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"},
146
147     {"ftp:fo/o@bar.baz/foo/bar", 0, 0, S_OK, "ftp:fo%2Fo@bar.baz%2Ffoo%2Fbar"},
148     {"ftp:/fo/o@bar.baz/foo/bar", 0, 0, S_OK, "ftp:/fo/o@bar.baz/foo/bar"},
149     {"ftp://fo/o@bar.baz/fo?o\\bar", 0, 0, S_OK, "ftp://fo/o@bar.baz/fo?o\\bar"},
150     {"ftp://fo/o@bar.baz/fo#o\\bar", 0, 0, S_OK, "ftp://fo/o@bar.baz/fo#o\\bar"},
151     {"ftp://localhost/o@bar.baz/fo#o\\bar", 0, 0, S_OK, "ftp://localhost/o@bar.baz/fo#o\\bar"},
152     {"ftp:///fo/o@bar.baz/foo/bar", 0, 0, S_OK, "ftp:///fo/o@bar.baz/foo/bar"},
153     {"ftp:////fo/o@bar.baz/foo/bar", 0, 0, S_OK, "ftp:////fo/o@bar.baz/foo/bar"}
154 };
155
156 typedef struct _TEST_URL_COMBINE {
157     char *url1;
158     char *url2;
159     DWORD flags;
160     HRESULT expectret;
161     char *expecturl;
162 } TEST_URL_COMBINE;
163
164 const TEST_URL_COMBINE TEST_COMBINE[] = {
165     {"http://www.winehq.org/tests", "tests1", 0, S_OK, "http://www.winehq.org/tests1"},
166     /*FIXME {"http://www.winehq.org/tests", "../tests2", 0, S_OK, "http://www.winehq.org/tests2"},*/
167     {"http://www.winehq.org/tests/", "../tests3", 0, S_OK, "http://www.winehq.org/tests3"},
168     {"http://www.winehq.org/tests/../tests", "tests4", 0, S_OK, "http://www.winehq.org/tests4"},
169     {"http://www.winehq.org/tests/../tests/", "tests5", 0, S_OK, "http://www.winehq.org/tests/tests5"},
170     {"http://www.winehq.org/tests/../tests/", "/tests6/..", 0, S_OK, "http://www.winehq.org/"},
171     {"http://www.winehq.org/tests/../tests/..", "tests7/..", 0, S_OK, "http://www.winehq.org/"},
172     {"http://www.winehq.org/tests/?query=x&return=y", "tests8", 0, S_OK, "http://www.winehq.org/tests/tests8"},
173     {"http://www.winehq.org/tests/#example", "tests9", 0, S_OK, "http://www.winehq.org/tests/tests9"},
174     {"http://www.winehq.org/tests/../tests/", "/tests10/..", URL_DONT_SIMPLIFY, S_OK, "http://www.winehq.org/tests10/.."},
175     {"http://www.winehq.org/tests/../", "tests11", URL_DONT_SIMPLIFY, S_OK, "http://www.winehq.org/tests/../tests11"},
176 };
177
178 struct {
179     char *path;
180     char *url;
181     DWORD ret;
182 } TEST_URLFROMPATH [] = {
183     {"foo", "file:foo", S_OK},
184     {"foo\\bar", "file:foo/bar", S_OK},
185     {"\\foo\\bar", "file:///foo/bar", S_OK},
186     {"c:\\foo\\bar", "file:///c:/foo/bar", S_OK},
187     {"c:foo\\bar", "file:///c:foo/bar", S_OK},
188     {"c:\\foo/b a%r", "file:///c:/foo/b%20a%25r", S_OK},
189 #if 0
190     /* The following test fails on native shlwapi as distributed with Win95/98.
191      * Wine matches the behaviour of later versions.
192      */
193     {"xx:c:\\foo\\bar", "xx:c:\\foo\\bar", S_FALSE}
194 #endif
195 };
196
197 struct {
198     char *url;
199     char *path;
200     DWORD ret;
201 } TEST_PATHFROMURL[] = {
202     {"file:///c:/foo/ba%5Cr", "c:\\foo\\ba\\r", S_OK},
203     {"file:///c:/foo/../ba%5Cr", "c:\\foo\\..\\ba\\r", S_OK},
204     {"file:///host/c:/foo/bar", "\\host\\c:\\foo\\bar", S_OK},
205     {"file://host/c:/foo/bar", "\\\\hostc:\\foo\\bar", S_OK},
206     {"file://host/c:/foo/bar", "\\\\hostc:\\foo\\bar", S_OK},
207     {"file:\\\\host\\c:\\foo\\bar", "\\\\hostc:\\foo\\bar", S_OK},
208     {"file:\\\\host\\ca\\foo\\bar", "\\\\host\\ca\\foo\\bar", S_OK},
209     {"file:\\\\host\\c|\\foo\\bar", "\\\\hostc|\\foo\\bar", S_OK},
210     {"file:\\%5Chost\\c:\\foo\\bar", "\\\\host\\c:\\foo\\bar", S_OK},
211     {"file:\\\\host\\cx:\\foo\\bar", "\\\\host\\cx:\\foo\\bar", S_OK},
212     {"file://c:/foo/bar", "c:\\foo\\bar", S_OK},
213     {"file://c:/d:/foo/bar", "c:\\d:\\foo\\bar", S_OK},
214     {"file://c|/d|/foo/bar", "c:\\d|\\foo\\bar", S_OK},
215     {"file://host/foo/bar", "\\\\host\\foo\\bar", S_OK},
216     {"file:/foo/bar", "\\foo\\bar", S_OK},
217     {"file:/foo/bar/", "\\foo\\bar\\", S_OK},
218     {"file:foo/bar", "foo\\bar", S_OK},
219     {"file:c:/foo/bar", "c:\\foo\\bar", S_OK},
220     {"file:c|/foo/bar", "c:\\foo\\bar", S_OK},
221     {"file:cx|/foo/bar", "cx|\\foo\\bar", S_OK},
222     {"file:////c:/foo/bar", "c:\\foo\\bar", S_OK},
223
224     {"c:\\foo\\bar", NULL, E_INVALIDARG},
225     {"foo/bar", NULL, E_INVALIDARG},
226     {"http://foo/bar", NULL, E_INVALIDARG},
227
228 };
229
230 struct {
231     char *url;
232     char *expect;
233 } TEST_URL_UNESCAPE[] = {
234     {"file://foo/bar", "file://foo/bar"},
235     {"file://fo%20o%5Ca/bar", "file://fo o\\a/bar"}
236 };
237
238
239 struct {
240     char *path;
241     BOOL expect;
242 } TEST_PATH_IS_URL[] = {
243     {"http://foo/bar", TRUE},
244     {"c:\\foo\\bar", FALSE},
245     {"foo://foo/bar", TRUE},
246     {"foo\\bar", FALSE},
247     {"foo.bar", FALSE},
248     {"bogusscheme:", TRUE},
249     {"http:partial", TRUE}
250 };
251
252 struct {
253     char *url;
254     BOOL expectOpaque;
255     BOOL expectFile;
256 } TEST_URLIS_ATTRIBS[] = {
257     {   "ftp:",                                         FALSE,  FALSE   },
258     {   "http:",                                        FALSE,  FALSE   },
259     {   "gopher:",                                      FALSE,  FALSE   },
260     {   "mailto:",                                      TRUE,   FALSE   },
261     {   "news:",                                        FALSE,  FALSE   },
262     {   "nntp:",                                        FALSE,  FALSE   },
263     {   "telnet:",                                      FALSE,  FALSE   },
264     {   "wais:",                                        FALSE,  FALSE   },
265     {   "file:",                                        FALSE,  TRUE    },
266     {   "mk:",                                          FALSE,  FALSE   },
267     {   "https:",                                       FALSE,  FALSE   },
268     {   "shell:",                                       TRUE,   FALSE   },
269     {   "https:",                                       FALSE,  FALSE   },
270     {   "snews:",                                       FALSE,  FALSE   },
271     {   "local:",                                       FALSE,  FALSE   },
272     {   "javascript:",                                  TRUE,   FALSE   },
273     {   "vbscript:",                                    TRUE,   FALSE   },
274     {   "about:",                                       TRUE,   FALSE   },
275     {   "res:",                                         FALSE,  FALSE   },
276     {   "bogusscheme:",                                 FALSE,  FALSE   },
277     {   "file:\\\\e:\\b\\c",                            FALSE,  TRUE    },
278     {   "file://e:/b/c",                                FALSE,  TRUE    },
279     {   "http:partial",                                 FALSE,  FALSE   },
280     {   "mailto://www.winehq.org/test.html",            TRUE,   FALSE   },
281     {   "file:partial",                                 FALSE,  TRUE    }
282 };
283
284
285 static LPWSTR GetWideString(const char* szString)
286 {
287   LPWSTR wszString = (LPWSTR) HeapAlloc(GetProcessHeap(), 0,
288                                          (2*INTERNET_MAX_URL_LENGTH) * sizeof(WCHAR));
289   
290   MultiByteToWideChar(0, 0, szString, -1, wszString, INTERNET_MAX_URL_LENGTH);
291
292   return wszString;
293 }
294
295 static void FreeWideString(LPWSTR wszString)
296 {
297    HeapFree(GetProcessHeap(), 0, wszString);
298 }
299
300 static void hash_url(const char* szUrl)
301 {
302   LPCSTR szTestUrl = szUrl;
303   LPWSTR wszTestUrl = GetWideString(szTestUrl);
304   
305   DWORD cbSize = sizeof(DWORD);
306   DWORD dwHash1, dwHash2;
307   ok(UrlHashA(szTestUrl, (LPBYTE)&dwHash1, cbSize) == S_OK, "UrlHashA didn't return S_OK\n");
308   ok(UrlHashW(wszTestUrl, (LPBYTE)&dwHash2, cbSize) == S_OK, "UrlHashW didn't return S_OK\n");
309
310   FreeWideString(wszTestUrl);
311
312   ok(dwHash1 == dwHash2, "Hashes didn't compare\n");
313 }
314
315 static void test_UrlHash(void)
316 {
317   hash_url(TEST_URL_1);
318   hash_url(TEST_URL_2);
319   hash_url(TEST_URL_3);
320 }
321
322 static void test_url_part(const char* szUrl, DWORD dwPart, DWORD dwFlags, const char* szExpected)
323 {
324   CHAR szPart[INTERNET_MAX_URL_LENGTH];
325   WCHAR wszPart[INTERNET_MAX_URL_LENGTH];
326   LPWSTR wszUrl = GetWideString(szUrl);
327   LPWSTR wszConvertedPart;
328
329   DWORD dwSize;
330
331   dwSize = INTERNET_MAX_URL_LENGTH;
332   ok( UrlGetPartA(szUrl, szPart, &dwSize, dwPart, dwFlags) == S_OK, "UrlGetPartA for \"%s\" part 0x%08lx didn't return S_OK but \"%s\"\n", szUrl, dwPart, szPart);
333   dwSize = INTERNET_MAX_URL_LENGTH;
334   ok( UrlGetPartW(wszUrl, wszPart, &dwSize, dwPart, dwFlags) == S_OK, "UrlGetPartW didn't return S_OK\n" );
335
336   wszConvertedPart = GetWideString(szPart);
337
338   ok(strcmpW(wszPart,wszConvertedPart)==0, "Strings didn't match between ascii and unicode UrlGetPart!\n");
339
340   FreeWideString(wszUrl);
341   FreeWideString(wszConvertedPart);
342
343   /* Note that v6.0 and later don't return '?' with the query */
344   ok(strcmp(szPart,szExpected)==0 ||
345      (*szExpected=='?' && !strcmp(szPart,szExpected+1)),
346          "Expected %s, but got %s\n", szExpected, szPart);
347 }
348
349 static void test_UrlGetPart(void)
350 {
351   test_url_part(TEST_URL_3, URL_PART_HOSTNAME, 0, "localhost");
352   test_url_part(TEST_URL_3, URL_PART_PORT, 0, "21");
353   test_url_part(TEST_URL_3, URL_PART_USERNAME, 0, "foo");
354   test_url_part(TEST_URL_3, URL_PART_PASSWORD, 0, "bar");
355   test_url_part(TEST_URL_3, URL_PART_SCHEME, 0, "http");
356   test_url_part(TEST_URL_3, URL_PART_QUERY, 0, "?query=x&return=y");
357 }
358
359 static void test_url_escape(const char *szUrl, DWORD dwFlags, HRESULT dwExpectReturn, const char *szExpectUrl)
360 {
361     CHAR szReturnUrl[INTERNET_MAX_URL_LENGTH];
362     DWORD dwEscaped;
363     WCHAR ret_urlW[INTERNET_MAX_URL_LENGTH];
364     WCHAR *urlW, *expected_urlW;
365     dwEscaped=INTERNET_MAX_URL_LENGTH;
366
367     ok(UrlEscapeA(szUrl, szReturnUrl, &dwEscaped, dwFlags) == dwExpectReturn, "UrlEscapeA didn't return 0x%08lx from \"%s\"\n", dwExpectReturn, szUrl);
368     ok(strcmp(szReturnUrl,szExpectUrl)==0, "Expected \"%s\", but got \"%s\" from \"%s\"\n", szExpectUrl, szReturnUrl, szUrl);
369     
370     dwEscaped = INTERNET_MAX_URL_LENGTH;
371     urlW = GetWideString(szUrl);
372     expected_urlW = GetWideString(szExpectUrl);
373     ok(UrlEscapeW(urlW, ret_urlW, &dwEscaped, dwFlags) == dwExpectReturn, "UrlEscapeW didn't return 0x%08lx from \"%s\"\n", dwExpectReturn, szUrl);
374     WideCharToMultiByte(CP_ACP,0,ret_urlW,-1,szReturnUrl,INTERNET_MAX_URL_LENGTH,0,0);
375     ok(strcmpW(ret_urlW, expected_urlW)==0, "Expected \"%s\", but got \"%s\" from \"%s\" flags %08lx\n", szExpectUrl, szReturnUrl, szUrl, dwFlags);
376     FreeWideString(urlW);
377     FreeWideString(expected_urlW);
378
379 }
380
381 static void test_url_canonicalize(const char *szUrl, DWORD dwFlags, HRESULT dwExpectReturn, const char *szExpectUrl)
382 {
383     CHAR szReturnUrl[INTERNET_MAX_URL_LENGTH];
384     WCHAR wszReturnUrl[INTERNET_MAX_URL_LENGTH];
385     LPWSTR wszUrl = GetWideString(szUrl);
386     LPWSTR wszExpectUrl = GetWideString(szExpectUrl);
387     LPWSTR wszConvertedUrl;
388     
389     DWORD dwSize;
390     
391     dwSize = INTERNET_MAX_URL_LENGTH;
392     ok(UrlCanonicalizeA(szUrl, szReturnUrl, &dwSize, dwFlags) == dwExpectReturn, "UrlCanonicalizeA didn't return 0x%08lx\n", dwExpectReturn);
393     ok(strcmp(szReturnUrl,szExpectUrl)==0, "Expected %s, but got %s\n", szExpectUrl, szReturnUrl);
394
395     dwSize = INTERNET_MAX_URL_LENGTH;
396     ok(UrlCanonicalizeW(wszUrl, wszReturnUrl, &dwSize, dwFlags) == dwExpectReturn, "UrlCanonicalizeW didn't return 0x%08lx\n", dwExpectReturn);
397     wszConvertedUrl = GetWideString(szReturnUrl);
398     ok(strcmpW(wszReturnUrl, wszConvertedUrl)==0, "Strings didn't match between ascii and unicode UrlCanonicalize!\n");
399     FreeWideString(wszConvertedUrl);
400     
401             
402     FreeWideString(wszUrl);
403     FreeWideString(wszExpectUrl);
404 }
405
406
407 static void test_UrlEscape(void)
408 {
409     unsigned int i;
410     for(i=0; i<sizeof(TEST_ESCAPE)/sizeof(TEST_ESCAPE[0]); i++) {
411         test_url_escape(TEST_ESCAPE[i].url, TEST_ESCAPE[i].flags,
412                               TEST_ESCAPE[i].expectret, TEST_ESCAPE[i].expecturl);
413     }
414 }
415
416 static void test_UrlCanonicalize(void)
417 {
418     unsigned int i;
419     for(i=0; i<sizeof(TEST_CANONICALIZE)/sizeof(TEST_CANONICALIZE[0]); i++) {
420         test_url_canonicalize(TEST_CANONICALIZE[i].url, TEST_CANONICALIZE[i].flags,
421                               TEST_CANONICALIZE[i].expectret, TEST_CANONICALIZE[i].expecturl);
422     }
423 }
424
425 static void test_url_combine(const char *szUrl1, const char *szUrl2, DWORD dwFlags, HRESULT dwExpectReturn, const char *szExpectUrl)
426 {
427     HRESULT hr;
428     CHAR szReturnUrl[INTERNET_MAX_URL_LENGTH];
429     WCHAR wszReturnUrl[INTERNET_MAX_URL_LENGTH];
430     LPWSTR wszUrl1 = GetWideString(szUrl1);
431     LPWSTR wszUrl2 = GetWideString(szUrl2);
432     LPWSTR wszExpectUrl = GetWideString(szExpectUrl);
433     LPWSTR wszConvertedUrl;
434
435     DWORD dwSize;
436     DWORD dwExpectLen = lstrlen(szExpectUrl);
437
438     hr = UrlCombineA(szUrl1, szUrl2, NULL, NULL, dwFlags);
439     ok(hr == E_INVALIDARG, "UrlCombineA returned 0x%08lx, expected 0x%08lx\n", hr, E_INVALIDARG);
440     
441     dwSize = 0;
442     hr = UrlCombineA(szUrl1, szUrl2, NULL, &dwSize, dwFlags);
443     ok(hr == E_POINTER, "Checking length of string, return was 0x%08lx, expected 0x%08lx\n", hr, E_POINTER);
444     ok(dwSize == dwExpectLen+1, "Got length %ld, expected %ld\n", dwSize, dwExpectLen+1);
445
446     dwSize--;
447     hr = UrlCombineA(szUrl1, szUrl2, szReturnUrl, &dwSize, dwFlags);
448     ok(hr == E_POINTER, "UrlCombineA returned 0x%08lx, expected 0x%08lx\n", hr, E_POINTER);
449     ok(dwSize == dwExpectLen+1, "Got length %ld, expected %ld\n", dwSize, dwExpectLen+1);
450     
451     hr = UrlCombineA(szUrl1, szUrl2, szReturnUrl, &dwSize, dwFlags);
452     ok(hr == dwExpectReturn, "UrlCombineA returned 0x%08lx, expected 0x%08lx\n", hr, dwExpectReturn);
453     ok(dwSize == dwExpectLen, "Got length %ld, expected %ld\n", dwSize, dwExpectLen);
454     if(SUCCEEDED(hr)) {
455         ok(strcmp(szReturnUrl,szExpectUrl)==0, "Expected %s, but got %s\n", szExpectUrl, szReturnUrl);
456     }
457
458     dwSize = 0;
459     hr = UrlCombineW(wszUrl1, wszUrl2, NULL, &dwSize, dwFlags);
460     ok(hr == E_POINTER, "Checking length of string, return was 0x%08lx, expected 0x%08lx\n", hr, E_POINTER);
461     ok(dwSize == dwExpectLen+1, "Got length %ld, expected %ld\n", dwSize, dwExpectLen+1);
462
463     dwSize--;
464     hr = UrlCombineW(wszUrl1, wszUrl2, wszReturnUrl, &dwSize, dwFlags);
465     ok(hr == E_POINTER, "UrlCombineA returned 0x%08lx, expected 0x%08lx\n", hr, E_POINTER);
466     ok(dwSize == dwExpectLen+1, "Got length %ld, expected %ld\n", dwSize, dwExpectLen+1);
467     
468     hr = UrlCombineW(wszUrl1, wszUrl2, wszReturnUrl, &dwSize, dwFlags);
469     ok(hr == dwExpectReturn, "UrlCombineW returned 0x%08lx, expected 0x%08lx\n", hr, dwExpectReturn);
470     ok(dwSize == dwExpectLen, "Got length %ld, expected %ld\n", dwSize, dwExpectLen);
471     if(SUCCEEDED(hr)) {
472         wszConvertedUrl = GetWideString(szReturnUrl);
473         ok(strcmpW(wszReturnUrl, wszConvertedUrl)==0, "Strings didn't match between ascii and unicode UrlCombine!\n");
474         FreeWideString(wszConvertedUrl);
475     }
476
477     FreeWideString(wszUrl1);
478     FreeWideString(wszUrl2);
479     FreeWideString(wszExpectUrl);
480 }
481
482 static void test_UrlCombine(void)
483 {
484     unsigned int i;
485     for(i=0; i<sizeof(TEST_COMBINE)/sizeof(TEST_COMBINE[0]); i++) {
486         test_url_combine(TEST_COMBINE[i].url1, TEST_COMBINE[i].url2, TEST_COMBINE[i].flags,
487                          TEST_COMBINE[i].expectret, TEST_COMBINE[i].expecturl);
488     }
489 }
490
491 static void test_UrlCreateFromPath(void)
492 {
493     size_t i;
494     char ret_url[INTERNET_MAX_URL_LENGTH];
495     DWORD len, ret;
496     WCHAR ret_urlW[INTERNET_MAX_URL_LENGTH];
497     WCHAR *pathW, *urlW;
498
499     for(i = 0; i < sizeof(TEST_URLFROMPATH) / sizeof(TEST_URLFROMPATH[0]); i++) {
500         len = INTERNET_MAX_URL_LENGTH;
501         ret = UrlCreateFromPathA(TEST_URLFROMPATH[i].path, ret_url, &len, 0);
502         ok(ret == TEST_URLFROMPATH[i].ret, "ret %08lx from path %s\n", ret, TEST_URLFROMPATH[i].path);
503         ok(!lstrcmpi(ret_url, TEST_URLFROMPATH[i].url), "url %s from path %s\n", ret_url, TEST_URLFROMPATH[i].path);
504         ok(len == strlen(ret_url), "ret len %ld from path %s\n", len, TEST_URLFROMPATH[i].path);
505
506         len = INTERNET_MAX_URL_LENGTH;
507         pathW = GetWideString(TEST_URLFROMPATH[i].path);
508         urlW = GetWideString(TEST_URLFROMPATH[i].url);
509         ret = UrlCreateFromPathW(pathW, ret_urlW, &len, 0);
510         WideCharToMultiByte(CP_ACP, 0, ret_urlW, -1, ret_url, sizeof(ret_url),0,0);
511         ok(ret == TEST_URLFROMPATH[i].ret, "ret %08lx from path L\"%s\", expected %08lx\n",
512            ret, TEST_URLFROMPATH[i].path, TEST_URLFROMPATH[i].ret);
513         ok(!lstrcmpiW(ret_urlW, urlW), "got %s expected %s from path L\"%s\"\n", ret_url, TEST_URLFROMPATH[i].url, TEST_URLFROMPATH[i].path);
514         ok(len == strlenW(ret_urlW), "ret len %ld from path L\"%s\"\n", len, TEST_URLFROMPATH[i].path);
515         FreeWideString(urlW);
516         FreeWideString(pathW);
517     }
518 }
519
520 static void test_UrlIs(void)
521 {
522     BOOL ret;
523     size_t i;
524     WCHAR wurl[80];
525
526     for(i = 0; i < sizeof(TEST_PATH_IS_URL) / sizeof(TEST_PATH_IS_URL[0]); i++) {
527         MultiByteToWideChar(CP_ACP, 0, TEST_PATH_IS_URL[i].path, -1, wurl, 80);
528
529         ret = UrlIsA( TEST_PATH_IS_URL[i].path, URLIS_URL );
530         ok( ret == TEST_PATH_IS_URL[i].expect,
531             "returned %d from path %s, expected %d\n", ret, TEST_PATH_IS_URL[i].path,
532             TEST_PATH_IS_URL[i].expect );
533
534         ret = UrlIsW( wurl, URLIS_URL );
535         ok( ret == TEST_PATH_IS_URL[i].expect,
536             "returned %d from path (UrlIsW) %s, expected %d\n", ret, TEST_PATH_IS_URL[i].path,
537             TEST_PATH_IS_URL[i].expect );
538     }
539     for(i = 0; i < sizeof(TEST_URLIS_ATTRIBS) / sizeof(TEST_URLIS_ATTRIBS[0]); i++) {
540         MultiByteToWideChar(CP_ACP, 0, TEST_URLIS_ATTRIBS[i].url, -1, wurl, 80);
541
542         ret = UrlIsA( TEST_URLIS_ATTRIBS[i].url, URLIS_OPAQUE);
543         ok( ret == TEST_URLIS_ATTRIBS[i].expectOpaque,
544             "returned %d for URLIS_OPAQUE, url \"%s\", expected %d\n", ret, TEST_URLIS_ATTRIBS[i].url,
545             TEST_URLIS_ATTRIBS[i].expectOpaque );
546         ret = UrlIsA( TEST_URLIS_ATTRIBS[i].url, URLIS_FILEURL);
547         ok( ret == TEST_URLIS_ATTRIBS[i].expectFile,
548             "returned %d for URLIS_FILEURL, url \"%s\", expected %d\n", ret, TEST_URLIS_ATTRIBS[i].url,
549             TEST_URLIS_ATTRIBS[i].expectFile );
550
551         ret = UrlIsW( wurl, URLIS_OPAQUE);
552         ok( ret == TEST_URLIS_ATTRIBS[i].expectOpaque,
553             "returned %d for URLIS_OPAQUE (UrlIsW), url \"%s\", expected %d\n", ret, TEST_URLIS_ATTRIBS[i].url,
554             TEST_URLIS_ATTRIBS[i].expectOpaque );
555         ret = UrlIsW( wurl, URLIS_FILEURL);
556         ok( ret == TEST_URLIS_ATTRIBS[i].expectFile,
557             "returned %d for URLIS_FILEURL (UrlIsW), url \"%s\", expected %d\n", ret, TEST_URLIS_ATTRIBS[i].url,
558             TEST_URLIS_ATTRIBS[i].expectFile );
559     }
560 }
561
562 static void test_UrlUnescape(void)
563 {
564     CHAR szReturnUrl[INTERNET_MAX_URL_LENGTH];
565     WCHAR ret_urlW[INTERNET_MAX_URL_LENGTH];
566     WCHAR *urlW, *expected_urlW; 
567     DWORD dwEscaped;
568     size_t i;
569
570     for(i=0; i<sizeof(TEST_URL_UNESCAPE)/sizeof(TEST_URL_UNESCAPE[0]); i++) { 
571         dwEscaped=INTERNET_MAX_URL_LENGTH;
572         ok(UrlUnescapeA(TEST_URL_UNESCAPE[i].url, szReturnUrl, &dwEscaped, 0) == S_OK, "UrlEscapeA didn't return 0x%08lx from \"%s\"\n", S_OK, TEST_URL_UNESCAPE[i].url);
573         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);
574
575         dwEscaped = INTERNET_MAX_URL_LENGTH;
576         urlW = GetWideString(TEST_URL_UNESCAPE[i].url);
577         expected_urlW = GetWideString(TEST_URL_UNESCAPE[i].expect);
578         ok(UrlUnescapeW(urlW, ret_urlW, &dwEscaped, 0) == S_OK, "UrlEscapeW didn't return 0x%08lx from \"%s\"\n", S_OK, TEST_URL_UNESCAPE[i].url);
579         WideCharToMultiByte(CP_ACP,0,ret_urlW,-1,szReturnUrl,INTERNET_MAX_URL_LENGTH,0,0);
580         ok(strcmpW(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);
581         FreeWideString(urlW);
582         FreeWideString(expected_urlW);
583     }
584
585 }
586
587 static void test_PathSearchAndQualify(void)
588 {
589     WCHAR path1[] = {'c',':','\\','f','o','o',0};
590     WCHAR expect1[] = {'c',':','\\','f','o','o',0};
591     WCHAR path2[] = {'c',':','f','o','o',0};
592     WCHAR c_drive[] = {'c',':',0}; 
593     WCHAR foo[] = {'f','o','o',0}; 
594     WCHAR path3[] = {'\\','f','o','o',0};
595     WCHAR winini[] = {'w','i','n','.','i','n','i',0};
596     WCHAR out[MAX_PATH];
597     WCHAR cur_dir[MAX_PATH];
598     WCHAR dot[] = {'.',0};
599
600     /* c:\foo */
601     ok(PathSearchAndQualifyW(path1, out, MAX_PATH) != 0,
602        "PathSearchAndQualify rets 0\n");
603     ok(!lstrcmpiW(out, expect1), "strings don't match\n");
604
605     /* c:foo */
606     ok(PathSearchAndQualifyW(path2, out, MAX_PATH) != 0,
607        "PathSearchAndQualify rets 0\n");
608     GetFullPathNameW(c_drive, MAX_PATH, cur_dir, NULL);
609     PathAddBackslashW(cur_dir);
610     strcatW(cur_dir, foo);
611     ok(!lstrcmpiW(out, cur_dir), "strings don't match\n");    
612
613     /* foo */
614     ok(PathSearchAndQualifyW(foo, out, MAX_PATH) != 0,
615        "PathSearchAndQualify rets 0\n");
616     GetFullPathNameW(dot, MAX_PATH, cur_dir, NULL);
617     PathAddBackslashW(cur_dir);
618     strcatW(cur_dir, foo);
619     ok(!lstrcmpiW(out, cur_dir), "strings don't match\n");    
620
621     /* \foo */
622     ok(PathSearchAndQualifyW(path3, out, MAX_PATH) != 0,
623        "PathSearchAndQualify rets 0\n");
624     GetFullPathNameW(dot, MAX_PATH, cur_dir, NULL);
625     strcpyW(cur_dir + 2, path3);
626     ok(!lstrcmpiW(out, cur_dir), "strings don't match\n");
627
628     /* win.ini */
629     ok(PathSearchAndQualifyW(winini, out, MAX_PATH) != 0,
630        "PathSearchAndQualify rets 0\n");
631     if(!SearchPathW(NULL, winini, NULL, MAX_PATH, cur_dir, NULL))
632         GetFullPathNameW(winini, MAX_PATH, cur_dir, NULL);
633     ok(!lstrcmpiW(out, cur_dir), "strings don't match\n");
634
635 }
636
637 static void test_PathCreateFromUrl(void)
638 {
639     size_t i;
640     char ret_path[INTERNET_MAX_URL_LENGTH];
641     DWORD len, ret;
642     WCHAR ret_pathW[INTERNET_MAX_URL_LENGTH];
643     WCHAR *pathW, *urlW;
644
645     for(i = 0; i < sizeof(TEST_PATHFROMURL) / sizeof(TEST_PATHFROMURL[0]); i++) {
646         len = INTERNET_MAX_URL_LENGTH;
647         ret = PathCreateFromUrlA(TEST_PATHFROMURL[i].url, ret_path, &len, 0);
648         ok(ret == TEST_PATHFROMURL[i].ret, "ret %08lx from url %s\n", ret, TEST_PATHFROMURL[i].url);
649         if(TEST_PATHFROMURL[i].path) {
650            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);
651            ok(len == strlen(ret_path), "ret len %ld from url %s\n", len, TEST_PATHFROMURL[i].url);
652         }
653         len = INTERNET_MAX_URL_LENGTH;
654         pathW = GetWideString(TEST_PATHFROMURL[i].path);
655         urlW = GetWideString(TEST_PATHFROMURL[i].url);
656         ret = PathCreateFromUrlW(urlW, ret_pathW, &len, 0);
657         WideCharToMultiByte(CP_ACP, 0, ret_pathW, -1, ret_path, sizeof(ret_path),0,0);
658         ok(ret == TEST_PATHFROMURL[i].ret, "ret %08lx from url L\"%s\"\n", ret, TEST_PATHFROMURL[i].url);
659         if(TEST_PATHFROMURL[i].path) {
660             ok(!lstrcmpiW(ret_pathW, pathW), "got %s expected %s from url L\"%s\"\n", ret_path, TEST_PATHFROMURL[i].path, TEST_PATHFROMURL[i].url);
661             ok(len == strlenW(ret_pathW), "ret len %ld from url L\"%s\"\n", len, TEST_PATHFROMURL[i].url);
662         }
663         FreeWideString(urlW);
664         FreeWideString(pathW);
665     }
666 }
667
668
669 static void test_PathIsUrl(void)
670 {
671     size_t i;
672     BOOL ret;
673
674     for(i = 0; i < sizeof(TEST_PATH_IS_URL)/sizeof(TEST_PATH_IS_URL[0]); i++) {
675         ret = PathIsURLA(TEST_PATH_IS_URL[i].path);
676         ok(ret == TEST_PATH_IS_URL[i].expect,
677            "returned %d from path %s, expected %d\n", ret, TEST_PATH_IS_URL[i].path,
678            TEST_PATH_IS_URL[i].expect);
679     }
680 }
681
682 static const DWORD SHELL_charclass[] =
683 {
684     0x00000000, 0x00000000, 0x00000000, 0x00000000,
685     0x00000000, 0x00000000, 0x00000000, 0x00000000,
686     0x00000000, 0x00000000, 0x00000000, 0x00000000,
687     0x00000000, 0x00000000, 0x00000000, 0x00000000,
688     0x00000000, 0x00000000, 0x00000000, 0x00000000,
689     0x00000000, 0x00000000, 0x00000000, 0x00000000,
690     0x00000000, 0x00000000, 0x00000000, 0x00000000,
691     0x00000000, 0x00000000, 0x00000000, 0x00000000,
692     0x00000080, 0x00000100, 0x00000200, 0x00000100,
693     0x00000100, 0x00000100, 0x00000100, 0x00000100,
694     0x00000100, 0x00000100, 0x00000002, 0x00000100,
695     0x00000040, 0x00000100, 0x00000004, 0x00000000,
696     0x00000100, 0x00000100, 0x00000100, 0x00000100,
697     0x00000100, 0x00000100, 0x00000100, 0x00000100,
698     0x00000100, 0x00000100, 0x00000010, 0x00000020,
699     0x00000000, 0x00000100, 0x00000000, 0x00000001,
700     0x00000100, 0xffffffff, 0xffffffff, 0xffffffff,
701     0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
702     0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
703     0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
704     0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
705     0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
706     0xffffffff, 0xffffffff, 0xffffffff, 0x00000100,
707     0x00000008, 0x00000100, 0x00000100, 0x00000100,
708     0x00000100, 0xffffffff, 0xffffffff, 0xffffffff,
709     0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
710     0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
711     0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
712     0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
713     0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
714     0xffffffff, 0xffffffff, 0xffffffff, 0x00000100,
715     0x00000000, 0x00000100, 0x00000100
716 };
717
718 static void test_PathIsValidCharA(void)
719 {
720     BOOL ret;
721     unsigned int c;
722
723     ret = pPathIsValidCharA( 0x7f, 0 );
724     ok ( !ret, "PathIsValidCharA succeeded: 0x%08lx\n", (DWORD)ret );
725
726     ret = pPathIsValidCharA( 0x7f, 1 );
727     ok ( !ret, "PathIsValidCharA succeeded: 0x%08lx\n", (DWORD)ret );
728
729     for (c = 0; c < 0x7f; c++)
730     {
731         ret = pPathIsValidCharA( c, ~0U );
732         ok ( ret == SHELL_charclass[c] || (ret == 1 && SHELL_charclass[c] == 0xffffffff),
733              "PathIsValidCharA failed: 0x%02x got 0x%08lx expected 0x%08lx\n",
734              c, (DWORD)ret, SHELL_charclass[c] );
735     }
736
737     for (c = 0x7f; c <= 0xff; c++)
738     {
739         ret = pPathIsValidCharA( c, ~0U );
740         ok ( ret == 0x00000100,
741              "PathIsValidCharA failed: 0x%02x got 0x%08lx expected 0x00000100\n",
742              c, (DWORD)ret );
743     }
744 }
745
746 static void test_PathIsValidCharW(void)
747 {
748     BOOL ret;
749     unsigned int c;
750
751     ret = pPathIsValidCharW( 0x7f, 0 );
752     ok ( !ret, "PathIsValidCharW succeeded: 0x%08lx\n", (DWORD)ret );
753
754     ret = pPathIsValidCharW( 0x7f, 1 );
755     ok ( !ret, "PathIsValidCharW succeeded: 0x%08lx\n", (DWORD)ret );
756
757     for (c = 0; c < 0x7f; c++)
758     {
759         ret = pPathIsValidCharW( c, ~0U );
760         ok ( ret == SHELL_charclass[c] || (ret == 1 && SHELL_charclass[c] == 0xffffffff),
761              "PathIsValidCharW failed: 0x%02x got 0x%08lx expected 0x%08lx\n",
762              c, (DWORD)ret, SHELL_charclass[c] );
763     }
764
765     for (c = 0x007f; c <= 0xffff; c++)
766     {
767         ret = pPathIsValidCharW( c, ~0U );
768         ok ( ret == 0x00000100,
769              "PathIsValidCharW failed: 0x%02x got 0x%08lx expected 0x00000100\n",
770              c, (DWORD)ret );
771     }
772 }
773
774 static void test_PathMakePretty(void)
775 {
776    char buff[MAX_PATH];
777
778    ok (PathMakePrettyA(NULL) == FALSE, "PathMakePretty: NULL path succeeded\n");
779    buff[0] = '\0';
780    ok (PathMakePrettyA(buff) == TRUE, "PathMakePretty: Empty path failed\n");
781
782    strcpy(buff, "C:\\A LONG FILE NAME WITH \\SPACES.TXT");
783    ok (PathMakePrettyA(buff) == TRUE, "PathMakePretty: Long UC name failed\n");
784    ok (strcmp(buff, "C:\\a long file name with \\spaces.txt") == 0,
785        "PathMakePretty: Long UC name not changed\n");
786
787    strcpy(buff, "C:\\A LONG FILE NAME WITH \\MixedCase.TXT");
788    ok (PathMakePrettyA(buff) == FALSE, "PathMakePretty: Long MC name succeeded\n");
789    ok (strcmp(buff, "C:\\A LONG FILE NAME WITH \\MixedCase.TXT") == 0,
790        "PathMakePretty: Failed but modified path\n");
791
792    strcpy(buff, "TEST");
793    ok (PathMakePrettyA(buff) == TRUE,  "PathMakePretty: Short name failed\n");
794    ok (strcmp(buff, "Test") == 0,  "PathMakePretty: 1st char lowercased %s\n", buff);
795 }
796
797 START_TEST(path)
798 {
799   hShlwapi = LoadLibraryA("shlwapi.dll");
800   if (!hShlwapi) return;
801
802   test_UrlHash();
803   test_UrlGetPart();
804   test_UrlCanonicalize();
805   test_UrlEscape();
806   test_UrlCombine();
807   test_UrlCreateFromPath();
808   test_UrlIs();
809   test_UrlUnescape();
810
811   test_PathSearchAndQualify();
812   test_PathCreateFromUrl();
813   test_PathIsUrl();
814   
815   test_PathMakePretty();
816
817   /* For whatever reason, PathIsValidCharA and PathAppendA share the same
818    * ordinal number in some native versions. Check this to prevent a crash.
819    */
820   pPathIsValidCharA = (void*)GetProcAddress(hShlwapi, (LPSTR)455);
821   if (pPathIsValidCharA && pPathIsValidCharA != (void*)GetProcAddress(hShlwapi, "PathAppendA"))
822   {
823     test_PathIsValidCharA();
824
825      pPathIsValidCharW = (void*)GetProcAddress(hShlwapi, (LPSTR)456);
826      if (pPathIsValidCharW) test_PathIsValidCharW();
827   }
828 }