kernel32: Return upper cased drive letters in paths, some applications depend on it.
[wine] / dlls / kernel32 / tests / path.c
1 /*
2  * Unit test suite for various Path and Directory Functions
3  *
4  * Copyright 2002 Geoffrey Hausheer
5  * Copyright 2006 Detlef Riekenberg
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21
22 #include <stdarg.h>
23 #include <stdio.h>
24 #include "wine/test.h"
25 #include "windef.h"
26 #include "winbase.h"
27 #include "winuser.h"
28 #include "winerror.h"
29 #include "winnls.h"
30
31 #define HAS_TRAIL_SLASH_A(string) (string[lstrlenA(string)-1]=='\\')
32
33 #define LONGFILE "Long File test.path"
34 #define SHORTFILE "pathtest.pth"
35 #define SHORTDIR "shortdir"
36 #define LONGDIR "Long Directory"
37 #define NONFILE_SHORT "noexist.pth"
38 #define NONFILE_LONG "NonExistent File"
39 #define NONDIR_SHORT "notadir"
40 #define NONDIR_LONG "NonExistent Directory"
41
42 #define NOT_A_VALID_DRIVE '@'
43
44 /* the following characters don't work well with GetFullPathNameA
45    in Win98.  I don't know if this is a FAT thing, or if it is an OS thing
46    but I don't test these characters now.
47    NOTE: Win2k allows GetFullPathNameA to work with them though
48       |<>"
49 */
50 static const CHAR funny_chars[]="!@#$%^&*()=+{}[],?'`";
51 static const CHAR is_char_ok[] ="11111110111111111011";
52
53 static DWORD (WINAPI *pGetLongPathNameA)(LPCSTR,LPSTR,DWORD);
54 static DWORD (WINAPI *pGetLongPathNameW)(LPWSTR,LPWSTR,DWORD);
55
56 /* Present in Win2003+ */
57 static BOOL  (WINAPI *pNeedCurrentDirectoryForExePathA)(LPCSTR);
58 static BOOL  (WINAPI *pNeedCurrentDirectoryForExePathW)(LPCWSTR);
59
60 /* a structure to deal with wine todos somewhat cleanly */
61 typedef struct {
62   DWORD shortlen;
63   DWORD shorterror;
64   DWORD s2llen;
65   DWORD s2lerror;
66   DWORD longlen;
67   DWORD longerror;
68 } SLpassfail;
69
70 /* function that tests GetFullPathNameA, GetShortPathNameA,GetLongPathNameA */
71 /* NOTE: the passfail structure is used to allow cutomizeable todo checking
72          for wine.  It is not very pretty, but it sure beats duplicating this
73          function lots of times
74 */
75 static void test_ValidPathA(const CHAR *curdir, const CHAR *subdir, const CHAR *filename,
76                          CHAR *shortstr, SLpassfail *passfail, const CHAR *errstr)
77 {
78   CHAR tmpstr[MAX_PATH],
79        fullpath[MAX_PATH],      /*full path to the file (not short/long) */
80        subpath[MAX_PATH],       /*relative path to the file */
81        fullpathshort[MAX_PATH], /*absolue path to the file (short format) */
82        fullpathlong[MAX_PATH],  /*absolute path to the file (long format) */
83        curdirshort[MAX_PATH],   /*absolute path to the current dir (short) */
84        curdirlong[MAX_PATH];    /*absolute path to the current dir (long) */
85   LPSTR strptr;                 /*ptr to the filename portion of the path */
86   DWORD len;
87 /* if passfail is NULL, we can perform all checks within this function,
88    otherwise, we will return the relevant data in the passfail struct, so
89    we must initialize it first
90 */
91   if(passfail!=NULL) {
92     passfail->shortlen=-1;passfail->s2llen=-1;passfail->longlen=-1;
93     passfail->shorterror=0;passfail->s2lerror=0;passfail->longerror=0;
94   }
95 /* GetLongPathNameA is only supported on Win2k+ and Win98+ */
96   if(pGetLongPathNameA) {
97     ok((len=pGetLongPathNameA(curdir,curdirlong,MAX_PATH)),
98        "%s: GetLongPathNameA failed\n",errstr);
99 /*GetLongPathNameA can return a trailing '\\' but shouldn't do so here */
100     ok(! HAS_TRAIL_SLASH_A(curdirlong),
101        "%s: GetLongPathNameA should not have a trailing \\\n",errstr);
102   }
103   ok((len=GetShortPathNameA(curdir,curdirshort,MAX_PATH)),
104      "%s: GetShortPathNameA failed\n",errstr);
105 /*GetShortPathNameA can return a trailing '\\' but shouldn't do so here */
106   ok(! HAS_TRAIL_SLASH_A(curdirshort),
107      "%s: GetShortPathNameA should not have a trailing \\\n",errstr);
108 /* build relative and absolute paths from inputs */
109   if(lstrlenA(subdir)) {
110     sprintf(subpath,"%s\\%s",subdir,filename);
111   } else {
112     lstrcpyA(subpath,filename);
113   }
114   sprintf(fullpath,"%s\\%s",curdir,subpath);
115   sprintf(fullpathshort,"%s\\%s",curdirshort,subpath);
116   sprintf(fullpathlong,"%s\\%s",curdirlong,subpath);
117 /* Test GetFullPathNameA functionality */
118   len=GetFullPathNameA(subpath,MAX_PATH,tmpstr,&strptr);
119   ok(len, "GetFullPathNameA failed for: '%s'\n",subpath);
120   if(HAS_TRAIL_SLASH_A(subpath)) {
121     ok(strptr==NULL,
122        "%s: GetFullPathNameA should not return a filename ptr\n",errstr);
123     ok(lstrcmpiA(fullpath,tmpstr)==0,
124        "%s: GetFullPathNameA returned '%s' instead of '%s'\n",
125        errstr,tmpstr,fullpath);
126   } else {
127     ok(lstrcmpiA(strptr,filename)==0,
128        "%s: GetFullPathNameA returned '%s' instead of '%s'\n",
129        errstr,strptr,filename);
130     ok(lstrcmpiA(fullpath,tmpstr)==0,
131        "%s: GetFullPathNameA returned '%s' instead of '%s'\n",
132        errstr,tmpstr,fullpath);
133   }
134 /* Test GetShortPathNameA functionality */
135   SetLastError(0);
136   len=GetShortPathNameA(fullpathshort,shortstr,MAX_PATH);
137   if(passfail==NULL) {
138     ok(len, "%s: GetShortPathNameA failed\n",errstr);
139   } else {
140     passfail->shortlen=len;
141     passfail->shorterror=GetLastError();
142   }
143 /* Test GetLongPathNameA functionality
144    We test both conversion from GetFullPathNameA and from GetShortPathNameA
145 */
146   if(pGetLongPathNameA) {
147     if(len!=0) {
148       SetLastError(0);
149       len=pGetLongPathNameA(shortstr,tmpstr,MAX_PATH);
150       if(passfail==NULL) {
151         ok(len,
152           "%s: GetLongPathNameA failed during Short->Long conversion\n", errstr);
153         ok(lstrcmpiA(fullpathlong,tmpstr)==0,
154            "%s: GetLongPathNameA returned '%s' instead of '%s'\n",
155            errstr,tmpstr,fullpathlong);
156       } else {
157         passfail->s2llen=len;
158         passfail->s2lerror=GetLastError();
159       }
160     }
161     SetLastError(0);
162     len=pGetLongPathNameA(fullpath,tmpstr,MAX_PATH);
163     if(passfail==NULL) {
164       ok(len, "%s: GetLongPathNameA failed\n",errstr);
165       if(HAS_TRAIL_SLASH_A(fullpath)) {
166         ok(lstrcmpiA(fullpathlong,tmpstr)==0,
167            "%s: GetLongPathNameA returned '%s' instead of '%s'\n",
168            errstr,tmpstr,fullpathlong);
169       } else {
170         ok(lstrcmpiA(fullpathlong,tmpstr)==0,
171           "%s: GetLongPathNameA returned '%s' instead of '%s'\n",
172           errstr,tmpstr,fullpathlong);
173       }
174     } else {
175       passfail->longlen=len;
176       passfail->longerror=GetLastError();
177     }
178   }
179 }
180
181 /* split path into leading directory, and 8.3 filename */
182 static void test_SplitShortPathA(CHAR *path,CHAR *dir,CHAR *eight,CHAR *three) {
183   int done,error;
184   int ext,fil;
185   int len,i;
186   len=lstrlenA(path);
187   ext=len; fil=len; done=0; error=0;
188 /* walk backwards over path looking for '.' or '\\' separators */
189   for(i=len-1;(i>=0) && (!done);i--) {
190     if(path[i]=='.')
191       if(ext!=len) error=1; else ext=i;
192     else if(path[i]=='\\') {
193       if(i==len-1) {
194         error=1;
195       } else {
196         fil=i;
197         done=1;
198       }
199     }
200   }
201 /* Check that we didn't find a trailing '\\' or multiple '.' */
202   ok(!error,"Illegal file found in 8.3 path '%s'\n",path);
203 /* Separate dir, root, and extension */
204   if(ext!=len) lstrcpyA(three,path+ext+1); else lstrcpyA(three,"");
205   if(fil!=len) {
206     lstrcpynA(eight,path+fil+1,ext-fil);
207     lstrcpynA(dir,path,fil+1);
208   } else {
209     lstrcpynA(eight,path,ext+1);
210     lstrcpyA(dir,"");
211   }
212 /* Validate that root and extension really are 8.3 */
213   ok(lstrlenA(eight)<=8 && lstrlenA(three)<=3,
214      "GetShortPathNAmeA did not return an 8.3 path\n");
215 }
216
217 /* Check that GetShortPathNameA returns a valid 8.3 path */
218 static void test_LongtoShortA(CHAR *teststr,const CHAR *goodstr,
219                               const CHAR *ext,const CHAR *errstr) {
220   CHAR dir[MAX_PATH],eight[MAX_PATH],three[MAX_PATH];
221
222   test_SplitShortPathA(teststr,dir,eight,three);
223   ok(lstrcmpiA(dir,goodstr)==0,
224      "GetShortPathNameA returned '%s' instead of '%s'\n",dir,goodstr);
225   ok(lstrcmpiA(three,ext)==0,
226      "GetShortPathNameA returned '%s' with incorrect extension\n",three);
227 }
228
229 /* Test that Get(Short|Long|Full)PathNameA work correctly with interesting
230    characters in the filename.
231      'valid' indicates whether this would be an allowed filename
232      'todo' indicates that wine doesn't get this right yet.
233    NOTE: We always call this routine with a nonexistent filename, so
234          Get(Short|Long)PathNameA should never pass, but GetFullPathNameA
235          should.
236 */
237 static void test_FunnyChars(CHAR *curdir,CHAR *curdir_short,CHAR *filename, INT valid,CHAR *errstr)
238 {
239   CHAR tmpstr[MAX_PATH],tmpstr1[MAX_PATH];
240   SLpassfail passfail;
241
242   test_ValidPathA(curdir,"",filename,tmpstr,&passfail,errstr);
243   if(valid) {
244     sprintf(tmpstr1,"%s\\%s",curdir_short,filename);
245       ok((passfail.shortlen==0 &&
246           (passfail.shorterror==ERROR_FILE_NOT_FOUND || passfail.shorterror==ERROR_PATH_NOT_FOUND || !passfail.shorterror)) ||
247          (passfail.shortlen==strlen(tmpstr1) && lstrcmpiA(tmpstr,tmpstr1)==0),
248          "%s: GetShortPathNameA error: len=%d error=%d tmpstr=[%s]\n",
249          errstr,passfail.shortlen,passfail.shorterror,tmpstr);
250   } else {
251       ok(passfail.shortlen==0 &&
252          (passfail.shorterror==ERROR_INVALID_NAME || passfail.shorterror==ERROR_FILE_NOT_FOUND || !passfail.shorterror),
253          "%s: GetShortPathA should have failed len=%d, error=%d\n",
254          errstr,passfail.shortlen,passfail.shorterror);
255   }
256   if(pGetLongPathNameA) {
257     ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
258     if(valid) {
259       ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
260          "%s: GetLongPathA returned %d and not %d\n",
261          errstr,passfail.longerror,ERROR_FILE_NOT_FOUND);
262     } else {
263       ok(passfail.longerror==ERROR_INVALID_NAME ||
264          passfail.longerror==ERROR_FILE_NOT_FOUND,
265          "%s: GetLongPathA returned %d and not %d or %d'\n",
266          errstr, passfail.longerror,ERROR_INVALID_NAME,ERROR_FILE_NOT_FOUND);
267     }
268   }
269 }
270
271 /* Routine to test that SetCurrentDirectory behaves as expected. */
272 static void test_setdir(CHAR *olddir,CHAR *newdir,
273                         CHAR *cmprstr, INT pass, const CHAR *errstr)
274 {
275   CHAR tmppath[MAX_PATH], *dirptr;
276   DWORD val,len,chklen;
277
278   val=SetCurrentDirectoryA(newdir);
279   len=GetCurrentDirectoryA(MAX_PATH,tmppath);
280 /* if 'pass' then the SetDirectoryA was supposed to pass */
281   if(pass) {
282     dirptr=(cmprstr==NULL) ? newdir : cmprstr;
283     chklen=lstrlenA(dirptr);
284     ok(val,"%s: SetCurrentDirectoryA failed\n",errstr);
285     ok(len==chklen,
286        "%s: SetCurrentDirectory did not change the directory, though it passed\n",
287        errstr);
288     ok(lstrcmpiA(dirptr,tmppath)==0,
289        "%s: SetCurrentDirectory did not change the directory, though it passed\n",
290        errstr);
291     ok(SetCurrentDirectoryA(olddir),
292        "%s: Couldn't set directory to it's original value\n",errstr);
293   } else {
294 /* else thest that it fails correctly */
295     chklen=lstrlenA(olddir);
296     ok(val==0,
297        "%s: SetCurrentDirectoryA passed when it should have failed\n",errstr);
298     ok(len==chklen,
299        "%s: SetCurrentDirectory changed the directory, though it failed\n",
300        errstr);
301     ok(lstrcmpiA(olddir,tmppath)==0,
302        "%s: SetCurrentDirectory changed the directory, though it failed\n",
303        errstr);
304   }
305 }
306 static void test_InitPathA(CHAR *newdir, CHAR *curDrive, CHAR *otherDrive)
307 {
308   CHAR tmppath[MAX_PATH], /*path to TEMP */
309        tmpstr[MAX_PATH],
310        tmpstr1[MAX_PATH];
311   DWORD len,len1,drives;
312   INT id;
313   HANDLE hndl;
314   BOOL bRes;
315
316   *curDrive = *otherDrive = NOT_A_VALID_DRIVE;
317
318 /* Get the current drive letter */
319   if( GetCurrentDirectoryA( MAX_PATH, tmpstr))
320     *curDrive = tmpstr[0];
321   else
322     trace( "Unable to discover current drive, some tests will not be conducted.\n");
323
324 /* Test GetTempPathA */
325   len=GetTempPathA(MAX_PATH,tmppath);
326   ok(len!=0 && len < MAX_PATH,"GetTempPathA failed\n");
327   ok(HAS_TRAIL_SLASH_A(tmppath),
328      "GetTempPathA returned a path that did not end in '\\'\n");
329   lstrcpyA(tmpstr,"aaaaaaaa");
330   len1=GetTempPathA(len,tmpstr);
331   ok(len1==len+1,
332      "GetTempPathA should return string length %d instead of %d\n",len+1,len1);
333
334 /* Test GetTmpFileNameA
335    The only test we do here is whether GetTempFileNameA passes or not.
336    We do not thoroughly test this function yet (specifically, whether
337    it behaves correctly when 'unique' is non zero)
338 */
339   ok((id=GetTempFileNameA(tmppath,"path",0,newdir)),"GetTempFileNameA failed\n");
340   sprintf(tmpstr,"pat%.4x.tmp",id & 0xffff);
341   sprintf(tmpstr1,"pat%x.tmp",id & 0xffff);
342   ok(lstrcmpiA(newdir+lstrlenA(tmppath),tmpstr)==0 ||
343      lstrcmpiA(newdir+lstrlenA(tmppath),tmpstr1)==0,
344      "GetTempFileNameA returned '%s' which doesn't match '%s' or '%s'. id=%x\n",
345      newdir,tmpstr,tmpstr1,id);
346   ok(DeleteFileA(newdir),"Couldn't delete the temporary file we just created\n");     
347
348   id=GetTempFileNameA(tmppath,NULL,0,newdir);
349 /* Windows 95, 98 return 0==id, while Windows 2000, XP return 0!=id */
350   if (id)
351   {
352     sprintf(tmpstr,"%.4x.tmp",id & 0xffff);
353     sprintf(tmpstr1,"%x.tmp",id & 0xffff);
354     ok(lstrcmpiA(newdir+lstrlenA(tmppath),tmpstr)==0 ||
355        lstrcmpiA(newdir+lstrlenA(tmppath),tmpstr1)==0,
356        "GetTempFileNameA returned '%s' which doesn't match '%s' or '%s'. id=%x\n",
357        newdir,tmpstr,tmpstr1,id);
358     ok(DeleteFileA(newdir),"Couldn't delete the temporary file we just created\n");
359   }
360
361 /* Find first valid drive letter that is neither newdir[0] nor curDrive */
362   drives = GetLogicalDrives() & ~(1<<(newdir[0]-'A'));
363   if( *curDrive != NOT_A_VALID_DRIVE)
364     drives &= ~(1<<(*curDrive-'A'));
365   if( drives)
366     for( *otherDrive='A'; (drives & 1) == 0; drives>>=1, (*otherDrive)++);
367   else
368     trace( "Could not find alternative drive, some tests will not be conducted.\n");
369
370 /* Do some CreateDirectoryA tests */
371 /* It would be nice to do test the SECURITY_ATTRIBUTES, but I don't
372    really understand how they work.
373    More formal tests should be done along with CreateFile tests
374 */
375   ok((id=GetTempFileNameA(tmppath,"path",0,newdir)),"GetTempFileNameA failed\n");
376   ok(CreateDirectoryA(newdir,NULL)==0,
377      "CreateDirectoryA succeeded even though a file of the same name exists\n");
378   ok(DeleteFileA(newdir),"Couldn't delete the temporary file we just created\n");
379   ok(CreateDirectoryA(newdir,NULL),"CreateDirectoryA failed\n");
380 /* Create some files to test other functions.  Note, we will test CreateFileA
381    at some later point
382 */
383   sprintf(tmpstr,"%s\\%s",newdir,SHORTDIR);
384   ok(CreateDirectoryA(tmpstr,NULL),"CreateDirectoryA failed\n");
385   sprintf(tmpstr,"%s\\%s",newdir,LONGDIR);
386   ok(CreateDirectoryA(tmpstr,NULL),"CreateDirectoryA failed\n");
387   bRes = CreateDirectoryA("c:",NULL);
388   ok(!bRes && (GetLastError() == ERROR_ACCESS_DENIED  || 
389                GetLastError() == ERROR_ALREADY_EXISTS),
390      "CreateDirectoryA(\"c:\" should have failed (%d)\n", GetLastError());
391   bRes = CreateDirectoryA("c:\\",NULL);
392   ok(!bRes && (GetLastError() == ERROR_ACCESS_DENIED  ||
393                GetLastError() == ERROR_ALREADY_EXISTS),
394      "CreateDirectoryA(\"c:\\\" should have failed (%d)\n", GetLastError());
395   sprintf(tmpstr,"%s\\%s\\%s",newdir,SHORTDIR,SHORTFILE);
396   hndl=CreateFileA(tmpstr,GENERIC_WRITE,0,NULL,
397                    CREATE_NEW,FILE_ATTRIBUTE_NORMAL,NULL);
398   ok(hndl!=INVALID_HANDLE_VALUE,"CreateFileA failed\n");
399   ok(CloseHandle(hndl),"CloseHandle failed\n");
400   sprintf(tmpstr,"%s\\%s\\%s",newdir,SHORTDIR,LONGFILE);
401   hndl=CreateFileA(tmpstr,GENERIC_WRITE,0,NULL,
402                    CREATE_NEW,FILE_ATTRIBUTE_NORMAL,NULL);
403   ok(hndl!=INVALID_HANDLE_VALUE,"CreateFileA failed\n");
404   ok(CloseHandle(hndl),"CloseHandle failed\n");
405   sprintf(tmpstr,"%s\\%s\\%s",newdir,LONGDIR,SHORTFILE);
406   hndl=CreateFileA(tmpstr,GENERIC_WRITE,0,NULL,
407                    CREATE_NEW,FILE_ATTRIBUTE_NORMAL,NULL);
408   ok(hndl!=INVALID_HANDLE_VALUE,"CreateFileA failed\n");
409   ok(CloseHandle(hndl),"CloseHandle failed\n");
410   sprintf(tmpstr,"%s\\%s\\%s",newdir,LONGDIR,LONGFILE);
411   hndl=CreateFileA(tmpstr,GENERIC_WRITE,0,NULL,
412                    CREATE_NEW,FILE_ATTRIBUTE_NORMAL,NULL);
413   ok(hndl!=INVALID_HANDLE_VALUE,"CreateFileA failed\n");
414   ok(CloseHandle(hndl),"CloseHandle failed\n");
415 }
416
417 /* Test GetCurrentDirectory & SetCurrentDirectory */
418 static void test_CurrentDirectoryA(CHAR *origdir, CHAR *newdir)
419 {
420   CHAR tmpstr[MAX_PATH],tmpstr1[MAX_PATH];
421   DWORD len,len1;
422 /* Save the original directory, so that we can return to it at the end
423    of the test
424 */
425   len=GetCurrentDirectoryA(MAX_PATH,origdir);
426   ok(len!=0 && len < MAX_PATH,"GetCurrentDirectoryA failed\n");
427 /* Make sure that CetCurrentDirectoryA doesn't overwrite the buffer when the
428    buffer size is too small to hold the current directory
429 */
430   lstrcpyA(tmpstr,"aaaaaaa");
431   len1=GetCurrentDirectoryA(len,tmpstr);
432   ok(len1==len+1, "GetCurrentDirectoryA returned %d instead of %d\n",len1,len+1);
433   ok(lstrcmpiA(tmpstr,"aaaaaaa")==0,
434      "GetCurrentDirectoryA should not have modified the buffer\n");
435 /* SetCurrentDirectoryA shouldn't care whether the string has a
436    trailing '\\' or not
437 */
438   sprintf(tmpstr,"%s\\",newdir);
439   test_setdir(origdir,tmpstr,newdir,1,"check 1");
440   test_setdir(origdir,newdir,NULL,1,"check 2");
441 /* Set the directory to the working area.  We just tested that this works,
442    so why check it again.
443 */
444   SetCurrentDirectoryA(newdir);
445 /* Check that SetCurrentDirectory fails when a nonexistent dir is specified */
446   sprintf(tmpstr,"%s\\%s\\%s",newdir,SHORTDIR,NONDIR_SHORT);
447   test_setdir(newdir,tmpstr,NULL,0,"check 3");
448 /* Check that SetCurrentDirectory fails for a nonexistent lond directory */
449   sprintf(tmpstr,"%s\\%s\\%s",newdir,SHORTDIR,NONDIR_LONG);
450   test_setdir(newdir,tmpstr,NULL,0,"check 4");
451 /* Check that SetCurrentDirectory passes with a long directory */
452   sprintf(tmpstr,"%s\\%s",newdir,LONGDIR);
453   test_setdir(newdir,tmpstr,NULL,1,"check 5");
454 /* Check that SetCurrentDirectory passes with a short relative directory */
455   sprintf(tmpstr,"%s",SHORTDIR);
456   sprintf(tmpstr1,"%s\\%s",newdir,SHORTDIR);
457   test_setdir(newdir,tmpstr,tmpstr1,1,"check 6");
458 /* starting with a '.' */
459   sprintf(tmpstr,".\\%s",SHORTDIR);
460   test_setdir(newdir,tmpstr,tmpstr1,1,"check 7");
461 /* Check that SetCurrentDirectory passes with a short relative directory */
462   sprintf(tmpstr,"%s",LONGDIR);
463   sprintf(tmpstr1,"%s\\%s",newdir,LONGDIR);
464   test_setdir(newdir,tmpstr,tmpstr1,1,"check 8");
465 /* starting with a '.' */
466   sprintf(tmpstr,".\\%s",LONGDIR);
467   test_setdir(newdir,tmpstr,tmpstr1,1,"check 9");
468 }
469
470 /* Cleanup the mess we made while executing these tests */
471 static void test_CleanupPathA(CHAR *origdir, CHAR *curdir)
472 {
473   CHAR tmpstr[MAX_PATH];
474   sprintf(tmpstr,"%s\\%s\\%s",curdir,SHORTDIR,SHORTFILE);
475   ok(DeleteFileA(tmpstr),"DeleteFileA failed\n");
476   sprintf(tmpstr,"%s\\%s\\%s",curdir,SHORTDIR,LONGFILE);
477   ok(DeleteFileA(tmpstr),"DeleteFileA failed\n");
478   sprintf(tmpstr,"%s\\%s\\%s",curdir,LONGDIR,SHORTFILE);
479   ok(DeleteFileA(tmpstr),"DeleteFileA failed\n");
480   sprintf(tmpstr,"%s\\%s\\%s",curdir,LONGDIR,LONGFILE);
481   ok(DeleteFileA(tmpstr),"DeleteFileA failed\n");
482   sprintf(tmpstr,"%s\\%s",curdir,SHORTDIR);
483   ok(RemoveDirectoryA(tmpstr),"RemoveDirectoryA failed\n");
484   sprintf(tmpstr,"%s\\%s",curdir,LONGDIR);
485   ok(RemoveDirectoryA(tmpstr),"RemoveDirectoryA failed\n");
486   ok(SetCurrentDirectoryA(origdir),"SetCurrentDirectoryA failed\n");
487   ok(RemoveDirectoryA(curdir),"RemoveDirectoryA failed\n");
488 }
489
490 /* This routine will test Get(Full|Short|Long)PathNameA */
491 static void test_PathNameA(CHAR *curdir, CHAR curDrive, CHAR otherDrive)
492 {
493   CHAR curdir_short[MAX_PATH],
494        longdir_short[MAX_PATH];
495   CHAR tmpstr[MAX_PATH],tmpstr1[MAX_PATH],tmpstr2[MAX_PATH];
496   LPSTR strptr;                 /*ptr to the filename portion of the path */
497   DWORD len;
498   INT i;
499   CHAR dir[MAX_PATH],eight[MAX_PATH],three[MAX_PATH];
500   SLpassfail passfail;
501
502 /* Get the short form of the current directory */
503   ok((len=GetShortPathNameA(curdir,curdir_short,MAX_PATH)),
504      "GetShortPathNameA failed\n");
505   ok(!HAS_TRAIL_SLASH_A(curdir_short),
506      "GetShortPathNameA should not have a trailing \\\n");
507 /* Get the short form of the absolute-path to LONGDIR */
508   sprintf(tmpstr,"%s\\%s",curdir_short,LONGDIR);
509   ok((len=GetShortPathNameA(tmpstr,longdir_short,MAX_PATH)),
510      "GetShortPathNameA failed\n");
511   ok(lstrcmpiA(longdir_short+(len-1),"\\")!=0,
512      "GetShortPathNameA should not have a trailing \\\n");
513
514   if (pGetLongPathNameA) {
515     DWORD rc1,rc2;
516     sprintf(tmpstr,"%s\\%s\\%s",curdir,LONGDIR,LONGFILE);
517     rc1=(*pGetLongPathNameA)(tmpstr,NULL,0);
518     rc2=(*pGetLongPathNameA)(curdir,NULL,0);
519     ok((rc1-strlen(tmpstr))==(rc2-strlen(curdir)),
520        "GetLongPathNameA: wrong return code, %d instead of %d\n",
521        rc1, lstrlenA(tmpstr)+1);
522
523     sprintf(dir,"%c:",curDrive);
524     rc1=(*pGetLongPathNameA)(dir,tmpstr,sizeof(tmpstr));
525     ok(strcmp(dir,tmpstr)==0,
526        "GetLongPathNameA: returned '%s' instead of '%s' (rc=%d)\n",
527        tmpstr,dir,rc1);
528   }
529
530 /* Check the cases where both file and directory exist first */
531 /* Start with a 8.3 directory, 8.3 filename */
532   test_ValidPathA(curdir,SHORTDIR,SHORTFILE,tmpstr,NULL,"test1");
533   sprintf(tmpstr1,"%s\\%s\\%s",curdir_short,SHORTDIR,SHORTFILE);
534   ok(lstrcmpiA(tmpstr,tmpstr1)==0,
535      "GetShortPathNameA returned '%s' instead of '%s'\n",tmpstr,tmpstr1);
536 /* Now try a 8.3 directory, long file name */
537   test_ValidPathA(curdir,SHORTDIR,LONGFILE,tmpstr,NULL,"test2");
538   sprintf(tmpstr1,"%s\\%s",curdir_short,SHORTDIR);
539   test_LongtoShortA(tmpstr,tmpstr1,"PAT","test2");
540 /* Next is a long directory, 8.3 file */
541   test_ValidPathA(curdir,LONGDIR,SHORTFILE,tmpstr,NULL,"test3");
542   sprintf(tmpstr1,"%s\\%s",longdir_short,SHORTFILE);
543   ok(lstrcmpiA(tmpstr,tmpstr1)==0,
544      "GetShortPathNameA returned '%s' instead of '%s'\n",tmpstr,tmpstr1);
545 /*Lastly a long directory, long file */
546   test_ValidPathA(curdir,LONGDIR,LONGFILE,tmpstr,NULL,"test4");
547   test_LongtoShortA(tmpstr,longdir_short,"PAT","test4");
548
549 /* Now check all of the invalid file w/ valid directory combinations */
550 /* Start with a 8.3 directory, 8.3 filename */
551   test_ValidPathA(curdir,SHORTDIR,NONFILE_SHORT,tmpstr,&passfail,"test5");
552   sprintf(tmpstr1,"%s\\%s\\%s",curdir_short,SHORTDIR,NONFILE_SHORT);
553   ok((passfail.shortlen==0 &&
554       (passfail.shorterror==ERROR_PATH_NOT_FOUND ||
555        passfail.shorterror==ERROR_FILE_NOT_FOUND)) ||
556      (passfail.shortlen==strlen(tmpstr1) && lstrcmpiA(tmpstr,tmpstr1)==0),
557      "GetShortPathNameA error: len=%d error=%d tmpstr=[%s]\n",
558      passfail.shortlen,passfail.shorterror,tmpstr);
559   if(pGetLongPathNameA) {
560     ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
561     ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
562        "GetlongPathA should have returned 'ERROR_FILE_NOT_FOUND'\n");
563   }
564 /* Now try a 8.3 directory, long file name */
565   test_ValidPathA(curdir,SHORTDIR,NONFILE_LONG,tmpstr,&passfail,"test6");
566   ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have\n");
567   ok(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
568      passfail.shorterror==ERROR_FILE_NOT_FOUND ||
569      !passfail.shorterror,
570      "GetShortPathA should have returned 'ERROR_FILE_NOT_FOUND'\n");
571   if(pGetLongPathNameA) {
572     ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
573     ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
574        "GetlongPathA should have returned 'ERROR_FILE_NOT_FOUND'\n");
575   }
576 /* Next is a long directory, 8.3 file */
577   test_ValidPathA(curdir,LONGDIR,NONFILE_SHORT,tmpstr,&passfail,"test7");
578   sprintf(tmpstr2,"%s\\%s",curdir_short,LONGDIR);
579   GetShortPathNameA(tmpstr2,tmpstr1,MAX_PATH);
580   strcat(tmpstr1,"\\" NONFILE_SHORT);
581   ok((passfail.shortlen==0 &&
582       (passfail.shorterror==ERROR_PATH_NOT_FOUND ||
583        passfail.shorterror==ERROR_FILE_NOT_FOUND)) ||
584      (passfail.shortlen==strlen(tmpstr1) && lstrcmpiA(tmpstr,tmpstr1)==0),
585      "GetShortPathNameA error: len=%d error=%d tmpstr=[%s]\n",
586      passfail.shortlen,passfail.shorterror,tmpstr);
587   if(pGetLongPathNameA) {
588     ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
589     ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
590       "GetlongPathA should have returned 'ERROR_FILE_NOT_FOUND'\n");
591   }
592 /*Lastly a long directory, long file */
593   test_ValidPathA(curdir,LONGDIR,NONFILE_LONG,tmpstr,&passfail,"test8");
594   ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have\n");
595   ok(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
596      passfail.shorterror==ERROR_FILE_NOT_FOUND ||
597      !passfail.shorterror,
598      "GetShortPathA should have returned 'ERROR_FILE_NOT_FOUND'\n");
599   if(pGetLongPathNameA) {
600     ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
601     ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
602        "GetlongPathA should have returned 'ERROR_FILE_NOT_FOUND'\n");
603   }
604 /* Now try again with directories that don't exist */
605 /* 8.3 directory, 8.3 filename */
606   test_ValidPathA(curdir,NONDIR_SHORT,SHORTFILE,tmpstr,&passfail,"test9");
607   sprintf(tmpstr1,"%s\\%s\\%s",curdir_short,NONDIR_SHORT,SHORTFILE);
608   ok((passfail.shortlen==0 &&
609       (passfail.shorterror==ERROR_PATH_NOT_FOUND ||
610        passfail.shorterror==ERROR_FILE_NOT_FOUND)) ||
611      (passfail.shortlen==strlen(tmpstr1) && lstrcmpiA(tmpstr,tmpstr1)==0),
612      "GetShortPathNameA error: len=%d error=%d tmpstr=[%s]\n",
613      passfail.shortlen,passfail.shorterror,tmpstr);
614   if(pGetLongPathNameA) {
615     ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
616     ok(passfail.longerror==ERROR_PATH_NOT_FOUND ||
617        passfail.longerror==ERROR_FILE_NOT_FOUND,
618        "GetLongPathA returned %d and not 'ERROR_PATH_NOT_FOUND'\n",
619        passfail.longerror);
620   }
621 /* Now try a 8.3 directory, long file name */
622   test_ValidPathA(curdir,NONDIR_SHORT,LONGFILE,tmpstr,&passfail,"test10");
623   ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have\n");
624   ok(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
625      passfail.shorterror==ERROR_FILE_NOT_FOUND ||
626      !passfail.shorterror,
627      "GetShortPathA returned %d and not 'ERROR_PATH_NOT_FOUND'\n",
628       passfail.shorterror);
629   if(pGetLongPathNameA) {
630     ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
631     ok(passfail.longerror==ERROR_PATH_NOT_FOUND ||
632        passfail.longerror==ERROR_FILE_NOT_FOUND,
633        "GetLongPathA returned %d and not 'ERROR_PATH_NOT_FOUND'\n",
634        passfail.longerror);
635   }
636 /* Next is a long directory, 8.3 file */
637   test_ValidPathA(curdir,NONDIR_LONG,SHORTFILE,tmpstr,&passfail,"test11");
638   ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have\n");
639   ok(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
640      passfail.shorterror==ERROR_FILE_NOT_FOUND ||
641      !passfail.shorterror,
642      "GetShortPathA returned %d and not 'ERROR_PATH_NOT_FOUND'\n",
643       passfail.shorterror);
644   if(pGetLongPathNameA) {
645     ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
646     ok(passfail.longerror==ERROR_PATH_NOT_FOUND ||
647        passfail.longerror==ERROR_FILE_NOT_FOUND,
648        "GetLongPathA returned %d and not 'ERROR_PATH_NOT_FOUND'\n",
649        passfail.longerror);
650   }
651 /*Lastly a long directory, long file */
652   test_ValidPathA(curdir,NONDIR_LONG,LONGFILE,tmpstr,&passfail,"test12");
653   ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have\n");
654   ok(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
655      passfail.shorterror==ERROR_FILE_NOT_FOUND ||
656      !passfail.shorterror,
657      "GetShortPathA returned %d and not 'ERROR_PATH_NOT_FOUND'\n",
658       passfail.shorterror);
659   if(pGetLongPathNameA) {
660     ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
661     ok(passfail.longerror==ERROR_PATH_NOT_FOUND ||
662        passfail.longerror==ERROR_FILE_NOT_FOUND,
663        "GetLongPathA returned %d and not 'ERROR_PATH_NOT_FOUND'\n",
664        passfail.longerror);
665   }
666 /* Next try directories ending with '\\' */
667 /* Existing Directories */
668   sprintf(tmpstr,"%s\\",SHORTDIR);
669   test_ValidPathA(curdir,"",tmpstr,tmpstr1,NULL,"test13");
670   sprintf(tmpstr,"%s\\",LONGDIR);
671   test_ValidPathA(curdir,"",tmpstr,tmpstr1,NULL,"test14");
672 /* Nonexistent directories */
673   sprintf(tmpstr,"%s\\",NONDIR_SHORT);
674   test_ValidPathA(curdir,"",tmpstr,tmpstr1,&passfail,"test15");
675   sprintf(tmpstr2,"%s\\%s",curdir_short,tmpstr);
676   ok((passfail.shortlen==0 &&
677       (passfail.shorterror==ERROR_PATH_NOT_FOUND ||
678        passfail.shorterror==ERROR_FILE_NOT_FOUND)) ||
679      (passfail.shortlen==strlen(tmpstr2) && lstrcmpiA(tmpstr1,tmpstr2)==0),
680      "GetShortPathNameA error: len=%d error=%d tmpstr=[%s]\n",
681      passfail.shortlen,passfail.shorterror,tmpstr);
682   if(pGetLongPathNameA) {
683     ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
684     ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
685        "GetLongPathA returned %d and not 'ERROR_FILE_NOT_FOUND'\n",
686        passfail.longerror);
687   }
688   sprintf(tmpstr,"%s\\",NONDIR_LONG);
689   test_ValidPathA(curdir,"",tmpstr,tmpstr1,&passfail,"test16");
690   ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have\n");
691   ok(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
692      passfail.shorterror==ERROR_FILE_NOT_FOUND ||
693      !passfail.shorterror,
694      "GetShortPathA returned %d and not 'ERROR_FILE_NOT_FOUND'\n",
695       passfail.shorterror);
696   if(pGetLongPathNameA) {
697     ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
698     ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
699        "GetLongPathA returned %d and not 'ERROR_FILE_NOT_FOUND'\n",
700        passfail.longerror);
701   }
702 /* Test GetFullPathNameA with drive letters */
703   if( curDrive != NOT_A_VALID_DRIVE) {
704     sprintf(tmpstr,"%c:",curdir[0]);
705     ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr2,&strptr),
706        "GetFullPathNameA(%c:) failed\n", curdir[0]);
707     GetCurrentDirectoryA(MAX_PATH,tmpstr);
708     sprintf(tmpstr1,"%s\\",tmpstr);
709     ok(lstrcmpiA(tmpstr,tmpstr2)==0 || lstrcmpiA(tmpstr1,tmpstr2)==0,
710        "GetFullPathNameA(%c:) returned '%s' instead of '%s' or '%s'\n",
711        curdir[0],tmpstr2,tmpstr,tmpstr1);
712
713     sprintf(tmpstr,"%c:\\%s\\%s",curDrive,SHORTDIR,SHORTFILE);
714     ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr1,&strptr),"GetFullPathNameA failed\n");
715     ok(lstrcmpiA(tmpstr,tmpstr1)==0,
716        "GetFullPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
717     ok(lstrcmpiA(SHORTFILE,strptr)==0,
718        "GetFullPathNameA returned part '%s' instead of '%s'\n",strptr,SHORTFILE);
719   }
720 /* Without a leading slash, insert the current directory if on the current drive */
721   sprintf(tmpstr,"%c:%s\\%s",curdir[0],SHORTDIR,SHORTFILE);
722   ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr1,&strptr),"GetFullPathNameA failed\n");
723   sprintf(tmpstr,"%s\\%s\\%s",curdir,SHORTDIR,SHORTFILE);
724   ok(lstrcmpiA(tmpstr,tmpstr1)==0,
725       "GetFullPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
726   ok(lstrcmpiA(SHORTFILE,strptr)==0,
727       "GetFullPathNameA returned part '%s' instead of '%s'\n",strptr,SHORTFILE);
728 /* Otherwise insert the missing leading slash */
729   if( otherDrive != NOT_A_VALID_DRIVE) {
730     /* FIXME: this test assumes that current directory on other drive is root */
731     sprintf(tmpstr,"%c:%s\\%s",otherDrive,SHORTDIR,SHORTFILE);
732     ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr1,&strptr),"GetFullPathNameA failed for %s\n", tmpstr);
733     sprintf(tmpstr,"%c:\\%s\\%s",otherDrive,SHORTDIR,SHORTFILE);
734     ok(lstrcmpiA(tmpstr,tmpstr1)==0,
735        "GetFullPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
736     ok(lstrcmpiA(SHORTFILE,strptr)==0,
737        "GetFullPathNameA returned part '%s' instead of '%s'\n",strptr,SHORTFILE);
738   }
739 /* Xilinx tools like to mix Unix and DOS formats, which Windows handles fine.
740    So test for them. */
741   if( curDrive != NOT_A_VALID_DRIVE) {
742     sprintf(tmpstr,"%c:/%s\\%s",curDrive,SHORTDIR,SHORTFILE);
743     ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr1,&strptr),"GetFullPathNameA failed\n");
744     sprintf(tmpstr,"%c:\\%s\\%s",curDrive,SHORTDIR,SHORTFILE);
745     ok(lstrcmpiA(tmpstr,tmpstr1)==0,
746        "GetFullPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
747     ok(lstrcmpiA(SHORTFILE,strptr)==0,
748        "GetFullPathNameA returned part '%s' instead of '%s'\n",strptr,SHORTFILE);
749   }
750 /**/
751   sprintf(tmpstr,"%c:%s/%s",curdir[0],SHORTDIR,SHORTFILE);
752   ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr1,&strptr),"GetFullPathNameA failed\n");
753   sprintf(tmpstr,"%s\\%s\\%s",curdir,SHORTDIR,SHORTFILE);
754   ok(lstrcmpiA(tmpstr,tmpstr1)==0,
755       "GetFullPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
756   ok(lstrcmpiA(SHORTFILE,strptr)==0,
757       "GetFullPathNameA returned part '%s' instead of '%s'\n",strptr,SHORTFILE);
758 /* Windows will insert a drive letter in front of an absolute UNIX path */
759   sprintf(tmpstr,"/%s/%s",SHORTDIR,SHORTFILE);
760   ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr1,&strptr),"GetFullPathNameA failed\n");
761   sprintf(tmpstr,"%c:\\%s\\%s",*tmpstr1,SHORTDIR,SHORTFILE);
762   ok(lstrcmpiA(tmpstr,tmpstr1)==0,
763      "GetFullPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
764 /* This passes in Wine because it still contains the pointer from the previous test */
765   ok(lstrcmpiA(SHORTFILE,strptr)==0,
766       "GetFullPathNameA returned part '%s' instead of '%s'\n",strptr,SHORTFILE);
767
768 /* Now try some relative paths */
769   ok(GetShortPathNameA(LONGDIR,tmpstr,MAX_PATH),"GetShortPathNameA failed\n");
770   test_SplitShortPathA(tmpstr,dir,eight,three);
771   if(pGetLongPathNameA) {
772     ok(pGetLongPathNameA(tmpstr,tmpstr1,MAX_PATH),"GetLongPathNameA failed\n");
773     ok(lstrcmpiA(tmpstr1,LONGDIR)==0,
774        "GetLongPathNameA returned '%s' instead of '%s'\n",tmpstr1,LONGDIR);
775   }
776   sprintf(tmpstr,".\\%s",LONGDIR);
777   ok(GetShortPathNameA(tmpstr,tmpstr1,MAX_PATH),"GetShortPathNameA failed\n");
778   test_SplitShortPathA(tmpstr1,dir,eight,three);
779   ok(lstrcmpiA(dir,".")==0 || dir[0]=='\0',
780      "GetShortPathNameA did not keep relative directory [%s]\n",tmpstr1);
781   if(pGetLongPathNameA) {
782     ok(pGetLongPathNameA(tmpstr1,tmpstr1,MAX_PATH),"GetLongPathNameA failed %s\n",
783        tmpstr);
784     ok(lstrcmpiA(tmpstr1,tmpstr)==0,
785        "GetLongPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
786   }
787 /* Check out Get*PathNameA on some funny characters */
788   for(i=0;i<lstrlenA(funny_chars);i++) {
789     INT valid;
790     valid=(is_char_ok[i]=='0') ? 0 : 1;
791     sprintf(tmpstr1,"check%d-1",i);
792     sprintf(tmpstr,"file%c000.ext",funny_chars[i]);
793     test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
794     sprintf(tmpstr1,"check%d-2",i);
795     sprintf(tmpstr,"file000.e%ct",funny_chars[i]);
796     test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
797     sprintf(tmpstr1,"check%d-3",i);
798     sprintf(tmpstr,"%cfile000.ext",funny_chars[i]);
799     test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
800     sprintf(tmpstr1,"check%d-4",i);
801     sprintf(tmpstr,"file000%c.ext",funny_chars[i]);
802     test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
803     sprintf(tmpstr1,"check%d-5",i);
804     sprintf(tmpstr,"Long %c File",funny_chars[i]);
805     test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
806     sprintf(tmpstr1,"check%d-6",i);
807     sprintf(tmpstr,"%c Long File",funny_chars[i]);
808     test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
809     sprintf(tmpstr1,"check%d-7",i);
810     sprintf(tmpstr,"Long File %c",funny_chars[i]);
811     test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
812   }
813 }
814
815 static void test_GetTempPathA(char* tmp_dir)
816 {
817     DWORD len, len_with_null;
818     char buf[MAX_PATH];
819
820     len_with_null = strlen(tmp_dir) + 1;
821
822     lstrcpyA(buf, "foo");
823     len = GetTempPathA(MAX_PATH, buf);
824     ok(len <= MAX_PATH, "should fit into MAX_PATH\n");
825     ok(lstrcmpiA(buf, tmp_dir) == 0, "expected [%s], got [%s]\n",tmp_dir,buf);
826     ok(len == strlen(buf), "returned length should be equal to the length of string\n");
827
828     /* Some versions of Windows touch the buffer, some don't so we don't
829      * test that. Also, NT sometimes exagerates the required buffer size
830      * so we cannot test for an exact match. Finally, the
831      * 'len_with_null - 1' case is so buggy on Windows it's not testable.
832      * For instance in some cases Win98 returns len_with_null - 1 instead
833      * of len_with_null.
834      */
835     len = GetTempPathA(1, buf);
836     ok(len >= len_with_null, "Expected >= %u, got %u\n", len_with_null, len);
837
838     len = GetTempPathA(0, NULL);
839     ok(len >= len_with_null, "Expected >= %u, got %u\n", len_with_null, len);
840
841     /* The call above gave us the buffer size that Windows thinks is needed
842      * so the next call should work
843      */
844     lstrcpyA(buf, "foo");
845     len = GetTempPathA(len, buf);
846     ok(lstrcmpiA(buf, tmp_dir) == 0, "expected [%s], got [%s]\n",tmp_dir,buf);
847     ok(len == strlen(buf), "returned length should be equal to the length of string\n");
848 }
849
850 static void test_GetTempPathW(char* tmp_dir)
851 {
852     DWORD len, len_with_null;
853     WCHAR buf[MAX_PATH];
854     WCHAR tmp_dirW[MAX_PATH];
855     static const WCHAR fooW[] = {'f','o','o',0};
856
857     MultiByteToWideChar(CP_ACP,0,tmp_dir,-1,tmp_dirW,sizeof(tmp_dirW)/sizeof(*tmp_dirW));
858     len_with_null = lstrlenW(tmp_dirW) + 1;
859
860     /* This one is different from ANSI version: ANSI version doesn't
861      * touch the buffer, unicode version usually truncates the buffer
862      * to zero size. NT still exagerates the required buffer size
863      * sometimes so we cannot test for an exact match. Finally, the
864      * 'len_with_null - 1' case is so buggy on Windows it's not testable.
865      * For instance on NT4 it will sometimes return a path without the
866      * trailing '\\' and sometimes return an error.
867      */
868
869     lstrcpyW(buf, fooW);
870     len = GetTempPathW(MAX_PATH, buf);
871     if (len==0 && GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
872         return;
873     ok(lstrcmpiW(buf, tmp_dirW) == 0, "GetTempPathW returned an incorrect temporary path\n");
874     ok(len == lstrlenW(buf), "returned length should be equal to the length of string\n");
875
876     lstrcpyW(buf, fooW);
877     len = GetTempPathW(1, buf);
878     ok(buf[0] == 0, "unicode version should truncate the buffer to zero size\n");
879     ok(len >= len_with_null, "Expected >= %u, got %u\n", len_with_null, len);
880
881     len = GetTempPathW(0, NULL);
882     ok(len >= len_with_null, "Expected >= %u, got %u\n", len_with_null, len);
883
884     lstrcpyW(buf, fooW);
885     len = GetTempPathW(len, buf);
886     ok(lstrcmpiW(buf, tmp_dirW) == 0, "GetTempPathW returned an incorrect temporary path\n");
887     ok(len == lstrlenW(buf), "returned length should be equal to the length of string\n");
888 }
889
890 static void test_GetTempPath(void)
891 {
892     char save_TMP[MAX_PATH];
893     char windir[MAX_PATH];
894     char buf[MAX_PATH];
895
896     GetEnvironmentVariableA("TMP", save_TMP, sizeof(save_TMP));
897
898     /* test default configuration */
899     trace("TMP=%s\n", save_TMP);
900     strcpy(buf,save_TMP);
901     if (buf[strlen(buf)-1]!='\\')
902         strcat(buf,"\\");
903     test_GetTempPathA(buf);
904     test_GetTempPathW(buf);
905
906     /* TMP=C:\WINDOWS */
907     GetWindowsDirectoryA(windir, sizeof(windir));
908     SetEnvironmentVariableA("TMP", windir);
909     GetEnvironmentVariableA("TMP", buf, sizeof(buf));
910     trace("TMP=%s\n", buf);
911     strcat(windir,"\\");
912     test_GetTempPathA(windir);
913     test_GetTempPathW(windir);
914
915     /* TMP=C:\ */
916     GetWindowsDirectoryA(windir, sizeof(windir));
917     windir[3] = 0;
918     SetEnvironmentVariableA("TMP", windir);
919     GetEnvironmentVariableA("TMP", buf, sizeof(buf));
920     trace("TMP=%s\n", buf);
921     test_GetTempPathA(windir);
922     test_GetTempPathW(windir);
923
924     /* TMP=C: i.e. use current working directory of the specified drive */
925     GetWindowsDirectoryA(windir, sizeof(windir));
926     SetCurrentDirectoryA(windir);
927     windir[2] = 0;
928     SetEnvironmentVariableA("TMP", windir);
929     GetEnvironmentVariableA("TMP", buf, sizeof(buf));
930     trace("TMP=%s\n", buf);
931     GetWindowsDirectoryA(windir, sizeof(windir));
932     strcat(windir,"\\");
933     test_GetTempPathA(windir);
934     test_GetTempPathW(windir);
935
936     SetEnvironmentVariableA("TMP", save_TMP);
937 }
938
939 static void test_GetLongPathNameW(void)
940 {
941     DWORD length; 
942     WCHAR empty[MAX_PATH];
943
944     /* Not present in all windows versions */
945     if(pGetLongPathNameW) 
946     {
947     SetLastError(0xdeadbeef); 
948     length = pGetLongPathNameW(NULL,NULL,0);
949     if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
950     {
951         skip("GetLongPathNameW is not implemented\n");
952         return;
953     }
954     ok(0==length,"GetLongPathNameW returned %d but expected 0\n",length);
955     ok(GetLastError()==ERROR_INVALID_PARAMETER,"GetLastError returned %d but expected ERROR_INVALID_PARAMETER\n",GetLastError());
956
957     SetLastError(0xdeadbeef); 
958     empty[0]=0;
959     length = pGetLongPathNameW(empty,NULL,0);
960     ok(0==length,"GetLongPathNameW returned %d but expected 0\n",length);
961     ok(GetLastError()==ERROR_PATH_NOT_FOUND,"GetLastError returned %d but expected ERROR_PATH_NOT_FOUND\n",GetLastError());
962     }
963 }
964
965 static void test_GetShortPathNameW(void)
966 {
967     WCHAR test_path[] = { 'L', 'o', 'n', 'g', 'D', 'i', 'r', 'e', 'c', 't', 'o', 'r', 'y', 'N', 'a', 'm', 'e',  0 };
968     WCHAR path[MAX_PATH];
969     WCHAR short_path[MAX_PATH];
970     DWORD length;
971     HANDLE file;
972     int ret;
973     WCHAR name[] = { 't', 'e', 's', 't', 0 };
974     WCHAR backSlash[] = { '\\', 0 };
975
976     SetLastError(0xdeadbeef);
977     GetTempPathW( MAX_PATH, path );
978     if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
979     {
980         skip("GetTempPathW is not implemented\n");
981         return;
982     }
983
984     lstrcatW( path, test_path );
985     lstrcatW( path, backSlash );
986     ret = CreateDirectoryW( path, NULL );
987     ok( ret, "Directory was not created. LastError = %d\n", GetLastError() );
988
989     /* Starting a main part of test */
990     length = GetShortPathNameW( path, short_path, 0 );
991     ok( length, "GetShortPathNameW returned 0.\n" );
992     ret = GetShortPathNameW( path, short_path, length );
993     ok( ret, "GetShortPathNameW returned 0.\n" );
994     lstrcatW( short_path, name );
995     file = CreateFileW( short_path, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
996     ok( file != INVALID_HANDLE_VALUE, "File was not created.\n" );
997
998     /* End test */
999     CloseHandle( file );
1000     ret = DeleteFileW( short_path );
1001     ok( ret, "Cannot delete file.\n" );
1002     ret = RemoveDirectoryW( path );
1003     ok( ret, "Cannot delete directory.\n" );
1004 }
1005
1006 static void test_GetSystemDirectory(void)
1007 {
1008     CHAR    buffer[MAX_PATH + 4];
1009     DWORD   res;
1010     DWORD   total;
1011
1012     SetLastError(0xdeadbeef);
1013     res = GetSystemDirectory(NULL, 0);
1014     /* res includes the terminating Zero */
1015     ok(res > 0, "returned %d with %d (expected '>0')\n", res, GetLastError());
1016
1017     total = res;
1018
1019     /* this crashes on XP */
1020     if (0) res = GetSystemDirectory(NULL, total);
1021
1022     SetLastError(0xdeadbeef);
1023     res = GetSystemDirectory(NULL, total-1);
1024     /* 95+NT: total (includes the terminating Zero)
1025        98+ME: 0 with ERROR_INVALID_PARAMETER */
1026     ok( (res == total) || (!res && (GetLastError() == ERROR_INVALID_PARAMETER)),
1027         "returned %d with %d (expected '%d' or: '0' with "
1028         "ERROR_INVALID_PARAMETER)\n", res, GetLastError(), total);
1029
1030     if (total > MAX_PATH) return;
1031
1032     buffer[0] = '\0';
1033     SetLastError(0xdeadbeef);
1034     res = GetSystemDirectory(buffer, total);
1035     /* res does not include the terminating Zero */
1036     ok( (res == (total-1)) && (buffer[0]),
1037         "returned %d with %d and '%s' (expected '%d' and a string)\n",
1038         res, GetLastError(), buffer, total-1);
1039
1040     buffer[0] = '\0';
1041     SetLastError(0xdeadbeef);
1042     res = GetSystemDirectory(buffer, total + 1);
1043     /* res does not include the terminating Zero */
1044     ok( (res == (total-1)) && (buffer[0]),
1045         "returned %d with %d and '%s' (expected '%d' and a string)\n",
1046         res, GetLastError(), buffer, total-1);
1047
1048     memset(buffer, '#', total + 1);
1049     buffer[total + 2] = '\0';
1050     SetLastError(0xdeadbeef);
1051     res = GetSystemDirectory(buffer, total-1);
1052     /* res includes the terminating Zero) */
1053     ok( res == total, "returned %d with %d and '%s' (expected '%d')\n",
1054         res, GetLastError(), buffer, total);
1055
1056     memset(buffer, '#', total + 1);
1057     buffer[total + 2] = '\0';
1058     SetLastError(0xdeadbeef);
1059     res = GetSystemDirectory(buffer, total-2);
1060     /* res includes the terminating Zero) */
1061     ok( res == total, "returned %d with %d and '%s' (expected '%d')\n",
1062         res, GetLastError(), buffer, total);
1063 }
1064
1065 static void test_GetWindowsDirectory(void)
1066 {
1067     CHAR    buffer[MAX_PATH + 4];
1068     DWORD   res;
1069     DWORD   total;
1070
1071     SetLastError(0xdeadbeef);
1072     res = GetWindowsDirectory(NULL, 0);
1073     /* res includes the terminating Zero */
1074     ok(res > 0, "returned %d with %d (expected '>0')\n", res, GetLastError());
1075
1076     total = res;
1077     /* this crashes on XP */
1078     if (0) res = GetWindowsDirectory(NULL, total);
1079
1080     SetLastError(0xdeadbeef);
1081     res = GetWindowsDirectory(NULL, total-1);
1082     /* 95+NT: total (includes the terminating Zero)
1083        98+ME: 0 with ERROR_INVALID_PARAMETER */
1084     ok( (res == total) || (!res && (GetLastError() == ERROR_INVALID_PARAMETER)),
1085         "returned %d with %d (expected '%d' or: '0' with "
1086         "ERROR_INVALID_PARAMETER)\n", res, GetLastError(), total);
1087
1088     if (total > MAX_PATH) return;
1089
1090     buffer[0] = '\0';
1091     SetLastError(0xdeadbeef);
1092     res = GetWindowsDirectory(buffer, total);
1093     /* res does not include the terminating Zero */
1094     ok( (res == (total-1)) && (buffer[0]),
1095         "returned %d with %d and '%s' (expected '%d' and a string)\n",
1096         res, GetLastError(), buffer, total-1);
1097
1098     buffer[0] = '\0';
1099     SetLastError(0xdeadbeef);
1100     res = GetWindowsDirectory(buffer, total + 1);
1101     /* res does not include the terminating Zero */
1102     ok( (res == (total-1)) && (buffer[0]),
1103         "returned %d with %d and '%s' (expected '%d' and a string)\n",
1104         res, GetLastError(), buffer, total-1);
1105
1106     memset(buffer, '#', total + 1);
1107     buffer[total + 2] = '\0';
1108     SetLastError(0xdeadbeef);
1109     res = GetWindowsDirectory(buffer, total-1);
1110     /* res includes the terminating Zero) */
1111     ok( res == total, "returned %d with %d and '%s' (expected '%d')\n",
1112         res, GetLastError(), buffer, total);
1113
1114     memset(buffer, '#', total + 1);
1115     buffer[total + 2] = '\0';
1116     SetLastError(0xdeadbeef);
1117     res = GetWindowsDirectory(buffer, total-2);
1118     /* res includes the terminating Zero) */
1119     ok( res == total, "returned %d with %d and '%s' (expected '%d')\n",
1120         res, GetLastError(), buffer, total);
1121 }
1122
1123 static void test_NeedCurrentDirectoryForExePathA(void)
1124 {
1125     /* Crashes in Windows */
1126     if (0)
1127         ok(pNeedCurrentDirectoryForExePathA(NULL), "returned FALSE for NULL\n");
1128
1129     SetEnvironmentVariableA("NoDefaultCurrentDirectoryInExePath", NULL);
1130     ok(pNeedCurrentDirectoryForExePathA("."), "returned FALSE for \".\"\n");
1131     ok(pNeedCurrentDirectoryForExePathA("c:\\"), "returned FALSE for \"c:\\\"\n");
1132     ok(pNeedCurrentDirectoryForExePathA("cmd.exe"), "returned FALSE for \"cmd.exe\"\n");
1133
1134     SetEnvironmentVariableA("NoDefaultCurrentDirectoryInExePath", "nya");
1135     ok(!pNeedCurrentDirectoryForExePathA("."), "returned TRUE for \".\"\n");
1136     ok(pNeedCurrentDirectoryForExePathA("c:\\"), "returned FALSE for \"c:\\\"\n");
1137     ok(!pNeedCurrentDirectoryForExePathA("cmd.exe"), "returned TRUE for \"cmd.exe\"\n");
1138 }
1139
1140 static void test_NeedCurrentDirectoryForExePathW(void)
1141 {
1142     const WCHAR thispath[] = {'.', 0};
1143     const WCHAR fullpath[] = {'c', ':', '\\', 0};
1144     const WCHAR cmdname[] = {'c', 'm', 'd', '.', 'e', 'x', 'e', 0};
1145
1146     /* Crashes in Windows */
1147     if (0)
1148         ok(pNeedCurrentDirectoryForExePathW(NULL), "returned FALSE for NULL\n");
1149
1150     SetEnvironmentVariableA("NoDefaultCurrentDirectoryInExePath", NULL);
1151     ok(pNeedCurrentDirectoryForExePathW(thispath), "returned FALSE for \".\"\n");
1152     ok(pNeedCurrentDirectoryForExePathW(fullpath), "returned FALSE for \"c:\\\"\n");
1153     ok(pNeedCurrentDirectoryForExePathW(cmdname), "returned FALSE for \"cmd.exe\"\n");
1154
1155     SetEnvironmentVariableA("NoDefaultCurrentDirectoryInExePath", "nya");
1156     ok(!pNeedCurrentDirectoryForExePathW(thispath), "returned TRUE for \".\"\n");
1157     ok(pNeedCurrentDirectoryForExePathW(fullpath), "returned FALSE for \"c:\\\"\n");
1158     ok(!pNeedCurrentDirectoryForExePathW(cmdname), "returned TRUE for \"cmd.exe\"\n");
1159 }
1160
1161 /* Call various path/file name retrieving APIs and check the case of
1162  * the returned drive letter. Some apps (for instance Adobe Photoshop CS3
1163  * installer) depend on the driver letter being in upper case.
1164  */
1165 static void test_drive_letter_case(void)
1166 {
1167     UINT ret;
1168     char buf[MAX_PATH];
1169
1170 #define is_upper_case_letter(a) ((a) >= 'A' && (a) <= 'Z')
1171
1172     memset(buf, 0, sizeof(buf));
1173     SetLastError(0xdeadbeef);
1174     ret = GetWindowsDirectory(buf, sizeof(buf));
1175     ok(ret, "GetWindowsDirectory error %u\n", GetLastError());
1176     ok(ret < sizeof(buf), "buffer should be %u bytes\n", ret);
1177     ok(buf[1] == ':', "expected buf[1] == ':' got %c\n", buf[1]);
1178     ok(is_upper_case_letter(buf[0]), "expected buf[0] upper case letter got %c\n", buf[0]);
1179
1180     /* re-use the buffer returned by GetFullPathName */
1181     buf[2] = '/';
1182     SetLastError(0xdeadbeef);
1183     ret = GetFullPathName(buf + 2, sizeof(buf), buf, NULL);
1184     ok(ret, "GetFullPathName error %u\n", GetLastError());
1185     ok(ret < sizeof(buf), "buffer should be %u bytes\n", ret);
1186     ok(buf[1] == ':', "expected buf[1] == ':' got %c\n", buf[1]);
1187     ok(is_upper_case_letter(buf[0]), "expected buf[0] upper case letter got %c\n", buf[0]);
1188
1189     memset(buf, 0, sizeof(buf));
1190     SetLastError(0xdeadbeef);
1191     ret = GetSystemDirectory(buf, sizeof(buf));
1192     ok(ret, "GetSystemDirectory error %u\n", GetLastError());
1193     ok(ret < sizeof(buf), "buffer should be %u bytes\n", ret);
1194     ok(buf[1] == ':', "expected buf[1] == ':' got %c\n", buf[1]);
1195     ok(is_upper_case_letter(buf[0]), "expected buf[0] upper case letter got %c\n", buf[0]);
1196
1197     memset(buf, 0, sizeof(buf));
1198     SetLastError(0xdeadbeef);
1199     ret = GetCurrentDirectory(sizeof(buf), buf);
1200     ok(ret, "GetCurrentDirectory error %u\n", GetLastError());
1201     ok(ret < sizeof(buf), "buffer should be %u bytes\n", ret);
1202     ok(buf[1] == ':', "expected buf[1] == ':' got %c\n", buf[1]);
1203     ok(is_upper_case_letter(buf[0]), "expected buf[0] upper case letter got %c\n", buf[0]);
1204
1205     memset(buf, 0, sizeof(buf));
1206     SetLastError(0xdeadbeef);
1207     ret = GetTempPath(sizeof(buf), buf);
1208     ok(ret, "GetTempPath error %u\n", GetLastError());
1209     ok(ret < sizeof(buf), "buffer should be %u bytes\n", ret);
1210     ok(buf[1] == ':', "expected buf[1] == ':' got %c\n", buf[1]);
1211     ok(is_upper_case_letter(buf[0]), "expected buf[0] upper case letter got %c\n", buf[0]);
1212
1213     memset(buf, 0, sizeof(buf));
1214     SetLastError(0xdeadbeef);
1215     ret = GetFullPathName(".", sizeof(buf), buf, NULL);
1216     ok(ret, "GetFullPathName error %u\n", GetLastError());
1217     ok(ret < sizeof(buf), "buffer should be %u bytes\n", ret);
1218     ok(buf[1] == ':', "expected buf[1] == ':' got %c\n", buf[1]);
1219     ok(is_upper_case_letter(buf[0]), "expected buf[0] upper case letter got %c\n", buf[0]);
1220
1221     /* re-use the buffer returned by GetFullPathName */
1222     SetLastError(0xdeadbeef);
1223     ret = GetShortPathName(buf, buf, sizeof(buf));
1224     ok(ret, "GetShortPathName error %u\n", GetLastError());
1225     ok(ret < sizeof(buf), "buffer should be %u bytes\n", ret);
1226     ok(buf[1] == ':', "expected buf[1] == ':' got %c\n", buf[1]);
1227     ok(is_upper_case_letter(buf[0]), "expected buf[0] upper case letter got %c\n", buf[0]);
1228
1229     if (pGetLongPathNameA)
1230     {
1231         /* re-use the buffer returned by GetShortPathName */
1232         SetLastError(0xdeadbeef);
1233         ret = pGetLongPathNameA(buf, buf, sizeof(buf));
1234         ok(ret, "GetLongPathNameA error %u\n", GetLastError());
1235         ok(ret < sizeof(buf), "buffer should be %u bytes\n", ret);
1236         ok(buf[1] == ':', "expected buf[1] == ':' got %c\n", buf[1]);
1237         ok(is_upper_case_letter(buf[0]), "expected buf[0] upper case letter got %c\n", buf[0]);
1238     }
1239 #undef is_upper_case_letter
1240 }
1241
1242 START_TEST(path)
1243 {
1244     CHAR origdir[MAX_PATH],curdir[MAX_PATH], curDrive, otherDrive;
1245     pGetLongPathNameA = (void*)GetProcAddress( GetModuleHandleA("kernel32.dll"),
1246                                                "GetLongPathNameA" );
1247     pGetLongPathNameW = (void*)GetProcAddress(GetModuleHandleA("kernel32.dll") ,
1248                                                "GetLongPathNameW" );
1249     pNeedCurrentDirectoryForExePathA =
1250         (void*)GetProcAddress( GetModuleHandleA("kernel32.dll"),
1251                                "NeedCurrentDirectoryForExePathA" );
1252     pNeedCurrentDirectoryForExePathW =
1253         (void*)GetProcAddress( GetModuleHandleA("kernel32.dll"),
1254                                "NeedCurrentDirectoryForExePathW" );
1255
1256     test_InitPathA(curdir, &curDrive, &otherDrive);
1257     test_CurrentDirectoryA(origdir,curdir);
1258     test_PathNameA(curdir, curDrive, otherDrive);
1259     test_CleanupPathA(origdir,curdir);
1260     test_GetTempPath();
1261     test_GetLongPathNameW();
1262     test_GetShortPathNameW();
1263     test_GetSystemDirectory();
1264     test_GetWindowsDirectory();
1265     if (pNeedCurrentDirectoryForExePathA)
1266     {
1267         test_NeedCurrentDirectoryForExePathA();
1268     }
1269     if (pNeedCurrentDirectoryForExePathW)
1270     {
1271         test_NeedCurrentDirectoryForExePathW();
1272     }
1273     test_drive_letter_case();
1274 }