wined3d: Implement more GLSL instructions and a little cleanup.
[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., 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", 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     {"file:///c:\\tests\\foo bar", 0, S_OK, "file:///c:/tests/foo bar"},
77     {"file:///c:\\tests\\foo bar", URL_DONT_SIMPLIFY, S_OK, "file:///c:/tests/foo bar"},
78 };
79
80 typedef struct _TEST_URL_ESCAPE {
81     const char *url;
82     DWORD flags;
83     DWORD expectescaped;
84     HRESULT expectret;
85     const char *expecturl;
86 } TEST_URL_ESCAPE;
87
88 const TEST_URL_ESCAPE TEST_ESCAPE[] = {
89     {"http://www.winehq.org/tests0", 0, 0, S_OK, "http://www.winehq.org/tests0"},
90     {"http://www.winehq.org/tests1\n", 0, 0, S_OK, "http://www.winehq.org/tests1%0A"},
91     {"http://www.winehq.org/tests2\r", 0, 0, S_OK, "http://www.winehq.org/tests2%0D"},
92     {"http://www.winehq.org/tests3\r", URL_ESCAPE_SPACES_ONLY|URL_ESCAPE_UNSAFE, 0, S_OK, "http://www.winehq.org/tests3\r"},
93     {"http://www.winehq.org/tests4\r", URL_ESCAPE_SPACES_ONLY, 0, S_OK, "http://www.winehq.org/tests4\r"},
94     {"http://www.winehq.org/tests5\r", URL_WININET_COMPATIBILITY|URL_ESCAPE_SPACES_ONLY, 0, S_OK, "http://www.winehq.org/tests5\r"},
95     {"/direct/swhelp/series6/6.2i_latestservicepack.dat\r", URL_ESCAPE_SPACES_ONLY, 0, S_OK, "/direct/swhelp/series6/6.2i_latestservicepack.dat\r"},
96
97     {"file://////foo/bar\\baz", 0, 0, S_OK, "file://foo/bar/baz"},
98     {"file://///foo/bar\\baz", 0, 0, S_OK, "file://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:///localhost/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:///foo/bar/baz"},
103     {"file://foo/bar\\baz", 0, 0, S_OK, "file://foo/bar/baz"},
104     {"file:/localhost/foo/bar\\baz", 0, 0, S_OK, "file:///localhost/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:\\\\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:///foo/bar/baz"},
111     {"file:///f oo/b?a r\\baz", 0, 0, S_OK, "file:///f%20oo/b?a r\\baz"},
112     {"file:///foo/b#a r\\baz", 0, 0, S_OK, "file:///foo/b%23a%20r/baz"},
113     {"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"},
114     {"file:///f o%o/b?a r\\b%az", URL_ESCAPE_PERCENT, 0, S_OK, "file:///f%20o%25o/b?a r\\b%az"},
115     {"file:/foo/bar\\baz", URL_ESCAPE_SEGMENT_ONLY, 0, S_OK, "file:%2Ffoo%2Fbar%5Cbaz"},
116
117     {"foo/b%ar\\ba?z\\", URL_ESCAPE_SEGMENT_ONLY, 0, S_OK, "foo%2Fb%ar%5Cba%3Fz%5C"},
118     {"foo/b%ar\\ba?z\\", URL_ESCAPE_PERCENT | URL_ESCAPE_SEGMENT_ONLY, 0, S_OK, "foo%2Fb%25ar%5Cba%3Fz%5C"},
119     {"foo/bar\\ba?z\\", 0, 0, S_OK, "foo/bar%5Cba?z\\"},
120     {"/foo/bar\\ba?z\\", 0, 0, S_OK, "/foo/bar%5Cba?z\\"},
121     {"/foo/bar\\ba#z\\", 0, 0, S_OK, "/foo/bar%5Cba#z\\"},
122     {"/foo/%5C", 0, 0, S_OK, "/foo/%5C"},
123     {"/foo/%5C", URL_ESCAPE_PERCENT, 0, S_OK, "/foo/%255C"},
124
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:////foo/bar\\baz", 0, 0, S_OK, "http:////foo/bar/baz"},
128     {"http:///foo/bar\\baz", 0, 0, S_OK, "http:///foo/bar/baz"},
129     {"http://localhost/foo/bar\\baz", 0, 0, S_OK, "http://localhost/foo/bar/baz"},
130     {"http://foo/bar\\baz", 0, 0, S_OK, "http://foo/bar/baz"},
131     {"http:/foo/bar\\baz", 0, 0, S_OK, "http:/foo/bar/baz"},
132     {"http:foo/bar\\ba?z\\", 0, 0, S_OK, "http:foo%2Fbar%2Fba?z\\"},
133     {"http:foo/bar\\ba#z\\", 0, 0, S_OK, "http:foo%2Fbar%2Fba#z\\"},
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:\\\\\\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:/fo ?o/b ar\\baz", 0, 0, S_OK, "http:/fo%20?o/b ar\\baz"},
139     {"http:fo ?o/b ar\\baz", 0, 0, S_OK, "http:fo%20?o/b ar\\baz"},
140     {"http:/foo/bar\\baz", URL_ESCAPE_SEGMENT_ONLY, 0, S_OK, "http:%2Ffoo%2Fbar%5Cbaz"},
141
142     {"https://foo/bar\\baz", 0, 0, S_OK, "https://foo/bar/baz"},
143     {"https:/foo/bar\\baz", 0, 0, S_OK, "https:/foo/bar/baz"},
144     {"https:\\foo/bar\\baz", 0, 0, S_OK, "https:/foo/bar/baz"},
145
146     {"foo:////foo/bar\\baz", 0, 0, S_OK, "foo:////foo/bar%5Cbaz"},
147     {"foo:///foo/bar\\baz", 0, 0, S_OK, "foo:///foo/bar%5Cbaz"},
148     {"foo://localhost/foo/bar\\baz", 0, 0, S_OK, "foo://localhost/foo/bar%5Cbaz"},
149     {"foo://foo/bar\\baz", 0, 0, S_OK, "foo://foo/bar%5Cbaz"},
150     {"foo:/foo/bar\\baz", 0, 0, S_OK, "foo:/foo/bar%5Cbaz"},
151     {"foo:foo/bar\\baz", 0, 0, S_OK, "foo:foo%2Fbar%5Cbaz"},
152     {"foo:\\foo/bar\\baz", 0, 0, S_OK, "foo:%5Cfoo%2Fbar%5Cbaz"},
153     {"foo:/foo/bar\\ba?\\z", 0, 0, S_OK, "foo:/foo/bar%5Cba?\\z"},
154     {"foo:/foo/bar\\ba#\\z", 0, 0, S_OK, "foo:/foo/bar%5Cba#\\z"},
155
156     {"mailto:/fo/o@b\\%a?\\r.b#\\az", 0, 0, S_OK, "mailto:%2Ffo%2Fo@b%5C%a%3F%5Cr.b%23%5Caz"},
157     {"mailto:fo/o@b\\%a?\\r.b#\\az", 0, 0, S_OK, "mailto:fo%2Fo@b%5C%a%3F%5Cr.b%23%5Caz"},
158     {"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"},
159
160     {"ftp:fo/o@bar.baz/foo/bar", 0, 0, S_OK, "ftp:fo%2Fo@bar.baz%2Ffoo%2Fbar"},
161     {"ftp:/fo/o@bar.baz/foo/bar", 0, 0, S_OK, "ftp:/fo/o@bar.baz/foo/bar"},
162     {"ftp://fo/o@bar.baz/fo?o\\bar", 0, 0, S_OK, "ftp://fo/o@bar.baz/fo?o\\bar"},
163     {"ftp://fo/o@bar.baz/fo#o\\bar", 0, 0, S_OK, "ftp://fo/o@bar.baz/fo#o\\bar"},
164     {"ftp://localhost/o@bar.baz/fo#o\\bar", 0, 0, S_OK, "ftp://localhost/o@bar.baz/fo#o\\bar"},
165     {"ftp:///fo/o@bar.baz/foo/bar", 0, 0, S_OK, "ftp:///fo/o@bar.baz/foo/bar"},
166     {"ftp:////fo/o@bar.baz/foo/bar", 0, 0, S_OK, "ftp:////fo/o@bar.baz/foo/bar"}
167 };
168
169 typedef struct _TEST_URL_COMBINE {
170     const char *url1;
171     const char *url2;
172     DWORD flags;
173     HRESULT expectret;
174     const char *expecturl;
175 } TEST_URL_COMBINE;
176
177 const TEST_URL_COMBINE TEST_COMBINE[] = {
178     {"http://www.winehq.org/tests", "tests1", 0, S_OK, "http://www.winehq.org/tests1"},
179     {"http://www.%77inehq.org/tests", "tests1", 0, S_OK, "http://www.%77inehq.org/tests1"},
180     /*FIXME {"http://www.winehq.org/tests", "../tests2", 0, S_OK, "http://www.winehq.org/tests2"},*/
181     {"http://www.winehq.org/tests/", "../tests3", 0, S_OK, "http://www.winehq.org/tests3"},
182     {"http://www.winehq.org/tests/test1", "test2", 0, S_OK, "http://www.winehq.org/tests/test2"},
183     {"http://www.winehq.org/tests/../tests", "tests4", 0, S_OK, "http://www.winehq.org/tests4"},
184     {"http://www.winehq.org/tests/../tests/", "tests5", 0, S_OK, "http://www.winehq.org/tests/tests5"},
185     {"http://www.winehq.org/tests/../tests/", "/tests6/..", 0, S_OK, "http://www.winehq.org/"},
186     {"http://www.winehq.org/tests/../tests/..", "tests7/..", 0, S_OK, "http://www.winehq.org/"},
187     {"http://www.winehq.org/tests/?query=x&return=y", "tests8", 0, S_OK, "http://www.winehq.org/tests/tests8"},
188     {"http://www.winehq.org/tests/#example", "tests9", 0, S_OK, "http://www.winehq.org/tests/tests9"},
189     {"http://www.winehq.org/tests/../tests/", "/tests10/..", URL_DONT_SIMPLIFY, S_OK, "http://www.winehq.org/tests10/.."},
190     {"http://www.winehq.org/tests/../", "tests11", URL_DONT_SIMPLIFY, S_OK, "http://www.winehq.org/tests/../tests11"},
191     {"file:///C:\\dir\\file.txt", "test.txt", 0, S_OK, "file:///C:/dir/test.txt"}
192 };
193
194 struct {
195     const char *path;
196     const char *url;
197     DWORD ret;
198 } TEST_URLFROMPATH [] = {
199     {"foo", "file:foo", S_OK},
200     {"foo\\bar", "file:foo/bar", S_OK},
201     {"\\foo\\bar", "file:///foo/bar", S_OK},
202     {"c:\\foo\\bar", "file:///c:/foo/bar", S_OK},
203     {"c:foo\\bar", "file:///c:foo/bar", S_OK},
204     {"c:\\foo/b a%r", "file:///c:/foo/b%20a%25r", S_OK},
205     {"c:\\foo\\foo bar", "file:///c:/foo/foo%20bar", S_OK},
206 #if 0
207     /* The following test fails on native shlwapi as distributed with Win95/98.
208      * Wine matches the behaviour of later versions.
209      */
210     {"xx:c:\\foo\\bar", "xx:c:\\foo\\bar", S_FALSE}
211 #endif
212 };
213
214 struct {
215     const char *url;
216     const char *path;
217     DWORD ret;
218 } TEST_PATHFROMURL[] = {
219     {"file:///c:/foo/ba%5Cr", "c:\\foo\\ba\\r", S_OK},
220     {"file:///c:/foo/../ba%5Cr", "c:\\foo\\..\\ba\\r", S_OK},
221     {"file:///host/c:/foo/bar", "\\host\\c:\\foo\\bar", S_OK},
222     {"file://host/c:/foo/bar", "\\\\hostc:\\foo\\bar", S_OK},
223     {"file://host/c:/foo/bar", "\\\\hostc:\\foo\\bar", S_OK},
224     {"file:\\\\host\\c:\\foo\\bar", "\\\\hostc:\\foo\\bar", S_OK},
225     {"file:\\\\host\\ca\\foo\\bar", "\\\\host\\ca\\foo\\bar", S_OK},
226     {"file:\\\\host\\c|\\foo\\bar", "\\\\hostc|\\foo\\bar", S_OK},
227     {"file:\\%5Chost\\c:\\foo\\bar", "\\\\host\\c:\\foo\\bar", S_OK},
228     {"file:\\\\host\\cx:\\foo\\bar", "\\\\host\\cx:\\foo\\bar", S_OK},
229     {"file://c:/foo/bar", "c:\\foo\\bar", S_OK},
230     {"file://c:/d:/foo/bar", "c:\\d:\\foo\\bar", S_OK},
231     {"file://c|/d|/foo/bar", "c:\\d|\\foo\\bar", S_OK},
232     {"file://host/foo/bar", "\\\\host\\foo\\bar", S_OK},
233     {"file:/foo/bar", "\\foo\\bar", S_OK},
234     {"file:/foo/bar/", "\\foo\\bar\\", S_OK},
235     {"file:foo/bar", "foo\\bar", S_OK},
236     {"file:c:/foo/bar", "c:\\foo\\bar", S_OK},
237     {"file:c|/foo/bar", "c:\\foo\\bar", S_OK},
238     {"file:cx|/foo/bar", "cx|\\foo\\bar", S_OK},
239     {"file:////c:/foo/bar", "c:\\foo\\bar", S_OK},
240 /*    {"file:////c:/foo/foo%20bar", "c:\\foo\\foo%20bar", S_OK},*/
241
242     {"c:\\foo\\bar", NULL, E_INVALIDARG},
243     {"foo/bar", NULL, E_INVALIDARG},
244     {"http://foo/bar", NULL, E_INVALIDARG},
245
246 };
247
248 struct {
249     char url[30];
250     const char *expect;
251 } TEST_URL_UNESCAPE[] = {
252     {"file://foo/bar", "file://foo/bar"},
253     {"file://fo%20o%5Ca/bar", "file://fo o\\a/bar"}
254 };
255
256
257 struct {
258     const char *path;
259     BOOL expect;
260 } TEST_PATH_IS_URL[] = {
261     {"http://foo/bar", TRUE},
262     {"c:\\foo\\bar", FALSE},
263     {"foo://foo/bar", TRUE},
264     {"foo\\bar", FALSE},
265     {"foo.bar", FALSE},
266     {"bogusscheme:", TRUE},
267     {"http:partial", TRUE}
268 };
269
270 struct {
271     const char *url;
272     BOOL expectOpaque;
273     BOOL expectFile;
274 } TEST_URLIS_ATTRIBS[] = {
275     {   "ftp:",                                         FALSE,  FALSE   },
276     {   "http:",                                        FALSE,  FALSE   },
277     {   "gopher:",                                      FALSE,  FALSE   },
278     {   "mailto:",                                      TRUE,   FALSE   },
279     {   "news:",                                        FALSE,  FALSE   },
280     {   "nntp:",                                        FALSE,  FALSE   },
281     {   "telnet:",                                      FALSE,  FALSE   },
282     {   "wais:",                                        FALSE,  FALSE   },
283     {   "file:",                                        FALSE,  TRUE    },
284     {   "mk:",                                          FALSE,  FALSE   },
285     {   "https:",                                       FALSE,  FALSE   },
286     {   "shell:",                                       TRUE,   FALSE   },
287     {   "https:",                                       FALSE,  FALSE   },
288     {   "snews:",                                       FALSE,  FALSE   },
289     {   "local:",                                       FALSE,  FALSE   },
290     {   "javascript:",                                  TRUE,   FALSE   },
291     {   "vbscript:",                                    TRUE,   FALSE   },
292     {   "about:",                                       TRUE,   FALSE   },
293     {   "res:",                                         FALSE,  FALSE   },
294     {   "bogusscheme:",                                 FALSE,  FALSE   },
295     {   "file:\\\\e:\\b\\c",                            FALSE,  TRUE    },
296     {   "file://e:/b/c",                                FALSE,  TRUE    },
297     {   "http:partial",                                 FALSE,  FALSE   },
298     {   "mailto://www.winehq.org/test.html",            TRUE,   FALSE   },
299     {   "file:partial",                                 FALSE,  TRUE    }
300 };
301
302
303 static LPWSTR GetWideString(const char* szString)
304 {
305   LPWSTR wszString = HeapAlloc(GetProcessHeap(), 0, (2*INTERNET_MAX_URL_LENGTH) * sizeof(WCHAR));
306   
307   MultiByteToWideChar(0, 0, szString, -1, wszString, INTERNET_MAX_URL_LENGTH);
308
309   return wszString;
310 }
311
312 static void FreeWideString(LPWSTR wszString)
313 {
314    HeapFree(GetProcessHeap(), 0, wszString);
315 }
316
317 static void hash_url(const char* szUrl)
318 {
319   LPCSTR szTestUrl = szUrl;
320   LPWSTR wszTestUrl = GetWideString(szTestUrl);
321   
322   DWORD cbSize = sizeof(DWORD);
323   DWORD dwHash1, dwHash2;
324   ok(UrlHashA(szTestUrl, (LPBYTE)&dwHash1, cbSize) == S_OK, "UrlHashA didn't return S_OK\n");
325   ok(UrlHashW(wszTestUrl, (LPBYTE)&dwHash2, cbSize) == S_OK, "UrlHashW didn't return S_OK\n");
326
327   FreeWideString(wszTestUrl);
328
329   ok(dwHash1 == dwHash2, "Hashes didn't compare\n");
330 }
331
332 static void test_UrlHash(void)
333 {
334   hash_url(TEST_URL_1);
335   hash_url(TEST_URL_2);
336   hash_url(TEST_URL_3);
337 }
338
339 static void test_url_part(const char* szUrl, DWORD dwPart, DWORD dwFlags, const char* szExpected)
340 {
341   CHAR szPart[INTERNET_MAX_URL_LENGTH];
342   WCHAR wszPart[INTERNET_MAX_URL_LENGTH];
343   LPWSTR wszUrl = GetWideString(szUrl);
344   LPWSTR wszConvertedPart;
345
346   DWORD dwSize;
347
348   dwSize = INTERNET_MAX_URL_LENGTH;
349   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);
350   dwSize = INTERNET_MAX_URL_LENGTH;
351   ok( UrlGetPartW(wszUrl, wszPart, &dwSize, dwPart, dwFlags) == S_OK, "UrlGetPartW didn't return S_OK\n" );
352
353   wszConvertedPart = GetWideString(szPart);
354
355   ok(lstrcmpW(wszPart,wszConvertedPart)==0, "Strings didn't match between ascii and unicode UrlGetPart!\n");
356
357   FreeWideString(wszUrl);
358   FreeWideString(wszConvertedPart);
359
360   /* Note that v6.0 and later don't return '?' with the query */
361   ok(strcmp(szPart,szExpected)==0 ||
362      (*szExpected=='?' && !strcmp(szPart,szExpected+1)),
363          "Expected %s, but got %s\n", szExpected, szPart);
364 }
365
366 static void test_UrlGetPart(void)
367 {
368   test_url_part(TEST_URL_3, URL_PART_HOSTNAME, 0, "localhost");
369   test_url_part(TEST_URL_3, URL_PART_PORT, 0, "21");
370   test_url_part(TEST_URL_3, URL_PART_USERNAME, 0, "foo");
371   test_url_part(TEST_URL_3, URL_PART_PASSWORD, 0, "bar");
372   test_url_part(TEST_URL_3, URL_PART_SCHEME, 0, "http");
373   test_url_part(TEST_URL_3, URL_PART_QUERY, 0, "?query=x&return=y");
374 }
375
376 static void test_url_escape(const char *szUrl, DWORD dwFlags, HRESULT dwExpectReturn, const char *szExpectUrl)
377 {
378     CHAR szReturnUrl[INTERNET_MAX_URL_LENGTH];
379     DWORD dwEscaped;
380     WCHAR ret_urlW[INTERNET_MAX_URL_LENGTH];
381     WCHAR *urlW, *expected_urlW;
382     dwEscaped=INTERNET_MAX_URL_LENGTH;
383
384     ok(UrlEscapeA(szUrl, szReturnUrl, &dwEscaped, dwFlags) == dwExpectReturn, "UrlEscapeA didn't return 0x%08lx from \"%s\"\n", dwExpectReturn, szUrl);
385     ok(strcmp(szReturnUrl,szExpectUrl)==0, "Expected \"%s\", but got \"%s\" from \"%s\"\n", szExpectUrl, szReturnUrl, szUrl);
386     
387     dwEscaped = INTERNET_MAX_URL_LENGTH;
388     urlW = GetWideString(szUrl);
389     expected_urlW = GetWideString(szExpectUrl);
390     ok(UrlEscapeW(urlW, ret_urlW, &dwEscaped, dwFlags) == dwExpectReturn, "UrlEscapeW didn't return 0x%08lx from \"%s\"\n", dwExpectReturn, szUrl);
391     WideCharToMultiByte(CP_ACP,0,ret_urlW,-1,szReturnUrl,INTERNET_MAX_URL_LENGTH,0,0);
392     ok(lstrcmpW(ret_urlW, expected_urlW)==0, "Expected \"%s\", but got \"%s\" from \"%s\" flags %08lx\n", szExpectUrl, szReturnUrl, szUrl, dwFlags);
393     FreeWideString(urlW);
394     FreeWideString(expected_urlW);
395
396 }
397
398 static void test_url_canonicalize(const char *szUrl, DWORD dwFlags, HRESULT dwExpectReturn, const char *szExpectUrl)
399 {
400     CHAR szReturnUrl[INTERNET_MAX_URL_LENGTH];
401     WCHAR wszReturnUrl[INTERNET_MAX_URL_LENGTH];
402     LPWSTR wszUrl = GetWideString(szUrl);
403     LPWSTR wszExpectUrl = GetWideString(szExpectUrl);
404     LPWSTR wszConvertedUrl;
405     
406     DWORD dwSize;
407     
408     dwSize = INTERNET_MAX_URL_LENGTH;
409     ok(UrlCanonicalizeA(szUrl, NULL, &dwSize, dwFlags) != dwExpectReturn, "Unexpected return for NULL buffer\n");
410     ok(UrlCanonicalizeA(szUrl, szReturnUrl, &dwSize, dwFlags) == dwExpectReturn, "UrlCanonicalizeA didn't return 0x%08lx\n", dwExpectReturn);
411     ok(strcmp(szReturnUrl,szExpectUrl)==0, "UrlCanonicalizeA dwFlags 0x%08lx Expected %s, but got %s\n", dwFlags, szExpectUrl, szReturnUrl);
412
413     dwSize = INTERNET_MAX_URL_LENGTH;
414     ok(UrlCanonicalizeW(wszUrl, NULL, &dwSize, dwFlags) != dwExpectReturn, "Unexpected return for NULL buffer\n");
415     ok(UrlCanonicalizeW(wszUrl, wszReturnUrl, &dwSize, dwFlags) == dwExpectReturn, "UrlCanonicalizeW didn't return 0x%08lx\n", dwExpectReturn);
416     wszConvertedUrl = GetWideString(szReturnUrl);
417     ok(lstrcmpW(wszReturnUrl, wszConvertedUrl)==0, "Strings didn't match between ascii and unicode UrlCanonicalize!\n");
418     FreeWideString(wszConvertedUrl);
419     
420             
421     FreeWideString(wszUrl);
422     FreeWideString(wszExpectUrl);
423 }
424
425
426 static void test_UrlEscape(void)
427 {
428     unsigned int i;
429     for(i=0; i<sizeof(TEST_ESCAPE)/sizeof(TEST_ESCAPE[0]); i++) {
430         test_url_escape(TEST_ESCAPE[i].url, TEST_ESCAPE[i].flags,
431                               TEST_ESCAPE[i].expectret, TEST_ESCAPE[i].expecturl);
432     }
433 }
434
435 static void test_UrlCanonicalize(void)
436 {
437     unsigned int i;
438     for(i=0; i<sizeof(TEST_CANONICALIZE)/sizeof(TEST_CANONICALIZE[0]); i++) {
439         test_url_canonicalize(TEST_CANONICALIZE[i].url, TEST_CANONICALIZE[i].flags,
440                               TEST_CANONICALIZE[i].expectret, TEST_CANONICALIZE[i].expecturl);
441     }
442 }
443
444 static void test_url_combine(const char *szUrl1, const char *szUrl2, DWORD dwFlags, HRESULT dwExpectReturn, const char *szExpectUrl)
445 {
446     HRESULT hr;
447     CHAR szReturnUrl[INTERNET_MAX_URL_LENGTH];
448     WCHAR wszReturnUrl[INTERNET_MAX_URL_LENGTH];
449     LPWSTR wszUrl1 = GetWideString(szUrl1);
450     LPWSTR wszUrl2 = GetWideString(szUrl2);
451     LPWSTR wszExpectUrl = GetWideString(szExpectUrl);
452     LPWSTR wszConvertedUrl;
453
454     DWORD dwSize;
455     DWORD dwExpectLen = lstrlen(szExpectUrl);
456
457     hr = UrlCombineA(szUrl1, szUrl2, NULL, NULL, dwFlags);
458     ok(hr == E_INVALIDARG, "UrlCombineA returned 0x%08lx, expected 0x%08lx\n", hr, E_INVALIDARG);
459     
460     dwSize = 0;
461     hr = UrlCombineA(szUrl1, szUrl2, NULL, &dwSize, dwFlags);
462     ok(hr == E_POINTER, "Checking length of string, return was 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     dwSize--;
466     hr = UrlCombineA(szUrl1, szUrl2, szReturnUrl, &dwSize, dwFlags);
467     ok(hr == E_POINTER, "UrlCombineA returned 0x%08lx, expected 0x%08lx\n", hr, E_POINTER);
468     ok(dwSize == dwExpectLen+1, "Got length %ld, expected %ld\n", dwSize, dwExpectLen+1);
469     
470     hr = UrlCombineA(szUrl1, szUrl2, szReturnUrl, &dwSize, dwFlags);
471     ok(hr == dwExpectReturn, "UrlCombineA returned 0x%08lx, expected 0x%08lx\n", hr, dwExpectReturn);
472     ok(dwSize == dwExpectLen, "Got length %ld, expected %ld\n", dwSize, dwExpectLen);
473     if(SUCCEEDED(hr)) {
474         ok(strcmp(szReturnUrl,szExpectUrl)==0, "Expected %s, but got %s\n", szExpectUrl, szReturnUrl);
475     }
476
477     dwSize = 0;
478     hr = UrlCombineW(wszUrl1, wszUrl2, NULL, &dwSize, dwFlags);
479     ok(hr == E_POINTER, "Checking length of string, return was 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     dwSize--;
483     hr = UrlCombineW(wszUrl1, wszUrl2, wszReturnUrl, &dwSize, dwFlags);
484     ok(hr == E_POINTER, "UrlCombineA returned 0x%08lx, expected 0x%08lx\n", hr, E_POINTER);
485     ok(dwSize == dwExpectLen+1, "Got length %ld, expected %ld\n", dwSize, dwExpectLen+1);
486     
487     hr = UrlCombineW(wszUrl1, wszUrl2, wszReturnUrl, &dwSize, dwFlags);
488     ok(hr == dwExpectReturn, "UrlCombineW returned 0x%08lx, expected 0x%08lx\n", hr, dwExpectReturn);
489     ok(dwSize == dwExpectLen, "Got length %ld, expected %ld\n", dwSize, dwExpectLen);
490     if(SUCCEEDED(hr)) {
491         wszConvertedUrl = GetWideString(szReturnUrl);
492         ok(lstrcmpW(wszReturnUrl, wszConvertedUrl)==0, "Strings didn't match between ascii and unicode UrlCombine!\n");
493         FreeWideString(wszConvertedUrl);
494     }
495
496     FreeWideString(wszUrl1);
497     FreeWideString(wszUrl2);
498     FreeWideString(wszExpectUrl);
499 }
500
501 static void test_UrlCombine(void)
502 {
503     unsigned int i;
504     for(i=0; i<sizeof(TEST_COMBINE)/sizeof(TEST_COMBINE[0]); i++) {
505         test_url_combine(TEST_COMBINE[i].url1, TEST_COMBINE[i].url2, TEST_COMBINE[i].flags,
506                          TEST_COMBINE[i].expectret, TEST_COMBINE[i].expecturl);
507     }
508 }
509
510 static void test_UrlCreateFromPath(void)
511 {
512     size_t i;
513     char ret_url[INTERNET_MAX_URL_LENGTH];
514     DWORD len, ret;
515     WCHAR ret_urlW[INTERNET_MAX_URL_LENGTH];
516     WCHAR *pathW, *urlW;
517
518     for(i = 0; i < sizeof(TEST_URLFROMPATH) / sizeof(TEST_URLFROMPATH[0]); i++) {
519         len = INTERNET_MAX_URL_LENGTH;
520         ret = UrlCreateFromPathA(TEST_URLFROMPATH[i].path, ret_url, &len, 0);
521         ok(ret == TEST_URLFROMPATH[i].ret, "ret %08lx from path %s\n", ret, TEST_URLFROMPATH[i].path);
522         ok(!lstrcmpi(ret_url, TEST_URLFROMPATH[i].url), "url %s from path %s\n", ret_url, TEST_URLFROMPATH[i].path);
523         ok(len == strlen(ret_url), "ret len %ld from path %s\n", len, TEST_URLFROMPATH[i].path);
524
525         len = INTERNET_MAX_URL_LENGTH;
526         pathW = GetWideString(TEST_URLFROMPATH[i].path);
527         urlW = GetWideString(TEST_URLFROMPATH[i].url);
528         ret = UrlCreateFromPathW(pathW, ret_urlW, &len, 0);
529         WideCharToMultiByte(CP_ACP, 0, ret_urlW, -1, ret_url, sizeof(ret_url),0,0);
530         ok(ret == TEST_URLFROMPATH[i].ret, "ret %08lx from path L\"%s\", expected %08lx\n",
531            ret, TEST_URLFROMPATH[i].path, TEST_URLFROMPATH[i].ret);
532         ok(!lstrcmpiW(ret_urlW, urlW), "got %s expected %s from path L\"%s\"\n", ret_url, TEST_URLFROMPATH[i].url, TEST_URLFROMPATH[i].path);
533         ok(len == lstrlenW(ret_urlW), "ret len %ld from path L\"%s\"\n", len, TEST_URLFROMPATH[i].path);
534         FreeWideString(urlW);
535         FreeWideString(pathW);
536     }
537 }
538
539 static void test_UrlIs(void)
540 {
541     BOOL ret;
542     size_t i;
543     WCHAR wurl[80];
544
545     for(i = 0; i < sizeof(TEST_PATH_IS_URL) / sizeof(TEST_PATH_IS_URL[0]); i++) {
546         MultiByteToWideChar(CP_ACP, 0, TEST_PATH_IS_URL[i].path, -1, wurl, 80);
547
548         ret = UrlIsA( TEST_PATH_IS_URL[i].path, URLIS_URL );
549         ok( ret == TEST_PATH_IS_URL[i].expect,
550             "returned %d from path %s, expected %d\n", ret, TEST_PATH_IS_URL[i].path,
551             TEST_PATH_IS_URL[i].expect );
552
553         ret = UrlIsW( wurl, URLIS_URL );
554         ok( ret == TEST_PATH_IS_URL[i].expect,
555             "returned %d from path (UrlIsW) %s, expected %d\n", ret, TEST_PATH_IS_URL[i].path,
556             TEST_PATH_IS_URL[i].expect );
557     }
558     for(i = 0; i < sizeof(TEST_URLIS_ATTRIBS) / sizeof(TEST_URLIS_ATTRIBS[0]); i++) {
559         MultiByteToWideChar(CP_ACP, 0, TEST_URLIS_ATTRIBS[i].url, -1, wurl, 80);
560
561         ret = UrlIsA( TEST_URLIS_ATTRIBS[i].url, URLIS_OPAQUE);
562         ok( ret == TEST_URLIS_ATTRIBS[i].expectOpaque,
563             "returned %d for URLIS_OPAQUE, url \"%s\", expected %d\n", ret, TEST_URLIS_ATTRIBS[i].url,
564             TEST_URLIS_ATTRIBS[i].expectOpaque );
565         ret = UrlIsA( TEST_URLIS_ATTRIBS[i].url, URLIS_FILEURL);
566         ok( ret == TEST_URLIS_ATTRIBS[i].expectFile,
567             "returned %d for URLIS_FILEURL, url \"%s\", expected %d\n", ret, TEST_URLIS_ATTRIBS[i].url,
568             TEST_URLIS_ATTRIBS[i].expectFile );
569
570         ret = UrlIsW( wurl, URLIS_OPAQUE);
571         ok( ret == TEST_URLIS_ATTRIBS[i].expectOpaque,
572             "returned %d for URLIS_OPAQUE (UrlIsW), url \"%s\", expected %d\n", ret, TEST_URLIS_ATTRIBS[i].url,
573             TEST_URLIS_ATTRIBS[i].expectOpaque );
574         ret = UrlIsW( wurl, URLIS_FILEURL);
575         ok( ret == TEST_URLIS_ATTRIBS[i].expectFile,
576             "returned %d for URLIS_FILEURL (UrlIsW), url \"%s\", expected %d\n", ret, TEST_URLIS_ATTRIBS[i].url,
577             TEST_URLIS_ATTRIBS[i].expectFile );
578     }
579 }
580
581 static void test_UrlUnescape(void)
582 {
583     CHAR szReturnUrl[INTERNET_MAX_URL_LENGTH];
584     WCHAR ret_urlW[INTERNET_MAX_URL_LENGTH];
585     WCHAR *urlW, *expected_urlW; 
586     DWORD dwEscaped;
587     size_t i;
588     static char inplace[] = "file:///C:/Program%20Files";
589     static WCHAR inplaceW[] = {'f','i','l','e',':','/','/','/','C',':','/',
590                                'P','r','o','g','r','a','m','%','2','0','F','i','l','e','s',0};
591
592     for(i=0; i<sizeof(TEST_URL_UNESCAPE)/sizeof(TEST_URL_UNESCAPE[0]); i++) { 
593         dwEscaped=INTERNET_MAX_URL_LENGTH;
594         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);
595         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);
596
597         dwEscaped = INTERNET_MAX_URL_LENGTH;
598         urlW = GetWideString(TEST_URL_UNESCAPE[i].url);
599         expected_urlW = GetWideString(TEST_URL_UNESCAPE[i].expect);
600         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);
601         WideCharToMultiByte(CP_ACP,0,ret_urlW,-1,szReturnUrl,INTERNET_MAX_URL_LENGTH,0,0);
602         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);
603         FreeWideString(urlW);
604         FreeWideString(expected_urlW);
605     }
606
607     dwEscaped = sizeof(inplace);
608     ok(UrlUnescapeA(inplace, NULL, &dwEscaped, URL_UNESCAPE_INPLACE) == S_OK, "UrlUnescapeA failed unexpectedly\n");
609
610     dwEscaped = sizeof(inplaceW);
611     ok(UrlUnescapeW(inplaceW, NULL, &dwEscaped, URL_UNESCAPE_INPLACE) == S_OK, "UrlUnescapeW failed unexpectedly\n");
612 }
613
614 static void test_PathSearchAndQualify(void)
615 {
616     WCHAR path1[] = {'c',':','\\','f','o','o',0};
617     WCHAR expect1[] = {'c',':','\\','f','o','o',0};
618     WCHAR path2[] = {'c',':','f','o','o',0};
619     WCHAR c_drive[] = {'c',':',0}; 
620     WCHAR foo[] = {'f','o','o',0}; 
621     WCHAR path3[] = {'\\','f','o','o',0};
622     WCHAR winini[] = {'w','i','n','.','i','n','i',0};
623     WCHAR out[MAX_PATH];
624     WCHAR cur_dir[MAX_PATH];
625     WCHAR dot[] = {'.',0};
626
627     /* c:\foo */
628     ok(PathSearchAndQualifyW(path1, out, MAX_PATH) != 0,
629        "PathSearchAndQualify rets 0\n");
630     ok(!lstrcmpiW(out, expect1), "strings don't match\n");
631
632     /* c:foo */
633     ok(PathSearchAndQualifyW(path2, out, MAX_PATH) != 0,
634        "PathSearchAndQualify rets 0\n");
635     GetFullPathNameW(c_drive, MAX_PATH, cur_dir, NULL);
636     PathAddBackslashW(cur_dir);
637     lstrcatW(cur_dir, foo);
638     ok(!lstrcmpiW(out, cur_dir), "strings don't match\n");    
639
640     /* foo */
641     ok(PathSearchAndQualifyW(foo, out, MAX_PATH) != 0,
642        "PathSearchAndQualify rets 0\n");
643     GetFullPathNameW(dot, MAX_PATH, cur_dir, NULL);
644     PathAddBackslashW(cur_dir);
645     lstrcatW(cur_dir, foo);
646     ok(!lstrcmpiW(out, cur_dir), "strings don't match\n");    
647
648     /* \foo */
649     ok(PathSearchAndQualifyW(path3, out, MAX_PATH) != 0,
650        "PathSearchAndQualify rets 0\n");
651     GetFullPathNameW(dot, MAX_PATH, cur_dir, NULL);
652     lstrcpyW(cur_dir + 2, path3);
653     ok(!lstrcmpiW(out, cur_dir), "strings don't match\n");
654
655     /* win.ini */
656     ok(PathSearchAndQualifyW(winini, out, MAX_PATH) != 0,
657        "PathSearchAndQualify rets 0\n");
658     if(!SearchPathW(NULL, winini, NULL, MAX_PATH, cur_dir, NULL))
659         GetFullPathNameW(winini, MAX_PATH, cur_dir, NULL);
660     ok(!lstrcmpiW(out, cur_dir), "strings don't match\n");
661
662 }
663
664 static void test_PathCreateFromUrl(void)
665 {
666     size_t i;
667     char ret_path[INTERNET_MAX_URL_LENGTH];
668     DWORD len, ret;
669     WCHAR ret_pathW[INTERNET_MAX_URL_LENGTH];
670     WCHAR *pathW, *urlW;
671
672     for(i = 0; i < sizeof(TEST_PATHFROMURL) / sizeof(TEST_PATHFROMURL[0]); i++) {
673         len = INTERNET_MAX_URL_LENGTH;
674         ret = PathCreateFromUrlA(TEST_PATHFROMURL[i].url, ret_path, &len, 0);
675         ok(ret == TEST_PATHFROMURL[i].ret, "ret %08lx from url %s\n", ret, TEST_PATHFROMURL[i].url);
676         if(TEST_PATHFROMURL[i].path) {
677            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);
678            ok(len == strlen(ret_path), "ret len %ld from url %s\n", len, TEST_PATHFROMURL[i].url);
679         }
680         len = INTERNET_MAX_URL_LENGTH;
681         pathW = GetWideString(TEST_PATHFROMURL[i].path);
682         urlW = GetWideString(TEST_PATHFROMURL[i].url);
683         ret = PathCreateFromUrlW(urlW, ret_pathW, &len, 0);
684         WideCharToMultiByte(CP_ACP, 0, ret_pathW, -1, ret_path, sizeof(ret_path),0,0);
685         ok(ret == TEST_PATHFROMURL[i].ret, "ret %08lx from url L\"%s\"\n", ret, TEST_PATHFROMURL[i].url);
686         if(TEST_PATHFROMURL[i].path) {
687             ok(!lstrcmpiW(ret_pathW, pathW), "got %s expected %s from url L\"%s\"\n", ret_path, TEST_PATHFROMURL[i].path, TEST_PATHFROMURL[i].url);
688             ok(len == lstrlenW(ret_pathW), "ret len %ld from url L\"%s\"\n", len, TEST_PATHFROMURL[i].url);
689         }
690         FreeWideString(urlW);
691         FreeWideString(pathW);
692     }
693 }
694
695
696 static void test_PathIsUrl(void)
697 {
698     size_t i;
699     BOOL ret;
700
701     for(i = 0; i < sizeof(TEST_PATH_IS_URL)/sizeof(TEST_PATH_IS_URL[0]); i++) {
702         ret = PathIsURLA(TEST_PATH_IS_URL[i].path);
703         ok(ret == TEST_PATH_IS_URL[i].expect,
704            "returned %d from path %s, expected %d\n", ret, TEST_PATH_IS_URL[i].path,
705            TEST_PATH_IS_URL[i].expect);
706     }
707 }
708
709 static const DWORD SHELL_charclass[] =
710 {
711     0x00000000, 0x00000000, 0x00000000, 0x00000000,
712     0x00000000, 0x00000000, 0x00000000, 0x00000000,
713     0x00000000, 0x00000000, 0x00000000, 0x00000000,
714     0x00000000, 0x00000000, 0x00000000, 0x00000000,
715     0x00000000, 0x00000000, 0x00000000, 0x00000000,
716     0x00000000, 0x00000000, 0x00000000, 0x00000000,
717     0x00000000, 0x00000000, 0x00000000, 0x00000000,
718     0x00000000, 0x00000000, 0x00000000, 0x00000000,
719     0x00000080, 0x00000100, 0x00000200, 0x00000100,
720     0x00000100, 0x00000100, 0x00000100, 0x00000100,
721     0x00000100, 0x00000100, 0x00000002, 0x00000100,
722     0x00000040, 0x00000100, 0x00000004, 0x00000000,
723     0x00000100, 0x00000100, 0x00000100, 0x00000100,
724     0x00000100, 0x00000100, 0x00000100, 0x00000100,
725     0x00000100, 0x00000100, 0x00000010, 0x00000020,
726     0x00000000, 0x00000100, 0x00000000, 0x00000001,
727     0x00000100, 0xffffffff, 0xffffffff, 0xffffffff,
728     0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
729     0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
730     0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
731     0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
732     0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
733     0xffffffff, 0xffffffff, 0xffffffff, 0x00000100,
734     0x00000008, 0x00000100, 0x00000100, 0x00000100,
735     0x00000100, 0xffffffff, 0xffffffff, 0xffffffff,
736     0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
737     0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
738     0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
739     0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
740     0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
741     0xffffffff, 0xffffffff, 0xffffffff, 0x00000100,
742     0x00000000, 0x00000100, 0x00000100
743 };
744
745 static void test_PathIsValidCharA(void)
746 {
747     BOOL ret;
748     unsigned int c;
749
750     ret = pPathIsValidCharA( 0x7f, 0 );
751     ok ( !ret, "PathIsValidCharA succeeded: 0x%08lx\n", (DWORD)ret );
752
753     ret = pPathIsValidCharA( 0x7f, 1 );
754     ok ( !ret, "PathIsValidCharA succeeded: 0x%08lx\n", (DWORD)ret );
755
756     for (c = 0; c < 0x7f; c++)
757     {
758         ret = pPathIsValidCharA( c, ~0U );
759         ok ( ret == SHELL_charclass[c] || (ret == 1 && SHELL_charclass[c] == 0xffffffff),
760              "PathIsValidCharA failed: 0x%02x got 0x%08lx expected 0x%08lx\n",
761              c, (DWORD)ret, SHELL_charclass[c] );
762     }
763
764     for (c = 0x7f; c <= 0xff; c++)
765     {
766         ret = pPathIsValidCharA( c, ~0U );
767         ok ( ret == 0x00000100,
768              "PathIsValidCharA failed: 0x%02x got 0x%08lx expected 0x00000100\n",
769              c, (DWORD)ret );
770     }
771 }
772
773 static void test_PathIsValidCharW(void)
774 {
775     BOOL ret;
776     unsigned int c, err_count = 0;
777
778     ret = pPathIsValidCharW( 0x7f, 0 );
779     ok ( !ret, "PathIsValidCharW succeeded: 0x%08lx\n", (DWORD)ret );
780
781     ret = pPathIsValidCharW( 0x7f, 1 );
782     ok ( !ret, "PathIsValidCharW succeeded: 0x%08lx\n", (DWORD)ret );
783
784     for (c = 0; c < 0x7f; c++)
785     {
786         ret = pPathIsValidCharW( c, ~0U );
787         ok ( ret == SHELL_charclass[c] || (ret == 1 && SHELL_charclass[c] == 0xffffffff),
788              "PathIsValidCharW failed: 0x%02x got 0x%08lx expected 0x%08lx\n",
789              c, (DWORD)ret, SHELL_charclass[c] );
790     }
791
792     for (c = 0x007f; c <= 0xffff; c++)
793     {
794         ret = pPathIsValidCharW( c, ~0U );
795         ok ( ret == 0x00000100,
796              "PathIsValidCharW failed: 0x%02x got 0x%08lx expected 0x00000100\n",
797              c, (DWORD)ret );
798         if (ret != 0x00000100)
799         {
800             if(++err_count > 100 ) {
801                 trace("skipping rest of PathIsValidCharW tests "
802                       "because of the current number of errors\n");
803                 break;
804             }
805         }
806     }
807 }
808
809 static void test_PathMakePretty(void)
810 {
811    char buff[MAX_PATH];
812
813    ok (PathMakePrettyA(NULL) == FALSE, "PathMakePretty: NULL path succeeded\n");
814    buff[0] = '\0';
815    ok (PathMakePrettyA(buff) == TRUE, "PathMakePretty: Empty path failed\n");
816
817    strcpy(buff, "C:\\A LONG FILE NAME WITH \\SPACES.TXT");
818    ok (PathMakePrettyA(buff) == TRUE, "PathMakePretty: Long UC name failed\n");
819    ok (strcmp(buff, "C:\\a long file name with \\spaces.txt") == 0,
820        "PathMakePretty: Long UC name not changed\n");
821
822    strcpy(buff, "C:\\A LONG FILE NAME WITH \\MixedCase.TXT");
823    ok (PathMakePrettyA(buff) == FALSE, "PathMakePretty: Long MC name succeeded\n");
824    ok (strcmp(buff, "C:\\A LONG FILE NAME WITH \\MixedCase.TXT") == 0,
825        "PathMakePretty: Failed but modified path\n");
826
827    strcpy(buff, "TEST");
828    ok (PathMakePrettyA(buff) == TRUE,  "PathMakePretty: Short name failed\n");
829    ok (strcmp(buff, "Test") == 0,  "PathMakePretty: 1st char lowercased %s\n", buff);
830 }
831
832 static void test_PathMatchSpec(void)
833 {
834     static const char file[] = "c:\\foo\\bar\\filename.ext";
835     static const char spec1[] = ".ext";
836     static const char spec2[] = "*.ext";
837     static const char spec3[] = "*.ext ";
838     static const char spec4[] = "  *.ext";
839     static const char spec5[] = "* .ext";
840     static const char spec6[] = "*. ext";
841     static const char spec7[] = "* . ext";
842     static const char spec8[] = "*.e?t";
843     static const char spec9[] = "filename.ext";
844     static const char spec10[] = "*bar\\filename.ext";
845     static const char spec11[] = " foo; *.ext";
846     static const char spec12[] = "*.ext;*.bar";
847     static const char spec13[] = "*bar*";
848
849     ok (PathMatchSpecA(file, spec1) == FALSE, "PathMatchSpec: Spec1 failed\n");
850     ok (PathMatchSpecA(file, spec2) == TRUE, "PathMatchSpec: Spec2 failed\n");
851     ok (PathMatchSpecA(file, spec3) == FALSE, "PathMatchSpec: Spec3 failed\n");
852     ok (PathMatchSpecA(file, spec4) == TRUE, "PathMatchSpec: Spec4 failed\n");
853     todo_wine ok (PathMatchSpecA(file, spec5) == TRUE, "PathMatchSpec: Spec5 failed\n");
854     todo_wine ok (PathMatchSpecA(file, spec6) == TRUE, "PathMatchSpec: Spec6 failed\n");
855     ok (PathMatchSpecA(file, spec7) == FALSE, "PathMatchSpec: Spec7 failed\n");
856     ok (PathMatchSpecA(file, spec8) == TRUE, "PathMatchSpec: Spec8 failed\n");
857     ok (PathMatchSpecA(file, spec9) == FALSE, "PathMatchSpec: Spec9 failed\n");
858     ok (PathMatchSpecA(file, spec10) == TRUE, "PathMatchSpec: Spec10 failed\n");
859     ok (PathMatchSpecA(file, spec11) == TRUE, "PathMatchSpec: Spec11 failed\n");
860     ok (PathMatchSpecA(file, spec12) == TRUE, "PathMatchSpec: Spec12 failed\n");
861     ok (PathMatchSpecA(file, spec13) == TRUE, "PathMatchSpec: Spec13 failed\n");
862 }
863
864 static void test_PathCombineW(void)
865 {
866     LPWSTR wszString, wszString2;
867    
868     wszString2 = HeapAlloc(GetProcessHeap(), 0, MAX_PATH * sizeof(WCHAR));
869
870     /* NULL test */
871     wszString = pPathCombineW(NULL, NULL, NULL);
872     ok (wszString == NULL, "Expected a NULL return\n");
873
874     /* Some NULL */
875     wszString = pPathCombineW(wszString2, NULL, NULL);
876     ok (wszString == NULL, "Expected a NULL return\n");
877  
878     HeapFree(GetProcessHeap(), 0, wszString2);
879 }
880
881 #define LONG_LEN (MAX_PATH * 2)
882 #define HALF_LEN (MAX_PATH / 2 + 1)
883
884 static void test_PathCombineA(void)
885 {
886     LPSTR str;
887     char dest[MAX_PATH];
888     char too_long[LONG_LEN];
889     char one[HALF_LEN], two[HALF_LEN];
890
891     /* try NULL dest */
892     SetLastError(0xdeadbeef);
893     str = PathCombineA(NULL, "C:\\", "one\\two\\three");
894     ok(str == NULL, "Expected NULL, got %p\n", str);
895     ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
896
897     /* try NULL dest and NULL directory */
898     SetLastError(0xdeadbeef);
899     str = PathCombineA(NULL, NULL, "one\\two\\three");
900     ok(str == NULL, "Expected NULL, got %p\n", str);
901     ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
902
903     /* try all NULL*/
904     SetLastError(0xdeadbeef);
905     str = PathCombineA(NULL, NULL, NULL);
906     ok(str == NULL, "Expected NULL, got %p\n", str);
907     ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
908
909     /* try NULL file part */
910     SetLastError(0xdeadbeef);
911     lstrcpyA(dest, "control");
912     str = PathCombineA(dest, "C:\\", NULL);
913     ok(str == dest, "Expected str == dest, got %p\n", str);
914     ok(!lstrcmp(str, "C:\\"), "Expected C:\\, got %s\n", str);
915     ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
916
917     /* try empty file part */
918     SetLastError(0xdeadbeef);
919     lstrcpyA(dest, "control");
920     str = PathCombineA(dest, "C:\\", "");
921     ok(str == dest, "Expected str == dest, got %p\n", str);
922     ok(!lstrcmp(str, "C:\\"), "Expected C:\\, got %s\n", str);
923     ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
924
925     /* try empty directory and file part */
926     SetLastError(0xdeadbeef);
927     lstrcpyA(dest, "control");
928     str = PathCombineA(dest, "", "");
929     ok(str == dest, "Expected str == dest, got %p\n", str);
930     ok(!lstrcmp(str, "\\"), "Expected \\, got %s\n", str);
931     ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
932
933     /* try NULL directory */
934     SetLastError(0xdeadbeef);
935     lstrcpyA(dest, "control");
936     str = PathCombineA(dest, NULL, "one\\two\\three");
937     ok(str == dest, "Expected str == dest, got %p\n", str);
938     ok(!lstrcmp(str, "one\\two\\three"), "Expected one\\two\\three, got %s\n", str);
939     ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
940
941     /* try NULL directory and empty file part */
942     SetLastError(0xdeadbeef);
943     lstrcpyA(dest, "control");
944     str = PathCombineA(dest, NULL, "");
945     ok(str == dest, "Expected str == dest, got %p\n", str);
946     ok(!lstrcmp(str, "\\"), "Expected \\, got %s\n", str);
947     ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
948
949     /* try NULL directory and file part */
950     SetLastError(0xdeadbeef);
951     lstrcpyA(dest, "control");
952     str = PathCombineA(dest, NULL, NULL);
953     ok(str == NULL, "Expected str == NULL, got %p\n", str);
954     todo_wine
955     {
956         ok(lstrlenA(dest) == 0, "Expected 0 length, got %i\n", lstrlenA(dest));
957     }
958     ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
959
960     /* try directory without backslash */
961     SetLastError(0xdeadbeef);
962     lstrcpyA(dest, "control");
963     str = PathCombineA(dest, "C:", "one\\two\\three");
964     ok(str == dest, "Expected str == dest, got %p\n", str);
965     ok(!lstrcmp(str, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", str);
966     ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
967
968     /* try directory with backslash */
969     SetLastError(0xdeadbeef);
970     lstrcpyA(dest, "control");
971     str = PathCombineA(dest, "C:\\", "one\\two\\three");
972     ok(str == dest, "Expected str == dest, got %p\n", str);
973     ok(!lstrcmp(str, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", str);
974     ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
975
976     /* try directory with backslash and file with prepended backslash */
977     SetLastError(0xdeadbeef);
978     lstrcpyA(dest, "control");
979     str = PathCombineA(dest, "C:\\", "\\one\\two\\three");
980     ok(str == dest, "Expected str == dest, got %p\n", str);
981     ok(!lstrcmp(str, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", str);
982     ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
983
984     /* try previous test, with backslash appended as well */
985     SetLastError(0xdeadbeef);
986     lstrcpyA(dest, "control");
987     str = PathCombineA(dest, "C:\\", "\\one\\two\\three\\");
988     ok(str == dest, "Expected str == dest, got %p\n", str);
989     ok(!lstrcmp(str, "C:\\one\\two\\three\\"), "Expected C:\\one\\two\\three\\, got %s\n", str);
990     ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
991
992     /* try a relative directory */
993     SetLastError(0xdeadbeef);
994     lstrcpyA(dest, "control");
995     str = PathCombineA(dest, "relative\\dir", "\\one\\two\\three\\");
996     ok(str == dest, "Expected str == dest, got %p\n", str);
997     ok(!lstrcmp(str, "one\\two\\three\\"), "Expected one\\two\\three\\, got %s\n", str);
998     ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
999
1000     /* try forward slashes */
1001     SetLastError(0xdeadbeef);
1002     lstrcpyA(dest, "control");
1003     str = PathCombineA(dest, "C:\\", "one/two/three\\");
1004     ok(str == dest, "Expected str == dest, got %p\n", str);
1005     ok(!lstrcmp(str, "C:\\one/two/three\\"), "Expected one/two/three\\, got %s\n", str);
1006     ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
1007
1008     /* try a really weird directory */
1009     SetLastError(0xdeadbeef);
1010     lstrcpyA(dest, "control");
1011     str = PathCombineA(dest, "C:\\/\\/", "\\one\\two\\three\\");
1012     ok(str == dest, "Expected str == dest, got %p\n", str);
1013     ok(!lstrcmp(str, "C:\\one\\two\\three\\"), "Expected C:\\one\\two\\three\\, got %s\n", str);
1014     ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
1015
1016     /* try periods */
1017     SetLastError(0xdeadbeef);
1018     lstrcpyA(dest, "control");
1019     str = PathCombineA(dest, "C:\\", "one\\..\\two\\.\\three");
1020     ok(str == dest, "Expected str == dest, got %p\n", str);
1021     ok(!lstrcmp(str, "C:\\two\\three"), "Expected C:\\two\\three, got %s\n", str);
1022     ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
1023
1024     /* try .. as file */
1025     /* try forward slashes */
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 %ld\n", GetLastError());
1032
1033     memset(too_long, 'a', LONG_LEN);
1034     too_long[LONG_LEN - 1] = '\0';
1035
1036     /* try a file longer than MAX_PATH */
1037     SetLastError(0xdeadbeef);
1038     lstrcpyA(dest, "control");
1039     str = PathCombineA(dest, "C:\\", too_long);
1040     todo_wine
1041     {
1042         ok(str == NULL, "Expected str == NULL, got %p\n", str);
1043         ok(lstrlenA(dest) == 0, "Expected 0 length, got %i\n", lstrlenA(dest));
1044         ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
1045     }
1046
1047     /* try a directory longer than MAX_PATH */
1048     SetLastError(0xdeadbeef);
1049     lstrcpyA(dest, "control");
1050     str = PathCombineA(dest, too_long, "one\\two\\three");
1051     todo_wine
1052     {
1053         ok(str == NULL, "Expected str == NULL, got %p\n", str);
1054         ok(lstrlenA(dest) == 0, "Expected 0 length, got %i\n", lstrlenA(dest));
1055         ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
1056     }
1057
1058     memset(one, 'b', HALF_LEN);
1059     memset(two, 'c', HALF_LEN);
1060     one[HALF_LEN - 1] = '\0';
1061     two[HALF_LEN - 1] = '\0';
1062
1063     /* destination string is longer than MAX_PATH, but not the constituent parts */
1064     SetLastError(0xdeadbeef);
1065     lstrcpyA(dest, "control");
1066     str = PathCombineA(dest, one, two);
1067     todo_wine
1068     {
1069         ok(str == NULL, "Expected str == NULL, got %p\n", str);
1070         ok(lstrlenA(dest) == 0, "Expected 0 length, got %i\n", lstrlenA(dest));
1071     }
1072     ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
1073 }
1074
1075 static void test_PathAddBackslash(void)
1076 {
1077     LPSTR str;
1078     char path[MAX_PATH];
1079     char too_long[LONG_LEN];
1080
1081     /* try a NULL path */
1082     SetLastError(0xdeadbeef);
1083     str = PathAddBackslashA(NULL);
1084     ok(str == NULL, "Expected str == NULL, got %p\n", str);
1085     ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
1086
1087     /* try an empty path */
1088     path[0] = '\0';
1089     SetLastError(0xdeadbeef);
1090     str = PathAddBackslashA(path);
1091     ok(str == (path + lstrlenA(path)), "Expected str to point to end of path, got %p\n", str);
1092     ok(lstrlenA(path) == 0, "Expected empty string, got %i\n", lstrlenA(path));
1093     ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
1094
1095     /* try a relative path */
1096     lstrcpyA(path, "one\\two");
1097     SetLastError(0xdeadbeef);
1098     str = PathAddBackslashA(path);
1099     ok(str == (path + lstrlenA(path)), "Expected str to point to end of path, got %p\n", str);
1100     ok(!lstrcmp(path, "one\\two\\"), "Expected one\\two\\, got %s\n", path);
1101     ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
1102
1103     /* try periods */
1104     lstrcpyA(path, "one\\..\\two");
1105     SetLastError(0xdeadbeef);
1106     str = PathAddBackslashA(path);
1107     ok(str == (path + lstrlenA(path)), "Expected str to point to end of path, got %p\n", str);
1108     ok(!lstrcmp(path, "one\\..\\two\\"), "Expected one\\..\\two\\, got %s\n", path);
1109     ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
1110
1111     /* try just a space */
1112     lstrcpyA(path, " ");
1113     SetLastError(0xdeadbeef);
1114     str = PathAddBackslashA(path);
1115     ok(str == (path + lstrlenA(path)), "Expected str to point to end of path, got %p\n", str);
1116     ok(!lstrcmp(path, " \\"), "Expected  \\, got %s\n", path);
1117     ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
1118
1119     /* path already has backslash */
1120     lstrcpyA(path, "C:\\one\\");
1121     SetLastError(0xdeadbeef);
1122     str = PathAddBackslashA(path);
1123     ok(str == (path + lstrlenA(path)), "Expected str to point to end of path, got %p\n", str);
1124     ok(!lstrcmp(path, "C:\\one\\"), "Expected C:\\one\\, got %s\n", path);
1125     ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
1126
1127     memset(too_long, 'a', LONG_LEN);
1128     too_long[LONG_LEN - 1] = '\0';
1129
1130     /* path is longer than MAX_PATH */
1131     SetLastError(0xdeadbeef);
1132     str = PathAddBackslashA(too_long);
1133     ok(str == NULL, "Expected str == NULL, got %p\n", str);
1134     ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
1135 }
1136
1137 START_TEST(path)
1138 {
1139   hShlwapi = LoadLibraryA("shlwapi.dll");
1140   if (!hShlwapi) return;
1141
1142   test_UrlHash();
1143   test_UrlGetPart();
1144   test_UrlCanonicalize();
1145   test_UrlEscape();
1146   test_UrlCombine();
1147   test_UrlCreateFromPath();
1148   test_UrlIs();
1149   test_UrlUnescape();
1150
1151   test_PathSearchAndQualify();
1152   test_PathCreateFromUrl();
1153   test_PathIsUrl();
1154
1155   test_PathAddBackslash();
1156   test_PathMakePretty();
1157   test_PathMatchSpec();
1158
1159   /* For whatever reason, PathIsValidCharA and PathAppendA share the same
1160    * ordinal number in some native versions. Check this to prevent a crash.
1161    */
1162   pPathIsValidCharA = (void*)GetProcAddress(hShlwapi, (LPSTR)455);
1163   if (pPathIsValidCharA && pPathIsValidCharA != (void*)GetProcAddress(hShlwapi, "PathAppendA"))
1164   {
1165     test_PathIsValidCharA();
1166
1167      pPathIsValidCharW = (void*)GetProcAddress(hShlwapi, (LPSTR)456);
1168      if (pPathIsValidCharW) test_PathIsValidCharW();
1169   }
1170
1171   pPathCombineW = (void*)GetProcAddress(hShlwapi, "PathCombineW");
1172   if (pPathCombineW)
1173     test_PathCombineW();
1174
1175   test_PathCombineA();
1176 }