Added regedit unit test, a couple minor changes to regedit.
[wine] / dlls / kernel / tests / path.c
1 /*
2  * Unit test suite for Get*PathNamesA and (Get|Set)CurrentDirectoryA.
3  *
4  * Copyright 2002 Geoffrey Hausheer
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include <stdio.h>
22 #include "wine/test.h"
23 #include "winbase.h"
24 #include "winuser.h"
25 #include "winerror.h"
26
27 #define WIN2K_PLUS(version) (version.dwMajorVersion==5)
28 #define WIN98_PLUS(version) (version.dwMajorVersion==4 && \
29                              version.dwMinorVersion>0)
30 #define HAS_TRAIL_SLASH_A(string) (string[lstrlenA(string)-1]=='\\')
31
32 #define LONGFILE "Long File test.path"
33 #define SHORTFILE "pathtest.pth"
34 #define SHORTDIR "shortdir"
35 #define LONGDIR "Long Directory"
36 #define NONFILE_SHORT "noexist.pth"
37 #define NONFILE_LONG "Non Existant File"
38 #define NONDIR_SHORT "notadir"
39 #define NONDIR_LONG "Non Existant Directory"
40
41 static OSVERSIONINFOA version;
42 /* the following characters don't work well with GetFullPathNameA
43    in Win98.  I don't know if this is a FAT thing, or if it is an OS thing
44    but I don't test these characters now.
45    NOTE: Win2k allows GetFullPathNameA to work with them though
46       |<>
47 */
48 static const CHAR funny_chars[]="!@#$%^&*()=+{}[],?'`\"";
49 static const CHAR is_char_ok[] ="111111101111111110110";
50 static const CHAR wine_todo[]  ="111111101100110000110";
51
52 static DWORD (WINAPI *pGetLongPathNameA)(LPCSTR,LPSTR,DWORD);
53
54 /* a structure to deal with wine todos somewhat cleanly */
55 typedef struct {
56   DWORD shortlen;
57   DWORD shorterror;
58   DWORD s2llen;
59   DWORD s2lerror;
60   DWORD longlen;
61   DWORD longerror;
62 } SLpassfail;
63
64 /* function that tests GetFullPathNameA, GetShortPathNameA,GetLongPathNameA */
65 /* NOTE: the passfail structure is used to allow cutomizeable todo checking
66          for wine.  It is not very pretty, but it sure beats duplicating this
67          function lots of times
68 */
69 static void test_ValidPathA(CHAR *curdir, CHAR *subdir, CHAR *filename,
70                          CHAR *shortstr, SLpassfail *passfail, CHAR *errstr) {
71   CHAR tmpstr[MAX_PATH],
72        fullpath[MAX_PATH],      /*full path to the file (not short/long) */
73        subpath[MAX_PATH],       /*relative path to the file */
74        fullpathshort[MAX_PATH], /*absolue path to the file (short format) */
75        fullpathlong[MAX_PATH],  /*absolute path to the file (long format) */
76        curdirshort[MAX_PATH],   /*absolute path to the current dir (short) */
77        curdirlong[MAX_PATH];    /*absolute path to the current dir (long) */
78   LPSTR strptr;                 /*ptr to the filename portion of the path */
79   DWORD len;
80 /* if passfail is NULL, we can perform all checks within this function,
81    otherwise, we will return the relevant data in the passfail struct, so
82    we must initialize it first
83 */
84   if(passfail!=NULL) {
85     passfail->shortlen=-1;passfail->s2llen=-1;passfail->longlen=-1;
86     passfail->shorterror=0;passfail->s2lerror=0;passfail->longerror=0;
87   }
88 /* GetLongPathNameA is only supported on Win2k+ and Win98+ */
89   if(pGetLongPathNameA) {
90     ok((len=pGetLongPathNameA(curdir,curdirlong,MAX_PATH)),
91        "%s: GetLongPathNameA failed",errstr);
92 /*GetLongPathNameA can return a trailing '\\' but shouldn't do so here */
93     ok(! HAS_TRAIL_SLASH_A(curdirlong),
94        "%s: GetLongPathNameA should not have a trailing \\",errstr);
95   }
96   ok((len=GetShortPathNameA(curdir,curdirshort,MAX_PATH)),
97      "%s: GetShortPathNameA failed",errstr);
98 /*GetShortPathNameA can return a trailing '\\' but shouldn't do so here */
99   ok(! HAS_TRAIL_SLASH_A(curdirshort),
100      "%s: GetShortPathNameA should not have a trailing \\",errstr);
101 /* build relative and absolute paths from inputs */
102   if(lstrlenA(subdir)) {
103     sprintf(subpath,"%s\\%s",subdir,filename);
104   } else {
105     lstrcpyA(subpath,filename);
106   }
107   sprintf(fullpath,"%s\\%s",curdir,subpath);
108   sprintf(fullpathshort,"%s\\%s",curdirshort,subpath);
109   sprintf(fullpathlong,"%s\\%s",curdirlong,subpath);
110 /* Test GetFullPathNameA functionality */
111   len=GetFullPathNameA(subpath,MAX_PATH,tmpstr,&strptr);
112   ok(len, "GetFullPathNameA failed for: '%s'",subpath);
113   if(HAS_TRAIL_SLASH_A(subpath)) {
114 /* Wine strips off the trailing '\\'. Neither Win98 nor Win2k do this. */
115     todo_wine {
116       ok(strptr==NULL,
117          "%s: GetFullPathNameA should not return a filename ptr",errstr);
118       ok(lstrcmpiA(fullpath,tmpstr)==0,
119          "%s: GetFullPathNameA returned '%s' instead of '%s'",
120          errstr,tmpstr,fullpath);
121     }
122   } else {
123     ok(lstrcmpiA(strptr,filename)==0,
124        "%s: GetFullPathNameA returned '%s' instead of '%s'",
125        errstr,strptr,filename);
126     ok(lstrcmpiA(fullpath,tmpstr)==0,
127        "%s: GetFullPathNameA returned '%s' instead of '%s'",
128        errstr,tmpstr,fullpath);
129   }
130 /* Test GetShortPathNameA functionality */
131   SetLastError(0);
132   len=GetShortPathNameA(fullpathshort,shortstr,MAX_PATH);
133   if(passfail==NULL) {
134     ok(len, "%s: GetShortPathNameA failed",errstr);
135   } else {
136     passfail->shortlen=len;
137     passfail->shorterror=GetLastError();
138   }
139 /* Test GetLongPathNameA functionality
140    We test both conversion from GetFullPathNameA and from GetShortPathNameA
141 */
142   if(pGetLongPathNameA) {
143     if(len==0) {
144       SetLastError(0);
145       len=pGetLongPathNameA(shortstr,tmpstr,MAX_PATH);
146       if(passfail==NULL) {
147         ok(len,
148           "%s: GetLongPathNameA failed during Short->Long conversion", errstr);
149         ok(lstrcmpiA(fullpathlong,tmpstr)==0,
150            "%s: GetLongPathNameA returned '%s' instead of '%s'",
151            errstr,tmpstr,fullpathlong);
152       } else {
153         passfail->s2llen=len;
154         passfail->s2lerror=GetLastError();
155       }
156     }
157     SetLastError(0);
158     len=pGetLongPathNameA(fullpath,tmpstr,MAX_PATH);
159     if(passfail==NULL) {
160       ok(len, "%s: GetLongPathNameA failed",errstr);
161       if(HAS_TRAIL_SLASH_A(fullpath)) {
162 /* Wine strips off the trailing '\\'  Neither Win98 nor Win2k do this */
163         todo_wine {
164           ok(lstrcmpiA(fullpathlong,tmpstr)==0,
165            "%s: GetLongPathNameA returned '%s' instead of '%s'",
166            errstr,tmpstr,fullpathlong);
167         }
168       } else {
169         ok(lstrcmpiA(fullpathlong,tmpstr)==0,
170           "%s: GetLongPathNameA returned '%s' instead of '%s'",
171           errstr,tmpstr,fullpathlong);
172       }
173     } else {
174       passfail->longlen=len;
175       passfail->longerror=GetLastError();
176     }
177   }
178 }
179
180 /* split path into leading directory, and 8.3 filename */
181 static void test_SplitShortPathA(CHAR *path,CHAR *dir,CHAR *eight,CHAR *three) {
182   DWORD len,done,error;
183   DWORD ext,fil;
184   INT i;
185   len=lstrlenA(path);
186   ext=len; fil=len; done=0; error=0;
187 /* walk backwards over path looking for '.' or '\\' seperators */
188   for(i=len-1;(i>=0) && (!done);i--) {
189     if(path[i]=='.')
190       if(ext!=len) error=1; else ext=i;
191     else if(path[i]=='\\') {
192       if(i==len-1) {
193         error=1;
194       } else {
195         fil=i;
196         done=1;
197       }
198     }
199   }
200 /* Check that we didn't find a trailing '\\' or multiple '.' */
201   ok(!error,"Illegal file found in 8.3 path '%s'",path);
202 /* Seperate dir, root, and extension */
203   if(ext!=len) lstrcpyA(three,path+ext+1); else lstrcpyA(three,"");
204   if(fil!=len) {
205     lstrcpynA(eight,path+fil+1,ext-fil);
206     lstrcpynA(dir,path,fil+1);
207   } else {
208     lstrcpynA(eight,path,ext+1);
209     lstrcpyA(dir,"");
210   }
211 /* Validate that root and extension really are 8.3 */
212   ok(lstrlenA(eight)<=8 && lstrlenA(three)<=3,
213      "GetShortPathNAmeA did not return an 8.3 path");
214 }
215
216 /* Check that GetShortPathNameA returns a valid 8.3 path */
217 static void test_LongtoShortA(CHAR *teststr,CHAR *goodstr,
218                               CHAR *ext,CHAR *errstr) {
219   CHAR dir[MAX_PATH],eight[MAX_PATH],three[MAX_PATH];
220
221   test_SplitShortPathA(teststr,dir,eight,three);
222   ok(lstrcmpiA(dir,goodstr)==0,
223      "GetShortPathNameA returned '%s' instead of '%s'",dir,goodstr);
224   ok(lstrcmpiA(three,ext)==0,
225      "GetShortPathNameA returned '%s' with incorrect extension",three);
226 }
227
228 /* Test that Get(Short|Long|Full)PathNameA work correctly with interesting
229    characters in the filename.
230      'valid' indicates whether this would be an allowed filename
231      'todo' indictaes that wine doesn't get this right yet.
232    NOTE: We always call this routine with a non-existant filename, so
233          Get(Short|Long)PathNameA should never pass, but GetFullPathNameA
234          should.
235 */
236 static void test_FunnyChars(CHAR *curdir,CHAR *filename,
237                              INT valid,INT todo,CHAR *errstr) {
238   CHAR tmpstr[MAX_PATH];
239   SLpassfail passfail;
240
241   test_ValidPathA(curdir,"",filename,tmpstr,&passfail,errstr);
242   if(todo) {
243     todo_wine {
244       ok(passfail.shortlen==0,
245          "%s: GetShortPathNameA passed when it shouldn't have",errstr);
246     }
247   } else {
248     ok(passfail.shortlen==0,
249        "%s: GetShortPathNameA passed when it shouldn't have",errstr);
250   }
251   if(valid) {
252     if(todo) {
253       todo_wine {
254         ok(passfail.shorterror==ERROR_FILE_NOT_FOUND,
255            "%s: GetShortPathA returned %d and not %d",
256            errstr,passfail.shorterror,ERROR_FILE_NOT_FOUND);
257       }
258     } else {
259       ok(passfail.shorterror==ERROR_FILE_NOT_FOUND,
260          "%s: GetShortPathA returned %d and not %d",
261           errstr,passfail.shorterror,ERROR_FILE_NOT_FOUND);
262     }
263   } else {
264     if(todo) {
265       todo_wine {
266 /* Win2k returns ERROR_INVALID_NAME, Win98, wine return ERROR_FILE_NOT_FOUND */
267         ok(passfail.shorterror==ERROR_INVALID_NAME ||
268            passfail.shorterror==ERROR_FILE_NOT_FOUND,
269            "%s: GetShortPathA returned %d and not %d or %d",
270            errstr,passfail.shorterror,ERROR_INVALID_NAME,ERROR_FILE_NOT_FOUND);
271       }
272     } else {
273       ok(passfail.shorterror==ERROR_INVALID_NAME ||
274          passfail.shorterror==ERROR_FILE_NOT_FOUND,
275          "%s: GetShortPathA returned %d and not %d or %d",
276          errstr,passfail.shorterror,ERROR_INVALID_NAME,ERROR_FILE_NOT_FOUND);
277     }
278   }
279   if(pGetLongPathNameA) {
280     ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have");
281     if(valid) {
282       ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
283          "%s: GetLongPathA returned %d and not %d",
284          errstr,passfail.longerror,ERROR_FILE_NOT_FOUND);
285     } else {
286       ok(passfail.longerror==ERROR_INVALID_NAME ||
287          passfail.longerror==ERROR_FILE_NOT_FOUND,
288          "%s: GetLongPathA returned %d and not %d or %d'",
289          errstr, passfail.longerror,ERROR_INVALID_NAME,ERROR_FILE_NOT_FOUND);
290     }
291   }
292 }
293
294 /* Routine to test that SetCurrentDirectory behaves as expected. */
295 static void test_setdir(CHAR *olddir,CHAR *newdir,
296                         CHAR *cmprstr, INT pass,CHAR *errstr)
297 {
298   CHAR tmppath[MAX_PATH], *dirptr;
299   DWORD val,len,chklen;
300
301   val=SetCurrentDirectoryA(newdir);
302   len=GetCurrentDirectoryA(MAX_PATH,tmppath);
303 /* if 'pass' then the SetDirectoryA was supposed to pass */
304   if(pass) {
305     dirptr=(cmprstr==NULL) ? newdir : cmprstr;
306     chklen=lstrlenA(dirptr);
307     ok(val,"%s: SetCurrentDirectoryA failed",errstr);
308     ok(len==chklen,
309        "%s: SetCurrentDirectory did not change the directory, though it passed",
310        errstr);
311     ok(lstrcmpiA(dirptr,tmppath)==0,
312        "%s: SetCurrentDirectory did not change the directory, though it passed",
313        errstr);
314     ok(SetCurrentDirectoryA(olddir),
315        "%s: Couldn't set directory to it's original value");
316   } else {
317 /* else thest that it fails correctly */
318     chklen=lstrlenA(olddir);
319     ok(val==0,
320        "%s: SetCurrentDirectoryA passed when it should have failed",errstr);
321     ok(len==chklen,
322        "%s: SetCurrentDirectory changed the directrory, though it failed",
323        errstr);
324     ok(lstrcmpiA(olddir,tmppath)==0,
325        "%s: SetCurrentDirectory changed the directrory, though it failed",
326        errstr);
327   }
328 }
329 static void test_InitPathA(CHAR *newdir)
330 {
331   CHAR tmppath[MAX_PATH], /*path to TEMP */
332        tmpstr[MAX_PATH],
333        tmpstr1[MAX_PATH];
334   DWORD len,len1;
335   INT id;
336   HANDLE hndl;
337
338 /* Test GetTempPathA */
339   len=GetTempPathA(MAX_PATH,tmppath);
340   ok(len!=0 && len < MAX_PATH,"GetTempPathA failed");
341   ok(HAS_TRAIL_SLASH_A(tmppath),
342      "GetTempPathA returned a path that did not end in '\\'");
343   lstrcpyA(tmpstr,"aaaaaaaa");
344   len1=GetTempPathA(len,tmpstr);
345   ok(len1==len+1,
346      "GetTempPathA should return string length %d instead of %d",len+1,len1);
347   if(WIN2K_PLUS(version)) {
348 /* in Win2k, the path won't be modified, but in win98, wine  it is */
349     todo_wine {
350       ok(lstrcmpiA(tmpstr,"aaaaaaaa")==0,
351          "GetTempPathA should not have modified the buffer");
352     }
353   }
354 /* Test GetTmpFileNameA
355    The only test we do here is whether GetTempFileNameA passes or not.
356    We do not thoroughly test this function yet (specifically, whether
357    it behaves correctly when 'unique' is non zero)
358 */
359   ok((id=GetTempFileNameA(tmppath,"path",0,newdir)),"GetTempFileNameA failed");
360   sprintf(tmpstr,"pat%.4x.tmp",id);
361   sprintf(tmpstr1,"pat%x.tmp",id);
362   ok(lstrcmpiA(newdir+(lstrlenA(newdir)-lstrlenA(tmpstr)),tmpstr)==0 ||
363      lstrcmpiA(newdir+(lstrlenA(newdir)-lstrlenA(tmpstr1)),tmpstr1)==0,
364      "GetTempPath returned '%s' which doesn't match '%s' or '%s'",
365      newdir,tmpstr,tmpstr1);
366
367 /* Do some CreateDirectoryA tests */
368 /* It would be nice to do test the SECURITY_ATTRIBUTES, but I don't
369    really understand how they work.
370    More formal tests should be done along with CreateFile tests
371 */
372   ok(CreateDirectoryA(newdir,NULL)==0,
373      "CreateDirectoryA succeeded even though a file of the same name exists");
374   ok(DeleteFileA(newdir),"Couldn't delete the temporary file we just created");
375   ok(CreateDirectoryA(newdir,NULL),"CreateDirectoryA failed");
376 /* Create some files to test other functions.  Note, we will test CreateFileA
377    at some later point
378 */
379   sprintf(tmpstr,"%s\\%s",newdir,SHORTDIR);
380   ok(CreateDirectoryA(tmpstr,NULL),"CreateDirectoryA failed");
381   sprintf(tmpstr,"%s\\%s",newdir,LONGDIR);
382   ok(CreateDirectoryA(tmpstr,NULL),"CreateDirectoryA failed");
383   sprintf(tmpstr,"%s\\%s\\%s",newdir,SHORTDIR,SHORTFILE);
384   hndl=CreateFileA(tmpstr,GENERIC_WRITE,0,NULL,
385                    CREATE_NEW,FILE_ATTRIBUTE_NORMAL,(HANDLE)NULL);
386   ok(hndl!=INVALID_HANDLE_VALUE,"CreateFileA failed");
387   ok(CloseHandle(hndl),"CloseHandle failed");
388   sprintf(tmpstr,"%s\\%s\\%s",newdir,SHORTDIR,LONGFILE);
389   hndl=CreateFileA(tmpstr,GENERIC_WRITE,0,NULL,
390                    CREATE_NEW,FILE_ATTRIBUTE_NORMAL,(HANDLE)NULL);
391   ok(hndl!=INVALID_HANDLE_VALUE,"CreateFileA failed");
392   ok(CloseHandle(hndl),"CloseHandle failed");
393   sprintf(tmpstr,"%s\\%s\\%s",newdir,LONGDIR,SHORTFILE);
394   hndl=CreateFileA(tmpstr,GENERIC_WRITE,0,NULL,
395                    CREATE_NEW,FILE_ATTRIBUTE_NORMAL,(HANDLE)NULL);
396   ok(hndl!=INVALID_HANDLE_VALUE,"CreateFileA failed");
397   ok(CloseHandle(hndl),"CloseHandle failed");
398   sprintf(tmpstr,"%s\\%s\\%s",newdir,LONGDIR,LONGFILE);
399   hndl=CreateFileA(tmpstr,GENERIC_WRITE,0,NULL,
400                    CREATE_NEW,FILE_ATTRIBUTE_NORMAL,(HANDLE)NULL);
401   ok(hndl!=INVALID_HANDLE_VALUE,"CreateFileA failed");
402   ok(CloseHandle(hndl),"CloseHandle failed");
403 }
404
405 /* Test GetCurrentDirectory & SetCurrentDirectory */
406 static void test_CurrentDirectoryA(CHAR *origdir, CHAR *newdir)
407 {
408   CHAR tmpstr[MAX_PATH],tmpstr1[MAX_PATH];
409   DWORD len,len1;
410 /* Save the original directory, so that we can return to it at the end
411    of the test
412 */
413   len=GetCurrentDirectoryA(MAX_PATH,origdir);
414   ok(len!=0 && len < MAX_PATH,"GetCurrentDirectoryA failed");
415   ok(lstrcmpiA(origdir+(len-1),"\\")!=0,
416      "GetCurrentDirectoryA should not have a trailing \\");
417 /* Make sure that CetCurrentDirectoryA doesn't overwrite the buffer when the
418    buffer size is too small to hold the current directory
419 */
420   lstrcpyA(tmpstr,"aaaaaaa");
421   len1=GetCurrentDirectoryA(len,tmpstr);
422   ok(len1==len+1, "GetCurrentDirectoryA returned %d instead of %d",len1,len+1);
423   ok(lstrcmpiA(tmpstr,"aaaaaaa")==0,
424      "GetCurrentDirectoryA should not have modified the buffer");
425 /* SetCurrentDirectoryA shouldn't care whether the string has a
426    trailing '\\' or not
427 */
428   sprintf(tmpstr,"%s\\",newdir);
429   test_setdir(origdir,tmpstr,newdir,1,"check 1");
430   test_setdir(origdir,newdir,NULL,1,"check 2");
431 /* Set the directory to the working area.  We just tested that this works,
432    so why check it again.
433 */
434   SetCurrentDirectoryA(newdir);
435 /* Check that SetCurrentDirectory fails when a non-existant dir is specified */
436   sprintf(tmpstr,"%s\\%s\\%s",newdir,SHORTDIR,NONDIR_SHORT);
437   test_setdir(newdir,tmpstr,NULL,0,"check 3");
438 /* Check that SetCurrentDirectory fails for a non-existant lond directory */
439   sprintf(tmpstr,"%s\\%s\\%s",newdir,SHORTDIR,NONDIR_LONG);
440   test_setdir(newdir,tmpstr,NULL,0,"check 4");
441 /* Check that SetCurrentDirectory passes with a long directory */
442   sprintf(tmpstr,"%s\\%s",newdir,LONGDIR);
443   test_setdir(newdir,tmpstr,NULL,1,"check 5");
444 /* Check that SetCurrentDirectory passes with a short relative directory */
445   sprintf(tmpstr,"%s",SHORTDIR);
446   sprintf(tmpstr1,"%s\\%s",newdir,SHORTDIR);
447   test_setdir(newdir,tmpstr,tmpstr1,1,"check 6");
448 /* starting with a '.' */
449   sprintf(tmpstr,".\\%s",SHORTDIR);
450   test_setdir(newdir,tmpstr,tmpstr1,1,"check 7");
451 /* Check that SetCurrentDirectory passes with a short relative directory */
452   sprintf(tmpstr,"%s",LONGDIR);
453   sprintf(tmpstr1,"%s\\%s",newdir,LONGDIR);
454   test_setdir(newdir,tmpstr,tmpstr1,1,"check 8");
455 /* starting with a '.' */
456   sprintf(tmpstr,".\\%s",LONGDIR);
457   test_setdir(newdir,tmpstr,tmpstr1,1,"check 9");
458 }
459
460 /* Cleanup the mess we made while executing these tests */
461 static void test_CleanupPathA(CHAR *origdir, CHAR *curdir)
462 {
463   CHAR tmpstr[MAX_PATH];
464   sprintf(tmpstr,"%s\\%s\\%s",curdir,SHORTDIR,SHORTFILE);
465   ok(DeleteFileA(tmpstr),"DeleteFileA failed");
466   sprintf(tmpstr,"%s\\%s\\%s",curdir,SHORTDIR,LONGFILE);
467   ok(DeleteFileA(tmpstr),"DeleteFileA failed");
468   sprintf(tmpstr,"%s\\%s\\%s",curdir,LONGDIR,SHORTFILE);
469   ok(DeleteFileA(tmpstr),"DeleteFileA failed");
470   sprintf(tmpstr,"%s\\%s\\%s",curdir,LONGDIR,LONGFILE);
471   ok(DeleteFileA(tmpstr),"DeleteFileA failed");
472   sprintf(tmpstr,"%s\\%s",curdir,SHORTDIR);
473   ok(RemoveDirectoryA(tmpstr),"RemoveDirectoryA failed");
474   sprintf(tmpstr,"%s\\%s",curdir,LONGDIR);
475   ok(RemoveDirectoryA(tmpstr),"RemoveDirectoryA failed");
476   ok(SetCurrentDirectoryA(origdir),"SetCurrentDirectoryA failed");
477   ok(RemoveDirectoryA(curdir),"RemoveDirectoryA failed");
478 }
479
480 /* This routine will test Get(Full|Short|Long)PathNameA */
481 static void test_PathNameA(CHAR *curdir)
482 {
483   CHAR curdir_short[MAX_PATH],
484        longdir_short[MAX_PATH];
485   CHAR tmpstr[MAX_PATH],tmpstr1[MAX_PATH];
486   DWORD len;
487   INT i;
488   CHAR dir[MAX_PATH],eight[MAX_PATH],three[MAX_PATH];
489   SLpassfail passfail;
490
491 /* Get the short form of the current directory */
492   ok((len=GetShortPathNameA(curdir,curdir_short,MAX_PATH)),
493      "GetShortPathNameA failed");
494   ok(!HAS_TRAIL_SLASH_A(curdir_short),
495      "GetShortPathNameA should not have a trailing \\");
496 /* Get the short form of the absolute-path to LONGDIR */
497   sprintf(tmpstr,"%s\\%s",curdir_short,LONGDIR);
498   ok((len=GetShortPathNameA(tmpstr,longdir_short,MAX_PATH)),
499      "GetShortPathNameA failed");
500   ok(lstrcmpiA(longdir_short+(len-1),"\\")!=0,
501      "GetShortPathNameA should not have a trailing \\");
502
503 /* Check the cases where both file and directory exist first */
504 /* Start with a 8.3 directory, 8.3 filename */
505   test_ValidPathA(curdir,SHORTDIR,SHORTFILE,tmpstr,NULL,"test1");
506   sprintf(tmpstr1,"%s\\%s\\%s",curdir_short,SHORTDIR,SHORTFILE);
507   ok(lstrcmpiA(tmpstr,tmpstr1)==0,
508      "GetShortPathNameA returned '%s' instead of '%s'",tmpstr,tmpstr1);
509 /* Now try a 8.3 directory, long file name */
510   test_ValidPathA(curdir,SHORTDIR,LONGFILE,tmpstr,NULL,"test2");
511   sprintf(tmpstr1,"%s\\%s",curdir_short,SHORTDIR);
512   test_LongtoShortA(tmpstr,tmpstr1,"PAT","test2");
513 /* Next is a long directory, 8.3 file */
514   test_ValidPathA(curdir,LONGDIR,SHORTFILE,tmpstr,NULL,"test3");
515   sprintf(tmpstr1,"%s\\%s",longdir_short,SHORTFILE);
516   ok(lstrcmpiA(tmpstr,tmpstr1)==0,
517      "GetShortPathNameA returned '%s' instead of '%s'",tmpstr,tmpstr1);
518 /*Lastly a long directory, long file */
519   test_ValidPathA(curdir,LONGDIR,LONGFILE,tmpstr,NULL,"test4");
520   test_LongtoShortA(tmpstr,longdir_short,"PAT","test4");
521
522 /* Now check all of the invalid file w/ valid directroy combinations */
523 /* Start with a 8.3 directory, 8.3 filename */
524   test_ValidPathA(curdir,SHORTDIR,NONFILE_SHORT,tmpstr,&passfail,"test5");
525   todo_wine {
526     ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have");
527     ok(passfail.shorterror==ERROR_FILE_NOT_FOUND,
528        "GetShortPathA should have returned 'ERROR_FILE_NOT_FOUND'");
529   }
530   if(pGetLongPathNameA) {
531     ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have");
532     ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
533        "GetlongPathA should have returned 'ERROR_FILE_NOT_FOUND'");
534   }
535 /* Now try a 8.3 directory, long file name */
536   test_ValidPathA(curdir,SHORTDIR,NONFILE_LONG,tmpstr,&passfail,"test6");
537   ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have");
538   ok(passfail.shorterror==ERROR_FILE_NOT_FOUND,
539      "GetShortPathA should have returned 'ERROR_FILE_NOT_FOUND'");
540   if(pGetLongPathNameA) {
541     ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have");
542     ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
543        "GetlongPathA should have returned 'ERROR_FILE_NOT_FOUND'");
544   }
545 /* Next is a long directory, 8.3 file */
546   test_ValidPathA(curdir,LONGDIR,NONFILE_SHORT,tmpstr,&passfail,"test7");
547   todo_wine {
548     ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have");
549     ok(passfail.shorterror==ERROR_FILE_NOT_FOUND,
550        "GetShortPathA should have returned 'ERROR_FILE_NOT_FOUND'");
551   }
552   if(pGetLongPathNameA) {
553     ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have");
554     ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
555       "GetlongPathA should have returned 'ERROR_FILE_NOT_FOUND'");
556   }
557 /*Lastly a long directory, long file */
558   test_ValidPathA(curdir,LONGDIR,NONFILE_LONG,tmpstr,&passfail,"test8");
559   ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have");
560   ok(passfail.shorterror==ERROR_FILE_NOT_FOUND,
561      "GetShortPathA should have returned 'ERROR_FILE_NOT_FOUND'");
562   if(pGetLongPathNameA) {
563     ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have");
564     ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
565        "GetlongPathA should have returned 'ERROR_FILE_NOT_FOUND'");
566   }
567 /* Now try again with directories that don't exist */
568 /* 8.3 directory, 8.3 filename */
569   test_ValidPathA(curdir,NONDIR_SHORT,SHORTFILE,tmpstr,&passfail,"test9");
570   todo_wine {
571     ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have");
572     ok(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
573        passfail.shorterror==ERROR_FILE_NOT_FOUND,
574        "GetShortPathA returned %d and not 'ERROR_PATH_NOT_FOUND'",
575         passfail.shorterror);
576   }
577   if(pGetLongPathNameA) {
578     ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have");
579     ok(passfail.longerror==ERROR_PATH_NOT_FOUND ||
580        passfail.longerror==ERROR_FILE_NOT_FOUND,
581        "GetLongPathA returned %d and not 'ERROR_PATH_NOT_FOUND'",
582        passfail.longerror);
583   }
584 /* Now try a 8.3 directory, long file name */
585   test_ValidPathA(curdir,NONDIR_SHORT,LONGFILE,tmpstr,&passfail,"test10");
586   ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have");
587   ok(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
588      passfail.shorterror==ERROR_FILE_NOT_FOUND,
589      "GetShortPathA returned %d and not 'ERROR_PATH_NOT_FOUND'",
590       passfail.shorterror);
591   if(pGetLongPathNameA) {
592     ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have");
593     ok(passfail.longerror==ERROR_PATH_NOT_FOUND ||
594        passfail.longerror==ERROR_FILE_NOT_FOUND,
595        "GetLongPathA returned %d and not 'ERROR_PATH_NOT_FOUND'",
596        passfail.longerror);
597   }
598 /* Next is a long directory, 8.3 file */
599   test_ValidPathA(curdir,NONDIR_LONG,SHORTFILE,tmpstr,&passfail,"test11");
600   ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have");
601   ok(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
602      passfail.shorterror==ERROR_FILE_NOT_FOUND,
603      "GetShortPathA returned %d and not 'ERROR_PATH_NOT_FOUND'",
604       passfail.shorterror);
605   if(pGetLongPathNameA) {
606     ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have");
607     ok(passfail.longerror==ERROR_PATH_NOT_FOUND ||
608        passfail.longerror==ERROR_FILE_NOT_FOUND,
609        "GetLongPathA returned %d and not 'ERROR_PATH_NOT_FOUND'",
610        passfail.longerror);
611   }
612 /*Lastly a long directory, long file */
613   test_ValidPathA(curdir,NONDIR_LONG,LONGFILE,tmpstr,&passfail,"test12");
614   ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have");
615   ok(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
616      passfail.shorterror==ERROR_FILE_NOT_FOUND,
617      "GetShortPathA returned %d and not 'ERROR_PATH_NOT_FOUND'",
618       passfail.shorterror);
619   if(pGetLongPathNameA) {
620     ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have");
621     ok(passfail.longerror==ERROR_PATH_NOT_FOUND ||
622        passfail.longerror==ERROR_FILE_NOT_FOUND,
623        "GetLongPathA returned %d and not 'ERROR_PATH_NOT_FOUND'",
624        passfail.longerror);
625   }
626 /* Next try directories ending with '\\' */
627 /* Existing Directories */
628   sprintf(tmpstr,"%s\\",SHORTDIR);
629   test_ValidPathA(curdir,"",tmpstr,tmpstr1,NULL,"test13");
630   sprintf(tmpstr,"%s\\",LONGDIR);
631   test_ValidPathA(curdir,"",tmpstr,tmpstr1,NULL,"test14");
632 /* Non-existant directories */
633   sprintf(tmpstr,"%s\\",NONDIR_SHORT);
634   test_ValidPathA(curdir,"",tmpstr,tmpstr1,&passfail,"test15");
635   todo_wine {
636     ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have");
637     ok(passfail.shorterror==ERROR_FILE_NOT_FOUND,
638      "GetShortPathA returned %d and not 'ERROR_FILE_NOT_FOUND'",
639       passfail.shorterror);
640   }
641   if(pGetLongPathNameA) {
642     ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have");
643     ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
644        "GetLongPathA returned %d and not 'ERROR_FILE_NOT_FOUND'",
645        passfail.longerror);
646   }
647   sprintf(tmpstr,"%s\\",NONDIR_LONG);
648   test_ValidPathA(curdir,"",tmpstr,tmpstr1,&passfail,"test16");
649   ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have");
650   ok(passfail.shorterror==ERROR_FILE_NOT_FOUND,
651      "GetShortPathA returned %d and not 'ERROR_FILE_NOT_FOUND'",
652       passfail.shorterror);
653   if(pGetLongPathNameA) {
654     ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have");
655     ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
656        "GetLongPathA returned %d and not 'ERROR_FILE_NOT_FOUND'",
657        passfail.longerror);
658   }
659 /* Now try some relative paths */
660   ok(GetShortPathNameA(LONGDIR,tmpstr,MAX_PATH),"GetShortPathNameA failed");
661   test_SplitShortPathA(tmpstr,dir,eight,three);
662   if(pGetLongPathNameA) {
663     ok(pGetLongPathNameA(tmpstr,tmpstr1,MAX_PATH),"GetShortPathNameA failed");
664     todo_wine {
665       ok(lstrcmpiA(tmpstr1,LONGDIR)==0,
666          "GetLongPathNameA returned '%s' instead of '%s'",tmpstr1,LONGDIR);
667     }
668   }
669   sprintf(tmpstr,".\\%s",LONGDIR);
670   ok(GetShortPathNameA(tmpstr,tmpstr1,MAX_PATH),"GetShortPathNameA failed");
671   test_SplitShortPathA(tmpstr1,dir,eight,three);
672   ok(lstrcmpiA(dir,".")==0,"GetShortPathNameA did not keep relative directory");
673   if(pGetLongPathNameA) {
674     ok(pGetLongPathNameA(tmpstr1,tmpstr1,MAX_PATH),"GetShortPathNameA failed");
675     todo_wine {
676       ok(lstrcmpiA(tmpstr1,tmpstr)==0,
677          "GetLongPathNameA returned '%s' instead of '%s'",tmpstr1,tmpstr);
678     }
679   }
680 /* Check out Get*PathNameA on some funny characters */
681   for(i=0;i<lstrlenA(funny_chars);i++) {
682     INT valid,todo;
683     valid=(is_char_ok[i]=='0') ? 0 : 1;
684     todo=(wine_todo[i]=='0') ? 0 : 1;
685     sprintf(tmpstr1,"check%d-1",i);
686     sprintf(tmpstr,"file%c000.ext",funny_chars[i]);
687     test_FunnyChars(curdir,tmpstr,valid,todo,tmpstr1);
688     sprintf(tmpstr1,"check%d-2",i);
689     sprintf(tmpstr,"file000.e%ct",funny_chars[i]);
690     test_FunnyChars(curdir,tmpstr,valid,todo,tmpstr1);
691     sprintf(tmpstr1,"check%d-3",i);
692     sprintf(tmpstr,"%cfile000.ext",funny_chars[i]);
693     test_FunnyChars(curdir,tmpstr,valid,todo,tmpstr1);
694     sprintf(tmpstr1,"check%d-4",i);
695     sprintf(tmpstr,"file000%c.ext",funny_chars[i]);
696     test_FunnyChars(curdir,tmpstr,valid,todo,tmpstr1);
697     sprintf(tmpstr1,"check%d-5",i);
698     sprintf(tmpstr,"Long %c File",funny_chars[i]);
699     test_FunnyChars(curdir,tmpstr,valid,0,tmpstr1);
700     sprintf(tmpstr1,"check%d-6",i);
701     sprintf(tmpstr,"%c Long File",funny_chars[i]);
702     test_FunnyChars(curdir,tmpstr,valid,0,tmpstr1);
703     sprintf(tmpstr1,"check%d-7",i);
704     sprintf(tmpstr,"Long File %c",funny_chars[i]);
705     test_FunnyChars(curdir,tmpstr,valid,0,tmpstr1);
706   }
707 /* ':' is a special case and is allowed only in certain cases */
708     test_FunnyChars(curdir,"file:000.ext",1,1,"check-1");
709     test_FunnyChars(curdir,"file000.e:t" ,1,1,"check-2");
710     test_FunnyChars(curdir,":file000.ext",0,1,"check-3");
711     test_FunnyChars(curdir,"file000:.ext",1,1,"check-4");
712     test_FunnyChars(curdir,"Long : File" ,1,0,"check-5");
713     test_FunnyChars(curdir,": Long File" ,0,0,"check-6");
714     test_FunnyChars(curdir,"Long File :" ,0,0,"check-7");
715 }
716
717 START_TEST(path)
718 {
719     CHAR origdir[MAX_PATH],curdir[MAX_PATH];
720     version.dwOSVersionInfoSize=sizeof(OSVERSIONINFOA);
721     ok(GetVersionExA(&version),"GetVersionEx failed: %d",GetLastError());
722     pGetLongPathNameA = (void*)GetProcAddress( GetModuleHandleA("kernel32.dll"),
723                                                "GetLongPathNameA" );
724     test_InitPathA(curdir);
725     test_CurrentDirectoryA(origdir,curdir);
726     test_PathNameA(curdir);
727     test_CleanupPathA(origdir,curdir);
728 }