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