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